[sr-dev] git:master: modules_k/registrar: New outbound_mode parameter

Peter Dunkley peter.dunkley at crocodile-rcs.com
Mon Jan 7 17:11:20 CET 2013


Module: sip-router
Branch: master
Commit: c486a9358f146ac2b3e5047021c197c3eb6b41d8
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=c486a9358f146ac2b3e5047021c197c3eb6b41d8

Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
Committer: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
Date:   Mon Jan  7 16:08:13 2013 +0000

modules_k/registrar: New outbound_mode parameter

- Controls whether outbound options-tag is required in REGISTER
  requests and whether they are added to responses to REGISTER requests.
- Needed so that an Outbound Edge Proxy can add a Flow-Timer: header
  to 200 OK responses (to REGISTERs) that contain a Requires: header with
  the outbound options-tag.

---

 modules_k/registrar/reg_mod.c |    7 +++
 modules_k/registrar/reg_mod.h |    5 ++
 modules_k/registrar/reply.c   |  117 +++++++++++++++++++++++++++++++++--------
 modules_k/registrar/rerrno.h  |    3 +-
 modules_k/registrar/save.c    |   10 ++++
 5 files changed, 119 insertions(+), 23 deletions(-)

diff --git a/modules_k/registrar/reg_mod.c b/modules_k/registrar/reg_mod.c
index de4067f..4f83696 100644
--- a/modules_k/registrar/reg_mod.c
+++ b/modules_k/registrar/reg_mod.c
@@ -119,6 +119,7 @@ int path_use_params = 0;			/*!< if the received- and nat-parameters of last Path
 sruid_t _reg_sruid;
 
 int reg_gruu_enabled = 1;
+int reg_outbound_mode = 0;
 
 /* Populate this AVP if testing for specific registration instance. */
 char *reg_callid_avp_param = 0;
@@ -222,6 +223,7 @@ static param_export_t params[] = {
 	{"xavp_cfg",           STR_PARAM, &reg_xavp_cfg.s     					},
 	{"xavp_rcd",           STR_PARAM, &reg_xavp_rcd.s     					},
 	{"gruu_enabled",       INT_PARAM, &reg_gruu_enabled    					},
+	{"outbound_mode",      INT_PARAM, &reg_outbound_mode					},
 	{0, 0, 0}
 };
 
@@ -373,6 +375,11 @@ static int mod_init(void)
 		sock_flag = -1;
 	}
 
+	if (reg_outbound_mode < 0 || reg_outbound_mode > 2) {
+		LM_ERR("outbound_mode modparam must be 0 (not supported), 1 (supported), or 2 (supported and required)\n");
+		return -1;
+	}
+
 	/* fix the flags */
 	sock_flag = (sock_flag!=-1)?(1<<sock_flag):0;
 	tcp_persistent_flag = (tcp_persistent_flag!=-1)?(1<<tcp_persistent_flag):0;
diff --git a/modules_k/registrar/reg_mod.h b/modules_k/registrar/reg_mod.h
index 5033550..04d31fa 100644
--- a/modules_k/registrar/reg_mod.h
+++ b/modules_k/registrar/reg_mod.h
@@ -67,6 +67,10 @@
 #define REG_SAVE_REPL_FL    (1<<2)
 #define REG_SAVE_ALL_FL     ((1<<3)-1)
 
+#define REG_OUTBOUND_NONE	0
+#define REG_OUTBOUND_SUPPORTED	1
+#define REG_OUTBOUND_REQUIRE	2
+
 extern int nat_flag;
 extern int tcp_persistent_flag;
 extern int received_avp;
@@ -84,6 +88,7 @@ extern int path_enabled;
 extern int path_mode;
 extern int path_use_params;
 extern int reg_gruu_enabled;
+extern int reg_outbound_mode;
 
 extern str sock_hdr_name;
 extern int sock_flag;
diff --git a/modules_k/registrar/reply.c b/modules_k/registrar/reply.c
index e403889..5ce444e 100644
--- a/modules_k/registrar/reply.c
+++ b/modules_k/registrar/reply.c
@@ -373,6 +373,7 @@ int build_contact(sip_msg_t *msg, ucontact_t* c, str *host)
 #define MSG_200 "OK"
 #define MSG_400 "Bad Request"
 #define MSG_420 "Bad Extension"
+#define MSG_421 "Extension Required"
 #define MSG_500 "Server Internal Error"
 #define MSG_503 "Service Unavailable"
 
@@ -406,6 +407,7 @@ int build_contact(sip_msg_t *msg, ucontact_t* c, str *host)
 #define EI_R_CALLID_LEN  "Callid too long"                          /* R_CALLID_LEN */
 #define EI_R_PARSE_PATH  "Path parse error"                         /* R_PARSE_PATH */
 #define EI_R_PATH_UNSUP  "No support for found Path indicated"      /* R_PATH_UNSUP */
