[sr-dev] git:master: xmlrpc: allow chaining with xhttp module

Daniel-Constantin Mierla miconda at gmail.com
Wed Sep 8 11:35:36 CEST 2010


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

Author: Daniel-Constantin Mierla <miconda at gmail.com>
Committer: Daniel-Constantin Mierla <miconda at gmail.com>
Date:   Wed Sep  8 11:31:31 2010 +0200

xmlrpc: allow chaining with xhttp module

- the module was intercepting all HTTP module, without a nice way to
  dispach HTTP traffic between this module and xhttp
- added new parameters that can select which HTTP requests to be handled
  by xmlrpc based on URL regexp matches
  - url_skip - if the regexp is matched, then xmlrpc will not handle the
	request
  - url_match - if the regexp is matched, then xmlrpc will handle the
	request
- url_skip is checked first
- default values are NULL, which means matching all HTTP requests
  (default behaviour so far)

---

 modules/xmlrpc/README         |   32 +++++++++-
 modules/xmlrpc/doc/params.xml |   42 +++++++++++++
 modules/xmlrpc/xmlrpc.c       |  137 ++++++++++++++++++++++++++++-------------
 3 files changed, 167 insertions(+), 44 deletions(-)

diff --git a/modules/xmlrpc/README b/modules/xmlrpc/README
index 7a7b6f7..7d6cba4 100644
--- a/modules/xmlrpc/README
+++ b/modules/xmlrpc/README
@@ -25,6 +25,8 @@ Jan Janak
         1.5.3. escape_cr (integer)
         1.5.4. double_lf_to_crlf (integer)
         1.5.5. mode (integer)
+        1.5.6. url_skip (str)
+        1.5.7. url_match (str)
 
    1.6. Functions
 
@@ -578,6 +580,32 @@ modparam("xmlrpc", "double_lf_to_crlf", 1)
    Example 6. Set the mode parameter
 modparam("xmlrpc", "mode", 1)
 
