mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-29 15:36:13 +00:00
Fix DTMF blind transfer continuing to execute dialplan after transfer.
Party A calls Party B. Party A DTMF blind transfers Party B to Party C. Party A channel continues to execute dialplan. * Fixed the return value of builtin_blindtransfer() to return the correct value after a transfer so the dialplan will not keep executing. * Removed unnecessary connected line update that did not really do anything. * Made access to GOTO_ON_BLINDXFR thread safe in check_goto_on_transfer(). * Fixed leak of xferchan for failure cases in check_goto_on_transfer(). * Updated debug messages in builtin_blindtransfer() and check_goto_on_transfer(). (closes issue ASTERISK-18275) Reported by: rmudgett Tested by: rmudgett ........ Merged revisions 340809 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 340810 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@340813 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -845,35 +845,49 @@ static void set_c_e_p(struct ast_channel *chan, const char *context, const char
|
|||||||
static void check_goto_on_transfer(struct ast_channel *chan)
|
static void check_goto_on_transfer(struct ast_channel *chan)
|
||||||
{
|
{
|
||||||
struct ast_channel *xferchan;
|
struct ast_channel *xferchan;
|
||||||
const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
|
const char *val;
|
||||||
char *x, *goto_on_transfer;
|
char *goto_on_transfer;
|
||||||
struct ast_frame *f;
|
char *x;
|
||||||
|
|
||||||
if (ast_strlen_zero(val))
|
ast_channel_lock(chan);
|
||||||
|
val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
|
||||||
|
if (ast_strlen_zero(val)) {
|
||||||
|
ast_channel_unlock(chan);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
goto_on_transfer = ast_strdupa(val);
|
|
||||||
|
|
||||||
if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", chan->linkedid, 0, "%s", chan->name)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (x = goto_on_transfer; x && *x; x++) {
|
|
||||||
if (*x == '^')
|
|
||||||
*x = ',';
|
|
||||||
}
|
}
|
||||||
|
goto_on_transfer = ast_strdupa(val);
|
||||||
|
ast_channel_unlock(chan);
|
||||||
|
|
||||||
|
ast_debug(1, "Attempting GOTO_ON_BLINDXFR=%s for %s.\n", val, chan->name);
|
||||||
|
|
||||||
|
xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", chan->linkedid, 0,
|
||||||
|
"%s", chan->name);
|
||||||
|
if (!xferchan) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make formats okay */
|
/* Make formats okay */
|
||||||
xferchan->readformat = chan->readformat;
|
xferchan->readformat = chan->readformat;
|
||||||
xferchan->writeformat = chan->writeformat;
|
xferchan->writeformat = chan->writeformat;
|
||||||
ast_channel_masquerade(xferchan, chan);
|
|
||||||
|
if (ast_channel_masquerade(xferchan, chan)) {
|
||||||
|
/* Failed to setup masquerade. */
|
||||||
|
ast_hangup(xferchan);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (x = goto_on_transfer; *x; ++x) {
|
||||||
|
if (*x == '^') {
|
||||||
|
*x = ',';
|
||||||
|
}
|
||||||
|
}
|
||||||
ast_parseable_goto(xferchan, goto_on_transfer);
|
ast_parseable_goto(xferchan, goto_on_transfer);
|
||||||
xferchan->_state = AST_STATE_UP;
|
xferchan->_state = AST_STATE_UP;
|
||||||
ast_clear_flag(xferchan, AST_FLAGS_ALL);
|
ast_clear_flag(xferchan, AST_FLAGS_ALL);
|
||||||
ast_channel_clear_softhangup(xferchan, AST_SOFTHANGUP_ALL);
|
ast_channel_clear_softhangup(xferchan, AST_SOFTHANGUP_ALL);
|
||||||
if ((f = ast_read(xferchan))) {
|
|
||||||
ast_frfree(f);
|
if (ast_do_masquerade(xferchan) || ast_pbx_start(xferchan)) {
|
||||||
f = NULL;
|
/* Failed to do masquerade or could not start PBX. */
|
||||||
ast_pbx_start(xferchan);
|
|
||||||
} else {
|
|
||||||
ast_hangup(xferchan);
|
ast_hangup(xferchan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2115,6 +2129,7 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
|
|||||||
char xferto[256] = "";
|
char xferto[256] = "";
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
ast_debug(1, "Executing Blind Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
|
||||||
set_peers(&transferer, &transferee, peer, chan, sense);
|
set_peers(&transferer, &transferee, peer, chan, sense);
|
||||||
transferer_real_context = real_ctx(transferer, transferee);
|
transferer_real_context = real_ctx(transferer, transferee);
|
||||||
|
|
||||||
@@ -2157,10 +2172,12 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do blind transfer. */
|
/* Do blind transfer. */
|
||||||
|
ast_verb(3, "Blind transferring %s to '%s' (context %s) priority 1\n",
|
||||||
|
transferee->name, xferto, transferer_real_context);
|
||||||
ast_cel_report_event(transferer, AST_CEL_BLINDTRANSFER, NULL, xferto, transferee);
|
ast_cel_report_event(transferer, AST_CEL_BLINDTRANSFER, NULL, xferto, transferee);
|
||||||
pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
|
pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
|
||||||
pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
|
pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
|
||||||
res = finishup(transferee);
|
finishup(transferee);
|
||||||
if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
|
if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
|
||||||
transferer->cdr = ast_cdr_alloc();
|
transferer->cdr = ast_cdr_alloc();
|
||||||
if (transferer->cdr) {
|
if (transferer->cdr) {
|
||||||
@@ -2187,21 +2204,24 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
|
|||||||
}
|
}
|
||||||
if (!transferee->pbx) {
|
if (!transferee->pbx) {
|
||||||
/* Doh! Use our handy async_goto functions */
|
/* Doh! Use our handy async_goto functions */
|
||||||
ast_verb(3, "Transferring %s to '%s' (context %s) priority 1\n",
|
ast_debug(1, "About to ast_async_goto %s.\n", transferee->name);
|
||||||
transferee->name, xferto, transferer_real_context);
|
|
||||||
if (ast_async_goto(transferee, transferer_real_context, xferto, 1)) {
|
if (ast_async_goto(transferee, transferer_real_context, xferto, 1)) {
|
||||||
ast_log(LOG_WARNING, "Async goto failed :-(\n");
|
ast_log(LOG_WARNING, "Async goto failed :-(\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The transferee is masqueraded and the original bridged channels can be hungup. */
|
||||||
|
res = -1;
|
||||||
} else {
|
} else {
|
||||||
/* Set the channel's new extension, since it exists, using transferer context */
|
/* Set the transferee's new extension, since it exists, using transferer context */
|
||||||
|
ast_debug(1, "About to explicit goto %s, it has a PBX.\n", transferee->name);
|
||||||
ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
|
ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
|
||||||
ast_debug(1,
|
|
||||||
"ABOUT TO AST_ASYNC_GOTO, have a pbx... set HANGUP_DONT on chan=%s\n",
|
|
||||||
transferee->name);
|
|
||||||
if (ast_channel_connected_line_macro(transferee, transferer, &transferer->connected, 1, 0)) {
|
|
||||||
ast_channel_update_connected_line(transferer, &transferer->connected, NULL);
|
|
||||||
}
|
|
||||||
set_c_e_p(transferee, transferer_real_context, xferto, 0);
|
set_c_e_p(transferee, transferer_real_context, xferto, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Break the bridge. The transferee needs to resume executing
|
||||||
|
* dialplan at the xferto location.
|
||||||
|
*/
|
||||||
|
res = AST_FEATURE_RETURN_SUCCESSBREAK;
|
||||||
}
|
}
|
||||||
check_goto_on_transfer(transferer);
|
check_goto_on_transfer(transferer);
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
Reference in New Issue
Block a user