Browse Source

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 16 years ago
parent
commit
ef79b7beb7
2 changed files with 603 additions and 0 deletions
  1. 508 0
      xavp.c
  2. 95 0
      xavp.h

+ 508 - 0
xavp.c

@@ -0,0 +1,508 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com) 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * History:
+ * --------
+ *  2009-05-20  created by daniel
+ */
+
+
+#ifdef WITH_XAVP
+
+#include <stdio.h>
+#include <string.h>
+
+#include "mem/shm_mem.h"
+#include "dprint.h"
+#include "hashes.h"
+#include "xavp.h"
+
+/*! XAVP list head */
+static sr_xavp_t *_xavp_list_head = 0;
+/*! Pointer to XAVP current list */
+static sr_xavp_t **_xavp_list_crt = &_xavp_list_head;
+
+void xavp_shm_free(void *p)
+{
+	shm_free(p);
+}
+
+void xavp_shm_free_unsafe(void *p)
+{
+	shm_free_unsafe(p);
+}
+
+
+void xavp_free(sr_xavp_t *xa)
+{
+	if(xa->val.type == SR_XTYPE_DATA) {
+		if(xa->val.v.data!=NULL && xa->val.v.data->pfree!=NULL) {
+			xa->val.v.data->pfree(xa->val.v.data->p, xavp_shm_free);
+			shm_free(xa->val.v.data);
+		}
+	} else if(xa->val.type == SR_XTYPE_XAVP) {
+		xavp_destroy_list(&xa->val.v.xavp);
+	}
+	shm_free(xa);
+}
+
+void xavp_free_unsafe(sr_xavp_t *xa)
+{
+	if(xa->val.type == SR_XTYPE_DATA) {
+		if(xa->val.v.data!=NULL && xa->val.v.data->pfree!=NULL) {
+			xa->val.v.data->pfree(xa->val.v.data->p, xavp_shm_free_unsafe);
+			shm_free_unsafe(xa->val.v.data);
+		}
+	} else if(xa->val.type == SR_XTYPE_XAVP) {
+		xavp_destroy_list_unsafe(&xa->val.v.xavp);
+	}
+	shm_free_unsafe(xa);
+}
+
+sr_xavp_t *xavp_add_value(str *name, sr_xval_t *val, sr_xavp_t **list)
+{
+	sr_xavp_t *avp=0;
+	int size;
+
+	if(name==NULL || name->s==NULL || val==NULL)
+		return NULL;
+
+	size = sizeof(sr_xavp_t) + name->len + 1;
+	if(val->type == SR_XTYPE_STR)
+		size += val->v.s.len + 1;
+	avp = (sr_xavp_t*)shm_malloc(size);
+	if(avp==NULL)
+		return NULL;
+	memset(avp, 0, size);
+	avp->id = get_hash1_raw(name->s, name->len);
+	avp->name.s = (char*)avp + sizeof(sr_xavp_t);
+	memcpy(avp->name.s, name->s, name->len);
+	avp->name.s[name->len] = '\0';
+	avp->name.len = name->len;
+	memcpy(&avp->val, val, sizeof(sr_xval_t));
+	if(val->type == SR_XTYPE_STR)
+	{
+		avp->val.v.s.s = avp->name.s + avp->name.len + 1;
+		memcpy(avp->val.v.s.s, val->v.s.s, val->v.s.len);
+		avp->val.v.s.s[val->v.s.len] = '\0';
+		avp->val.v.s.len = val->v.s.len;
+	}
+	if(list) {
+		avp->next = *list;
+		*list = avp;
+	} else {
+		avp->next = *_xavp_list_crt;
+		*_xavp_list_crt = avp;
+	}
+
+	return avp;
+}
+
+sr_xavp_t *xavp_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list)
+{
+	sr_xavp_t *avp=0;
+	sr_xavp_t *prv=0;
+	sr_xavp_t *tmp=0;
+	unsigned int id;
+	int size;
+	int n=0;
+
+	if(name==NULL || name->s==NULL || val==NULL)
+		return NULL;
+
+	id = get_hash1_raw(name->s, name->len);
+	if(list)
+		avp = *list;
+	else
+		avp=*_xavp_list_crt;
+	while(avp)
+	{
+		if(avp->id==id && avp->name.len==name->len
+				&& strncmp(avp->name.s, name->s, name->len)==0)
+		{
+			if(idx==n)
+				return avp;
+			n++;
+		}
+		prv = avp;
+		avp=avp->next;
+	}
+	if(avp==NULL)
+		return NULL;
+	tmp = avp;
+
+	size = sizeof(sr_xavp_t) + name->len + 1;
+	if(val->type == SR_XTYPE_STR)
+		size += val->v.s.len + 1;
+	avp = (sr_xavp_t*)shm_malloc(size);
+	if(avp==NULL)
+		return NULL;
+	memset(avp, 0, size);
+	avp->id = get_hash1_raw(name->s, name->len);
+	avp->name.s = (char*)avp + sizeof(sr_xavp_t);
+	memcpy(avp->name.s, name->s, name->len);
+	avp->name.s[name->len] = '\0';
+	avp->name.len = name->len;
+	memcpy(&avp->val, val, sizeof(sr_xval_t));
+	if(val->type == SR_XTYPE_STR)
+	{
+		avp->val.v.s.s = avp->name.s + avp->name.len + 1;
+		memcpy(avp->val.v.s.s, val->v.s.s, val->v.s.len);
+		avp->val.v.s.s[val->v.s.len] = '\0';
+		avp->val.v.s.len = val->v.s.len;
+	}
+	if(prv)
+	{
+			avp->next = prv->next;
+			prv->next = avp;
+	} else {
+		if(list) {
+			avp->next = *list;
+			*list = avp;
+		} else {
+			avp->next = *_xavp_list_crt;
+			*_xavp_list_crt = avp;
+		}
+	}
+	xavp_free(tmp);
+
+	return avp;
+}
+
+sr_xavp_t *xavp_get(str *name, sr_xavp_t *start)
+{
+	sr_xavp_t *avp=0;
+	unsigned int id;
+
+	if(name==NULL || name->s==NULL)
+		return NULL;
+	id = get_hash1_raw(name->s, name->len);
+	
+	if(start)
+		avp = start;
+	else
+		avp=*_xavp_list_crt;
+	while(avp)
+	{
+		if(avp->id==id && avp->name.len==name->len
+				&& strncmp(avp->name.s, name->s, name->len)==0)
+			return avp;
+		avp=avp->next;
+	}
+
+	return NULL;
+}
+
+sr_xavp_t *xavp_get_by_index(str *name, int idx, sr_xavp_t **start)
+{
+	sr_xavp_t *avp=0;
+	unsigned int id;
+	int n = 0;
+
+	if(name==NULL || name->s==NULL)
+		return NULL;
+	id = get_hash1_raw(name->s, name->len);
+	
+	if(start)
+		avp = *start;
+	else
+		avp=*_xavp_list_crt;
+	while(avp)
+	{
+		if(avp->id==id && avp->name.len==name->len
+				&& strncmp(avp->name.s, name->s, name->len)==0)
+		{
+			if(idx==n)
+				return avp;
+			n++;
+		}
+		avp=avp->next;
+	}
+
+	return NULL;
+}
+
+
+sr_xavp_t *xavp_get_next(sr_xavp_t *start)
+{
+	sr_xavp_t *avp=0;
+
+	if(start==NULL)
+		return NULL;
+	
+	avp = start->next;
+	while(avp)
+	{
+		if(avp->id==start->id && avp->name.len==start->name.len
+				&& strncmp(avp->name.s, start->name.s, start->name.len)==0)
+			return avp;
+		avp=avp->next;
+	}
+
+	return NULL;
+}
+
+
+int xavp_rm(sr_xavp_t *xa, sr_xavp_t **head)
+{
+	sr_xavp_t *avp=0;
+	sr_xavp_t *prv=0;
+
+	if(head!=NULL)
+		avp = *head;
+	else
+		avp=*_xavp_list_crt;
+
+	while(avp)
+	{
+		if(avp==xa)
+		{
+			if(prv)
+				prv->next=avp->next;
+			else
+				if(head!=NULL)
+					*head = avp->next;
+				else
+					*_xavp_list_crt = avp->next;
+			xavp_free(avp);
+			return 1;
+		}
+		prv=avp; avp=avp->next;
+	}
+	return 0;
+}
+
+
+int xavp_rm_by_name(str *name, int all, sr_xavp_t **head)
+{
+	sr_xavp_t *avp=0;
+	sr_xavp_t *foo=0;
+	sr_xavp_t *prv=0;
+	unsigned int id = 0;
+	int n=0;
+
+	if(name==NULL || name->s==NULL)
+		return 0;
+
+	id = get_hash1_raw(name->s, name->len);
+	if(head!=NULL)
+		avp = *head;
+	else
+		avp=*_xavp_list_crt;
+	while(avp)
+	{
+		foo = avp;
+		avp=avp->next;
+		if(foo->id==id && foo->name.len==name->len
+				&& strncmp(foo->name.s, name->s, name->len)==0)
+		{
+			if(prv!=NULL)
+				prv->next=foo->next;
+			else
+				if(head!=NULL)
+					*head = foo->next;
+				else
+					*_xavp_list_crt = foo->next;
+			xavp_free(foo);
+			n++;
+			if(all==0)
+				return n;
+		} else {
+			prv = foo;
+		}
+	}
+	return n;
+}
+
+int xavp_rm_by_index(str *name, int idx, sr_xavp_t **head)
+{
+	sr_xavp_t *avp=0;
+	sr_xavp_t *foo=0;
+	sr_xavp_t *prv=0;
+	unsigned int id = 0;
+	int n=0;
+
+	if(name==NULL || name->s==NULL)
+		return 0;
+	if(idx<0)
+		return 0;
+
+	id = get_hash1_raw(name->s, name->len);
+	if(head!=NULL)
+		avp = *head;
+	else
+		avp=*_xavp_list_crt;
+	while(avp)
+	{
+		foo = avp;
+		avp=avp->next;
+		if(foo->id==id && foo->name.len==name->len
+				&& strncmp(foo->name.s, name->s, name->len)==0)
+		{
+			if(idx==n)
+			{
+				if(prv!=NULL)
+					prv->next=foo->next;
+				else
+					if(head!=NULL)
+						*head = foo->next;
+					else
+						*_xavp_list_crt = foo->next;
+				xavp_free(foo);
+				return 1;
+			}
+			n++;
+		}
+		prv = foo;
+	}
+	return 0;
+}
+
+
+int xavp_count(str *name, sr_xavp_t **start)
+{
+	sr_xavp_t *avp=0;
+	unsigned int id;
+	int n = 0;
+
+	if(name==NULL || name->s==NULL)
+		return -1;
+	id = get_hash1_raw(name->s, name->len);
+	
+	if(start)
+		avp = *start;
+	else
+		avp=*_xavp_list_crt;
+	while(avp)
+	{
+		if(avp->id==id && avp->name.len==name->len
+				&& strncmp(avp->name.s, name->s, name->len)==0)
+		{
+			n++;
+		}
+		avp=avp->next;
+	}
+
+	return n;
+}
+
+void xavp_destroy_list_unsafe(sr_xavp_t **head)
+{
+	sr_xavp_t *avp, *foo;
+
+	avp = *head;
+	while(avp)
+	{
+		foo = avp;
+		avp = avp->next;
+		xavp_free_unsafe(foo);
+	}
+	*head = 0;
+}
+
+
+void xavp_destroy_list(sr_xavp_t **head)
+{
+	sr_xavp_t *avp, *foo;
+
+	LM_DBG("destroying xavp list %p\n", *head);
+	avp = *head;
+	while(avp)
+	{
+		foo = avp;
+		avp = avp->next;
+		xavp_free(foo);
+	}
+	*head = 0;
+}
+
+
+void xavp_reset_list(void)
+{
+	assert(_xavp_list_crt!=0 );
+	
+	if (_xavp_list_crt!=&_xavp_list_head)
+		_xavp_list_crt=&_xavp_list_head;
+	xavp_destroy_list(_xavp_list_crt);
+}
+
+
+sr_xavp_t **xavp_set_list(sr_xavp_t **head)
+{
+	sr_xavp_t **avp;
+	
+	assert(_xavp_list_crt!=0);
+
+	avp = _xavp_list_crt;
+	_xavp_list_crt = head;
+	return avp;
+}
+
+sr_xavp_t **xavp_get_crt_list(void)
+{
+	assert(_xavp_list_crt!=0);
+	return _xavp_list_crt;
+}
+
+void xavp_print_list(sr_xavp_t **head)
+{
+	sr_xavp_t *avp=0;
+
+	if(head!=NULL)
+		avp = *head;
+	else
+		avp=*_xavp_list_crt;
+	LM_DBG("+++++ XAVP list: %p\n", avp);
+	while(avp)
+	{
+		LM_DBG("     *** XAVP name: %s\n", avp->name.s);
+		LM_DBG("     XAVP id: %u\n", avp->id);
+		LM_DBG("     XAVP value type: %d\n", avp->val.type);
+		switch(avp->val.type) {
+			case SR_XTYPE_NULL:
+				LM_DBG("     XAVP value: <null>\n");
+			break;
+			case SR_XTYPE_INT:
+				LM_DBG("     XAVP value: %d\n", avp->val.v.i);
+			break;
+			case SR_XTYPE_STR:
+				LM_DBG("     XAVP value: %s\n", avp->val.v.s.s);
+			break;
+			case SR_XTYPE_TIME:
+				LM_DBG("     XAVP value: %lu\n", avp->val.v.t);
+			break;
+			case SR_XTYPE_LONG:
+				LM_DBG("     XAVP value: %ld\n", avp->val.v.l);
+			break;
+			case SR_XTYPE_LLONG:
+				LM_DBG("     XAVP value: %lld\n", avp->val.v.ll);
+			break;
+			case SR_XTYPE_XAVP:
+				LM_DBG("     XAVP value: <xavp:%p>\n", avp->val.v.xavp);
+				xavp_print_list(&avp->val.v.xavp);
+			break;
+			case SR_XTYPE_DATA:
+				LM_DBG("     XAVP value: <data:%p>\n", avp->val.v.data);
+			break;
+		}
+		avp = avp->next;
+	}
+	LM_DBG("----- XAVP list\n");
+}
+
+#endif

