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