00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #include <string.h>
00036 #include "../str.h"
00037 #include "../ut.h"
00038 #include "../dprint.h"
00039 #include "../trim.h"
00040 #include "../mem/mem.h"
00041 #include "../mem/shm_mem.h"
00042 #include "parse_param.h"
00043
00044
00045 static inline void parse_event_dialog_class(param_hooks_t* h, param_t* p)
00046 {
00047
00048 if (!p->name.s) {
00049 LOG(L_ERR, "ERROR: parse_event_dialog_class: empty value\n");
00050 return;
00051 }
00052 if (!h) {
00053 LOG(L_CRIT, "BUG: parse_event_dialog_class: NULL param hook pointer\n");
00054 return;
00055 }
00056 switch(p->name.s[0]) {
00057 case 'c':
00058 case 'C':
00059 if ((p->name.len == 7) &&
00060 (!strncasecmp(p->name.s + 1, "all-id", 6))) {
00061 p->type = P_CALL_ID;
00062 h->event_dialog.call_id = p;
00063 }
00064 break;
00065
00066 case 'f':
00067 case 'F':
00068 if ((p->name.len == 8) &&
00069 (!strncasecmp(p->name.s + 1, "rom-tag", 7))) {
00070 p->type = P_FROM_TAG;
00071 h->event_dialog.from_tag = p;
00072 }
00073 break;
00074
00075 case 't':
00076 case 'T':
00077 if ((p->name.len == 6) &&
00078 (!strncasecmp(p->name.s + 1, "o-tag", 5))) {
00079 p->type = P_TO_TAG;
00080 h->event_dialog.to_tag = p;
00081 }
00082 break;
00083
00084 case 'i':
00085 case 'I':
00086 if ((p->name.len == 27) &&
00087 (!strncasecmp(p->name.s + 1, "nclude-session-description", 26))) {
00088 p->type = P_ISD;
00089 h->event_dialog.include_session_description = p;
00090 }
00091 break;
00092
00093 case 's':
00094 case 'S':
00095 if ((p->name.len == 3) &&
00096 (!strncasecmp(p->name.s + 1, "la", 2))) {
00097 p->type = P_SLA;
00098 h->event_dialog.sla = p;
00099 }
00100 break;
00101
00102 case 'm':
00103 case 'M':
00104 if ((p->name.len == 2) &&
00105 (!strncasecmp(p->name.s + 1, "a", 1))) {
00106 p->type = P_MA;
00107 h->event_dialog.ma = p;
00108 }
00109 break;
00110 }
00111 }
00112
00113
00118 static inline void parse_contact_class(param_hooks_t* _h, param_t* _p)
00119 {
00120
00121 if (!_p->name.s) {
00122 LOG(L_ERR, "ERROR: parse_contact_class: empty value\n");
00123 return;
00124 }
00125 if (!_h) {
00126 LOG(L_CRIT, "BUG: parse_contact_class: NULL param hook pointer\n");
00127 return;
00128 }
00129 switch(_p->name.s[0]) {
00130 case 'q':
00131 case 'Q':
00132 if (_p->name.len == 1) {
00133 _p->type = P_Q;
00134 _h->contact.q = _p;
00135 }
00136 break;
00137
00138 case 'e':
00139 case 'E':
00140 if ((_p->name.len == 7) &&
00141 (!strncasecmp(_p->name.s + 1, "xpires", 6))) {
00142 _p->type = P_EXPIRES;
00143 _h->contact.expires = _p;
00144 }
00145 break;
00146
00147 case 'm':
00148 case 'M':
00149 if ((_p->name.len == 7) &&
00150 (!strncasecmp(_p->name.s + 1, "ethods", 6))) {
00151 _p->type = P_METHODS;
00152 _h->contact.methods = _p;
00153 }
00154 break;
00155
00156 case 'r':
00157 case 'R':
00158 if ((_p->name.len == 8) &&
00159 (!strncasecmp(_p->name.s + 1, "eceived", 7))) {
00160 _p->type = P_RECEIVED;
00161 _h->contact.received = _p;
00162 } else if((_p->name.len == 6) &&
00163 (!strncasecmp(_p->name.s + 1, "eg-id", 5))) {
00164 _p->type = P_REG_ID;
00165 _h->contact.reg_id = _p;
00166 }
00167 break;
00168 case '+':
00169 if ((_p->name.len == 13) &&
00170 (!strncasecmp(_p->name.s + 1, "sip.instance", 12))) {
00171 _p->type = P_INSTANCE;
00172 _h->contact.instance = _p;
00173 }
00174 break;
00175 }
00176 }
00177
00178
00183 static inline void parse_uri_class(param_hooks_t* _h, param_t* _p)
00184 {
00185
00186 if (!_p->name.s) {
00187 LOG(L_ERR, "ERROR: parse_uri_class: empty value\n");
00188 return;
00189 }
00190 if (!_h) {
00191 LOG(L_CRIT, "BUG: parse_uri_class: NULL param hook pointer\n");
00192 return;
00193 }
00194 switch(_p->name.s[0]) {
00195 case 't':
00196 case 'T':
00197 if ((_p->name.len == 9) &&
00198 (!strncasecmp(_p->name.s + 1, "ransport", 8))) {
00199 _p->type = P_TRANSPORT;
00200 _h->uri.transport = _p;
00201 } else if (_p->name.len == 2) {
00202 if (((_p->name.s[1] == 't') || (_p->name.s[1] == 'T')) &&
00203 ((_p->name.s[2] == 'l') || (_p->name.s[2] == 'L'))) {
00204 _p->type = P_TTL;
00205 _h->uri.ttl = _p;
00206 }
00207 }
00208 break;
00209
00210 case 'l':
00211 case 'L':
00212 if ((_p->name.len == 2) && ((_p->name.s[1] == 'r') || (_p->name.s[1] == 'R'))) {
00213 _p->type = P_LR;
00214 _h->uri.lr = _p;
00215 }
00216 break;
00217
00218 case 'r':
00219 case 'R':
00220 if ((_p->name.len == 2) && (_p->name.s[1] == '2')) {
00221 _p->type = P_R2;
00222 _h->uri.r2 = _p;
00223 }
00224 break;
00225
00226 case 'm':
00227 case 'M':
00228 if ((_p->name.len == 5) &&
00229 (!strncasecmp(_p->name.s + 1, "addr", 4))) {
00230 _p->type = P_MADDR;
00231 _h->uri.maddr = _p;
00232 }
00233 break;
00234
00235 case 'd':
00236 case 'D':
00237 if ((_p->name.len == 5) &&
00238 (!strncasecmp(_p->name.s + 1, "stip", 4))) {
00239 _p->type = P_DSTIP;
00240 _h->uri.dstip = _p;
00241 } else if ((_p->name.len == 7) &&
00242 (!strncasecmp(_p->name.s + 1, "stport", 6))) {
00243 _p->type = P_DSTPORT;
00244 _h->uri.dstport = _p;
00245 }
00246 break;
00247 case 'f':
00248 case 'F':
00249 if ((_p->name.len == 4) &&
00250 (!strncasecmp(_p->name.s + 1, "tag", 3))) {
00251 _p->type = P_FTAG;
00252 _h->uri.ftag = _p;
00253 }
00254 break;
00255 }
00256
00257 }
00258
00259
00266 static inline int parse_quoted_param(str* _s, str* _r)
00267 {
00268 char* end_quote;
00269
00270
00271
00272
00273 if (_s->len < 2) {
00274 return -1;
00275 }
00276
00277
00278 _s->s++;
00279 _s->len--;
00280
00281
00282
00283 end_quote = q_memchr(_s->s, '\"', _s->len);
00284
00285
00286 if (!end_quote) {
00287 return -2;
00288 }
00289
00290
00291
00292
00293 _r->s = _s->s;
00294 _r->len = end_quote - _s->s;
00295
00296
00297
00298
00299 _s->len -= (end_quote - _s->s + 1);
00300 _s->s = end_quote + 1;
00301
00302
00303 return 0;
00304 }
00305
00306
00312 static inline int parse_token_param(str* _s, str* _r)
00313 {
00314 int i;
00315
00316
00317
00318
00319 if (_s->len == 0) {
00320 return -1;
00321 }
00322
00323
00324
00325
00326 _r->s = _s->s;
00327
00328
00329
00330
00331 for(i = 0; i < _s->len; i++) {
00332
00333
00334
00335
00336 switch(_s->s[i]) {
00337 case ' ':
00338 case '\t':
00339 case '\r':
00340 case '\n':
00341 case ',':
00342 case ';':
00343
00344
00345
00346
00347 goto out;
00348 }
00349 }
00350 out:
00351 if (i == 0) {
00352 return -1;
00353 }
00354
00355
00356 _r->len = i;
00357
00358
00359
00360
00361 _s->s = _s->s + i;
00362 _s->len -= i;
00363
00364
00365 return 0;
00366 }
00367
00368
00372 static inline void parse_param_name(str* _s, pclass_t _c, param_hooks_t* _h, param_t* _p)
00373 {
00374
00375 if (!_s->s) {
00376 DBG("DEBUG: parse_param_name: empty parameter\n");
00377 return;
00378 }
00379
00380 _p->name.s = _s->s;
00381
00382 while(_s->len) {
00383 switch(_s->s[0]) {
00384 case ' ':
00385 case '\t':
00386 case '\r':
00387 case '\n':
00388 case ';':
00389 case ',':
00390 case '=':
00391 goto out;
00392 }
00393 _s->s++;
00394 _s->len--;
00395 }
00396
00397 out:
00398 _p->name.len = _s->s - _p->name.s;
00399
00400 switch(_c) {
00401 case CLASS_CONTACT: parse_contact_class(_h, _p); break;
00402 case CLASS_URI: parse_uri_class(_h, _p); break;
00403 case CLASS_EVENT_DIALOG: parse_event_dialog_class(_h, _p); break;
00404 default: break;
00405 }
00406 }
00407
00408
00409
00410
00411
00416 static inline int parse_param_body(str* _s, param_t* _c)
00417 {
00418 if (_s->s[0] == '\"') {
00419 if (parse_quoted_param(_s, &(_c->body)) < 0) {
00420 LOG(L_ERR, "parse_param_body(): Error while parsing quoted string\n");
00421 return -2;
00422 }
00423 } else {
00424 if (parse_token_param(_s, &(_c->body)) < 0) {
00425 LOG(L_ERR, "parse_param_body(): Error while parsing token\n");
00426 return -3;
00427 }
00428 }
00429
00430 return 0;
00431 }
00432
00433
00442 inline int parse_param(str *_s, pclass_t _c, param_hooks_t *_h, param_t *t)
00443 {
00444 memset(t, 0, sizeof(param_t));
00445
00446 parse_param_name(_s, _c, _h, t);
00447 trim_leading(_s);
00448
00449 if (_s->len == 0) {
00450 t->len = t->name.len;
00451 goto ok;
00452 }
00453
00454 if (_s->s[0] == '=') {
00455 _s->s++;
00456 _s->len--;
00457 trim_leading(_s);
00458
00459 if (_s->len == 0) {
00460
00461
00462 t->body.s = _s->s;
00463 t->body.len = 0;
00464 } else if (parse_param_body(_s, t) < 0) {
00465 LOG(L_ERR, "parse_params(): Error while parsing param body\n");
00466 goto error;
00467 }
00468
00469 t->len = _s->s - t->name.s;
00470
00471 trim_leading(_s);
00472 if (_s->len == 0) {
00473 goto ok;
00474 }
00475 } else {
00476 t->len = t->name.len;
00477 }
00478
00479 if (_s->s[0] == ',') goto ok;
00480 if (_s->s[0] == '>') goto ok;
00481
00482 if (_s->s[0] != ';') {
00483 LOG(L_ERR, "parse_params(): Invalid character, ; expected\n");
00484 goto error;
00485 }
00486
00487 _s->s++;
00488 _s->len--;
00489 trim_leading(_s);
00490
00491 if (_s->len == 0) {
00492 LOG(L_ERR, "parse_params(): Param name missing after ;\n");
00493 goto error;
00494 }
00495
00496 return 0;
00497
00498 ok:
00499 return 1;
00500 error:
00501 return -1;
00502 }
00503
00504
00505
00514 int parse_params(str* _s, pclass_t _c, param_hooks_t* _h, param_t** _p)
00515 {
00516 param_t* t;
00517
00518 if (!_s || !_p) {
00519 LOG(L_ERR, "parse_params(): Invalid parameter value\n");
00520 return -1;
00521 }
00522
00523 if (_h)
00524 memset(_h, 0, sizeof(param_hooks_t));
00525 *_p = 0;
00526
00527 if (!_s->s) {
00528 DBG("DEBUG: parse_params: empty uri params, skipping\n");
00529 return 0;
00530 }
00531
00532 while(1) {
00533 t = (param_t*)pkg_malloc(sizeof(param_t));
00534 if (t == 0) {
00535 LOG(L_ERR, "parse_params(): No memory left\n");
00536 goto error;
00537 }
00538
00539 switch(parse_param(_s, _c, _h, t)) {
00540 case 0: break;
00541 case 1: goto ok;
00542 default: goto error;
00543 }
00544
00545 t->next = *_p;
00546 *_p = t;
00547 }
00548
00549 error:
00550 if (t) pkg_free(t);
00551 free_params(*_p);
00552 return -2;
00553
00554 ok:
00555 t->next = *_p;
00556 *_p = t;
00557 return 0;
00558 }
00559
00560
00564 static inline void do_free_params(param_t* _p, int _shm)
00565 {
00566 param_t* ptr;
00567
00568 while(_p) {
00569 ptr = _p;
00570 _p = _p->next;
00571 if (_shm) shm_free(ptr);
00572 else pkg_free(ptr);
00573 }
00574 }
00575
00576
00580 void free_params(param_t* _p)
00581 {
00582 do_free_params(_p, 0);
00583 }
00584
00585
00589 void shm_free_params(param_t* _p)
00590 {
00591 do_free_params(_p, 1);
00592 }
00593
00594
00598 static inline void print_param(FILE* _o, param_t* _p)
00599 {
00600 char* type;
00601
00602 fprintf(_o, "---param(%p)---\n", _p);
00603
00604 switch(_p->type) {
00605 case P_OTHER: type = "P_OTHER"; break;
00606 case P_Q: type = "P_Q"; break;
00607 case P_EXPIRES: type = "P_EXPIRES"; break;
00608 case P_METHODS: type = "P_METHODS"; break;
00609 case P_TRANSPORT: type = "P_TRANSPORT"; break;
00610 case P_LR: type = "P_LR"; break;
00611 case P_R2: type = "P_R2"; break;
00612 case P_MADDR: type = "P_MADDR"; break;
00613 case P_TTL: type = "P_TTL"; break;
00614 case P_RECEIVED: type = "P_RECEIVED"; break;
00615 case P_DSTIP: type = "P_DSTIP"; break;
00616 case P_DSTPORT: type = "P_DSTPORT"; break;
00617 case P_INSTANCE: type = "P_INSTANCE"; break;
00618 case P_FTAG: type = "P_FTAG"; break;
00619 case P_CALL_ID: type = "P_CALL_ID"; break;
00620 case P_FROM_TAG: type = "P_FROM_TAG"; break;
00621 case P_TO_TAG: type = "P_TO_TAG"; break;
00622 case P_ISD: type = "P_ISD"; break;
00623 case P_SLA: type = "P_SLA"; break;
00624 default: type = "UNKNOWN"; break;
00625 }
00626
00627 fprintf(_o, "type: %s\n", type);
00628 fprintf(_o, "name: \'%.*s\'\n", _p->name.len, _p->name.s);
00629 fprintf(_o, "body: \'%.*s\'\n", _p->body.len, _p->body.s);
00630 fprintf(_o, "len : %d\n", _p->len);
00631 fprintf(_o, "---/param---\n");
00632 }
00633
00634
00638 void print_params(FILE* _o, param_t* _p)
00639 {
00640 param_t* ptr;
00641
00642 ptr = _p;
00643 while(ptr) {
00644 print_param(_o, ptr);
00645 ptr = ptr->next;
00646 }
00647 }
00648
00649
00653 static inline int do_duplicate_params(param_t** _n, param_t* _p, int _shm)
00654 {
00655 param_t* last, *ptr, *t;
00656
00657 if (!_n) {
00658 LOG(L_ERR, "duplicate_params(): Invalid parameter value\n");
00659 return -1;
00660 }
00661
00662 last = 0;
00663 *_n = 0;
00664 ptr = _p;
00665 while(ptr) {
00666 if (_shm) {
00667 t = (param_t*)shm_malloc(sizeof(param_t));
00668 } else {
00669 t = (param_t*)pkg_malloc(sizeof(param_t));
00670 }
00671 if (!t) {
00672 LOG(L_ERR, "duplicate_params(): Invalid parameter value\n");
00673 goto err;
00674 }
00675 memcpy(t, ptr, sizeof(param_t));
00676 t->next = 0;
00677
00678 if (!*_n) *_n = t;
00679 if (last) last->next = t;
00680 last = t;
00681
00682 ptr = ptr->next;
00683 }
00684 return 0;
00685
00686 err:
00687 do_free_params(*_n, _shm);
00688 return -2;
00689 }
00690
00691
00695 int duplicate_params(param_t** _n, param_t* _p)
00696 {
00697 return do_duplicate_params(_n, _p, 0);
00698 }
00699
00700
00704 int shm_duplicate_params(param_t** _n, param_t* _p)
00705 {
00706 return do_duplicate_params(_n, _p, 1);
00707 }