From: Victor Seva <vseva@sipwise.com>
Date: Fri, 6 May 2022 13:30:01 +0200
Subject: [PATCH] dialog: dlg_get_var(ci, ft, tt, key, dst_var)

---
 src/modules/dialog/dialog.c             | 113 +++++++++++++++++++++++++++++++-
 src/modules/dialog/doc/dialog_admin.xml |  48 ++++++++++++++
 2 files changed, 160 insertions(+), 1 deletion(-)

diff --git a/src/modules/dialog/dialog.c b/src/modules/dialog/dialog.c
index 9f9f647..25584b5 100644
--- a/src/modules/dialog/dialog.c
+++ b/src/modules/dialog/dialog.c
@@ -194,7 +194,9 @@ static int w_is_known_dlg(struct sip_msg *);
 static int w_dlg_set_ruri(sip_msg_t *, char *, char *);
 static int w_dlg_db_load_callid(sip_msg_t *msg, char *ci, char *p2);
 static int w_dlg_db_load_extra(sip_msg_t *msg, char *p1, char *p2);
-
+static int fixup_dlg_get_var(void** param, int param_no);
+static int fixup_dlg_get_var_free(void** param, int param_no);
+static int w_dlg_get_var(struct sip_msg*, char*, char*, char*, char*, char*);
 static int w_dlg_remote_profile(sip_msg_t *msg, char *cmd, char *pname,
 		char *pval, char *puid, char *expires);
 static int fixup_dlg_remote_profile(void** param, int param_no);
@@ -256,6 +258,8 @@ static cmd_export_t cmds[]={
 			0, ANY_ROUTE },
 	{"dlg_db_load_extra", (cmd_function)w_dlg_db_load_extra, 0, 0,
 			0, ANY_ROUTE },
+	{"dlg_get_var",(cmd_function)w_dlg_get_var, 5, fixup_dlg_get_var,
+			fixup_dlg_get_var_free, ANY_ROUTE },
 
 	{"load_dlg",  (cmd_function)load_dlg,   0, 0, 0, 0},
 	{0,0,0,0,0,0}
@@ -1505,6 +1509,108 @@ static int fixup_dlg_bridge(void** param, int param_no)
 	return 0;
 }
 
+static str *ki_dlg_get_var(sip_msg_t *msg, str *sc, str *sf, str *st, str *key)
+{
+	dlg_cell_t *dlg = NULL;
+	unsigned int dir = 0;
+	str *val = NULL;
+
+	if(sc==NULL || sc->s==NULL || sc->len == 0) {
+		LM_ERR("invalid Call-ID parameter\n");
+		return val;
+	}
+	if(sf==NULL || sf->s==NULL || sf->len == 0) {
+		LM_ERR("invalid From tag parameter\n");
+		return val;
+	}
+	if(st==NULL || st->s==NULL || st->len == 0) {
+		LM_ERR("invalid To tag parameter\n");
+		return val;
+	}
+
+	dlg = get_dlg(sc, sf, st, &dir);
+	if(dlg==NULL)
+		return val;
+	val = get_dlg_variable(dlg, key);
+	dlg_release(dlg);
+	return val;
+}
+
+static int w_dlg_get_var(struct sip_msg *msg, char *ci, char *ft, char *tt, char *key, char *pv)
+{
+	str sc = STR_NULL;
+	str sf = STR_NULL;
+	str st = STR_NULL;
+	str k = STR_NULL;
+	str *val = NULL;
+	pv_value_t dst_val;
+	pv_spec_t* dst_pv;
+
+	if(ci==0 || ft==0 || tt==0)
+	{
+		LM_ERR("invalid parameters\n");
+		return -1;
+	}
+
+	if(fixup_get_svalue(msg, (gparam_p)ci, &sc)!=0)
+	{
+		LM_ERR("unable to get Call-ID\n");
+		return -1;
+	}
+
+	if(fixup_get_svalue(msg, (gparam_p)ft, &sf)!=0)
+	{
+		LM_ERR("unable to get From tag\n");
+		return -1;
+	}
+
+	if(fixup_get_svalue(msg, (gparam_p)tt, &st)!=0)
+	{
+		LM_ERR("unable to get To Tag\n");
+		return -1;
+	}
+	if(st.s==NULL || st.len == 0)
+	{
+		LM_ERR("invalid To tag parameter\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_p)key, &k)!=0)
+	{
+		LM_ERR("unable to get key name\n");
+		return -1;
+	}
+	dst_pv = (pv_spec_t *)pv;
+	val = ki_dlg_get_var(msg, &sc, &sf, &st, &k);
+	if(val) {
+		memset(&dst_val, 0, sizeof(pv_value_t));
+		dst_val.flags |= PV_VAL_STR;
+		dst_val.rs.s = val->s;
+		dst_val.rs.len = val->len;
+		if(pv_set_spec_value(msg, dst_pv, 0, &dst_val) != 0) return -1;
+	} else {
+		if(pv_get_null(msg, NULL, &dst_val) != 0) return -1;
+	}
+	return 1;
+}
+
+static int fixup_dlg_get_var(void** param, int param_no)
+{
+	if(param_no>=1 && param_no<=4)
+		return fixup_spve_null(param, 1);
+	if(param_no==5)
+		return fixup_pvar_all(param, 1);
+	return 0;
+}
+
+static int fixup_dlg_get_var_free(void** param, int param_no)
+{
+	if (param_no <= 4)
+		return fixup_free_spve_null(param, 1);
+	if (param_no == 5)
+		return fixup_free_pvar_all(param, 1);
+	return -1;
+}
+
 static int ki_dlg_get(sip_msg_t *msg, str *sc, str *sf, str *st)
 {
 	dlg_cell_t *dlg = NULL;
@@ -2090,6 +2196,11 @@ static sr_kemi_t sr_kemi_dialog_exports[] = {
 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
 	},
+	{ str_init("dialog"), str_init("dlg_get_var"),
+		SR_KEMIP_STR, ki_dlg_get_var,
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
+			SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE }
+	},
 	{ str_init("dialog"), str_init("set_dlg_profile_static"),
 		SR_KEMIP_INT, ki_set_dlg_profile_static,
 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
diff --git a/src/modules/dialog/doc/dialog_admin.xml b/src/modules/dialog/doc/dialog_admin.xml
index 51faa16..9f20125 100644
--- a/src/modules/dialog/doc/dialog_admin.xml
+++ b/src/modules/dialog/doc/dialog_admin.xml
@@ -2103,6 +2103,54 @@ if(dlg_get("abcdef", "123", "456"))
 		</example>
 	</section>
 
+	<section id="dialog.f.dlg_get_var">
+		<title>
+		<function moreinfo="none">dlg_get_var(callid, ftag, ttag, name, dst)</function>
+		</title>
+		<para>
+			Get dlg_var of another dialog value based on Call-ID, From-Tag and To-Tag
+			parameters.
+		</para>
+		<para>Meaning of the parameters is as follows:</para>
+		<itemizedlist>
+		<listitem>
+			<para><emphasis>callid</emphasis> - SIP call-id.
+			</para>
+		</listitem>
+		<listitem>
+			<para><emphasis>ftag</emphasis> - SIP From tag.
+			</para>
+		</listitem>
+		<listitem>
+			<para><emphasis>ttag</emphasis> - SIP To tag.
+			</para>
+		</listitem>
+		<listitem>
+			<para><emphasis>name</emphasis> - key name of the $dlg_var.
+			</para>
+		</listitem>
+		<listitem>
+			<para><emphasis>dst</emphasis> - pv to store the value of $dlg_var(name).
+			</para>
+		</listitem>
+		</itemizedlist>
+		<para>
+		This function can be used from BRANCH_ROUTE,
+			REQUEST_ROUTE, ONREPLY_ROUTE and FAILURE_ROUTE.
+		</para>
+		<example>
+		<title><function>dlg_get_var</function> usage</title>
+		<programlisting format="linespecific">
+...
+if(dlg_get_var("$var(ci)", "$var(ft)", "456", "test", "$var(tmp)"))
+{
+	xdbg("$$dlg_var(test):$var(tmp)\n");
+}
+...
+</programlisting>
+		</example>
+	</section>
+
 	<section id="dialog.f.is_known_dlg">
 		<title>
 		<function moreinfo="none">is_known_dlg()</function>
