[SR-Dev] git:sip-router: more PV API integration

Andrei Pelinescu-Onciul andrei at iptel.org
Fri Nov 21 11:49:44 CET 2008


Module: sip-router
Branch: andrei/fixups
Commit: d79388b32114357ca98159d5c49fc2b3996d18a7
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=d79388b32114357ca98159d5c49fc2b3996d18a7

Author: Daniel-Constantin Mierla <miconda at gmail.com>
Committer: Daniel-Constantin Mierla <miconda at gmail.com>
Date:   Thu Nov 20 23:17:26 2008 +0200

more PV API integration

- register PV exported by modules
- added functions to evaluate PVs
- xlog module from Kamailio/OpenSER should run now in sip-router compiled with DEFS+= -DKAMAILIO_MOD_INTERFACE

---

 pvapi.c     |  227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 pvar.h      |    5 +-
 sr_module.c |   12 +++
 3 files changed, 242 insertions(+), 2 deletions(-)

diff --git a/pvapi.c b/pvapi.c
index eb4ea7a..f3d7b58 100644
--- a/pvapi.c
+++ b/pvapi.c
@@ -31,6 +31,7 @@
 #include <unistd.h>
 
 #include "mem/mem.h"
+#include "mem/shm_mem.h"
 #include "ut.h"
 #include "dprint.h"
 #include "hashes.h"
@@ -301,6 +302,7 @@ static int pv_get_marker(struct sip_msg *msg, pv_param_t *param,
 }
 
 static str pv_str_empty  = { "", 0 };
