From bc1e13dfc3f77c8a6bc07d50552638c1eb1563b3 Mon Sep 17 00:00:00 2001 From: Matthew Jordan <mjordan@digium.com> Date: Mon, 9 Feb 2015 02:44:24 +0000 Subject: [PATCH] channels/chan_sip: Ensure that a BYE is sent during INVITE w/Replaces transfer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consider a scenario where Alice and Bob have an established dialog with each other external to Asterisk. Bob decides to perform an attended transfer of Alice to Asterisk. In this case, Alice will send an INVITE with Replaces to Asterisk, where the Replaces specifies Bob's dialog with Asterisk. In this particular scenario, Asterisk will complete the transfer, but - since Bob's channel has had Alice masqueraded into it and is now a Zombie - a BYE request will not be sent. This patch fixes that issue by adding a new flag to chan_sip that tracks whether or not we have an INVITE with Replaces. If we do, the flag is used on the sip_pvt to ensure that a BYE request is sent, even if the channel has been masqueraded away. Review: https://reviewboard.asterisk.org/r/4362/ ASTERISK-22436 #close Reported by: Eelco Brolman Tested by: Jeremiah Gowdy, Kristian Høgh patches: asterisk-11-hangup-replaced-3.diff uploaded by Jeremiah Gowdy (License 6358) git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@431620 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 10 +++++++++- channels/sip/include/sip.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 52874228d2..1feccba01f 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -7044,7 +7044,7 @@ static int sip_hangup(struct ast_channel *ast) } /* Send a hangup */ - if (ast_channel_state(oldowner) == AST_STATE_UP) { + if (ast_channel_state(oldowner) == AST_STATE_UP || p->invitereplaces) { transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1); } @@ -8591,6 +8591,7 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr, make_our_tag(p); p->ocseq = INITIAL_CSEQ; p->allowed_methods = UINT_MAX; + p->invitereplaces = 0; if (sip_methods[intended_method].need_rtp) { p->maxcallbitrate = default_maxcallbitrate; @@ -24917,6 +24918,8 @@ static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, st struct ast_channel *replacecall = p->refer->refer_call->owner; /* The channel we're about to take over */ struct ast_channel *targetcall; /* The bridge to the take-over target */ + p->refer->refer_call->invitereplaces = 1; + /* Check if we're in ring state */ if (ast_channel_state(replacecall) == AST_STATE_RING) earlyreplace = 1; @@ -25026,6 +25029,11 @@ static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, st ast_channel_unlock(c); } + /* Clear SIP_DEFER_BYE_ON_TRANSFER after the masq to avoid delay hanging up replaced channel */ + sip_pvt_lock(p); + ast_clear_flag(&p->refer->refer_call->flags[0], SIP_DEFER_BYE_ON_TRANSFER); + sip_pvt_unlock(p); + /* c and c's tech pvt must be unlocked at this point for ast_hangup */ ast_hangup(c); /* this indicates to handle_request_do that the owner channel has already been unlocked */ diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h index 6b448bf075..87a8c68e32 100644 --- a/channels/sip/include/sip.h +++ b/channels/sip/include/sip.h @@ -1100,6 +1100,7 @@ struct sip_pvt { */ unsigned short req_secure_signaling:1;/*!< Whether we are required to have secure signaling or not */ unsigned short natdetected:1; /*!< Whether we detected a NAT when processing the Via */ + unsigned short invitereplaces:1; /*!< Whether we are doing an Invite: Replaces */ int timer_t1; /*!< SIP timer T1, ms rtt */ int timer_b; /*!< SIP timer B, ms */ unsigned int sipoptions; /*!< Supported SIP options on the other end */ -- GitLab