Browse code

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

Daniel-Constantin Mierla authored on 20/11/2008 21:17:26
Showing 3 changed files
... ...
@@ -31,6 +31,7 @@
31 31
 #include <unistd.h>
32 32
 
33 33
 #include "mem/mem.h"
34
+#include "mem/shm_mem.h"
34 35
 #include "ut.h"
35 36
 #include "dprint.h"
36 37
 #include "hashes.h"
... ...
@@ -301,6 +302,7 @@ static int pv_get_marker(struct sip_msg *msg, pv_param_t *param,
301 301
 }
302 302
 
303 303
 static str pv_str_empty  = { "", 0 };
304
+static str pv_str_null   = { "<null>", 6 };
304 305
 int pv_get_null(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
305 306
 {
306 307
 	if(res==NULL)
... ...
@@ -628,6 +630,175 @@ error:
628 628
 
629 629
 } /* end: pv_parse_spec */
630 630
 
631
+/**
632
+ *
633
+ */
634
+int pv_parse_format(str *in, pv_elem_p *el)
635
+{
636
+	char *p, *p0;
637
+	int n = 0;
638
+	pv_elem_p e, e0;
639
+	str s;
640
+
641
+	if(in==NULL || in->s==NULL || el==NULL)
642
+		return -1;
643
+
644
+	/*LM_DBG("parsing [%.*s]\n", in->len, in->s);*/
645
+	
646
+	if(in->len == 0)
647
+	{
648
+		*el = pkg_malloc(sizeof(pv_elem_t));
649
+		if(*el == NULL)
650
+			goto error;
651
+		memset(*el, 0, sizeof(pv_elem_t));
652
+		(*el)->text = *in;
653
+		return 0;
654
+	}
655
+
656
+	p = in->s;
657
+	*el = NULL;
658
+	e = e0 = NULL;
659
+
660
+	while(is_in_str(p,in))
661
+	{
662
+		e0 = e;
663
+		e = pkg_malloc(sizeof(pv_elem_t));
664
+		if(!e)
665
+			goto error;
666
+		memset(e, 0, sizeof(pv_elem_t));
667
+		n++;
668
+		if(*el == NULL)
669
+			*el = e;
670
+		if(e0)
671
+			e0->next = e;
672
+	
673
+		e->text.s = p;
674
+		while(is_in_str(p,in) && *p!=PV_MARKER)
675
+			p++;
676
+		e->text.len = p - e->text.s;
677
+		
678
+		if(*p == '\0' || !is_in_str(p,in))
679
+			break;
680
+		s.s = p;
681
+		s.len = in->s+in->len-p;
682
+		p0 = pv_parse_spec(&s, &e->spec);
683
+		
684
+		if(p0==NULL)
685
+			goto error;
686
+		if(*p0 == '\0')
687
+			break;
688
+		p = p0;
689
+	}
690
+	/*LM_DBG("format parsed OK: [%d] items\n", n);*/
691
+
692
+	if(*el == NULL)
693
+		return -1;
694
+
695
+	return 0;
696
+
697
+error:
698
+	pv_elem_free_all(*el);
699
+	*el = NULL;
700
+	return -1;
701
+}
702
+
703
+int pv_get_spec_value(struct sip_msg* msg, pv_spec_p sp, pv_value_t *value)
704
+{
705
+	int ret = 0;
706
+
707
+	if(msg==NULL || sp==NULL || sp->getf==NULL || value==NULL
708
+			|| sp->type==PVT_NONE)
709
+	{
710
+		LM_ERR("bad parameters\n");
711
+		return -1;
712
+	}
713
+	
714
+	memset(value, 0, sizeof(pv_value_t));
715
+
716
+	ret = (*sp->getf)(msg, &(sp->pvp), value);
717
+	if(ret!=0)
718
+		return ret;
719
+	if(sp->trans)
720
+		return tr_exec(msg, (trans_t*)sp->trans, value);
721
+	return ret;
722
+}
723
+
724
+/**
725
+ *
726
+ */
727
+int pv_printf(struct sip_msg* msg, pv_elem_p list, char *buf, int *len)
728
+{
729
+	int n, h;
730
+	pv_value_t tok;
731
+	pv_elem_p it;
732
+	char *cur;
733
+	
734
+	if(msg==NULL || list==NULL || buf==NULL || len==NULL)
735
+		return -1;
736
+
737
+	if(*len <= 0)
738
+		return -1;
739
+
740
+	*buf = '\0';
741
+	cur = buf;
742
+	
743
+	h = 0;
744
+	n = 0;
745
+	for (it=list; it; it=it->next)
746
+	{
747
+		/* put the text */
748
+		if(it->text.s && it->text.len>0)
749
+		{
750
+			if(n+it->text.len < *len)
751
+			{
752
+				memcpy(cur, it->text.s, it->text.len);
753
+				n += it->text.len;
754
+				cur += it->text.len;
755
+			} else {
756
+				LM_ERR("no more space for text [%d]\n", it->text.len);
757
+				goto overflow;
758
+			}
759
+		}
760
+		/* put the value of the specifier */
761
+		if(it->spec.type!=PVT_NONE
762
+				&& pv_get_spec_value(msg, &(it->spec), &tok)==0)
763
+		{
764
+			if(tok.flags&PV_VAL_NULL)
765
+				tok.rs = pv_str_null;
766
+			if(n+tok.rs.len < *len)
767
+			{
768
+				if(tok.rs.len>0)
769
+				{
770
+					memcpy(cur, tok.rs.s, tok.rs.len);
771
+					n += tok.rs.len;
772
+					cur += tok.rs.len;
773
+				}
774
+			} else {
775
+				LM_ERR("no more space for spec value\n");
776
+				goto overflow;
777
+			}
778
+		}
779
+	}
780
+
781
+	goto done;
782
+	
783
+overflow:
784
+	LM_ERR("buffer overflow -- increase the buffer size...\n");
785
+	return -1;
786
+
787
+done:
788
+#ifdef EXTRA_DEBUG
789
+	LM_DBG("final buffer length %d\n", n);
790
+#endif
791
+	*cur = '\0';
792
+	*len = n;
793
+	return 0;
794
+}
795
+
796
+
797
+/**
798
+ *
799
+ */
631 800
 void pv_spec_free(pv_spec_t *spec)
632 801
 {
633 802
 	if(spec==0) return;
... ...
@@ -637,6 +808,40 @@ void pv_spec_free(pv_spec_t *spec)
637 637
 	pkg_free(spec);
638 638
 }
639 639
 
640
+/**
641
+ *
642
+ */
643
+int pv_elem_free_all(pv_elem_p log)
644
+{
645
+	pv_elem_p t;
646
+	while(log)
647
+	{
648
+		t = log;
649
+		log = log->next;
650
+		pkg_free(t);
651
+	}
652
+	return 0;
653
+}
654
+
655
+/**
656
+ *
657
+ */
658
+void pv_value_destroy(pv_value_t *val)
659
+{
660
+	if(val==0) return;
661
+	if(val->flags&PV_VAL_PKG) pkg_free(val->rs.s);
662
+	if(val->flags&PV_VAL_SHM) shm_free(val->rs.s);
663
+	memset(val, 0, sizeof(pv_value_t));
664
+}
665
+
666
+
667
+/********************************************************
668
+ * Transformations API
669
+ ********************************************************/
670
+
671
+/**
672
+ *
673
+ */
640 674
 static inline char* tr_get_class(str *in, char *p, str *tclass)
641 675
 {
642 676
 	tclass->s = p;
... ...
@@ -652,6 +857,9 @@ static inline char* tr_get_class(str *in, char *p, str *tclass)
652 652
 	return p;
653 653
 }
654 654
 
655
+/**
656
+ *
657
+ */
655 658
 static inline trans_t* tr_new()
656 659
 {
657 660
 	trans_t *t = NULL;
... ...
@@ -757,6 +965,25 @@ void tr_destroy(trans_t *t)
757 757
 	memset(t, 0, sizeof(trans_t));
758 758
 }
759 759
 
760
+int tr_exec(struct sip_msg *msg, trans_t *t, pv_value_t *v)
761
+{
762
+	int r;
763
+	trans_t *i;
764
+
765
+	if(t==NULL || v==NULL)
766
+	{
767
+		LM_DBG("invalid parameters\n");
768
+		return -1;
769
+	}
770
+	
771
+	for(i = t; i!=NULL; i=i->next)
772
+	{
773
+		r = (*i->trf)(msg, i->params, i->subtype, v);
774
+		if(r!=0)
775
+			return r;
776
+	}
777
+	return 0;
778
+}
760 779
 
761 780
 /*!
762 781
  * \brief Free allocated memory of transformation list
... ...
@@ -72,8 +72,8 @@
72 72
 
73 73
 enum _pv_type { 
74 74
 	PVT_NONE=0,           PVT_EMPTY,             PVT_NULL, 
75
-	PVT_MARKER,           PVT_AVP,               PVT_OTHER,
76
-	PVT_EXTRA /* keep it last */
75
+	PVT_MARKER,           PVT_AVP,               PVT_COLOR,
76
+	PVT_OTHER,            PVT_EXTRA /* keep it last */
77 77
 };
78 78
 
79 79
 typedef enum _pv_type pv_type_t;
... ...
@@ -248,6 +248,7 @@ typedef struct _tr_export {
248 248
 
249 249
 char* tr_lookup(str *in, trans_t **tr);
250 250
 tr_export_t* tr_lookup_class(str *tclass);
251
+int tr_exec(struct sip_msg *msg, trans_t *t, pv_value_t *v);
251 252
 
252 253
 #endif
253 254
 
... ...
@@ -164,6 +164,18 @@ static int register_module(unsigned ver, union module_exports_u* e,
164 164
 	mod->exports=e;
165 165
 	mod->next=modules;
166 166
 	modules=mod;
167
+
168
+	/* register module pseudo-variables */
169
+	if (ver==1 && e->v1.items) {
170
+		LM_DBG("register PV from: %s\n", e->c.name);
171
+		if (register_pvars_mod(e->c.name, e->v1.items)!=0) {
172
+			LM_ERR("failed to register pseudo-variables for module %s\n",
173
+				e->c.name);
174
+			pkg_free(mod);
175
+			return -1;
176
+		}
177
+	}
178
+
167 179
 	return 0;
168 180
 error:
169 181
 	return ret;