Remove the unsafe bridge parameter from ast_bridge_hook_callback's.

Most hook callbacks did not need the bridge parameter.  The pointer value
could become invalid if the channel is moved to another bridge while it is
executing.

* Fixed some issues in feature_attended_transfer() as a result.

* Reduce the bridge inhibit count in
attended_transfer_properties_shutdown() after it has restored the bridge
channel hooks.

* Removed basic bridge requirement on feature_blind_transfer().  It does
not require the basic bridge like feature_attended_transfer().


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@395574 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/78/78/1
Richard Mudgett 12 years ago
parent 50aba6be36
commit c017d5e6a3

@ -1078,12 +1078,11 @@ static void agent_connect_caller(struct ast_bridge_channel *bridge_channel, stru
* The agent is in the new bridge so we can invoke the
* mixmonitor hook to only start recording.
*/
ast_bridge_features_do(AST_BRIDGE_BUILTIN_AUTOMIXMON, caller_bridge,
bridge_channel, &options);
ast_bridge_features_do(AST_BRIDGE_BUILTIN_AUTOMIXMON, bridge_channel, &options);
}
}
static int bridge_agent_hold_ack(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int bridge_agent_hold_ack(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct agent_pvt *agent = hook_pvt;
@ -1101,7 +1100,7 @@ static int bridge_agent_hold_ack(struct ast_bridge *bridge, struct ast_bridge_ch
return 0;
}
static int bridge_agent_hold_heartbeat(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int bridge_agent_hold_heartbeat(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct agent_pvt *agent = hook_pvt;
int probation_timedout = 0;
@ -1709,7 +1708,7 @@ static void caller_abort_agent(struct agent_pvt *agent)
ast_bridge_channel_unlock(logged);
}
static int caller_safety_timeout(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int caller_safety_timeout(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct agent_pvt *agent = hook_pvt;

@ -201,7 +201,7 @@ AST_APP_OPTIONS(bridgewait_opts, {
AST_APP_OPTION_ARG('S', MUXFLAG_TIMEOUT, OPT_ARG_TIMEOUT),
});
static int bridgewait_timeout_callback(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int bridgewait_timeout_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
ast_verb(3, "Channel %s timed out.\n", ast_channel_name(bridge_channel->chan));
ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);

@ -1402,9 +1402,9 @@ static void conf_handle_talker_destructor(void *pvt_data)
ast_free(pvt_data);
}
static int conf_handle_talker_cb(struct ast_bridge_channel *bridge_channel, void *pvt_data, int talking)
static int conf_handle_talker_cb(struct ast_bridge_channel *bridge_channel, void *hook_pvt, int talking)
{
const char *conf_name = pvt_data;
const char *conf_name = hook_pvt;
struct confbridge_conference *conference = ao2_find(conference_bridges, conf_name, OBJ_KEY);
struct ast_json *talking_extras;

@ -2080,9 +2080,10 @@ static void menu_hook_destroy(void *hook_pvt)
ast_free(pvt);
}
static int menu_hook_callback(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int menu_hook_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct dtmf_menu_hook_pvt *pvt = hook_pvt;
return conf_handle_dtmf(bridge_channel, pvt->user, &pvt->menu_entry, pvt->menu);
}

@ -214,7 +214,7 @@ static void start_automonitor(struct ast_bridge_channel *bridge_channel, struct
pbx_builtin_setvar_helper(peer_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
}
static int feature_automonitor(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int feature_automonitor(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
const char *start_message;
const char *stop_message;
@ -226,7 +226,9 @@ static int feature_automonitor(struct ast_bridge *bridge, struct ast_bridge_chan
RAII_VAR(struct ast_features_general_config *, features_cfg, NULL, ao2_cleanup);
features_cfg = ast_get_chan_features_general_config(bridge_channel->chan);
peer_chan = ast_bridge_peer(bridge, bridge_channel->chan);
ast_bridge_channel_lock_bridge(bridge_channel);
peer_chan = ast_bridge_peer_nolock(bridge_channel->bridge, bridge_channel->chan);
ast_bridge_unlock(bridge_channel->bridge);
if (!peer_chan) {
ast_verb(3, "Cannot start AutoMonitor for %s - can not determine peer in bridge.\n",
@ -397,7 +399,7 @@ static void start_automixmonitor(struct ast_bridge_channel *bridge_channel, stru
pbx_builtin_setvar_helper(peer_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
}
static int feature_automixmonitor(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int feature_automixmonitor(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
static const char *mixmonitor_spy_type = "MixMonitor";
const char *stop_message;
@ -410,7 +412,9 @@ static int feature_automixmonitor(struct ast_bridge *bridge, struct ast_bridge_c
RAII_VAR(struct ast_features_general_config *, features_cfg, NULL, ao2_cleanup);
features_cfg = ast_get_chan_features_general_config(bridge_channel->chan);
peer_chan = ast_bridge_peer(bridge, bridge_channel->chan);
ast_bridge_channel_lock_bridge(bridge_channel);
peer_chan = ast_bridge_peer_nolock(bridge_channel->bridge, bridge_channel->chan);
ast_bridge_unlock(bridge_channel->bridge);
if (!peer_chan) {
ast_verb(3, "Cannot do AutoMixMonitor for %s - cannot determine peer in bridge.\n",
@ -476,7 +480,7 @@ static int feature_automixmonitor(struct ast_bridge *bridge, struct ast_bridge_c
}
/*! \brief Internal built in feature for hangup */
static int feature_hangup(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int feature_hangup(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
/*
* This is very simple, we simply change the state on the

@ -50,7 +50,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stringfields.h"
#include "asterisk/musiconhold.h"
static int bridge_features_duration_callback(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int bridge_features_duration_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct ast_bridge_features_limits *limits = hook_pvt;
@ -110,7 +110,7 @@ static void limits_interval_playback(struct ast_bridge_channel *bridge_channel,
}
}
static int bridge_features_connect_callback(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int bridge_features_connect_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct ast_bridge_features_limits *limits = hook_pvt;
@ -118,7 +118,7 @@ static int bridge_features_connect_callback(struct ast_bridge *bridge, struct as
return -1;
}
static int bridge_features_warning_callback(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int bridge_features_warning_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct ast_bridge_features_limits *limits = hook_pvt;

@ -118,7 +118,6 @@ struct ast_bridge_channel;
/*!
* \brief Hook callback type
*
* \param bridge The bridge that the channel is part of
* \param bridge_channel Channel executing the feature
* \param hook_pvt Private data passed in when the hook was created
*
@ -131,7 +130,7 @@ struct ast_bridge_channel;
* \retval 0 Keep the callback hook.
* \retval -1 Remove the callback hook.
*/
typedef int (*ast_bridge_hook_callback)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt);
typedef int (*ast_bridge_hook_callback)(struct ast_bridge_channel *bridge_channel, void *hook_pvt);
/*!
* \brief Hook pvt destructor callback
@ -143,17 +142,19 @@ typedef void (*ast_bridge_hook_pvt_destructor)(void *hook_pvt);
/*!
* \brief Talking indicator callback
*
* \details This callback can be registered with the bridge in order
* to receive updates on when a bridge_channel has started and stopped
* talking
* \details
* This callback can be registered with the bridge channel in
* order to receive updates when the bridge_channel has started
* and stopped talking.
*
* \param bridge_channel Channel executing the feature
* \param hook_pvt Private data passed in when the hook was created
* \param talking TRUE if the channel is now talking
*
* \retval 0 Keep the callback hook.
* \retval -1 Remove the callback hook.
*/
typedef int (*ast_bridge_talking_indicate_callback)(struct ast_bridge_channel *bridge_channel, void *pvt_data, int talking);
typedef int (*ast_bridge_talking_indicate_callback)(struct ast_bridge_channel *bridge_channel, void *hook_pvt, int talking);
enum ast_bridge_hook_remove_flags {
/*! The hook is removed when the channel is pulled from the bridge. */
@ -357,6 +358,8 @@ int ast_bridge_features_unregister(enum ast_bridge_builtin_feature feature);
* \brief Invoke a built in feature hook now.
*
* \param feature The feature to invoke
* \param bridge_channel Channel executing the feature
* \param hook_pvt Private data passed in when the hook was created
*
* \note This API call is only meant to be used by bridge
* subclasses and hook callbacks to request a builtin feature
@ -368,10 +371,10 @@ int ast_bridge_features_unregister(enum ast_bridge_builtin_feature feature);
* Example usage:
*
* \code
* ast_bridge_features_do(AST_BRIDGE_BUILTIN_ATTENDED_TRANSFER, bridge, bridge_channel, hook_pvt);
* ast_bridge_features_do(AST_BRIDGE_BUILTIN_ATTENDED_TRANSFER, bridge_channel, hook_pvt);
* \endcode
*/
int ast_bridge_features_do(enum ast_bridge_builtin_feature feature, struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt);
int ast_bridge_features_do(enum ast_bridge_builtin_feature feature, struct ast_bridge_channel *bridge_channel, void *hook_pvt);
/*!
* \brief Attach interval hooks to a bridge features structure

@ -111,8 +111,7 @@ void ast_bridge_channel_park(struct ast_bridge_channel *bridge_channel,
const char *parker_uuid,
const char *app_data);
typedef int (*ast_park_blind_xfer_fn)(struct ast_bridge *bridge, struct ast_bridge_channel *parker,
struct ast_exten *park_exten);
typedef int (*ast_park_blind_xfer_fn)(struct ast_bridge_channel *parker, struct ast_exten *park_exten);
/*!
* \brief install a callback for handling blind transfers to a parking extension
@ -132,15 +131,13 @@ void ast_uninstall_park_blind_xfer_func(void);
* \brief use the installed park blind xfer func
* \since 12
*
* \param bridge Bridge being transferred from
* \param bridge_channel Bridge channel initiating the transfer
* \param app_data arguments to the park application
* \param parker Bridge channel initiating the park
* \param park_exten Exten to blind transfer part to.
*
* \retval 0 on success
* \retval -1 on failure
*/
int ast_park_blind_xfer(struct ast_bridge *bridge, struct ast_bridge_channel *parker,
struct ast_exten *park_exten);
int ast_park_blind_xfer(struct ast_bridge_channel *parker, struct ast_exten *park_exten);
typedef void (*ast_bridge_channel_park_fn)(struct ast_bridge_channel *parkee, const char *parkee_uuid,
const char *parker_uuid, const char *app_data);

@ -2675,7 +2675,7 @@ int ast_bridge_features_unregister(enum ast_bridge_builtin_feature feature)
return 0;
}
int ast_bridge_features_do(enum ast_bridge_builtin_feature feature, struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
int ast_bridge_features_do(enum ast_bridge_builtin_feature feature, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
ast_bridge_hook_callback callback;
@ -2687,7 +2687,7 @@ int ast_bridge_features_do(enum ast_bridge_builtin_feature feature, struct ast_b
if (!callback) {
return -1;
}
callback(bridge, bridge_channel, hook_pvt);
callback(bridge_channel, hook_pvt);
return 0;
}
@ -3777,8 +3777,7 @@ enum try_parking_result {
PARKING_NOT_APPLICABLE,
};
static enum try_parking_result try_parking(struct ast_bridge *bridge, struct ast_channel *transferer,
const char *exten, const char *context)
static enum try_parking_result try_parking(struct ast_channel *transferer, const char *exten, const char *context)
{
RAII_VAR(struct ast_bridge_channel *, transferer_bridge_channel, NULL, ao2_cleanup);
struct ast_exten *parking_exten;
@ -3793,7 +3792,7 @@ static enum try_parking_result try_parking(struct ast_bridge *bridge, struct ast
parking_exten = ast_get_parking_exten(exten, NULL, context);
if (parking_exten) {
return ast_park_blind_xfer(bridge, transferer_bridge_channel, parking_exten) == 0 ?
return ast_park_blind_xfer(transferer_bridge_channel, parking_exten) == 0 ?
PARKING_SUCCESS : PARKING_FAILURE;
}
@ -3871,7 +3870,7 @@ enum ast_transfer_result ast_bridge_transfer_blind(int is_external,
RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
RAII_VAR(struct ao2_container *, channels, NULL, ao2_cleanup);
RAII_VAR(struct ast_channel *, transferee, NULL, ao2_cleanup);
RAII_VAR(struct ast_channel *, transferee, NULL, ast_channel_cleanup);
int do_bridge_transfer;
int transfer_prohibited;
enum try_parking_result parking_result;
@ -3893,7 +3892,7 @@ enum ast_transfer_result ast_bridge_transfer_blind(int is_external,
/* Take off hold if they are on hold. */
ast_bridge_channel_write_unhold(bridge_channel);
parking_result = try_parking(bridge, transferer, exten, context);
parking_result = try_parking(transferer, exten, context);
switch (parking_result) {
case PARKING_SUCCESS:
transfer_result = AST_BRIDGE_TRANSFER_SUCCESS;

@ -265,20 +265,19 @@ struct ast_flags *ast_bridge_features_ds_get(struct ast_channel *chan)
* \brief Determine if we should dissolve the bridge from a hangup.
* \since 12.0.0
*
* \param bridge The bridge that the channel is part of
* \param bridge_channel Channel executing the feature
* \param hook_pvt Private data passed in when the hook was created
*
* \retval 0 Keep the callback hook.
* \retval -1 Remove the callback hook.
*/
static int basic_hangup_hook(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int basic_hangup_hook(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
int bridge_count = 0;
struct ast_bridge_channel *iter;
ast_bridge_channel_lock_bridge(bridge_channel);
AST_LIST_TRAVERSE(&bridge->channels, iter, entry) {
AST_LIST_TRAVERSE(&bridge_channel->bridge->channels, iter, entry) {
if (iter != bridge_channel && iter->state == BRIDGE_CHANNEL_STATE_WAIT) {
++bridge_count;
}
@ -1069,7 +1068,6 @@ static const char *get_transfer_context(struct ast_channel *transferer, const ch
/*!
* \brief Allocate and initialize attended transfer properties
*
* \param transferee_bridge The bridge where the transfer was initiated
* \param transferer The channel performing the attended transfer
* \param context Suggestion for what context the transfer target extension can be found in
*
@ -1077,8 +1075,7 @@ static const char *get_transfer_context(struct ast_channel *transferer, const ch
* \retval non-NULL Newly allocated properties
*/
static struct attended_transfer_properties *attended_transfer_properties_alloc(
struct ast_bridge *transferee_bridge, struct ast_channel *transferer,
const char *context)
struct ast_channel *transferer, const char *context)
{
struct attended_transfer_properties *props;
char *tech;
@ -1162,9 +1159,9 @@ static void attended_transfer_properties_shutdown(struct attended_transfer_prope
ast_debug(1, "Shutting down attended transfer %p\n", props);
if (props->transferee_bridge) {
ast_bridge_merge_inhibit(props->transferee_bridge, -1);
bridge_basic_change_personality(props->transferee_bridge,
BRIDGE_BASIC_PERSONALITY_NORMAL, NULL);
ast_bridge_merge_inhibit(props->transferee_bridge, -1);
}
if (props->target_bridge) {
@ -2145,7 +2142,7 @@ static int fail_enter(struct attended_transfer_properties *props)
*
* Sends a stimulus to the attended transfer monitor thread that the abort sequence has been pressed
*/
static int atxfer_abort(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int atxfer_abort(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct attended_transfer_properties *props = hook_pvt;
@ -2159,7 +2156,7 @@ static int atxfer_abort(struct ast_bridge *bridge, struct ast_bridge_channel *br
*
* Sends a stimulus to the attended transfer monitor thread that the complete sequence has been pressed
*/
static int atxfer_complete(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int atxfer_complete(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct attended_transfer_properties *props = hook_pvt;
@ -2173,7 +2170,7 @@ static int atxfer_complete(struct ast_bridge *bridge, struct ast_bridge_channel
*
* Sends a stimulus to the attended transfer monitor thread that the threeway sequence has been pressed
*/
static int atxfer_threeway(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int atxfer_threeway(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct attended_transfer_properties *props = hook_pvt;
@ -2187,7 +2184,7 @@ static int atxfer_threeway(struct ast_bridge *bridge, struct ast_bridge_channel
*
* Sends a stimulus to the attended transfer monitor thread that the swap sequence has been pressed
*/
static int atxfer_swap(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int atxfer_swap(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct attended_transfer_properties *props = hook_pvt;
@ -2201,7 +2198,7 @@ static int atxfer_swap(struct ast_bridge *bridge, struct ast_bridge_channel *bri
*
* Sends a stimulus to the attended transfer monitor thread that the transferer has hung up.
*/
static int atxfer_transferer_hangup(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int atxfer_transferer_hangup(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct attended_transfer_properties *props = hook_pvt;
@ -2622,48 +2619,64 @@ static struct ast_channel *dial_transfer(struct ast_channel *caller, const char
* an attended transfer. For more information about attended transfer
* progress, see documentation on the transfer state machine.
*
* \param bridge Bridge where attended transfer DTMF sequence was entered
* \param bridge_channel The channel that pressed the attended transfer DTMF sequence
* \param hook_pvt Structure with further information about the attended transfer
*/
static int feature_attended_transfer(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct ast_bridge_features_attended_transfer *attended_transfer = hook_pvt;
struct attended_transfer_properties *props;
struct ast_bridge *bridge;
char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
char exten[AST_MAX_EXTENSION] = "";
pthread_t thread;
/* Inhibit the bridge before we do anything else. */
bridge = ast_bridge_channel_merge_inhibit(bridge_channel, +1);
if (strcmp(bridge->v_table->name, "basic")) {
ast_log(LOG_ERROR, "Attended transfer attempted on unsupported bridge type '%s'\n", bridge->v_table->name);
ast_log(LOG_ERROR, "Attended transfer attempted on unsupported bridge type '%s'.\n",
bridge->v_table->name);
ast_bridge_merge_inhibit(bridge, -1);
ao2_ref(bridge, -1);
return 0;
}
if (bridge->inhibit_merge) {
ast_log(LOG_ERROR, "Unable to perform attended transfer since bridge '%s' does not permit merging.\n", bridge->uniqueid);
/* Was the bridge inhibited before we inhibited it? */
if (1 < bridge->inhibit_merge) {
/*
* The peer likely initiated attended transfer at the same time
* and we lost the race.
*/
ast_verb(3, "Channel %s: Bridge '%s' does not permit merging at this time.\n",
ast_channel_name(bridge_channel->chan), bridge->uniqueid);
ast_bridge_merge_inhibit(bridge, -1);
ao2_ref(bridge, -1);
return 0;
}
props = attended_transfer_properties_alloc(bridge, bridge_channel->chan,
attended_transfer ? attended_transfer->context : NULL);
props = attended_transfer_properties_alloc(bridge_channel->chan,
attended_transfer ? attended_transfer->context : NULL);
if (!props) {
ast_log(LOG_ERROR, "Unable to allocate control structure for performing attended transfer\n");
ast_log(LOG_ERROR, "Unable to allocate control structure for performing attended transfer.\n");
ast_bridge_merge_inhibit(bridge, -1);
ao2_ref(bridge, -1);
return 0;
}
props->transferee_bridge = bridge;
if (add_transferer_role(props->transferer, attended_transfer)) {
ast_log(LOG_ERROR, "Unable to set transferer bridge role properly\n");
ast_log(LOG_ERROR, "Unable to set transferrer bridge role.\n");
attended_transfer_properties_shutdown(props);
return 0;
}
ast_bridge_channel_write_hold(bridge_channel, NULL);
props->transferee_bridge = ast_bridge_channel_merge_inhibit(bridge_channel, +1);
/* Grab the extension to transfer to */
if (grab_transfer(bridge_channel->chan, exten, sizeof(exten), props->context)) {
ast_log(LOG_WARNING, "Unable to acquire target extension for attended transfer\n");
ast_log(LOG_WARNING, "Unable to acquire target extension for attended transfer.\n");
ast_bridge_channel_write_unhold(bridge_channel);
attended_transfer_properties_shutdown(props);
return 0;
@ -2679,7 +2692,7 @@ static int feature_attended_transfer(struct ast_bridge *bridge, struct ast_bridg
/* Get a channel that is the destination we wish to call */
props->transfer_target = dial_transfer(bridge_channel->chan, destination);
if (!props->transfer_target) {
ast_log(LOG_ERROR, "Unable to request outbound channel for attended transfer target\n");
ast_log(LOG_ERROR, "Unable to request outbound channel for attended transfer target.\n");
ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE);
ast_bridge_channel_write_unhold(bridge_channel);
attended_transfer_properties_shutdown(props);
@ -2690,7 +2703,7 @@ static int feature_attended_transfer(struct ast_bridge *bridge, struct ast_bridg
/* Create a bridge to use to talk to the person we are calling */
props->target_bridge = ast_bridge_basic_new();
if (!props->target_bridge) {
ast_log(LOG_ERROR, "Unable to create bridge for attended transfer target\n");
ast_log(LOG_ERROR, "Unable to create bridge for attended transfer target.\n");
ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE);
ast_bridge_channel_write_unhold(bridge_channel);
ast_hangup(props->transfer_target);
@ -2701,7 +2714,7 @@ static int feature_attended_transfer(struct ast_bridge *bridge, struct ast_bridg
ast_bridge_merge_inhibit(props->target_bridge, +1);
if (attach_framehook(props, props->transfer_target)) {
ast_log(LOG_ERROR, "Unable to attach framehook to transfer target\n");
ast_log(LOG_ERROR, "Unable to attach framehook to transfer target.\n");
ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE);
ast_bridge_channel_write_unhold(bridge_channel);
ast_hangup(props->transfer_target);
@ -2716,7 +2729,7 @@ static int feature_attended_transfer(struct ast_bridge *bridge, struct ast_bridg
BRIDGE_BASIC_PERSONALITY_ATXFER, props);
if (ast_call(props->transfer_target, destination, 0)) {
ast_log(LOG_ERROR, "Unable to place outbound call to transfer target\n");
ast_log(LOG_ERROR, "Unable to place outbound call to transfer target.\n");
ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE);
ast_bridge_channel_write_unhold(bridge_channel);
ast_hangup(props->transfer_target);
@ -2731,16 +2744,17 @@ static int feature_attended_transfer(struct ast_bridge *bridge, struct ast_bridg
*/
ast_channel_ref(props->transfer_target);
if (ast_bridge_impart(props->target_bridge, props->transfer_target, NULL, NULL, 1)) {
ast_log(LOG_ERROR, "Unable to place transfer target into bridge\n");
ast_log(LOG_ERROR, "Unable to place transfer target into bridge.\n");
ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE);
ast_bridge_channel_write_unhold(bridge_channel);
ast_hangup(props->transfer_target);
props->transfer_target = NULL;
attended_transfer_properties_shutdown(props);
return 0;
}
if (ast_pthread_create_detached(&thread, NULL, attended_transfer_monitor_thread, props)) {
ast_log(LOG_ERROR, "Unable to create monitoring thread for attended transfer\n");
ast_log(LOG_ERROR, "Unable to create monitoring thread for attended transfer.\n");
ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE);
ast_bridge_channel_write_unhold(bridge_channel);
attended_transfer_properties_shutdown(props);
@ -2764,18 +2778,13 @@ static void blind_transfer_cb(struct ast_channel *new_channel, void *user_data,
}
/*! \brief Internal built in feature for blind transfers */
static int feature_blind_transfer(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int feature_blind_transfer(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
char exten[AST_MAX_EXTENSION] = "";
struct ast_bridge_features_blind_transfer *blind_transfer = hook_pvt;
const char *context;
char *goto_on_blindxfr;
if (strcmp(bridge->v_table->name, "basic")) {
ast_log(LOG_ERROR, "Blind transfer attempted on unsupported bridge type '%s'\n", bridge->v_table->name);
return 0;
}
ast_bridge_channel_write_hold(bridge_channel, NULL);
ast_channel_lock(bridge_channel->chan);

@ -283,7 +283,7 @@ static void bridge_channel_handle_hangup(struct ast_bridge_channel *bridge_chann
if (hook->type != AST_BRIDGE_HOOK_TYPE_HANGUP) {
continue;
}
remove_me = hook->callback(bridge_channel->bridge, bridge_channel, hook->hook_pvt);
remove_me = hook->callback(bridge_channel, hook->hook_pvt);
if (remove_me) {
ast_debug(1, "Hangup hook %p is being removed from %p(%s)\n",
hook, bridge_channel, ast_channel_name(bridge_channel->chan));
@ -916,8 +916,7 @@ static void bridge_channel_handle_interval(struct ast_bridge_channel *bridge_cha
ast_debug(1, "Executing hook %p on %p(%s)\n",
hook, bridge_channel, ast_channel_name(bridge_channel->chan));
interval = hook->generic.callback(bridge_channel->bridge, bridge_channel,
hook->generic.hook_pvt);
interval = hook->generic.callback(bridge_channel, hook->generic.hook_pvt);
ast_heap_wrlock(interval_hooks);
if (ast_heap_peek(interval_hooks, hook->timer.heap_index) != hook
@ -1053,8 +1052,7 @@ static void bridge_channel_feature(struct ast_bridge_channel *bridge_channel)
if (hook) {
int remove_me;
remove_me = hook->generic.callback(bridge_channel->bridge, bridge_channel,
hook->generic.hook_pvt);
remove_me = hook->generic.callback(bridge_channel, hook->generic.hook_pvt);
if (remove_me) {
ast_debug(1, "DTMF hook %p is being removed from %p(%s)\n",
hook, bridge_channel, ast_channel_name(bridge_channel->chan));
@ -1782,7 +1780,7 @@ static void bridge_channel_event_join_leave(struct ast_bridge_channel *bridge_ch
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
do {
if (hook->type == type) {
hook->callback(bridge_channel->bridge, bridge_channel, hook->hook_pvt);
hook->callback(bridge_channel, hook->hook_pvt);
ao2_unlink(features->other_hooks, hook);
}
ao2_ref(hook, -1);

@ -1842,14 +1842,13 @@ struct dynamic_dtmf_hook_data {
* \brief Activated dynamic DTMF feature hook.
* \since 12.0.0
*
* \param bridge The bridge that the channel is part of
* \param bridge_channel Channel executing the feature
* \param hook_pvt Private data passed in when the hook was created
*
* \retval 0 Keep the callback hook.
* \retval -1 Remove the callback hook.
*/
static int dynamic_dtmf_hook_trip(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int dynamic_dtmf_hook_trip(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct dynamic_dtmf_hook_data *pvt = hook_pvt;
int (*run_it)(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_callback_fn callback, const void *payload, size_t payload_size);

@ -147,12 +147,12 @@ void ast_uninstall_bridge_channel_park_func(void)
ast_bridge_channel_park_func = NULL;
}
int ast_park_blind_xfer(struct ast_bridge *bridge, struct ast_bridge_channel *parker,
struct ast_exten *park_exten)
int ast_park_blind_xfer(struct ast_bridge_channel *parker, struct ast_exten *park_exten)
{
static int warned = 0;
if (ast_park_blind_xfer_func) {
return ast_park_blind_xfer_func(bridge, parker, park_exten);
return ast_park_blind_xfer_func(parker, park_exten);
}
if (warned++ % 10 == 0) {

@ -183,7 +183,7 @@ static int create_parked_subscription(struct ast_channel *chan, const char *park
/*!
* \internal
* \brief Helper function that creates an outgoing channel and returns it immediately. This function is nearly
* identical to the dial_transfer function in bridge_builtin_features.c, however it doesn't swap the
* identical to the dial_transfer function in bridge_basic.c, however it doesn't swap the
* local channel and the channel that instigated the park.
*/
static struct ast_channel *park_local_transfer(struct ast_channel *parker, const char *exten, const char *context)
@ -242,7 +242,7 @@ static struct ast_channel *park_local_transfer(struct ast_channel *parker, const
return parkee;
}
static int park_feature_helper(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_exten *park_exten)
static int park_feature_helper(struct ast_bridge_channel *bridge_channel, struct ast_exten *park_exten)
{
RAII_VAR(struct ast_channel *, other, NULL, ao2_cleanup);
RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
@ -251,7 +251,9 @@ static int park_feature_helper(struct ast_bridge *bridge, struct ast_bridge_chan
RAII_VAR(struct ao2_container *, bridge_peers, NULL, ao2_cleanup);
struct ao2_iterator iter;
bridge_peers = ast_bridge_peers(bridge);
ast_bridge_channel_lock_bridge(bridge_channel);
bridge_peers = ast_bridge_peers_nolock(bridge_channel->bridge);
ast_bridge_unlock(bridge_channel->bridge);
if (ao2_container_count(bridge_peers) < 2) {
/* There is nothing to do if there is no one to park. */
@ -357,20 +359,19 @@ static void park_bridge_channel(struct ast_bridge_channel *bridge_channel, const
}
}
static int feature_park(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int feature_park(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
park_feature_helper(bridge, bridge_channel, NULL);
park_feature_helper(bridge_channel, NULL);
return 0;
}
/*! \internal
* \brief Interval hook. Pulls a parked call from the parking bridge after the timeout is passed and sets the resolution to timeout.
*
* \param bridge Which bridge the channel was parked in
* \param bridge_channel bridge channel this interval hook is being executed on
* \param hook_pvt A pointer to the parked_user struct associated with the channel is stuffed in here
*/
static int parking_duration_callback(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static int parking_duration_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
struct parked_user *user = hook_pvt;
struct ast_channel *chan = user->chan;

Loading…
Cancel
Save