<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
<META content="MSHTML 6.00.2800.1264" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff>
<DIV><FONT face=Arial size=2>Hi all,</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2> I've found the following buggy
behaviour regarding retransmission of 407 responses. When asterisk is acting
like UA and calling outside trough a proxy, if the proxy retransmits 407
responses asterisk ack them (which is the proper behaviour) but also sends a new
INVITE with the Digest information but the CSeq augmented by one (new
transaction). The escenario is</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>Asterisk as UA ---> Proxy : INVITE
CSeq 102</FONT></DIV>
<DIV><FONT face=Arial size=2>Proxy ------> Asterisk as UA: 407 CSeq
102</FONT></DIV>
<DIV><FONT face=Arial size=2>
<DIV><FONT face=Arial size=2>Asterisk as UA ---> Proxy : ACK CSeq
102</FONT></DIV>
<DIV>
<DIV><FONT face=Arial size=2>Asterisk as UA ---> Proxy : INVITE
(with Digest info) CSeq 103</FONT></DIV></DIV>
<DIV><FONT face=Arial size=2>Proxy ------> Asterisk as UA: 407 CSeq 102
(RETRANSMISSION)
<DIV><FONT face=Arial size=2><FONT face=Arial size=2>Asterisk as UA
---> Proxy : ACK CSeq 102</FONT>
<DIV>
<DIV><FONT face=Arial size=2>Asterisk as UA ---> Proxy : INVITE
(with Digest info) CSeq 104 (NEW TRANSACTION)</FONT></DIV></DIV></FONT></DIV>
<DIV><FONT face=Arial size=2>Proxy ------> Asterisk as UA: 481
</FONT></DIV></FONT></DIV></FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>As seen the transaction with CSeq 104 will cause a
481 error. As per the RFC, the retransmitted 407 should be ACK'ed but it should
never originate a new transaction, not even a INVITE/Digest
retransmission</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>Going through the code I found that in the method
handle_request this scenario is controlled, and if packets are retransmitted are
marked as ignored. The ignore int acts as a boolean there. The problem is
that ignore information is not passed to handle_response method. The patch
below calls to handle response passing int ignored and checks in 407 handling
code block if the response is retransmission or not. If so, it is ack'ed but a
new transaction is not initiated</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>Please let me know if you consider the solution
good enough to include in the cvs code. Please, feel free to do it</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>Thanks for your time</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>Gines</FONT></DIV>
<DIV><FONT face=Arial size=2>Voz Telecom</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>--- chan_sip.c Sat Oct 25 22:05:17
2003<BR>+++ chan_sip.c.orig Sat Oct 25 22:05:53
2003<BR>@@ -4673,12 +4673,9
@@<BR>
/* First we ACK
*/<BR>
transmit_request(p, "ACK", seqno,
0);<BR>
/* Then we AUTH
*/<BR>-
/* But only if the packet wasn't marked as ignore in handle_request
*/<BR>-
if(!ignore){<BR>-
if ((p->authtries > 1) || do_proxy_auth(p, req, "INVITE", 1))
{<BR>-
ast_log(LOG_NOTICE, "Failed to authenticate on INVITE to '%s'\n",
get_header(&p->initreq,
"From"));<BR>-
p->needdestroy =
1;<BR>-
}<BR>+
if ((p->authtries > 1) || do_proxy_auth(p, req, "INVITE", 1))
{<BR>+
ast_log(LOG_NOTICE, "Failed to authenticate on INVITE to '%s'\n",
get_header(&p->initreq,
"From"));<BR>+
p->needdestroy =
1;<BR>
}<BR>
} else if (!strcasecmp(msg, "BYE"))
{<BR>
if (!strlen(p->peername))<BR>@@ -5237,7 +5234,7
@@<BR>
if (sscanf(e, "%i %n", &respid, &len) != 1)
{<BR>
ast_log(LOG_WARNING, "Invalid response: '%s'\n",
e);<BR>
} else
{<BR>-
handle_response(p, respid, e + len, req,
ignore);<BR>+
handle_response(p, respid, e + len,
req);<BR>
}<BR> } else
{<BR>
transmit_response_with_allow(p, "405 Method Not Allowed",
req);<BR></FONT></DIV></BODY></HTML>