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
00029
00042 #include <string.h>
00043 #include "parse_rr.h"
00044 #include "../mem/mem.h"
00045 #include "../mem/shm_mem.h"
00046 #include "../dprint.h"
00047 #include "../trim.h"
00048 #include "../ut.h"
00049
00053 static inline int do_parse_rr_body(char *buf, int len, rr_t **head)
00054 {
00055 rr_t* r, *last;
00056 str s;
00057 param_hooks_t hooks;
00058
00059
00060 if(buf==0 || len<=0)
00061 {
00062 DBG("parse_rr_body(): No body for record-route\n");
00063 *head = 0;
00064 return -2;
00065 }
00066 s.s = buf;
00067 s.len = len;
00068 trim_leading(&s);
00069
00070 last = 0;
00071
00072 while(1) {
00073
00074 r = (rr_t*)pkg_malloc(sizeof(rr_t));
00075 if (!r) {
00076 LOG(L_ERR, "parse_rr(): No memory left\n");
00077 goto error;
00078 }
00079 memset(r, 0, sizeof(rr_t));
00080
00081
00082 if (parse_nameaddr(&s, &r->nameaddr) < 0) {
00083 LOG(L_ERR, "parse_rr(): Error while parsing name-addr (%.*s)\n",
00084 s.len, ZSW(s.s));
00085 goto error;
00086 }
00087 r->len = r->nameaddr.len;
00088
00089
00090 s.s = r->nameaddr.name.s + r->nameaddr.len;
00091 s.len -= r->nameaddr.len;
00092
00093 trim_leading(&s);
00094
00095 if (s.len == 0) goto ok;
00096
00097 if (s.s[0] == ';') {
00098 s.s++;
00099 s.len--;
00100 trim_leading(&s);
00101
00102 if (s.len == 0) {
00103 LOG(L_ERR, "parse_rr(): Error while parsing params\n");
00104 goto error;
00105 }
00106
00107
00108 if (parse_params(&s, CLASS_ANY, &hooks, &r->params) < 0) {
00109 LOG(L_ERR, "parse_rr(): Error while parsing params\n");
00110 goto error;
00111 }
00112 r->len = r->params->name.s + r->params->len - r->nameaddr.name.s;
00113
00114
00115
00116
00117 trim_leading(&s);
00118 if (s.len == 0) goto ok;
00119 }
00120
00121 if (s.s[0] != ',') {
00122 LOG(L_ERR, "parse_rr(): Invalid character '%c', comma expected\n", s.s[0]);
00123 goto error;
00124 }
00125
00126
00127 s.s++;
00128 s.len--;
00129 trim_leading(&s);
00130
00131 if (s.len == 0) {
00132 LOG(L_ERR, "parse_rr(): Text after comma missing\n");
00133 goto error;
00134 }
00135
00136
00137 if (!*head) *head = r;
00138 if (last) last->next = r;
00139 last = r;
00140 }
00141
00142 error:
00143 if (r) pkg_free(r);
00144 free_rr(head);
00145 return -1;
00146
00147 ok:
00148 if (!*head) *head = r;
00149 if (last) last->next = r;
00150 return 0;
00151 }
00152
00156 int parse_rr_body(char *buf, int len, rr_t **head)
00157 {
00158 return do_parse_rr_body(buf, len, head);
00159 }
00160
00164 int parse_rr(struct hdr_field* _h)
00165 {
00166 rr_t* r = NULL;
00167
00168 if (!_h) {
00169 LOG(L_ERR, "parse_rr(): Invalid parameter value\n");
00170 return -1;
00171 }
00172
00173 if (_h->parsed) {
00174
00175 return 0;
00176 }
00177
00178 if(do_parse_rr_body(_h->body.s, _h->body.len, &r) < 0)
00179 return -1;
00180 _h->parsed = (void*)r;
00181 return 0;
00182 }
00183
00188 static inline void do_free_rr(rr_t** _r, int _shm)
00189 {
00190 rr_t* ptr;
00191
00192 while(*_r) {
00193 ptr = *_r;
00194 *_r = (*_r)->next;
00195 if (ptr->params) {
00196 if (_shm) shm_free_params(ptr->params);
00197 else free_params(ptr->params);
00198 }
00199 if (_shm) shm_free(ptr);
00200 else pkg_free(ptr);
00201 }
00202 }
00203
00204
00210 void free_rr(rr_t** _r)
00211 {
00212 do_free_rr(_r, 0);
00213 }
00214
00215
00221 void shm_free_rr(rr_t** _r)
00222 {
00223 do_free_rr(_r, 1);
00224 }
00225
00226
00230 void print_rr(FILE* _o, rr_t* _r)
00231 {
00232 rr_t* ptr;
00233
00234 ptr = _r;
00235
00236 while(ptr) {
00237 fprintf(_o, "---RR---\n");
00238 print_nameaddr(_o, &ptr->nameaddr);
00239 fprintf(_o, "r2 : %p\n", ptr->r2);
00240 if (ptr->params) {
00241 print_params(_o, ptr->params);
00242 }
00243 fprintf(_o, "len: %d\n", ptr->len);
00244 fprintf(_o, "---/RR---\n");
00245 ptr = ptr->next;
00246 }
00247 }
00248
00249
00254 static inline void xlate_pointers(rr_t* _orig, rr_t* _r)
00255 {
00256 param_t* ptr;
00257 _r->nameaddr.uri.s = translate_pointer(_r->nameaddr.name.s, _orig->nameaddr.name.s, _r->nameaddr.uri.s);
00258
00259 ptr = _r->params;
00260 while(ptr) {
00261
00262 ptr->name.s = translate_pointer(_r->nameaddr.name.s, _orig->nameaddr.name.s, ptr->name.s);
00263 ptr->body.s = translate_pointer(_r->nameaddr.name.s, _orig->nameaddr.name.s, ptr->body.s);
00264 ptr = ptr->next;
00265 }
00266 }
00267
00268
00272 static inline int do_duplicate_rr(rr_t** _new, rr_t* _r, int _shm)
00273 {
00274 int len, ret;
00275 rr_t* res, *prev, *it;
00276
00277 if (!_new || !_r) {
00278 LOG(L_ERR, "duplicate_rr(): Invalid parameter value\n");
00279 return -1;
00280 }
00281 prev = NULL;
00282 *_new = NULL;
00283 it = _r;
00284 while(it)
00285 {
00286 if (it->params) {
00287 len = it->params->name.s + it->params->len - it->nameaddr.name.s;
00288 } else {
00289 len = it->nameaddr.len;
00290 }
00291
00292 if (_shm) res = shm_malloc(sizeof(rr_t) + len);
00293 else res = pkg_malloc(sizeof(rr_t) + len);
00294 if (!res) {
00295 LOG(L_ERR, "duplicate_rr(): No memory left\n");
00296 return -2;
00297 }
00298 memcpy(res, it, sizeof(rr_t));
00299
00300 res->nameaddr.name.s = (char*)res + sizeof(rr_t);
00301 memcpy(res->nameaddr.name.s, it->nameaddr.name.s, len);
00302
00303 if (_shm) {
00304 ret = shm_duplicate_params(&res->params, it->params);
00305 } else {
00306 ret = duplicate_params(&res->params, it->params);
00307 }
00308
00309 if (ret < 0) {
00310 LOG(L_ERR, "duplicate_rr(): Error while duplicating parameters\n");
00311 if (_shm) shm_free(res);
00312 else pkg_free(res);
00313 return -3;
00314 }
00315
00316 xlate_pointers(it, res);
00317
00318 res->next=NULL;
00319 if(*_new==NULL)
00320 *_new = res;
00321 if(prev)
00322 prev->next = res;
00323 prev = res;
00324 it = it->next;
00325 }
00326 return 0;
00327 }
00328
00329
00333 int duplicate_rr(rr_t** _new, rr_t* _r)
00334 {
00335 return do_duplicate_rr(_new, _r, 0);
00336 }
00337
00338
00342 int shm_duplicate_rr(rr_t** _new, rr_t* _r)
00343 {
00344 return do_duplicate_rr(_new, _r, 1);
00345 }
00346
00352 int print_rr_body(struct hdr_field *iroute, str *oroute, int order,
00353 unsigned int * nb_recs)
00354 {
00355 rr_t *p;
00356 int n = 0, nr=0;
00357 int i = 0;
00358 int route_len;
00359 #define MAX_RR_HDRS 64
00360 static str route[MAX_RR_HDRS];
00361 char *cp, *start;
00362
00363 if(iroute==NULL)
00364 return 0;
00365
00366 route_len= 0;
00367 memset(route, 0, MAX_RR_HDRS*sizeof(str));
00368
00369 while (iroute!=NULL)
00370 {
00371 if (parse_rr(iroute) < 0)
00372 {
00373 LM_ERR("failed to parse RR\n");
00374 goto error;
00375 }
00376
00377 p =(rr_t*)iroute->parsed;
00378 while (p)
00379 {
00380 route[n].s = p->nameaddr.name.s;
00381 route[n].len = p->len;
00382 LM_DBG("current rr is %.*s\n", route[n].len, route[n].s);
00383
00384 n++;
00385 if(n==MAX_RR_HDRS)
00386 {
00387 LM_ERR("too many RR\n");
00388 goto error;
00389 }
00390 p = p->next;
00391 }
00392
00393 iroute = next_sibling_hdr(iroute);
00394 }
00395
00396 for(i=0;i<n;i++){
00397 if(!nb_recs || (nb_recs &&
00398 ( (!order&& (i>=*nb_recs)) || (order && (i<=(n-*nb_recs)) )) ) )
00399 {
00400 route_len+= route[i].len;
00401 nr++;
00402 }
00403
00404 }
00405
00406 if(nb_recs)
00407 LM_DBG("skipping %i route records\n", *nb_recs);
00408
00409 route_len += --nr;
00410
00411 oroute->s=(char*)pkg_malloc(route_len);
00412
00413
00414 if(oroute->s==0)
00415 {
00416 LM_ERR("no more pkg mem\n");
00417 goto error;
00418 }
00419 cp = start = oroute->s;
00420 if(order==0)
00421 {
00422 i= (nb_recs == NULL) ? 0:*nb_recs;
00423
00424 while (i<n)
00425 {
00426 memcpy(cp, route[i].s, route[i].len);
00427 cp += route[i].len;
00428 if (++i<n)
00429 *(cp++) = ',';
00430 }
00431 } else {
00432
00433 i = (nb_recs == NULL) ? n-1 : (n-*nb_recs-1);
00434
00435 while (i>=0)
00436 {
00437 memcpy(cp, route[i].s, route[i].len);
00438 cp += route[i].len;
00439 if (i-->0)
00440 *(cp++) = ',';
00441 }
00442 }
00443 oroute->len=cp - start;
00444
00445 LM_DBG("out rr [%.*s]\n", oroute->len, oroute->s);
00446 LM_DBG("we have %i records\n", n);
00447 if(nb_recs != NULL)
00448 *nb_recs = (unsigned int)n;
00449
00450 return 0;
00451
00452 error:
00453 return -1;
00454 }
00455
00456
00461 int get_path_dst_uri(str *_p, str *_dst)
00462 {
00463 rr_t *route = 0;
00464
00465 LM_DBG("path for branch: '%.*s'\n", _p->len, _p->s);
00466 if(parse_rr_body(_p->s, _p->len, &route) < 0) {
00467 LM_ERR("failed to parse Path body\n");
00468 return -1;
00469 }
00470
00471 if(!route) {
00472 LM_ERR("failed to parse Path body no head found\n");
00473 return -1;
00474 }
00475 *_dst = route->nameaddr.uri;
00476
00477 free_rr(&route);
00478
00479 return 0;
00480 }