[Home]

Summary:ASTERISK-11206: Cancel sending not conform to SIP RFC 3261
Reporter:Gaspar Zoltan (gasparz)Labels:
Date Opened:2008-01-11 03:58:19.000-0600Date Closed:2011-06-07 14:08:01
Priority:MinorRegression?No
Status:Closed/CompleteComponents:Channels/chan_sip/General
Versions:Frequency of
Occurrence
Related
Issues:
Environment:Attachments:
Description:See the following call flow.

Src ip is asterisk
Date              Src IP Dst IP Packet type
2008-01-10 10:57:24 ip1 ip2 INVITE sip:number@ip2 SIP/2.0.
2008-01-10 10:57:24 ip2 ip1 SIP/2.0 100 Trying.
2008-01-10 10:57:26 ip2 ip1 SIP/2.0 180 Ringing.
2008-01-10 10:57:49 ip2 ip1 SIP/2.0 180 Ringing.
2008-01-10 10:57:49 ip1 ip2 CANCEL sip:number@ip2 SIP/2.0.
2008-01-10 10:57:49 ip2 ip1 SIP/2.0 200 OK. (CSeq: 102 INVITE.!!!!)
2008-01-10 10:57:49 ip1 ip2 ACK sip:number1@ip2; SIP/2.0
2008-01-10 10:57:49 ip1 ip2 BYE sip:number1@ip2; SIP/2.0
2008-01-10 10:57:49 ip2 ip1 SIP/2.0 481 Call/Transaction Does Not Exist. (CSeq: 102 CANCEL.!!!)
2008-01-10 10:57:49 ip2 ip1 SIP/2.0 200 OK. (CSeq: 103 BYE.)
2008-01-10 10:57:50 ip1 ip2 CANCEL sip:number@ip2 SIP/2.0.
2008-01-10 10:57:50 ip2 ip1 SIP/2.0 200 OK. (CSeq: 102 CANCEL.)
2008-01-10 10:57:51 ip1 ip2 CANCEL sip:number@ip2 SIP/2.0.
2008-01-10 10:57:51 ip2 ip1 SIP/2.0 200 OK. CSeq: 102 CANCEL.
2008-01-10 10:57:53 ip1 ip2 CANCEL sip:number@ip2 SIP/2.0.
2008-01-10 10:57:53 ip2 ip1 SIP/2.0 200 OK. CSeq: 102 CANCEL.
2008-01-10 10:57:57 ip1 ip2 CANCEL sip:number@ip2 SIP/2.0.
2008-01-10 10:57:57 ip2 ip1 SIP/2.0 200 OK. CSeq: 102 CANCEL.
2008-01-10 10:58:01 ip1 ip2 CANCEL sip:number@ip2 SIP/2.0.
2008-01-10 10:58:01 ip2 ip1 SIP/2.0 200 OK. CSeq: 102 CANCEL.
2008-01-10 10:58:05 ip1 ip2 CANCEL sip:number@ip2 SIP/2.0.
2008-01-10 10:58:05 ip2 ip1 SIP/2.0 200 OK. CSeq: 102 CANCEL.

so we want to cancel after we received the 180 ringing from ip2. But while we send the first cancel (sending this cancel is correct) the ip2 accepts the call (200 ok). Now we have a strange situation. Asterisk confirms the 200 ok for the invite with an ACK, then imidiatly sends a BYE request. The ip2 accepts the bye with a 200 ok, great.

Now the strange things:
ip2 sends 481 Call/Transaction Does Not Exist. for the cancel request. I don't know how good is this message, but this is not the issue.

After the ip2 sends the 200 ok for the bye we resend the cancel. I understand asterisk sees no 200 ok for the cancel and it resends it after exactly 1 second, a normal packet retransmision, BUT it shouldn't. In this case the 200 ok that accepts the invite, or at least the 200 ok for the bye should block the sending, retransmision of the cancel packet.

Because: (sip RFC 3261)
page 42:
"Once the CANCEL is constructed, the client SHOULD check whether it has received any response (provisional
or final) for the request being cancelled (herein referred to as the “original request”).
If no provisional response has been received, the CANCEL request MUST NOT be sent; rather, the client
MUST wait for the arrival of a provisional response before sending the request. If the original request has
generated a final response, the CANCEL SHOULD NOT be sent, as it is an effective no-op, since CANCEL
has no effect on requests that have already generated a final response."

But anyway after the second cancel we receive a 200 ok message acknowlegeing the cancel so the cancel retransmition should be stoped at least at this point.

But no the rettransmission continues another 5 times (I think until it reaches max_retrans for the packet).
Comments:By: Gaspar Zoltan (gasparz) 2008-01-11 04:02:27.000-0600

About how to reproduce this: this is really not easy, I captured this behavior from a production sistem, it is really timing sensitive. Maybe building a state machine that responds with this message flow or just put the patched version in production and let it run until the conditions become right again :). I don't have better ideas sorry.

By: Frederic LE FOLL (flefoll) 2008-01-11 05:24:12.000-0600

As far as CANCEL repetition is concerned, this is one more consequence of code in chan_sip.c sip_handle_request() (better renamed handle_incoming() in SVN trunk) that voluntarily ignores responses where CSeq is not the highest sent CSeq. In your case, Asterisk has sent a BYE after the CANCEL, thus it will ignore all responses except for the BYE. Consequence : retransmission mechanism keeps running for "unanswered :-(" CANCEL request.

A number of patches have been proposed by different people, probably none of them ideal, probably most of them preferable to current situation (imho).
http://bugs.digium.com/view.php?id=11231
http://bugs.digium.com/view.php?id=10946
http://bugs.digium.com/view.php?id=10915
http://bugs.digium.com/view.php?id=10052
http://bugs.digium.com/view.php?id=9567

By: Olle Johansson (oej) 2008-01-22 09:00:42.000-0600

Does it break the call? Affect the call in any way?

By: Olle Johansson (oej) 2008-01-22 09:01:52.000-0600

And yes, this is yet another case of a non-existent state machine for transactions, something that is already noted as a bug in the source code.

So the main question here is whether it affects the actual call?

By: Gaspar Zoltan (gasparz) 2008-01-22 10:55:10.000-0600

No, it does not affect the call in any way, but it is not a standard behaviour. This is the reason why I reported it.

By: Olle Johansson (oej) 2008-01-22 11:06:27.000-0600

Ok, then this is a well-known problem and I'm going to close this bug as it is a duplicate. Thanks for reporting this.