2
0
Эх сурвалжийг харах

pv: export new PV class $xavp(name)

- allow management of XAVP from config file
Daniel-Constantin Mierla 16 жил өмнө
parent
commit
d68a8b4db0

+ 518 - 0
modules_k/pv/pv_xavp.c

@@ -0,0 +1,518 @@
+/**
+ * $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.
+ */
+
+#ifdef WITH_XAVP
+
+#include <stdio.h>
+
+#include "../../dprint.h"
+#include "../../xavp.h"
+
+#include "pv_xavp.h"
+
+int pv_xavp_get_value(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res, sr_xavp_t *avp)
+{
+	static char _pv_xavp_buf[128];
+	str s;
+
+	switch(avp->val.type) {
+		case SR_XTYPE_NULL:
+			return pv_get_null(msg, param, res);
+		break;
+		case SR_XTYPE_INT:
+			return pv_get_sintval(msg, param, res, avp->val.v.i);
+		break;
+		case SR_XTYPE_STR:
+			return pv_get_strval(msg, param, res, &avp->val.v.s);
+		break;
+		case SR_XTYPE_TIME:
+			if(snprintf(_pv_xavp_buf, 128, "%lu", avp->val.v.t)<0)
+				return pv_get_null(msg, param, res);
+		break;
+		case SR_XTYPE_LONG:
+			if(snprintf(_pv_xavp_buf, 128, "%ld", avp->val.v.l)<0)
+				return pv_get_null(msg, param, res);
+		break;
+		case SR_XTYPE_LLONG:
+			if(snprintf(_pv_xavp_buf, 128, "%lld", avp->val.v.ll)<0)
+				return pv_get_null(msg, param, res);
+		break;
+		case SR_XTYPE_XAVP:
+			if(snprintf(_pv_xavp_buf, 128, "<<xavp:%p>>", avp->val.v.xavp)<0)
+				return pv_get_null(msg, param, res);
+		break;
+		case SR_XTYPE_DATA:
+			if(snprintf(_pv_xavp_buf, 128, "<<data:%p>>", avp->val.v.data)<0)
+				return pv_get_null(msg, param, res);
+		break;
+		default:
+			return pv_get_null(msg, param, res);
+	}
+	s.s = _pv_xavp_buf;
+	s.len = strlen(_pv_xavp_buf);
+	return pv_get_strval(msg, param, res, &s);
+}
+
+
+int pv_get_xavp(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res)
+{
+	pv_xavp_name_t *xname=NULL;
+	sr_xavp_t *avp=NULL;
+	int idxf = 0;
+	int idx = 0;
+	int count;
+
+	if(param==NULL)
+	{
+		LM_ERR("bad parameters\n");
+		return -1;
+	}
+	xname = (pv_xavp_name_t*)param->pvn.u.dname;
+
+	if(xname->index.type==PVT_EXTRA)
+	{
+		/* get the index */
+		if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0)
+		{
+			LM_ERR("invalid index\n");
+			return -1;
+		}
+	}
+	/* fix the index */
+	if(idx<0)
+	{
+		count = xavp_count(&xname->name, NULL);
+		idx = count + idx + 1;
+	}
+	avp = xavp_get_by_index(&xname->name, idx, NULL);
+	if(avp==NULL)
+		return pv_get_null(msg, param, res);
+	if(xname->next==NULL)
+		return pv_xavp_get_value(msg, param, res, avp);
+
+	if(xname->next->index.type==PVT_EXTRA)
+	{
+		/* get the index */
+		if(pv_get_spec_index(msg, &xname->next->index.pvp, &idx, &idxf)!=0)
+		{
+			LM_ERR("invalid index\n");
+			return -1;
+		}
+	}
+	/* fix the index */
+	if(idx<0)
+	{
+		count = xavp_count(&xname->next->name, &avp->val.v.xavp);
+		idx = count + idx + 1;
+	}
+	avp = xavp_get_by_index(&xname->next->name, idx, &avp->val.v.xavp);
+	if(avp==NULL)
+		return pv_get_null(msg, param, res);
+	return pv_xavp_get_value(msg, param, res, avp);
+}
+
+/**
+ * $xavp(name1[idx1]=>name2[idx2])
+ */
+int pv_set_xavp(struct sip_msg* msg, pv_param_t *param,
+		int op, pv_value_t *val)
+{
+	pv_xavp_name_t *xname=NULL;
+	sr_xavp_t *avp=NULL;
+	sr_xavp_t *list=NULL;
+	sr_xval_t xval;
+	int idxf = 0;
+	int idx = 0;
+	int idxf1 = 0;
+	int idx1 = 0;
+	int count;
+
+	if(param==NULL)
+	{
+		LM_ERR("bad parameters\n");
+		return -1;
+	}
+	xname = (pv_xavp_name_t*)param->pvn.u.dname;
+
+	if(xname->index.type==PVT_EXTRA)
+	{
+		/* get the index */
+		if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0)
+		{
+			LM_ERR("invalid index\n");
+			return -1;
+		}
+	}
+
+	if((val==NULL) || (val->flags&PV_VAL_NULL))
+	{
+		if(xname->next==NULL)
+		{
+			if(xname->index.type==PVT_EXTRA) {
+				if(idxf==PV_IDX_ALL) {
+					xavp_rm_by_name(&xname->name, 1, NULL);
+					return 0;
+				}
+			}
+			if(idx==0) {
+				xavp_rm_by_name(&xname->name, 0, NULL);
+				return 0;
+			}
+			/* fix the index */
+			if(idx<0)
+			{
+				count = xavp_count(&xname->name, NULL);
+				idx = count + idx + 1;
+			}
+			xavp_rm_by_index(&xname->name, idx, NULL);
+			return 0;
+		}
+		
+		if(xname->next->index.type==PVT_EXTRA)
+		{
+			/* get the index */
+			if(pv_get_spec_index(msg,&xname->next->index.pvp,&idx1,&idxf1)!=0)
+			{
+				LM_ERR("invalid index!\n");
+				return -1;
+			}
+		}
+
+		if(idxf==PV_IDX_ALL) {
+			/* iterate */
+			avp = xavp_get(&xname->name, NULL);
+			while(avp) {
+				if(avp->val.type==SR_XTYPE_XAVP) {
+					if(xname->next->index.type==PVT_EXTRA) {
+						if(idxf1==PV_IDX_ALL) {
+							xavp_rm_by_name(&xname->next->name, 1,
+									&avp->val.v.xavp);
+						} else {
+							/* fix the index */
+							idx = idx1;
+							if(idx<0)
+							{
+								count = xavp_count(&xname->next->name,
+										&avp->val.v.xavp);
+								idx = count + idx1 + 1;
+							}
+							xavp_rm_by_index(&xname->next->name, idx,
+									&avp->val.v.xavp);
+						}
+					} else {
+						xavp_rm_by_name(&xname->next->name, 0,
+								&avp->val.v.xavp);
+					}
+				}
+				avp = xavp_get_next(avp);
+			}
+			return 0;
+		}
+
+		if(idx==0) {
+			avp = xavp_get(&xname->name, NULL);
+		} else {
+			/* fix the index */
+			if(idx<0)
+			{
+				count = xavp_count(&xname->name, NULL);
+				idx = count + idx + 1;
+			}
+			avp = xavp_get_by_index(&xname->name, idx, NULL);
+		}
+		if(avp) {
+			if(avp->val.type==SR_XTYPE_XAVP) {
+				if(xname->next->index.type==PVT_EXTRA) {
+					if(idxf1==PV_IDX_ALL) {
+						xavp_rm_by_name(&xname->next->name, 1,
+								&avp->val.v.xavp);
+					} else {
+						/* fix the index */
+						idx = idx1;
+						if(idx<0)
+						{
+							count = xavp_count(&xname->next->name,
+									&avp->val.v.xavp);
+							idx = count + idx1 + 1;
+						}
+						xavp_rm_by_index(&xname->next->name, idx,
+								&avp->val.v.xavp);
+					}
+				} else {
+					xavp_rm_by_name(&xname->next->name, 0,
+							&avp->val.v.xavp);
+				}
+			}
+		}
+		return 0;
+	} /* NULL assignment */
+
+	/* build xavp value */
+	memset(&xval, 0, sizeof(sr_xval_t));
+
+	if(val->flags&PV_TYPE_INT)
+	{
+		xval.type = SR_XTYPE_INT;
+		xval.v.i = val->ri;
+	} else {
+		xval.type = SR_XTYPE_STR;
+		xval.v.s = val->rs;
+	}
+
+	/* where to add */
+	if(xname->next==NULL)
+	{
+		/* xavp with single value */
+		if(xname->index.type==PVT_EXTRA) {
+			if(idxf==PV_IDX_ALL) {
+				/* ignore: should iterate and set same value to all xavps
+				 * with same name?!?! */
+				return -1;
+			}
+			/* fix the index */
+			if(idx<0)
+			{
+				count = xavp_count(&xname->name, NULL);
+				idx = count + idx + 1;
+			}
+			/* set the value */
+			if(xavp_set_value(&xname->name, idx, &xval, NULL)==NULL)
+				return -1;
+			return 0;
+		}
+		/* add new value */
+		if(xavp_add_value(&xname->name, &xval, NULL)==NULL)
+			return -1;
+		return 0;
+	}
+		
+	/* xavp with xavp list value */
+	if(xname->next->index.type==PVT_EXTRA)
+	{
+		/* get the index */
+		if(pv_get_spec_index(msg,&xname->next->index.pvp,&idx1,&idxf1)!=0)
+		{
+			LM_ERR("invalid index!\n");
+			return -1;
+		}
+	}
+
+	if(xname->index.type==PVT_EXTRA)
+	{
+		/* set the value */
+		if(idxf==PV_IDX_ALL) {
+			/* ignore: should iterate and set same value to all xavps
+			 * with same name?!?! */
+			return 0;
+		}
+
+		if(idx==0) {
+			avp = xavp_get(&xname->name, NULL);
+		} else {
+			/* fix the index */
+			if(idx<0)
+			{
+				count = xavp_count(&xname->name, NULL);
+				idx = count + idx + 1;
+			}
+			avp = xavp_get_by_index(&xname->name, idx, NULL);
+		}
+		if(avp==NULL)
+			return 0;
+
+		if(avp->val.type!=SR_XTYPE_XAVP)
+			return -1;
+			
+		if(xname->next->index.type==PVT_EXTRA) {
+			if(idxf1==PV_IDX_ALL) {
+				/* ignore: should iterate and set same value to all xavps
+				 * with same name?!?! */
+				return 0;
+			}
+			/* fix the index */
+			idx = idx1;
+			if(idx<0)
+			{
+				count = xavp_count(&xname->next->name,
+						&avp->val.v.xavp);
+				idx = count + idx1 + 1;
+			}
+			/* set value */
+			xavp_set_value(&xname->next->name, idx, &xval, &avp->val.v.xavp);
+			return 0;
+		}
+		/* add new value in sublist */
+		if(xavp_add_value(&xname->next->name, &xval, &avp->val.v.xavp)==NULL)
+			return -1;
+		return 0;
+	}
+	/* add new xavp with xavp list */
+	if(xavp_add_value(&xname->next->name, &xval, &list)==NULL)
+		return -1;
+	
+	/* build xavp value */
+	memset(&xval, 0, sizeof(sr_xval_t));
+	xval.type = SR_XTYPE_XAVP;
+	xval.v.xavp = list;
+	xavp_add_value(&xname->name, &xval, NULL);
+
+	return 0;
+}
+
+char* pv_xavp_fill_ni(str *in, pv_xavp_name_t *xname)
+{
+	char *p;
+	str idx;
+	int n;
+
+	if(in->s==NULL || in->len<=0 || xname==NULL)
+		return NULL;
+	p = in->s;
+
+	/* eat ws */
+	while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
+		p++;
+	if(p>in->s+in->len || *p=='\0')
+		goto error;
+	xname->name.s = p;
+	while(p < in->s + in->len)
+	{
+		if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r' || *p=='[')
+			break;
+		p++;
+	}
+	xname->name.len = p - xname->name.s;
+	if(p>in->s+in->len || *p=='\0')
+		return p;
+	/* eat ws */
+	while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
+		p++;
+	if(p>in->s+in->len || *p=='\0')
+		return p;
+
+	if(*p!='[')
+		return p;
+	/* there is index */
+	p++;
+	idx.s = p;
+	n = 0;
+	while(p<in->s+in->len && *p!='\0')
+	{
+		if(*p==']')
+		{
+			if(n==0)
+				break;
+			n--;
+		}
+		if(*p == '[')
+			n++;
+		p++;
+	}
+	if(p>in->s+in->len || *p=='\0')
+		goto error;
+
+	if(p==idx.s)
+	{
+		LM_ERR("xavp [\"%.*s\"] does not get empty index param\n",
+				in->len, in->s);
+		goto error;
+	}
+	idx.len = p - idx.s;
+	if(pv_parse_index(&xname->index, &idx)!=0)
+	{
+		LM_ERR("idx \"%.*s\" has an invalid index param [%.*s]\n",
+					in->len, in->s, idx.len, idx.s);
+		goto error;
+	}
+	xname->index.type = PVT_EXTRA;
+	p++;
+	return p;
+error:
+	return NULL;
+}
+
+void pv_xavp_name_destroy(pv_xavp_name_t *xname)
+{
+	return;
+}
+
+int pv_parse_xavp_name(pv_spec_p sp, str *in)
+{
+	pv_xavp_name_t *xname=NULL;
+	char *p;
+	str s;
+
+	if(in->s==NULL || in->len<=0)
+		return -1;
+
+	xname = (pv_xavp_name_t*)pkg_malloc(sizeof(pv_xavp_name_t));
+	if(xname==NULL)
+		return -1;
+
+	memset(xname, 0, sizeof(pv_xavp_name_t));
+
+	s = *in;
+
+	p = pv_xavp_fill_ni(&s, xname);
+	if(p==NULL)
+		goto error;
+
+	if(*p!='=')
+		goto done;
+	p++;
+	if(*p!='>')
+		goto error;
+	p++;
+
+	s.len = in->len - (int)(p - in->s);
+	s.s = p;
+	LM_DBG("xavp sublist [%.*s] - key [%.*s]\n", xname->name.len,
+			xname->name.s, s.len, s.s);
+
+	xname->next = (pv_xavp_name_t*)pkg_malloc(sizeof(pv_xavp_name_t));
+	if(xname->next==NULL)
+		goto error;
+
+	memset(xname->next, 0, sizeof(pv_xavp_name_t));
+
+	p = pv_xavp_fill_ni(&s, xname->next);
+	if(p==NULL)
+		goto error;
+
+done:
+	sp->pvp.pvn.u.dname = (void*)xname;
+	sp->pvp.pvn.type = PV_NAME_PVAR;
+	return 0;
+
+error:
+	if(xname!=NULL) {
+		pv_xavp_name_destroy(xname);
+		pkg_free(xname);
+	}
+	return -1;
+}
+
+int pv_xavp_print(struct sip_msg* msg, char* s1, char *s2)
+{
+	xavp_print_list(NULL);
+	return 1;
+}
+
+#endif

+ 41 - 0
modules_k/pv/pv_xavp.h

@@ -0,0 +1,41 @@
+/**
+ * $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.
+ */
+ 
+#ifndef _PV_XAVP_H_
+#define _PV_XAVP_H_
+
+#ifdef WITH_XAVP
+
+#include "../../pvar.h"
+
+typedef struct _pv_xavp_name {
+	str name;
+	pv_spec_t index;
+	struct _pv_xavp_name *next;
+} pv_xavp_name_t;
+
+int pv_get_xavp(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res);
+int pv_set_xavp(struct sip_msg* msg, pv_param_t *param,
+		int op, pv_value_t *val);
+int pv_parse_xavp_name(pv_spec_p sp, str *in);
+
+int pv_xavp_print(struct sip_msg* msg, char* s1, char *s2);
+
+#endif
+#endif