mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-20 12:20:12 +00:00
res_pjsip_refer/chan_sip: Fix INVITE with replaces transfer to ConfBridge
There is a problem when an INVITE-with-Replaces transfer targets a channel in a ConfBridge. The transfer will unconditionally swap out the ConfBridge channel. Unfortunately, the ConfBridge state will not be aware of this change. Unexpected behavior will happen as a result since ConfBridge channels currently can only be replaced by a masquerade and not normal bridge channel moves. * We just need to pretend that the channel isn't in a bridge (like other transfer methods already do) so the transfer channel will masquerade into the ConfBridge channel. Change-Id: I209beb0e748fa4f4b92a576f36afa8f495ba4c82
This commit is contained in:
@@ -25886,10 +25886,7 @@ static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req,
|
|||||||
|
|
||||||
ast_raw_answer(c);
|
ast_raw_answer(c);
|
||||||
|
|
||||||
ast_channel_lock(replaces_chan);
|
bridge = ast_bridge_transfer_acquire_bridge(replaces_chan);
|
||||||
bridge = ast_channel_get_bridge(replaces_chan);
|
|
||||||
ast_channel_unlock(replaces_chan);
|
|
||||||
|
|
||||||
if (bridge) {
|
if (bridge) {
|
||||||
if (ast_bridge_impart(bridge, c, replaces_chan, NULL,
|
if (ast_bridge_impart(bridge, c, replaces_chan, NULL,
|
||||||
AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
|
AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
|
||||||
|
@@ -945,6 +945,17 @@ void ast_bridge_remove_video_src(struct ast_bridge *bridge, struct ast_channel *
|
|||||||
*/
|
*/
|
||||||
const char *ast_bridge_video_mode_to_string(enum ast_bridge_video_mode_type video_mode);
|
const char *ast_bridge_video_mode_to_string(enum ast_bridge_video_mode_type video_mode);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Acquire the channel's bridge for transfer purposes.
|
||||||
|
* \since 13.21.0
|
||||||
|
*
|
||||||
|
* \param chan Channel involved in a transfer.
|
||||||
|
*
|
||||||
|
* \return The bridge the channel is in or NULL if it either isn't
|
||||||
|
* in a bridge or should not be considered to be in a bridge.
|
||||||
|
*/
|
||||||
|
struct ast_bridge *ast_bridge_transfer_acquire_bridge(struct ast_channel *chan);
|
||||||
|
|
||||||
enum ast_transfer_result {
|
enum ast_transfer_result {
|
||||||
/*! The transfer completed successfully */
|
/*! The transfer completed successfully */
|
||||||
AST_BRIDGE_TRANSFER_SUCCESS,
|
AST_BRIDGE_TRANSFER_SUCCESS,
|
||||||
|
@@ -4420,7 +4420,7 @@ static void set_transfer_variables_all(struct ast_channel *transferer, struct ao
|
|||||||
ao2_iterator_destroy(&iter);
|
ao2_iterator_destroy(&iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ast_bridge *acquire_bridge(struct ast_channel *chan)
|
struct ast_bridge *ast_bridge_transfer_acquire_bridge(struct ast_channel *chan)
|
||||||
{
|
{
|
||||||
struct ast_bridge *bridge;
|
struct ast_bridge *bridge;
|
||||||
|
|
||||||
@@ -4461,7 +4461,7 @@ enum ast_transfer_result ast_bridge_transfer_blind(int is_external,
|
|||||||
return AST_BRIDGE_TRANSFER_FAIL;
|
return AST_BRIDGE_TRANSFER_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bridge = acquire_bridge(transferer);
|
bridge = ast_bridge_transfer_acquire_bridge(transferer);
|
||||||
if (!bridge) {
|
if (!bridge) {
|
||||||
transfer_result = AST_BRIDGE_TRANSFER_INVALID;
|
transfer_result = AST_BRIDGE_TRANSFER_INVALID;
|
||||||
goto publish;
|
goto publish;
|
||||||
@@ -4708,8 +4708,8 @@ enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_tra
|
|||||||
const char *app = NULL;
|
const char *app = NULL;
|
||||||
int hangup_target = 0;
|
int hangup_target = 0;
|
||||||
|
|
||||||
to_transferee_bridge = acquire_bridge(to_transferee);
|
to_transferee_bridge = ast_bridge_transfer_acquire_bridge(to_transferee);
|
||||||
to_target_bridge = acquire_bridge(to_transfer_target);
|
to_target_bridge = ast_bridge_transfer_acquire_bridge(to_transfer_target);
|
||||||
|
|
||||||
transfer_msg = ast_attended_transfer_message_create(1, to_transferee, to_transferee_bridge,
|
transfer_msg = ast_attended_transfer_message_create(1, to_transferee, to_transferee_bridge,
|
||||||
to_transfer_target, to_target_bridge, NULL, NULL);
|
to_transfer_target, to_target_bridge, NULL, NULL);
|
||||||
|
@@ -917,10 +917,7 @@ static int invite_replaces(void *data)
|
|||||||
ast_channel_ref(invite->session->channel);
|
ast_channel_ref(invite->session->channel);
|
||||||
invite->channel = invite->session->channel;
|
invite->channel = invite->session->channel;
|
||||||
|
|
||||||
ast_channel_lock(invite->channel);
|
invite->bridge = ast_bridge_transfer_acquire_bridge(invite->channel);
|
||||||
invite->bridge = ast_channel_get_bridge(invite->channel);
|
|
||||||
ast_channel_unlock(invite->channel);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user