diff --git a/include/asterisk/bridge.h b/include/asterisk/bridge.h index 53673c7f7f..fdb3803ad2 100644 --- a/include/asterisk/bridge.h +++ b/include/asterisk/bridge.h @@ -954,6 +954,19 @@ enum ast_transfer_result ast_bridge_transfer_blind(int is_external, enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target); +/*! + * \brief Set the relevant transfer variables for a single channel + * + * Sets either the ATTENDEDTRANSFER or BLINDTRANSFER variable for a channel while clearing + * the opposite. + * + * \param chan Channel the variable is being set for + * \param value Value the variable is being set to + * \param is_attended false set BLINDTRANSFER and unset ATTENDEDTRANSFER + * true set ATTENDEDTRANSFER and unset BLINDTRANSFER + */ +void ast_bridge_set_transfer_variables(struct ast_channel *chan, const char *value, int is_attended); + /*! * \brief Get a container of all channels in the bridge * \since 12.0.0 diff --git a/main/bridge.c b/main/bridge.c index 1c3bf16e3a..c64a879de8 100644 --- a/main/bridge.c +++ b/main/bridge.c @@ -122,6 +122,12 @@ static unsigned int optimization_id; /* Grow rate of bridge array of channels */ #define BRIDGE_ARRAY_GROW 32 +/* Variable name - stores peer information about the most recent blind transfer */ +#define BLINDTRANSFER "BLINDTRANSFER" + +/* Variable name - stores peer information about the most recent attended transfer */ +#define ATTENDEDTRANSFER "ATTENDEDTRANSFER" + static void cleanup_video_mode(struct ast_bridge *bridge); static int bridge_make_compatible(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel); @@ -3688,6 +3694,8 @@ static enum ast_transfer_result blind_transfer_bridge(struct ast_channel *transf return AST_BRIDGE_TRANSFER_FAIL; } + pbx_builtin_setvar_helper(local, BLINDTRANSFER, ast_channel_name(transferer)); + if (new_channel_cb) { new_channel_cb(local, user_data, AST_BRIDGE_TRANSFER_MULTI_PARTY); } @@ -3850,6 +3858,8 @@ static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *cha return AST_BRIDGE_TRANSFER_FAIL; } + pbx_builtin_setvar_helper(local_chan, ATTENDEDTRANSFER, ast_channel_name(chan1)); + if (bridge2) { res = ast_local_setup_bridge(local_chan, bridge2, chan2, NULL); } else { @@ -3945,19 +3955,38 @@ static enum ast_transfer_result try_parking(struct ast_channel *transferer, cons return AST_BRIDGE_TRANSFER_SUCCESS; } +void ast_bridge_set_transfer_variables(struct ast_channel *chan, const char *value, int attended) +{ + char *writevar; + char *erasevar; + + if (attended) { + writevar = ATTENDEDTRANSFER; + erasevar = BLINDTRANSFER; + } else { + writevar = BLINDTRANSFER; + erasevar = ATTENDEDTRANSFER; + } + + pbx_builtin_setvar_helper(chan, writevar, value); + pbx_builtin_setvar_helper(chan, erasevar, value); +} + /*! * \internal - * \brief Set the BLINDTRANSFER variable as appropriate on channels involved in the transfer + * \brief Set the transfer variable as appropriate on channels involved in the transfer * - * The transferer channel will have its BLINDTRANSFER variable set the same as its BRIDGEPEER + * The transferer channel will have its variable set the same as its BRIDGEPEER * variable. This will account for all channels that it is bridged to. The other channels - * involved in the transfer will have their BLINDTRANSFER variable set to the transferer + * involved in the transfer will have their variable set to the transferer * channel's name. * - * \param transferer The channel performing the blind transfer + * \param transferer The channel performing the transfer * \param channels The channels belonging to the bridge + * \param is_attended false set BLINDTRANSFER and unset ATTENDEDTRANSFER + * true set ATTENDEDTRANSFER and unset BLINDTRANSFER */ -static void set_blind_transfer_variables(struct ast_channel *transferer, struct ao2_container *channels) +static void set_transfer_variables_all(struct ast_channel *transferer, struct ao2_container *channels, int is_attended) { struct ao2_iterator iter; struct ast_channel *chan; @@ -3973,9 +4002,9 @@ static void set_blind_transfer_variables(struct ast_channel *transferer, struct (chan = ao2_iterator_next(&iter)); ao2_cleanup(chan)) { if (chan == transferer) { - pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", transferer_bridgepeer); + ast_bridge_set_transfer_variables(chan, transferer_bridgepeer, is_attended); } else { - pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", transferer_name); + ast_bridge_set_transfer_variables(chan, transferer_name, is_attended); } } @@ -4066,7 +4095,7 @@ enum ast_transfer_result ast_bridge_transfer_blind(int is_external, goto publish; } - set_blind_transfer_variables(transferer, channels); + set_transfer_variables_all(transferer, channels, 0); if (do_bridge_transfer) { transfer_result = blind_transfer_bridge(transferer, bridge, exten, context, @@ -4167,6 +4196,16 @@ static enum ast_transfer_result two_bridge_attended_transfer(struct ast_channel }; enum ast_transfer_result res; struct ast_bridge *final_bridge = NULL; + RAII_VAR(struct ao2_container *, channels, NULL, ao2_cleanup); + + channels = ast_bridge_peers_nolock(to_transferee_bridge); + + if (!channels) { + res = AST_BRIDGE_TRANSFER_FAIL; + goto end; + } + + set_transfer_variables_all(to_transferee, channels, 1); switch (ast_bridges_allow_optimization(to_transferee_bridge, to_target_bridge)) { case AST_BRIDGE_OPTIMIZE_SWAP_TO_CHAN_BRIDGE: @@ -4338,6 +4377,8 @@ enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_tra goto end; } + set_transfer_variables_all(to_transferee, channels, 1); + if (do_bridge_transfer) { res = attended_transfer_bridge(chan_bridged, chan_unbridged, the_bridge, NULL, &publication); goto end; diff --git a/main/bridge_basic.c b/main/bridge_basic.c index 76dfb28936..eaec68995b 100644 --- a/main/bridge_basic.c +++ b/main/bridge_basic.c @@ -2929,8 +2929,7 @@ static struct ast_channel *dial_transfer(struct ast_channel *caller, const char /* Who is transferring the call. */ pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", ast_channel_name(caller)); - /* To work as an analog to BLINDTRANSFER */ - pbx_builtin_setvar_helper(chan, "ATTENDEDTRANSFER", ast_channel_name(caller)); + ast_bridge_set_transfer_variables(chan, ast_channel_name(caller), 1); /* Before we actually dial out let's inherit appropriate information. */ copy_caller_data(chan, caller); diff --git a/res/parking/parking_bridge_features.c b/res/parking/parking_bridge_features.c index 4f39e2e941..ba0ffddfb6 100644 --- a/res/parking/parking_bridge_features.c +++ b/res/parking/parking_bridge_features.c @@ -220,7 +220,7 @@ static struct ast_channel *park_local_transfer(struct ast_channel *parker, const /* We need to have the parker subscribe to the new local channel before hand. */ create_parked_subscription(parker, ast_channel_uniqueid(parkee_side_2)); - pbx_builtin_setvar_helper(parkee_side_2, "BLINDTRANSFER", ast_channel_name(parker)); + ast_bridge_set_transfer_variables(parkee_side_2, ast_channel_name(parker), 0); ast_channel_unref(parkee_side_2); @@ -375,7 +375,7 @@ static int parking_park_bridge_channel(struct ast_bridge_channel *bridge_channel return -1; } - pbx_builtin_setvar_helper(bridge_channel->chan, "BLINDTRANSFER", ast_channel_name(parker)); + ast_bridge_set_transfer_variables(bridge_channel->chan, ast_channel_name(parker), 0); /* bridge_channel must be locked so we can get a reference to the bridge it is currently on */ ao2_lock(bridge_channel); diff --git a/res/parking/parking_manager.c b/res/parking/parking_manager.c index 0c577018a0..60baa65101 100644 --- a/res/parking/parking_manager.c +++ b/res/parking/parking_manager.c @@ -453,7 +453,7 @@ static int manager_park(struct mansession *s, const struct message *m) ast_channel_lock(chan); if (!ast_strlen_zero(timeout_channel)) { - pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", timeout_channel); + ast_bridge_set_transfer_variables(chan, timeout_channel, 0); } ast_channel_unlock(chan);