Parcourir la source

Merge pull request #2070 from kamailio/xavp_copy

pv: adding xavp_copy
Julien Chavanton il y a 6 ans
Parent
commit
7522699742
4 fichiers modifiés avec 117 ajouts et 3 suppressions
  1. 8 3
      src/core/xavp.c
  2. 1 0
      src/core/xavp.h
  3. 43 0
      src/modules/pv/doc/pv_admin.xml
  4. 65 0
      src/modules/pv/pv.c

+ 8 - 3
src/core/xavp.c

@@ -693,11 +693,16 @@ struct str_list *xavp_get_list_key_names(sr_xavp_t *xavp)
 	return result;
 }
 
+sr_xavp_t *xavp_clone_level_nodata(sr_xavp_t *xold)
+{
+	return xavp_clone_level_nodata_with_new_name(xold, &xold->name);
+}
+
 /**
  * clone the xavp without values that are custom data
  * - only one list level is cloned, other sublists are ignored
  */
-sr_xavp_t *xavp_clone_level_nodata(sr_xavp_t *xold)
+sr_xavp_t *xavp_clone_level_nodata_with_new_name(sr_xavp_t *xold, str *dst_name)
 {
 	sr_xavp_t *xnew = NULL;
 	sr_xavp_t *navp = NULL;
@@ -713,13 +718,13 @@ sr_xavp_t *xavp_clone_level_nodata(sr_xavp_t *xold)
 		LM_INFO("xavp value type is 'data' - ignoring in clone\n");
 		return NULL;
 	}
-	xnew = xavp_new_value(&xold->name, &xold->val);
+	xnew = xavp_new_value(dst_name, &xold->val);
 	if(xnew==NULL)
 	{
 		LM_ERR("cannot create cloned root xavp\n");
 		return NULL;
 	}
