[sr-dev] git:master: sl: new function sl_forward_reply(...)

Daniel-Constantin Mierla miconda at gmail.com
Fri Jan 4 20:47:43 CET 2013


Module: sip-router
Branch: master
Commit: d01b11b0cbbbfb84ae3d10fb90c05aedf07c9ccc
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=d01b11b0cbbbfb84ae3d10fb90c05aedf07c9ccc

Author: Daniel-Constantin Mierla <miconda at gmail.com>
Committer: Daniel-Constantin Mierla <miconda at gmail.com>
Date:   Fri Jan  4 19:26:21 2013 +0100

sl: new function sl_forward_reply(...)

- forward the received reply fron configuration, before it would be done
  by the core. It has the option to change the status code and reason
  phrase
- the forwarding is statelessy, not affecting the tm states

---

 modules/sl/README               |   27 ++++++-
 modules/sl/doc/sl_functions.xml |   36 ++++++++++
 modules/sl/sl.c                 |  147 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 205 insertions(+), 5 deletions(-)

diff --git a/modules/sl/README b/modules/sl/README
index 9d5b29c..d15521a 100644
--- a/modules/sl/README
+++ b/modules/sl/README
@@ -19,6 +19,7 @@ Daniel-Constantin Mierla
    4. sl_send_reply usage
    5. send_reply usage
    6. sl_reply_error usage
+   7. send_reply usage
 
 1. Overview
 
@@ -92,8 +93,9 @@ modparam("sl", "bind_tm", 0)  # feature disabled
    3.1. sl_send_reply(code, reason)
    3.2. send_reply(code, reason)
    3.3. sl_reply_error()
+   3.4. sl_forward _reply([ code, [ reason ] ])
 
-3.1.  sl_send_reply(code, reason)
+3.1. sl_send_reply(code, reason)
 
    For the current request, a reply is sent back having the given code and
    text reason. The reply is sent stateless, totally independent of the
@@ -108,7 +110,7 @@ modparam("sl", "bind_tm", 0)  # feature disabled
 sl_send_reply("404", "Not found");
 ...
 
-3.2.  send_reply(code, reason)
+3.2. send_reply(code, reason)
 
    For the current request, a reply is sent back having the given code and
    text reason. The reply is sent stateful or stateless, depending of the
@@ -129,7 +131,7 @@ send_reply("404", "Not found");
 send_reply("403", "Invalid user - $fU");
 ...
 
-3.3.  sl_reply_error()
+3.3. sl_reply_error()
 
    Sends back an error reply describing the nature of the last internal
    error. Usually this function should be used after a script function
@@ -140,6 +142,25 @@ send_reply("403", "Invalid user - $fU");
 sl_reply_error();
 ...
 
+3.4. sl_forward _reply([ code, [ reason ] ])
+
+   Forward statelessy the current received SIP reply, with the option to
+   change the status code and reason text. The new code has to be in the
+   same class. The received reply is forwarded as well by core when the
+   config execution ended, unless it is dropped from config.
+
+   Meaning of the parameters is as follows:
+     * code - Status code.
+     * reason - Reason phrase.
+
+   This function can be used from ONREPLY_ROUTE.
+
+   Example 7. send_reply usage
+...
+if(status=="408")
+    sl_forward_reply("404", "Not found");
+...
+
 4. Statistics
 
    4.1. 1xx_replies
diff --git a/modules/sl/doc/sl_functions.xml b/modules/sl/doc/sl_functions.xml
index 63abcb6..bf58ce0 100644
--- a/modules/sl/doc/sl_functions.xml
+++ b/modules/sl/doc/sl_functions.xml
@@ -92,4 +92,40 @@ sl_reply_error();
 	    </programlisting>
 	</example>
     </section>
