Module: sip-router
Branch: daniel/pv
Commit: d79388b32114357ca98159d5c49fc2b3996d18a7
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=d79388b…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)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;