[asterisk-commits] dvossel: branch dvossel/sip_request_transaction_matching r275997 - in /team/d...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Jul 13 12:02:03 CDT 2010
Author: dvossel
Date: Tue Jul 13 12:01:59 2010
New Revision: 275997
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=275997
Log:
store initial cseq number to match against possible forked requests
Modified:
team/dvossel/sip_request_transaction_matching/channels/chan_sip.c
team/dvossel/sip_request_transaction_matching/channels/sip/include/sip.h
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=275997&r1=275996&r2=275997
==============================================================================
--- team/dvossel/sip_request_transaction_matching/channels/chan_sip.c (original)
+++ team/dvossel/sip_request_transaction_matching/channels/chan_sip.c Tue Jul 13 12:01:59 2010
@@ -6913,8 +6913,12 @@
return NULL;
}
+ /* If this dialog is created as the result of an incoming Request. Lets store
+ * some information about that request */
if (req) {
char *sent_by, *branch;
+ const char *cseq = get_header(req, "Cseq");
+ int seqno;
/* get branch parameter from initial Request that started this dialog */
get_viabranch(ast_strdupa(get_header(req, "Via")), &sent_by, &branch);
/* only store the branch if it begins with the magic prefix "z9hG4bK", otherwise
@@ -6922,6 +6926,12 @@
if (!ast_strlen_zero(branch) && !strncasecmp(branch, "z9hG4bK", 7)) {
ast_string_field_set(p, initviabranch, branch);
ast_string_field_set(p, initviasentby, sent_by);
+ }
+
+ /* Store initial incoming cseq. An error in sscanf here is ignored. There is no approperiate
+ * except not storing the number. CSeq validation must take place before dialog creation in find_call */
+ if (!ast_strlen_zero(cseq) && (sscanf(cseq, "%30u", &seqno) == 1)) {
+ p->init_icseq = seqno;
}
set_socket_transport(&p->socket, req->socket.type); /* Later in ast_sip_ouraddrfor we need this to choose the right ip and port for the specific transport */
} else {
@@ -7042,12 +7052,14 @@
const char *from = get_header(req, "From");
const char *to = get_header(req, "To");
const char *cseq = get_header(req, "Cseq");
+ 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) ||
- ast_strlen_zero(from) || ast_strlen_zero(cseq)) {
+ ast_strlen_zero(from) || ast_strlen_zero(cseq) ||
+ (sscanf(cseq, "%30d", &seqno) != 1)) {
/* RFC 3261 section 24.4.1. Send a 400 Bad Request if the request is malformed. */
if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) {
@@ -7092,7 +7104,7 @@
sip_pvt_lock(sip_pvt_ptr);
return sip_pvt_ptr;
}
- } else { /* in pedantic mode! -- do the fancy linear search */
+ } else { /* in pedantic mode! -- do the fancy search */
struct sip_pvt tmp_dialog = {
.callid = callid,
};
@@ -7101,7 +7113,7 @@
while (iterator && (sip_pvt_ptr = ao2_iterator_next(iterator))) {
if (req->method == SIP_RESPONSE) {
/* MATCH RESPONSE with DIALOG */
- /* check totag if we have one stored for this dialog */
+ /* Verify totag if we have one stored for this dialog */
if (!ast_strlen_zero(sip_pvt_ptr->theirtag)) {
if (ast_strlen_zero(totag)) {
/* missing totag when they already gave us one earlier */
@@ -7112,45 +7124,72 @@
goto not_a_match;
}
}
- /* check fromtag of response matches the tag we gave them. */
+ /* 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;
}
- /* if totag is present in Request, verify it matches what we gave them as our tag earlier */
+
+ /* 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 totag is NOT present in Request, compare branch parameters with initial Request */
- if (ast_strlen_zero(totag) && !ast_strlen_zero(sip_pvt_ptr->initviabranch)) {
+
+ /* If totag is not present to match, and the CSeq is the same as our initial request,
+ * go down the path of comparing branch parameters with initial Request to verify whether
+ * this is a retransmit or a Forked Request */
+ if (ast_strlen_zero(totag) &&
+ (sip_pvt_ptr->init_icseq == seqno) &&
+ !ast_strlen_zero(sip_pvt_ptr->initviabranch)) {
char *sent_by, *branch;
- /* get branch parameter from top VIA header of Request */
+
+ /* If the methods are different, then this does not match this dialog. */
+ if (sip_pvt_ptr->method != req->method) {
+ /* If the methods are not the same, then this is just a mismatch. */
+ goto not_a_match;
+ }
+
+ /* Compare this Requests VIA header with our initial Request's top Via header.
+ * If they are the same, this is a retransmit and this dialog matches.*/
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 made it in here, the branch and sent_by of top VIA did not match our initial Request */
- if (sip_pvt_ptr->method != req->method) {
- /* If the methods are not the same, then this is just a normal mismatch. */
- goto not_a_match;
- } else {
- /* Loop Detected: everything is the EXACT same about this Request and the initial
- * request except the branch parameters are different in the TOP VIA. */
- goto loop_detected;
- }
+ /* If we are here, everything matches the initial Request except for the top Via */
+
+ /* FORK DETECTION CRITERIA
+ *
+ * ---Current Matches to Initial Request---
+ * 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);
@@ -7160,16 +7199,16 @@
/* 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 incomming SIP msg, unref pvt from find_call search.");
+ 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 incomming SIP msg, unref pvt from find_call search.");
+ dialog_unref(sip_pvt_ptr, "This pvt did not match incoming SIP msg, unref pvt from find_call search.");
} /* end of while */
if (iterator) {
ao2_iterator_destroy(iterator);
}
- }
+ } /* end of pedantic mode Request/Reponse to Dialog matching */
/* See if the method is capable of creating a dialog */
if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) {
Modified: team/dvossel/sip_request_transaction_matching/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/sip_request_transaction_matching/channels/sip/include/sip.h?view=diff&rev=275997&r1=275996&r2=275997
==============================================================================
--- team/dvossel/sip_request_transaction_matching/channels/sip/include/sip.h (original)
+++ team/dvossel/sip_request_transaction_matching/channels/sip/include/sip.h Tue Jul 13 12:01:59 2010
@@ -959,6 +959,7 @@
struct sip_socket socket; /*!< The socket used for this dialog */
unsigned int ocseq; /*!< Current outgoing seqno */
unsigned int icseq; /*!< Current incoming seqno */
+ unsigned int init_icseq; /*!< Initial incoming seqno from first request */
ast_group_t callgroup; /*!< Call group */
ast_group_t pickupgroup; /*!< Pickup group */
int lastinvite; /*!< Last Cseq of invite */
More information about the asterisk-commits
mailing list