[svn-commits] mmichelson: trunk r197959 - /trunk/channels/chan_sip.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri May 29 10:48:08 CDT 2009


Author: mmichelson
Date: Fri May 29 10:48:04 2009
New Revision: 197959

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=197959
Log:
A few fixes to SIP with regards to connected line updates during transfers.

* Set the invitestate to INV_CALLING when we send a connected line reinvite.
This prevents us from potentially rapid-firing reinvites to a single peer.

* Use the astdb to store a peer's allowed methods. This prevents us from sending
an UPDATE during the interval between startup and the peer's first registration
if the peer does not support the UPDATE method.

* Handle Polycom's method of indicating allowed methods in REGISTER. Instead of
using an Allow header, they place the allowed methods in a methods= parameter
in the Contact header.

ABE-1873


Modified:
    trunk/channels/chan_sip.c

Modified: trunk/channels/chan_sip.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/channels/chan_sip.c?view=diff&rev=197959&r1=197958&r2=197959
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Fri May 29 10:48:04 2009
@@ -7404,18 +7404,28 @@
 	unsigned int allowed_methods = SIP_UNKNOWN;
 
 	if (ast_strlen_zero(allow)) {
-		/* RFC 3261 states:
-		 *
-		 * "The absence of an Allow header field MUST NOT be
-		 * interpreted to mean that the UA sending the message supports no
-		 * methods.   Rather, it implies that the UA is not providing any
-		 * information on what methods it supports."
-		 *
-		 * For simplicity, we'll assume that the peer allows all known
-		 * SIP methods if they have no Allow header. We can then clear out the necessary
-		 * bits if the peer lets us know that we have sent an unsupported method.
+		/* I have witnessed that REGISTER requests from Polycom phones do not
+		 * place the phone's allowed methods in an Allow header. Instead, they place the
+		 * allowed methods in a methods= parameter in the Contact header.
 		 */
-		return UINT_MAX;
+		char *contact = ast_strdupa(get_header(req, "Contact"));
+		char *methods = strstr(contact, ";methods=");
+
+		if (ast_strlen_zero(methods)) {
+			/* RFC 3261 states:
+			 *
+			 * "The absence of an Allow header field MUST NOT be
+			 * interpreted to mean that the UA sending the message supports no
+			 * methods.   Rather, it implies that the UA is not providing any
+			 * information on what methods it supports."
+			 *
+			 * For simplicity, we'll assume that the peer allows all known
+			 * SIP methods if they have no Allow header. We can then clear out the necessary
+			 * bits if the peer lets us know that we have sent an unsupported method.
+			 */
+			return UINT_MAX;
+		}
+		allow = ast_strip_quoted(methods + 9, "\"", "\"");
 	}
 	for (method = strsep(&allow, ","); !ast_strlen_zero(method); method = strsep(&allow, ",")) {
 		int id = find_sip_method(ast_skip_blanks(method));
@@ -11020,6 +11030,7 @@
 			initialize_initreq(p, &req);
 			p->lastinvite = p->ocseq;
 			ast_set_flag(&p->flags[0], SIP_OUTGOING);
+			p->invitestate = INV_CALLING;
 			send_request(p, &req, XMIT_CRITICAL, p->ocseq);
 		} else if (is_method_allowed(&p->allowed_methods, SIP_UPDATE)) {
 			reqprep(&req, p, SIP_UPDATE, 0, 1);
@@ -11614,6 +11625,7 @@
 			ast_update_realtime(tablename, "name", peer->name, "fullcontact", "", "ipaddr", "", "port", "", "regseconds", "0", peer->deprecated_username ? "username" : "defaultuser", "", "regserver", "", "useragent", "", "lastms", "", SENTINEL);
 		} else {
 			ast_db_del("SIP/Registry", peer->name);
+			ast_db_del("SIP/PeerMethods", peer->name);
 		}
 	}
 }
@@ -11691,11 +11703,13 @@
 	int expire;
 	int port;
 	char *scan, *addr, *port_str, *expiry_str, *username, *contact;
+	char allowed_methods_str[256] = "";
 
 	if (peer->rt_fromcontact) 
 		return;
 	if (ast_db_get("SIP/Registry", peer->name, data, sizeof(data)))
 		return;
+	ast_db_get("SIP/PeerMethods", peer->name, allowed_methods_str, sizeof(allowed_methods_str));
 
 	scan = data;
 	addr = strsep(&scan, ":");
@@ -11721,6 +11735,10 @@
 		ast_string_field_set(peer, username, username);
 	if (contact)
 		ast_string_field_set(peer, fullcontact, contact);
+
+	if (!ast_strlen_zero(allowed_methods_str)) {
+		peer->allowed_methods = atoi(allowed_methods_str);
+	}
 
 	ast_debug(2, "SIP Seeding peer from astdb: '%s' at %s@%s:%d for %d\n",
 	    peer->name, peer->username, ast_inet_ntoa(in), port, expire);
@@ -12755,6 +12773,11 @@
 		ao2_lock(peer);
 		if (peer->allowed_methods == SIP_UNKNOWN) {
 			peer->allowed_methods = set_pvt_allowed_methods(p, req);
+		}
+		if (!peer->rt_fromcontact) {
+			char allowed_methods_str[256];
+			snprintf(allowed_methods_str, sizeof(allowed_methods_str), "%u", peer->allowed_methods);
+			ast_db_put("SIP/PeerMethods", peer->name, allowed_methods_str);
 		}
 		ao2_unlock(peer);
 		unref_peer(peer, "register_verify: unref_peer: tossing stack peer pointer at end of func");




More information about the svn-commits mailing list