mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-21 12:30:41 +00:00
Misc core external attended transfer fixes.
* Fix external attended transfer bridge move/swap method. One of the transferrer channels was not kicked out of the bridge. * Fix several off-nominal extended attended transfer paths. Mainly the channels involved needed to be hung up or kicked out of the bridge. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390613 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -2020,7 +2020,10 @@ static void bridge_channel_blind_transfer(struct ast_bridge_channel *bridge_chan
|
||||
static void after_bridge_move_channel(struct ast_channel *chan_bridged, void *data)
|
||||
{
|
||||
RAII_VAR(struct ast_channel *, chan_target, data, ao2_cleanup);
|
||||
ast_channel_move(chan_target, chan_bridged);
|
||||
|
||||
if (ast_channel_move(chan_target, chan_bridged)) {
|
||||
ast_softhangup(chan_target, AST_SOFTHANGUP_DEV);
|
||||
}
|
||||
}
|
||||
|
||||
static void after_bridge_move_channel_fail(enum ast_after_bridge_cb_reason reason, void *data)
|
||||
@@ -2028,7 +2031,8 @@ static void after_bridge_move_channel_fail(enum ast_after_bridge_cb_reason reaso
|
||||
RAII_VAR(struct ast_channel *, chan_target, data, ao2_cleanup);
|
||||
|
||||
ast_log(LOG_WARNING, "Unable to complete transfer: %s\n",
|
||||
ast_after_bridge_cb_reason_string(reason));
|
||||
ast_after_bridge_cb_reason_string(reason));
|
||||
ast_softhangup(chan_target, AST_SOFTHANGUP_DEV);
|
||||
}
|
||||
|
||||
static void bridge_channel_attended_transfer(struct ast_bridge_channel *bridge_channel,
|
||||
@@ -2040,21 +2044,22 @@ static void bridge_channel_attended_transfer(struct ast_bridge_channel *bridge_c
|
||||
chan_target = ast_channel_get_by_name(target_chan_name);
|
||||
if (!chan_target) {
|
||||
/* Dang, it disappeared somehow */
|
||||
bridge_handle_hangup(bridge_channel);
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
SCOPED_CHANNELLOCK(lock, bridge_channel);
|
||||
chan_bridged = bridge_channel->chan;
|
||||
if (!chan_bridged) {
|
||||
return;
|
||||
}
|
||||
ao2_ref(chan_bridged, +1);
|
||||
}
|
||||
ast_bridge_channel_lock(bridge_channel);
|
||||
chan_bridged = bridge_channel->chan;
|
||||
ast_assert(chan_bridged != NULL);
|
||||
ao2_ref(chan_bridged, +1);
|
||||
ast_bridge_channel_unlock(bridge_channel);
|
||||
|
||||
if (ast_after_bridge_callback_set(chan_bridged, after_bridge_move_channel,
|
||||
after_bridge_move_channel_fail, ast_channel_ref(chan_target))) {
|
||||
return;
|
||||
after_bridge_move_channel_fail, ast_channel_ref(chan_target))) {
|
||||
ast_softhangup(chan_target, AST_SOFTHANGUP_DEV);
|
||||
|
||||
/* Release the ref we tried to pass to ast_after_bridge_callback_set(). */
|
||||
ast_channel_unref(chan_target);
|
||||
}
|
||||
bridge_handle_hangup(bridge_channel);
|
||||
}
|
||||
@@ -5363,11 +5368,11 @@ static int bridge_channel_queue_attended_transfer(struct ast_channel *transferee
|
||||
}
|
||||
|
||||
ast_copy_string(unbridged_chan_name, ast_channel_name(unbridged_chan),
|
||||
sizeof(unbridged_chan_name));
|
||||
sizeof(unbridged_chan_name));
|
||||
|
||||
ast_bridge_channel_queue_action_data(transferee_bridge_channel,
|
||||
AST_BRIDGE_ACTION_ATTENDED_TRANSFER, unbridged_chan_name,
|
||||
sizeof(unbridged_chan_name));
|
||||
AST_BRIDGE_ACTION_ATTENDED_TRANSFER, unbridged_chan_name,
|
||||
sizeof(unbridged_chan_name));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -5502,6 +5507,7 @@ enum ast_transfer_result ast_bridge_transfer_blind(struct ast_channel *transfere
|
||||
|
||||
{
|
||||
SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
|
||||
|
||||
channels = ast_bridge_peers_nolock(bridge);
|
||||
if (!channels) {
|
||||
return AST_BRIDGE_TRANSFER_FAIL;
|
||||
@@ -5564,11 +5570,17 @@ static enum ast_transfer_result bridge_swap_attended_transfer(struct ast_bridge
|
||||
struct ast_bridge_channel *bridged_to_source;
|
||||
|
||||
bridged_to_source = ast_bridge_channel_peer(source_bridge_channel);
|
||||
if (bridged_to_source && bridged_to_source->state == AST_BRIDGE_CHANNEL_STATE_WAIT
|
||||
&& !ast_test_flag(&bridged_to_source->features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE)) {
|
||||
if (bridged_to_source
|
||||
&& bridged_to_source->state == AST_BRIDGE_CHANNEL_STATE_WAIT
|
||||
&& !ast_test_flag(&bridged_to_source->features->feature_flags,
|
||||
AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE)) {
|
||||
bridged_to_source->swap = swap_channel;
|
||||
return bridge_move_do(dest_bridge, bridged_to_source, 1) ?
|
||||
AST_BRIDGE_TRANSFER_FAIL : AST_BRIDGE_TRANSFER_SUCCESS;
|
||||
if (bridge_move_do(dest_bridge, bridged_to_source, 1)) {
|
||||
return AST_BRIDGE_TRANSFER_FAIL;
|
||||
}
|
||||
/* Must kick the source channel out of its bridge. */
|
||||
ast_bridge_change_state(source_bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
return AST_BRIDGE_TRANSFER_SUCCESS;
|
||||
} else {
|
||||
return AST_BRIDGE_TRANSFER_INVALID;
|
||||
}
|
||||
|
Reference in New Issue
Block a user