1 /*
2 * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16 /*!
17 * \file
18 * \brief Kamailio core :: Extended AVPs
19 * \ingroup core
20 * Module: \ref core
21 */
22
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "mem/mem.h"
27 #include "mem/shm_mem.h"
28 #include "dprint.h"
29 #include "hashes.h"
30 #include "xavp.h"
31
32 /*! XAVP list head */
33 static sr_xavp_t *_xavp_list_head = 0;
34 /*! Pointer to XAVP current list */
35 static sr_xavp_t **_xavp_list_crt = &_xavp_list_head;
36
37 /*! XAVU list head */
38 static sr_xavp_t *_xavu_list_head = 0;
39 /*! Pointer to XAVP current list */
40 static sr_xavp_t **_xavu_list_crt = &_xavu_list_head;
41
42 /*! XAVI list head */
43 static sr_xavp_t *_xavi_list_head = 0;
44 /*! Pointer to XAVI current list */
45 static sr_xavp_t **_xavi_list_crt = &_xavi_list_head;
46
47 /*! Helper functions */
48 static sr_xavp_t *xavp_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv);
49 static int xavp_rm_internal(str *name, sr_xavp_t **head, int idx);
50
51
xavp_shm_free(void * p)52 void xavp_shm_free(void *p)
53 {
54 shm_free(p);
55 }
56
xavp_shm_free_unsafe(void * p)57 void xavp_shm_free_unsafe(void *p)
58 {
59 shm_free_unsafe(p);
60 }
61
62
xavp_free(sr_xavp_t * xa)63 void xavp_free(sr_xavp_t *xa)
64 {
65 if(xa==NULL) {
66 return;
67 }
68 if(xa->val.type == SR_XTYPE_DATA) {
69 if(xa->val.v.data!=NULL && xa->val.v.data->pfree!=NULL) {
70 xa->val.v.data->pfree(xa->val.v.data->p, xavp_shm_free);
71 shm_free(xa->val.v.data);
72 }
73 } else if(xa->val.type == SR_XTYPE_SPTR) {
74 if(xa->val.v.vptr) {
75 shm_free(xa->val.v.vptr);
76 }
77 } else if(xa->val.type == SR_XTYPE_XAVP) {
78 xavp_destroy_list(&xa->val.v.xavp);
79 }
80 shm_free(xa);
81 }
82
xavp_free_unsafe(sr_xavp_t * xa)83 void xavp_free_unsafe(sr_xavp_t *xa)
84 {
85 if(xa==NULL) {
86 return;
87 }
88 if(xa->val.type == SR_XTYPE_DATA) {
89 if(xa->val.v.data!=NULL && xa->val.v.data->pfree!=NULL) {
90 xa->val.v.data->pfree(xa->val.v.data->p, xavp_shm_free_unsafe);
91 shm_free_unsafe(xa->val.v.data);
92 }
93 } else if(xa->val.type == SR_XTYPE_SPTR) {
94 if(xa->val.v.vptr) {
95 shm_free_unsafe(xa->val.v.vptr);
96 }
97 } else if(xa->val.type == SR_XTYPE_XAVP) {
98 xavp_destroy_list_unsafe(&xa->val.v.xavp);
99 }
100 shm_free_unsafe(xa);
101 }
102
xavp_new_value(str * name,sr_xval_t * val)103 static sr_xavp_t *xavp_new_value(str *name, sr_xval_t *val)
104 {
105 sr_xavp_t *avp;
106 int size;
107 unsigned int id;
108
109 if(name==NULL || name->s==NULL || val==NULL)
110 return NULL;
111 id = get_hash1_raw(name->s, name->len);
112
113 size = sizeof(sr_xavp_t) + name->len + 1;
114 if(val->type == SR_XTYPE_STR)
115 size += val->v.s.len + 1;
116 avp = (sr_xavp_t*)shm_malloc(size);
117 if(avp==NULL) {
118 SHM_MEM_ERROR;
119 return NULL;
120 }
121 memset(avp, 0, size);
122 avp->id = id;
123 avp->name.s = (char*)avp + sizeof(sr_xavp_t);
124 memcpy(avp->name.s, name->s, name->len);
125 avp->name.s[name->len] = '\0';
126 avp->name.len = name->len;
127 memcpy(&avp->val, val, sizeof(sr_xval_t));
128 if(val->type == SR_XTYPE_STR)
129 {
130 avp->val.v.s.s = avp->name.s + avp->name.len + 1;
131 memcpy(avp->val.v.s.s, val->v.s.s, val->v.s.len);
132 avp->val.v.s.s[val->v.s.len] = '\0';
133 avp->val.v.s.len = val->v.s.len;
134 }
135
136 return avp;
137 }
138
xavp_add(sr_xavp_t * xavp,sr_xavp_t ** list)139 int xavp_add(sr_xavp_t *xavp, sr_xavp_t **list)
140 {
141 if (xavp==NULL) {
142 return -1;
143 }
144 /* Prepend new xavp to the list */
145 if(list) {
146 xavp->next = *list;
147 *list = xavp;
148 } else {
149 xavp->next = *_xavp_list_crt;
150 *_xavp_list_crt = xavp;
151 }
152
153 return 0;
154 }
155
xavp_add_last(sr_xavp_t * xavp,sr_xavp_t ** list)156 int xavp_add_last(sr_xavp_t *xavp, sr_xavp_t **list)
157 {
158 sr_xavp_t *prev;
159 sr_xavp_t *crt;
160
161 if (xavp==NULL) {
162 return -1;
163 }
164
165 crt = xavp_get_internal(&xavp->name, list, 0, 0);
166
167 prev = NULL;
168
169 while(crt) {
170 prev = crt;
171 crt = xavp_get_next(prev);
172 }
173
174 if(prev==NULL) {
175 /* Prepend new xavp to the list */
176 if(list) {
177 xavp->next = *list;
178 *list = xavp;
179 } else {
180 xavp->next = *_xavp_list_crt;
181 *_xavp_list_crt = xavp;
182 }
183 } else {
184 xavp->next = prev->next;
185 prev->next = xavp;
186 }
187
188 return 0;
189 }
190
xavp_add_after(sr_xavp_t * nxavp,sr_xavp_t * pxavp)191 int xavp_add_after(sr_xavp_t *nxavp, sr_xavp_t *pxavp)
192 {
193 if (nxavp==NULL) {
194 return -1;
195 }
196
197 if(pxavp==NULL) {
198 nxavp->next = *_xavp_list_crt;
199 *_xavp_list_crt = nxavp;
200 } else {
201 nxavp->next = pxavp->next;
202 pxavp->next = nxavp;
203 }
204
205 return 0;
206 }
207
xavp_add_value(str * name,sr_xval_t * val,sr_xavp_t ** list)208 sr_xavp_t *xavp_add_value(str *name, sr_xval_t *val, sr_xavp_t **list)
209 {
210 sr_xavp_t *avp=0;
211
212 avp = xavp_new_value(name, val);
213 if (avp==NULL)
214 return NULL;
215
216 /* Prepend new value to the list */
217 if(list) {
218 avp->next = *list;
219 *list = avp;
220 } else {
221 avp->next = *_xavp_list_crt;
222 *_xavp_list_crt = avp;
223 }
224
225 return avp;
226 }
227
xavp_add_value_after(str * name,sr_xval_t * val,sr_xavp_t * pxavp)228 sr_xavp_t *xavp_add_value_after(str *name, sr_xval_t *val, sr_xavp_t *pxavp)
229 {
230 sr_xavp_t *avp=0;
231
232 avp = xavp_new_value(name, val);
233 if (avp==NULL)
234 return NULL;
235
236 /* link new xavp */
237 if(pxavp) {
238 avp->next = pxavp->next;
239 pxavp->next = avp;
240 } else {
241 avp->next = *_xavp_list_crt;
242 *_xavp_list_crt = avp;
243 }
244
245 return avp;
246 }
247
xavp_add_xavp_value(str * rname,str * name,sr_xval_t * val,sr_xavp_t ** list)248 sr_xavp_t *xavp_add_xavp_value(str *rname, str *name, sr_xval_t *val, sr_xavp_t **list)
249 {
250 sr_xavp_t *ravp=0;
251 sr_xavp_t *cavp=0;
252 sr_xval_t rval;
253
254 cavp = xavp_new_value(name, val);
255 if (cavp==NULL)
256 return NULL;
257
258 memset(&rval, 0, sizeof(sr_xval_t));
259 rval.type = SR_XTYPE_XAVP;
260 rval.v.xavp = cavp;
261
262 ravp = xavp_new_value(rname, &rval);
263 if (ravp==NULL) {
264 xavp_destroy_list(&cavp);
265 return NULL;
266 }
267
268 /* Prepend new value to the list */
269 if(list) {
270 ravp->next = *list;
271 *list = ravp;
272 } else {
273 ravp->next = *_xavp_list_crt;
274 *_xavp_list_crt = ravp;
275 }
276
277 return ravp;
278 }
279
xavp_set_value(str * name,int idx,sr_xval_t * val,sr_xavp_t ** list)280 sr_xavp_t *xavp_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list)
281 {
282 sr_xavp_t *avp;
283 sr_xavp_t *cur;
284 sr_xavp_t *prv=0;
285
286 if(val==NULL)
287 return NULL;
288
289 /* Find the current value */
290 cur = xavp_get_internal(name, list, idx, &prv);
291 if(cur==NULL)
292 return NULL;
293
294 avp = xavp_new_value(name, val);
295 if (avp==NULL)
296 return NULL;
297
298 /* Replace the current value with the new */
299 avp->next = cur->next;
300 if(prv)
301 prv->next = avp;
302 else if(list)
303 *list = avp;
304 else
305 *_xavp_list_crt = avp;
306
307 xavp_free(cur);
308
309 return avp;
310 }
311
xavp_get_internal(str * name,sr_xavp_t ** list,int idx,sr_xavp_t ** prv)312 static sr_xavp_t *xavp_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv)
313 {
314 sr_xavp_t *avp;
315 unsigned int id;
316 int n = 0;
317
318 if(name==NULL || name->s==NULL)
319 return NULL;
320 id = get_hash1_raw(name->s, name->len);
321
322 if(list && *list)
323 avp = *list;
324 else
325 avp = *_xavp_list_crt;
326 while(avp)
327 {
328 if(avp->id==id && avp->name.len==name->len
329 && strncmp(avp->name.s, name->s, name->len)==0)
330 {
331 if(idx==n)
332 return avp;
333 n++;
334 }
335 if(prv)
336 *prv = avp;
337 avp = avp->next;
338 }
339 return NULL;
340 }
341
xavp_get(str * name,sr_xavp_t * start)342 sr_xavp_t *xavp_get(str *name, sr_xavp_t *start)
343 {
344 return xavp_get_internal(name, (start)?&start:NULL, 0, NULL);
345 }
346
xavp_get_by_index(str * name,int idx,sr_xavp_t ** start)347 sr_xavp_t *xavp_get_by_index(str *name, int idx, sr_xavp_t **start)
348 {
349 return xavp_get_internal(name, start, idx, NULL);
350 }
351
xavp_get_next(sr_xavp_t * start)352 sr_xavp_t *xavp_get_next(sr_xavp_t *start)
353 {
354 sr_xavp_t *avp;
355
356 if(start==NULL)
357 return NULL;
358
359 avp = start->next;
360 while(avp)
361 {
362 if(avp->id==start->id && avp->name.len==start->name.len
363 && strncmp(avp->name.s, start->name.s, start->name.len)==0)
364 return avp;
365 avp=avp->next;
366 }
367
368 return NULL;
369 }
370
xavp_get_last(str * xname,sr_xavp_t ** list)371 sr_xavp_t *xavp_get_last(str *xname, sr_xavp_t **list)
372 {
373 sr_xavp_t *prev;
374 sr_xavp_t *crt;
375
376 crt = xavp_get_internal(xname, list, 0, 0);
377
378 prev = NULL;
379
380 while(crt) {
381 prev = crt;
382 crt = xavp_get_next(prev);
383 }
384
385 return prev;
386 }
387
xavp_rm(sr_xavp_t * xa,sr_xavp_t ** head)388 int xavp_rm(sr_xavp_t *xa, sr_xavp_t **head)
389 {
390 sr_xavp_t *avp;
391 sr_xavp_t *prv=0;
392
393 if(head!=NULL)
394 avp = *head;
395 else
396 avp=*_xavp_list_crt;
397
398 while(avp)
399 {
400 if(avp==xa)
401 {
402 if(prv)
403 prv->next=avp->next;
404 else if(head!=NULL)
405 *head = avp->next;
406 else
407 *_xavp_list_crt = avp->next;
408 xavp_free(avp);
409 return 1;
410 }
411 prv=avp; avp=avp->next;
412 }
413 return 0;
414 }
415
416 /* Remove xavps
417 * idx: <0 remove all xavps with the same name
418 * >=0 remove only the specified index xavp
419 * Returns number of xavps that were deleted
420 */
xavp_rm_internal(str * name,sr_xavp_t ** head,int idx)421 static int xavp_rm_internal(str *name, sr_xavp_t **head, int idx)
422 {
423 sr_xavp_t *avp;
424 sr_xavp_t *foo;
425 sr_xavp_t *prv=0;
426 unsigned int id;
427 int n=0;
428 int count=0;
429
430 if(name==NULL || name->s==NULL)
431 return 0;
432
433 id = get_hash1_raw(name->s, name->len);
434 if(head!=NULL)
435 avp = *head;
436 else
437 avp = *_xavp_list_crt;
438 while(avp)
439 {
440 foo = avp;
441 avp=avp->next;
442 if(foo->id==id && foo->name.len==name->len
443 && strncmp(foo->name.s, name->s, name->len)==0)
444 {
445 if(idx<0 || idx==n)
446 {
447 if(prv!=NULL)
448 prv->next=foo->next;
449 else if(head!=NULL)
450 *head = foo->next;
451 else
452 *_xavp_list_crt = foo->next;
453 xavp_free(foo);
454 if(idx>=0)
455 return 1;
456 count++;
457 } else {
458 prv = foo;
459 }
460 n++;
461 } else {
462 prv = foo;
463 }
464 }
465 return count;
466 }
467
xavp_rm_by_name(str * name,int all,sr_xavp_t ** head)468 int xavp_rm_by_name(str *name, int all, sr_xavp_t **head)
469 {
470 return xavp_rm_internal(name, head, -1*all);
471 }
472
xavp_rm_by_index(str * name,int idx,sr_xavp_t ** head)473 int xavp_rm_by_index(str *name, int idx, sr_xavp_t **head)
474 {
475 if (idx<0)
476 return 0;
477 return xavp_rm_internal(name, head, idx);
478 }
479
xavp_rm_child_by_index(str * rname,str * cname,int idx)480 int xavp_rm_child_by_index(str *rname, str *cname, int idx)
481 {
482 sr_xavp_t *avp=NULL;
483
484 if (idx<0) {
485 return 0;
486 }
487 avp = xavp_get(rname, NULL);
488
489 if(avp == NULL || avp->val.type!=SR_XTYPE_XAVP) {
490 return 0;
491 }
492 return xavp_rm_internal(cname, &avp->val.v.xavp, idx);
493 }
494
xavp_count(str * name,sr_xavp_t ** start)495 int xavp_count(str *name, sr_xavp_t **start)
496 {
497 sr_xavp_t *avp;
498 unsigned int id;
499 int n = 0;
500
501 if(name==NULL || name->s==NULL)
502 return -1;
503 id = get_hash1_raw(name->s, name->len);
504
505 if(start)
506 avp = *start;
507 else
508 avp=*_xavp_list_crt;
509 while(avp)
510 {
511 if(avp->id==id && avp->name.len==name->len
512 && strncmp(avp->name.s, name->s, name->len)==0)
513 {
514 n++;
515 }
516 avp=avp->next;
517 }
518
519 return n;
520 }
521
xavp_destroy_list_unsafe(sr_xavp_t ** head)522 void xavp_destroy_list_unsafe(sr_xavp_t **head)
523 {
524 sr_xavp_t *avp, *foo;
525
526 avp = *head;
527 while(avp)
528 {
529 foo = avp;
530 avp = avp->next;
531 xavp_free_unsafe(foo);
532 }
533 *head = 0;
534 }
535
536
xavp_destroy_list(sr_xavp_t ** head)537 void xavp_destroy_list(sr_xavp_t **head)
538 {
539 sr_xavp_t *avp, *foo;
540
541 LM_DBG("destroying xavp list %p\n", *head);
542 avp = *head;
543 while(avp)
544 {
545 foo = avp;
546 avp = avp->next;
547 xavp_free(foo);
548 }
549 *head = 0;
550 }
551
552
xavp_reset_list(void)553 void xavp_reset_list(void)
554 {
555 assert(_xavp_list_crt!=0 );
556
557 if (_xavp_list_crt!=&_xavp_list_head)
558 _xavp_list_crt=&_xavp_list_head;
559 xavp_destroy_list(_xavp_list_crt);
560 }
561
562
xavp_set_list(sr_xavp_t ** head)563 sr_xavp_t **xavp_set_list(sr_xavp_t **head)
564 {
565 sr_xavp_t **avp;
566
567 assert(_xavp_list_crt!=0);
568
569 avp = _xavp_list_crt;
570 _xavp_list_crt = head;
571 return avp;
572 }
573
xavp_get_crt_list(void)574 sr_xavp_t **xavp_get_crt_list(void)
575 {
576 assert(_xavp_list_crt!=0);
577 return _xavp_list_crt;
578 }
579
xavx_print_list_content(char * name,sr_xavp_t ** head,sr_xavp_t ** rlist,int level)580 void xavx_print_list_content(char *name, sr_xavp_t **head, sr_xavp_t **rlist, int level)
581 {
582 sr_xavp_t *avp=0;
583 sr_xavp_t *start=0;
584
585 if(head!=NULL) {
586 start = *head;
587 } else {
588 start=*rlist;
589 }
590 LM_INFO("+++++ start %s list: %p (%p) (level=%d)\n", name, start, head, level);
591 avp = start;
592 while(avp)
593 {
594 LM_INFO(" *** (l:%d - %p) %s name: %s\n", level, avp, name, avp->name.s);
595 LM_INFO(" %s id: %u\n", name, avp->id);
596 LM_INFO(" %s value type: %d\n", name, avp->val.type);
597 switch(avp->val.type) {
598 case SR_XTYPE_NULL:
599 LM_INFO(" %s value: <null>\n", name);
600 break;
601 case SR_XTYPE_INT:
602 LM_INFO(" %s value (int): %d\n", name, avp->val.v.i);
603 break;
604 case SR_XTYPE_STR:
605 LM_INFO(" %s value (str): %s\n", name, avp->val.v.s.s);
606 break;
607 case SR_XTYPE_TIME:
608 LM_INFO(" %s value (time): %lu\n", name,
609 (long unsigned int)avp->val.v.t);
610 break;
611 case SR_XTYPE_LONG:
612 LM_INFO(" %s value (long): %ld\n", name, avp->val.v.l);
613 break;
614 case SR_XTYPE_LLONG:
615 LM_INFO(" %s value (llong): %lld\n", name, avp->val.v.ll);
616 break;
617 case SR_XTYPE_XAVP:
618 LM_INFO(" %s value: <xavp:%p>\n", name, avp->val.v.xavp);
619 xavx_print_list_content(name, &avp->val.v.xavp, rlist, level+1);
620 break;
621 case SR_XTYPE_VPTR:
622 LM_INFO(" %s value: <vptr:%p>\n", name, avp->val.v.vptr);
623 break;
624 case SR_XTYPE_SPTR:
625 LM_INFO(" %s value: <sptr:%p>\n", name, avp->val.v.vptr);
626 break;
627 case SR_XTYPE_DATA:
628 LM_INFO(" %s value: <data:%p>\n", name, avp->val.v.data);
629 break;
630 }
631 LM_INFO(" *** (l:%d - %p) end\n", level, avp);
632 avp = avp->next;
633 }
634 LM_INFO("----- end %s list: %p (level=%d)\n", name, start, level);
635 }
636
xavp_print_list_content(sr_xavp_t ** head,int level)637 void xavp_print_list_content(sr_xavp_t **head, int level)
638 {
639 xavx_print_list_content("XAVP", head, _xavp_list_crt, level);
640 }
641
xavp_print_list(sr_xavp_t ** head)642 void xavp_print_list(sr_xavp_t **head)
643 {
644 xavp_print_list_content(head, 0);
645 }
646
647 /**
648 * returns a list of str with key names.
649 * Example:
650 * If we have this structure
651 * $xavp(test=>one) = 1
652 * $xavp(test[0]=>two) = "2"
653 * $xavp(test[0]=>three) = 3
654 * $xavp(test[0]=>four) = $xavp(whatever)
655 * $xavp(test[0]=>two) = "other 2"
656 *
657 * xavp_get_list_keys_names(test[0]) returns
658 * {"one", "two", "three", "four"}
659 *
660 * free the struct str_list afterwards
661 * but do *NO* free the strings inside
662 */
xavp_get_list_key_names(sr_xavp_t * xavp)663 struct str_list *xavp_get_list_key_names(sr_xavp_t *xavp)
664 {
665 sr_xavp_t *avp = NULL;
666 struct str_list *result = NULL;
667 struct str_list *r = NULL;
668 struct str_list *f = NULL;
669 int total = 0;
670
671 if(xavp==NULL){
672 LM_ERR("xavp is NULL\n");
673 return 0;
674 }
675
676 if(xavp->val.type!=SR_XTYPE_XAVP){
677 LM_ERR("%s not xavp?\n", xavp->name.s);
678 return 0;
679 }
680
681 avp = xavp->val.v.xavp;
682
683 if (avp)
684 {
685 result = (struct str_list*)pkg_malloc(sizeof(struct str_list));
686 if (result==NULL) {
687 PKG_MEM_ERROR;
688 return 0;
689 }
690 r = result;
691 r->s.s = avp->name.s;
692 r->s.len = avp->name.len;
693 r->next = NULL;
694 avp = avp->next;
695 }
696
697 while(avp)
698 {
699 f = result;
700 while(f)
701 {
702 if((avp->name.len==f->s.len)&&
703 (strncmp(avp->name.s, f->s.s, f->s.len)==0))
704 {
705 break; /* name already on list */
706 }
707 f = f->next;
708 }
709 if (f==NULL)
710 {
711 r = append_str_list(avp->name.s, avp->name.len, &r, &total);
712 if(r==NULL){
713 while(result){
714 r = result;
715 result = result->next;
716 pkg_free(r);
717 }
718 return 0;
719 }
720 }
721 avp = avp->next;
722 }
723 return result;
724 }
725
xavp_clone_level_nodata(sr_xavp_t * xold)726 sr_xavp_t *xavp_clone_level_nodata(sr_xavp_t *xold)
727 {
728 return xavp_clone_level_nodata_with_new_name(xold, &xold->name);
729 }
730
731 /**
732 * clone the xavp without values that are custom data
733 * - only one list level is cloned, other sublists are ignored
734 */
xavp_clone_level_nodata_with_new_name(sr_xavp_t * xold,str * dst_name)735 sr_xavp_t *xavp_clone_level_nodata_with_new_name(sr_xavp_t *xold, str *dst_name)
736 {
737 sr_xavp_t *xnew = NULL;
738 sr_xavp_t *navp = NULL;
739 sr_xavp_t *oavp = NULL;
740 sr_xavp_t *pavp = NULL;
741
742 if(xold == NULL)
743 {
744 return NULL;
745 }
746 if(xold->val.type==SR_XTYPE_DATA || xold->val.type==SR_XTYPE_SPTR)
747 {
748 LM_INFO("xavp value type is 'data' - ignoring in clone\n");
749 return NULL;
750 }
751 xnew = xavp_new_value(dst_name, &xold->val);
752 if(xnew==NULL)
753 {
754 LM_ERR("cannot create cloned root xavp\n");
755 return NULL;
756 }
757 LM_DBG("cloned root xavp [%.*s] >> [%.*s]\n", xold->name.len, xold->name.s, dst_name->len, dst_name->s);
758
759 if(xold->val.type!=SR_XTYPE_XAVP)
760 {
761 return xnew;
762 }
763
764 xnew->val.v.xavp = NULL;
765 oavp = xold->val.v.xavp;
766
767 while(oavp)
768 {
769 if(oavp->val.type!=SR_XTYPE_DATA && oavp->val.type!=SR_XTYPE_XAVP
770 && oavp->val.type!=SR_XTYPE_SPTR)
771 {
772 navp = xavp_new_value(&oavp->name, &oavp->val);
773 if(navp==NULL)
774 {
775 LM_ERR("cannot create cloned embedded xavp\n");
776 if(xnew->val.v.xavp != NULL) {
777 xavp_destroy_list(&xnew->val.v.xavp);
778 }
779 shm_free(xnew);
780 return NULL;
781 }
782 LM_DBG("cloned inner xavp [%.*s]\n", oavp->name.len, oavp->name.s);
783 if(xnew->val.v.xavp == NULL)
784 {
785 /* link to val in head xavp */
786 xnew->val.v.xavp = navp;
787 } else {
788 /* link to prev xavp in the list */
789 pavp->next = navp;
790 }
791 pavp = navp;
792 }
793 oavp = oavp->next;
794 }
795
796 if(xnew->val.v.xavp == NULL)
797 {
798 shm_free(xnew);
799 return NULL;
800 }
801
802 return xnew;
803 }
804
xavp_insert(sr_xavp_t * xavp,int idx,sr_xavp_t ** list)805 int xavp_insert(sr_xavp_t *xavp, int idx, sr_xavp_t **list)
806 {
807 sr_xavp_t *crt = 0;
808 sr_xavp_t *lst = 0;
809 sr_xval_t val;
810 int n = 0;
811 int i = 0;
812
813 if(xavp==NULL) {
814 return -1;
815 }
816
817 crt = xavp_get_internal(&xavp->name, list, 0, NULL);
818
819 if (idx == 0 && (!crt || crt->val.type != SR_XTYPE_NULL))
820 return xavp_add(xavp, list);
821
822 while(crt!=NULL && n<idx) {
823 lst = crt;
824 n++;
825 crt = xavp_get_next(lst);
826 }
827
828 if (crt && crt->val.type == SR_XTYPE_NULL) {
829 xavp->next = crt->next;
830 crt->next = xavp;
831
832 xavp_rm(crt, list);
833 return 0;
834 }
835
836 memset(&val, 0, sizeof(sr_xval_t));
837 val.type = SR_XTYPE_NULL;
838 for(i=0; i<idx-n; i++) {
839 crt = xavp_new_value(&xavp->name, &val);
840 if(crt==NULL)
841 return -1;
842 if (lst == NULL) {
843 xavp_add(crt, list);
844 } else {
845 crt->next = lst->next;
846 lst->next = crt;
847 }
848 lst = crt;
849 }
850
851 if(lst==NULL) {
852 LM_ERR("cannot link the xavp\n");
853 return -1;
854 }
855 xavp->next = lst->next;
856 lst->next = xavp;
857
858 return 0;
859 }
860
xavp_extract(str * name,sr_xavp_t ** list)861 sr_xavp_t *xavp_extract(str *name, sr_xavp_t **list)
862 {
863 sr_xavp_t *avp = 0;
864 sr_xavp_t *foo;
865 sr_xavp_t *prv = 0;
866 unsigned int id;
867
868 if(name==NULL || name->s==NULL) {
869 if(list!=NULL) {
870 avp = *list;
871 if(avp!=NULL) {
872 *list = avp->next;
873 avp->next = NULL;
874 }
875 } else {
876 avp = *_xavp_list_crt;
877 if(avp!=NULL) {
878 *_xavp_list_crt = avp->next;
879 avp->next = NULL;
880 }
881 }
882
883 return avp;
884 }
885
886 id = get_hash1_raw(name->s, name->len);
887 if(list!=NULL)
888 avp = *list;
889 else
890 avp = *_xavp_list_crt;
891 while(avp)
892 {
893 foo = avp;
894 avp=avp->next;
895 if(foo->id==id && foo->name.len==name->len
896 && strncmp(foo->name.s, name->s, name->len)==0)
897 {
898 if(prv!=NULL)
899 prv->next=foo->next;
900 else if(list!=NULL)
901 *list = foo->next;
902 else
903 *_xavp_list_crt = foo->next;
904 foo->next = NULL;
905 return foo;
906 } else {
907 prv = foo;
908 }
909 }
910 return NULL;
911 }
912
913 /**
914 * return child node of an xavp
915 * - $xavp(rname=>cname)
916 */
xavp_get_child(str * rname,str * cname)917 sr_xavp_t* xavp_get_child(str *rname, str *cname)
918 {
919 sr_xavp_t *ravp=NULL;
920
921 ravp = xavp_get(rname, NULL);
922 if(ravp==NULL || ravp->val.type!=SR_XTYPE_XAVP)
923 return NULL;
924
925 return xavp_get(cname, ravp->val.v.xavp);
926 }
927
928
929 /**
930 * return child node of an xavp if it has int value
931 * - $xavp(rname=>cname)
932 */
xavp_get_child_with_ival(str * rname,str * cname)933 sr_xavp_t* xavp_get_child_with_ival(str *rname, str *cname)
934 {
935 sr_xavp_t *vavp=NULL;
936
937 vavp = xavp_get_child(rname, cname);
938
939 if(vavp==NULL || vavp->val.type!=SR_XTYPE_INT)
940 return NULL;
941
942 return vavp;
943 }
944
945
946 /**
947 * return child node of an xavp if it has string value
948 * - $xavp(rname=>cname)
949 */
xavp_get_child_with_sval(str * rname,str * cname)950 sr_xavp_t* xavp_get_child_with_sval(str *rname, str *cname)
951 {
952 sr_xavp_t *vavp=NULL;
953
954 vavp = xavp_get_child(rname, cname);
955
956 if(vavp==NULL || vavp->val.type!=SR_XTYPE_STR)
957 return NULL;
958
959 return vavp;
960 }
961
962 /**
963 * Set the value of the first xavp rname with first child xavp cname
964 * - replace if it exits; add if it doesn't exist
965 * - config operations:
966 * $xavp(rxname=>cname) = xval;
967 * or:
968 * $xavp(rxname[0]=>cname[0]) = xval;
969 */
xavp_set_child_xval(str * rname,str * cname,sr_xval_t * xval)970 int xavp_set_child_xval(str *rname, str *cname, sr_xval_t *xval)
971 {
972 sr_xavp_t *ravp=NULL;
973 sr_xavp_t *cavp=NULL;
974
975 ravp = xavp_get(rname, NULL);
976 if(ravp) {
977 if(ravp->val.type != SR_XTYPE_XAVP) {
978 /* first root xavp does not have xavp list value - remove it */
979 xavp_rm(ravp, NULL);
980 /* add a new xavp in the root list with a child */
981 if(xavp_add_xavp_value(rname, cname, xval, NULL)==NULL) {
982 return -1;
983 }
984 } else {
985 /* first root xavp has an xavp list value */
986 cavp = xavp_get(cname, ravp->val.v.xavp);
987 if(cavp) {
988 /* child xavp with same name - remove it */
989 /* todo: update in place for int or if allocated size fits */
990 xavp_rm(cavp, &ravp->val.v.xavp);
991 }
992 if(xavp_add_value(cname, xval, &ravp->val.v.xavp)==NULL) {
993 return -1;
994 }
995 }
996 } else {
997 /* no xavp with rname in root list found */
998 if(xavp_add_xavp_value(rname, cname, xval, NULL)==NULL) {
999 return -1;
1000 }
1001 }
1002
1003 return 0;
1004 }
1005
1006 /**
1007 *
1008 */
xavp_set_child_ival(str * rname,str * cname,int ival)1009 int xavp_set_child_ival(str *rname, str *cname, int ival)
1010 {
1011 sr_xval_t xval;
1012
1013 memset(&xval, 0, sizeof(sr_xval_t));
1014 xval.type = SR_XTYPE_INT;
1015 xval.v.i = ival;
1016
1017 return xavp_set_child_xval(rname, cname, &xval);
1018 }
1019
1020 /**
1021 *
1022 */
xavp_set_child_sval(str * rname,str * cname,str * sval)1023 int xavp_set_child_sval(str *rname, str *cname, str *sval)
1024 {
1025 sr_xval_t xval;
1026
1027 memset(&xval, 0, sizeof(sr_xval_t));
1028 xval.type = SR_XTYPE_STR;
1029 xval.v.s = *sval;
1030
1031 return xavp_set_child_xval(rname, cname, &xval);
1032 }
1033
1034 /**
1035 * serialize the values in subfields of an xavp in name=value; format
1036 * - rname - name of the root list xavp
1037 * - obuf - buffer were to write the output
1038 * - olen - the size of obuf
1039 * return: 0 - not found; -1 - error; >0 - length of output
1040 */
1041
xavp_serialize_fields(str * rname,char * obuf,int olen)1042 int xavp_serialize_fields(str *rname, char *obuf, int olen)
1043 {
1044 sr_xavp_t *ravp = NULL;
1045 sr_xavp_t *avp = NULL;
1046 str ostr;
1047 int rlen;
1048
1049 ravp = xavp_get(rname, NULL);
1050 if(ravp==NULL || ravp->val.type!=SR_XTYPE_XAVP) {
1051 /* not found or not holding subfields */
1052 return 0;
1053 }
1054
1055 rlen = 0;
1056 ostr.s = obuf;
1057 avp = ravp->val.v.xavp;
1058 while(avp) {
1059 switch(avp->val.type) {
1060 case SR_XTYPE_INT:
1061 LM_DBG(" XAVP int value: %d\n", avp->val.v.i);
1062 ostr.len = snprintf(ostr.s, olen-rlen, "%.*s=%u;",
1063 avp->name.len, avp->name.s, (unsigned int)avp->val.v.i);
1064 if(ostr.len<=0 || ostr.len>=olen-rlen) {
1065 LM_ERR("failed to serialize int value (%d/%d\n",
1066 ostr.len, olen-rlen);
1067 return -1;
1068 }
1069 break;
1070 case SR_XTYPE_STR:
1071 LM_DBG(" XAVP str value: %s\n", avp->val.v.s.s);
1072 if(avp->val.v.s.len == 0) {
1073 ostr.len = snprintf(ostr.s, olen-rlen, "%.*s;",
1074 avp->name.len, avp->name.s);
1075 } else {
1076 ostr.len = snprintf(ostr.s, olen-rlen, "%.*s=%.*s;",
1077 avp->name.len, avp->name.s,
1078 avp->val.v.s.len, avp->val.v.s.s);
1079 }
1080 if(ostr.len<=0 || ostr.len>=olen-rlen) {
1081 LM_ERR("failed to serialize int value (%d/%d\n",
1082 ostr.len, olen-rlen);
1083 return -1;
1084 }
1085 break;
1086 default:
1087 LM_DBG("skipping value type: %d\n", avp->val.type);
1088 ostr.len = 0;
1089 }
1090 if(ostr.len>0) {
1091 ostr.s += ostr.len;
1092 rlen += ostr.len;
1093 }
1094 avp = avp->next;
1095 }
1096 return rlen;
1097 }
1098
1099 /**
1100 *
1101 */
1102 /*** XAVU - eXtended Attribute Value Unique pair - implementation ***/
1103
1104 /**
1105 *
1106 */
xavu_print_list_content(sr_xavp_t ** head,int level)1107 void xavu_print_list_content(sr_xavp_t **head, int level)
1108 {
1109 xavx_print_list_content("XAVU", head, _xavu_list_crt, level);
1110 }
1111
xavu_print_list(sr_xavp_t ** head)1112 void xavu_print_list(sr_xavp_t **head)
1113 {
1114 xavu_print_list_content(head, 0);
1115 }
1116
1117 /**
1118 *
1119 */
xavu_reset_list(void)1120 void xavu_reset_list(void)
1121 {
1122 assert(_xavu_list_crt!=0 );
1123
1124 if (_xavu_list_crt!=&_xavu_list_head)
1125 _xavu_list_crt=&_xavu_list_head;
1126 xavp_destroy_list(_xavu_list_crt);
1127 }
1128
1129 /**
1130 *
1131 */
xavu_set_list(sr_xavp_t ** head)1132 sr_xavp_t **xavu_set_list(sr_xavp_t **head)
1133 {
1134 sr_xavp_t **avu;
1135
1136 assert(_xavu_list_crt!=0);
1137
1138 avu = _xavu_list_crt;
1139 _xavu_list_crt = head;
1140 return avu;
1141 }
1142
1143 /**
1144 *
1145 */
xavu_get_crt_list(void)1146 sr_xavp_t **xavu_get_crt_list(void)
1147 {
1148 assert(_xavu_list_crt!=0);
1149 return _xavu_list_crt;
1150 }
1151
1152 /**
1153 *
1154 */
xavu_get_internal(str * name,sr_xavp_t ** list,sr_xavp_t ** prv)1155 static sr_xavp_t *xavu_get_internal(str *name, sr_xavp_t **list, sr_xavp_t **prv)
1156 {
1157 sr_xavp_t *avu;
1158 unsigned int id;
1159
1160 if(name==NULL || name->s==NULL) {
1161 return NULL;
1162 }
1163
1164 id = get_hash1_raw(name->s, name->len);
1165
1166 if(list && *list) {
1167 avu = *list;
1168 } else {
1169 avu = *_xavu_list_crt;
1170 }
1171 while(avu) {
1172 if(avu->id==id && avu->name.len==name->len
1173 && strncmp(avu->name.s, name->s, name->len)==0) {
1174 return avu;
1175 }
1176 if(prv) {
1177 *prv = avu;
1178 }
1179 avu = avu->next;
1180 }
1181 return NULL;
1182 }
1183
1184 /**
1185 *
1186 */
xavu_get(str * name,sr_xavp_t * start)1187 sr_xavp_t *xavu_get(str *name, sr_xavp_t *start)
1188 {
1189 return xavu_get_internal(name, (start)?&start:NULL, NULL);
1190 }
1191
xavu_lookup(str * name,sr_xavp_t ** start)1192 sr_xavp_t *xavu_lookup(str *name, sr_xavp_t **start)
1193 {
1194 return xavu_get_internal(name, start, NULL);
1195 }
1196
1197 /**
1198 *
1199 */
xavu_rm(sr_xavp_t * xa,sr_xavp_t ** head)1200 int xavu_rm(sr_xavp_t *xa, sr_xavp_t **head)
1201 {
1202 sr_xavp_t *avu;
1203 sr_xavp_t *prv=0;
1204
1205 if(head!=NULL)
1206 avu = *head;
1207 else
1208 avu=*_xavu_list_crt;
1209
1210 while(avu) {
1211 if(avu==xa) {
1212 if(prv) {
1213 prv->next=avu->next;
1214 } else if(head!=NULL) {
1215 *head = avu->next;
1216 } else {
1217 *_xavu_list_crt = avu->next;
1218 }
1219 xavp_free(avu);
1220 return 1;
1221 }
1222 prv=avu; avu=avu->next;
1223 }
1224 return 0;
1225 }
1226
1227 /**
1228 *
1229 */
xavu_rm_by_name(str * name,sr_xavp_t ** head)1230 int xavu_rm_by_name(str *name, sr_xavp_t **head)
1231 {
1232 sr_xavp_t *avu;
1233 sr_xavp_t *foo;
1234 sr_xavp_t *prv=0;
1235 unsigned int id;
1236
1237
1238 if(name==NULL || name->s==NULL) {
1239 return -1;
1240 }
1241
1242 id = get_hash1_raw(name->s, name->len);
1243 if(head!=NULL) {
1244 avu = *head;
1245 } else {
1246 avu = *_xavu_list_crt;
1247 }
1248 while(avu) {
1249 foo = avu;
1250 avu = avu->next;
1251 if(foo->id==id && foo->name.len==name->len
1252 && strncmp(foo->name.s, name->s, name->len)==0) {
1253 if(prv!=NULL) {
1254 prv->next=foo->next;
1255 } else if(head!=NULL) {
1256 *head = foo->next;
1257 } else {
1258 *_xavu_list_crt = foo->next;
1259 }
1260 xavp_free(foo);
1261 } else {
1262 prv = foo;
1263 }
1264 }
1265 return 0;
1266 }
1267
1268 /**
1269 *
1270 */
xavu_rm_child_by_name(str * rname,str * cname)1271 int xavu_rm_child_by_name(str *rname, str *cname)
1272 {
1273 sr_xavp_t *avu=NULL;
1274
1275 avu = xavu_lookup(rname, NULL);
1276
1277 if(avu == NULL || avu->val.type!=SR_XTYPE_XAVP) {
1278 return 0;
1279 }
1280 return xavu_rm_by_name(cname, &avu->val.v.xavp);
1281 }
1282
1283 /**
1284 *
1285 */
xavu_set_xval(str * name,sr_xval_t * val,sr_xavp_t ** list)1286 sr_xavp_t *xavu_set_xval(str *name, sr_xval_t *val, sr_xavp_t **list)
1287 {
1288 sr_xavp_t *avu;
1289 sr_xavp_t *crt;
1290 sr_xavp_t *prv=0;
1291
1292 if(val==NULL) {
1293 return NULL;
1294 }
1295
1296 avu = xavp_new_value(name, val);
1297 if (avu==NULL) {
1298 return NULL;
1299 }
1300
1301 /* find the current value */
1302 crt = xavu_get_internal(name, list, &prv);
1303 if(crt==NULL) {
1304 /* add a new one in the list */
1305 avu->next = *_xavu_list_crt;
1306 *_xavu_list_crt = avu;
1307 return avu;
1308 }
1309
1310 /* replace the current value with the new */
1311 avu->next = crt->next;
1312 if(prv) {
1313 prv->next = avu;
1314 } else if(list) {
1315 *list = avu;
1316 } else {
1317 *_xavu_list_crt = avu;
1318 }
1319
1320 xavp_free(crt);
1321
1322 return avu;
1323 }
1324
1325 /**
1326 *
1327 */
xavu_set_ival(str * rname,int ival)1328 sr_xavp_t *xavu_set_ival(str *rname, int ival)
1329 {
1330 sr_xval_t xval;
1331
1332 memset(&xval, 0, sizeof(sr_xval_t));
1333 xval.type = SR_XTYPE_INT;
1334 xval.v.i = ival;
1335
1336 return xavu_set_xval(rname, &xval, NULL);
1337 }
1338
1339 /**
1340 *
1341 */
xavu_set_sval(str * rname,str * sval)1342 sr_xavp_t *xavu_set_sval(str *rname, str *sval)
1343 {
1344 sr_xval_t xval;
1345
1346 memset(&xval, 0, sizeof(sr_xval_t));
1347 xval.type = SR_XTYPE_STR;
1348 xval.v.s = *sval;
1349
1350 return xavu_set_xval(rname, &xval, NULL);
1351 }
1352
1353 /**
1354 *
1355 */
xavu_set_xavu_value(str * rname,str * name,sr_xval_t * val,sr_xavp_t ** list)1356 sr_xavp_t *xavu_set_xavu_value(str *rname, str *name, sr_xval_t *val, sr_xavp_t **list)
1357 {
1358 sr_xavp_t *ravu=0;
1359 sr_xavp_t *cavu=0;
1360 sr_xval_t rval;
1361
1362 cavu = xavp_new_value(name, val);
1363 if (cavu==NULL) {
1364 return NULL;
1365 }
1366
1367 memset(&rval, 0, sizeof(sr_xval_t));
1368 rval.type = SR_XTYPE_XAVP;
1369 rval.v.xavp = cavu;
1370
1371 ravu = xavp_new_value(rname, &rval);
1372 if (ravu==NULL) {
1373 xavp_destroy_list(&cavu);
1374 return NULL;
1375 }
1376
1377 /* Prepend new value to the list */
1378 if(list) {
1379 ravu->next = *list;
1380 *list = ravu;
1381 } else {
1382 ravu->next = *_xavu_list_crt;
1383 *_xavu_list_crt = ravu;
1384 }
1385
1386 return ravu;
1387 }
1388
1389 /**
1390 * Set the value of the xavu rname with child xavu cname
1391 * - set if it exits; add if it doesn't exist
1392 * - config operations:
1393 * $xavu(rxname=>cname) = xval;
1394 */
xavu_set_child_xval(str * rname,str * cname,sr_xval_t * xval)1395 sr_xavp_t *xavu_set_child_xval(str *rname, str *cname, sr_xval_t *xval)
1396 {
1397 sr_xavp_t *ravu=NULL;
1398 sr_xavp_t *cavu=NULL;
1399
1400 ravu = xavu_get(rname, NULL);
1401 if(ravu) {
1402 if(ravu->val.type != SR_XTYPE_XAVP) {
1403 /* first root xavp does not have xavp list value - remove it */
1404 xavp_rm(ravu, NULL);
1405 /* add a new xavp in the root list with a child */
1406 return xavu_set_xavu_value(rname, cname, xval, NULL);
1407 } else {
1408 /* first root xavp has an xavp list value */
1409 cavu = xavu_get(cname, ravu->val.v.xavp);
1410 if(cavu) {
1411 /* child xavp with same name - remove it */
1412 /* todo: update in place for int or if allocated size fits */
1413 xavp_rm(cavu, &ravu->val.v.xavp);
1414 }
1415 return xavp_add_value(cname, xval, &ravu->val.v.xavp);
1416 }
1417 } else {
1418 /* no xavp with rname in root list found */
1419 return xavu_set_xavu_value(rname, cname, xval, NULL);
1420 }
1421 }
1422
1423 /**
1424 *
1425 */
xavu_set_child_ival(str * rname,str * cname,int ival)1426 sr_xavp_t *xavu_set_child_ival(str *rname, str *cname, int ival)
1427 {
1428 sr_xval_t xval;
1429
1430 memset(&xval, 0, sizeof(sr_xval_t));
1431 xval.type = SR_XTYPE_INT;
1432 xval.v.i = ival;
1433
1434 return xavu_set_child_xval(rname, cname, &xval);
1435 }
1436
1437 /**
1438 *
1439 */
xavu_set_child_sval(str * rname,str * cname,str * sval)1440 sr_xavp_t *xavu_set_child_sval(str *rname, str *cname, str *sval)
1441 {
1442 sr_xval_t xval;
1443
1444 memset(&xval, 0, sizeof(sr_xval_t));
1445 xval.type = SR_XTYPE_STR;
1446 xval.v.s = *sval;
1447
1448 return xavu_set_child_xval(rname, cname, &xval);
1449 }
1450
1451
1452 /**
1453 *
1454 */
1455 /*** XAVI - eXtended Attribute Value Insensitive case - implementation ***/
1456 /*! Helper functions */
1457 static sr_xavp_t *xavi_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv);
1458 static int xavi_rm_internal(str *name, sr_xavp_t **head, int idx);
1459
1460 /**
1461 *
1462 */
xavi_new_value(str * name,sr_xval_t * val)1463 static sr_xavp_t *xavi_new_value(str *name, sr_xval_t *val)
1464 {
1465 sr_xavp_t *avi;
1466 int size;
1467 unsigned int id;
1468
1469 if(name==NULL || name->s==NULL || val==NULL)
1470 return NULL;
1471 id = get_hash1_case_raw(name->s, name->len);
1472
1473 size = sizeof(sr_xavp_t) + name->len + 1;
1474 if(val->type == SR_XTYPE_STR)
1475 size += val->v.s.len + 1;
1476 avi = (sr_xavp_t*)shm_malloc(size);
1477 if(avi==NULL) {
1478 SHM_MEM_ERROR;
1479 return NULL;
1480 }
1481 memset(avi, 0, size);
1482 avi->id = id;
1483 avi->name.s = (char*)avi + sizeof(sr_xavp_t);
1484 memcpy(avi->name.s, name->s, name->len);
1485 avi->name.s[name->len] = '\0';
1486 avi->name.len = name->len;
1487 memcpy(&avi->val, val, sizeof(sr_xval_t));
1488 if(val->type == SR_XTYPE_STR)
1489 {
1490 avi->val.v.s.s = avi->name.s + avi->name.len + 1;
1491 memcpy(avi->val.v.s.s, val->v.s.s, val->v.s.len);
1492 avi->val.v.s.s[val->v.s.len] = '\0';
1493 avi->val.v.s.len = val->v.s.len;
1494 }
1495
1496 return avi;
1497 }
1498
1499 /**
1500 *
1501 */
xavi_add(sr_xavp_t * xavi,sr_xavp_t ** list)1502 int xavi_add(sr_xavp_t *xavi, sr_xavp_t **list)
1503 {
1504 if (xavi==NULL) {
1505 return -1;
1506 }
1507 /* Prepend new xavi to the list */
1508 if(list) {
1509 xavi->next = *list;
1510 *list = xavi;
1511 } else {
1512 xavi->next = *_xavi_list_crt;
1513 *_xavi_list_crt = xavi;
1514 }
1515
1516 return 0;
1517 }
1518
1519 /**
1520 *
1521 */
xavi_add_last(sr_xavp_t * xavi,sr_xavp_t ** list)1522 int xavi_add_last(sr_xavp_t *xavi, sr_xavp_t **list)
1523 {
1524 sr_xavp_t *prev;
1525 sr_xavp_t *crt;
1526
1527 if (xavi==NULL) {
1528 return -1;
1529 }
1530
1531 crt = xavi_get_internal(&xavi->name, list, 0, 0);
1532
1533 prev = NULL;
1534
1535 while(crt) {
1536 prev = crt;
1537 crt = xavi_get_next(prev);
1538 }
1539
1540 if(prev==NULL) {
1541 /* Prepend new xavi to the list */
1542 if(list) {
1543 xavi->next = *list;
1544 *list = xavi;
1545 } else {
1546 xavi->next = *_xavi_list_crt;
1547 *_xavi_list_crt = xavi;
1548 }
1549 } else {
1550 xavi->next = prev->next;
1551 prev->next = xavi;
1552 }
1553
1554 return 0;
1555 }
1556
1557 /**
1558 *
1559 */
xavi_add_after(sr_xavp_t * nxavi,sr_xavp_t * pxavi)1560 int xavi_add_after(sr_xavp_t *nxavi, sr_xavp_t *pxavi)
1561 {
1562 if (nxavi==NULL) {
1563 return -1;
1564 }
1565
1566 if(pxavi==NULL) {
1567 nxavi->next = *_xavi_list_crt;
1568 *_xavi_list_crt = nxavi;
1569 } else {
1570 nxavi->next = pxavi->next;
1571 pxavi->next = nxavi;
1572 }
1573
1574 return 0;
1575 }
1576
1577 /**
1578 *
1579 */
xavi_add_value(str * name,sr_xval_t * val,sr_xavp_t ** list)1580 sr_xavp_t *xavi_add_value(str *name, sr_xval_t *val, sr_xavp_t **list)
1581 {
1582 sr_xavp_t *avi=0;
1583
1584 avi = xavi_new_value(name, val);
1585 if (avi==NULL)
1586 return NULL;
1587
1588 /* Prepend new value to the list */
1589 if(list) {
1590 avi->next = *list;
1591 *list = avi;
1592 } else {
1593 avi->next = *_xavi_list_crt;
1594 *_xavi_list_crt = avi;
1595 }
1596
1597 return avi;
1598 }
1599
1600 /**
1601 *
1602 */
xavi_add_value_after(str * name,sr_xval_t * val,sr_xavp_t * pxavi)1603 sr_xavp_t *xavi_add_value_after(str *name, sr_xval_t *val, sr_xavp_t *pxavi)
1604 {
1605 sr_xavp_t *avi=0;
1606
1607 avi = xavi_new_value(name, val);
1608 if (avi==NULL)
1609 return NULL;
1610
1611 /* link new xavi */
1612 if(pxavi) {
1613 avi->next = pxavi->next;
1614 pxavi->next = avi;
1615 } else {
1616 avi->next = *_xavi_list_crt;
1617 *_xavi_list_crt = avi;
1618 }
1619
1620 return avi;
1621 }
1622
1623 /**
1624 *
1625 */
xavi_add_xavi_value(str * rname,str * name,sr_xval_t * val,sr_xavp_t ** list)1626 sr_xavp_t *xavi_add_xavi_value(str *rname, str *name, sr_xval_t *val, sr_xavp_t **list)
1627 {
1628 sr_xavp_t *ravi=0;
1629 sr_xavp_t *cavi=0;
1630 sr_xval_t rval;
1631
1632 cavi = xavi_new_value(name, val);
1633 if (cavi==NULL)
1634 return NULL;
1635
1636 memset(&rval, 0, sizeof(sr_xval_t));
1637 rval.type = SR_XTYPE_XAVP;
1638 rval.v.xavp = cavi;
1639
1640 ravi = xavi_new_value(rname, &rval);
1641 if (ravi==NULL) {
1642 xavi_destroy_list(&cavi);
1643 return NULL;
1644 }
1645
1646 /* Prepend new value to the list */
1647 if(list) {
1648 ravi->next = *list;
1649 *list = ravi;
1650 } else {
1651 ravi->next = *_xavi_list_crt;
1652 *_xavi_list_crt = ravi;
1653 }
1654
1655 return ravi;
1656 }
1657
1658 /**
1659 *
1660 */
xavi_set_value(str * name,int idx,sr_xval_t * val,sr_xavp_t ** list)1661 sr_xavp_t *xavi_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list)
1662 {
1663 sr_xavp_t *avi;
1664 sr_xavp_t *cur;
1665 sr_xavp_t *prv=0;
1666
1667 if(val==NULL)
1668 return NULL;
1669
1670 /* Find the current value */
1671 cur = xavi_get_internal(name, list, idx, &prv);
1672 if(cur==NULL)
1673 return NULL;
1674
1675 avi = xavi_new_value(name, val);
1676 if (avi==NULL)
1677 return NULL;
1678
1679 /* Replace the current value with the new */
1680 avi->next = cur->next;
1681 if(prv)
1682 prv->next = avi;
1683 else if(list)
1684 *list = avi;
1685 else
1686 *_xavi_list_crt = avi;
1687
1688 xavi_free(cur);
1689
1690 return avi;
1691 }
1692
1693 /**
1694 *
1695 */
xavi_get_internal(str * name,sr_xavp_t ** list,int idx,sr_xavp_t ** prv)1696 static sr_xavp_t *xavi_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv)
1697 {
1698 sr_xavp_t *avi;
1699 unsigned int id;
1700 int n = 0;
1701
1702 if(name==NULL || name->s==NULL)
1703 return NULL;
1704 id = get_hash1_case_raw(name->s, name->len);
1705
1706 if(list && *list)
1707 avi = *list;
1708 else
1709 avi = *_xavi_list_crt;
1710 while(avi)
1711 {
1712 if(avi->id==id && avi->name.len==name->len
1713 && strncasecmp(avi->name.s, name->s, name->len)==0)
1714 {
1715 if(idx==n)
1716 return avi;
1717 n++;
1718 }
1719 if(prv)
1720 *prv = avi;
1721 avi = avi->next;
1722 }
1723 return NULL;
1724 }
1725
1726 /**
1727 *
1728 */
xavi_get(str * name,sr_xavp_t * start)1729 sr_xavp_t *xavi_get(str *name, sr_xavp_t *start)
1730 {
1731 return xavi_get_internal(name, (start)?&start:NULL, 0, NULL);
1732 }
1733
1734 /**
1735 *
1736 */
xavi_get_by_index(str * name,int idx,sr_xavp_t ** start)1737 sr_xavp_t *xavi_get_by_index(str *name, int idx, sr_xavp_t **start)
1738 {
1739 return xavi_get_internal(name, start, idx, NULL);
1740 }
1741
1742 /**
1743 *
1744 */
xavi_get_next(sr_xavp_t * start)1745 sr_xavp_t *xavi_get_next(sr_xavp_t *start)
1746 {
1747 sr_xavp_t *avi;
1748
1749 if(start==NULL)
1750 return NULL;
1751
1752 avi = start->next;
1753 while(avi)
1754 {
1755 if(avi->id==start->id && avi->name.len==start->name.len
1756 && strncasecmp(avi->name.s, start->name.s, start->name.len)==0)
1757 return avi;
1758 avi=avi->next;
1759 }
1760
1761 return NULL;
1762 }
1763
1764 /**
1765 *
1766 */
xavi_get_last(str * xname,sr_xavp_t ** list)1767 sr_xavp_t *xavi_get_last(str *xname, sr_xavp_t **list)
1768 {
1769 sr_xavp_t *prev;
1770 sr_xavp_t *crt;
1771
1772 crt = xavi_get_internal(xname, list, 0, 0);
1773
1774 prev = NULL;
1775
1776 while(crt) {
1777 prev = crt;
1778 crt = xavi_get_next(prev);
1779 }
1780
1781 return prev;
1782 }
1783
1784 /**
1785 *
1786 */
xavi_rm(sr_xavp_t * xa,sr_xavp_t ** head)1787 int xavi_rm(sr_xavp_t *xa, sr_xavp_t **head)
1788 {
1789 sr_xavp_t *avi;
1790 sr_xavp_t *prv=0;
1791
1792 if(head!=NULL)
1793 avi = *head;
1794 else
1795 avi=*_xavi_list_crt;
1796
1797 while(avi)
1798 {
1799 if(avi==xa)
1800 {
1801 if(prv)
1802 prv->next=avi->next;
1803 else if(head!=NULL)
1804 *head = avi->next;
1805 else
1806 *_xavi_list_crt = avi->next;
1807 xavi_free(avi);
1808 return 1;
1809 }
1810 prv=avi; avi=avi->next;
1811 }
1812 return 0;
1813 }
1814
1815 /* Remove xavis
1816 * idx: <0 remove all xavis with the same name
1817 * >=0 remove only the specified index xavi
1818 * Returns number of xavis that were deleted
1819 */
xavi_rm_internal(str * name,sr_xavp_t ** head,int idx)1820 static int xavi_rm_internal(str *name, sr_xavp_t **head, int idx)
1821 {
1822 sr_xavp_t *avi;
1823 sr_xavp_t *foo;
1824 sr_xavp_t *prv=0;
1825 unsigned int id;
1826 int n=0;
1827 int count=0;
1828
1829 if(name==NULL || name->s==NULL)
1830 return 0;
1831
1832 id = get_hash1_case_raw(name->s, name->len);
1833 if(head!=NULL)
1834 avi = *head;
1835 else
1836 avi = *_xavi_list_crt;
1837 while(avi)
1838 {
1839 foo = avi;
1840 avi=avi->next;
1841 if(foo->id==id && foo->name.len==name->len
1842 && strncasecmp(foo->name.s, name->s, name->len)==0)
1843 {
1844 if(idx<0 || idx==n)
1845 {
1846 if(prv!=NULL)
1847 prv->next=foo->next;
1848 else if(head!=NULL)
1849 *head = foo->next;
1850 else
1851 *_xavi_list_crt = foo->next;
1852 xavi_free(foo);
1853 if(idx>=0)
1854 return 1;
1855 count++;
1856 } else {
1857 prv = foo;
1858 }
1859 n++;
1860 } else {
1861 prv = foo;
1862 }
1863 }
1864 return count;
1865 }
1866
1867 /**
1868 *
1869 */
xavi_rm_by_name(str * name,int all,sr_xavp_t ** head)1870 int xavi_rm_by_name(str *name, int all, sr_xavp_t **head)
1871 {
1872 return xavi_rm_internal(name, head, -1*all);
1873 }
1874
1875 /**
1876 *
1877 */
xavi_rm_by_index(str * name,int idx,sr_xavp_t ** head)1878 int xavi_rm_by_index(str *name, int idx, sr_xavp_t **head)
1879 {
1880 if (idx<0)
1881 return 0;
1882 return xavi_rm_internal(name, head, idx);
1883 }
1884
1885 /**
1886 *
1887 */
xavi_rm_child_by_index(str * rname,str * cname,int idx)1888 int xavi_rm_child_by_index(str *rname, str *cname, int idx)
1889 {
1890 sr_xavp_t *avi=NULL;
1891
1892 if (idx<0) {
1893 return 0;
1894 }
1895 avi = xavi_get(rname, NULL);
1896
1897 if(avi == NULL || avi->val.type!=SR_XTYPE_XAVP) {
1898 return 0;
1899 }
1900 return xavi_rm_internal(cname, &avi->val.v.xavp, idx);
1901 }
1902
1903 /**
1904 *
1905 */
xavi_count(str * name,sr_xavp_t ** start)1906 int xavi_count(str *name, sr_xavp_t **start)
1907 {
1908 sr_xavp_t *avi;
1909 unsigned int id;
1910 int n = 0;
1911
1912 if(name==NULL || name->s==NULL)
1913 return -1;
1914 id = get_hash1_case_raw(name->s, name->len);
1915
1916 if(start)
1917 avi = *start;
1918 else
1919 avi=*_xavi_list_crt;
1920 while(avi)
1921 {
1922 if(avi->id==id && avi->name.len==name->len
1923 && strncasecmp(avi->name.s, name->s, name->len)==0)
1924 {
1925 n++;
1926 }
1927 avi=avi->next;
1928 }
1929
1930 return n;
1931 }
1932
1933 /**
1934 *
1935 */
xavi_reset_list(void)1936 void xavi_reset_list(void)
1937 {
1938 assert(_xavi_list_crt!=0 );
1939
1940 if (_xavi_list_crt!=&_xavi_list_head)
1941 _xavi_list_crt=&_xavi_list_head;
1942 xavi_destroy_list(_xavi_list_crt);
1943 }
1944
1945 /**
1946 *
1947 */
xavi_set_list(sr_xavp_t ** head)1948 sr_xavp_t **xavi_set_list(sr_xavp_t **head)
1949 {
1950 sr_xavp_t **avi;
1951
1952 assert(_xavi_list_crt!=0);
1953
1954 avi = _xavi_list_crt;
1955 _xavi_list_crt = head;
1956 return avi;
1957 }
1958
1959 /**
1960 *
1961 */
xavi_get_crt_list(void)1962 sr_xavp_t **xavi_get_crt_list(void)
1963 {
1964 assert(_xavi_list_crt!=0);
1965 return _xavi_list_crt;
1966 }
1967
1968 /**
1969 *
1970 */
xavi_print_list_content(sr_xavp_t ** head,int level)1971 void xavi_print_list_content(sr_xavp_t **head, int level)
1972 {
1973 xavx_print_list_content("XAVI", head, _xavi_list_crt, level);
1974 }
1975
1976 /**
1977 *
1978 */
xavi_print_list(sr_xavp_t ** head)1979 void xavi_print_list(sr_xavp_t **head)
1980 {
1981 xavi_print_list_content(head, 0);
1982 }
1983
1984 /**
1985 * returns a list of str with key names.
1986 * Example:
1987 * If we have this structure
1988 * $xavi(test=>one) = 1
1989 * $xavi(test[0]=>two) = "2"
1990 * $xavi(test[0]=>three) = 3
1991 * $xavi(test[0]=>four) = $xavp(whatever)
1992 * $xavi(test[0]=>two) = "other 2"
1993 *
1994 * xavi_get_list_keys_names(test[0]) returns
1995 * {"one", "two", "three", "four"}
1996 *
1997 * free the struct str_list afterwards
1998 * but do *NOT* free the strings inside
1999 */
xavi_get_list_key_names(sr_xavp_t * xavi)2000 struct str_list *xavi_get_list_key_names(sr_xavp_t *xavi)
2001 {
2002 sr_xavp_t *avi = NULL;
2003 struct str_list *result = NULL;
2004 struct str_list *r = NULL;
2005 struct str_list *f = NULL;
2006 int total = 0;
2007
2008 if(xavi==NULL){
2009 LM_ERR("xavi is NULL\n");
2010 return 0;
2011 }
2012
2013 if(xavi->val.type!=SR_XTYPE_XAVP){
2014 LM_ERR("%s not xavp?\n", xavi->name.s);
2015 return 0;
2016 }
2017
2018 avi = xavi->val.v.xavp;
2019
2020 if (avi)
2021 {
2022 result = (struct str_list*)pkg_malloc(sizeof(struct str_list));
2023 if (result==NULL) {
2024 PKG_MEM_ERROR;
2025 return 0;
2026 }
2027 r = result;
2028 r->s.s = avi->name.s;
2029 r->s.len = avi->name.len;
2030 r->next = NULL;
2031 avi = avi->next;
2032 }
2033
2034 while(avi)
2035 {
2036 f = result;
2037 while(f)
2038 {
2039 if((avi->name.len==f->s.len)&&
2040 (strncasecmp(avi->name.s, f->s.s, f->s.len)==0))
2041 {
2042 break; /* name already on list */
2043 }
2044 f = f->next;
2045 }
2046 if (f==NULL)
2047 {
2048 r = append_str_list(avi->name.s, avi->name.len, &r, &total);
2049 if(r==NULL){
2050 while(result){
2051 r = result;
2052 result = result->next;
2053 pkg_free(r);
2054 }
2055 return 0;
2056 }
2057 }
2058 avi = avi->next;
2059 }
2060 return result;
2061 }
2062
xavi_clone_level_nodata(sr_xavp_t * xold)2063 sr_xavp_t *xavi_clone_level_nodata(sr_xavp_t *xold)
2064 {
2065 return xavi_clone_level_nodata_with_new_name(xold, &xold->name);
2066 }
2067
2068 /**
2069 * clone the xavi without values that are custom data
2070 * - only one list level is cloned, other sublists are ignored
2071 */
xavi_clone_level_nodata_with_new_name(sr_xavp_t * xold,str * dst_name)2072 sr_xavp_t *xavi_clone_level_nodata_with_new_name(sr_xavp_t *xold, str *dst_name)
2073 {
2074 sr_xavp_t *xnew = NULL;
2075 sr_xavp_t *navi = NULL;
2076 sr_xavp_t *oavi = NULL;
2077 sr_xavp_t *pavi = NULL;
2078
2079 if(xold == NULL)
2080 {
2081 return NULL;
2082 }
2083 if(xold->val.type==SR_XTYPE_DATA || xold->val.type==SR_XTYPE_SPTR)
2084 {
2085 LM_INFO("xavi value type is 'data' - ignoring in clone\n");
2086 return NULL;
2087 }
2088 xnew = xavi_new_value(dst_name, &xold->val);
2089 if(xnew==NULL)
2090 {
2091 LM_ERR("cannot create cloned root xavi\n");
2092 return NULL;
2093 }
2094 LM_DBG("cloned root xavi [%.*s] >> [%.*s]\n", xold->name.len, xold->name.s, dst_name->len, dst_name->s);
2095
2096 if(xold->val.type!=SR_XTYPE_XAVP)
2097 {
2098 return xnew;
2099 }
2100
2101 xnew->val.v.xavp = NULL;
2102 oavi = xold->val.v.xavp;
2103
2104 while(oavi)
2105 {
2106 if(oavi->val.type!=SR_XTYPE_DATA && oavi->val.type!=SR_XTYPE_XAVP
2107 && oavi->val.type!=SR_XTYPE_SPTR)
2108 {
2109 navi = xavi_new_value(&oavi->name, &oavi->val);
2110 if(navi==NULL)
2111 {
2112 LM_ERR("cannot create cloned embedded xavi\n");
2113 if(xnew->val.v.xavp != NULL) {
2114 xavi_destroy_list(&xnew->val.v.xavp);
2115 }
2116 shm_free(xnew);
2117 return NULL;
2118 }
2119 LM_DBG("cloned inner xavi [%.*s]\n", oavi->name.len, oavi->name.s);
2120 if(xnew->val.v.xavp == NULL)
2121 {
2122 /* link to val in head xavi */
2123 xnew->val.v.xavp = navi;
2124 } else {
2125 /* link to prev xavi in the list */
2126 pavi->next = navi;
2127 }
2128 pavi = navi;
2129 }
2130 oavi = oavi->next;
2131 }
2132
2133 if(xnew->val.v.xavp == NULL)
2134 {
2135 shm_free(xnew);
2136 return NULL;
2137 }
2138
2139 return xnew;
2140 }
2141
xavi_insert(sr_xavp_t * xavi,int idx,sr_xavp_t ** list)2142 int xavi_insert(sr_xavp_t *xavi, int idx, sr_xavp_t **list)
2143 {
2144 sr_xavp_t *crt = 0;
2145 sr_xavp_t *lst = 0;
2146 sr_xval_t val;
2147 int n = 0;
2148 int i = 0;
2149
2150 if(xavi==NULL) {
2151 return -1;
2152 }
2153
2154 crt = xavi_get_internal(&xavi->name, list, 0, NULL);
2155
2156 if (idx == 0 && (!crt || crt->val.type != SR_XTYPE_NULL))
2157 return xavi_add(xavi, list);
2158
2159 while(crt!=NULL && n<idx) {
2160 lst = crt;
2161 n++;
2162 crt = xavi_get_next(lst);
2163 }
2164
2165 if (crt && crt->val.type == SR_XTYPE_NULL) {
2166 xavi->next = crt->next;
2167 crt->next = xavi;
2168
2169 xavi_rm(crt, list);
2170 return 0;
2171 }
2172
2173 memset(&val, 0, sizeof(sr_xval_t));
2174 val.type = SR_XTYPE_NULL;
2175 for(i=0; i<idx-n; i++) {
2176 crt = xavi_new_value(&xavi->name, &val);
2177 if(crt==NULL)
2178 return -1;
2179 if (lst == NULL) {
2180 xavi_add(crt, list);
2181 } else {
2182 crt->next = lst->next;
2183 lst->next = crt;
2184 }
2185 lst = crt;
2186 }
2187
2188 if(lst==NULL) {
2189 LM_ERR("cannot link the xavi\n");
2190 return -1;
2191 }
2192 xavi->next = lst->next;
2193 lst->next = xavi;
2194
2195 return 0;
2196 }
2197
xavi_extract(str * name,sr_xavp_t ** list)2198 sr_xavp_t *xavi_extract(str *name, sr_xavp_t **list)
2199 {
2200 sr_xavp_t *avi = 0;
2201 sr_xavp_t *foo;
2202 sr_xavp_t *prv = 0;
2203 unsigned int id;
2204
2205 if(name==NULL || name->s==NULL) {
2206 if(list!=NULL) {
2207 avi = *list;
2208 if(avi!=NULL) {
2209 *list = avi->next;
2210 avi->next = NULL;
2211 }
2212 } else {
2213 avi = *_xavi_list_crt;
2214 if(avi!=NULL) {
2215 *_xavi_list_crt = avi->next;
2216 avi->next = NULL;
2217 }
2218 }
2219
2220 return avi;
2221 }
2222
2223 id = get_hash1_case_raw(name->s, name->len);
2224 if(list!=NULL)
2225 avi = *list;
2226 else
2227 avi = *_xavi_list_crt;
2228 while(avi)
2229 {
2230 foo = avi;
2231 avi=avi->next;
2232 if(foo->id==id && foo->name.len==name->len
2233 && strncasecmp(foo->name.s, name->s, name->len)==0)
2234 {
2235 if(prv!=NULL)
2236 prv->next=foo->next;
2237 else if(list!=NULL)
2238 *list = foo->next;
2239 else
2240 *_xavi_list_crt = foo->next;
2241 foo->next = NULL;
2242 return foo;
2243 } else {
2244 prv = foo;
2245 }
2246 }
2247 return NULL;
2248 }
2249
2250 /**
2251 * return child node of an xavi
2252 * - $xavi(rname=>cname)
2253 */
xavi_get_child(str * rname,str * cname)2254 sr_xavp_t* xavi_get_child(str *rname, str *cname)
2255 {
2256 sr_xavp_t *ravi=NULL;
2257
2258 ravi = xavi_get(rname, NULL);
2259 if(ravi==NULL || ravi->val.type!=SR_XTYPE_XAVP)
2260 return NULL;
2261
2262 return xavi_get(cname, ravi->val.v.xavp);
2263 }
2264
2265
2266 /**
2267 * return child node of an xavi if it has int value
2268 * - $xavi(rname=>cname)
2269 */
xavi_get_child_with_ival(str * rname,str * cname)2270 sr_xavp_t* xavi_get_child_with_ival(str *rname, str *cname)
2271 {
2272 sr_xavp_t *vavi=NULL;
2273
2274 vavi = xavi_get_child(rname, cname);
2275
2276 if(vavi==NULL || vavi->val.type!=SR_XTYPE_INT)
2277 return NULL;
2278
2279 return vavi;
2280 }
2281
2282
2283 /**
2284 * return child node of an xavi if it has string value
2285 * - $xavi(rname=>cname)
2286 */
xavi_get_child_with_sval(str * rname,str * cname)2287 sr_xavp_t* xavi_get_child_with_sval(str *rname, str *cname)
2288 {
2289 sr_xavp_t *vavi=NULL;
2290
2291 vavi = xavi_get_child(rname, cname);
2292
2293 if(vavi==NULL || vavi->val.type!=SR_XTYPE_STR)
2294 return NULL;
2295
2296 return vavi;
2297 }
2298
2299 /**
2300 * Set the value of the first xavi rname with first child xavi cname
2301 * - replace if it exits; add if it doesn't exist
2302 * - config operations:
2303 * $xavi(rxname=>cname) = xval;
2304 * or:
2305 * $xavi(rxname[0]=>cname[0]) = xval;
2306 */
xavi_set_child_xval(str * rname,str * cname,sr_xval_t * xval)2307 int xavi_set_child_xval(str *rname, str *cname, sr_xval_t *xval)
2308 {
2309 sr_xavp_t *ravi=NULL;
2310 sr_xavp_t *cavi=NULL;
2311
2312 ravi = xavi_get(rname, NULL);
2313 if(ravi) {
2314 if(ravi->val.type != SR_XTYPE_XAVP) {
2315 /* first root xavi does not have xavi list value - remove it */
2316 xavi_rm(ravi, NULL);
2317 /* add a new xavi in the root list with a child */
2318 if(xavi_add_xavi_value(rname, cname, xval, NULL)==NULL) {
2319 return -1;
2320 }
2321 } else {
2322 /* first root xavi has an xavi list value */
2323 cavi = xavi_get(cname, ravi->val.v.xavp);
2324 if(cavi) {
2325 /* child xavi with same name - remove it */
2326 /* todo: update in place for int or if allocated size fits */
2327 xavi_rm(cavi, &ravi->val.v.xavp);
2328 }
2329 if(xavi_add_value(cname, xval, &ravi->val.v.xavp)==NULL) {
2330 return -1;
2331 }
2332 }
2333 } else {
2334 /* no xavi with rname in root list found */
2335 if(xavi_add_xavi_value(rname, cname, xval, NULL)==NULL) {
2336 return -1;
2337 }
2338 }
2339
2340 return 0;
2341 }
2342
2343 /**
2344 *
2345 */
xavi_set_child_ival(str * rname,str * cname,int ival)2346 int xavi_set_child_ival(str *rname, str *cname, int ival)
2347 {
2348 sr_xval_t xval;
2349
2350 memset(&xval, 0, sizeof(sr_xval_t));
2351 xval.type = SR_XTYPE_INT;
2352 xval.v.i = ival;
2353
2354 return xavi_set_child_xval(rname, cname, &xval);
2355 }
2356
2357 /**
2358 *
2359 */
xavi_set_child_sval(str * rname,str * cname,str * sval)2360 int xavi_set_child_sval(str *rname, str *cname, str *sval)
2361 {
2362 sr_xval_t xval;
2363
2364 memset(&xval, 0, sizeof(sr_xval_t));
2365 xval.type = SR_XTYPE_STR;
2366 xval.v.s = *sval;
2367
2368 return xavi_set_child_xval(rname, cname, &xval);
2369 }
2370
2371 /**
2372 * serialize the values in subfields of an xavi in name=value; format
2373 * - rname - name of the root list xavi
2374 * - obuf - buffer were to write the output
2375 * - olen - the size of obuf
2376 * return: 0 - not found; -1 - error; >0 - length of output
2377 */
xavi_serialize_fields(str * rname,char * obuf,int olen)2378 int xavi_serialize_fields(str *rname, char *obuf, int olen)
2379 {
2380 sr_xavp_t *ravi = NULL;
2381 sr_xavp_t *avi = NULL;
2382 str ostr;
2383 int rlen;
2384
2385 ravi = xavi_get(rname, NULL);
2386 if(ravi==NULL || ravi->val.type!=SR_XTYPE_XAVP) {
2387 /* not found or not holding subfields */
2388 return 0;
2389 }
2390
2391 rlen = 0;
2392 ostr.s = obuf;
2393 avi = ravi->val.v.xavp;
2394 while(avi) {
2395 switch(avi->val.type) {
2396 case SR_XTYPE_INT:
2397 LM_DBG(" XAVP int value: %d\n", avi->val.v.i);
2398 ostr.len = snprintf(ostr.s, olen-rlen, "%.*s=%u;",
2399 avi->name.len, avi->name.s, (unsigned int)avi->val.v.i);
2400 if(ostr.len<=0 || ostr.len>=olen-rlen) {
2401 LM_ERR("failed to serialize int value (%d/%d\n",
2402 ostr.len, olen-rlen);
2403 return -1;
2404 }
2405 break;
2406 case SR_XTYPE_STR:
2407 LM_DBG(" XAVP str value: %s\n", avi->val.v.s.s);
2408 if(avi->val.v.s.len == 0) {
2409 ostr.len = snprintf(ostr.s, olen-rlen, "%.*s;",
2410 avi->name.len, avi->name.s);
2411 } else {
2412 ostr.len = snprintf(ostr.s, olen-rlen, "%.*s=%.*s;",
2413 avi->name.len, avi->name.s,
2414 avi->val.v.s.len, avi->val.v.s.s);
2415 }
2416 if(ostr.len<=0 || ostr.len>=olen-rlen) {
2417 LM_ERR("failed to serialize int value (%d/%d\n",
2418 ostr.len, olen-rlen);
2419 return -1;
2420 }
2421 break;
2422 default:
2423 LM_DBG("skipping value type: %d\n", avi->val.type);
2424 ostr.len = 0;
2425 }
2426 if(ostr.len>0) {
2427 ostr.s += ostr.len;
2428 rlen += ostr.len;
2429 }
2430 avi = avi->next;
2431 }
2432 return rlen;
2433 }
2434