-	LM_DBG("cloned root xavp [%.*s]\n", xold->name.len, xold->name.s);
+	LM_DBG("cloned root xavp [%.*s] >> [%.*s]\n", xold->name.len, xold->name.s, dst_name->len, dst_name->s);
 
 	if(xold->val.type!=SR_XTYPE_XAVP)
 	{

+ 1 - 0
src/core/xavp.h

@@ -102,6 +102,7 @@ sr_xavp_t *xavp_extract(str *name, sr_xavp_t **list);
 void xavp_print_list(sr_xavp_t **head);
 
 sr_xavp_t *xavp_clone_level_nodata(sr_xavp_t *xold);
+sr_xavp_t *xavp_clone_level_nodata_with_new_name(sr_xavp_t *xold, str *dst_name);
 
 sr_xavp_t* xavp_get_child(str *rname, str *cname);
 sr_xavp_t* xavp_get_child_with_ival(str *rname, str *cname);

+ 43 - 0
src/modules/pv/doc/pv_admin.xml

@@ -261,6 +261,49 @@ if (typeof("$var(foo)", "str")) {
 if (not_empty("$var(foo)")) {
     append_hf("X-Foo: $var(foo)\r\n");
 }
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="pv.f.xavp_copy">
+			<title>
+				<function moreinfo="none">xavp_copy(source_name, source_index, destination_name)</function>
+			</title>
+			<para>
+				Copy one XAVP.
+			</para>
+			<para>
+				The parameters can be variables or strings.
+				First parameter is the source XAVP name.
+				Second parameter is the source XAVP stack index, use 0 to copy the last assigned XAVP.
+				Third parameter is the destination XAVP name, if found the XAVP will be appended else it will be created.
+			</para>
+			<para>
+			Function can be used from ANY ROUTE.
+			</para>
+			<example>
+				<title><function>xavp_copy</function> usage</title>
+				<programlisting format="linespecific">
+...
+# Using xavp_copy to reorder an existing xavp stack
+$xavp(a=&gt;x) = "a-0-x";
+$xavp(a[0]=&gt;y) = "a-0-y";
+$xavp(a=&gt;x) = "a-1-x";
+$xavp(a[0]=&gt;y) = "a-1-y";
+xinfo("$$xavp(a[0]) = [$xavp(a[0]=&gt;x)][$xavp(a[0]=&gt;y)]\n");
+xinfo("$$xavp(a[1]) = [$xavp(a[1]=&gt;x)][$xavp(a[1]=&gt;y)]\n");
+# reorder
+$var(source_index) = 1;
+$var(destination_name) = "b";
+xavp_copy("a", "$var(source_index)", "$var(destination_name)");
+xavp_copy("a", "0", "$var(destination_name)");
+xinfo("reordered: $$xavp(b[0]) = [$xavp(b[0]=&gt;x)][$xavp(b[0]=&gt;y)]\n");
+xinfo("reordered: $$xavp(b[1]) = [$xavp(b[1]=&gt;x)][$xavp(b[1]=&gt;y)]\n");
+# results in:
+# INFO: $xavp(a[0]) = [a-1-x][a-1-y]
+# INFO: $xavp(a[1]) = [a-0-x][a-0-y]
+# INFO: reordered: $xavp(b[0]) = [a-0-x][a-0-y]
+# INFO: reordered: $xavp(b[1]) = [a-1-x][a-1-y]
 ...
 				</programlisting>
 			</example>

+ 65 - 0
src/modules/pv/pv.c

@@ -535,6 +535,7 @@ static int pv_unset(struct sip_msg* msg, char* pvid, char *foo);
 static int is_int(struct sip_msg* msg, char* pvar, char* s2);
 static int pv_typeof(sip_msg_t *msg, char *pv, char *t);
 static int pv_not_empty(sip_msg_t *msg, char *pv, char *s2);
+static int w_xavp_copy(sip_msg_t *msg, char *src_name, char *src_idx, char *dst_name);
 static int w_xavp_params_explode(sip_msg_t *msg, char *pparams, char *pxname);
 static int w_xavp_params_implode(sip_msg_t *msg, char *pxname, char *pvname);
 static int w_xavp_child_seti(sip_msg_t *msg, char *prname, char *pcname,
@@ -549,6 +550,7 @@ static int w_sbranch_reset(sip_msg_t *msg, char p1, char *p2);
 static int w_var_to_xavp(sip_msg_t *msg, char *p1, char *p2);
 static int w_xavp_to_var(sip_msg_t *msg, char *p1);
 
+int pv_xavp_copy_fixup(void** param, int param_no);
 int pv_evalx_fixup(void** param, int param_no);
 int w_pv_evalx(struct sip_msg *msg, char *dst, str *fmt);
 
@@ -580,6 +582,8 @@ static cmd_export_t cmds[]={
 	{"xavp_params_explode", (cmd_function)w_xavp_params_explode,
 		2, fixup_spve_spve, fixup_free_spve_spve,
 		ANY_ROUTE},
+	{"xavp_copy", (cmd_function)w_xavp_copy, 3, pv_xavp_copy_fixup, 0,
+		ANY_ROUTE},
 	{"xavp_params_implode", (cmd_function)w_xavp_params_implode,
 		2, fixup_spve_str, fixup_free_spve_str,
 		ANY_ROUTE},
@@ -811,6 +815,57 @@ static int ki_xavp_print(sip_msg_t* msg)
 	return 1;
 }
 
+/**
+ *
+ */
+static int w_xavp_copy(sip_msg_t *msg, char *_src_name, char *_src_idx, char *_dst_name)
+{
+	str src_name;
+	int src_idx;
+	str dst_name;
+	if(get_str_fparam(&src_name, msg, (gparam_p)_src_name) != 0) {
+		LM_ERR("xavp_copy: missing source\n");
+		return -1;
+	}
+	if(get_str_fparam(&dst_name, msg, (gparam_p)_dst_name) != 0) {
+		LM_ERR("xavp_copy: missing destination\n");
+		return -1;
+	}
+	if(get_int_fparam(&src_idx, msg, (gparam_t*)_src_idx)<0) {
+		LM_ERR("failed to get the src_idx value\n");
+		return -1;
+	}
+	sr_xavp_t *src_xavp = xavp_get_by_index(&src_name, src_idx, NULL);
+	if(!src_xavp) {
+		LM_ERR("xavp_copy: missing can not find source xavp [%.*s]\n", src_name.len, src_name.s);
+		return -1;
+	}
+	// Check if destination exist, if it does we will append, similar to XAVP assigment
+	sr_xavp_t *dst_xavp = xavp_get(&dst_name, NULL);
+	sr_xavp_t *new_xavp = xavp_clone_level_nodata_with_new_name(src_xavp, &dst_name);
+	if (!new_xavp) {
+		LM_ERR("error cloning xavp\n");
+		return -1;
+	}
+	if (!dst_xavp) {
+		LM_DBG("xavp_copy(new): $xavp(%.*s[%d]) >> $xavp(%.*s)\n", src_name.len, src_name.s, src_idx, dst_name.len, dst_name.s);
+		if(xavp_add(new_xavp, NULL)<0) {
+			LM_ERR("error adding new xavp\n");
+			xavp_destroy_list(&dst_xavp);
+			return -1;
+		}
+	} else {
+		LM_DBG("xavp_copy(append): $xavp(%.*s[%d]) >> $xavp(%.*s)\n", src_name.len, src_name.s, src_idx, dst_name.len, dst_name.s);
+		if(xavp_add_last(new_xavp, &dst_xavp)<0) {
+			LM_ERR("error appending new xavp\n");
+			xavp_destroy_list(&dst_xavp);
+			return -1;
+		}
+	}
+	return 1;
+}
+
+
 /**
  *
  */
@@ -1365,6 +1420,16 @@ static int ki_sbranch_reset(sip_msg_t *msg)
 	return 1;
 }
 
+int pv_xavp_copy_fixup(void **param, int param_no)
+{
+	if(param_no == 1 || param_no == 3)
+		return fixup_var_str_12(param, param_no);
+	if (param_no == 2)
+		return fixup_var_int_12(param, param_no);
+	LM_ERR("invalid parameter count [%d]\n", param_no);
+	return -1;
+}
+
 int pv_evalx_fixup(void** param, int param_no)
 {
 	pv_spec_t *spec=NULL;