+#define EI_R_OB_UNSUP    "No support for Outbound indicated"        /* R_OB_UNSUP */
 
 str error_info[] = {
 	{EI_R_FINE,       sizeof(EI_R_FINE) - 1},
@@ -437,7 +439,8 @@ str error_info[] = {
 	{EI_R_CONTACT_LEN,sizeof(EI_R_CONTACT_LEN) - 1},
 	{EI_R_CALLID_LEN, sizeof(EI_R_CALLID_LEN) - 1},
 	{EI_R_PARSE_PATH, sizeof(EI_R_PARSE_PATH) - 1},
-	{EI_R_PATH_UNSUP, sizeof(EI_R_PATH_UNSUP) - 1}
+	{EI_R_PATH_UNSUP, sizeof(EI_R_PATH_UNSUP) - 1},
+	{EI_R_OB_UNSUP,   sizeof(EI_R_OB_UNSUP) - 1},
 
 };
 
@@ -471,7 +474,8 @@ int codes[] = {
 	400, /* R_CONTACT_LEN */
 	400, /* R_CALLID_LEN */
 	400, /* R_PARSE_PATH */
-	420  /* R_PATH_UNSUP */
+	420, /* R_PATH_UNSUP */
+	421  /* R_OB_UNSUP */
 
 };
 
@@ -537,6 +541,46 @@ static int add_unsupported(struct sip_msg* _m, str* _p)
  		     LUMP_RPL_HDR | LUMP_RPL_NODUP);
  	return 0;
 }
+
+#define REQUIRE "Require: "
+#define REQUIRE_LEN (sizeof(REQUIRE) - 1)
+
+static int add_require(struct sip_msg* _m, str* _p)
+{
+	char* buf;
+
+ 	buf = (char*)pkg_malloc(REQUIRE_LEN + _p->len + CRLF_LEN);
+ 	if (!buf) {
+ 		LM_ERR("no pkg memory left\n");
+ 		return -1;
+ 	}
+ 	memcpy(buf, REQUIRE, REQUIRE_LEN);
+ 	memcpy(buf + REQUIRE_LEN, _p->s, _p->len);
+ 	memcpy(buf + REQUIRE_LEN + _p->len, CRLF, CRLF_LEN);
+ 	add_lump_rpl(_m, buf, REQUIRE_LEN + _p->len + CRLF_LEN,
+ 		     LUMP_RPL_HDR | LUMP_RPL_NODUP);
+ 	return 0;
+}
+
+#define SUPPORTED "Supported: "
+#define SUPPORTED_LEN (sizeof(SUPPORTED) - 1)
+
+static int add_supported(struct sip_msg* _m, str* _p)
+{
+	char* buf;
+
+ 	buf = (char*)pkg_malloc(SUPPORTED_LEN + _p->len + CRLF_LEN);
+ 	if (!buf) {
+ 		LM_ERR("no pkg memory left\n");
+ 		return -1;
+ 	}
+ 	memcpy(buf, SUPPORTED, SUPPORTED_LEN);
+ 	memcpy(buf + SUPPORTED_LEN, _p->s, _p->len);
+ 	memcpy(buf + SUPPORTED_LEN + _p->len, CRLF, CRLF_LEN);
+ 	add_lump_rpl(_m, buf, SUPPORTED_LEN + _p->len + CRLF_LEN,
+ 		     LUMP_RPL_HDR | LUMP_RPL_NODUP);
+ 	return 0;
+}
  
 /*! \brief
  * Send a reply
@@ -544,6 +588,7 @@ static int add_unsupported(struct sip_msg* _m, str* _p)
 int reg_send_reply(struct sip_msg* _m)
 {
 	str unsup = str_init(SUPPORTED_PATH_STR);
+	str outbound_str = str_init(SUPPORTED_OUTBOUND_STR);
 	long code;
 	str msg = str_init(MSG_200); /* makes gcc shut up */
 	char* buf;
@@ -552,34 +597,62 @@ int reg_send_reply(struct sip_msg* _m)
 		add_lump_rpl( _m, contact.buf, contact.data_len, LUMP_RPL_HDR|LUMP_RPL_NODUP|LUMP_RPL_NOFREE);
 		contact.data_len = 0;
 	}
