[asterisk-commits] tilghman: branch 1.6.0 r242514 - in /branches/1.6.0: ./ channels/ configs/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Jan 22 18:42:20 CST 2010


Author: tilghman
Date: Fri Jan 22 18:42:09 2010
New Revision: 242514

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=242514
Log:
Backporting register line parsing from trunk to fix a bad parsing error in 1.6.0.

(closes issue #16491)
 Reported by: jamicque
 Patches: 
       20100114__issue16491.diff.txt uploaded by tilghman (license 14)
 Tested by: jamicque

........
  r213098 | tilghman | 2009-08-19 16:05:17 -0500 (Wed, 19 Aug 2009) | 9 lines
  
  Better parsing for the "register" line
  Allows characters that are otherwise used as delimiters to be used within
  certain fields (like the secret).
  (closes issue #15008, closes issue #15672)
   Reported by: tilghman
   Patches: 
         20090818__issue15008.diff.txt uploaded by tilghman (license 14)
   Tested by: lmadsen, tilghman
........
  r213635 | dvossel | 2009-08-21 16:02:50 -0500 (Fri, 21 Aug 2009) | 5 lines
  
  fixes sip register parsing when user at domain is used
  
  (issue #15008)
  (issue #15672)
........
  r215222 | tilghman | 2009-09-01 16:19:40 -0500 (Tue, 01 Sep 2009) | 3 lines
  
  Fix register such that lines with a transport string, but without an authuser, parse correctly.
  (AST-228)
........
  r215801 | tilghman | 2009-09-02 22:43:51 -0500 (Wed, 02 Sep 2009) | 5 lines
  
  Default the callback extension to "s".  This is a regression.
  (closes issue #15764)
   Reported by: elguero
   Change-type: bugfix
........
  r235132 | dvossel | 2009-12-15 12:43:06 -0600 (Tue, 15 Dec 2009) | 14 lines
  
  reverse minor sip registration regression
  
  A registration regression caused by a code tweak in (issue #14331)
  and a bug fix in (issue #15539) caused some sip registration
  config entries to be constructed incorrectly.  Origially
  issue #14331 contained the code tweak as well as a bug fix, but since
  the issue was reported as a tweak the bug fix portion was moved into
  issue #15539.  Both the tweak and the bug fix contained minor incorrect
  logic that resulted in some SIP registrations to fail.
  
  (issue #14331)
  (issue #15539)
........

Modified:
    branches/1.6.0/   (props changed)
    branches/1.6.0/channels/chan_sip.c
    branches/1.6.0/configs/sip.conf.sample

Propchange: branches/1.6.0/
------------------------------------------------------------------------------
Binary property 'trunk-merged' - no diff available.

Modified: branches/1.6.0/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.6.0/channels/chan_sip.c?view=diff&rev=242514&r1=242513&r2=242514
==============================================================================
--- branches/1.6.0/channels/chan_sip.c (original)
+++ branches/1.6.0/channels/chan_sip.c Fri Jan 22 18:42:09 2010
@@ -177,6 +177,7 @@
 #include "asterisk/ast_version.h"
 #include "asterisk/event.h"
 #include "asterisk/tcptls.h"
+#include "asterisk/strings.h"
 
 #ifndef FALSE
 #define FALSE    0
@@ -6520,60 +6521,198 @@
 	int portnum = 0;
 	enum sip_transport transport = SIP_TRANSPORT_UDP;
 	char buf[256] = "";
-	char *username = NULL;
-	char *port = NULL;
-	char *hostname=NULL, *secret=NULL, *authuser=NULL, *tmp=NULL;
-	char *callback=NULL, *peername=NULL;
+	char *userpart = NULL, *hostpart = NULL;
+	/* register => [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] */
+	AST_DECLARE_APP_ARGS(pre1,
+		AST_APP_ARG(peer);
+		AST_APP_ARG(userpart);
+	);
+	AST_DECLARE_APP_ARGS(pre2,
+		AST_APP_ARG(transport);
+		AST_APP_ARG(blank);
+		AST_APP_ARG(userpart);
+	);
+	AST_DECLARE_APP_ARGS(user1,
+		AST_APP_ARG(userpart);
+		AST_APP_ARG(secret);
+		AST_APP_ARG(authuser);
+	);
+	AST_DECLARE_APP_ARGS(user2,
+		AST_APP_ARG(userpart);
+		AST_APP_ARG(domain);
+	);
+	AST_DECLARE_APP_ARGS(host1,
+		AST_APP_ARG(hostpart);
+		AST_APP_ARG(expiry);
+	);
+	AST_DECLARE_APP_ARGS(host2,
+		AST_APP_ARG(hostpart);
+		AST_APP_ARG(extension);
+	);
+	AST_DECLARE_APP_ARGS(host3,
+		AST_APP_ARG(host);
+		AST_APP_ARG(port);
+	);
 
 	if (!value)
 		return -1;
 
 	ast_copy_string(buf, value, sizeof(buf));
 
-	/* split [peername?][transport://] */
-	tmp = strchr(buf, '?');
-	if (tmp) {
-		*tmp++ = '\0';
-		peername = buf;
+	/*! register => [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry]
+	 * becomes
+	 *   userpart => [peer?][transport://]user[@domain][:secret[:authuser]]
+	 *   hostpart => host[:port][/extension][~expiry]
+	 */
+	if ((hostpart = strrchr(buf, '@'))) {
+		*hostpart++ = '\0';
+		userpart = buf;
+	}
+
+	if (ast_strlen_zero(userpart) || ast_strlen_zero(hostpart)) {
+		ast_log(LOG_WARNING, "Format for registration is [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] at line %d\n", lineno);
+		return -1;
+	}
+
+	/*!
+	 * pre1.peer => peer
+	 * pre1.userpart => [transport://]user[@domain][:secret[:authuser]]
+	 * hostpart => host[:port][/extension][~expiry]
+	 */
+	AST_NONSTANDARD_RAW_ARGS(pre1, userpart, '?');
+	if (ast_strlen_zero(pre1.userpart)) {
+		pre1.userpart = pre1.peer;
+		pre1.peer = NULL;
+	}
+
+	/*!
+	 * pre1.peer => peer
+	 * pre2.transport = transport
+	 * pre2.userpart => user[@domain][:secret[:authuser]]
+	 * hostpart => host[:port][/extension][~expiry]
+	 */
+	AST_NONSTANDARD_RAW_ARGS(pre2, userpart, '/');
+	if (ast_strlen_zero(pre2.userpart)) {
+		pre2.userpart = pre2.transport;
+		pre2.transport = NULL;
 	} else {
-		tmp = buf;
-	}
-	/* tmp is set at the beginning of [transport://] */
-	sip_parse_host(tmp, lineno, &username, &portnum, &transport);
-
-	/* First split around the last '@' then parse the two components. */
-	hostname = strrchr(username, '@'); /* allow @ in the first part */
-	if (hostname)
-		*hostname++ = '\0';
-	if (ast_strlen_zero(username) || ast_strlen_zero(hostname)) {
-		ast_log(LOG_WARNING, "Format for registration is [transport://]user[@domain][:secret[:authuser]]@host[:port][/extension] at line %d\n", lineno);
+		pre2.transport[strlen(pre2.transport) - 1] = '\0'; /* Remove trailing : */
+	}
+
+	if (!ast_strlen_zero(pre2.blank)) {
+		ast_log(LOG_WARNING, "Format for registration is [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] at line %d\n", lineno);
 		return -1;
 	}
-	/* split user[:secret[:authuser]] */
-	secret = strchr(username, ':');
-	if (secret) {
-		*secret++ = '\0';
-		authuser = strchr(secret, ':');
-		if (authuser)
-			*authuser++ = '\0';
-	}
-
-	/* split host[:port][/contact] */
-	callback = strchr(hostname, '/');
-	if (callback)
-		*callback++ = '\0';
-	if (ast_strlen_zero(callback))
-		callback = "s";
-	/* Separate host from port when checking for reserved characters
+
+	/*!
+	 * pre1.peer => peer
+	 * pre2.transport = transport
+	 * user1.userpart => user[@domain]
+	 * user1.secret => secret
+	 * user1.authuser => authuser
+	 * hostpart => host[:port][/extension][~expiry]
 	 */
-	if ((port = strchr(hostname, ':'))) {
-		*port = '\0';
-	}
-	/* And then re-merge the host and port so they are stored correctly
+	AST_NONSTANDARD_RAW_ARGS(user1, pre2.userpart, ':');
+
+	/*!
+	 * pre1.peer => peer
+	 * pre2.transport = transport
+	 * user1.userpart => user[@domain]
+	 * user1.secret => secret
+	 * user1.authuser => authuser
+	 * host1.hostpart => host[:port][/extension]
+	 * host1.expiry => [expiry]
 	 */
-	if (port) {
-		*port = ':';
-	}
+	AST_NONSTANDARD_RAW_ARGS(host1, hostpart, '~');
+
+	/*!
+	 * pre1.peer => peer
+	 * pre2.transport = transport
+	 * user1.userpart => user[@domain]
+	 * user1.secret => secret
+	 * user1.authuser => authuser
+	 * host2.hostpart => host[:port]
+	 * host2.extension => [extension]
+	 */
+	AST_NONSTANDARD_RAW_ARGS(host2, host1.hostpart, '/');
+
+	/*!
+	 * pre1.peer => peer
+	 * pre2.transport = transport
+	 * user1.userpart => user[@domain]
+	 * user1.secret => secret
+	 * user1.authuser => authuser
+	 * host3.host => host
+	 * host3.port => port
+	 * host2.extension => extension
+	 * host1.expiry => expiry
+	 */
+	AST_NONSTANDARD_RAW_ARGS(host3, host2.hostpart, ':');
+
+	/*!
+	 * pre1.peer => peer
+	 * pre2.transport = transport
+	 * user2.userpart => user
+	 * user2.domain => domain (regdomain)
+	 * user1.secret => secret
+	 * user1.authuser => authuser
+	 * host3.host => host
+	 * host3.port => port
+	 * host2.extension => extension (callback)
+	 * host1.expiry => expiry
+	 */
+	AST_NONSTANDARD_RAW_ARGS(user2, user1.userpart, '@');
+
+	/*!
+	 * pre1.peer => peer
+	 * transport = transport
+	 * user2.userpart => user
+	 * user2.domain => domain (regdomain)
+	 * user1.secret => secret
+	 * user1.authuser => authuser
+	 * host3.host => host
+	 * portnum => port
+	 * host2.extension => extension (callback)
+	 * host1.expiry => expiry
+	 */
+	if (host3.port) {
+		if (sscanf(host3.port, "%5u", &portnum) != 1 || portnum > 65535) {
+			ast_log(LOG_NOTICE, "'%s' is not a valid port number on line %d of sip.conf. using default.\n", host3.port, lineno);
+			portnum = -1;
+		}
+	}
+
+	/*!
+	 * pre1.peer => peer
+	 * transport = transport
+	 * user2.userpart => user
+	 * user2.domain => domain (regdomain)
+	 * user1.secret => secret
+	 * user1.authuser => authuser
+	 * host3.host => host
+	 * portnum => port
+	 * host2.extension => extension (callback)
+	 * host1.expiry => expiry
+	 */
+	if (!pre2.transport) {
+		transport = SIP_TRANSPORT_UDP;
+	} else if (!strncasecmp(pre2.transport, "tcp", 3)) {
+		transport = SIP_TRANSPORT_TCP;
+	} else if (!strncasecmp(pre2.transport, "tls", 3)) {
+		transport = SIP_TRANSPORT_TLS;
+		if (portnum < 0) {
+			portnum = STANDARD_TLS_PORT;
+		}
+	} else if (!strncasecmp(pre2.transport, "udp", 3)) {
+		transport = SIP_TRANSPORT_UDP;
+	} else {
+		ast_log(LOG_NOTICE, "'%.3s' is not a valid transport type on line %d of sip.conf. defaulting to udp.\n", pre2.transport, lineno);
+	}
+
+	if (portnum < 0) {
+		portnum = STANDARD_SIP_PORT;
+	}
+
 	if (!(reg = ast_calloc(1, sizeof(*reg)))) {
 		ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n");
 		return -1;
@@ -6585,26 +6724,31 @@
 		return -1;
 	}
 
+	/*!
+	 * pre1.peer => peer
+	 * transport = transport
+	 * user2.userpart => user
+	 * user2.domain => domain (regdomain)
+	 * user1.secret => secret
+	 * user1.authuser => authuser
+	 * host3.host => host
+	 * portnum => port
+	 * host2.extension => extension (callback)
+	 * host1.expiry => expiry
+	 */
 	regobjs++;
 	ASTOBJ_INIT(reg);
-	ast_string_field_set(reg, callback, callback);
-	if (!ast_strlen_zero(username))
-		ast_string_field_set(reg, username, username);
-	if (hostname)
-		ast_string_field_set(reg, hostname, hostname);
-	if (authuser)
-		ast_string_field_set(reg, authuser, authuser);
-	if (secret)
-		ast_string_field_set(reg, secret, secret);
-	if (peername) {
-		ast_string_field_set(reg, peername, peername);
-	}
+	ast_string_field_set(reg, callback, ast_strip_quoted(S_OR(host2.extension, "s"), "\"", "\""));
+	ast_string_field_set(reg, username, ast_strip_quoted(S_OR(user2.userpart, ""), "\"", "\""));
+	ast_string_field_set(reg, hostname, ast_strip_quoted(S_OR(host3.host, ""), "\"", "\""));
+	ast_string_field_set(reg, domain, ast_strip_quoted(S_OR(user2.domain, S_OR(host3.host, "")), "\"", "\""));
+	ast_string_field_set(reg, authuser, ast_strip_quoted(S_OR(user1.authuser, ""), "\"", "\""));
+	ast_string_field_set(reg, secret, ast_strip_quoted(S_OR(user1.secret, ""), "\"", "\""));
+	ast_string_field_set(reg, peername, ast_strip_quoted(S_OR(pre1.peer, ""), "\"", "\""));
+
 	reg->transport = transport;
-	reg->expire = -1;
-	reg->configured_expiry = default_expiry;
-	reg->expiry = reg->configured_expiry;
-	reg->timeout =  -1;
-	reg->refresh = default_expiry;
+	reg->timeout = reg->expire = -1;
+	reg->refresh = reg->expiry = reg->configured_expiry = (host1.expiry ? atoi(ast_strip_quoted(host1.expiry, "\"", "\"")) : default_expiry);
 	reg->portno = portnum;
 	reg->callid_valid = FALSE;
 	reg->ocseq = INITIAL_CSEQ;
@@ -10100,6 +10244,7 @@
 	char addr[80];
 	struct sip_pvt *p;
 	char *fromdomain;
+	char *domainport = NULL;
 
 	/* exit if we are already in process with this registrar ?*/
 	if ( r == NULL || ((auth==NULL) && (r->regstate==REG_STATE_REGSENT || r->regstate==REG_STATE_AUTHSENT))) {
@@ -10165,9 +10310,10 @@
 		ast_string_field_set(r, callid, p->callid);
 		if (r->portno) {
 			p->sa.sin_port = htons(r->portno);
-			p->recv.sin_port = htons(r->portno);
-		} else 	/* Set registry port to the port set from the peer definition/srv or default */
+ 			p->recv.sin_port = htons(r->portno);
+		} else {	/* Set registry port to the port set from the peer definition/srv or default */
 			r->portno = ntohs(p->sa.sin_port);
+		}
 		ast_set_flag(&p->flags[0], SIP_OUTGOING);	/* Registration is outgoing call */
 		r->call = p;		/* Save pointer to SIP dialog */
 		p->registry = registry_addref(r);	/* Add pointer to registry in packet */
@@ -10235,14 +10381,27 @@
 		else
 			snprintf(to, sizeof(to), "<sip:%s@%s>", r->username, p->tohost);
 	}
-	
+
 	/* Fromdomain is what we are registering to, regardless of actual
-	   host name from SRV */
+  	   host name from SRV */
 	if (!ast_strlen_zero(p->fromdomain)) {
-		if (r->portno && r->portno != STANDARD_SIP_PORT)
-			snprintf(addr, sizeof(addr), "sip:%s:%d", p->fromdomain, r->portno);
-		else
-			snprintf(addr, sizeof(addr), "sip:%s", p->fromdomain);
+		domainport = strrchr(p->fromdomain, ':');
+		if (domainport) {
+			*domainport++ = '\0'; /* trim off domainport from p->fromdomain */
+			if (ast_strlen_zero(domainport))
+				domainport = NULL;
+		}
+		if (domainport) {
+			if (atoi(domainport) != STANDARD_SIP_PORT)
+				snprintf(addr, sizeof(addr), "sip:%s:%s", p->fromdomain, domainport);
+			else
+				snprintf(addr, sizeof(addr), "sip:%s", p->fromdomain);
+		} else {
+			if (r->portno && r->portno != STANDARD_SIP_PORT)
+				snprintf(addr, sizeof(addr), "sip:%s:%d", p->fromdomain, r->portno);
+			else
+				snprintf(addr, sizeof(addr), "sip:%s", p->fromdomain);
+		}
 	} else {
 		if (r->portno && r->portno != STANDARD_SIP_PORT)
 			snprintf(addr, sizeof(addr), "sip:%s:%d", r->hostname, r->portno);
@@ -10269,7 +10428,6 @@
 	if (!ast_strlen_zero(global_useragent))
 		add_header(&req, "User-Agent", global_useragent);
 
-	
 	if (auth) 	/* Add auth header */
 		add_header(&req, authheader, auth);
 	else if (!ast_strlen_zero(r->nonce)) {

Modified: branches/1.6.0/configs/sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/branches/1.6.0/configs/sip.conf.sample?view=diff&rev=242514&r1=242513&r2=242514
==============================================================================
--- branches/1.6.0/configs/sip.conf.sample (original)
+++ branches/1.6.0/configs/sip.conf.sample Fri Jan 22 18:42:09 2010
@@ -437,7 +437,7 @@
 ;----------------------------------------- OUTBOUND SIP REGISTRATIONS  ------------------------
 ; Asterisk can register as a SIP user agent to a SIP proxy (provider)
 ; Format for the register statement is:
-;       register => [transport://]user[@domain][:secret[:authuser]]@host[:port][/extension]
+;       register => [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry]
 ;
 ; 
 ;




More information about the asterisk-commits mailing list