00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00029 #include <strings.h>
00030 #include "../dprint.h"
00031 #include "../trim.h"
00032 #include "parse_methods.h"
00033
00034
00038 static int token_char(char _c)
00039 {
00040 return (_c >= 65 && _c <= 90) ||
00041 (_c >= 97 && _c <= 122) ||
00042 (_c >= 48 && _c <= 57) ||
00043 (_c == '-') || (_c == '.') || (_c == '!') || (_c == '%') ||
00044 (_c == '*') || (_c == '_') || (_c == '+') || (_c == '`') ||
00045 (_c == '\'') || (_c == '~') || (_c == '+') || (_c == '`');
00046 }
00047
00048
00049
00056 int parse_method_name(str* s, enum request_method* method)
00057 {
00058 if (unlikely(!s || !method)) {
00059 LOG(L_ERR, "Invalid parameter value\n");
00060 return -1;
00061 }
00062
00063 if (unlikely(!s->len || (s->s==0))) {
00064 DBG("No input\n");
00065 *method = METHOD_OTHER;
00066 return 0;
00067 }
00068
00069 switch ((s->s)[0]) {
00070
00071 case 'R':
00072 case 'r':
00073 if (likely((s->len == 8) &&
00074 !strncasecmp(s->s + 1, "egister", 7))) {
00075 *method = METHOD_REGISTER;
00076 return 0;
00077 }
00078 if (likely((s->len==5) && !strncasecmp(s->s + 1, "efer", 4))) {
00079 *method = METHOD_REFER;
00080 return 0;
00081 }
00082 break;
00083 case 'A':
00084 case 'a':
00085 if (likely((s->len==3) && !strncasecmp(s->s + 1, "ck", 2))) {
00086 *method = METHOD_ACK;
00087 return 0;
00088 }
00089 break;
00090 case 'I':
00091 case 'i':
00092 if (likely((s->len==6) && !strncasecmp(s->s + 1, "nvite", 5))){
00093 *method = METHOD_INVITE;
00094 return 0;
00095 }
00096 if (likely((s->len==4) && !strncasecmp(s->s + 1, "nfo", 3))) {
00097 *method = METHOD_INFO;
00098 return 0;
00099 }
00100 break;
00101 case 'P':
00102 case 'p':
00103 if (likely((s->len==5) && !strncasecmp(s->s + 1, "rack", 4))) {
00104 *method = METHOD_PRACK;
00105 return 0;
00106 }
00107 if (likely((s->len==7) && !strncasecmp(s->s + 1, "ublish", 6))) {
00108 *method = METHOD_PUBLISH;
00109 return 0;
00110 }
00111 break;
00112 case 'C':
00113 case 'c':
00114 if (likely((s->len==6) && !strncasecmp(s->s + 1, "ancel", 5))) {
00115 *method = METHOD_CANCEL;
00116 return 0;
00117 }
00118 break;
00119 case 'B':
00120 case 'b':
00121 if (likely((s->len==3) && !strncasecmp(s->s + 1, "ye", 2))) {
00122 *method = METHOD_BYE;
00123 return 0;
00124 }
00125 break;
00126 case 'M':
00127 case 'm':
00128 if (likely((s->len==7) && !strncasecmp(s->s + 1, "essage", 6))) {
00129 *method = METHOD_MESSAGE;
00130 return 0;
00131 }
00132 break;
00133 case 'O':
00134 case 'o':
00135 if (likely((s->len==7) && !strncasecmp(s->s + 1, "ptions", 6))) {
00136 *method = METHOD_OPTIONS;
00137 return 0;
00138 }
00139 break;
00140 case 'S':
00141 case 's':
00142 if (likely((s->len==9) && !strncasecmp(s->s + 1, "ubscribe", 8))) {
00143 *method = METHOD_SUBSCRIBE;
00144 return 0;
00145 }
00146 break;
00147 case 'N':
00148 case 'n':
00149 if (likely((s->len==6) && !strncasecmp(s->s + 1, "otify", 5))){
00150 *method = METHOD_NOTIFY;
00151 return 0;
00152 }
00153 break;
00154 case 'U':
00155 case 'u':
00156 if (likely((s->len==6) && !strncasecmp(s->s + 1, "pdate", 5))){
00157 *method = METHOD_UPDATE;
00158 return 0;
00159 }
00160 break;
00161 default:
00162 break;
00163 }
00164
00165 *method = METHOD_OTHER;
00166 return 0;
00167 }
00168
00169
00170
00175 static int parse_method_advance(str* _next, enum request_method* _method)
00176 {
00177 char* end;
00178
00179 if (unlikely(!_next || !_method)) {
00180 LOG(L_ERR, "Invalid parameter value\n");
00181 return 0;
00182 }
00183
00184 if (unlikely(!_next->len || !_next->s)) {
00185 DBG("No input\n");
00186 *_method = METHOD_OTHER;
00187 return 1;
00188 }
00189 end=_next->s+_next->len;
00190
00191 switch ((_next->s)[0]) {
00192 case 'A':
00193 case 'a':
00194 if ((_next->len > 2) && !strncasecmp(_next->s + 1, "ck", 2)) {
00195 *_method = METHOD_ACK;
00196 _next->len -= 3;
00197 _next->s += 3;
00198 goto found;
00199 } else {
00200 goto unknown;
00201 }
00202
00203 case 'B':
00204 case 'b':
00205 if ((_next->len > 2) && !strncasecmp(_next->s + 1, "ye", 2)) {
00206 *_method = METHOD_BYE;
00207 _next->len -= 3;
00208 _next->s += 3;
00209 goto found;
00210 } else {
00211 goto unknown;
00212 }
00213
00214 case 'C':
00215 case 'c':
00216 if ((_next->len > 5) && !strncasecmp(_next->s + 1, "ancel", 5)) {
00217 *_method = METHOD_CANCEL;
00218 _next->len -= 6;
00219 _next->s += 6;
00220 goto found;
00221 } else {
00222 goto unknown;
00223 }
00224
00225 case 'I':
00226 case 'i':
00227 if ((_next->len > 3) &&
00228 ((*(_next->s + 1) == 'N') || (*(_next->s + 1) == 'n'))) {
00229 if (!strncasecmp(_next->s + 2, "fo", 2)) {
00230 *_method = METHOD_INFO;
00231 _next->len -= 4;
00232 _next->s += 4;
00233 goto found;
00234 }
00235
00236 if ((_next->len > 5) && !strncasecmp(_next->s + 2, "vite", 4)) {
00237 *_method = METHOD_INVITE;
00238 _next->len -= 6;
00239 _next->s += 6;
00240 goto found;
00241 }
00242 }
00243 goto unknown;
00244
00245 case 'M':
00246 case 'm':
00247 if ((_next->len > 6) && !strncasecmp(_next->s + 1, "essage", 6)) {
00248 *_method = METHOD_MESSAGE;
00249 _next->len -= 7;
00250 _next->s += 7;
00251 goto found;
00252 } else {
00253 goto unknown;
00254 }
00255
00256 case 'N':
00257 case 'n':
00258 if ((_next->len > 5) && !strncasecmp(_next->s + 1, "otify", 5)) {
00259 *_method = METHOD_NOTIFY;
00260 _next->len -= 6;
00261 _next->s += 6;
00262 goto found;
00263 } else {
00264 goto unknown;
00265 }
00266
00267 case 'O':
00268 case 'o':
00269 if ((_next->len > 6) && !strncasecmp(_next->s + 1, "ptions", 6)) {
00270 *_method = METHOD_OPTIONS;
00271 _next->len -= 7;
00272 _next->s += 7;
00273 goto found;
00274 } else {
00275 goto unknown;
00276 }
00277
00278 case 'P':
00279 case 'p':
00280 if ((_next->len > 4) && !strncasecmp(_next->s + 1, "rack", 4)) {
00281 *_method = METHOD_PRACK;
00282 _next->len -= 5;
00283 _next->s += 5;
00284 goto found;
00285 }
00286 if ((_next->len > 6) && !strncasecmp(_next->s + 1, "ublish", 6)) {
00287 *_method = METHOD_PUBLISH;
00288 _next->len -= 7;
00289 _next->s += 7;
00290 goto found;
00291 }
00292 goto unknown;
00293
00294 case 'R':
00295 case 'r':
00296 if ((_next->len > 4) &&
00297 ((*(_next->s + 1) == 'E') || (*(_next->s + 1) == 'e'))) {
00298 if (!strncasecmp(_next->s + 2, "fer", 3)) {
00299 *_method = METHOD_REFER;
00300 _next->len -= 5;
00301 _next->s += 5;
00302 goto found;
00303 }
00304
00305 if ((_next->len > 7) && !strncasecmp(_next->s + 2, "gister", 6)) {
00306 *_method = METHOD_REGISTER;
00307 _next->len -= 8;
00308 _next->s += 8;
00309 goto found;
00310 }
00311 }
00312 goto unknown;
00313
00314 case 'S':
00315 case 's':
00316 if ((_next->len > 8) && !strncasecmp(_next->s + 1, "ubscribe", 8)) {
00317 *_method = METHOD_SUBSCRIBE;
00318 _next->len -= 9;
00319 _next->s += 9;
00320 goto found;
00321 } else {
00322 goto unknown;
00323 }
00324
00325 case 'U':
00326 case 'u':
00327 if ((_next->len > 5) && !strncasecmp(_next->s + 1, "pdate", 5)) {
00328 *_method = METHOD_UPDATE;
00329 _next->len -= 6;
00330 _next->s += 6;
00331 goto found;
00332 } else {
00333 goto unknown;
00334 }
00335
00336 default:
00337 goto unknown;
00338 }
00339
00340 unknown:
00341 if (token_char(*(_next->s))) {
00342 do {
00343 _next->s++;
00344 _next->len--;
00345 } while (_next->len && token_char(*(_next->s)));
00346 *_method = METHOD_OTHER;
00347 return 1;
00348 } else {
00349 return 0;
00350 }
00351 found:
00352
00353 return (_next->s>=end) || (!token_char(*(_next->s)));
00354 }
00355
00356
00361 int parse_methods(str* _body, unsigned int* _methods)
00362 {
00363 str next;
00364 unsigned int method;
00365
00366 method=0;
00367
00368 if (!_body || !_methods) {
00369 LOG(L_ERR, "parse_methods: Invalid parameter value\n");
00370 return -1;
00371 }
00372
00373 next.len = _body->len;
00374 next.s = _body->s;
00375
00376 trim_leading(&next);
00377
00378 *_methods = 0;
00379
00380 if (next.len == 0) {
00381 return 0;
00382 }
00383
00384 while (1) {
00385 if (parse_method_advance(&next, &method)) {
00386 *_methods |= method;
00387 } else {
00388 LOG(L_ERR, "ERROR: parse_methods: Invalid method\n");
00389 return -1;
00390 }
00391
00392 trim_leading(&next);
00393 if (next.len) {
00394 if (next.s[0] == ',') {
00395 next.len--;
00396 next.s++;
00397 trim_leading(&next);
00398 if (next.len == 0) {
00399 LOG(L_ERR, "ERROR: parse_methods: Method expected\n");
00400 return 0;
00401 }
00402 } else {
00403 LOG(L_ERR, "ERROR: parse_methods: Comma expected\n");
00404 return -1;
00405 }
00406 } else {
00407 break;
00408 }
00409 }
00410
00411 return 0;
00412 }