modules/lcr: Fixed to/from_gw tests when proto parameter is 0 (ANY)
[sip-router] / xavp.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com) 
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 /*
19  * History:
20  * --------
21  *  2009-05-20  created by daniel
22  */
23
24
25 #ifdef WITH_XAVP
26
27 #include <stdio.h>
28 #include <string.h>
29
30 #include "mem/shm_mem.h"
31 #include "dprint.h"
32 #include "hashes.h"
33 #include "xavp.h"
34
35 /*! XAVP list head */
36 static sr_xavp_t *_xavp_list_head = 0;
37 /*! Pointer to XAVP current list */
38 static sr_xavp_t **_xavp_list_crt = &_xavp_list_head;
39
40 /*! Helper functions */
41 static sr_xavp_t *xavp_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv);
42 static int xavp_rm_internal(str *name, sr_xavp_t **head, int idx);
43
44
45 void xavp_shm_free(void *p)
46 {
47         shm_free(p);
48 }
49
50 void xavp_shm_free_unsafe(void *p)
51 {
52         shm_free_unsafe(p);
53 }
54
55
56 void xavp_free(sr_xavp_t *xa)
57 {
58         if(xa->val.type == SR_XTYPE_DATA) {
59                 if(xa->val.v.data!=NULL && xa->val.v.data->pfree!=NULL) {
60                         xa->val.v.data->pfree(xa->val.v.data->p, xavp_shm_free);
61                         shm_free(xa->val.v.data);
62                 }
63         } else if(xa->val.type == SR_XTYPE_XAVP) {
64                 xavp_destroy_list(&xa->val.v.xavp);
65         }
66         shm_free(xa);
67 }
68
69 void xavp_free_unsafe(sr_xavp_t *xa)
70 {
71         if(xa->val.type == SR_XTYPE_DATA) {
72                 if(xa->val.v.data!=NULL && xa->val.v.data->pfree!=NULL) {
73                         xa->val.v.data->pfree(xa->val.v.data->p, xavp_shm_free_unsafe);
74                         shm_free_unsafe(xa->val.v.data);
75                 }
76         } else if(xa->val.type == SR_XTYPE_XAVP) {
77                 xavp_destroy_list_unsafe(&xa->val.v.xavp);
78         }
79         shm_free_unsafe(xa);
80 }
81
82 static sr_xavp_t *xavp_new_value(str *name, sr_xval_t *val)
83 {
84         sr_xavp_t *avp;
85         int size;
86         unsigned int id;
87
88         if(name==NULL || name->s==NULL || val==NULL)
89                 return NULL;
90         id = get_hash1_raw(name->s, name->len);
91
92         size = sizeof(sr_xavp_t) + name->len + 1;
93         if(val->type == SR_XTYPE_STR)
94                 size += val->v.s.len + 1;
95         avp = (sr_xavp_t*)shm_malloc(size);
96         if(avp==NULL)
97                 return NULL;
98         memset(avp, 0, size);
99         avp->id = id;
100         avp->name.s = (char*)avp + sizeof(sr_xavp_t);
101         memcpy(avp->name.s, name->s, name->len);
102         avp->name.s[name->len] = '\0';
103         avp->name.len = name->len;
104         memcpy(&avp->val, val, sizeof(sr_xval_t));
105         if(val->type == SR_XTYPE_STR)
106         {
107                 avp->val.v.s.s = avp->name.s + avp->name.len + 1;
108                 memcpy(avp->val.v.s.s, val->v.s.s, val->v.s.len);
109                 avp->val.v.s.s[val->v.s.len] = '\0';
110                 avp->val.v.s.len = val->v.s.len;
111         }
112
113         return avp;
114 }
115
116 sr_xavp_t *xavp_add_value(str *name, sr_xval_t *val, sr_xavp_t **list)
117 {
118         sr_xavp_t *avp=0;
119
120         avp = xavp_new_value(name, val);
121         if (avp==NULL)
122                 return NULL;
123
124         /* Prepend new value to the list */
125         if(list) {
126                 avp->next = *list;
127                 *list = avp;
128         } else {
129                 avp->next = *_xavp_list_crt;
130                 *_xavp_list_crt = avp;
131         }
132
133         return avp;
134 }
135
136 sr_xavp_t *xavp_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list)
137 {
138         sr_xavp_t *avp;
139         sr_xavp_t *cur;
140         sr_xavp_t *prv=0;
141
142         if(val==NULL)
143                 return NULL;
144
145         /* Find the current value */
146         cur = xavp_get_internal(name, list, idx, &prv);
147         if(cur==NULL)
148                 return NULL;
149
150         avp = xavp_new_value(name, val);
151         if (avp==NULL)
152                 return NULL;
153
154         /* Replace the current value with the new */
155         avp->next = cur->next;
156         if(prv)
157                 prv->next = avp;
158         else if(list)
159                 *list = avp;
160         else
161                 *_xavp_list_crt = avp;
162
163         xavp_free(cur);
164
165         return avp;
166 }
167
168 static sr_xavp_t *xavp_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv)
169 {
170         sr_xavp_t *avp;
171         unsigned int id;
172         int n = 0;
173
174         if(name==NULL || name->s==NULL)
175                 return NULL;
176         id = get_hash1_raw(name->s, name->len);
177         
178         if(list && *list)
179                 avp = *list;
180         else
181                 avp = *_xavp_list_crt;
182         while(avp)
183         {
184                 if(avp->id==id && avp->name.len==name->len
185                                 && strncmp(avp->name.s, name->s, name->len)==0)
186                 {
187                         if(idx==n)
188                                 return avp;
189                         n++;
190                 }
191                 if(prv)
192                         *prv = avp;
193                 avp = avp->next;
194         }
195         return NULL;
196 }
197
198 sr_xavp_t *xavp_get(str *name, sr_xavp_t *start)
199 {
200         return xavp_get_internal(name, (start)?&start:NULL, 0, NULL);
201 }
202
203 sr_xavp_t *xavp_get_by_index(str *name, int idx, sr_xavp_t **start)
204 {
205         return xavp_get_internal(name, start, idx, NULL);
206 }
207
208 sr_xavp_t *xavp_get_next(sr_xavp_t *start)
209 {
210         sr_xavp_t *avp;
211
212         if(start==NULL)
213                 return NULL;
214         
215         avp = start->next;
216         while(avp)
217         {
218                 if(avp->id==start->id && avp->name.len==start->name.len
219                                 && strncmp(avp->name.s, start->name.s, start->name.len)==0)
220                         return avp;
221                 avp=avp->next;
222         }
223
224         return NULL;
225 }
226
227
228 int xavp_rm(sr_xavp_t *xa, sr_xavp_t **head)
229 {
230         sr_xavp_t *avp;
231         sr_xavp_t *prv=0;
232
233         if(head!=NULL)
234                 avp = *head;
235         else
236                 avp=*_xavp_list_crt;
237
238         while(avp)
239         {
240                 if(avp==xa)
241                 {
242                         if(prv)
243                                 prv->next=avp->next;
244                         else if(head!=NULL)
245                                 *head = avp->next;
246                         else
247                                 *_xavp_list_crt = avp->next;
248                         xavp_free(avp);
249                         return 1;
250                 }
251                 prv=avp; avp=avp->next;
252         }
253         return 0;
254 }
255
256 /* Remove xavps
257  * idx: <0 remove all xavps with the same name
258  *      >=0 remove only the specified index xavp
259  * Returns number of xavps that were deleted
260  */
261 static int xavp_rm_internal(str *name, sr_xavp_t **head, int idx)
262 {
263         sr_xavp_t *avp;
264         sr_xavp_t *foo;
265         sr_xavp_t *prv=0;
266         unsigned int id;
267         int n=0;
268         int count=0;
269
270         if(name==NULL || name->s==NULL)
271                 return 0;
272
273         id = get_hash1_raw(name->s, name->len);
274         if(head!=NULL)
275                 avp = *head;
276         else
277                 avp = *_xavp_list_crt;
278         while(avp)
279         {
280                 foo = avp;
281                 avp=avp->next;
282                 if(foo->id==id && foo->name.len==name->len
283                                 && strncmp(foo->name.s, name->s, name->len)==0)
284                 {
285                         if(idx<0 || idx==n)
286                         {
287                                 if(prv!=NULL)
288                                         prv->next=foo->next;
289                                 else if(head!=NULL)
290                                         *head = foo->next;
291                                 else
292                                         *_xavp_list_crt = foo->next;
293                                 xavp_free(foo);
294                                 if(idx>=0)
295                                         return 1;
296                                 count++;
297                         }
298                         n++;
299                 } else {
300                         prv = foo;
301                 }
302         }
303         return count;
304 }
305
306 int xavp_rm_by_name(str *name, int all, sr_xavp_t **head)
307 {
308         return xavp_rm_internal(name, head, -1*all);
309 }
310
311 int xavp_rm_by_index(str *name, int idx, sr_xavp_t **head)
312 {
313         if (idx<0)
314                 return 0;
315         return xavp_rm_internal(name, head, idx);
316 }
317
318
319 int xavp_count(str *name, sr_xavp_t **start)
320 {
321         sr_xavp_t *avp;
322         unsigned int id;
323         int n = 0;
324
325         if(name==NULL || name->s==NULL)
326                 return -1;
327         id = get_hash1_raw(name->s, name->len);
328         
329         if(start)
330                 avp = *start;
331         else
332                 avp=*_xavp_list_crt;
333         while(avp)
334         {
335                 if(avp->id==id && avp->name.len==name->len
336                                 && strncmp(avp->name.s, name->s, name->len)==0)
337                 {
338                         n++;
339                 }
340                 avp=avp->next;
341         }
342
343         return n;
344 }
345
346 void xavp_destroy_list_unsafe(sr_xavp_t **head)
347 {
348         sr_xavp_t *avp, *foo;
349
350         avp = *head;
351         while(avp)
352         {
353                 foo = avp;
354                 avp = avp->next;
355                 xavp_free_unsafe(foo);
356         }
357         *head = 0;
358 }
359
360
361 void xavp_destroy_list(sr_xavp_t **head)
362 {
363         sr_xavp_t *avp, *foo;
364
365         LM_DBG("destroying xavp list %p\n", *head);
366         avp = *head;
367         while(avp)
368         {
369                 foo = avp;
370                 avp = avp->next;
371                 xavp_free(foo);
372         }
373         *head = 0;
374 }
375
376
377 void xavp_reset_list(void)
378 {
379         assert(_xavp_list_crt!=0 );
380         
381         if (_xavp_list_crt!=&_xavp_list_head)
382                 _xavp_list_crt=&_xavp_list_head;
383         xavp_destroy_list(_xavp_list_crt);
384 }
385
386
387 sr_xavp_t **xavp_set_list(sr_xavp_t **head)
388 {
389         sr_xavp_t **avp;
390         
391         assert(_xavp_list_crt!=0);
392
393         avp = _xavp_list_crt;
394         _xavp_list_crt = head;
395         return avp;
396 }
397
398 sr_xavp_t **xavp_get_crt_list(void)
399 {
400         assert(_xavp_list_crt!=0);
401         return _xavp_list_crt;
402 }
403
404 void xavp_print_list_content(sr_xavp_t **head, int level)
405 {
406         sr_xavp_t *avp=0;
407         sr_xavp_t *start=0;
408
409         if(head!=NULL)
410                 start = *head;
411         else
412                 start=*_xavp_list_crt;
413         LM_INFO("+++++ start XAVP list: %p (level=%d)\n", start, level);
414         avp = start;
415         while(avp)
416         {
417                 LM_INFO("     *** XAVP name: %s\n", avp->name.s);
418                 LM_INFO("     XAVP id: %u\n", avp->id);
419                 LM_INFO("     XAVP value type: %d\n", avp->val.type);
420                 switch(avp->val.type) {
421                         case SR_XTYPE_NULL:
422                                 LM_INFO("     XAVP value: <null>\n");
423                         break;
424                         case SR_XTYPE_INT:
425                                 LM_INFO("     XAVP value: %d\n", avp->val.v.i);
426                         break;
427                         case SR_XTYPE_STR:
428                                 LM_INFO("     XAVP value: %s\n", avp->val.v.s.s);
429                         break;
430                         case SR_XTYPE_TIME:
431                                 LM_INFO("     XAVP value: %lu\n",
432                                                 (long unsigned int)avp->val.v.t);
433                         break;
434                         case SR_XTYPE_LONG:
435                                 LM_INFO("     XAVP value: %ld\n", avp->val.v.l);
436                         break;
437                         case SR_XTYPE_LLONG:
438                                 LM_INFO("     XAVP value: %lld\n", avp->val.v.ll);
439                         break;
440                         case SR_XTYPE_XAVP:
441                                 LM_INFO("     XAVP value: <xavp:%p>\n", avp->val.v.xavp);
442                                 xavp_print_list_content(&avp->val.v.xavp, level+1);
443                         break;
444                         case SR_XTYPE_DATA:
445                                 LM_INFO("     XAVP value: <data:%p>\n", avp->val.v.data);
446                         break;
447                 }
448                 avp = avp->next;
449         }
450         LM_INFO("----- end XAVP list: %p (level=%d)\n", start, level);
451 }
452
453 void xavp_print_list(sr_xavp_t **head)
454 {
455         xavp_print_list_content(head, 0);
456 }
457 #endif