浏览代码

path: support SPVE in add_path*() and add second parameter

This includes a major rewrite and code cleanup of prepend_path(), which
doesn't perform any other functional changes.
Richard Fuchs 12 年之前
父节点
当前提交
9941551612
共有 5 个文件被更改,包括 227 次插入127 次删除
  1. 66 15
      modules/path/README
  2. 7 0
      modules/path/doc/path.xml
  3. 72 2
      modules/path/doc/path_admin.xml
  4. 76 108
      modules/path/path.c
  5. 6 2
      modules/path/path_mod.c

+ 66 - 15
modules/path/README

@@ -8,6 +8,10 @@ Edited by
 
 Andreas Granig
 
+Edited by
+
+Richard Fuchs
+
    Copyright © 2006 Inode GmbH
      __________________________________________________________________
 
@@ -33,16 +37,20 @@ Andreas Granig
 
               4.1. add_path()
               4.2. add_path(user)
-              4.3. add_path_received()
-              4.4. add_path_received(user)
+              4.3. add_path(user, parameters)
+              4.4. add_path_received()
+              4.5. add_path_received(user)
+              4.6. add_path_received(user, parameters)
 
    List of Examples
 
    1.1. Set use_received parameter
    1.2. add_path usage
    1.3. add_path(user) usage
-   1.4. add_path_received() usage
-   1.5. add_path_received(user) usage
+   1.4. add_path(user, parameters) usage
+   1.5. add_path_received() usage
+   1.6. add_path_received(user) usage
+   1.7. add_path_received(user, parameters) usage
 
 Chapter 1. Admin Guide
 
@@ -66,8 +74,10 @@ Chapter 1. Admin Guide
 
         4.1. add_path()
         4.2. add_path(user)
-        4.3. add_path_received()
-        4.4. add_path_received(user)
+        4.3. add_path(user, parameters)
+        4.4. add_path_received()
+        4.5. add_path_received(user)
+        4.6. add_path_received(user, parameters)
 
 1. Overview
 
@@ -151,8 +161,10 @@ modparam("path", "use_received", 1)
 
    4.1. add_path()
    4.2. add_path(user)
-   4.3. add_path_received()
-   4.4. add_path_received(user)
+   4.3. add_path(user, parameters)
+   4.4. add_path_received()
+   4.5. add_path_received(user)
+   4.6. add_path_received(user, parameters)
 
 4.1.  add_path()
 
