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 @@
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