Browse code

Merge remote branch 'origin/daniel/xavp'

* origin/daniel/xavp:
pv: export new PV class $xavp(name)
core: introducing xavp (eXtended AVP)
tm: set/reset head of xavps on TM events
pv: new pv class $xavp(...)
core: destroy xavp list once sip msg processing is done

Conflicts:
modules/tm/h_table.c
modules/tm/t_reply.c
modules/tm/uac.c
modules_k/pv/pv.c

Andrei Pelinescu-Onciul authored on 15/02/2010 14:47:37
Showing 11 changed files
... ...
@@ -212,6 +212,10 @@ void free_cell( struct cell* dead_cell )
212 212
 		destroy_avp_list_unsafe( &dead_cell->uri_avps_from );
213 213
 	if (dead_cell->uri_avps_to)
214 214
 		destroy_avp_list_unsafe( &dead_cell->uri_avps_to );
215
+#ifdef WITH_XAVP
216
+	if (dead_cell->xavps_list)
217
+		xavp_destroy_list_unsafe( &dead_cell->xavps_list );
218
+#endif
215 219
 
216 220
 	/* the cell's body */
217 221
 	shm_free_unsafe( dead_cell );
... ...
@@ -278,6 +282,9 @@ struct cell*  build_cell( struct sip_msg* p_msg )
278 282
 	int          sip_msg_len;
279 283
 	avp_list_t* old;
280 284
 	struct tm_callback *cbs, *cbs_tmp;
285
+#ifdef WITH_XAVP
286
+	sr_xavp_t** xold;
287
+#endif
281 288
 
282 289
 	/* allocs a new cell */
283 290
 	/* if syn_branch==0 add space for md5 (MD5_LEN -sizeof(struct cell.md5)) */
... ...
@@ -317,6 +324,12 @@ struct cell*  build_cell( struct sip_msg* p_msg )
317 324
 	new_cell->user_avps_to = *old;
318 325
 	*old = 0;
319 326
 
327
+#ifdef WITH_XAVP
328
+	xold = xavp_set_list(&new_cell->xavps_list );
329
+	new_cell->xavps_list = *xold;
330
+	*xold = 0;
331
+#endif
332
+
320 333
 	     /* We can just store pointer to domain avps in the transaction context,
321 334
 	      * because they are read-only
322 335
 	      */
... ...
@@ -380,9 +393,15 @@ error:
380 393
 	destroy_avp_list(&new_cell->user_avps_to);
381 394
 	destroy_avp_list(&new_cell->uri_avps_from);
382 395
 	destroy_avp_list(&new_cell->uri_avps_to);
396
+#ifdef WITH_XAVP
397
+	xavp_destroy_list(&new_cell->xavps_list);
398
+#endif
383 399
 	shm_free(new_cell);
384 400
 	/* unlink transaction AVP list and link back the global AVP list (bogdan)*/
385 401
 	reset_avps();
402
+#ifdef WITH_XAVP
403
+	xavp_reset_list();
404
+#endif
386 405
 	return NULL;
387 406
 }
388 407
 
... ...
@@ -71,6 +71,9 @@
71 71
 #include "../../types.h"
72 72
 #include "../../md5utils.h"
73 73
 #include "../../usr_avp.h"
74
+#ifdef WITH_XAVP
75
+#include "../../xavp.h"
76
+#endif
74 77
 #include "../../timer.h"
75 78
 #include "../../flags.h"
76 79
 #include "../../atomic_ops.h"
... ...
@@ -362,7 +365,10 @@ typedef struct cell
362 365
 	struct usr_avp *user_avps_to;
363 366
 	struct usr_avp *domain_avps_from;
364 367
 	struct usr_avp *domain_avps_to;
365
-	
368
+#ifdef WITH_XAVP
369
+	sr_xavp_t *xavps_list;
370
+#endif
371
+
366 372
 	/* protection against concurrent reply processing */
367 373
 	ser_lock_t   reply_mutex;
368 374
 	
... ...
@@ -259,6 +259,9 @@ void run_trans_callbacks_internal(struct tmcb_head_list* cb_lst, int type,
259 259
 {
260 260
 	struct tm_callback    *cbp;
261 261
 	avp_list_t* backup_from, *backup_to, *backup_dom_from, *backup_dom_to, *backup_uri_from, *backup_uri_to;
262
+#ifdef WITH_XAVP
263
+	sr_xavp_t **backup_xavps;
264
+#endif
262 265
 
263 266
 	backup_uri_from = set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM,
264 267
 			&trans->uri_avps_from );
... ...
@@ -272,6 +275,10 @@ void run_trans_callbacks_internal(struct tmcb_head_list* cb_lst, int type,
272 275
 			&trans->domain_avps_from);
273 276
 	backup_dom_to = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, 
274 277
 			&trans->domain_avps_to);
278
+#ifdef WITH_XAVP
279
+	backup_xavps = xavp_set_list(&trans->xavps_list);
280
+#endif
281
+
275 282
 	cbp=(struct tm_callback*)cb_lst->first;
276 283
 	while(cbp){
277 284
 		membar_depends(); /* make sure the cache has the correct cbp 
... ...
@@ -290,6 +297,9 @@ void run_trans_callbacks_internal(struct tmcb_head_list* cb_lst, int type,
290 297
 	set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, backup_from );
291 298
 	set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, backup_uri_to );
292 299
 	set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM, backup_uri_from );
300
+#ifdef WITH_XAVP
301
+	xavp_set_list(backup_xavps);
302
+#endif
293 303
 }
294 304
 
295 305
 
... ...
@@ -116,6 +116,9 @@
116 116
 #include "../../data_lump.h"
117 117
 #include "../../data_lump_rpl.h"
118 118
 #include "../../usr_avp.h"
119
+#ifdef WITH_XAVP
120
+#include "../../usr_avp.h"
121
+#endif
119 122
 #include "../../atomic_ops.h" /* membar_write() */
120 123
 #include "../../compiler_opt.h"
121 124
 #ifdef USE_DST_BLACKLIST
... ...
@@ -692,6 +695,9 @@ void faked_env( struct cell *t, struct sip_msg *msg)
692 695
 	static avp_list_t* backup_user_from, *backup_user_to;
693 696
 	static avp_list_t* backup_domain_from, *backup_domain_to;
694 697
 	static avp_list_t* backup_uri_from, *backup_uri_to;
698
+#ifdef WITH_XAVP
699
+	static sr_xavp_t **backup_xavps;
700
+#endif
695 701
 	static struct socket_info* backup_si;
696 702
 
697 703
 	if (msg) {
... ...
@@ -722,6 +728,9 @@ void faked_env( struct cell *t, struct sip_msg *msg)
722 728
 		backup_user_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to );
723 729
 		backup_domain_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from );
