Browse code

Merge commit 'origin/daniel/pv' into fixups

* commit 'origin/daniel/pv':
more PV API integration

Andrei Pelinescu-Onciul authored on 21/11/2008 10:47:56
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 302
 }
302 303
 
303 304
 static str pv_str_empty  = { "", 0 };
305
+static str pv_str_null   = { "<null>", 6 };
304 306
 int pv_get_null(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
305 307
 {
306 308
 	if(res==NULL)
... ...
@@ -628,6 +630,175 @@ error:
628 630
 
629 631
 } /* end: pv_parse_spec */
630 632
 
633
+/**
634
+ *
635
+ */
636
+int pv_parse_format(str *in, pv_elem_p *el)
637
+{
638
+	char *p, *p0;
639
+	int n = 0;
640
+	pv_elem_p e, e0;
641
+	str s;
642
+
643
+	if(in==NULL || in->s==NULL || el==NULL)
644
+		return -1;
645
+
646
+	/*LM_DBG("parsing [%.*s]\n", in->len, in->s);*/
647
+	
648
+	if(in->len == 0)
649
+	{
650
+		*el = pkg_malloc(sizeof(pv_elem_t));
651
+		if(*el == NULL)
652
+			goto error;
653
+		memset(*el, 0, sizeof(pv_elem_t));
654
+		(*el)->text = *in;
655
+		return 0;
656
+	}
657
+
658
+	p = in->s;
659
+	*el = NULL;
660
+	e = e0 = NULL;
661
+
662
+	while(is_in_str(p,in))
663
+	{
664
+		e0 = e;
665
+		e = pkg_malloc(sizeof(pv_elem_t));
666
+		if(!e)
667
+			goto error;
668
+		memset(e, 0, sizeof(pv_elem_t));
669
+		n++;
670
+		if(*el == NULL)
671
+			*el = e;
672
+		if(e0)
673
+			e0->next = e;
674
+	
675
+		e->text.s = p;
676
+		while(is_in_str(p,in) && *p!=PV_MARKER)
677
+			p++;
678
+		e->text.len = p - e->text.s;
679
+		
680
+		if(*p == '\0' || !is_in_str(p,in))
681
+			break;
682
+		s.s = p;
683
+		s.len = in->s+in->len-p;
684
+		p0 = pv_parse_spec(&s, &e->spec);
685
+		
686
+		if(p0==NULL)
687
+			goto error;
688
+		if(*p0 == '\0')
689
+			break;
690
+		p = p0;
691
+	}
692
+	/*LM_DBG("format parsed OK: [%d] items\n", n);*/
693
+
694
+	if(*el == NULL)
695
+		return -1;
696
+
697
+	return 0;
698
+
699
+error:
700
+	pv_elem_free_all(*el);
701
+	*el = NULL;
702
+	return -1;
703
+}
704
+
705
+int pv_get_spec_value(struct sip_msg* msg, pv_spec_p sp, pv_value_t *value)
706
+{
707
+	int ret = 0;
708
+
709
+	if(msg==NULL || sp==NULL || sp->getf==NULL || value==NULL
710
+			|| sp->type==PVT_NONE)
711
+	{
712
+		LM_ERR("bad parameters\n");
713
+		return -1;
714
+	}
715
+	
716
+	memset(value, 0, sizeof(pv_value_t));
717
+
718
+	ret = (*sp->getf)(msg, &(sp->pvp), value);
719
+	if(ret!=0)
720
+		return ret;
721
+	if(sp->trans)
722
+		return tr_exec(msg, (trans_t*)sp->trans, value);
723
+	return ret;
724
+}
725
+
726
+/**
727
+ *
728
+ */
729
+int pv_printf(struct sip_msg* msg, pv_elem_p list, char *buf, int *len)
730
+{
731
+	int n, h;
732
+	pv_value_t tok;
733
+	pv_elem_p it;
734
+	char *cur;
735
+	
736
+	if(msg==NULL || list==NULL || buf==NULL || len==NULL)
737
+		return -1;
738
+
739
+	if(*len <= 0)
740
+		return -1;
741
+
742
+	*buf = '\0';
743
+	cur = buf;
744
+	
745
+	h = 0;
746
+	n = 0;
747
+	for (it=list; it; it=it->next)
748
+	{
749
+		/* put the text */
750
+		if(it->text.s && it->text.len>0)
751
+		{
752
+			if(n+it->text.len < *len)
753
+			{
754
+				memcpy(cur, it->text.s, it->text.len);
755
+				n += it->text.len;
756
+				cur += it->text.len;
757
+			} else {
758
+				LM_ERR("no more space for text [%d]\n", it->text.len);
759
+				goto overflow;
760
+			}
761
+		}
762
+		/* put the value of the specifier */
763
+		if(it->spec.type!=PVT_NONE
764
+				&& pv_get_spec_value(msg, &(it->spec), &tok)==0)
765
+		{
766
+			if(tok.flags&PV_VAL_NULL)
767
+				tok.rs = pv_str_null;
768
+			if(n+tok.rs.len < *len)
769
+			{
770
+				if(tok.rs.len>0)
771
+				{
772
+					memcpy(cur, tok.rs.s, tok.rs.len);
773
+					n += tok.rs.len;
774
+					cur += tok.rs.len;
775
+				}
776
+			} else {
777
+				LM_ERR("no more space for spec value\n");
778
+				goto overflow;
779
+			}
780
+		}
781
+	}
782
+
783
+	goto done;
784
+	
785
+overflow:
786
+	LM_ERR("buffer overflow -- increase the buffer size...\n");
787
+	return -1;
788
+
789
+done:
790
+#ifdef EXTRA_DEBUG
791
+	LM_DBG("final buffer length %d\n", n);
792
+#endif
793
+	*cur = '\0';
794
+	*len = n;
795
+	return 0;
796
+}
797
+
798
+
799
+/**
800
+ *
801
+ */
631 802
 void pv_spec_free(pv_spec_t *spec)
632 803
 {
633 804
 	if(spec==0) return;
... ...
@@ -637,6 +808,40 @@ void pv_spec_free(pv_spec_t *spec)
637 808
 	pkg_free(spec);
638 809
 }
639 810
 
811
+/**
812
+ *
813
+ */
814
+int pv_elem_free_all(pv_elem_p log)
815
+{
816
+	pv_elem_p t;
817
+	while(log)
818
+	{
819
+		t = log;
820
+		log = log->next;
821
+		pkg_free(t);
822
+	}
823
+	return 0;
824
+}
825
+
826
+/**
827
+ *
828
+ */
829
+void pv_value_destroy(pv_value_t *val)
830
+{
831
+	if(val==0) return;
832
+	if(val->flags&PV_VAL_PKG) pkg_free(val->rs.s);
833
+	if(val->flags&PV_VAL_SHM) shm_free(val->rs.s);
834
+	memset(val, 0, sizeof(pv_value_t));
835
+}
836
+
837
+
838
+/********************************************************
839
+ * Transformations API
840
+ ********************************************************/
841
+
842
+/**
843
+ *
844
+ */
640 845
 static inline char* tr_get_class(str *in, char *p, str *tclass)
641 846
 {
642 847
 	tclass->s = p;
... ...
@@ -652,6 +857,9 @@ static inline char* tr_get_class(str *in, char *p, str *tclass)
652 857
 	return p;
653 858
 }
654 859
 
860
+/**
861
+ *
862
+ */
655 863
 static inline trans_t* tr_new()
656 864
 {
657 865
 	trans_t *t = NULL;
... ...
@@ -757,6 +965,25 @@ void tr_destroy(trans_t *t)
757 965
 	memset(t, 0, sizeof(trans_t));
758 966
 }
759 967
 
968
+int tr_exec(struct sip_msg *msg, trans_t *t, pv_value_t *v)
969
+{
970
+	int r;
971
+	trans_t *i;
972
+
973
+	if(t==NULL || v==NULL)
974
+	{
975
+		LM_DBG("invalid parameters\n");
976
+		return -1;
977
+	}
978
+	
979
+	for(i = t; i!=NULL; i=i->next)
980
+	{
981
+		r = (*i->trf)(msg, i->params, i->subtype, v);
982
+		if(r!=0)
983
+			return r;
984
+	}
985
+	return 0;
986
+}
760 987
 
761 988
 /*!
762 989
  * \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;