+
+	<section id="sl_forward_reply">
+		<title>
+		<function moreinfo="none">sl_forward _reply([ code, [ reason ] ])</function>
+		</title>
+		<para>
+		Forward statelessy the current received SIP reply, with the option to
+		change the status code and reason text. The new code has to be in the same
+		class. The received reply is forwarded as well by core when the config
+		execution ended, unless it is dropped from config.
+		</para>
+		<para>Meaning of the parameters is as follows:</para>
+		<itemizedlist>
+		<listitem>
+			<para><emphasis>code</emphasis> - Status code.
+			</para>
+		</listitem>
+		<listitem>
+			<para><emphasis>reason</emphasis> - Reason phrase.
+			</para>
+		</listitem>
+		</itemizedlist>
+		<para>
+			This function can be used from ONREPLY_ROUTE.
+		</para>
+		<example>
+		<title><function>send_reply</function> usage</title>
+		<programlisting format="linespecific">
+...
+if(status=="408")
+    sl_forward_reply("404", "Not found");
+...
+</programlisting>
+		</example>
+	</section>
+
 </section>
diff --git a/modules/sl/sl.c b/modules/sl/sl.c
index eedb953..6d05569 100644
--- a/modules/sl/sl.c
+++ b/modules/sl/sl.c
@@ -62,6 +62,8 @@
 #include "../../dprint.h"
 #include "../../error.h"
 #include "../../ut.h"
+#include "../../data_lump.h"
+#include "../../mod_fix.h"
 #include "../../script_cb.h"
 #include "../../mem/mem.h"
 
@@ -81,9 +83,12 @@ int _sl_filtered_ack_route = -1; /* default disabled */
 static int sl_bind_tm = 1;
 static struct tm_binds tmb;
 
-static int w_sl_send_reply(struct sip_msg* msg, char* str, char* str2);
+static int w_sl_send_reply(struct sip_msg* msg, char* str1, char* str2);
 static int w_send_reply(struct sip_msg* msg, char* str1, char* str2);
-static int w_sl_reply_error(struct sip_msg* msg, char* str, char* str2);
+static int w_sl_reply_error(struct sip_msg* msg, char* str1, char* str2);
+static int w_sl_forward_reply0(sip_msg_t* msg, char* str1, char* str2);
+static int w_sl_forward_reply1(sip_msg_t* msg, char* str1, char* str2);
+static int w_sl_forward_reply2(sip_msg_t* msg, char* str1, char* str2);
 static int bind_sl(sl_api_t* api);
 static int mod_init(void);
 static int child_init(int rank);
@@ -99,6 +104,12 @@ static cmd_export_t cmds[]={
 		REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
 	{"sl_reply_error", w_sl_reply_error,            0, 0,
 		REQUEST_ROUTE},
+	{"sl_forward_reply",  w_sl_forward_reply0,      0, 0,
+		ONREPLY_ROUTE},
+	{"sl_forward_reply",  w_sl_forward_reply1,      1, fixup_spve_all,
+		ONREPLY_ROUTE},
+	{"sl_forward_reply",  w_sl_forward_reply2,      2, fixup_spve_all,
+		ONREPLY_ROUTE},
 	{"bind_sl",        (cmd_function)bind_sl,       0, 0,              0},
 	{0,0,0,0,0}
 };
@@ -347,6 +358,138 @@ static int fixup_sl_reply(void** param, int param_no)
 	return 0;
 }
 
