瀏覽代碼

path: option to add two path headers and use alias like received value

- enable_r2 - add two path headers, one for incoming socket and one for
  outgoing socket
- received_format - parameter to control if received value should be
  in sip uri (as so far) or in contact-alias param format
Daniel-Constantin Mierla 8 年之前
父節點
當前提交
2c62b31706
共有 4 個文件被更改,包括 152 次插入40 次删除
  1. 134 25
      src/modules/path/path.c
  2. 2 4
      src/modules/path/path.h
  3. 11 6
      src/modules/path/path_mod.c
  4. 5 5
      src/modules/path/path_mod.h

+ 134 - 25
src/modules/path/path.c

@@ -34,6 +34,7 @@
 #include "../../core/mem/mem.h"
 #include "../../core/data_lump.h"
 #include "../../core/parser/parse_param.h"
+#include "../../core/parser/parse_uri.h"
 #include "../../core/strutils.h"
 #include "../../core/dset.h"
 
@@ -55,16 +56,34 @@ const static char *proto_strings[] = {
 	[PROTO_WSS] = "%3Btransport%3Dws",
 };
 
-static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *add_params)
+static char *path_strzdup(char *src, int len)
+{
+	char *res;
+
+	if (!src)
+		return NULL;
+	if(len<0) {
+		len = strlen(src);
+	}
+	if (!(res = (char *) pkg_malloc(len + 1)))
+		return NULL;
+	strncpy(res, src, len);
+	res[len] = 0;
+
+	return res;
+}
+
+static int prepend_path(sip_msg_t* _m, str *user, path_param_t param,
+		str *add_params)
 {
 	struct lump *l;
-	char *prefix, *suffix, *cp;
+	char *prefix, *suffix, *cp, *dp;
 	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")
+	suffix_len = sizeof(";lr;r2=on;received=sip::12345%3Btransport%3Dsctp;ob;>\r\n")
 			+ IP_ADDR_MAX_STR_SIZE + 2 + (add_params ? add_params->len : 0) + 1;
 
 	cp = suffix = pkg_malloc(suffix_len);
@@ -79,17 +98,32 @@ static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *
 	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;
-
-		if(_m->rcv.src_ip.af==AF_INET6) {
-			cp += sprintf(cp, ";received=sip:[%s]:%hu%s", ip_addr2a(&_m->rcv.src_ip),
-					_m->rcv.src_port, proto_str ? : "");
+		if(path_received_format==0) {
+			if (_m->rcv.proto
+						< (sizeof(proto_strings) / sizeof(*proto_strings))) {
+				proto_str = proto_strings[(unsigned int) _m->rcv.proto];
+			} else {
+				proto_str = NULL;
+			}
+			if(_m->rcv.src_ip.af==AF_INET6) {
+				cp += sprintf(cp, ";received=sip:[%s]:%hu%s",
+						ip_addr2a(&_m->rcv.src_ip),
+						_m->rcv.src_port, proto_str ? : "");
+			} else {
+				cp += sprintf(cp, ";received=sip:%s:%hu%s"
+						, ip_addr2a(&_m->rcv.src_ip),
+						_m->rcv.src_port, proto_str ? : "");
+			}
 		} else {
-			cp += sprintf(cp, ";received=sip:%s:%hu%s", ip_addr2a(&_m->rcv.src_ip),
-					_m->rcv.src_port, proto_str ? : "");
+			if(_m->rcv.src_ip.af==AF_INET6) {
+				cp += sprintf(cp, ";received=[%s]~%hu~%d",
+						ip_addr2a(&_m->rcv.src_ip),
+						_m->rcv.src_port, (int)_m->rcv.proto);
+			} else {
+				cp += sprintf(cp, ";received=%s~%hu~%d",
+						ip_addr2a(&_m->rcv.src_ip),
+						_m->rcv.src_port, (int)_m->rcv.proto);
+			}
 		}
 		break;
 	case PATH_PARAM_OB:
@@ -100,7 +134,11 @@ static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *
 	if (add_params && add_params->len)
 		cp += sprintf(cp, ";%.*s", add_params->len, add_params->s);
 
-	cp += sprintf(cp, ">\r\n");
+	if(path_enable_r2==0) {
+		cp += sprintf(cp, ">\r\n");
+	} else {
+		cp += sprintf(cp, ";r2=on>\r\n");
+	}
 
 	prefix_len = PATH_PREFIX_LEN + (user ? user->len : 0) + 2;
 	prefix = pkg_malloc(prefix_len);
@@ -136,6 +174,19 @@ static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *
 	l = insert_new_lump_before(l, suffix, cp - suffix, 0);
 	if (!l) goto out2;
 
+	if(path_enable_r2!=0) {
+		dp = path_strzdup(prefix, prefix_len);
+		if(dp==NULL) goto out1;
+		l = insert_new_lump_before(l, dp, prefix_len, 0);
+		if (!l) goto out1;
+		l = insert_subst_lump_before(l, SUBST_RCV_ALL, 0);
+		if (!l) goto out1;
+		dp = path_strzdup(suffix, cp - suffix);
+		if(dp==NULL) goto out1;
+		l = insert_new_lump_before(l, suffix, cp - suffix, 0);
+		if (!l) goto out1;
+	}
+
 	return 1;
 
 out3:
@@ -162,11 +213,11 @@ int ki_add_path(struct sip_msg* _msg)
 		&& path_obb.use_outbound(_msg)) {
 		if (path_obb.encode_flow_token(&user, _msg->rcv) != 0) {
 			LM_ERR("encoding outbound flow-token\n");
-			return -1;	
+			return -1;
 		}
 
-		/* Only include ;ob parameter if this is the first-hop (that
-		   means only one Via:) */
+		/* 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;
 	}
@@ -284,20 +335,77 @@ void path_rr_callback(struct sip_msg *_m, str *r_param, void *cb_param)
 	param_t *params;
 	static char dst_uri_buf[MAX_URI_SIZE];
 	static str dst_uri;
-			
+	char *p;
+	int n;
+	int nproto;
+	str sproto;
+
 	if (parse_params(r_param, CLASS_CONTACT, &hooks, &params) != 0) {
 		LM_ERR("failed to parse route parameters\n");
 		return;
 	}
 
-	if (hooks.contact.received) {
-	        dst_uri.s = dst_uri_buf;
+	if (hooks.contact.received
+			&& hooks.contact.received->body.len>0) {
+		/* 24 => sip:...;transport=sctp */
+		if(hooks.contact.received->body.len + 24 >= MAX_URI_SIZE) {
+			LM_ERR("received uri is too long\n");
+			goto done;
+		}
+		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(path_enable_r2==0) {
+			if (unescape_user(&(hooks.contact.received->body), &dst_uri) < 0) {
+				LM_ERR("unescaping received failed\n");
+				free_params(params);
+				return;
+			} else {
+				/* ip~port~proto */
+				strncpy(dst_uri_buf, "sip:", 4);
+				strncpy(dst_uri_buf+4, hooks.contact.received->body.s,
+						hooks.contact.received->body.len);
+				dst_uri_buf[hooks.contact.received->body.len] = '\0';
+				p = dst_uri_buf + 4;
+				n = 0;
+				while(*p!='\0') {
+					if(*p=='~') {
+						n++;
+						if(n==1) {
+							/* port */
+							*p = ':';
+						} else if(n==2) {
+							/* proto */
+							*p = ';';
+							p++;
+							if(*p=='\0') {
+								LM_ERR("invalid received format\n");
+								goto done;
+							}
+							nproto = *p - '0';
+							if (nproto != PROTO_UDP) {
+								proto_type_to_str(nproto, &sproto);
+								if (sproto.len == 0) {
+									LM_ERR("unknown proto in received param\n");
+									goto done;
+								}
+								strncpy(p, "transport=", 10);
+								p += 10;
+								memcpy(p, sproto.s, sproto.len);
+								p += sproto.len;
+								*p = '\0';
+								dst_uri.len = p - dst_uri_buf;
+								break;
+							}
+						} else {
+							LM_ERR("invalid number of spearators (%d)\n", n);
+							goto done;
+						}
+					}
+					p++;
+				}
+			}
+		}
+		LM_DBG("setting dst uri: %.*s\n", dst_uri.len, dst_uri.s);
 		if (set_dst_uri(_m, &dst_uri) != 0) {
 			LM_ERR("failed to set dst-uri\n");
 			free_params(params);
@@ -307,5 +415,6 @@ void path_rr_callback(struct sip_msg *_m, str *r_param, void *cb_param)
 			forking */
 		ruri_mark_new(); /* re-use uri for serial forking */
 	}
+done:
 	free_params(params);
 }

+ 2 - 4
src/modules/path/path.h

@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Path handling for intermediate proxies.
  *
  * Copyright (C) 2006 Inode GmbH (Andreas Granig <[email protected]>)
@@ -17,8 +15,8 @@
  * 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 
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
 

+ 11 - 6
src/modules/path/path_mod.c

@@ -64,7 +64,10 @@ MODULE_VERSION
 
 /*! \brief If received-param of current Route uri should be used
  * as dst-uri. */
-int use_received = 0;
+int path_use_received = 0;
+
+int path_received_format = 0;
+int path_enable_r2 = 0;
 
 /*! \brief
  * Module initialization function prototype
@@ -105,7 +108,9 @@ static cmd_export_t cmds[] = {
  * Exported parameters
  */
 static param_export_t params[] = {
-	{"use_received", INT_PARAM, &use_received },
+	{"use_received",    INT_PARAM, &path_use_received },
+	{"received_format", INT_PARAM, &path_received_format },
+	{"enable_r2",       INT_PARAM, &path_enable_r2 },
 	{ 0, 0, 0 }
 };
 
@@ -114,7 +119,7 @@ static param_export_t params[] = {
  * Module interface
  */
 struct module_exports exports = {
-	"path", 
+	"path",
 	DEFAULT_DLFLAGS, /* dlopen flags */
 	cmds,       /* Exported functions */
 	params,     /* Exported parameters */
@@ -131,7 +136,7 @@ struct module_exports exports = {
 
 static int mod_init(void)
 {
-	if (use_received) {
+	if (path_use_received) {
 		if (load_rr_api(&path_rrb) != 0) {
 			LM_ERR("failed to load rr-API\n");
 			return -1;
@@ -148,7 +153,7 @@ static int mod_init(void)
 		LM_INFO("outbound module not available\n");
 		memset(&path_obb, 0, sizeof(ob_api_t));
 	}
-	
+
 	return 0;
 }
 
@@ -198,4 +203,4 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
 {
 	sr_kemi_modules_add(sr_kemi_path_exports);
 	return 0;
-}
+}

+ 5 - 5
src/modules/path/path_mod.h

@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Path handling for intermediate proxies
  *
  * Copyright (C) 2006 Inode GmbH (Andreas Granig <[email protected]>)
@@ -17,8 +15,8 @@
  * 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 
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
@@ -36,7 +34,9 @@
 
 #include "../outbound/api.h"
 
-extern int use_received;
+extern int path_use_received;
+extern int path_received_format;
+extern int path_enable_r2;
 extern ob_api_t path_obb;
 
 #endif /* PATH_MOD_H */