瀏覽代碼

pv api updates

- fix the transformations hash table size
- complete the functions in PV&T API
Daniel-Constantin Mierla 16 年之前
父節點
當前提交
037dd9e5df
共有 2 個文件被更改,包括 240 次插入21 次删除
  1. 232 15
      pvapi.c
  2. 8 6
      pvar.h

+ 232 - 15
pvapi.c

@@ -34,18 +34,18 @@
 #include "mem/shm_mem.h"
 #include "ut.h"
 #include "dprint.h"
-#include "hashes.h"
+#include "hash_func.h"
 #include "pvar.h"
 
 #define is_in_str(p, in) (p<in->s+in->len && *p)
 
 #define PV_TABLE_SIZE	16
-#define TR_TABLE_SIZE	2
+#define TR_TABLE_SIZE	4
 
+#define core_hash(in, a, b) get_hash1_raw((in)->s, (in)->len);
 
 void tr_destroy(trans_t *t);
 void tr_free(trans_t *t);
-void tr_param_free(tr_param_t *tp);
 
 typedef struct _pv_item
 {
@@ -57,11 +57,10 @@ typedef struct _pv_item
 static pv_item_t* _pv_table[PV_TABLE_SIZE];
 static int _pv_table_set = 0;
 
-
 /**
  *
  */
-void pv_init_table()
+void pv_init_table(void)
 {
 	memset(_pv_table, 0, sizeof(pv_item_t*)*PV_TABLE_SIZE);
 	_pv_table_set = 1;
@@ -112,7 +111,8 @@ int pv_table_add(pv_export_t *e)
 		return -1;
 	}
 	found = 0;
-	pvid = get_hash1_raw(in->s, in->len);
+	//pvid = get_hash1_raw(in->s, in->len);
+	pvid = core_hash(in, 0, 0);
 
 	pvi = _pv_table[pvid%PV_TABLE_SIZE];
 	while(pvi)
@@ -239,6 +239,7 @@ int pv_get_sintval(struct sip_msg *msg, pv_param_t *param,
 	if(res==NULL)
 		return -1;
 
+	// ch = sint2str(sival, &l);
 	ch = int2str(sival, &l);
 	res->rs.s = ch;
 	res->rs.len = l;
@@ -326,7 +327,8 @@ pv_export_t* pv_lookup_spec_name(str *pvname, pv_spec_p e)
 	}
 
 	/* search in PV table */
-	pvid = get_hash1_raw(pvname->s, pvname->len);
+	// pvid = get_hash1_raw(pvname->s, pvname->len);
+	pvid = core_hash(pvname, 0, 0);
 	pvi = _pv_table[pvid%PV_TABLE_SIZE];
 	while(pvi)
 	{
@@ -352,6 +354,71 @@ pv_export_t* pv_lookup_spec_name(str *pvname, pv_spec_p e)
 	return NULL;
 }
 
+int pv_parse_index(pv_spec_p sp, str *in)
+{
+	char *p;
+	char *s;
+	int sign;
+	pv_spec_p nsp = 0;
+
+	if(in==NULL || in->s==NULL || sp==NULL)
+		return -1;
+	p = in->s;
+	if(*p==PV_MARKER)
+	{
+		nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
+		if(nsp==NULL)
+		{
+			LM_ERR("no more memory\n");
+			return -1;
+		}
+		s = pv_parse_spec(in, nsp);
+		if(s==NULL)
+		{
+			LM_ERR("invalid index [%.*s]\n", in->len, in->s);
+			pv_spec_free(nsp);
+			return -1;
+		}
+		sp->pvp.pvi.type = PV_IDX_PVAR;
+		sp->pvp.pvi.u.dval = (void*)nsp;
+		return 0;
+	}
+	if(*p=='*' && in->len==1)
+	{
+		sp->pvp.pvi.type = PV_IDX_ALL;
+		return 0;
+	}
+	sign = 1;
+	if(*p=='-')
+	{
+		sign = -1;
+		p++;
+	}
+	sp->pvp.pvi.u.ival = 0;
+	while(p<in->s+in->len && *p>='0' && *p<='9')
+	{
+		sp->pvp.pvi.u.ival = sp->pvp.pvi.u.ival * 10 + *p - '0';
+		p++;
+	}
+	if(p!=in->s+in->len)
+	{
+		LM_ERR("invalid index [%.*s]\n", in->len, in->s);
+		return -1;
+	}
+	sp->pvp.pvi.u.ival *= sign;
+	sp->pvp.pvi.type = PV_IDX_INT;
+	return 0;
+}
+
+int pv_init_iname(pv_spec_p sp, int param)
+{
+	if(sp==NULL)
+		return -1;
+	sp->pvp.pvn.type = PV_NAME_INTSTR;
+	sp->pvp.pvn.u.isname.name.n = param;
+	return 0;
+}
+
 char* pv_parse_spec(str *in, pv_spec_p e)
 {
 	char *p;
@@ -702,6 +769,121 @@ error:
 	return -1;
 }
 
+int pv_get_spec_name(struct sip_msg* msg, pv_param_p ip, pv_value_t *name)
+{
+	if(msg==NULL || ip==NULL || name==NULL)
+		return -1;
+	memset(name, 0, sizeof(pv_value_t));
+
+	if(ip->pvn.type==PV_NAME_INTSTR)
+	{
+		if(ip->pvn.u.isname.type&AVP_NAME_STR)
+		{
+			name->rs = ip->pvn.u.isname.name.s;
+			name->flags = PV_VAL_STR;
+		} else {
+			name->ri = ip->pvn.u.isname.name.n;
+			name->flags = PV_VAL_INT|PV_TYPE_INT;
+		}
+		return 0;
+	} else if(ip->pvn.type==PV_NAME_INTSTR) {
+		/* pvar */
+		if(pv_get_spec_value(msg, (pv_spec_p)(ip->pvn.u.dname), name)!=0)
+		{
+			LM_ERR("cannot get name value\n");
+			return -1;
+		}
+		if(name->flags&PV_VAL_NULL || name->flags&PV_VAL_EMPTY)
+		{
+			LM_ERR("null or empty name\n");
+			return -1;
+		}
+		return 0;
+	}
+	LM_ERR("name type is PV_NAME_OTHER - cannot resolve\n");
+	return -1;
+}
+
+int pv_get_avp_name(struct sip_msg* msg, pv_param_p ip, int_str *avp_name,
+		unsigned short *name_type)
+{
+	pv_value_t tv;
+	if(ip==NULL || avp_name==NULL || name_type==NULL)
+		return -1;
+	memset(avp_name, 0, sizeof(int_str));
+	*name_type = 0;
+
+	if(ip->pvn.type==PV_NAME_INTSTR)
+	{
+		*name_type = ip->pvn.u.isname.type;
+		if(ip->pvn.u.isname.type&AVP_NAME_STR)
+		{
+			avp_name->s = ip->pvn.u.isname.name.s;
+			*name_type |= AVP_NAME_STR;
+		} else {
+			avp_name->n = ip->pvn.u.isname.name.n;
+			*name_type = 0; // &= AVP_SCRIPT_MASK;
+		}
+		return 0;
+	}
+	/* pvar */
+	if(pv_get_spec_value(msg, (pv_spec_p)(ip->pvn.u.dname), &tv)!=0)
+	{
+		LM_ERR("cannot get avp value\n");
+		return -1;
+	}
+	if(tv.flags&PV_VAL_NULL || tv.flags&PV_VAL_EMPTY)
+	{
+		LM_ERR("null or empty name\n");
+		return -1;
+	}
+		
+	if((tv.flags&PV_TYPE_INT) && (tv.flags&PV_VAL_INT))
+	{
+		avp_name->n = tv.ri;
+	} else {
+		avp_name->s = tv.rs;
+		*name_type = AVP_NAME_STR;
+	}
+	return 0;
+}
+
+
+int pv_get_spec_index(struct sip_msg* msg, pv_param_p ip, int *idx, int *flags)
+{
+	pv_value_t tv;
+	if(ip==NULL || idx==NULL || flags==NULL)
+		return -1;
+
+	*idx = 0;
+	*flags = 0;
+
+	if(ip->pvi.type == PV_IDX_ALL) {
+		*flags = PV_IDX_ALL;
+		return 0;
+	}
+	
+	if(ip->pvi.type == PV_IDX_INT)
+	{
+		*idx = ip->pvi.u.ival;
+		return 0;
+	}
+
+	/* pvar */
+	if(pv_get_spec_value(msg, (pv_spec_p)ip->pvi.u.dval, &tv)!=0)
+	{
+		LM_ERR("cannot get index value\n");
+		return -1;
+	}
+	if(!(tv.flags&PV_VAL_INT))
+	{
+		LM_ERR("invalid index value\n");
+		return -1;
+	}
+	*idx = tv.ri;
+	return 0;
+}
+
 int pv_get_spec_value(struct sip_msg* msg, pv_spec_p sp, pv_value_t *value)
 {
 	int ret = 0;
@@ -718,6 +900,7 @@ int pv_get_spec_value(struct sip_msg* msg, pv_spec_p sp, pv_value_t *value)
 	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;
@@ -834,6 +1017,23 @@ void pv_value_destroy(pv_value_t *val)
 	memset(val, 0, sizeof(pv_value_t));
 }
 
+#define PV_PRINT_BUF_SIZE  1024
+#define PV_PRINT_BUF_NO    3
+int pv_printf_s(struct sip_msg* msg, pv_elem_p list, str *s)
+{
+	static int buf_itr = 0;
+	static char buf[PV_PRINT_BUF_NO][PV_PRINT_BUF_SIZE];
+
+	if (list->next==0 && list->spec.getf==0) {
+		*s = list->text;
+		return 0;
+	} else {
+		s->s = buf[buf_itr];
+		s->len = PV_PRINT_BUF_SIZE;
+		buf_itr = (buf_itr+1)%PV_PRINT_BUF_NO;
+		return pv_printf( msg, list, s->s, &s->len);
+	}
+}
 
 /********************************************************
  * Transformations API
@@ -860,7 +1060,7 @@ static inline char* tr_get_class(str *in, char *p, str *tclass)
 /**
  *
  */
-static inline trans_t* tr_new()
+static inline trans_t* tr_new(void)
 {
 	trans_t *t = NULL;
 
@@ -965,6 +1165,14 @@ void tr_destroy(trans_t *t)
 	memset(t, 0, sizeof(trans_t));
 }
 
+/*!
+ * \brief Exec transformation on a pseudo-variable value
+ * \param msg SIP message
+ * \param tr one or more transformations
+ * \param val pseudo-variable value
+ * \return 0 on success, -1 on error
+ */
+
 int tr_exec(struct sip_msg *msg, trans_t *t, pv_value_t *v)
 {
 	int r;
@@ -1029,14 +1237,14 @@ typedef struct _tr_item
 	struct _tr_item *next;
 } tr_item_t, *tr_item_p;
 
-static tr_item_t* _tr_table[PV_TABLE_SIZE];
+static tr_item_t* _tr_table[TR_TABLE_SIZE];
 static int _tr_table_set = 0;
 
 
 /**
  *
  */
-void tr_init_table()
+void tr_init_table(void)
 {
 	memset(_tr_table, 0, sizeof(tr_item_t*)*TR_TABLE_SIZE);
 	_tr_table_set = 1;
@@ -1066,9 +1274,10 @@ int tr_table_add(tr_export_t *e)
 	}
 
 	found = 0;
-	trid = get_hash1_raw(e->tclass.s, e->tclass.len);
+	// trid = get_hash1_raw(e->tclass.s, e->tclass.len);
+	trid = core_hash(&e->tclass, 0, 0);
 
-	tri = _tr_table[trid%PV_TABLE_SIZE];
+	tri = _tr_table[trid%TR_TABLE_SIZE];
 	while(tri)
 	{
 		if(tri->trid > trid)
@@ -1101,10 +1310,12 @@ int tr_table_add(tr_export_t *e)
 	memcpy(&(trn->tre), e, sizeof(tr_export_t));
 	trn->trid = trid;
 
+	//LM_DBG("TR class [%.*s] added to entry [%d]\n", e->tclass.len,
+	//					e->tclass.s, trid%TR_TABLE_SIZE);
 	if(trj==0)
 	{
-		trn->next = _tr_table[trid%PV_TABLE_SIZE];
-		_tr_table[trid%PV_TABLE_SIZE] = trn;
+		trn->next = _tr_table[trid%TR_TABLE_SIZE];
+		_tr_table[trid%TR_TABLE_SIZE] = trn;
 		goto done;
 	}
 	trn->next = trj->next;
@@ -1172,7 +1383,8 @@ tr_export_t* tr_lookup_class(str *tclass)
 	}
 
 	/* search in TR table */
-	trid = get_hash1_raw(tclass->s, tclass->len);
+	// trid = get_hash1_raw(tclass->s, tclass->len);
+	trid = core_hash(tclass, 0, 0);
 	tri = _tr_table[trid%TR_TABLE_SIZE];
 	while(tri)
 	{
@@ -1190,3 +1402,8 @@ tr_export_t* tr_lookup_class(str *tclass)
 	return NULL;
 }
 
+void pv_api_destroy(void)
+{
+	/* free PV and TR hash tables */
+	return;
+}

+ 8 - 6
pvar.h

@@ -57,6 +57,7 @@
 
 #define PV_NAME_INTSTR	0
 #define PV_NAME_PVAR	1
+#define PV_NAME_OTHER	2
 
 #define PV_IDX_INT	0
 #define PV_IDX_PVAR	1
@@ -76,7 +77,7 @@ enum _pv_type {
 	PVT_RURI,             PVT_RURI_USERNAME,     PVT_RURI_DOMAIN,
 	PVT_DSTURI,           PVT_COLOR,             PVT_BRANCH,
 	PVT_FROM,             PVT_TO,                PVT_OURI,
-	PVT_SCRIPTVAR,        PVT_MSG_BODY,
+	PVT_SCRIPTVAR,        PVT_MSG_BODY,          PVT_CONTEXT,
 	PVT_OTHER,            PVT_EXTRA /* keep it last */
 };
 
@@ -164,7 +165,6 @@ typedef struct _pv_elem
 
 char* pv_parse_spec(str *in, pv_spec_p sp);
 int pv_get_spec_value(struct sip_msg* msg, pv_spec_p sp, pv_value_t *value);
-int pv_print_spec(struct sip_msg* msg, pv_spec_p sp, char *buf, int *len);
 int pv_printf(struct sip_msg* msg, pv_elem_p list, char *buf, int *len);
 int pv_elem_free_all(pv_elem_p log);
 void pv_value_destroy(pv_value_t *val);
@@ -175,8 +175,10 @@ int pv_get_avp_name(struct sip_msg* msg, pv_param_p ip, int_str *avp_name,
 		unsigned short *name_type);
 int pv_get_spec_name(struct sip_msg* msg, pv_param_p ip, pv_value_t *name);
 int pv_parse_format(str *in, pv_elem_p *el);
+int pv_parse_index(pv_spec_p sp, str *in);
 int pv_init_iname(pv_spec_p sp, int param);
 int pv_printf_s(struct sip_msg* msg, pv_elem_p list, str *s);
+void pv_api_destroy(void);
 
 typedef struct _pvname_list {
 	pv_spec_t sname;
@@ -194,10 +196,7 @@ int register_pvars_mod(char *mod_name, pv_export_t *items);
 int pv_free_extra_list(void);
 
 /*! \brief PV helper functions */
-int pv_parse_index(pv_spec_p sp, str *in);
-
 int pv_get_null(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
-int pv_update_time(struct sip_msg *msg, time_t *t);
 
 int pv_get_uintval(struct sip_msg *msg, pv_param_t *param,
 		pv_value_t *res, unsigned int uival);
@@ -221,7 +220,7 @@ int pv_get_intstrval(struct sip_msg *msg, pv_param_t *param,
 #define TR_PARAM_MARKER		','
 
 enum _tr_param_type { TR_PARAM_NONE=0, TR_PARAM_STRING, TR_PARAM_NUMBER,
-	TR_PARAM_SPEC };
+	TR_PARAM_SPEC, TR_PARAM_SUBST, TR_PARAM_OTHER };
 
 typedef struct _tr_param {
 	int type;
@@ -253,6 +252,9 @@ 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);
+void tr_param_free(tr_param_t *tp);
+
+int register_trans_mod(char *mod_name, tr_export_t *items);
 
 #endif