From e51b6a37e934bea61082607601ce1016c9858f74 Mon Sep 17 00:00:00 2001 From: Matthew Jordan Date: Tue, 30 Apr 2013 22:50:40 +0000 Subject: [PATCH] Fix CDR not being created during an externally initiated blind transfer Way back when in the dark days of Asterisk 1.8.9, blind transferring a call in a context that included the 'h' extension would inadvertently execute the hangup code logic on the transferred channel. This was a "bad thing". The fix was to properly check for the softhangup flags on the channel and only execute the 'h' extension logic (and, in later versions, hangup handler logic) if the channel was well and truly dead (Jim). Unfortunately, CDRs are fickle. Setting the softhangup flag when we detected that the channel was leaving the bridge (but not to die) caused some crucial snippet of CDR code, lying in ambush in the middle of the bridging code, to not get executed. This had the effect of blowing away one of the CDRs that is typically created during a blind transfer. While we live and die by the adage "don't touch CDRs in release branches", this was our bad. The attached patch restores the CDR behavior, and still manages to not run the 'h' extension during a blind transfer (at least not when it's supposed to). Thanks to Steve Davies for diagnosing this and providing a fix. Review: https://reviewboard.asterisk.org/r/2476 (closes issue ASTERISK-21394) Reported by: Ishfaq Malik Tested by: Ishfaq Malik, mjordan patches: fix_missing_blindXfer_cdr2 uploaded by one47 (License 5012) ........ Merged revisions 387036 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 387038 from http://svn.asterisk.org/svn/asterisk/branches/11 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@387039 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- main/features.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/main/features.c b/main/features.c index 8d2cffb208..b6cc191649 100644 --- a/main/features.c +++ b/main/features.c @@ -4644,17 +4644,6 @@ int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct a if (!f || (f->frametype == AST_FRAME_CONTROL && (f->subclass.integer == AST_CONTROL_HANGUP || f->subclass.integer == AST_CONTROL_BUSY || f->subclass.integer == AST_CONTROL_CONGESTION))) { - /* - * If the bridge was broken for a hangup that isn't real, - * then don't run the h extension, because the channel isn't - * really hung up. This should really only happen with AST_SOFTHANGUP_ASYNCGOTO, - * but it doesn't hurt to check AST_SOFTHANGUP_UNBRIDGE either. - */ - ast_channel_lock(chan); - if (ast_channel_softhangup_internal_flag(chan) & (AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE)) { - ast_set_flag(ast_channel_flags(chan), AST_FLAG_BRIDGE_HANGUP_DONT); - } - ast_channel_unlock(chan); res = -1; break; } @@ -4841,7 +4830,12 @@ before_you_go: config->end_bridge_callback(config->end_bridge_callback_data); } - if (!ast_test_flag(&config->features_caller, AST_FEATURE_NO_H_EXTEN)) { + /* run the hangup exten on the chan object IFF it was NOT involved in a parking situation + * if it were, then chan belongs to a different thread now, and might have been hung up long + * ago. + */ + if (!(ast_channel_softhangup_internal_flag(chan) & (AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE)) + && !ast_test_flag(&config->features_caller, AST_FEATURE_NO_H_EXTEN)) { struct ast_cdr *swapper = NULL; char savelastapp[AST_MAX_EXTENSION]; char savelastdata[AST_MAX_EXTENSION];