+/**
+ * @brief forward SIP reply statelessy with different code and reason text
+ */
+static int w_sl_forward_reply(sip_msg_t* msg, str* code, str* reason)
+{
+	char oldscode[3];
+	int oldncode;
+	int ret;
+	struct lump	*ldel = NULL;
+	struct lump	*ladd = NULL;
+	char *rbuf;
+
+	if(msg->first_line.type!=SIP_REPLY) {
+		LM_ERR("invalid SIP message type\n");
+		return -1;
+	}
+	if(code!=NULL) {
+		if(code->len!=3) {
+			LM_ERR("invalid reply code value %.*s\n", code->len, code->s);
+			return -1;
+		}
+		if(msg->first_line.u.reply.status.s[0]!=code->s[0]) {
+			LM_ERR("reply code class cannot be changed\n");
+			return -1;
+		}
+		if(code->s[1]<'0' || code->s[1]>'9'
+				|| code->s[2]<'0' || code->s[2]>'9') {
+			LM_ERR("invalid reply code value %.*s!\n", code->len, code->s);
+			return -1;
+		}
+	}
+	if(reason!=NULL && reason->len<=0) {
+		LM_ERR("invalid reply reason value\n");
+		return -1;
+	}
+	if(code!=NULL) {
+		/* backup old values */
+		oldscode[0] = msg->first_line.u.reply.status.s[0];
+		oldscode[1] = msg->first_line.u.reply.status.s[1];
+		oldscode[2] = msg->first_line.u.reply.status.s[2];
+		oldncode = msg->first_line.u.reply.statuscode;
+		/* update status code directly in msg buffer */
+		msg->first_line.u.reply.statuscode = (code->s[0]-'0')*100
+			+ (code->s[1]-'0')*10 + code->s[2]-'0';
+		msg->first_line.u.reply.status.s[0] = code->s[0];
+		msg->first_line.u.reply.status.s[1] = code->s[1];
+		msg->first_line.u.reply.status.s[2] = code->s[2];
+
+	}
+	if(reason!=NULL) {
+		ldel = del_lump(msg,
+					msg->first_line.u.reply.reason.s - msg->buf,
+					msg->first_line.u.reply.reason.len,
+					0);
+		if (ldel==NULL) {
+			LM_ERR("failed to add del lump\n");
+			ret = -1;
+			goto restore;
+		}
+		rbuf = (char *)pkg_malloc(reason->len);
+		if (rbuf==NULL) {
+			LM_ERR("not enough memory\n");
+			ret = -1;
+			goto restore;
+		}
+		memcpy(rbuf, reason->s, reason->len);
+		ladd = insert_new_lump_after(ldel, rbuf, reason->len, 0);
+		if (ladd==0) {
+			LOG(L_ERR, "failed to add reason lump: %.*s\n",
+				reason->len, reason->s);
+			pkg_free(rbuf);
+			ret = -1;
+			goto restore;
+		}
+	}
+	ret = forward_reply(msg);
+restore:
+	if(reason!=NULL) {
+		if(ldel!=NULL) {
+			remove_lump(msg, ldel);
+		}
+		if(ladd!=NULL) {
+			remove_lump(msg, ladd);
+		}
+	}
+	if(code!=NULL) {
+		msg->first_line.u.reply.statuscode = oldncode;
+		msg->first_line.u.reply.status.s[0] = oldscode[0];
+		msg->first_line.u.reply.status.s[1] = oldscode[1];
+		msg->first_line.u.reply.status.s[2] = oldscode[2];
+	}
+	return ret;
+}
+
+/**
+ * @brief forward SIP reply statelessy
+ */
+static int w_sl_forward_reply0(sip_msg_t* msg, char* str1, char* str2)
+{
+	return w_sl_forward_reply(msg, NULL, NULL);
+}
+
+/**
+ * @brief forward SIP reply statelessy with a new code
+ */
+static int w_sl_forward_reply1(sip_msg_t* msg, char* str1, char* str2)
+{
+	str code;
+	if(fixup_get_svalue(msg, (gparam_t*)str1, &code)<0) {
+		LM_ERR("cannot get the reply code parameter value\n");
+		return -1;
+	}
+	return w_sl_forward_reply(msg, &code, NULL);
+}
+
+/**
+ * @brief forward SIP reply statelessy with new code and reason text
+ */
+static int w_sl_forward_reply2(sip_msg_t* msg, char* str1, char* str2)
+{
+	str code;
+	str reason;
+	if(fixup_get_svalue(msg, (gparam_t*)str1, &code)<0) {
+		LM_ERR("cannot get the reply code parameter value\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_t*)str2, &reason)<0) {
+		LM_ERR("cannot get the reply reason parameter value\n");
+		return -1;
+	}
+	return w_sl_forward_reply(msg, &code, &reason);
+}
 
 /**
  * @brief bind functions to SL API structure




More information about the sr-dev mailing list