724 730
 		backup_domain_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to );
731
+#ifdef WITH_XAVP
732
+		backup_xavps = xavp_set_list(&t->xavps_list);
733
+#endif
725 734
 		/* set default send address to the saved value */
726 735
 		backup_si=bind_address;
727 736
 		bind_address=t->uac[0].request.dst.send_sock;
... ...
@@ -737,6 +746,9 @@ void faked_env( struct cell *t, struct sip_msg *msg)
737 746
 		set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, backup_domain_to );
738 747
 		set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, backup_uri_from );
739 748
 		set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, backup_uri_to );
749
+#ifdef WITH_XAVP
750
+		xavp_set_list(backup_xavps);
751
+#endif
740 752
 		bind_address=backup_si;
741 753
 	}
742 754
 }
... ...
@@ -1857,6 +1869,9 @@ int reply_received( struct sip_msg  *p_msg )
1857 1869
 	avp_list_t* backup_user_from, *backup_user_to;
1858 1870
 	avp_list_t* backup_domain_from, *backup_domain_to;
1859 1871
 	avp_list_t* backup_uri_from, *backup_uri_to;
1872
+#ifdef WITH_XAVP
1873
+	sr_xavp_t **backup_xavps;
1874
+#endif
1860 1875
 	int replies_locked;
1861 1876
 #ifdef USE_DNS_FAILOVER
1862 1877
 	int branch_ret;
... ...
@@ -2006,6 +2021,9 @@ int reply_received( struct sip_msg  *p_msg )
2006 2021
 		backup_user_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to );
2007 2022
 		backup_domain_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from );
2008 2023
 		backup_domain_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to );
2024
+#ifdef WITH_XAVP
2025
+		backup_xavps = xavp_set_list(&t->xavps_list);
2026
+#endif
2009 2027
 		setbflagsval(0, uac->branch_flags);
2010 2028
 		/* Pre- and post-script callbacks have already
2011 2029
 		 * been executed by the core. (Miklos)
... ...
@@ -2032,6 +2050,9 @@ int reply_received( struct sip_msg  *p_msg )
2032 2050
 		set_avp_list( AVP_TRACK_TO | AVP_CLASS_USER, backup_user_to );
2033 2051
 		set_avp_list( AVP_TRACK_FROM | AVP_CLASS_DOMAIN, backup_domain_from );
2034 2052
 		set_avp_list( AVP_TRACK_TO | AVP_CLASS_DOMAIN, backup_domain_to );
2053
+#ifdef WITH_XAVP
2054
+		xavp_set_list(backup_xavps);
2055
+#endif
2035 2056
 	}
2036 2057
 #ifdef USE_DST_BLACKLIST
2037 2058
 		/* add temporary to the blacklist the source of a 503 reply */
... ...
@@ -409,6 +409,9 @@ static inline int t_uac_prepare(uac_req_t *uac_r,
409 409
 	/* better reset avp list now - anyhow, it's useless from
410 410
 	 * this point (bogdan) */
411 411
 	reset_avps();
412
+#ifdef WITH_XAVP
413
+	xavp_reset_list();
414
+#endif
412 415
 
413 416
 	new_cell->method.s = buf;
414 417
 	new_cell->method.len = uac_r->method->len;
... ...
@@ -36,7 +36,9 @@
36 36
 #include "pv_time.h"
37 37
 #include "pv_trans.h"
38 38
 #include "pv_select.h"
39
-
39
+#ifdef WITH_XAVP
40
+#include "pv_xavp.h"
41
+#endif
40 42
 
41 43
 MODULE_VERSION
42 44
 
... ...
@@ -70,6 +72,11 @@ static pv_export_t mod_pvs[] = {
70 72
 		pv_parse_select_name, 0, 0, 0 },
71 73
 	{{"snd", (sizeof("snd")-1)}, PVT_OTHER, pv_get_snd, 0,
72 74
 		pv_parse_snd_name, 0, 0, 0},
75
+#ifdef WITH_XAVP
76
+	{ {"xavp", sizeof("xavp")-1}, /* xavp */
77
+		PVT_OTHER, pv_get_xavp, pv_set_xavp,
78
+		pv_parse_xavp_name, 0, 0, 0 },
79
+#endif
73 80
 
74 81
 	{{"avp", (sizeof("avp")-1)}, PVT_AVP, pv_get_avp, pv_set_avp,
75 82
 		pv_parse_avp_name, pv_parse_index, 0, 0},
... ...
@@ -397,6 +404,10 @@ static cmd_export_t cmds[]={
397 404
 		ANY_ROUTE },
398 405
 	{"pv_unset",  (cmd_function)pv_unset,  1, fixup_pvar_null, 0, 
399 406
 		ANY_ROUTE },
407
+#ifdef WITH_XAVP
408
+	{"pv_xavp_print",  (cmd_function)pv_xavp_print,  0, 0, 0, 
409
+		ANY_ROUTE },
410
+#endif
400 411
 	{0,0,0,0,0,0}
401 412
 };
402 413
 
