[asterisk-commits] dvossel: branch dvossel/sip_request_transaction_matching r276598 - /team/dvos...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Jul 14 18:23:10 CDT 2010
Author: dvossel
Date: Wed Jul 14 18:23:06 2010
New Revision: 276598
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=276598
Log:
moved req to dialog matching into a 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=276598&r1=276597&r2=276598
==============================================================================
--- team/dvossel/sip_request_transaction_matching/channels/chan_sip.c (original)
+++ team/dvossel/sip_request_transaction_matching/channels/chan_sip.c Wed Jul 14 18:23:06 2010
@@ -7103,6 +7103,102 @@
return p;
}
+enum match_req_to_dialog_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 */
+ /* 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)) {
+ /* missing totag when they already gave us one earlier */
+ return SIP_REQ_NOT_MATCH;
+ }
+ if (strcmp(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)) {
+ /* 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)) {
+ /* 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))) {
+ /* 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)) {
+ /* 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 */
+
+ return SIP_REQ_MATCH;
+}
+
/*! \brief find or create a dialog structure for an incoming SIP message.
* Connect incoming SIP message to current dialog or create new dialog structure
* Returns a reference to the sip_pvt object, remember to give it back once done.
@@ -7174,113 +7270,28 @@
.callid = callid,
};
struct ao2_iterator *iterator = ao2_t_callback(dialogs, OBJ_POINTER | OBJ_MULTIPLE, dialog_find_multiple, &tmp_dialog, "pedantic ao2_find in dialogs");
+ int found;
/* Iterate a list of dialogs already matched by Call-id */
while (iterator && (sip_pvt_ptr = ao2_iterator_next(iterator))) {
- if (req->method == SIP_RESPONSE) {
- /* MATCH RESPONSE with DIALOG */
- /* 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)) {
- /* missing totag when they already gave us one earlier */
- goto not_a_match;
- }
- if (strcmp(totag, sip_pvt_ptr->theirtag)) {
- /* The totag of the response does not match the one we have stored */
- goto not_a_match;
- }
- }
- /* Verify fromtag of response matches the tag we gave them. */
- if (strcmp(fromtag, sip_pvt_ptr->tag)) {
- /* fromtag from response does not match our tag */
- goto not_a_match;
- }
- } else {
- /* MATCH REQUEST with DIALOG */
-
- /* Verify the fromtag of Request matches the tag they provided earlier. */
- if (strcmp(fromtag, sip_pvt_ptr->theirtag)) {
- /* their tag does not match the one was have stored for them */
- goto not_a_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))) {
- /* totag from Request does not match our tag */
- goto not_a_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 methods are different, then this does not match this dialog.
- * The only time this is not true is when the incoming request is a CANCEL. */
- if ((sip_pvt_ptr->method != req->method) && (req->method != SIP_CANCEL)) {
- /* not a match, methods are not the same */
- goto not_a_match;
- }
-
- /* If the Request-uris are different, then this is neither a match nor a forked request */
- if (sip_uri_cmp(initial_rlPart2, this_rlPart2)) {
- /* not a match, request uris are different */
- goto not_a_match;
- }
-
- /* At this point check to see if this is a Forked Request by comparing VIA headers.
- * If they are the same, this is a retransmit and this dialog matches, otherwise we have
- * a forked request. */
- 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)) {
-
- /* If we are here, everything matches the initial Request except for the top Via */
-
- /* 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.
- */
- goto loop_detected;
- }
- } /* end of Request Via check */
- } /* end of Request/Response matching */
-
- /* If we made it here, then this is a match. Leave the reference from the iterator */
- sip_pvt_lock(sip_pvt_ptr);
- ao2_iterator_destroy(iterator);
- return sip_pvt_ptr;
-
-loop_detected:
- /* This is likely a forked Request that somehow resulted in us receiving multiple parts of the fork.
- * RFC 3261 section 8.2.2.2, Indicate that we want to merge requests by sending a 482 response. */
- transmit_response_using_temp(callid, addr, 1, intended_method, req, "482 (Loop Detected)");
- dialog_unref(sip_pvt_ptr, "This pvt did not match incoming SIP msg, unref pvt from find_call search.");
- return NULL;
-not_a_match:
- dialog_unref(sip_pvt_ptr, "This pvt did not match incoming SIP msg, unref pvt from find_call search.");
- } /* end of while */
-
+ found = match_req_to_dialog(req, sip_pvt_ptr, totag, fromtag, seqno);
+
+ switch (found) {
+ case SIP_REQ_MATCH:
+ sip_pvt_lock(sip_pvt_ptr);
+ ao2_iterator_destroy(iterator);
+ return sip_pvt_ptr; /* return pvt with ref */
+ case SIP_REQ_LOOP_DETECTED:
+ /* This is likely a forked Request that somehow resulted in us receiving multiple parts of the fork.
+ * RFC 3261 section 8.2.2.2, Indicate that we want to merge requests by sending a 482 response. */
+ transmit_response_using_temp(callid, addr, 1, intended_method, req, "482 (Loop Detected)");
+ dialog_unref(sip_pvt_ptr, "This pvt did not match incoming SIP msg, unref pvt from find_call search.");
+ ao2_iterator_destroy(iterator);
+ return NULL;
+ case SIP_REQ_NOT_MATCH:
+ default:
+ dialog_unref(sip_pvt_ptr, "This pvt did not match incoming SIP msg, unref pvt from find_call search.");
+ }
+ }
if (iterator) {
ao2_iterator_destroy(iterator);
}
More information about the asterisk-commits
mailing list