[asterisk-commits] dvossel: branch dvossel/sip_forked_responses r289093 - /team/dvossel/sip_fork...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Sep 28 12:19:48 CDT 2010


Author: dvossel
Date: Tue Sep 28 12:19:45 2010
New Revision: 289093

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=289093
Log:
detect a forked 200ok response

Modified:
    team/dvossel/sip_forked_responses/channels/chan_sip.c

Modified: team/dvossel/sip_forked_responses/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/sip_forked_responses/channels/chan_sip.c?view=diff&rev=289093&r1=289092&r2=289093
==============================================================================
--- team/dvossel/sip_forked_responses/channels/chan_sip.c (original)
+++ team/dvossel/sip_forked_responses/channels/chan_sip.c Tue Sep 28 12:19:45 2010
@@ -7241,6 +7241,9 @@
 	const char *fromtag;
 	unsigned int seqno;
 
+	/* Set if this method is a Response */
+	int respid;
+
 	/* Set if the method is a Request */
 	const char *ruri;
 	const char *viabranch;
@@ -7254,6 +7257,7 @@
 	SIP_REQ_MATCH,
 	SIP_REQ_NOT_MATCH,
 	SIP_REQ_LOOP_DETECTED,
+	SIP_REQ_FORKED_RESPONSE,
 };
 
 /*
@@ -7276,6 +7280,12 @@
 		return SIP_REQ_NOT_MATCH;
 	}
 	if (arg->method == SIP_RESPONSE) {
+		/* Verify fromtag of response matches the tag we gave them. */
+		if (strcmp(arg->fromtag, sip_pvt_ptr->tag)) {
+			/* fromtag from response does not match our tag */
+			return SIP_REQ_NOT_MATCH;
+		}
+
 		/* Verify totag if we have one stored for this dialog, but never be strict about this for
 		 * a response until the dialog is established */
 		if (!ast_strlen_zero(sip_pvt_ptr->theirtag) && ast_test_flag(&sip_pvt_ptr->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED)) {
@@ -7283,15 +7293,35 @@
 				/* missing totag when they already gave us one earlier */
 				return SIP_REQ_NOT_MATCH;
 			}
+			/* compare the totag of response with the tag we have stored for them */
 			if (strcmp(arg->totag, sip_pvt_ptr->theirtag)) {
-				/* The totag of the response does not match the one we have stored */
+				/* totag did not match what we had stored for them. */
+				char invite_branch[32] = { 0, };
+				if (sip_pvt_ptr->invite_branch) {
+					snprintf(invite_branch, sizeof(invite_branch), "z9hG4bK%08x", (int) sip_pvt_ptr->invite_branch);
+				}
+				/* Forked Request Detection
+				 *
+				 * If this is a 200ok response and the totags do not match, this
+				 * might be a forked response to an outgoing Request. Detection of
+				 * a forked response must meet the criteria below.
+				 *
+				 * 1. must be a 2xx Response
+				 * 2. call-d equal to call-id of Request. this is done earlier
+				 * 3. from-tag equal to from-tag of Request. this is done earlier
+				 * 4. branch parameter equal to branch of inital Request
+				 * 5. to-tag _NOT_ equal to previous 2xx response that already established the dialog.
+				 */
+				if ((arg->respid == 200) &&
+					!ast_strlen_zero(invite_branch) &&
+					!ast_strlen_zero(arg->viabranch) &&
+					!strcmp(invite_branch, arg->viabranch)) {
+					return SIP_REQ_FORKED_RESPONSE;
+				}
+
+				/* The totag did not match the one we had stored, and this is not a Forked Request. */
 				return SIP_REQ_NOT_MATCH;
 			}
-		}
-		/* Verify fromtag of response matches the tag we gave them. */
-		if (strcmp(arg->fromtag, sip_pvt_ptr->tag)) {
-			/* fromtag from response does not match our tag */
-			return SIP_REQ_NOT_MATCH;
 		}
 	} else {
 		/* Verify the fromtag of Request matches the tag they provided earlier.
@@ -7473,14 +7503,20 @@
 		args.totag = totag;
 		args.fromtag = fromtag;
 		args.seqno = seqno;
-
-		/* If this is a Request, set the Via and Authorization header arguments */
-		if (req->method != SIP_RESPONSE) {
-			args.ruri = REQ_OFFSET_TO_STR(req, rlPart2);
-			get_viabranch(ast_strdupa(get_header(req, "Via")), (char **) &args.viasentby, (char **) &args.viabranch);
-			if (!ast_strlen_zero(get_header(req, "Authorization")) ||
-				!ast_strlen_zero(get_header(req, "Proxy-Authorization"))) {
-				args.authentication_present = 1;
+		/* get via header information. */
+		args.ruri = REQ_OFFSET_TO_STR(req, rlPart2);
+		get_viabranch(ast_strdupa(get_header(req, "Via")), (char **) &args.viasentby, (char **) &args.viabranch);
+		/* determine if this is a Request with authentication credentials. */
+		if (!ast_strlen_zero(get_header(req, "Authorization")) ||
+			!ast_strlen_zero(get_header(req, "Proxy-Authorization"))) {
+			args.authentication_present = 1;
+		}
+		/* if it is a response, get the response code */
+		if (req->method == SIP_RESPONSE) {
+			const char* e = ast_skip_blanks(REQ_OFFSET_TO_STR(req, rlPart2));
+			int respid;
+			if (!ast_strlen_zero(e) && (sscanf(e, "%30d", &respid) == 1)) {
+				args.respid = respid;
 			}
 		}
 
@@ -7500,6 +7536,8 @@
 				dialog_unref(sip_pvt_ptr, "pvt did not match incoming SIP msg, unref from search.");
 				ao2_iterator_destroy(iterator);
 				return NULL;
+			case SIP_REQ_FORKED_REQUEST:
+			//todohere handle forked request
 			case SIP_REQ_NOT_MATCH:
 			default:
 				dialog_unref(sip_pvt_ptr, "pvt did not match incoming SIP msg, unref from search");




More information about the asterisk-commits mailing list