[svn-commits] dvossel: trunk r273427 - in /trunk/channels: chan_sip.c sip/include/sip.h

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Jul 1 11:40:21 CDT 2010


Author: dvossel
Date: Thu Jul  1 11:40:17 2010
New Revision: 273427

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=273427
Log:
correct handling of get_destination return values

A failure when calling the get_destination can mean multiple things.  If
the extension is not found, a 404 error is appropriate, but if the URI
scheme is incorrect, a 404 is not approperiate.  This patch adds the
get_destination_result enum to differentiate between these and other failure
types.  The only logical difference in this patch is that we now send a "416
Unsupported URI scheme" response instead of a "404" when the scheme is not
recognized.  This indicates to the initiator of the INVITE to retry the request
with a correct URI. 


Modified:
    trunk/channels/chan_sip.c
    trunk/channels/sip/include/sip.h

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=273427&r1=273426&r2=273427
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Thu Jul  1 11:40:17 2010
@@ -1446,7 +1446,7 @@
 static void check_via(struct sip_pvt *p, struct sip_request *req);
 static int get_rpid(struct sip_pvt *p, struct sip_request *oreq);
 static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason);
-static int get_destination(struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id);
+static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id);
 static int get_msg_text(char *buf, int len, struct sip_request *req, int addnewline);
 static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout);
 static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen);
@@ -13622,15 +13622,13 @@
 	We use the request uri as a destination.
 	This code assumes authentication has been done, so that the
 	device (peer/user) context is already set.
-	\return 0 on success (found a matching extension),
-	1 for pickup extension or overlap dialling support (if we support it),
-	-1 on error.
+	\return 0 on success (found a matching extension), non-zero on failure
 
   \note If the incoming uri is a SIPS: uri, we are required to carry this across
 	the dialplan, so that the outbound call also is a sips: call or encrypted
 	IAX2 call. If that's not available, the call should FAIL.
 */
