From 4b07aa5f132d2f97097ccd140a28f68b777b36f7 Mon Sep 17 00:00:00 2001 From: Matthew Jordan Date: Tue, 14 Jan 2014 19:46:52 +0000 Subject: [PATCH] chan_sip: Hangup transferer/transferee when transfer to Parking fails When performing a SIP transfer to a Park extension, if the Park fails, chan_sip will currently not hang up either the transferer or the transfer target. This results in the channels being orphaned with no thread to service frames, resulting in stuck channels. This patch immediately hangs up the two channels if a Park fails. (closes issue ASTERISK-22834) Reported by: rsw686 Tested by: rsw686 (closes issue ASTERISK-23047) Reported by: Tommy Thompson Tested by: Tommy Thomspon Review: https://reviewboard.asterisk.org/r/3107 ........ Merged revisions 405380 from http://svn.asterisk.org/svn/asterisk/branches/11 git-svn-id: https://origsvn.digium.com/svn/asterisk/certified/branches/11.6@405536 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 3ecb0fdc36..d8af87ab74 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -24111,6 +24111,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc static void *sip_park_thread(void *stuff) { struct ast_channel *transferee, *transferer; /* Chan1: The transferee, Chan2: The transferer */ + struct sip_pvt *transferer_pvt; struct sip_dual *d; int ext; int res; @@ -24118,43 +24119,46 @@ static void *sip_park_thread(void *stuff) d = stuff; transferee = d->chan1; transferer = d->chan2; + transferer_pvt = ast_channel_tech_pvt(transferer); ast_debug(4, "SIP Park: Transferer channel %s, Transferee %s\n", ast_channel_name(transferer), ast_channel_name(transferee)); res = ast_park_call_exten(transferee, transferer, d->park_exten, d->park_context, 0, &ext); - sip_pvt_lock(ast_channel_tech_pvt(transferer)); + sip_pvt_lock(transferer_pvt); #ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE if (res) { - destroy_msg_headers(ast_channel_tech_pvt(transferer)); - ast_string_field_set(ast_channel_tech_pvt(transferer), msg_body, "Unable to park call."); - transmit_message(ast_channel_tech_pvt(transferer), 0, 0); + destroy_msg_headers(transferer_pvt); + ast_string_field_set(transferer_pvt, msg_body, "Unable to park call."); + transmit_message(transferer_pvt, 0, 0); } else { /* Then tell the transferer what happened */ - destroy_msg_headers(ast_channel_tech_pvt(transferer)); + destroy_msg_headers(transferer_pvt); sprintf(buf, "Call parked on extension '%d'.", ext); - ast_string_field_set(ast_channel_tech_pvt(transferer), msg_body, buf); - transmit_message(ast_channel_tech_pvt(transferer), 0, 0); + ast_string_field_set(transferer_pvt, msg_body, buf); + transmit_message(transferer_pvt, 0, 0); } #endif /* Any way back to the current call??? */ /* Transmit response to the REFER request */ + ast_set_flag(&transferer_pvt->flags[0], SIP_DEFER_BYE_ON_TRANSFER); if (!res) { /* Transfer succeeded */ - append_history(ast_channel_tech_pvt(transferer), "SIPpark", "Parked call on %d", ext); - transmit_notify_with_sipfrag(ast_channel_tech_pvt(transferer), d->seqno, "200 OK", TRUE); - sip_pvt_unlock(ast_channel_tech_pvt(transferer)); + append_history(transferer_pvt, "SIPpark", "Parked call on %d", ext); + transmit_notify_with_sipfrag(transferer_pvt, d->seqno, "200 OK", TRUE); + sip_pvt_unlock(transferer_pvt); ast_channel_hangupcause_set(transferer, AST_CAUSE_NORMAL_CLEARING); - ast_hangup(transferer); /* This will cause a BYE */ ast_debug(1, "SIP Call parked on extension '%d'\n", ext); } else { - transmit_notify_with_sipfrag(ast_channel_tech_pvt(transferer), d->seqno, "503 Service Unavailable", TRUE); - append_history(ast_channel_tech_pvt(transferer), "SIPpark", "Parking failed\n"); - sip_pvt_unlock(ast_channel_tech_pvt(transferer)); - ast_debug(1, "SIP Call parked failed \n"); - /* Do not hangup call */ + transmit_notify_with_sipfrag(transferer_pvt, d->seqno, "503 Service Unavailable", TRUE); + append_history(transferer_pvt, "SIPpark", "Parking failed\n"); + sip_pvt_unlock(transferer_pvt); + ast_log(AST_LOG_NOTICE, "SIP Call parked failed for %s\n", ast_channel_name(transferee)); + ast_hangup(transferee); } + ast_hangup(transferer); + deinit_req(&d->req); ast_free(d->park_exten); ast_free(d->park_context); @@ -24224,6 +24228,7 @@ static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct /* Prepare for taking over the channel */ if (ast_channel_masquerade(transferer, chan2)) { + ast_hangup(transferee); ast_hangup(transferer); ast_free(d->park_exten); ast_free(d->park_context); @@ -24245,6 +24250,8 @@ static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct d->seqno = seqno; if (ast_pthread_create_detached_background(&th, NULL, sip_park_thread, d) < 0) { /* Could not start thread */ + ast_hangup(transferer); + ast_hangup(transferee); deinit_req(&d->req); ast_free(d->park_exten); ast_free(d->park_context); -- 2.47.2