Module: sip-router
Branch: master
Commit: 1a810f97265302a3e7c8033b1b8c5de7c6491fb4
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=1a810f9…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)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;
}