403 414
new file mode 100644
... ...
@@ -0,0 +1,518 @@
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
+#ifdef WITH_XAVP
20
+
21
+#include <stdio.h>
22
+
23
+#include "../../dprint.h"
24
+#include "../../xavp.h"
25
+
26
+#include "pv_xavp.h"
27
+
28
+int pv_xavp_get_value(struct sip_msg *msg, pv_param_t *param,
29
+		pv_value_t *res, sr_xavp_t *avp)
30
+{
31
+	static char _pv_xavp_buf[128];
32
+	str s;
33
+
34
+	switch(avp->val.type) {
35
+		case SR_XTYPE_NULL:
36
+			return pv_get_null(msg, param, res);
37
+		break;
38
+		case SR_XTYPE_INT:
39
+			return pv_get_sintval(msg, param, res, avp->val.v.i);
40
+		break;
41
+		case SR_XTYPE_STR:
42
+			return pv_get_strval(msg, param, res, &avp->val.v.s);
43
+		break;
44
+		case SR_XTYPE_TIME:
45
+			if(snprintf(_pv_xavp_buf, 128, "%lu", avp->val.v.t)<0)
46
+				return pv_get_null(msg, param, res);
47
+		break;
48
+		case SR_XTYPE_LONG:
49
+			if(snprintf(_pv_xavp_buf, 128, "%ld", avp->val.v.l)<0)
50
+				return pv_get_null(msg, param, res);
51
+		break;
52
+		case SR_XTYPE_LLONG:
53
+			if(snprintf(_pv_xavp_buf, 128, "%lld", avp->val.v.ll)<0)
54
+				return pv_get_null(msg, param, res);
55
+		break;
56
+		case SR_XTYPE_XAVP:
57
+			if(snprintf(_pv_xavp_buf, 128, "<<xavp:%p>>", avp->val.v.xavp)<0)
58
+				return pv_get_null(msg, param, res);
59
+		break;
60
+		case SR_XTYPE_DATA:
61
+			if(snprintf(_pv_xavp_buf, 128, "<<data:%p>>", avp->val.v.data)<0)
62
+				return pv_get_null(msg, param, res);
63
+		break;
64
+		default:
65
+			return pv_get_null(msg, param, res);
66
+	}
67
+	s.s = _pv_xavp_buf;
68
+	s.len = strlen(_pv_xavp_buf);
69
+	return pv_get_strval(msg, param, res, &s);
70
+}
71
+
72
+
73
+int pv_get_xavp(struct sip_msg *msg, pv_param_t *param,
74
+		pv_value_t *res)
75
+{
76
+	pv_xavp_name_t *xname=NULL;
77
+	sr_xavp_t *avp=NULL;
78
+	int idxf = 0;
79
+	int idx = 0;
80
+	int count;
81
+
82
+	if(param==NULL)
83
+	{
84
+		LM_ERR("bad parameters\n");
85
+		return -1;
86
+	}
87
+	xname = (pv_xavp_name_t*)param->pvn.u.dname;
88
+
89
+	if(xname->index.type==PVT_EXTRA)
90
+	{
91
+		/* get the index */
92
+		if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0)
93
+		{
94
+			LM_ERR("invalid index\n");
95
+			return -1;
96
+		}
97
+	}
98
+	/* fix the index */
99
+	if(idx<0)
100
+	{
101
+		count = xavp_count(&xname->name, NULL);
102
+		idx = count + idx + 1;
103
+	}
104
+	avp = xavp_get_by_index(&xname->name, idx, NULL);
105
+	if(avp==NULL)
106
+		return pv_get_null(msg, param, res);
107
+	if(xname->next==NULL)
108
+		return pv_xavp_get_value(msg, param, res, avp);
109
+
110
+	if(xname->next->index.type==PVT_EXTRA)
111
+	{
112
+		/* get the index */
113
+		if(pv_get_spec_index(msg, &xname->next->index.pvp, &idx, &idxf)!=0)
114
+		{
115
+			LM_ERR("invalid index\n");
116
+			return -1;
117
+		}
118
+	}
119
+	/* fix the index */
120
+	if(idx<0)
121
+	{
122
+		count = xavp_count(&xname->next->name, &avp->val.v.xavp);
123
+		idx = count + idx + 1;
124
+	}
125
+	avp = xavp_get_by_index(&xname->next->name, idx, &avp->val.v.xavp);
126
+	if(avp==NULL)
127
+		return pv_get_null(msg, param, res);
128
+	return pv_xavp_get_value(msg, param, res, avp);
129
+}
130
+
131
+/**
132
+ * $xavp(name1[idx1]=>name2[idx2])
133
+ */
134
+int pv_set_xavp(struct sip_msg* msg, pv_param_t *param,
135
+		int op, pv_value_t *val)
136
+{
137
+	pv_xavp_name_t *xname=NULL;
138
+	sr_xavp_t *avp=NULL;
139
+	sr_xavp_t *list=NULL;
140
+	sr_xval_t xval;
141
+	int idxf = 0;
142
+	int idx = 0;
143
+	int idxf1 = 0;
144
+	int idx1 = 0;
145
+	int count;
146
+
147
+	if(param==NULL)
148
+	{
149
+		LM_ERR("bad parameters\n");
150
+		return -1;
151
+	}
152
+	xname = (pv_xavp_name_t*)param->pvn.u.dname;
153
+
154
+	if(xname->index.type==PVT_EXTRA)
155
+	{
156
+		/* get the index */
157
+		if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0)
158
+		{
159
+			LM_ERR("invalid index\n");
160
+			return -1;
161
+		}
162
+	}
163
+
164
+	if((val==NULL) || (val->flags&PV_VAL_NULL))
165
+	{
166
+		if(xname->next==NULL)
167
+		{
168
+			if(xname->index.type==PVT_EXTRA) {
169
+				if(idxf==PV_IDX_ALL) {
170
+					xavp_rm_by_name(&xname->name, 1, NULL);
171
+					return 0;
172
+				}
173
+			}
174
+			if(idx==0) {
175
+				xavp_rm_by_name(&xname->name, 0, NULL);
176
+				return 0;
177
+			}
178
+			/* fix the index */
179
+			if(idx<0)
180
+			{
181
+				count = xavp_count(&xname->name, NULL);
182
+				idx = count + idx + 1;
183
+			}
184
+			xavp_rm_by_index(&xname->name, idx, NULL);
185
+			return 0;
186
+		}
187
+		
188
+		if(xname->next->index.type==PVT_EXTRA)
189
+		{
190
+			/* get the index */
191
+			if(pv_get_spec_index(msg,&xname->next->index.pvp,&idx1,&idxf1)!=0)
192
+			{
193
+				LM_ERR("invalid index!\n");
194
+				return -1;
195
+			}
196
+		}
197
+
198
+		if(idxf==PV_IDX_ALL) {
199
+			/* iterate */
200
+			avp = xavp_get(&xname->name, NULL);
201
+			while(avp) {
202
+				if(avp->val.type==SR_XTYPE_XAVP) {
203
+					if(xname->next->index.type==PVT_EXTRA) {
204
+						if(idxf1==PV_IDX_ALL) {
205
+							xavp_rm_by_name(&xname->next->name, 1,
206
+									&avp->val.v.xavp);
207
+						} else {
208
+							/* fix the index */
209
+							idx = idx1;
210
+							if(idx<0)
211
+							{
212
+								count = xavp_count(&xname->next->name,
213
+										&avp->val.v.xavp);
214
+								idx = count + idx1 + 1;
215
+							}
216
+							xavp_rm_by_index(&xname->next->name, idx,
217
+									&avp->val.v.xavp);
218
+						}
219
+					} else {
220
+						xavp_rm_by_name(&xname->next->name, 0,
221
+								&avp->val.v.xavp);
222
+					}
223
+				}
224
+				avp = xavp_get_next(avp);
225
+			}
226
+			return 0;
227
+		}
228
+
229
+		if(idx==0) {
230
+			avp = xavp_get(&xname->name, NULL);
231
+		} else {
232
+			/* fix the index */
233
+			if(idx<0)
234
+			{
235
+				count = xavp_count(&xname->name, NULL);
236
+				idx = count + idx + 1;
237
+			}
238
+			avp = xavp_get_by_index(&xname->name, idx, NULL);
239
+		}
240
+		if(avp) {
241
+			if(avp->val.type==SR_XTYPE_XAVP) {
242
+				if(xname->next->index.type==PVT_EXTRA) {
243
+					if(idxf1==PV_IDX_ALL) {
244
+						xavp_rm_by_name(&xname->next->name, 1,
245
+								&avp->val.v.xavp);
246
+					} else {
247
+						/* fix the index */
248
+						idx = idx1;
249
+						if(idx<0)
250
+						{
251
+							count = xavp_count(&xname->next->name,
252
+									&avp->val.v.xavp);
253
+							idx = count + idx1 + 1;
254
+						}
255
+						xavp_rm_by_index(&xname->next->name, idx,
256
+								&avp->val.v.xavp);
257
+					}
258
+				} else {
259
+					xavp_rm_by_name(&xname->next->name, 0,
260
+							&avp->val.v.xavp);
261
+				}
262
+			}
263
+		}
264
+		return 0;
265
+	} /* NULL assignment */
266
+
267
+	/* build xavp value */
268
+	memset(&xval, 0, sizeof(sr_xval_t));
269
+
270
+	if(val->flags&PV_TYPE_INT)
271
+	{
272
+		xval.type = SR_XTYPE_INT;
273
+		xval.v.i = val->ri;
274
+	} else {
275
+		xval.type = SR_XTYPE_STR;
276
+		xval.v.s = val->rs;
277
+	}
278
+
279
+	/* where to add */
280
+	if(xname->next==NULL)
281
+	{
282
+		/* xavp with single value */
283
+		if(xname->index.type==PVT_EXTRA) {
284
+			if(idxf==PV_IDX_ALL) {
285
+				/* ignore: should iterate and set same value to all xavps
286
+				 * with same name?!?! */
287
+				return -1;
288
+			}
289
+			/* fix the index */
290
+			if(idx<0)
291
+			{
292
+				count = xavp_count(&xname->name, NULL);
293
+				idx = count + idx + 1;
294
+			}
295
+			/* set the value */
296
+			if(xavp_set_value(&xname->name, idx, &xval, NULL)==NULL)
297
+				return -1;
298
+			return 0;
299
+		}
300
+		/* add new value */
301
+		if(xavp_add_value(&xname->name, &xval, NULL)==NULL)
302
+			return -1;
303
+		return 0;
304
+	}
305
+		
306
+	/* xavp with xavp list value */
307
+	if(xname->next->index.type==PVT_EXTRA)
308
+	{
309
+		/* get the index */
310
+		if(pv_get_spec_index(msg,&xname->next->index.pvp,&idx1,&idxf1)!=0)
311
+		{
312
+			LM_ERR("invalid index!\n");
313
+			return -1;
314
+		}
315
+	}
316
+
317
+	if(xname->index.type==PVT_EXTRA)
318
+	{
319
+		/* set the value */
320
+		if(idxf==PV_IDX_ALL) {
321
+			/* ignore: should iterate and set same value to all xavps
322
+			 * with same name?!?! */
323
+			return 0;
324
+		}
325
+
326
+		if(idx==0) {
327
+			avp = xavp_get(&xname->name, NULL);
328
+		} else {
329
+			/* fix the index */
330
+			if(idx<0)
331
+			{
332
+				count = xavp_count(&xname->name, NULL);
333
+				idx = count + idx + 1;
334
+			}
335
+			avp = xavp_get_by_index(&xname->name, idx, NULL);
336
+		}
337
+		if(avp==NULL)
338
+			return 0;
339
+
340
+		if(avp->val.type!=SR_XTYPE_XAVP)
341
+			return -1;
342
+			
343
+		if(xname->next->index.type==PVT_EXTRA) {
344
+			if(idxf1==PV_IDX_ALL) {
345
+				/* ignore: should iterate and set same value to all xavps
346
+				 * with same name?!?! */
347
+				return 0;
348
+			}
349
+			/* fix the index */
350
+			idx = idx1;
351
+			if(idx<0)
352
+			{
353
+				count = xavp_count(&xname->next->name,
354
+						&avp->val.v.xavp);
355
+				idx = count + idx1 + 1;
356
+			}
357
+			/* set value */
358
+			xavp_set_value(&xname->next->name, idx, &xval, &avp->val.v.xavp);
359
+			return 0;
360
+		}
361
+		/* add new value in sublist */
362
+		if(xavp_add_value(&xname->next->name, &xval, &avp->val.v.xavp)==NULL)
363
+			return -1;
364
+		return 0;
365
+	}
366
+	/* add new xavp with xavp list */
367
+	if(xavp_add_value(&xname->next->name, &xval, &list)==NULL)
368
+		return -1;
369
+	
370
+	/* build xavp value */
371
+	memset(&xval, 0, sizeof(sr_xval_t));
372
+	xval.type = SR_XTYPE_XAVP;
373
+	xval.v.xavp = list;
374
+	xavp_add_value(&xname->name, &xval, NULL);
375
+
376
+	return 0;
377
+}
378
+
379
+char* pv_xavp_fill_ni(str *in, pv_xavp_name_t *xname)
380
+{
381
+	char *p;
382
+	str idx;
383
+	int n;
384
+
385
+	if(in->s==NULL || in->len<=0 || xname==NULL)
386
+		return NULL;
387
+	p = in->s;
388
+
389
+	/* eat ws */
390
+	while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
391
+		p++;
392
+	if(p>in->s+in->len || *p=='\0')
393
+		goto error;
394
+	xname->name.s = p;
395
+	while(p < in->s + in->len)
396
+	{
397
+		if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r' || *p=='[')
398
+			break;
399
+		p++;
400
+	}
401
+	xname->name.len = p - xname->name.s;
402
+	if(p>in->s+in->len || *p=='\0')
403
+		return p;
404
+	/* eat ws */
405
+	while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
406
+		p++;
407
+	if(p>in->s+in->len || *p=='\0')
408
+		return p;
409
+
410
+	if(*p!='[')
411
+		return p;
412
+	/* there is index */
413
+	p++;
414
+	idx.s = p;
415
+	n = 0;
416
+	while(p<in->s+in->len && *p!='\0')
417
+	{
418
+		if(*p==']')
419
+		{
420
+			if(n==0)
421
+				break;
422
+			n--;
423
+		}
424
+		if(*p == '[')
425
+			n++;
426
+		p++;
427
+	}
428
+	if(p>in->s+in->len || *p=='\0')
429
+		goto error;
430
+
431
+	if(p==idx.s)
432
+	{
433
+		LM_ERR("xavp [\"%.*s\"] does not get empty index param\n",
434
+				in->len, in->s);
435
+		goto error;
436
+	}
437
+	idx.len = p - idx.s;
438
+	if(pv_parse_index(&xname->index, &idx)!=0)
439
+	{
440
+		LM_ERR("idx \"%.*s\" has an invalid index param [%.*s]\n",
441
+					in->len, in->s, idx.len, idx.s);
442
+		goto error;
443
+	}
444
+	xname->index.type = PVT_EXTRA;
445
+	p++;
446
+	return p;
447
+error:
448
+	return NULL;
449
+}
450
+
451
+void pv_xavp_name_destroy(pv_xavp_name_t *xname)
452
+{
453
+	return;
454
+}
455
+
456
+int pv_parse_xavp_name(pv_spec_p sp, str *in)
457
+{
458
+	pv_xavp_name_t *xname=NULL;
459
+	char *p;
460
+	str s;
461
+
462
+	if(in->s==NULL || in->len<=0)
463
+		return -1;
464
+
465
+	xname = (pv_xavp_name_t*)pkg_malloc(sizeof(pv_xavp_name_t));
466
+	if(xname==NULL)
467
+		return -1;
468
+
469
+	memset(xname, 0, sizeof(pv_xavp_name_t));
470
+
471
+	s = *in;
472
+
473
+	p = pv_xavp_fill_ni(&s, xname);
474
+	if(p==NULL)
475
+		goto error;
476
+
477
+	if(*p!='=')
478
+		goto done;
479
+	p++;
480
+	if(*p!='>')
481
+		goto error;
482
+	p++;
483
+
484
+	s.len = in->len - (int)(p - in->s);
485
+	s.s = p;
486
+	LM_DBG("xavp sublist [%.*s] - key [%.*s]\n", xname->name.len,
487
+			xname->name.s, s.len, s.s);
488
+
489
+	xname->next = (pv_xavp_name_t*)pkg_malloc(sizeof(pv_xavp_name_t));
490
+	if(xname->next==NULL)
491
+		goto error;
492
+
493
+	memset(xname->next, 0, sizeof(pv_xavp_name_t));
494
+
495
+	p = pv_xavp_fill_ni(&s, xname->next);
496
+	if(p==NULL)
497
+		goto error;
498
+
499
+done:
500
+	sp->pvp.pvn.u.dname = (void*)xname;
501
+	sp->pvp.pvn.type = PV_NAME_PVAR;
502
+	return 0;
503
+
504
+error:
505
+	if(xname!=NULL) {
506
+		pv_xavp_name_destroy(xname);
507
+		pkg_free(xname);
508
+	}
509
+	return -1;
510
+}
511
+
512
+int pv_xavp_print(struct sip_msg* msg, char* s1, char *s2)
513
+{
514
+	xavp_print_list(NULL);
515
+	return 1;
516
+}
517
+
518
+#endif
0 519
new file mode 100644
... ...
@@ -0,0 +1,41 @@
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
+#ifndef _PV_XAVP_H_
20
+#define _PV_XAVP_H_
21
+
22
+#ifdef WITH_XAVP
23
+
24
+#include "../../pvar.h"
25
+
26
+typedef struct _pv_xavp_name {
27
+	str name;
28
+	pv_spec_t index;
29
+	struct _pv_xavp_name *next;
30
+} pv_xavp_name_t;
31
+
32
+int pv_get_xavp(struct sip_msg *msg, pv_param_t *param,
33
+		pv_value_t *res);
34
+int pv_set_xavp(struct sip_msg* msg, pv_param_t *param,
35
+		int op, pv_value_t *val);
36
+int pv_parse_xavp_name(pv_spec_p sp, str *in);
37
+
38
+int pv_xavp_print(struct sip_msg* msg, char* s1, char *s2);
39
+
40
+#endif
41
+#endif
... ...
@@ -66,6 +66,9 @@
66 66
 #include "nonsip_hooks.h"
67 67
 #include "dset.h"
68 68
 #include "usr_avp.h"
69
+#ifdef WITH_XAVP
70
+#include "xavp.h"
71
+#endif
69 72
 #include "select_buf.h"
70 73
 
71 74
 #include "tcp_server.h" /* for tcpconn_add_alias */
... ...
@@ -279,6 +282,9 @@ end:
279 282
 #endif
280 283
 	/* free possible loaded avps -bogdan */
281 284
 	reset_avps();
285
+#ifdef WITH_XAVP
286
+	xavp_reset_list();
287
+#endif
282 288
 	DBG("receive_msg: cleaning up\n");
283 289
 	free_sip_msg(msg);
284 290
 	pkg_free(msg);
... ...
@@ -291,6 +297,9 @@ error_rpl:
291 297
 	/* execute post reply-script callbacks */
292 298
 	exec_post_script_cb(msg, ONREPLY_CB_TYPE);
293 299
 	reset_avps();
300
+#ifdef WITH_XAVP
301
+	xavp_reset_list();
302
+#endif
294 303
 	goto error02;
295 304
 #endif /* NO_ONREPLY_ROUTE_ERROR */
296 305
 error_req:
... ...
@@ -300,6 +309,9 @@ error_req:
300 309
 error03:
301 310
 	/* free possible loaded avps -bogdan */
302 311
 	reset_avps();
312
+#ifdef WITH_XAVP
313
+	xavp_reset_list();
314
+#endif
303 315
 error02:
304 316
 	free_sip_msg(msg);
305 317
 	pkg_free(msg);
306 318
new file mode 100644
... ...
@@ -0,0 +1,508 @@
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
+void xavp_shm_free(void *p)
41
+{
42
+	shm_free(p);
43
+}
44
+
45
+void xavp_shm_free_unsafe(void *p)
46
+{
47
+	shm_free_unsafe(p);
48
+}
49
+
50
+
51
+void xavp_free(sr_xavp_t *xa)
52
+{
53
+	if(xa->val.type == SR_XTYPE_DATA) {
54
+		if(xa->val.v.data!=NULL && xa->val.v.data->pfree!=NULL) {
55
+			xa->val.v.data->pfree(xa->val.v.data->p, xavp_shm_free);
56
+			shm_free(xa->val.v.data);
57
+		}
58
+	} else if(xa->val.type == SR_XTYPE_XAVP) {
59
+		xavp_destroy_list(&xa->val.v.xavp);
60
+	}
61
+	shm_free(xa);
62
+}
63
+
64
+void xavp_free_unsafe(sr_xavp_t *xa)
65
+{
66
+	if(xa->val.type == SR_XTYPE_DATA) {
67
+		if(xa->val.v.data!=NULL && xa->val.v.data->pfree!=NULL) {
68
+			xa->val.v.data->pfree(xa->val.v.data->p, xavp_shm_free_unsafe);
69
+			shm_free_unsafe(xa->val.v.data);
70
+		}
71
+	} else if(xa->val.type == SR_XTYPE_XAVP) {
72
+		xavp_destroy_list_unsafe(&xa->val.v.xavp);
73
+	}
74
+	shm_free_unsafe(xa);
75
+}
76
+
77
+sr_xavp_t *xavp_add_value(str *name, sr_xval_t *val, sr_xavp_t **list)
78
+{
79
+	sr_xavp_t *avp=0;
80
+	int size;
81
+
82
+	if(name==NULL || name->s==NULL || val==NULL)
83
+		return NULL;
84
+
85
+	size = sizeof(sr_xavp_t) + name->len + 1;
86
+	if(val->type == SR_XTYPE_STR)
87
+		size += val->v.s.len + 1;
88
+	avp = (sr_xavp_t*)shm_malloc(size);
89
+	if(avp==NULL)
90
+		return NULL;
91
+	memset(avp, 0, size);
92
+	avp->id = get_hash1_raw(name->s, name->len);
93
+	avp->name.s = (char*)avp + sizeof(sr_xavp_t);
94
+	memcpy(avp->name.s, name->s, name->len);
95
+	avp->name.s[name->len] = '\0';
96
+	avp->name.len = name->len;
97
+	memcpy(&avp->val, val, sizeof(sr_xval_t));
98
+	if(val->type == SR_XTYPE_STR)
99
+	{
100
+		avp->val.v.s.s = avp->name.s + avp->name.len + 1;
101
+		memcpy(avp->val.v.s.s, val->v.s.s, val->v.s.len);
102
+		avp->val.v.s.s[val->v.s.len] = '\0';
103
+		avp->val.v.s.len = val->v.s.len;
104
+	}
105
+	if(list) {
106
+		avp->next = *list;
107
+		*list = avp;
108
+	} else {
109
+		avp->next = *_xavp_list_crt;
110
+		*_xavp_list_crt = avp;
111
+	}
112
+
113
+	return avp;
114
+}
115
+
116
+sr_xavp_t *xavp_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list)
117
+{
118
+	sr_xavp_t *avp=0;
119
+	sr_xavp_t *prv=0;
120
+	sr_xavp_t *tmp=0;
121
+	unsigned int id;
122
+	int size;
123
+	int n=0;
124
+
125
+	if(name==NULL || name->s==NULL || val==NULL)
126
+		return NULL;
127
+
128
+	id = get_hash1_raw(name->s, name->len);
129
+	if(list)
130
+		avp = *list;
131
+	else
132
+		avp=*_xavp_list_crt;
133
+	while(avp)
134
+	{
135
+		if(avp->id==id && avp->name.len==name->len
136
+				&& strncmp(avp->name.s, name->s, name->len)==0)
137
+		{
138
+			if(idx==n)
139
+				return avp;
140
+			n++;
141
+		}
142
+		prv = avp;
143
+		avp=avp->next;
144
+	}
145
+	if(avp==NULL)
146
+		return NULL;
147
+	tmp = avp;
148
+
149
+	size = sizeof(sr_xavp_t) + name->len + 1;
150
+	if(val->type == SR_XTYPE_STR)
151
+		size += val->v.s.len + 1;
152
+	avp = (sr_xavp_t*)shm_malloc(size);
153
+	if(avp==NULL)
154
+		return NULL;
155
+	memset(avp, 0, size);
156
+	avp->id = get_hash1_raw(name->s, name->len);
157
+	avp->name.s = (char*)avp + sizeof(sr_xavp_t);
158
+	memcpy(avp->name.s, name->s, name->len);
159
+	avp->name.s[name->len] = '\0';
160
+	avp->name.len = name->len;
161
+	memcpy(&avp->val, val, sizeof(sr_xval_t));
162
+	if(val->type == SR_XTYPE_STR)
163
+	{
164
+		avp->val.v.s.s = avp->name.s + avp->name.len + 1;
165
+		memcpy(avp->val.v.s.s, val->v.s.s, val->v.s.len);
166
+		avp->val.v.s.s[val->v.s.len] = '\0';
167
+		avp->val.v.s.len = val->v.s.len;
168
+	}
169
+	if(prv)
170
+	{
171
+			avp->next = prv->next;
172
+			prv->next = avp;
173
+	} else {
174
+		if(list) {
175
+			avp->next = *list;
176
+			*list = avp;
177
+		} else {
178
+			avp->next = *_xavp_list_crt;
179
+			*_xavp_list_crt = avp;
180
+		}
181
+	}
182
+	xavp_free(tmp);
183
+
184
+	return avp;
185
+}
186
+
187
+sr_xavp_t *xavp_get(str *name, sr_xavp_t *start)
188
+{
189
+	sr_xavp_t *avp=0;
190
+	unsigned int id;
191
+
192
+	if(name==NULL || name->s==NULL)
193
+		return NULL;
194
+	id = get_hash1_raw(name->s, name->len);
195
+	
196
+	if(start)
197
+		avp = start;
198
+	else
199
+		avp=*_xavp_list_crt;
200
+	while(avp)
201
+	{
202
+		if(avp->id==id && avp->name.len==name->len
203
+				&& strncmp(avp->name.s, name->s, name->len)==0)
204
+			return avp;
205
+		avp=avp->next;
206
+	}
207
+
208
+	return NULL;
209
+}
210
+
211
+sr_xavp_t *xavp_get_by_index(str *name, int idx, sr_xavp_t **start)
212
+{
213
+	sr_xavp_t *avp=0;
214
+	unsigned int id;
215
+	int n = 0;
216
+
217
+	if(name==NULL || name->s==NULL)
218
+		return NULL;
219
+	id = get_hash1_raw(name->s, name->len);
220
+	
221
+	if(start)
222
+		avp = *start;
223
+	else
224
+		avp=*_xavp_list_crt;
225
+	while(avp)
226
+	{
227
+		if(avp->id==id && avp->name.len==name->len
228
+				&& strncmp(avp->name.s, name->s, name->len)==0)
229
+		{
230
+			if(idx==n)
231
+				return avp;
232
+			n++;
233
+		}
234
+		avp=avp->next;
235
+	}
236
+
237
+	return NULL;
238
+}
239
+
240
+
241
+sr_xavp_t *xavp_get_next(sr_xavp_t *start)
242
+{
243
+	sr_xavp_t *avp=0;
244
+
245
+	if(start==NULL)
246
+		return NULL;
247
+	
248
+	avp = start->next;
249
+	while(avp)
250
+	{
251
+		if(avp->id==start->id && avp->name.len==start->name.len
252
+				&& strncmp(avp->name.s, start->name.s, start->name.len)==0)
253
+			return avp;
254
+		avp=avp->next;
255
+	}
256
+
257
+	return NULL;
258
+}
259
+
260
+
261
+int xavp_rm(sr_xavp_t *xa, sr_xavp_t **head)
262
+{
263
+	sr_xavp_t *avp=0;
264
+	sr_xavp_t *prv=0;
265
+
266
+	if(head!=NULL)
267
+		avp = *head;
268
+	else
269
+		avp=*_xavp_list_crt;
270
+
271
+	while(avp)
272
+	{
273
+		if(avp==xa)
274
+		{
275
+			if(prv)
276
+				prv->next=avp->next;
277
+			else
278
+				if(head!=NULL)
279
+					*head = avp->next;
280
+				else
281
+					*_xavp_list_crt = avp->next;
282
+			xavp_free(avp);
283
+			return 1;
284
+		}
285
+		prv=avp; avp=avp->next;
286
+	}
287
+	return 0;
288
+}
289
+
290
+
291
+int xavp_rm_by_name(str *name, int all, sr_xavp_t **head)
292
+{
293
+	sr_xavp_t *avp=0;
294
+	sr_xavp_t *foo=0;
295
+	sr_xavp_t *prv=0;
296
+	unsigned int id = 0;
297
+	int n=0;
298
+
299
+	if(name==NULL || name->s==NULL)
300
+		return 0;
301
+
302
+	id = get_hash1_raw(name->s, name->len);
303
+	if(head!=NULL)
304
+		avp = *head;
305
+	else
306
+		avp=*_xavp_list_crt;
307
+	while(avp)
308
+	{
309
+		foo = avp;
310
+		avp=avp->next;
311
+		if(foo->id==id && foo->name.len==name->len
312
+				&& strncmp(foo->name.s, name->s, name->len)==0)
313
+		{
314
+			if(prv!=NULL)
315
+				prv->next=foo->next;
316
+			else
317
+				if(head!=NULL)
318
+					*head = foo->next;
319
+				else
320
+					*_xavp_list_crt = foo->next;
321
+			xavp_free(foo);
322
+			n++;
323
+			if(all==0)
324
+				return n;
325
+		} else {
326
+			prv = foo;
327
+		}
328
+	}
329
+	return n;
330
+}
331
+
332
+int xavp_rm_by_index(str *name, int idx, sr_xavp_t **head)
333
+{
334
+	sr_xavp_t *avp=0;
335
+	sr_xavp_t *foo=0;
336
+	sr_xavp_t *prv=0;
337
+	unsigned int id = 0;
338
+	int n=0;
339
+
340
+	if(name==NULL || name->s==NULL)
341
+		return 0;
342
+	if(idx<0)
343
+		return 0;
344
+
345
+	id = get_hash1_raw(name->s, name->len);
346
+	if(head!=NULL)
347
+		avp = *head;
348
+	else
349
+		avp=*_xavp_list_crt;
350
+	while(avp)
351
+	{
352
+		foo = avp;
353
+		avp=avp->next;
354
+		if(foo->id==id && foo->name.len==name->len
355
+				&& strncmp(foo->name.s, name->s, name->len)==0)
356
+		{
357
+			if(idx==n)
358
+			{
359
+				if(prv!=NULL)
360
+					prv->next=foo->next;
361
+				else
362
+					if(head!=NULL)
363
+						*head = foo->next;
364
+					else
365
+						*_xavp_list_crt = foo->next;
366
+				xavp_free(foo);
367
+				return 1;
368
+			}
369
+			n++;
370
+		}
371
+		prv = foo;
372
+	}
373
+	return 0;
374
+}
375
+
376
+
377
+int xavp_count(str *name, sr_xavp_t **start)
378
+{
379
+	sr_xavp_t *avp=0;
380
+	unsigned int id;
381
+	int n = 0;
382
+
383
+	if(name==NULL || name->s==NULL)
384
+		return -1;
385
+	id = get_hash1_raw(name->s, name->len);
386
+	
387
+	if(start)
388
+		avp = *start;
389
+	else
390
+		avp=*_xavp_list_crt;
391
+	while(avp)
392
+	{
393
+		if(avp->id==id && avp->name.len==name->len
394
+				&& strncmp(avp->name.s, name->s, name->len)==0)
395
+		{
396
+			n++;
397
+		}
398
+		avp=avp->next;
399
+	}
400
+
401
+	return n;
402
+}
403
+
404
+void xavp_destroy_list_unsafe(sr_xavp_t **head)
405
+{
406
+	sr_xavp_t *avp, *foo;
407
+
408
+	avp = *head;
409
+	while(avp)
410
+	{
411
+		foo = avp;
412
+		avp = avp->next;
413
+		xavp_free_unsafe(foo);
414
+	}
415
+	*head = 0;
416
+}
417
+
418
+
419
+void xavp_destroy_list(sr_xavp_t **head)
420
+{
421
+	sr_xavp_t *avp, *foo;
422
+
423
+	LM_DBG("destroying xavp list %p\n", *head);
424
+	avp = *head;
425
+	while(avp)
426
+	{
427
+		foo = avp;
428
+		avp = avp->next;
429
+		xavp_free(foo);
430
+	}
431
+	*head = 0;
432
+}
433
+
434
+
435
+void xavp_reset_list(void)
436
+{
437
+	assert(_xavp_list_crt!=0 );
438
+	
439
+	if (_xavp_list_crt!=&_xavp_list_head)
440
+		_xavp_list_crt=&_xavp_list_head;
441
+	xavp_destroy_list(_xavp_list_crt);
442
+}
443
+
444
+
445
+sr_xavp_t **xavp_set_list(sr_xavp_t **head)
446
+{
447
+	sr_xavp_t **avp;
448
+	
449
+	assert(_xavp_list_crt!=0);
450
+
451
+	avp = _xavp_list_crt;
452
+	_xavp_list_crt = head;
453
+	return avp;
454
+}
455
+
456
+sr_xavp_t **xavp_get_crt_list(void)
457
+{
458
+	assert(_xavp_list_crt!=0);
459
+	return _xavp_list_crt;
460
+}
461
+
462
+void xavp_print_list(sr_xavp_t **head)
463
+{
464
+	sr_xavp_t *avp=0;
465
+
466
+	if(head!=NULL)
467
+		avp = *head;
468
+	else
469
+		avp=*_xavp_list_crt;
470
+	LM_DBG("+++++ XAVP list: %p\n", avp);
471
+	while(avp)
472
+	{
473
+		LM_DBG("     *** XAVP name: %s\n", avp->name.s);
474
+		LM_DBG("     XAVP id: %u\n", avp->id);
475
+		LM_DBG("     XAVP value type: %d\n", avp->val.type);
476
+		switch(avp->val.type) {
477
+			case SR_XTYPE_NULL:
478
+				LM_DBG("     XAVP value: <null>\n");
479
+			break;
480
+			case SR_XTYPE_INT:
481
+				LM_DBG("     XAVP value: %d\n", avp->val.v.i);
482
+			break;
483
+			case SR_XTYPE_STR:
484
+				LM_DBG("     XAVP value: %s\n", avp->val.v.s.s);
485
+			break;
486
+			case SR_XTYPE_TIME:
487
+				LM_DBG("     XAVP value: %lu\n", avp->val.v.t);
488
+			break;
489
+			case SR_XTYPE_LONG:
490
+				LM_DBG("     XAVP value: %ld\n", avp->val.v.l);
491
+			break;
492
+			case SR_XTYPE_LLONG:
493
+				LM_DBG("     XAVP value: %lld\n", avp->val.v.ll);
494
+			break;
495
+			case SR_XTYPE_XAVP:
496
+				LM_DBG("     XAVP value: <xavp:%p>\n", avp->val.v.xavp);
497
+				xavp_print_list(&avp->val.v.xavp);
498
+			break;
499
+			case SR_XTYPE_DATA:
500
+				LM_DBG("     XAVP value: <data:%p>\n", avp->val.v.data);
501
+			break;
502
+		}
503
+		avp = avp->next;
504
+	}
505
+	LM_DBG("----- XAVP list\n");
506
+}
507
+
508
+#endif
0 509
new file mode 100644
... ...
@@ -0,0 +1,95 @@
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
+#ifndef _SR_XAVP_H_
26
+#define _SR_XAVP_H_
27
+
28
+#ifdef WITH_XAVP
29
+
30
+#include <time.h>
31
+#include "str.h"
32
+
33
+struct _sr_xavp;
34
+
35
+typedef enum {
36
+	SR_XTYPE_NULL=0,
37
+	SR_XTYPE_INT,
38
+	SR_XTYPE_STR,
39
+	SR_XTYPE_TIME,
40
+	SR_XTYPE_LONG,
41
+	SR_XTYPE_LLONG,
42
+	SR_XTYPE_XAVP,
43
+	SR_XTYPE_DATA
44
+} sr_xtype_t;
45
+
46
+typedef void (*sr_xavp_sfree_f)(void *d);
47
+typedef void (*sr_data_free_f)(void *d, sr_xavp_sfree_f sfree);
48
+
49
+typedef struct _sr_data {
50
+	void *p;
51
+	sr_data_free_f pfree;
52
+} sr_data_t;
53
+
54
+typedef struct _sr_xval {
55
+	sr_xtype_t type;
56
+	union {
57
+		int i;
58
+		str s;                 /* replicated */
59
+		time_t t;
60
+		long l;
61
+		long long ll;
62
+		struct _sr_xavp *xavp; /* must be given in shm */
63
+		sr_data_t *data;       /* must be given in shm */
64
+	} v;
65
+} sr_xval_t;
66
+
67
+typedef struct _sr_xavp {
68
+	unsigned int id;
69
+	str name;
70
+	sr_xval_t val;
71
+	struct _sr_xavp *next;
72
+} sr_xavp_t;
73
+
74
+int xavp_init_head(void);
75
+void avpx_free(sr_xavp_t *xa);
76
+
77
+sr_xavp_t *xavp_add_value(str *name, sr_xval_t *val, sr_xavp_t **list);
78
+sr_xavp_t *xavp_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list);
79
+sr_xavp_t *xavp_get(str *name, sr_xavp_t *start);
80
+sr_xavp_t *xavp_get_by_index(str *name, int idx, sr_xavp_t **start);
81
+sr_xavp_t *xavp_get_next(sr_xavp_t *start);
82
+int xavp_rm_by_name(str *name, int all, sr_xavp_t **head);
83
+int xavp_rm_by_index(str *name, int idx, sr_xavp_t **head);
84
+int xavp_rm(sr_xavp_t *xa, sr_xavp_t **head);
85
+int xavp_count(str *name, sr_xavp_t **start);
86
+void xavp_destroy_list_unsafe(sr_xavp_t **head);
87
+void xavp_destroy_list(sr_xavp_t **head);
88
+void xavp_reset_list(void);
89
+sr_xavp_t **xavp_set_list(sr_xavp_t **head);
90
+sr_xavp_t **xavp_get_crt_list(void);
91
+
92
+void xavp_print_list(sr_xavp_t **head);
93
+#endif
94
+
95
+#endif