Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 47646) +++ channels/chan_sip.c (working copy) @@ -4350,6 +4350,10 @@ const char *from = get_header(req, "From"); const char *to = get_header(req, "To"); const char *cseq = get_header(req, "Cseq"); + const char *their_local_tag; + const char *their_remote_tag; + int found = FALSE; + int chan_is_outgoing = ast_test_flag(&p->flags[0], SIP_OUTGOING); /* 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() */ @@ -4389,39 +4393,58 @@ dialoglist_lock(); for (p = dialoglist; p; p = p->next) { - /* In pedantic, we do not want packets with bad syntax to be connected to a PVT */ - int found = FALSE; - if (req->method == SIP_REGISTER) - found = (!strcmp(p->callid, callid)); - else - found = (!strcmp(p->callid, callid) && - (!pedanticsipchecking || !tag || ast_strlen_zero(p->theirtag) || !strcmp(p->theirtag, tag))) ; - - if (option_debug > 4) - ast_log(LOG_DEBUG, "= %s Their Call ID: %s Their Tag %s Our tag: %s\n", found ? "Found" : "No match", p->callid, p->theirtag, p->tag); - - /* If we get a new request within an existing to-tag - check the to tag as well */ - if (pedanticsipchecking && found && req->method != SIP_RESPONSE) { /* SIP Request */ - if (p->tag[0] == '\0' && totag[0]) { - /* We have no to tag, but they have. Wrong dialog */ - found = FALSE; - } else if (totag[0]) { /* Both have tags, compare them */ - if (strcmp(totag, p->tag)) { - found = FALSE; /* This is not our packet */ - } + /* try and find a channel with a matching callid */ + /* if pedantic check the tags as well */ + if (strcmp(p->callid, callid)) { + continue; + } + if (!pedanticsipchecking) { + found = TRUE; + break; + } + /* Cancel sometimes has no to tag, if this channel didn't send it we have found the right one */ + if ( req->method == SIP_CANCEL && totag[0] == '\0' && strcmp(p->tag, fromtag)) { + found = TRUE; + if (option_debug > 4 ) { + ast_log(LOG_DEBUG, "Found dialog for CANCEL callid: %s from: %s\n", callid, from); } - if (!found && option_debug > 4) - ast_log(LOG_DEBUG, "= Being pedantic: This is not our match on request: Call ID: %s Ourtag Totag %s Method %s\n", p->callid, totag, sip_methods[req->method].text); + break; } - - - if (found) { - /* Found the call */ - sip_pvt_lock(p); - dialoglist_unlock(); - return p; + if (req->method == SIP_RESPONSE) { + their_local_tag = totag; + their_remote_tag = fromtag; + } else { + their_local_tag = fromtag; + their_remote_tag = totag; } + /* see if we match both sets of tags. we have already filtered the request to make sure it */ + /* has the required tags for it's type, responses outside a dialog like 100 trying will find the */ + /* right channel because p->theirtag will also be empty */ + if ( strcmp(p->tag, their_remote_tag) ) { + continue; + } + if ( !strcmp(p->theirtag, their_local_tag)) { + if (option_debug > 4 ) { + ast_log(LOG_DEBUG, "%s callid: %s found channel: %p , local tag: %s remote tag: %s\n", sip_methods[req->method].text , callid ,p , p->tag, p->theirtag ); + } + found = TRUE; + break; + } + /* UAC channel does not have a dialog yet. reponse has a to tag establishing a new dialog */ + if ( p->theirtag[0] == '\0' && chan_is_outgoing && ( req->method == SIP_RESPONSE )) { + if (option_debug > 4 ) { + ast_log(LOG_DEBUG, "%s callid: %s found channel, response with new dialog, local tag: %s remote tag: %s\n", sip_methods[req->method].text , callid , p->tag, their_local_tag ); + } + found = TRUE; + break; + } } + if (found) { + /* Found the call */ + sip_pvt_lock(p); + dialoglist_unlock(); + return p; + } dialoglist_unlock(); /* See if the method is capable of creating a dialog */