Browse code

core: introducing xavp (eXtended AVP)

- design:
- one master list stored in core
- internal integer id to optimise the search in list (hash value over the string name)
- name stored as str and null terminated (can use regexp over it)
- string values stored as str and null terminated
- other types of value that can be used internally (not in config)
- long
- long long
- time
- xavp (or list of xavp)
- generic data structure
- for more see: http://sip-router.org/wiki/devel/xavp
- NOTE: this is not a replacement for existing AVPs, but an add-on, a new pseudo-variable class

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