@@ -183,7 +195,7 @@ if (!add_path()) {
    <sip:[email protected];lr>”.
 
    Meaning of the parameters is as follows:
-     * user - The username to be inserted as user part.
+     * user - The username to be inserted as user part. SPVE is supported.
 
    This function can be used from REQUEST_ROUTE.
 
@@ -195,16 +207,38 @@ if (!add_path("loadbalancer")) {
 };
 ...
 
-4.3.  add_path_received()
+4.3.  add_path(user, parameters)
 
    This function adds a Path header in the form “Path:
-   <sip:1.2.3.4;received=sip:2.3.4.5:1234;lr>”, setting it's own outgoing
+   <sip:[email protected];lr>” and appends the given parameters as additional
+   URI parameters.
+
+   Meaning of the parameters is as follows:
+     * user - The username to be inserted as user part. SPVE is supported.
+     * parameters - Additional URI parameters to be appended to the URI.
+       The semicolon separator is added automatically. The script writer
+       is responsible for proper URI escaping. SPVE is supported.
+
+   This function can be used from REQUEST_ROUTE.
+
+   Example 1.4. add_path(user, parameters) usage
+...
+if (!add_path("loadbalancer", "ob")) {
+        sl_send_reply("503", "Internal Path Error");
+        ...
+};
+...
+
+4.4.  add_path_received()
+
+   This function adds a Path header in the form “Path:
+   <sip:1.2.3.4;received=sip:2.3.4.5:1234;lr>”, setting its own outgoing
    address as domain-part, and the address the request has been received
    from as received-parameter.
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.4. add_path_received() usage
+   Example 1.5. add_path_received() usage
 ...
 if (!add_path_received()) {
         sl_send_reply("503", "Internal Path Error");
@@ -212,19 +246,36 @@ if (!add_path_received()) {
 };
 ...
 
-4.4.  add_path_received(user)
+4.5.  add_path_received(user)
 
    This function adds a Path header in the form “Path:
    <sip:[email protected];received=sip:2.3.4.5:1234;lr>”, setting 'user' as
-   username part of address, it's own outgoing address as domain-part, and
+   username part of address, its own outgoing address as domain-part, and
    the address the request has been received from as received-parameter.
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.5. add_path_received(user) usage
+   Example 1.6. add_path_received(user) usage
 ...
 if (!add_path_received("inbound")) {
         sl_send_reply("503", "Internal Path Error");
         ...
 };
 ...
+
+4.6.  add_path_received(user, parameters)
+
+   This function adds a Path header in the form “Path:
+   <sip:[email protected];received=sip:2.3.4.5:1234;lr>”, setting 'user' as
+   username part of address, its own outgoing address as domain-part, and
+   the address the request has been received from as received-parameter.
+
+   This function can be used from REQUEST_ROUTE.
+
+   Example 1.7. add_path_received(user, parameters) usage
+...
+if (!add_path_received("inbound", "ob")) {
+        sl_send_reply("503", "Internal Path Error");
+        ...
+};
+...

+ 7 - 0
modules/path/doc/path.xml

@@ -28,6 +28,13 @@
 		    <email>[email protected]</email>
 		</address>
 	    </editor>
+	    <editor>
+		<firstname>Richard</firstname>
+		<surname>Fuchs</surname>
+		<address>
+		    <email>[email protected]</email>
+		</address>
+	    </editor>
 	</authorgroup>
 	<copyright>
 	    <year>2006</year>

+ 72 - 2
modules/path/doc/path_admin.xml

@@ -183,6 +183,7 @@ if (!add_path()) {
 		<listitem>
 			<para>
 			<emphasis>user</emphasis> - The username to be inserted as user part.
+			SPVE is supported.
 			</para>
 		</listitem>
 		</itemizedlist>
@@ -202,13 +203,55 @@ if (!add_path("loadbalancer")) {
 		</example>
 	</section>
 
+	<section>
+		<title>
+		<function moreinfo="none">add_path(user, parameters)</function>
+		</title>
+		<para>
+		This function adds a Path header in the form 
+		<quote>Path: &lt;sip:[email protected];lr&gt;</quote> and appends the
+		given <emphasis>parameters</emphasis> as additional URI parameters.
+		</para>
+		<para>Meaning of the parameters is as follows:</para>
+		<itemizedlist>
+		<listitem>
+			<para>
+			<emphasis>user</emphasis> - The username to be inserted as user part.
+			SPVE is supported.
+			</para>
+		</listitem>
+		<listitem>
+			<para>
+			<emphasis>parameters</emphasis> - Additional URI parameters to be
+			appended to the URI. The semicolon separator is added automatically.
+			The script writer is responsible for proper URI escaping.
+			SPVE is supported.
+			</para>
+		</listitem>
+		</itemizedlist>
+		<para>
+		This function can be used from REQUEST_ROUTE.
+		</para>
+		<example>
+		<title><function>add_path(user, parameters)</function> usage</title>
+		<programlisting format="linespecific">
+...
+if (!add_path("loadbalancer", "ob")) {
+	sl_send_reply("503", "Internal Path Error");
+	...
+};
+...
+</programlisting>
+		</example>
+	</section>
+
 	<section>
 		<title>
 		<function moreinfo="none">add_path_received()</function>
 		</title>
 		<para>
 		This function adds a Path header in the form 
-		<quote>Path: &lt;sip:1.2.3.4;received=sip:2.3.4.5:1234;lr&gt;</quote>, setting it's own 
+		<quote>Path: &lt;sip:1.2.3.4;received=sip:2.3.4.5:1234;lr&gt;</quote>, setting its own 
 		outgoing address as domain-part, and the address the request has been received from as
 		received-parameter.
 		</para>
@@ -235,7 +278,7 @@ if (!add_path_received()) {
 		<para>
 		This function adds a Path header in the form 
 		<quote>Path: &lt;sip:[email protected];received=sip:2.3.4.5:1234;lr&gt;</quote>, setting
-		'user' as username part of address, it's own 
+		'user' as username part of address, its own 
 		outgoing address as domain-part, and the address the request has been received from as
 		received-parameter.
 		</para>
@@ -255,6 +298,33 @@ if (!add_path_received("inbound")) {
 		</example>
 	</section>
 
+	<section>
+		<title>
+		<function moreinfo="none">add_path_received(user, parameters)</function>
+		</title>
+		<para>
+		This function adds a Path header in the form 
+		<quote>Path: &lt;sip:[email protected];received=sip:2.3.4.5:1234;lr&gt;</quote>, setting
+		'user' as username part of address, its own 
+		outgoing address as domain-part, and the address the request has been received from as
+		received-parameter.
+		</para>
+		<para>
+		This function can be used from REQUEST_ROUTE.
+		</para>
+		<example>
+		<title><function>add_path_received(user, parameters)</function> usage</title>
+		<programlisting format="linespecific">
+...
+if (!add_path_received("inbound", "ob")) {
+	sl_send_reply("503", "Internal Path Error");
+	...
+};
+...
+</programlisting>
+		</example>
+	</section>
+
 
 	</section>
 

+ 76 - 108
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

+ 6 - 2
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 }
 };