Hi Steve,<br><br>> So, TELL ME, please, that if totag is empty, that You Never Will See
more than one dialog with the same callid, <br>> and mayhaps with different
tag field values, or better yet, with different theirtag values.<br><br>I'd not get into the fundamental root of the problem (which is that we currently don't have a notion of sessions, dialogs and transactions as separate state machines), but to answer your question -- you could have a situation where a proxy forks an INVITE from Asterisk to several UASs some of which are RFC 2543 based. These UASs may not insert a To tag in their responses (To/From tags were optional in RFC 2543).
<br><br>I'm not sure I fully understand what all goes into computing your hash key, but To tag should not be a part of it (simply because it could be absent). I've personally dealt with this problem (in a different implementation) by only hashing on the Call-ID and then resolving the collision by checking something to the effect of the following:
<br><br><font color="#000000">(!totag[0] <span style="color: rgb(255, 0, 0);">&&</span><span style="background-color: rgb(255, 255, 255);"><span style="color: rgb(255, 0, 0);"> !p->tag[0]</span></span>) || (p->tag[0] && match(p->tag,totag))
</font><br><br>Thanks,<br>Raj<br><br><br><br><br><br><div class="gmail_quote">On Dec 20, 2007 4:57 PM, Steve Murphy <<a href="mailto:murf@parsetree.com">murf@parsetree.com</a>> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div>
On Wed, 2007-12-19 at 17:06 -0700, Steve Murphy wrote:<br>
<blockquote type="CITE">
<font color="#000000">Olle--</font><br>
<br>
<font color="#000000">I thought to double check with you... the price of missing something is pretty high.</font><br>
<br>
<font color="#000000">Put on your thinking cap, pull out some paper and a pencil, turn off the cell phone... this is going to require</font><br>
<font color="#000000">some thought!</font><br>
<br>
<br>
<font color="#000000">For reference, here's the search loop in find_call:</font><br>
<br>
<br>
<font color="#000000"> dialoglist_lock();</font><br>
<font color="#000000"> for (p = dialoglist; p; p = p->next) {</font><br>
<font color="#000000"> /* In pedantic, we do not want packets with bad syntax to be connected to a PVT */</font><br>
<font color="#000000"> int found = FALSE;</font><br>
<font color="#000000"> if (ast_strlen_zero(p->callid))</font><br>
<font color="#000000"> continue;</font><br>
<font color="#000000"> if (req->method == SIP_REGISTER)</font><br>
<font color="#000000"> found = (!strcmp(p->callid, callid));</font><br>
<font color="#000000"> else</font><br>
<font color="#000000"> found = (!strcmp(p->callid, callid) &&</font><br>
<font color="#000000"> (!pedanticsipchecking </font><font color="#ff0000">|| !tag ||</font><font color="#000000"> ast_strlen_zero(p->theirtag) || !strcmp(p->theirtag, tag))) ;</font><br>
<br>
<font color="#000000"> ast_debug(5, "= %s Their Call ID: %s Their Tag %s Our tag: %s\n", </font><br>
<font color="#000000"> found ? "Found" : "No match", p->callid, p->theirtag, p->tag);</font><br>
<br>
<font color="#000000"> /* If we get a new request within an existing to-tag - check the to tag as well */</font><br>
<font color="#000000"> if (pedanticsipchecking && found && req->method != SIP_RESPONSE) { /* SIP Request */</font><br>
<font color="#000000"> if (p->tag[0] == '\0' && totag[0]) {</font><br>
<font color="#000000"> /* We have no to tag, but they have. Wrong dialog */</font><br>
<font color="#000000"> found = FALSE;</font><br>
<font color="#000000"> } else if (totag[0]) { /* Both have tags, compare them */</font><br>
<font color="#000000"> if (strcmp(totag, p->tag)) {</font><br>
<font color="#000000"> found = FALSE; /* This is not our packet */</font><br>
<font color="#000000"> }</font><br>
<font color="#000000"> }</font><br>
<font color="#000000"> if (!found)</font><br>
<font color="#000000"> ast_debug(5, "= Being pedantic: This ... request: Call ID: %s Ourtag <null> Totag %s Method %s\n", </font><br>
<font color="#000000"> p->callid, totag, sip_methods[req->method].text);</font><br>
<font color="#000000"> }</font><br>
<br>
<br>
<font color="#000000"> if (found) {</font><br>
<font color="#000000"> /* Found the call */</font><br>
<font color="#000000"> sip_pvt_lock(p);</font><br>
<font color="#000000"> dialoglist_unlock();</font><br>
<font color="#000000"> return p;</font><br>
<font color="#000000"> }</font><br>
<font color="#000000"> }</font><br>
<font color="#000000"> dialoglist_unlock();</font><br>
<br>
<font color="#000000">The object: remove the loop, and replace it with astobj2 hash table lookups.</font><br>
<br>
<font color="#000000">I checked Luigi's astobj2 branch, where he put dialogs in a table, but he implements the above as a linear traversal, which is not my goal. I want to improve performance, not just convert the code to be astobj2 based...
</font><br>
<br>
<font color="#000000">There seem to be two main modes: with pedanticsipchecking ON, and pedanticsipchecking OFF.</font><br>
<hr noshade>
<br>
<br>
<br>
<br>
<font color="#000000">Things are simple in OFF mode:</font><br>
<br>
<font color="#000000">fundamentally, whether req->method is SIP_REGISTER or not, found is true when a dialog's callid matches.</font><br>
<font color="#000000">No code after setting found could disqualify this choice.</font><br>
<br>
<hr noshade>
<br>
<br>
<br>
<br>
<font color="#000000">Things get more complex in pedanticsipchecking ON mode:</font><br>
<br>
<font color="#000000">It seems split into whether req->method is SIP_REGISTER/SIP_RESPONSE or not:</font><br>
<br>
<font color="#000000">If req->method is SIP_REGISTER:</font><br>
<br>
<font color="#000000"> if match(p->callid,callid) AND (!totag[0] || (p->tag[0] && match(p->tag,totag)) </font><br>
<br>
<font color="#000000">else </font><br>
<br>
<font color="#000000"> If req->method is SIP_RESPONSE:</font><br>
<br>
<font color="#000000"> If callid matches AND ( empty(p->theirtag) || match(p->theirtag,tag)) </font><br>
<br>
<font color="#000000"> else</font><br>
<br>
<font color="#000000"> If callid matches AND (!totag[0] || (p->tag[0] && match(p->tag,totag)) </font><br>
<font color="#000000"> AND ( empty(p->theirtag) || match(p->theirtag,tag)) </font><br>
<br>
<font color="#000000">(I notice in the code that there is : ... </font><font color="#ff0000">|| !tag ||</font><font color="#000000"> ... which will never be true, and can be dropped)</font><br>
<br>
<hr noshade>
<br>
</blockquote>
<br>
<br>
OK, terms like: <font color="#000000">empty(p->theirtag) || match(p->theirtag,tag)</font> ,<br>
<br>
which means: "if p->theirtag is null/empty, then it doesn't affect the match, otherwise, it must match the tag.<br>
<br>
This I can handle just fine, most likely by trying to ao2_find with theirtag set, and if no match, look for a null theirtag match.<br>
<br>
<br>
But: <font color="#000000">(!totag[0] || (p->tag[0] && match(p->tag,totag)) </font><br>
<br>
means that if the totag is empty, then it matches whatever p->tag might be in the db. This is impossible to replicate in hashtable searches, because the search term is blank, and will not match any entries where the field is not blank.
<br>
Nor can I define another table, or even just enter another row with the tag field blank, BECAUSE THERE MIGHT BE A COLLISION.<br>
<br>
I have come to the conclusion that this is not necessarily a weakness in the trying to use hash tables. but could be a weakness in the linear search algorithm itself. If totag is empty, then you could conceivably fetch the wrong dialog from the db, which would probably just be the first one you hit in your traversal.
<br>
<br>
So, TELL ME, please, that if totag is empty, that You Never Will See more than one dialog with the same callid, and mayhaps with different tag field values, or better yet, with different theirtag values. <br>
<br>
--Before the search starts, I see this code:<br>
<br>
if (ast_strlen_zero(totag) && (req->method == SIP_ACK <br>
|| req->method == SIP_BYE <br>
|| req->method == SIP_INFO )) {<br>
ast_debug(5, "%s must have a to tag. dropping callid: %s from: %s\n", <br>
sip_methods[req->method].text , callid, from );<br>
return NULL;<br>
}<br>
<br>
This doesn't protect the SIP_REGISTER case; and the other non-SIP_RESPONSE cases:<br>
SIP_UNKNOWN, /*!< Unknown response */<br>
SIP_OPTIONS, /*!< Check capabilities of a device, used for "ping" too */<br>
SIP_NOTIFY, /*!< Status update, Part of the event package standard, result of a SUBSCRIBE or a REFER */<br>
SIP_INVITE, /*!< Set up a session */<br>
SIP_PRACK, /*!< Reliable pre-call signalling. Not supported in Asterisk. */<br>
SIP_REFER, /*!< Refer to another URI (transfer) */<br>
SIP_SUBSCRIBE, /*!< Subscribe for updates (voicemail, session status, device status, presence) */<br>
SIP_MESSAGE, /*!< Text messaging */<br>
SIP_UPDATE, /*!< Update a dialog. We can send UPDATE; but not accept it */<br>
SIP_CANCEL, /*!< Cancel an INVITE */<br>
SIP_PUBLISH, /*!< Not supported in Asterisk */<br>
SIP_PING, /*!< Not supported at all, no standard but still implemented out there */<br>
<br>
So, is there a problem here or not?<br>
<br>
murf<br>
<br>
<br>
</div>
<br>_______________________________________________<br>--Bandwidth and Colocation Provided by <a href="http://www.api-digital.com--" target="_blank">http://www.api-digital.com--</a><br><br>asterisk-dev mailing list<br>To UNSUBSCRIBE or update options visit:
<br> <a href="http://lists.digium.com/mailman/listinfo/asterisk-dev" target="_blank">http://lists.digium.com/mailman/listinfo/asterisk-dev</a><br></blockquote></div><br>