+1.5.6. url_skip (str)
+
+   Regular expression to match the HTPP URL. If there is match, then
+   xmlrpc route is not executed.
+
+   Default value is null (don't skip).
+
+   Example 7. Set url_skip parameter
+...
+modparam("xhttp", "url_skip", "^/sip")
+...
+
+1.5.7. url_match (str)
+
+   Regular expression to match the HTPP URL. If there is no match, then
+   xmlrpc route is not executed. This check is done after url_skip, so if
+   both url_skip and url_match would match then the xmlrpc route is not
+   executed (url_skip has higher priority).
+
+   Default value is null (match everything).
+
+   Example 8. Set url_match parameter
+...
+modparam("xhttp", "url_match", "^/RPC2")
+...
+
 1.6. Functions
 
    Revision History
@@ -599,7 +627,7 @@ modparam("xmlrpc", "mode", 1)
    function with matching name. If such a function is found then
    dispatch_rpc() will pass control to the function to handle the request.
 
-   Example 7. dispatch_rpc usage
+   Example 9. dispatch_rpc usage
 #...
 modparam("xmlrpc", "route", "XMLRPC");
 #...
@@ -615,7 +643,7 @@ route[XMLRPC]{
    This function can be called from the config script to directly generate
    an XML-RPC reply.
 
-   Example 8. xmlrpc_reply usage
+   Example 10. xmlrpc_reply usage
 #...
 modparam("xmlrpc", "route", "XMLRPC");
 #...
diff --git a/modules/xmlrpc/doc/params.xml b/modules/xmlrpc/doc/params.xml
index 67e7a5f..5cd120a 100644
--- a/modules/xmlrpc/doc/params.xml
+++ b/modules/xmlrpc/doc/params.xml
@@ -134,6 +134,48 @@ modparam("xmlrpc", "mode", 1)
 		</programlisting>
 	</example>
 	</section>
+	<section>
+		<title><varname>url_skip</varname> (str)</title>
+		<para>
+			Regular expression to match the HTPP URL. If there is match,
+			then xmlrpc route is not executed.
+		</para>
+		<para>
+		<emphasis>
+			Default value is null (don't skip).
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>url_skip</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("xhttp", "url_skip", "^/sip")
+...
+</programlisting>
+		</example>
+	</section>
+	<section>
+		<title><varname>url_match</varname> (str)</title>
+		<para>
+			Regular expression to match the HTPP URL. If there is no match,
+			then xmlrpc route is not executed. This check is done after
+			url_skip, so if both url_skip and url_match would match then
+			the xmlrpc route is not executed (url_skip has higher priority).
+		</para>
+		<para>
+		<emphasis>
+			Default value is null (match everything).
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>url_match</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("xhttp", "url_match", "^/RPC2")
+...
+</programlisting>
+		</example>
+	</section>
 
 	<!--
 	Obsolete (hardwired on in the rpc core functions, cannot  be turned off) 
diff --git a/modules/xmlrpc/xmlrpc.c b/modules/xmlrpc/xmlrpc.c
index b4cee98..90dd397 100644
--- a/modules/xmlrpc/xmlrpc.c
+++ b/modules/xmlrpc/xmlrpc.c
@@ -400,6 +400,12 @@ static int lflf2crlf=0; /* default off */
 /* do not register for non-sip requests */
 static int xmlrpc_mode = 0;
 
+static char* xmlrpc_url_match = NULL;
+static regex_t xmlrpc_url_match_regexp;
+static char* xmlrpc_url_skip = NULL;
+static regex_t xmlrpc_url_skip_regexp;
+
+
 /*
  * Exported functions
  */
@@ -414,11 +420,13 @@ static cmd_export_t cmds[] = {
  * Exported parameters
  */
 static param_export_t params[] = {
-	{"route", PARAM_STRING, &xmlrpc_route},
-	{"autoconversion", PARAM_INT, &autoconvert},
-	{"escape_cr", PARAM_INT, &escape_cr},
-	{"double_lf_to_crlf", PARAM_INT, &lflf2crlf},
-	{"mode", PARAM_INT, &xmlrpc_mode},
+	{"route",             PARAM_STRING, &xmlrpc_route},
+	{"autoconversion",    PARAM_INT,    &autoconvert},
+	{"escape_cr",         PARAM_INT,    &escape_cr},
+	{"double_lf_to_crlf", PARAM_INT,    &lflf2crlf},
+	{"mode",              PARAM_INT,    &xmlrpc_mode},
+	{"url_match",         PARAM_STRING, &xmlrpc_url_match},
+	{"url_skip",          PARAM_STRING, &xmlrpc_url_skip},
 	{0, 0, 0}
 };
 
@@ -2160,50 +2168,78 @@ static int process_xmlrpc(sip_msg_t* msg)
 	int fake_msg_len;
 	unsigned char* method;
 	unsigned int method_len, n_method;
+	regmatch_t pmatch;
+	char c;
 	
 	ret=NONSIP_MSG_DROP;
-	if (IS_HTTP(msg)) {
-		method = (unsigned char*)msg->first_line.u.request.method.s;
-		method_len = msg->first_line.u.request.method.len;
-		/* first line is always > 4, so it's always safe to try to read the
-		 * 1st 4 bytes from method, even if method is shorter*/
-		n_method = method[0] + (method[1] << 8) + (method[2] << 16) + 
+	if (IS_HTTP(msg))
+		return NONSIP_MSG_PASS;
+
+	if(xmlrpc_url_skip!=NULL || xmlrpc_url_match!=NULL)
+	{
+		c = msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len];
+		msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
+			= '\0';
+		if (xmlrpc_url_skip!=NULL &&
+			regexec(&xmlrpc_url_skip_regexp, msg->first_line.u.request.uri.s,
+					1, &pmatch, 0)==0)
+		{
+			LM_DBG("URL matched skip re\n");
+			msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
+				= c;
+			return NONSIP_MSG_PASS;
+		}
+		if (xmlrpc_url_match!=NULL &&
+			regexec(&xmlrpc_url_match_regexp, msg->first_line.u.request.uri.s,
+					1, &pmatch, 0)!=0)
+		{
+			LM_DBG("URL not matched\n");
+			msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
+				= c;
+			return NONSIP_MSG_PASS;
+		}
+		msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len] = c;
+	}
+
+	method = (unsigned char*)msg->first_line.u.request.method.s;
+	method_len = msg->first_line.u.request.method.len;
+	/* first line is always > 4, so it's always safe to try to read the
+	 * 1st 4 bytes from method, even if method is shorter*/
+	n_method = method[0] + (method[1] << 8) + (method[2] << 16) +
 			(method[3] << 24);
-		n_method |= 0x20202020;
-		n_method &= ((method_len < 4) * (1U << method_len * 8) - 1);
-		/* accept only GET or POST */
-		if ((n_method == N_HTTP_GET) || 
+	n_method |= 0x20202020;
+	n_method &= ((method_len < 4) * (1U << method_len * 8) - 1);
+	/* accept only GET or POST */
+	if ((n_method == N_HTTP_GET) ||
 			((n_method == N_HTTP_POST) && (method_len == HTTP_POST_LEN))) {
-			if (msg->via1 == 0){
-				/* create a fake sip message */
-				fake_msg = http_xmlrpc2sip(msg, &fake_msg_len);
-				if (fake_msg == 0) {
-					ERR("xmlrpc: out of memory\n");
-					ret=NONSIP_MSG_ERROR;
-				} else {
-					/* send it */
-					DBG("new fake xml msg created (%d bytes):\n<%.*s>\n",
-						fake_msg_len, fake_msg_len, fake_msg);
-					if (em_receive_request(msg, fake_msg, fake_msg_len)<0)
-						ret=NONSIP_MSG_ERROR;
-					pkg_free(fake_msg);
-				}
-				return ret; /* we "ate" the message, 
-										   stop processing */
-			} else { /* the message has a via */
-				DBG("http xml msg unchanged (%d bytes):\n<%.*s>\n",
-					msg->len, msg->len, msg->buf);
-				if (em_receive_request(msg, 0, 0)<0)
+		if (msg->via1 == 0){
+			/* create a fake sip message */
+			fake_msg = http_xmlrpc2sip(msg, &fake_msg_len);
+			if (fake_msg == 0) {
+				ERR("xmlrpc: out of memory\n");
+				ret=NONSIP_MSG_ERROR;
+			} else {
+			/* send it */
+				DBG("new fake xml msg created (%d bytes):\n<%.*s>\n",
+					fake_msg_len, fake_msg_len, fake_msg);
+				if (em_receive_request(msg, fake_msg, fake_msg_len)<0)
 					ret=NONSIP_MSG_ERROR;
-				return ret;
+				pkg_free(fake_msg);
 			}
-		} else {
-			ERR("xmlrpc: bad HTTP request method: \"%.*s\"\n",
-				msg->first_line.u.request.method.len,
-				msg->first_line.u.request.method.s);
-			/* the message was for us, but it is an error */
-			return NONSIP_MSG_ERROR; 
+			return ret; /* we "ate" the message, stop processing */
+		} else { /* the message has a via */
+			DBG("http xml msg unchanged (%d bytes):\n<%.*s>\n",
+				msg->len, msg->len, msg->buf);
+			if (em_receive_request(msg, 0, 0)<0)
+				ret=NONSIP_MSG_ERROR;
+			return ret;
 		}
+	} else {
+		ERR("xmlrpc: bad HTTP request method: \"%.*s\"\n",
+			msg->first_line.u.request.method.len,
+			msg->first_line.u.request.method.s);
+		/* the message was for us, but it is an error */
+		return NONSIP_MSG_ERROR;
 	}
 	return NONSIP_MSG_PASS; /* message not for us, maybe somebody 
 								   else needs it */
@@ -2395,6 +2431,23 @@ static int mod_init(void)
 			return -1;
 		}
 	}
+	if(xmlrpc_url_match!=NULL)
+	{
+		memset(&xmlrpc_url_match_regexp, 0, sizeof(regex_t));
+		if (regcomp(&xmlrpc_url_match_regexp, xmlrpc_url_match, REG_EXTENDED)!=0) {
+			LM_ERR("bad match re %s\n", xmlrpc_url_match);
+			return E_BAD_RE;
+		}
+	}
+	if(xmlrpc_url_skip!=NULL)
+	{
+		memset(&xmlrpc_url_skip_regexp, 0, sizeof(regex_t));
+		if (regcomp(&xmlrpc_url_skip_regexp, xmlrpc_url_skip, REG_EXTENDED)!=0) {
+			LM_ERR("bad skip re %s\n", xmlrpc_url_skip);
+			return E_BAD_RE;
+		}
+	}
+
 	return 0;
 }
 




More information about the sr-dev mailing list