-static int get_destination(struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id)
+static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id)
 {
 	char tmp[256] = "", *uri, *domain, *dummy = NULL;
 	char tmpf[256] = "", *from = NULL;
@@ -13649,7 +13647,7 @@
 
 	if (parse_uri(uri, "sip:,sips:", &uri, &dummy, &domain, &dummy, NULL)) {
 		ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", uri);
-		return -1;
+		return SIP_GET_DEST_INVALID_URI;
 	}
 
 	SIP_PEDANTIC_DECODE(domain);
@@ -13666,7 +13664,7 @@
 		from = get_in_brackets(tmpf);
 		if (parse_uri(from, "sip:,sips:", &from, NULL, &domain, NULL, NULL)) {
 			ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", from);
-			return -1;
+			return SIP_GET_DEST_INVALID_URI;
 		}
 
 		SIP_PEDANTIC_DECODE(from);
@@ -13682,7 +13680,7 @@
 		if (!check_sip_domain(p->domain, domain_context, sizeof(domain_context))) {
 			if (!sip_cfg.allow_external_domains && (req->method == SIP_INVITE || req->method == SIP_REFER)) {
 				ast_debug(1, "Got SIP %s to non-local domain '%s'; refusing request.\n", sip_methods[req->method].text, p->domain);
-				return -2;
+				return SIP_GET_DEST_REFUSED;
 			}
 		}
 		/* If we don't have a peer (i.e. we're a guest call),
@@ -13701,7 +13699,9 @@
 	/* If this is a subscription we actually just need to see if a hint exists for the extension */
 	if (req->method == SIP_SUBSCRIBE) {
 		char hint[AST_MAX_EXTENSION];
-		return (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten) ? 0 : -1);
+		return (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten) ?
+			SIP_GET_DEST_EXTEN_FOUND :
+			SIP_GET_DEST_EXTEN_NOT_FOUND);
 	} else {
 		struct ast_cc_agent *agent;
 		decoded_uri = ast_strdupa(uri);
@@ -13711,11 +13711,12 @@
 		   Since extensions.conf can have unescaped characters, try matching a decoded
 		   uri in addition to the non-decoded uri
 		   Return 0 if we have a matching extension */
-		if (ast_exists_extension(NULL, p->context, uri, 1, S_OR(p->cid_num, from)) || ast_exists_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from)) ||
+		if (ast_exists_extension(NULL, p->context, uri, 1, S_OR(p->cid_num, from)) ||
+			ast_exists_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from)) ||
 		    !strcmp(decoded_uri, ast_pickup_ext())) {
 			if (!oreq)
 				ast_string_field_set(p, exten, decoded_uri);
-			return 0;
+			return SIP_GET_DEST_EXTEN_FOUND;
 		} else if ((agent = find_sip_cc_agent_by_notify_uri(tmp))) {
 			struct sip_cc_agent_pvt *agent_pvt = agent->private_data;
 			/* This is a CC recall. We can set p's extension to the exten from
@@ -13731,7 +13732,7 @@
 				*cc_recall_core_id = agent->core_id;
 			}
 			ao2_ref(agent, -1);
-			return 0;
+			return SIP_GET_DEST_EXTEN_FOUND;
 		}
 	}
 
@@ -13739,10 +13740,10 @@
 	if((ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP) &&
  	    ast_canmatch_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from))) ||
 	    !strncmp(decoded_uri, ast_pickup_ext(), strlen(decoded_uri))) {
-		return 1;
-	}
-	
-	return -1;
+		return SIP_GET_DEST_PICKUP_EXTEN_FOUND;
+	}
+
+	return SIP_GET_DEST_EXTEN_NOT_FOUND;
 }
 
 /*! \brief Lock dialog lock and find matching pvt lock
@@ -19844,7 +19845,7 @@
 		return 0;
 	}
 
-	res = get_destination(p, req, NULL);
+	res = (get_destination(p, req, NULL) == SIP_GET_DEST_EXTEN_FOUND ? 0 : -1);
 	build_contact(p);
 
 	if (ast_strlen_zero(p->context))
@@ -20789,18 +20790,30 @@
 			ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
 		}
 
-		if (!replace_id && gotdest) {	/* No matching extension found */
-			if (gotdest == 1 && ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP))
-				transmit_response_reliable(p, "484 Address Incomplete", req);
-			else {
-				char *decoded_exten = ast_strdupa(p->exten);
-
-				transmit_response_reliable(p, "404 Not Found", req);
-				ast_uri_decode(decoded_exten);
-				ast_log(LOG_NOTICE, "Call from '%s' to extension"
-					" '%s' rejected because extension not found in context '%s'.\n",
-					S_OR(p->username, p->peername), decoded_exten, p->context);
-			}
+		if (!replace_id && (gotdest != SIP_GET_DEST_EXTEN_FOUND)) {	/* No matching extension found */
+			switch(gotdest) {
+			case SIP_GET_DEST_INVALID_URI:
+				transmit_response_reliable(p, "416 Unsupported URI scheme", req);
+				break;
+			case SIP_GET_DEST_PICKUP_EXTEN_FOUND:
+				if (ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) {
+					transmit_response_reliable(p, "484 Address Incomplete", req);
+					break;
+				}
+			/* INTENTIONAL FALL THROUGH */
+			case SIP_GET_DEST_EXTEN_NOT_FOUND:
+			case SIP_GET_DEST_REFUSED:
+			default:
+				{
+					char *decoded_exten = ast_strdupa(p->exten);
+					transmit_response_reliable(p, "404 Not Found", req);
+					ast_uri_decode(decoded_exten);
+					ast_log(LOG_NOTICE, "Call from '%s' to extension"
+						" '%s' rejected because extension not found in context '%s'.\n",
+						S_OR(p->username, p->peername), decoded_exten, p->context);
+				}
+			} /* end switch */
+
 			p->invitestate = INV_COMPLETED;
 			update_call_counter(p, DEC_CALL_LIMIT);
 			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
@@ -22609,8 +22622,12 @@
 	parse_ok_contact(p, req);
 
 	build_contact(p);
-	if (gotdest) {
-		transmit_response(p, "404 Not Found", req);
+	if (gotdest != SIP_GET_DEST_EXTEN_FOUND) {
+		if (gotdest == SIP_GET_DEST_INVALID_URI) {
+			transmit_response(p, "416 Unsupported URI scheme", req);
+		} else {
+			transmit_response(p, "404 Not Found", req);
+		}
 		pvt_set_needdestroy(p, "subscription target not found");
 		if (authpeer)
 			unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)");

Modified: trunk/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sip/include/sip.h?view=diff&rev=273427&r1=273426&r2=273427
==============================================================================
--- trunk/channels/sip/include/sip.h (original)
+++ trunk/channels/sip/include/sip.h Thu Jul  1 11:40:17 2010
@@ -447,6 +447,15 @@
 enum sip_auth_type {
 	PROXY_AUTH = 407,
 	WWW_AUTH = 401,
+};
+
+/*! \brief Result from get_destination function */
+enum sip_get_dest_result {
+	SIP_GET_DEST_PICKUP_EXTEN_FOUND = 1,
+	SIP_GET_DEST_EXTEN_FOUND = 0,
+	SIP_GET_DEST_EXTEN_NOT_FOUND = -1,
+	SIP_GET_DEST_REFUSED = -2,
+	SIP_GET_DEST_INVALID_URI = -3,
 };
 
 /*! \brief Authentication result from check_auth* functions */




More information about the svn-commits mailing list