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)





git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@387036 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Matthew Jordan
2013-04-30 22:34:05 +00:00
parent cf90e44d99
commit 8d1f50d957

View File

@@ -4208,17 +4208,6 @@ int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct a
if (!f || (f->frametype == AST_FRAME_CONTROL && if (!f || (f->frametype == AST_FRAME_CONTROL &&
(f->subclass.integer == AST_CONTROL_HANGUP || f->subclass.integer == AST_CONTROL_BUSY || (f->subclass.integer == AST_CONTROL_HANGUP || f->subclass.integer == AST_CONTROL_BUSY ||
f->subclass.integer == AST_CONTROL_CONGESTION))) { 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 (chan->_softhangup & (AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE)) {
ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT);
}
ast_channel_unlock(chan);
res = -1; res = -1;
break; break;
} }
@@ -4406,7 +4395,15 @@ before_you_go:
* if it were, then chan belongs to a different thread now, and might have been hung up long * if it were, then chan belongs to a different thread now, and might have been hung up long
* ago. * ago.
*/ */
if (ast_test_flag(&config->features_caller, AST_FEATURE_NO_H_EXTEN)) { if (chan->_softhangup & (AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE)) {
/*
* 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.
*/
h_context = NULL;
} else if (ast_test_flag(&config->features_caller, AST_FEATURE_NO_H_EXTEN)) {
h_context = NULL; h_context = NULL;
} else if (ast_exists_extension(chan, chan->context, "h", 1, } else if (ast_exists_extension(chan, chan->context, "h", 1,
S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {