Hello, Since this is a significant rewrite of an existing module, I'd like to ask if anyone has any objections against committing the attached patch.
Functionally, it adds a second parameter to add_path() and add_path_received(), enabling the script writer to include arbitrary additional URI parameters in the Path header. It also adds support for SPVE for all parameters. Code wise, it rewrites most parts of prepend_path() to make the code more streamlined, use fewer memory chunks and lumps and (hopefully) make the code easier to read, shorter, and easier to extend in the future. I'm attaching the new path.c as well for readability. I haven't included the updates to docs. cheers
diff --git a/modules/path/path.c b/modules/path/path.c
index 122d7fa..6cf7f8f 100644
--- a/modules/path/path.c
+++ b/modules/path/path.c
@@ -49,83 +49,72 @@ typedef enum {
#define PATH_PREFIX "Path: <sip:"
#define PATH_PREFIX_LEN (sizeof(PATH_PREFIX)-1)
-#define PATH_LR_PARAM ";lr"
-#define PATH_LR_PARAM_LEN (sizeof(PATH_LR_PARAM)-1)
-
-#define PATH_RC_PARAM ";received="
-#define PATH_RC_PARAM_LEN (sizeof(PATH_RC_PARAM)-1)
-
-#define PATH_OB_PARAM ";ob"
-#define PATH_OB_PARAM_LEN (sizeof(PATH_OB_PARAM)-1)
-
-#define PATH_CRLF ">\r\n"
-#define PATH_CRLF_LEN (sizeof(PATH_CRLF)-1)
-
-#define ALLOC_AND_COPY_PATH_HDR() \
- if ((suffix = pkg_malloc(suffix_len)) == NULL) { \
- LM_ERR("no pkg memory left for suffix\n"); \
- goto out1; \
- } \
- memcpy(suffix, PATH_LR_PARAM, PATH_LR_PARAM_LEN);
-
-static int prepend_path(struct sip_msg* _m, str *user, path_param_t param)
+const static char *proto_strings[] = {
+ [PROTO_TCP] = "%3Btransport%3Dtcp",
+ [PROTO_TLS] = "%3Btransport%3Dtls",
+ [PROTO_SCTP] = "%3Btransport%3Dsctp",
+ [PROTO_WS] = "%3Btransport%3Dws",
+ [PROTO_WSS] = "%3Btransport%3Dws",
+};
+
+static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *add_params)
{
struct lump *l;
- char *prefix, *suffix, *crlf;
+ char *prefix, *suffix, *cp;
+ const char *proto_str;
int prefix_len, suffix_len;
struct hdr_field *hf;
- str rcv_addr = {0, 0};
- char *src_ip;
-
- prefix = suffix = crlf = 0;
- prefix_len = PATH_PREFIX_LEN + (user->len ? (user->len+1) : 0);
- prefix = pkg_malloc(prefix_len);
- if (!prefix) {
- LM_ERR("no pkg memory left for prefix\n");
+ /* maximum possible length of suffix */
+ suffix_len = strlen(";lr;received=sip::12345%3Btransport%3Dsctp;ob;>\r\n")
+ + IP_ADDR_MAX_STR_SIZE + (add_params ? add_params->len : 0) + 1;
+
+ cp = suffix = pkg_malloc(suffix_len);
+ if (!suffix) {
+ LM_ERR("no pkg memory left for suffix\n");
goto out1;
}
- memcpy(prefix, PATH_PREFIX, PATH_PREFIX_LEN);
- if (user->len) {
- memcpy(prefix + PATH_PREFIX_LEN, user->s, user->len);
- memcpy(prefix + prefix_len - 1, "@", 1);
- }
+
+ cp += sprintf(cp, ";lr");
switch(param) {
default:
- suffix_len = PATH_LR_PARAM_LEN;
- ALLOC_AND_COPY_PATH_HDR();
break;
case PATH_PARAM_RECEIVED:
- suffix_len = PATH_LR_PARAM_LEN + PATH_RC_PARAM_LEN;
- ALLOC_AND_COPY_PATH_HDR();
- memcpy(suffix + PATH_LR_PARAM_LEN, PATH_RC_PARAM,
- PATH_RC_PARAM_LEN);
+ if (_m->rcv.proto < (sizeof(proto_strings) / sizeof(*proto_strings)))
+ proto_str = proto_strings[(unsigned int) _m->rcv.proto];
+ else
+ proto_str = NULL;
+
+ cp += sprintf(cp, ";received=sip:%s:%hu%s", ip_addr2a(&_m->rcv.src_ip),
+ _m->rcv.src_port, proto_str ? : "");
break;
case PATH_PARAM_OB:
- suffix_len = PATH_LR_PARAM_LEN + PATH_OB_PARAM_LEN;
- ALLOC_AND_COPY_PATH_HDR();
- memcpy(suffix + PATH_LR_PARAM_LEN, PATH_OB_PARAM,
- PATH_OB_PARAM_LEN);
+ cp += sprintf(cp, ";ob");
break;
}
- crlf = pkg_malloc(PATH_CRLF_LEN);
- if (!crlf) {
- LM_ERR("no pkg memory left for crlf\n");
- goto out1;
+ if (add_params && add_params->len)
+ cp += sprintf(cp, ";%.*s", add_params->len, add_params->s);
+
+ cp += sprintf(cp, ">\r\n");
+
+ prefix_len = PATH_PREFIX_LEN + (user ? user->len : 0) + 2;
+ prefix = pkg_malloc(prefix_len);
+ if (!prefix) {
+ LM_ERR("no pkg memory left for prefix\n");
+ goto out2;
}
- memcpy(crlf, PATH_CRLF, PATH_CRLF_LEN);
+ if (user && user->len)
+ prefix_len = sprintf(prefix, PATH_PREFIX "%.*s@", user->len, user->s);
+ else
+ prefix_len = sprintf(prefix, PATH_PREFIX);
if (parse_headers(_m, HDR_PATH_F, 0) < 0) {
LM_ERR("failed to parse message for Path header\n");
- goto out1;
- }
- for (hf = _m->headers; hf; hf = hf->next) {
- if (hf->type == HDR_PATH_T) {
- break;
- }
+ goto out3;
}
+ hf = get_hdr(_m, HDR_PATH_T);
if (hf)
/* path found, add ours in front of that */
l = anchor_lump(_m, hf->name.s - _m->buf, 0, 0);
@@ -134,60 +123,24 @@ static int prepend_path(struct sip_msg* _m, str *user, path_param_t param)
l = anchor_lump(_m, _m->unparsed - _m->buf, 0, 0);
if (!l) {
LM_ERR("failed to get anchor\n");
- goto out1;
+ goto out3;
}
l = insert_new_lump_before(l, prefix, prefix_len, 0);
- if (!l) goto out1;
+ if (!l) goto out3;
l = insert_subst_lump_before(l, SUBST_SND_ALL, 0);
if (!l) goto out2;
- l = insert_new_lump_before(l, suffix, suffix_len, 0);
+ l = insert_new_lump_before(l, suffix, cp - suffix, 0);
if (!l) goto out2;
- if (param == PATH_PARAM_RECEIVED) {
- /* TODO: agranig: optimize this one! */
- src_ip = ip_addr2a(&_m->rcv.src_ip);
- rcv_addr.s = pkg_malloc(6 + IP_ADDR_MAX_STR_SIZE + 24); /* sip:<ip>:<port>%3Btransport%3Dsctp\0 */
- if(!rcv_addr.s) {
- LM_ERR("no pkg memory left for receive-address\n");
- goto out3;
- }
- switch (_m->rcv.proto) {
- case PROTO_UDP:
- rcv_addr.len = snprintf(rcv_addr.s, 6 + IP_ADDR_MAX_STR_SIZE + 4, "sip:%s:%u", src_ip, _m->rcv.src_port);
- break;
- case PROTO_TCP:
- rcv_addr.len = snprintf(rcv_addr.s, 6 + IP_ADDR_MAX_STR_SIZE + 22, "sip:%s:%u%%3Btransport%%3Dtcp", src_ip, _m->rcv.src_port);
- break;
- case PROTO_TLS:
- rcv_addr.len = snprintf(rcv_addr.s, 6 + IP_ADDR_MAX_STR_SIZE + 22, "sip:%s:%u%%3Btransport%%3Dtls", src_ip, _m->rcv.src_port);
- break;
- case PROTO_SCTP:
- rcv_addr.len = snprintf(rcv_addr.s, 6 + IP_ADDR_MAX_STR_SIZE + 23, "sip:%s:%u%%3Btransport%%3Dsctp", src_ip, _m->rcv.src_port);
- break;
- case PROTO_WS:
- case PROTO_WSS:
- rcv_addr.len = snprintf(rcv_addr.s, 6 + IP_ADDR_MAX_STR_SIZE + 21, "sip:%s:%u%%3Btransport%%3Dws", src_ip, _m->rcv.src_port);
- break;
- }
-
- l = insert_new_lump_before(l, rcv_addr.s, rcv_addr.len, 0);
- if (!l) goto out3;
- }
- l = insert_new_lump_before(l, crlf, CRLF_LEN+1, 0);
- if (!l) goto out4;
-
+
return 1;
-
-out1:
- if (prefix) pkg_free(prefix);
-out2:
- if (suffix) pkg_free(suffix);
-out3:
- if (rcv_addr.s) pkg_free(rcv_addr.s);
-out4:
- if (crlf) pkg_free(crlf);
- LM_ERR("failed to insert prefix lump\n");
+out3:
+ pkg_free(prefix);
+out2:
+ pkg_free(suffix);
+out1:
+ LM_ERR("failed to insert Path header\n");
return -1;
}
@@ -215,7 +168,7 @@ int add_path(struct sip_msg* _msg, char* _a, char* _b)
param = PATH_PARAM_OB;
}
- ret = prepend_path(_msg, &user, param);
+ ret = prepend_path(_msg, &user, param, NULL);
if (user.s != NULL)
pkg_free(user.s);
@@ -227,9 +180,17 @@ int add_path(struct sip_msg* _msg, char* _a, char* _b)
* Prepend own uri to Path header and take care of given
* user.
*/
-int add_path_usr(struct sip_msg* _msg, char* _usr, char* _b)
+int add_path_usr(struct sip_msg* _msg, char* _usr, char* _parms)
{
- return prepend_path(_msg, (str*)_usr, PATH_PARAM_NONE);
+ str user = {0,0};
+ str parms = {0,0};
+
+ if (_usr)
+ get_str_fparam(&user, _msg, (fparam_t *) _usr);
+ if (_parms)
+ get_str_fparam(&parms, _msg, (fparam_t *) _parms);
+
+ return prepend_path(_msg, &user, PATH_PARAM_NONE, &parms);
}
/*! \brief
@@ -238,17 +199,24 @@ int add_path_usr(struct sip_msg* _msg, char* _usr, char* _b)
*/
int add_path_received(struct sip_msg* _msg, char* _a, char* _b)
{
- str user = {0,0};
- return prepend_path(_msg, &user, PATH_PARAM_RECEIVED);
+ return prepend_path(_msg, NULL, PATH_PARAM_RECEIVED, NULL);
}
/*! \brief
* Prepend own uri to Path header and append received address as
* "received"-param to that uri and take care of given user.
*/
-int add_path_received_usr(struct sip_msg* _msg, char* _usr, char* _b)
+int add_path_received_usr(struct sip_msg* _msg, char* _usr, char* _parms)
{
- return prepend_path(_msg, (str*)_usr, PATH_PARAM_RECEIVED);
+ str user = {0,0};
+ str parms = {0,0};
+
+ if (_usr)
+ get_str_fparam(&user, _msg, (fparam_t *) _usr);
+ if (_parms)
+ get_str_fparam(&parms, _msg, (fparam_t *) _parms);
+
+ return prepend_path(_msg, &user, PATH_PARAM_RECEIVED, &parms);
}
/*! \brief
diff --git a/modules/path/path_mod.c b/modules/path/path_mod.c
index 15fbc4d..0da11ae 100644
--- a/modules/path/path_mod.c
+++ b/modules/path/path_mod.c
@@ -87,11 +87,15 @@ static cmd_export_t cmds[] = {
{ "add_path", (cmd_function)add_path, 0,
0, 0, REQUEST_ROUTE },
{ "add_path", (cmd_function)add_path_usr, 1,
- fixup_str_null, 0, REQUEST_ROUTE },
+ fixup_spve_null, 0, REQUEST_ROUTE },
+ { "add_path", (cmd_function)add_path_usr, 2,
+ fixup_spve_spve, 0, REQUEST_ROUTE },
{ "add_path_received", (cmd_function)add_path_received, 0,
0, 0, REQUEST_ROUTE },
{ "add_path_received", (cmd_function)add_path_received_usr, 1,
- fixup_str_null, 0, REQUEST_ROUTE },
+ fixup_spve_null, 0, REQUEST_ROUTE },
+ { "add_path_received", (cmd_function)add_path_received_usr, 2,
+ fixup_spve_spve, 0, REQUEST_ROUTE },
{ 0, 0, 0, 0, 0, 0 }
};
/* * $Id$ * * Path handling for intermediate proxies. * * Copyright (C) 2006 Inode GmbH (Andreas Granig <[email protected]>) * * This file is part of Kamailio, a free SIP server. * * Kamailio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * Kamailio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /*! \file * \brief Path :: Utilities * * \ingroup path * - Module: path */ #include <string.h> #include <stdio.h> #include "../../mem/mem.h" #include "../../data_lump.h" #include "../../parser/parse_param.h" #include "../../lib/kcore/strcommon.h" #include "../../dset.h" #include "path.h" #include "path_mod.h" typedef enum { PATH_PARAM_NONE, PATH_PARAM_RECEIVED, PATH_PARAM_OB } path_param_t; #define PATH_PREFIX "Path: <sip:" #define PATH_PREFIX_LEN (sizeof(PATH_PREFIX)-1) const static char *proto_strings[] = { [PROTO_TCP] = "%3Btransport%3Dtcp", [PROTO_TLS] = "%3Btransport%3Dtls", [PROTO_SCTP] = "%3Btransport%3Dsctp", [PROTO_WS] = "%3Btransport%3Dws", [PROTO_WSS] = "%3Btransport%3Dws", }; static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *add_params) { struct lump *l; char *prefix, *suffix, *cp; const char *proto_str; int prefix_len, suffix_len; struct hdr_field *hf; /* maximum possible length of suffix */ suffix_len = strlen(";lr;received=sip::12345%3Btransport%3Dsctp;ob;>\r\n") + IP_ADDR_MAX_STR_SIZE + (add_params ? add_params->len : 0) + 1; cp = suffix = pkg_malloc(suffix_len); if (!suffix) { LM_ERR("no pkg memory left for suffix\n"); goto out1; } cp += sprintf(cp, ";lr"); switch(param) { default: break; case PATH_PARAM_RECEIVED: if (_m->rcv.proto < (sizeof(proto_strings) / sizeof(*proto_strings))) proto_str = proto_strings[(unsigned int) _m->rcv.proto]; else proto_str = NULL; cp += sprintf(cp, ";received=sip:%s:%hu%s", ip_addr2a(&_m->rcv.src_ip), _m->rcv.src_port, proto_str ? : ""); break; case PATH_PARAM_OB: cp += sprintf(cp, ";ob"); break; } if (add_params && add_params->len) cp += sprintf(cp, ";%.*s", add_params->len, add_params->s); cp += sprintf(cp, ">\r\n"); prefix_len = PATH_PREFIX_LEN + (user ? user->len : 0) + 2; prefix = pkg_malloc(prefix_len); if (!prefix) { LM_ERR("no pkg memory left for prefix\n"); goto out2; } if (user && user->len) prefix_len = sprintf(prefix, PATH_PREFIX "%.*s@", user->len, user->s); else prefix_len = sprintf(prefix, PATH_PREFIX); if (parse_headers(_m, HDR_PATH_F, 0) < 0) { LM_ERR("failed to parse message for Path header\n"); goto out3; } hf = get_hdr(_m, HDR_PATH_T); if (hf) /* path found, add ours in front of that */ l = anchor_lump(_m, hf->name.s - _m->buf, 0, 0); else /* no path, append to message */ l = anchor_lump(_m, _m->unparsed - _m->buf, 0, 0); if (!l) { LM_ERR("failed to get anchor\n"); goto out3; } l = insert_new_lump_before(l, prefix, prefix_len, 0); if (!l) goto out3; l = insert_subst_lump_before(l, SUBST_SND_ALL, 0); if (!l) goto out2; l = insert_new_lump_before(l, suffix, cp - suffix, 0); if (!l) goto out2; return 1; out3: pkg_free(prefix); out2: pkg_free(suffix); out1: LM_ERR("failed to insert Path header\n"); return -1; } /*! \brief * Prepend own uri to Path header */ int add_path(struct sip_msg* _msg, char* _a, char* _b) { str user = {0,0}; int ret; path_param_t param = PATH_PARAM_NONE; struct via_body *via; if (path_obb.use_outbound != NULL && path_obb.use_outbound(_msg)) { if (path_obb.encode_flow_token(&user, _msg->rcv) != 0) { LM_ERR("encoding outbound flow-token\n"); return -1; } /* Only include ;ob parameter if this is the first-hop (that means only one Via:) */ if (parse_via_header(_msg, 2, &via) < 0) param = PATH_PARAM_OB; } ret = prepend_path(_msg, &user, param, NULL); if (user.s != NULL) pkg_free(user.s); return ret; } /*! \brief * Prepend own uri to Path header and take care of given * user. */ int add_path_usr(struct sip_msg* _msg, char* _usr, char* _parms) { str user = {0,0}; str parms = {0,0}; if (_usr) get_str_fparam(&user, _msg, (fparam_t *) _usr); if (_parms) get_str_fparam(&parms, _msg, (fparam_t *) _parms); return prepend_path(_msg, &user, PATH_PARAM_NONE, &parms); } /*! \brief * Prepend own uri to Path header and append received address as * "received"-param to that uri. */ int add_path_received(struct sip_msg* _msg, char* _a, char* _b) { return prepend_path(_msg, NULL, PATH_PARAM_RECEIVED, NULL); } /*! \brief * Prepend own uri to Path header and append received address as * "received"-param to that uri and take care of given user. */ int add_path_received_usr(struct sip_msg* _msg, char* _usr, char* _parms) { str user = {0,0}; str parms = {0,0}; if (_usr) get_str_fparam(&user, _msg, (fparam_t *) _usr); if (_parms) get_str_fparam(&parms, _msg, (fparam_t *) _parms); return prepend_path(_msg, &user, PATH_PARAM_RECEIVED, &parms); } /*! \brief * rr callback */ void path_rr_callback(struct sip_msg *_m, str *r_param, void *cb_param) { param_hooks_t hooks; param_t *params; static char dst_uri_buf[MAX_URI_SIZE]; static str dst_uri; if (parse_params(r_param, CLASS_CONTACT, &hooks, ¶ms) != 0) { LM_ERR("failed to parse route parameters\n"); return; } if (hooks.contact.received) { dst_uri.s = dst_uri_buf; dst_uri.len = MAX_URI_SIZE; if (unescape_user(&(hooks.contact.received->body), &dst_uri) < 0) { LM_ERR("unescaping received failed\n"); free_params(params); return; } if (set_dst_uri(_m, &dst_uri) != 0) { LM_ERR("failed to set dst-uri\n"); free_params(params); return; } /* dst_uri changed, so it makes sense to re-use the current uri for forking */ ruri_mark_new(); /* re-use uri for serial forking */ } free_params(params); }
signature.asc
Description: OpenPGP digital signature
_______________________________________________ sr-dev mailing list [email protected] http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
