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