+ 95 - 0
xavp.h

@@ -0,0 +1,95 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com) 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * History:
+ * --------
+ *  2009-05-20  created by daniel
+ */
+
+
+#ifndef _SR_XAVP_H_
+#define _SR_XAVP_H_
+
+#ifdef WITH_XAVP
+
+#include <time.h>
+#include "str.h"
+
+struct _sr_xavp;
+
+typedef enum {
+	SR_XTYPE_NULL=0,
+	SR_XTYPE_INT,
+	SR_XTYPE_STR,
+	SR_XTYPE_TIME,
+	SR_XTYPE_LONG,
+	SR_XTYPE_LLONG,
+	SR_XTYPE_XAVP,
+	SR_XTYPE_DATA
+} sr_xtype_t;
+
+typedef void (*sr_xavp_sfree_f)(void *d);
+typedef void (*sr_data_free_f)(void *d, sr_xavp_sfree_f sfree);
+
+typedef struct _sr_data {
+	void *p;
+	sr_data_free_f pfree;
+} sr_data_t;
+
+typedef struct _sr_xval {
+	sr_xtype_t type;
+	union {
+		int i;
+		str s;                 /* replicated */
+		time_t t;
+		long l;
+		long long ll;
+		struct _sr_xavp *xavp; /* must be given in shm */
+		sr_data_t *data;       /* must be given in shm */
+	} v;
+} sr_xval_t;
+
+typedef struct _sr_xavp {
+	unsigned int id;
+	str name;
+	sr_xval_t val;
+	struct _sr_xavp *next;
+} sr_xavp_t;
+
+int xavp_init_head(void);
+void avpx_free(sr_xavp_t *xa);
+
+sr_xavp_t *xavp_add_value(str *name, sr_xval_t *val, sr_xavp_t **list);
+sr_xavp_t *xavp_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list);
+sr_xavp_t *xavp_get(str *name, sr_xavp_t *start);
+sr_xavp_t *xavp_get_by_index(str *name, int idx, sr_xavp_t **start);
+sr_xavp_t *xavp_get_next(sr_xavp_t *start);
+int xavp_rm_by_name(str *name, int all, sr_xavp_t **head);
+int xavp_rm_by_index(str *name, int idx, sr_xavp_t **head);
+int xavp_rm(sr_xavp_t *xa, sr_xavp_t **head);
+int xavp_count(str *name, sr_xavp_t **start);
+void xavp_destroy_list_unsafe(sr_xavp_t **head);
+void xavp_destroy_list(sr_xavp_t **head);
+void xavp_reset_list(void);
+sr_xavp_t **xavp_set_list(sr_xavp_t **head);
+sr_xavp_t **xavp_get_crt_list(void);
+
+void xavp_print_list(sr_xavp_t **head);
+#endif
+
+#endif