From d00882108fabd3798aa6566aa5697d82459e753e Mon Sep 17 00:00:00 2001 From: Jonathan Rose Date: Thu, 22 May 2014 15:52:30 +0000 Subject: res_pjsip_refer: Fix bugs involving Parking/PJSIP/transfers PJSIP would never send the final 200 Notify for a blind transfer when transferring to parking. This patch fixes that. In addition, it fixes a reference leak when performing blind transfers to non-bridging extensions. Review: https://reviewboard.asterisk.org/r/3485/ ........ Merged revisions 414400 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@414403 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- res/res_pjsip_refer.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'res/res_pjsip_refer.c') diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c index e6855ae47..20e3012b1 100644 --- a/res/res_pjsip_refer.c +++ b/res/res_pjsip_refer.c @@ -55,6 +55,8 @@ struct refer_progress { struct ast_taskprocessor *serializer; /*! \brief Stasis subscription for bridge events */ struct stasis_subscription *bridge_sub; + /*! \brief Reference to transfer_channel_data related to the refer */ + struct transfer_channel_data *transfer_data; /*! \brief Uniqueid of transferee channel */ char *transferee; }; @@ -165,6 +167,12 @@ static void refer_progress_bridge(void *data, struct stasis_subscription *sub, return; } + if (!progress->transfer_data->completed) { + /* We can't act on this message because the transfer_channel_data doesn't show that + * the transfer is ready to progress */ + return; + } + /* OMG the transferee is joining a bridge. His call got answered! */ notification = refer_progress_notification_alloc(progress, 200, PJSIP_EVSUB_STATE_TERMINATED); if (notification) { @@ -186,6 +194,11 @@ static struct ast_frame *refer_progress_framehook(struct ast_channel *chan, stru return f; } + /* If the completed flag hasn't been raised, skip this pass. */ + if (!progress->transfer_data->completed) { + return f; + } + /* Determine the state of the REFER based on the control frames (or voice frames) passing */ if (f->frametype == AST_FRAME_VOICE && !progress->subclass) { /* Media is passing without progress, this means the call has been answered */ @@ -240,6 +253,10 @@ static void refer_progress_framehook_destroy(void *data) ao2_cleanup(notification); } + if (progress->bridge_sub) { + progress->bridge_sub = stasis_unsubscribe(progress->bridge_sub); + } + ao2_cleanup(progress); } @@ -296,6 +313,8 @@ static void refer_progress_destroy(void *obj) progress->bridge_sub = stasis_unsubscribe(progress->bridge_sub); } + ao2_cleanup(progress->transfer_data); + ast_free(progress->transferee); ast_taskprocessor_unreference(progress->serializer); } @@ -472,9 +491,10 @@ struct refer_blind { }; /*! \brief Blind transfer callback function */ -static void refer_blind_callback(struct ast_channel *chan, void *user_data, enum ast_transfer_type transfer_type) +static void refer_blind_callback(struct ast_channel *chan, struct transfer_channel_data *user_data_wrapper, + enum ast_transfer_type transfer_type) { - struct refer_blind *refer = user_data; + struct refer_blind *refer = user_data_wrapper->data; pjsip_generic_string_hdr *referred_by; static const pj_str_t str_referred_by = { "Referred-By", 11 }; @@ -503,6 +523,10 @@ static void refer_blind_callback(struct ast_channel *chan, void *user_data, enum } } + /* Progress needs a reference to the transfer_channel_data so that it can track the completed status of the transfer */ + ao2_ref(user_data_wrapper, +1); + refer->progress->transfer_data = user_data_wrapper; + /* We need to bump the reference count up on the progress structure since it is in the frame hook now */ ao2_ref(refer->progress, +1); -- cgit v1.2.3