浏览代码

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
Daniel-Constantin Mierla 12 年之前
父节点
当前提交
d01b11b0cb
共有 3 个文件被更改,包括 205 次插入5 次删除
  1. 24 3
      modules/sl/README
  2. 36 0
      modules/sl/doc/sl_functions.xml
  3. 145 2
      modules/sl/sl.c

+ 24 - 3
modules/sl/README

@@ -19,6 +19,7 @@ Daniel-Constantin Mierla
    4. sl_send_reply usage
    4. sl_send_reply usage
    5. send_reply usage
    5. send_reply usage
    6. sl_reply_error usage
    6. sl_reply_error usage
+   7. send_reply usage
 
 
 1. Overview
 1. Overview
 
 
@@ -92,8 +93,9 @@ modparam("sl", "bind_tm", 0)  # feature disabled
    3.1. sl_send_reply(code, reason)
    3.1. sl_send_reply(code, reason)
    3.2. send_reply(code, reason)
    3.2. send_reply(code, reason)
    3.3. sl_reply_error()
    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
    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
    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");
 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
    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
    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");
 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
    Sends back an error reply describing the nature of the last internal
    error. Usually this function should be used after a script function
    error. Usually this function should be used after a script function
@@ -140,6 +142,25 @@ send_reply("403", "Invalid user - $fU");
 sl_reply_error();
 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. Statistics
 
 
    4.1. 1xx_replies
    4.1. 1xx_replies

+ 36 - 0
modules/sl/doc/sl_functions.xml

@@ -92,4 +92,40 @@ sl_reply_error();
 	    </programlisting>
 	    </programlisting>
 	</example>
 	</example>
     </section>
     </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>
 </section>

+ 145 - 2
modules/sl/sl.c

@@ -62,6 +62,8 @@
 #include "../../dprint.h"
 #include "../../dprint.h"
 #include "../../error.h"
 #include "../../error.h"
 #include "../../ut.h"
 #include "../../ut.h"
+#include "../../data_lump.h"
+#include "../../mod_fix.h"
 #include "../../script_cb.h"
 #include "../../script_cb.h"
 #include "../../mem/mem.h"
 #include "../../mem/mem.h"
 
 
@@ -81,9 +83,12 @@ int _sl_filtered_ack_route = -1; /* default disabled */
 static int sl_bind_tm = 1;
 static int sl_bind_tm = 1;
 static struct tm_binds tmb;
 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_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 bind_sl(sl_api_t* api);
 static int mod_init(void);
 static int mod_init(void);
 static int child_init(int rank);
 static int child_init(int rank);
@@ -99,6 +104,12 @@ static cmd_export_t cmds[]={
 		REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
 		REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
 	{"sl_reply_error", w_sl_reply_error,            0, 0,
 	{"sl_reply_error", w_sl_reply_error,            0, 0,
 		REQUEST_ROUTE},
 		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},
 	{"bind_sl",        (cmd_function)bind_sl,       0, 0,              0},
 	{0,0,0,0,0}
 	{0,0,0,0,0}
 };
 };
@@ -347,6 +358,138 @@ static int fixup_sl_reply(void** param, int param_no)
 	return 0;
 	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
  * @brief bind functions to SL API structure