[asterisk-commits] dvossel: branch dvossel/sip_request_transaction_matching r276732 - /team/dvos...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Jul 15 13:58:15 CDT 2010


Author: dvossel
Date: Thu Jul 15 13:58:11 2010
New Revision: 276732

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=276732
Log:
additional changes to moving req to dialog matching to separate function

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

Modified: team/dvossel/sip_request_transaction_matching/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/sip_request_transaction_matching/channels/chan_sip.c?view=diff&rev=276732&r1=276731&r2=276732
==============================================================================
--- team/dvossel/sip_request_transaction_matching/channels/chan_sip.c (original)
+++ team/dvossel/sip_request_transaction_matching/channels/chan_sip.c Thu Jul 15 13:58:11 2010
@@ -7103,98 +7103,126 @@
 	return p;
 }
 
-enum match_req_to_dialog_res {
+enum match_req_res {
 	SIP_REQ_MATCH,
 	SIP_REQ_NOT_MATCH,
 	SIP_REQ_LOOP_DETECTED,
 };
 
-static enum match_req_to_dialog_res match_req_to_dialog(struct sip_request *req, struct sip_pvt *sip_pvt_ptr, const char *totag, const char *fromtag, int seqno)
-{
-	if (req->method == SIP_RESPONSE) {
-		/* MATCH RESPONSE with DIALOG */
+struct match_req_args {
+	int method;
+	const char *callid;
+	const char *totag;
+	const char *fromtag;
+	int seqno;
+
+	/* these only need to be set if the method is a Request */
+	const char *ruri;
+	const char *viabranch;
+	const char *viasentby;
+};
+
+static enum match_req_res match_req_to_dialog(struct sip_pvt *sip_pvt_ptr, struct match_req_args *arg)
+{
+
+	/* Match Tags and call-id to Dialog */
+	if (!ast_strlen_zero(arg->callid) && strcmp(sip_pvt_ptr->callid, arg->callid)) {
+		/* call-id does not match. */
+		return SIP_REQ_NOT_MATCH;
+	}
+	if (arg->method == SIP_RESPONSE) {
 		/* 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)) {
-			if (ast_strlen_zero(totag)) {
+			if (ast_strlen_zero(arg->totag)) {
 				/* missing totag when they already gave us one earlier */
 				return SIP_REQ_NOT_MATCH;
 			}
-			if (strcmp(totag, sip_pvt_ptr->theirtag)) {
+			if (strcmp(arg->totag, sip_pvt_ptr->theirtag)) {
 				/* The totag of the response does not match the one we have stored */
 				return SIP_REQ_NOT_MATCH;
 			}
 		}
 		/* Verify fromtag of response matches the tag we gave them. */
-		if (strcmp(fromtag, sip_pvt_ptr->tag)) {
+		if (strcmp(arg->fromtag, sip_pvt_ptr->tag)) {
 			/* fromtag from response does not match our tag */
 			return SIP_REQ_NOT_MATCH;
 		}
 	} else {
-		/* MATCH REQUEST with DIALOG */
-
 		/* Verify the fromtag of Request matches the tag they provided earlier. */
-		if (strcmp(fromtag, sip_pvt_ptr->theirtag)) {
+		if (strcmp(arg->fromtag, sip_pvt_ptr->theirtag)) {
 			/* their tag does not match the one was have stored for them */
 			return SIP_REQ_NOT_MATCH;
 		}
 		/* Verify if totag is present in Request, that it matches what we gave them as our tag earlier */
-		if (!ast_strlen_zero(totag) && (strcmp(totag, sip_pvt_ptr->tag))) {
+		if (!ast_strlen_zero(arg->totag) && (strcmp(arg->totag, sip_pvt_ptr->tag))) {
 			/* totag from Request does not match our tag */
 			return SIP_REQ_NOT_MATCH;
 		}
-
-		/* If the totag is not present in the Request, then we must go forward with
-		 * attempting to match this Request to this dialog's initial transaction. */
-		if (ast_strlen_zero(totag) &&
-			(sip_pvt_ptr->init_icseq == seqno) &&
-			!ast_strlen_zero(sip_pvt_ptr->initviabranch)) {
-			char *sent_by, *branch;
-			const char *initial_rlPart2 = REQ_OFFSET_TO_STR(&sip_pvt_ptr->initreq, rlPart2);
-			const char *this_rlPart2 = REQ_OFFSET_TO_STR(req, rlPart2);
-
-			/* If the Request-URIs are different, then this is neither a match nor a forked request */
-			if (sip_uri_cmp(initial_rlPart2, this_rlPart2)) {
+	}
+
+	/* Initial Transaction Matching.
+	 * 
+	 * This is a best effort attempt at distinguishing forked requests from
+	 * our initial transaction.  If all the elements are NOT in place to evaluate
+	 * this, this block is ignored and the dialog match is made regardless.
+	 * Once the totag is established after the dialog is confirmed, this is not necessary.
+	 *
+	 * CRITERIA required for initial transaction matching.
+	 * 
+	 * 1. Is a Request
+	 * 2. Callid and theirtag match (this is done in the dialog matching block)
+	 * 3. totag is NOT present
+	 * 4. CSeq matchs our initial transaction's cseq number
+	 * 5. pvt has init via branch parameter stored
+	 */
+	if ((arg->method != SIP_RESPONSE) &&                 /* must be a Request */
+		ast_strlen_zero(arg->totag) &&                   /* must not have a totag */
+		(sip_pvt_ptr->init_icseq == arg->seqno) &&       /* the cseq must be the same as this dialogs initial cseq */
+		!ast_strlen_zero(sip_pvt_ptr->initviabranch)) {  /* The dialog must have started with a RFC3261 compliant branch tag */
+		const char *init_ruri = REQ_OFFSET_TO_STR(&sip_pvt_ptr->initreq, rlPart2);
+
+		/* This Request matches all the criteria required for Loop/Merge detection.
+		 * Now we must go down the patch of comparing VIA's and RURIs. */
+		if (ast_strlen_zero(arg->viabranch) ||
+			strcmp(arg->viabranch, sip_pvt_ptr->initviabranch) ||
+			ast_strlen_zero(arg->viasentby) ||
+			strcmp(arg->viasentby, sip_pvt_ptr->initviasentby)) {
+			/* At this point, this request does not match this Dialog.*/
+
+			/* if methods are different this is just a mismatch */
+			if ((sip_pvt_ptr->method != arg->method)) {
+				return SIP_REQ_NOT_MATCH;
+			}
+
+			/* If RUIs are different, this is a forked request to a separate URI.
+			 * Returning a mismatch allows this Request to be processed separately. */
+			if (sip_uri_cmp(init_ruri, arg->ruri)) {
 				/* not a match, request uris are different */
 				return SIP_REQ_NOT_MATCH;
 			}
 
-			/* The requests matched, now compare top VIA headers to see if this is the same transaction */
-			get_viabranch(ast_strdupa(get_header(req, "Via")), &sent_by, &branch);
-			if (ast_strlen_zero(branch) ||
-				strcmp(branch, sip_pvt_ptr->initviabranch) ||
-				ast_strlen_zero(sent_by) ||
-				strcmp(sent_by, sip_pvt_ptr->initviasentby)) {
-
-				/* The TOP VIA's do not match, but the Request-URI is the exact same. Check to
-				 * see if the method's match to determine if this is a forked request or not. */
-				if ((sip_pvt_ptr->method != req->method)) {
-					/* not a match and not a fork. methods are not the same */
-					return SIP_REQ_NOT_MATCH;
-				}
-
-				/* FORK DETECTION CRITERIA
-				 *
-				 * ---Current Matches to Initial Request---
-				 * request uri
-				 * Call-id
-				 * their-tag
-				 * no totag present
-				 * method
-				 * cseq
-				 *
-				 * --- Does not Match Initial Request ---
-				 * Top Via
-				 *
-				 * Without the same Via, this can not match our initial transaction for this dialog,
-				 * but given that this Request matches everything else associated with that initial
-				 * Request this is most certainly a Forked request in which we have already received
-				 * part of the fork.
-				 */
-				return SIP_REQ_LOOP_DETECTED;
-			}
-		} /* end of Request Via check */
-	} /* end of Request/Response matching */
+			/* Loop/Merge Detected
+			 *
+			 * ---Current Matches to Initial Request---
+			 * request uri
+			 * Call-id
+			 * their-tag
+			 * no totag present
+			 * method
+			 * cseq
+			 *
+			 * --- Does not Match Initial Request ---
+			 * Top Via
+			 *
+			 * Without the same Via, this can not match our initial transaction for this dialog,
+			 * but given that this Request matches everything else associated with that initial
+			 * Request this is most certainly a Forked request in which we have already received
+			 * part of the fork.
+			 */
+			return SIP_REQ_LOOP_DETECTED;
+		}
+	} /* end of Request Via check */
 
 	return SIP_REQ_MATCH;
 }
@@ -7213,9 +7241,8 @@
 	const char *from = get_header(req, "From");
 	const char *to = get_header(req, "To");
 	const char *cseq = get_header(req, "Cseq");
+	struct sip_pvt *sip_pvt_ptr;
 	int seqno;
-	struct sip_pvt *sip_pvt_ptr;
-
 	/* Call-ID, to, from and Cseq are required by RFC 3261. (Max-forwards and via too - ignored now) */
 	/* get_header always returns non-NULL so we must use ast_strlen_zero() */
 	if (ast_strlen_zero(callid) || ast_strlen_zero(to) ||
@@ -7269,11 +7296,23 @@
 		struct sip_pvt tmp_dialog = {
 			.callid = callid,
 		};
+		struct match_req_args args = { 0, };
 		struct ao2_iterator *iterator = ao2_t_callback(dialogs, OBJ_POINTER | OBJ_MULTIPLE, dialog_find_multiple, &tmp_dialog, "pedantic ao2_find in dialogs");
 		int found;
+
+		args.method = req->method;
+		args.callid = NULL; /* we already matched this. */
+		args.totag = totag;
+		args.fromtag = fromtag;
+		args.seqno = seqno;
+		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);
+		}
+
 		/* Iterate a list of dialogs already matched by Call-id */
 		while (iterator && (sip_pvt_ptr = ao2_iterator_next(iterator))) {
-			found = match_req_to_dialog(req, sip_pvt_ptr, totag, fromtag, seqno);
+			found = match_req_to_dialog(sip_pvt_ptr, &args);
 
 			switch (found) {
 			case SIP_REQ_MATCH:




More information about the asterisk-commits mailing list