-			
-	if (rerrno == R_FINE && path_enabled && _m->path_vec.s) {
-		if (path_mode != PATH_MODE_OFF) {
-			if (parse_supported(_m)<0 && path_mode == PATH_MODE_STRICT) {
-				rerrno = R_PATH_UNSUP;
-				if (add_unsupported(_m, &unsup) < 0)
-					return -1;
-				if (add_path(_m, &_m->path_vec) < 0)
-					return -1;
-			}
-			else if (get_supported(_m) & F_SUPPORTED_PATH) {
-				if (add_path(_m, &_m->path_vec) < 0)
-					return -1;
-			} else if (path_mode == PATH_MODE_STRICT) {
-				rerrno = R_PATH_UNSUP;
-				if (add_unsupported(_m, &unsup) < 0)
-					return -1;
-				if (add_path(_m, &_m->path_vec) < 0)
-					return -1;
+
+	switch (rerrno) {
+	case R_FINE:
+		if (path_enabled && _m->path_vec.s) {
+			if (path_mode != PATH_MODE_OFF) {
+				if (parse_supported(_m)<0 && path_mode == PATH_MODE_STRICT) {
+					rerrno = R_PATH_UNSUP;
+					if (add_unsupported(_m, &unsup) < 0)
+						return -1;
+					if (add_path(_m, &_m->path_vec) < 0)
+						return -1;
+				}
+				else if (get_supported(_m) & F_SUPPORTED_PATH) {
+					if (add_path(_m, &_m->path_vec) < 0)
+						return -1;
+				} else if (path_mode == PATH_MODE_STRICT) {
+					rerrno = R_PATH_UNSUP;
+					if (add_unsupported(_m, &unsup) < 0)
+						return -1;
+					if (add_path(_m, &_m->path_vec) < 0)
+						return -1;
+				}
 			}
 		}
+
+		switch(reg_outbound_mode)
+		{
+		case REG_OUTBOUND_NONE:
+		default:
+			break;
+		case REG_OUTBOUND_REQUIRE:
+			if (add_require(_m, &outbound_str) < 0)
+				return -1;
+			/* Fall-thru */
+		case REG_OUTBOUND_SUPPORTED:
+			if (add_supported(_m, &outbound_str) < 0)
+				return -1;
+			break;
+		}
+		break;
+	case R_OB_UNSUP:
+		if (add_require(_m, &outbound_str) < 0)
+			return -1;
+		if (add_supported(_m, &outbound_str) < 0)
+			return -1;
+		break;
+	default:
+		break;
 	}
 
 	code = codes[rerrno];
 	switch(code) {
-	case 200: msg.s = MSG_200; msg.len = sizeof(MSG_200)-1; break;
+	case 200: msg.s = MSG_200; msg.len = sizeof(MSG_200)-1;break;
 	case 400: msg.s = MSG_400; msg.len = sizeof(MSG_400)-1;break;
 	case 420: msg.s = MSG_420; msg.len = sizeof(MSG_420)-1;break;
+	case 421: msg.s = MSG_420; msg.len = sizeof(MSG_421)-1;break;
 	case 500: msg.s = MSG_500; msg.len = sizeof(MSG_500)-1;break;
 	case 503: msg.s = MSG_503; msg.len = sizeof(MSG_503)-1;break;
 	}
diff --git a/modules_k/registrar/rerrno.h b/modules_k/registrar/rerrno.h
index 5cc1fc4..63add5a 100644
--- a/modules_k/registrar/rerrno.h
+++ b/modules_k/registrar/rerrno.h
@@ -63,7 +63,8 @@ typedef enum rerr {
 	R_CONTACT_LEN,/*!< Contact URI or RECEIVED too long */
 	R_CALLID_LEN, /*!< Callid too long */
 	R_PARSE_PATH, /*!< Error while parsing Path */
-	R_PATH_UNSUP  /*!< Path not supported by UAC */
+	R_PATH_UNSUP, /*!< Path not supported by UAC */
+	R_OB_UNSUP    /*!< Outbound not supported by UAC */
 
 } rerr_t;
 
diff --git a/modules_k/registrar/save.c b/modules_k/registrar/save.c
index 06bf559..7596c6a 100644
--- a/modules_k/registrar/save.c
+++ b/modules_k/registrar/save.c
@@ -61,6 +61,7 @@
 #include "../../mod_fix.h"
 #include "../../lib/srutils/sruid.h"
 #include "../../lib/kcore/cmpapi.h"
+#include "../../lib/kcore/parse_supported.h"
 #include "../../lib/kcore/statistics.h"
 #ifdef USE_TCP
 #include "../../tcp_server.h"
@@ -840,6 +841,15 @@ int save(struct sip_msg* _m, udomain_t* _d, int _cflags, str *_uri)
 	if (check_contacts(_m, &st) > 0) {
 		goto error;
 	}
+
+	if (parse_supported(_m) == 0) {
+		if (!(((struct supported_body *)_m->supported->parsed)->supported_all
+				& F_SUPPORTED_OUTBOUND) && reg_outbound_mode == REG_OUTBOUND_REQUIRE) {
+			LM_WARN("Outbound required by server and not supported by UAC\n");
+			rerrno = R_OB_UNSUP;
+			goto error;
+		}
+	}
 	
 	get_act_time();
 	c = get_first_contact(_m);




More information about the sr-dev mailing list