[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