mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-28 18:51:30 +00:00
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. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@278234 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -22131,20 +22131,10 @@ static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, int
|
||||
/*! \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);
|
||||
|
||||
/* 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)
|
||||
__sip_pretend_ack(p);
|
||||
else
|
||||
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);
|
||||
@@ -22152,6 +22142,17 @@ static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req)
|
||||
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 || p->invitestate == INV_COMPLETED) {
|
||||
__sip_pretend_ack(p);
|
||||
}
|
||||
if (p->invitestate != INV_TERMINATED)
|
||||
p->invitestate = INV_CANCELLED;
|
||||
|
||||
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);
|
||||
|
||||
|
Reference in New Issue
Block a user