+static str pv_str_null   = { "<null>", 6 };
 int pv_get_null(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
 {
 	if(res==NULL)
@@ -628,6 +630,175 @@ error:
 
 } /* end: pv_parse_spec */
 
+/**
+ *
+ */
+int pv_parse_format(str *in, pv_elem_p *el)
+{
+	char *p, *p0;
+	int n = 0;
+	pv_elem_p e, e0;
+	str s;
+
+	if(in==NULL || in->s==NULL || el==NULL)
+		return -1;
+
+	/*LM_DBG("parsing [%.*s]\n", in->len, in->s);*/
+	
+	if(in->len == 0)
+	{
+		*el = pkg_malloc(sizeof(pv_elem_t));
+		if(*el == NULL)
+			goto error;
+		memset(*el, 0, sizeof(pv_elem_t));
+		(*el)->text = *in;
+		return 0;
+	}
+
+	p = in->s;
+	*el = NULL;
+	e = e0 = NULL;
+
+	while(is_in_str(p,in))
+	{
+		e0 = e;
+		e = pkg_malloc(sizeof(pv_elem_t));
+		if(!e)
+			goto error;
+		memset(e, 0, sizeof(pv_elem_t));
+		n++;
+		if(*el == NULL)
+			*el = e;
+		if(e0)
+			e0->next = e;
+	
+		e->text.s = p;
+		while(is_in_str(p,in) && *p!=PV_MARKER)
+			p++;
+		e->text.len = p - e->text.s;
+		
+		if(*p == '\0' || !is_in_str(p,in))
+			break;
+		s.s = p;
+		s.len = in->s+in->len-p;
+		p0 = pv_parse_spec(&s, &e->spec);
+		
+		if(p0==NULL)
+			goto error;
+		if(*p0 == '\0')
+			break;
+		p = p0;
+	}
+	/*LM_DBG("format parsed OK: [%d] items\n", n);*/
+
+	if(*el == NULL)
+		return -1;
+
+	return 0;
+
+error:
+	pv_elem_free_all(*el);
+	*el = NULL;
+	return -1;
+}
+
+int pv_get_spec_value(struct sip_msg* msg, pv_spec_p sp, pv_value_t *value)
+{
+	int ret = 0;
+
+	if(msg==NULL || sp==NULL || sp->getf==NULL || value==NULL
+			|| sp->type==PVT_NONE)
+	{
+		LM_ERR("bad parameters\n");
+		return -1;
+	}
+	
+	memset(value, 0, sizeof(pv_value_t));
+
+	ret = (*sp->getf)(msg, &(sp->pvp), value);
+	if(ret!=0)
+		return ret;
+	if(sp->trans)
+		return tr_exec(msg, (trans_t*)sp->trans, value);
+	return ret;
+}
+
+/**
+ *
+ */
+int pv_printf(struct sip_msg* msg, pv_elem_p list, char *buf, int *len)
+{
+	int n, h;
+	pv_value_t tok;
+	pv_elem_p it;
+	char *cur;
+	
+	if(msg==NULL || list==NULL || buf==NULL || len==NULL)
+		return -1;
+
+	if(*len <= 0)
+		return -1;
+
+	*buf = '\0';
+	cur = buf;
+	
+	h = 0;
+	n = 0;
+	for (it=list; it; it=it->next)
+	{
+		/* put the text */
+		if(it->text.s && it->text.len>0)
+		{
+			if(n+it->text.len < *len)
+			{
+				memcpy(cur, it->text.s, it->text.len);
+				n += it->text.len;
+				cur += it->text.len;
+			} else {
+				LM_ERR("no more space for text [%d]\n", it->text.len);
+				goto overflow;
+			}
+		}
+		/* put the value of the specifier */
+		if(it->spec.type!=PVT_NONE
+				&& pv_get_spec_value(msg, &(it->spec), &tok)==0)
+		{
+			if(tok.flags&PV_VAL_NULL)
+				tok.rs = pv_str_null;
+			if(n+tok.rs.len < *len)
+			{
+				if(tok.rs.len>0)
+				{
+					memcpy(cur, tok.rs.s, tok.rs.len);
+					n += tok.rs.len;
+					cur += tok.rs.len;
+				}
+			} else {
+				LM_ERR("no more space for spec value\n");
+				goto overflow;
+			}
+		}
+	}
+
+	goto done;
+	
+overflow:
+	LM_ERR("buffer overflow -- increase the buffer size...\n");
+	return -1;
+
+done:
+#ifdef EXTRA_DEBUG
+	LM_DBG("final buffer length %d\n", n);
+#endif
+	*cur = '\0';
+	*len = n;
+	return 0;
+}
+
+
+/**
+ *
+ */
 void pv_spec_free(pv_spec_t *spec)
 {
 	if(spec==0) return;
@@ -637,6 +808,40 @@ void pv_spec_free(pv_spec_t *spec)
 	pkg_free(spec);
 }
 
+/**
+ *
+ */
+int pv_elem_free_all(pv_elem_p log)
+{
+	pv_elem_p t;
+	while(log)
+	{
+		t = log;
+		log = log->next;
+		pkg_free(t);
+	}
+	return 0;
+}
+
+/**
+ *
+ */
+void pv_value_destroy(pv_value_t *val)
+{
+	if(val==0) return;
+	if(val->flags&PV_VAL_PKG) pkg_free(val->rs.s);
+	if(val->flags&PV_VAL_SHM) shm_free(val->rs.s);
+	memset(val, 0, sizeof(pv_value_t));
+}
+
+
+/********************************************************
+ * Transformations API
+ ********************************************************/
+
+/**
+ *
+ */
 static inline char* tr_get_class(str *in, char *p, str *tclass)
 {
 	tclass->s = p;
@@ -652,6 +857,9 @@ static inline char* tr_get_class(str *in, char *p, str *tclass)
 	return p;
 }
 
+/**
+ *
+ */
 static inline trans_t* tr_new()
 {
 	trans_t *t = NULL;
@@ -757,6 +965,25 @@ void tr_destroy(trans_t *t)
 	memset(t, 0, sizeof(trans_t));
 }
 
+int tr_exec(struct sip_msg *msg, trans_t *t, pv_value_t *v)
+{
+	int r;
+	trans_t *i;
+
+	if(t==NULL || v==NULL)
+	{
+		LM_DBG("invalid parameters\n");
+		return -1;
+	}
+	
+	for(i = t; i!=NULL; i=i->next)
+	{
+		r = (*i->trf)(msg, i->params, i->subtype, v);
+		if(r!=0)
+			return r;
+	}
+	return 0;
+}
 
 /*!
  * \brief Free allocated memory of transformation list
diff --git a/pvar.h b/pvar.h
index be7b3bc..811ea34 100644
--- a/pvar.h
+++ b/pvar.h
@@ -72,8 +72,8 @@
 
 enum _pv_type { 
 	PVT_NONE=0,           PVT_EMPTY,             PVT_NULL, 
-	PVT_MARKER,           PVT_AVP,               PVT_OTHER,
-	PVT_EXTRA /* keep it last */
+	PVT_MARKER,           PVT_AVP,               PVT_COLOR,
+	PVT_OTHER,            PVT_EXTRA /* keep it last */
 };
 
 typedef enum _pv_type pv_type_t;
@@ -248,6 +248,7 @@ typedef struct _tr_export {
 
 char* tr_lookup(str *in, trans_t **tr);
 tr_export_t* tr_lookup_class(str *tclass);
+int tr_exec(struct sip_msg *msg, trans_t *t, pv_value_t *v);
 
 #endif
 
diff --git a/sr_module.c b/sr_module.c
index 491e971..6d803f8 100644
--- a/sr_module.c
+++ b/sr_module.c
@@ -164,6 +164,18 @@ static int register_module(unsigned ver, union module_exports_u* e,
 	mod->exports=e;
 	mod->next=modules;
 	modules=mod;
+
+	/* register module pseudo-variables */
+	if (ver==1 && e->v1.items) {
+		LM_DBG("register PV from: %s\n", e->c.name);
+		if (register_pvars_mod(e->c.name, e->v1.items)!=0) {
+			LM_ERR("failed to register pseudo-variables for module %s\n",
+				e->c.name);
+			pkg_free(mod);
+			return -1;
+		}
+	}
+
 	return 0;
 error:
 	return ret;




More information about the sr-dev mailing list