[svn-commits] dvossel: trunk r278234 - /trunk/channels/chan_sip.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Jul 20 16:41:25 CDT 2010


Author: dvossel
Date: Tue Jul 20 16:41:21 2010
New Revision: 278234

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=278234
Log:
fixes sip CANCEL race condition

If Asterisk sends a 4xx error and the other side sends a CANCEl
before receiving the 4xx and responding with the ACK, Asterisk
will process the CANCEL and send a 487 Request Terminated as
a new final response to the INVITE.  Since we are issuing a new
final response to the INVITE, the old one must be pretend_acked
else it will keep retransmitting.

Modified:
    trunk/channels/chan_sip.c

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=278234&r1=278233&r2=278234
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Tue Jul 20 16:41:21 2010
@@ -22131,26 +22131,27 @@
 /*! \brief Handle incoming CANCEL request */
 static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req)
 {
-		
+
 	check_via(p, req);
 	sip_alreadygone(p);
+
+	if (p->owner && p->owner->_state == AST_STATE_UP) {
+		/* This call is up, cancel is ignored, we need a bye */
+		transmit_response(p, "200 OK", req);
+		ast_debug(1, "Got CANCEL on an answered call. Ignoring... \n");
+		return 0;
+	}
 
 	/* At this point, we could have cancelled the invite at the same time
 	   as the other side sends a CANCEL. Our final reply with error code
 	   might not have been received by the other side before the CANCEL
 	   was sent, so let's just give up retransmissions and waiting for
 	   ACK on our error code. The call is hanging up any way. */
-	if (p->invitestate == INV_TERMINATED)
+	if (p->invitestate == INV_TERMINATED || p->invitestate == INV_COMPLETED) {
 		__sip_pretend_ack(p);
-	else
+	}
+	if (p->invitestate != INV_TERMINATED)
 		p->invitestate = INV_CANCELLED;
-	
-	if (p->owner && p->owner->_state == AST_STATE_UP) {
-		/* This call is up, cancel is ignored, we need a bye */
-		transmit_response(p, "200 OK", req);
-		ast_debug(1, "Got CANCEL on an answered call. Ignoring... \n");
-		return 0;
-	}
 
 	if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD))
 		update_call_counter(p, DEC_CALL_LIMIT);




More information about the svn-commits mailing list