Perform the initial renaming of the Bridging API

This patch does the following:
 * It pulls out bridge_channel and puts it into its own translation unit
 * It adds public and protected headers for bridging_channel. Protected
   functions are appropriate only for the Bridging API and sub-classes of a
   bridge.

(issue ASTERISK-22130)


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@395253 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/78/78/1
Matthew Jordan 12 years ago
parent 1f0ac51f49
commit d91dc6d1a8

@ -41,6 +41,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/bridging.h"
#include "asterisk/bridging_internal.h"
#include "asterisk/bridging_basic.h"
#include "asterisk/config_options.h"
#include "asterisk/features_config.h"
@ -1054,7 +1055,7 @@ static void agent_connect_caller(struct ast_bridge_channel *bridge_channel, stru
if (!caller_bridge) {
/* Reset agent. */
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel);
return;
}
res = ast_bridge_move(caller_bridge, bridge_channel->bridge, bridge_channel->chan,
@ -1062,7 +1063,7 @@ static void agent_connect_caller(struct ast_bridge_channel *bridge_channel, stru
if (res) {
/* Reset agent. */
ast_bridge_destroy(caller_bridge);
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel);
return;
}
ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_ANSWER, NULL, 0);
@ -1158,13 +1159,13 @@ static int bridge_agent_hold_heartbeat(struct ast_bridge *bridge, struct ast_bri
if (deferred_logoff) {
ast_debug(1, "Agent %s: Deferred logoff.\n", agent->username);
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel);
} else if (probation_timedout) {
ast_debug(1, "Agent %s: Login complete.\n", agent->username);
agent_devstate_changed(agent->username);
} else if (ack_timedout) {
ast_debug(1, "Agent %s: Ack call timeout.\n", agent->username);
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel);
} else if (wrapup_timedout) {
ast_debug(1, "Agent %s: Wrapup timeout. Ready for new call.\n", agent->username);
agent_devstate_changed(agent->username);
@ -1269,7 +1270,7 @@ static int bridge_agent_hold_push(struct ast_bridge *self, struct ast_bridge_cha
* agent will have some slightly different behavior in corner
* cases.
*/
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel);
return 0;
}
@ -1393,11 +1394,11 @@ static struct ast_bridge *bridge_agent_hold_new(void)
{
struct ast_bridge *bridge;
bridge = ast_bridge_alloc(sizeof(struct ast_bridge), &bridge_agent_hold_v_table);
bridge = ast_bridge_base_init(bridge, AST_BRIDGE_CAPABILITY_HOLDING,
bridge = bridge_alloc(sizeof(struct ast_bridge), &bridge_agent_hold_v_table);
bridge = bridge_base_init(bridge, AST_BRIDGE_CAPABILITY_HOLDING,
AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
| AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED);
bridge = ast_bridge_register(bridge);
bridge = bridge_register(bridge);
return bridge;
}
@ -1703,7 +1704,7 @@ static void caller_abort_agent(struct agent_pvt *agent)
}
/* Kick the agent out of the holding bridge to reset it. */
ast_bridge_change_state_nolock(logged, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge_nolock(logged);
ast_bridge_channel_unlock(logged);
}
@ -1713,7 +1714,7 @@ static int caller_safety_timeout(struct ast_bridge *bridge, struct ast_bridge_ch
if (agent->state == AGENT_STATE_CALL_PRESENT) {
ast_verb(3, "Agent '%s' did not respond. Safety timeout.\n", agent->username);
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel);
caller_abort_agent(agent);
}

@ -483,7 +483,7 @@ static int feature_hangup(struct ast_bridge *bridge, struct ast_bridge_channel *
* bridge_channel to force the channel out of the bridge and the
* core takes care of the rest.
*/
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel);
return 0;
}

@ -58,7 +58,7 @@ static int bridge_features_duration_callback(struct ast_bridge *bridge, struct a
ast_stream_and_wait(bridge_channel->chan, limits->duration_sound, AST_DIGIT_NONE);
}
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel);
ast_test_suite_event_notify("BRIDGE_TIMELIMIT", "Channel1: %s", ast_channel_name(bridge_channel->chan));
return -1;

@ -19,7 +19,7 @@
/*!
* \file
* \brief Channel Bridging API
* \brief Bridging API
*
* \author Richard Mudgett <rmudgett@digium.com>
* \author Joshua Colp <jcolp@digium.com>
@ -30,7 +30,7 @@
*/
/*!
* \page AstBridging Channel Bridging API
* \page AstBridging Bridging API
*
* The purpose of this API is to provide an easy and flexible way to bridge
* channels of different technologies with different features.
@ -70,10 +70,15 @@ extern "C" {
#endif
#include "asterisk/bridging_features.h"
#include "asterisk/bridging_channel.h"
#include "asterisk/bridging_roles.h"
#include "asterisk/dsp.h"
#include "asterisk/uuid.h"
struct ast_bridge_technology;
struct ast_bridge;
struct ast_bridge_tech_optimizations;
/*! \brief Capabilities for a bridge technology */
enum ast_bridge_capability {
/*! Bridge technology can service calls on hold. */
@ -88,160 +93,7 @@ enum ast_bridge_capability {
AST_BRIDGE_CAPABILITY_MULTIMIX = (1 << 4),
};
/*! \brief State information about a bridged channel */
enum ast_bridge_channel_state {
/*! Waiting for a signal (Channel in the bridge) */
AST_BRIDGE_CHANNEL_STATE_WAIT = 0,
/*! Bridged channel was forced out and should be hung up (Bridge may dissolve.) */
AST_BRIDGE_CHANNEL_STATE_END,
/*! Bridged channel was forced out and should be hung up */
AST_BRIDGE_CHANNEL_STATE_HANGUP,
};
enum ast_bridge_channel_thread_state {
/*! Bridge channel thread is idle/waiting. */
AST_BRIDGE_CHANNEL_THREAD_IDLE,
/*! Bridge channel thread is writing a normal/simple frame. */
AST_BRIDGE_CHANNEL_THREAD_SIMPLE,
/*! Bridge channel thread is processing a frame. */
AST_BRIDGE_CHANNEL_THREAD_FRAME,
};
struct ast_bridge_technology;
struct ast_bridge;
/*!
* \brief Structure specific to bridge technologies capable of
* performing talking optimizations.
*/
struct ast_bridge_tech_optimizations {
/*! The amount of time in ms that talking must be detected before
* the dsp determines that talking has occurred */
unsigned int talking_threshold;
/*! The amount of time in ms that silence must be detected before
* the dsp determines that talking has stopped */
unsigned int silence_threshold;
/*! Whether or not the bridging technology should drop audio
* detected as silence from the mix. */
unsigned int drop_silence:1;
};
/*!
* \brief Structure that contains information regarding a channel in a bridge
*/
struct ast_bridge_channel {
/* BUGBUG cond is only here because of external party suspend/unsuspend support. */
/*! Condition, used if we want to wake up a thread waiting on the bridged channel */
ast_cond_t cond;
/*! Current bridged channel state */
enum ast_bridge_channel_state state;
/*! Asterisk channel participating in the bridge */
struct ast_channel *chan;
/*! Asterisk channel we are swapping with (if swapping) */
struct ast_channel *swap;
/*!
* \brief Bridge this channel is participating in
*
* \note The bridge pointer cannot change while the bridge or
* bridge_channel is locked.
*/
struct ast_bridge *bridge;
/*!
* \brief Bridge class private channel data.
*
* \note This information is added when the channel is pushed
* into the bridge and removed when it is pulled from the
* bridge.
*/
void *bridge_pvt;
/*!
* \brief Private information unique to the bridge technology.
*
* \note This information is added when the channel joins the
* bridge's technology and removed when it leaves the bridge's
* technology.
*/
void *tech_pvt;
/*! Thread handling the bridged channel (Needed by ast_bridge_depart) */
pthread_t thread;
/* v-- These flags change while the bridge is locked or before the channel is in the bridge. */
/*! TRUE if the channel is in a bridge. */
unsigned int in_bridge:1;
/*! TRUE if the channel just joined the bridge. */
unsigned int just_joined:1;
/*! TRUE if the channel is suspended from the bridge. */
unsigned int suspended:1;
/*! TRUE if the channel must wait for an ast_bridge_depart to reclaim the channel. */
unsigned int depart_wait:1;
/* ^-- These flags change while the bridge is locked or before the channel is in the bridge. */
/*! Features structure for features that are specific to this channel */
struct ast_bridge_features *features;
/*! Technology optimization parameters used by bridging technologies capable of
* optimizing based upon talk detection. */
struct ast_bridge_tech_optimizations tech_args;
/*! Copy of read format used by chan before join */
struct ast_format read_format;
/*! Copy of write format used by chan before join */
struct ast_format write_format;
/*! Call ID associated with bridge channel */
struct ast_callid *callid;
/*! A clone of the roles living on chan when the bridge channel joins the bridge. This may require some opacification */
struct bridge_roles_datastore *bridge_roles;
/*! Linked list information */
AST_LIST_ENTRY(ast_bridge_channel) entry;
/*! Queue of outgoing frames to the channel. */
AST_LIST_HEAD_NOLOCK(, ast_frame) wr_queue;
/*! Pipe to alert thread when frames are put into the wr_queue. */
int alert_pipe[2];
/*! TRUE if the bridge channel thread is waiting on channels (needs to be atomically settable) */
int waiting;
/*!
* \brief The bridge channel thread activity.
*
* \details Used by local channel optimization to determine if
* the thread is in an acceptable state to optimize.
*
* \note Needs to be atomically settable.
*/
enum ast_bridge_channel_thread_state activity;
};
enum ast_bridge_action_type {
/*! Bridged channel is to detect a feature hook */
AST_BRIDGE_ACTION_FEATURE,
/*! Bridged channel is to act on an interval hook */
AST_BRIDGE_ACTION_INTERVAL,
/*! Bridged channel is to send a DTMF stream out */
AST_BRIDGE_ACTION_DTMF_STREAM,
/*! Bridged channel is to indicate talking start */
AST_BRIDGE_ACTION_TALKING_START,
/*! Bridged channel is to indicate talking stop */
AST_BRIDGE_ACTION_TALKING_STOP,
/*! Bridge channel is to play the indicated sound file. */
AST_BRIDGE_ACTION_PLAY_FILE,
/*! Bridge channel is to run the indicated application. */
AST_BRIDGE_ACTION_RUN_APP,
/*! Bridge channel is to run the custom callback routine. */
AST_BRIDGE_ACTION_CALLBACK,
/*! Bridge channel is to get parked. */
AST_BRIDGE_ACTION_PARK,
/*! Bridge channel is to execute a blind transfer. */
AST_BRIDGE_ACTION_BLIND_TRANSFER,
/*! Bridge channel is to execute an attended transfer */
AST_BRIDGE_ACTION_ATTENDED_TRANSFER,
/*
* Bridge actions put after this comment must never be put onto
* the bridge_channel wr_queue because they have other resources
* that must be freed.
*/
/*! Bridge reconfiguration deferred technology destruction. */
AST_BRIDGE_ACTION_DEFERRED_TECH_DESTROY = 1000,
/*! Bridge deferred dissolving. */
AST_BRIDGE_ACTION_DEFERRED_DISSOLVING,
};
/*! \brief Video source modes */
enum ast_bridge_video_mode_type {
/*! Video is not allowed in the bridge */
AST_BRIDGE_VIDEO_MODE_NONE = 0,
@ -252,14 +104,14 @@ enum ast_bridge_video_mode_type {
AST_BRIDGE_VIDEO_MODE_TALKER_SRC,
};
/*! This is used for both SINGLE_SRC mode to set what channel
/*! \brief This is used for both SINGLE_SRC mode to set what channel
* should be the current single video feed */
struct ast_bridge_video_single_src_data {
/*! Only accept video coming from this channel */
struct ast_channel *chan_vsrc;
};
/*! This is used for both SINGLE_SRC_TALKER mode to set what channel
/*! \brief This is used for both SINGLE_SRC_TALKER mode to set what channel
* should be the current single video feed */
struct ast_bridge_video_talker_src_data {
/*! Only accept video coming from this channel */
@ -270,6 +122,7 @@ struct ast_bridge_video_talker_src_data {
struct ast_channel *chan_old_vsrc;
};
/*! \brief Data structure that defines a video source mode */
struct ast_bridge_video_mode {
enum ast_bridge_video_mode_type mode;
/* Add data for all the video modes here. */
@ -371,7 +224,7 @@ typedef int (*ast_bridge_merge_priority_fn)(struct ast_bridge *self);
* \brief Bridge virtual methods table definition.
*
* \note Any changes to this struct must be reflected in
* ast_bridge_alloc() validity checking.
* bridge_alloc() validity checking.
*/
struct ast_bridge_methods {
/*! Bridge class name for log messages. */
@ -390,6 +243,8 @@ struct ast_bridge_methods {
ast_bridge_merge_priority_fn get_merge_priority;
};
struct ast_bridge_channel;
/*! Softmix technology parameters. */
struct ast_bridge_softmix {
/*! The video mode softmix is using */
@ -455,75 +310,9 @@ struct ast_bridge {
char uniqueid[AST_UUID_STR_LEN];
};
/*!
* \brief Register the new bridge with the system.
* \since 12.0.0
*
* \param bridge What to register. (Tolerates a NULL pointer)
*
* \code
* struct ast_bridge *ast_bridge_basic_new(uint32_t capabilities, int flags, uint32 dtmf_features)
* {
* void *bridge;
*
* bridge = ast_bridge_alloc(sizeof(struct ast_bridge_basic), &ast_bridge_basic_v_table);
* bridge = ast_bridge_base_init(bridge, capabilities, flags);
* bridge = ast_bridge_basic_init(bridge, dtmf_features);
* bridge = ast_bridge_register(bridge);
* return bridge;
* }
* \endcode
*
* \note This must be done after a bridge constructor has
* completed setting up the new bridge but before it returns.
*
* \note After a bridge is registered, ast_bridge_destroy() must
* eventually be called to get rid of the bridge.
*
* \retval bridge on success.
* \retval NULL on error.
*/
struct ast_bridge *ast_bridge_register(struct ast_bridge *bridge);
/*!
* \internal
* \brief Allocate the bridge class object memory.
* \since 12.0.0
*
* \param size Size of the bridge class structure to allocate.
* \param v_table Bridge class virtual method table.
*
* \retval bridge on success.
* \retval NULL on error.
*/
struct ast_bridge *ast_bridge_alloc(size_t size, const struct ast_bridge_methods *v_table);
/*! \brief Bridge base class virtual method table. */
extern struct ast_bridge_methods ast_bridge_base_v_table;
/*!
* \brief Initialize the base class of the bridge.
*
* \param self Bridge to operate upon. (Tolerates a NULL pointer)
* \param capabilities The capabilities that we require to be used on the bridge
* \param flags Flags that will alter the behavior of the bridge
*
* \retval self on success
* \retval NULL on failure, self is already destroyed
*
* Example usage:
*
* \code
* struct ast_bridge *bridge;
* bridge = ast_bridge_alloc(sizeof(*bridge), &ast_bridge_base_v_table);
* bridge = ast_bridge_base_init(bridge, AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_FLAG_DISSOLVE_HANGUP);
* \endcode
*
* This creates a no frills two party bridge that will be
* destroyed once one of the channels hangs up.
*/
struct ast_bridge *ast_bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags);
/*!
* \brief Create a new base class bridge
*
@ -824,20 +613,6 @@ int ast_bridge_move(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge
*/
void ast_bridge_merge_inhibit(struct ast_bridge *bridge, int request);
/*!
* \brief Adjust the bridge_channel's bridge merge inhibit request count.
* \since 12.0.0
*
* \param bridge_channel What to operate on.
* \param request Inhibit request increment.
* (Positive to add requests. Negative to remove requests.)
*
* \note This API call is meant for internal bridging operations.
*
* \retval bridge adjusted merge inhibit with reference count.
*/
struct ast_bridge *ast_bridge_channel_merge_inhibit(struct ast_bridge_channel *bridge_channel, int request);
/*!
* \brief Suspend a channel temporarily from a bridge
*
@ -942,101 +717,6 @@ enum ast_bridge_optimization {
enum ast_bridge_optimization ast_bridges_allow_optimization(struct ast_bridge *chan_bridge,
struct ast_bridge *peer_bridge);
/*!
* \brief Try locking the bridge_channel.
*
* \param bridge_channel What to try locking
*
* \retval 0 on success.
* \retval non-zero on error.
*/
#define ast_bridge_channel_trylock(bridge_channel) _ast_bridge_channel_trylock(bridge_channel, __FILE__, __PRETTY_FUNCTION__, __LINE__, #bridge_channel)
static inline int _ast_bridge_channel_trylock(struct ast_bridge_channel *bridge_channel, const char *file, const char *function, int line, const char *var)
{
return __ao2_trylock(bridge_channel, AO2_LOCK_REQ_MUTEX, file, function, line, var);
}
/*!
* \brief Lock the bridge_channel.
*
* \param bridge_channel What to lock
*
* \return Nothing
*/
#define ast_bridge_channel_lock(bridge_channel) _ast_bridge_channel_lock(bridge_channel, __FILE__, __PRETTY_FUNCTION__, __LINE__, #bridge_channel)
static inline void _ast_bridge_channel_lock(struct ast_bridge_channel *bridge_channel, const char *file, const char *function, int line, const char *var)
{
__ao2_lock(bridge_channel, AO2_LOCK_REQ_MUTEX, file, function, line, var);
}
/*!
* \brief Unlock the bridge_channel.
*
* \param bridge_channel What to unlock
*
* \return Nothing
*/
#define ast_bridge_channel_unlock(bridge_channel) _ast_bridge_channel_unlock(bridge_channel, __FILE__, __PRETTY_FUNCTION__, __LINE__, #bridge_channel)
static inline void _ast_bridge_channel_unlock(struct ast_bridge_channel *bridge_channel, const char *file, const char *function, int line, const char *var)
{
__ao2_unlock(bridge_channel, file, function, line, var);
}
/*!
* \brief Lock the bridge associated with the bridge channel.
* \since 12.0.0
*
* \param bridge_channel Channel that wants to lock the bridge.
*
* \details
* This is an upstream lock operation. The defined locking
* order is bridge then bridge_channel.
*
* \note On entry, neither the bridge nor bridge_channel is locked.
*
* \note The bridge_channel->bridge pointer changes because of a
* bridge-merge/channel-move operation between bridges.
*
* \return Nothing
*/
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Set bridge channel state to leave bridge (if not leaving already) with no lock.
*
* \param bridge_channel Channel to change the state on
* \param new_state The new state to place the channel into
*
* \note This API call is only meant to be used within the
* bridging module and hook callbacks to request the channel
* exit the bridge.
*
* \note This function assumes the bridge_channel is locked.
*/
void ast_bridge_change_state_nolock(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state);
/*!
* \brief Set bridge channel state to leave bridge (if not leaving already).
*
* \param bridge_channel Channel to change the state on
* \param new_state The new state to place the channel into
*
* Example usage:
*
* \code
* ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
* \endcode
*
* This places the channel pointed to by bridge_channel into the
* state AST_BRIDGE_CHANNEL_STATE_HANGUP if it was
* AST_BRIDGE_CHANNEL_STATE_WAIT before.
*
* \note This API call is only meant to be used within the
* bridging module and hook callbacks to request the channel
* exit the bridge.
*/
void ast_bridge_change_state(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state);
/*!
* \brief Put an action onto the specified bridge.
* \since 12.0.0
@ -1052,37 +732,6 @@ void ast_bridge_change_state(struct ast_bridge_channel *bridge_channel, enum ast
*/
int ast_bridge_queue_action(struct ast_bridge *bridge, struct ast_frame *action);
/*!
* \brief Update the linkedid for all channels in a bridge
* \since 12.0.0
*
* \param bridge The bridge to update the linkedids on
* \param bridge_channel The channel joining the bridge
* \param swap The channel being swapped out of the bridge. May be NULL.
*
* \note The bridge must be locked prior to calling this function.
* \note This API call is meant for internal bridging operations.
*/
void ast_bridge_update_linkedids(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
/*!
* \brief Update the accountcodes for a channel entering a bridge
* \since 12.0.0
*
* This function updates the accountcode and peeraccount on channels in two-party
* bridges. In multi-party bridges, peeraccount is not set - it doesn't make much sense -
* however accountcode propagation will still occur if the channel joining has an
* accountcode.
*
* \param bridge The bridge to update the accountcodes in
* \param bridge_channel The channel joining the bridge
* \param swap The channel being swapped out of the bridge. May be NULL.
*
* \note The bridge must be locked prior to calling this function.
* \note This API call is meant for internal bridging operations.
*/
void ast_bridge_update_accountcodes(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
/*!
* \brief Queue the given frame to everyone else.
* \since 12.0.0
@ -1099,319 +748,6 @@ void ast_bridge_update_accountcodes(struct ast_bridge *bridge, struct ast_bridge
*/
int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame);
/*!
* \brief Write a frame to the specified bridge_channel.
* \since 12.0.0
*
* \param bridge_channel Channel to queue the frame.
* \param fr Frame to write.
*
* \retval 0 on success.
* \retval -1 on error.
*
* \note This API call is meant for internal bridging operations.
* \note BUGBUG This may get moved.
*/
int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *fr);
/*!
* \brief Used to queue an action frame onto a bridge channel and write an action frame into a bridge.
* \since 12.0.0
*
* \param bridge_channel Which channel work with.
* \param action Type of bridge action frame.
* \param data Frame payload data to pass.
* \param datalen Frame payload data length to pass.
*
* \retval 0 on success.
* \retval -1 on error.
*/
typedef int (*ast_bridge_channel_post_action_data)(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen);
/*!
* \brief Queue an action frame onto the bridge channel with data.
* \since 12.0.0
*
* \param bridge_channel Which channel to queue the frame onto.
* \param action Type of bridge action frame.
* \param data Frame payload data to pass.
* \param datalen Frame payload data length to pass.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_queue_action_data(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen);
/*!
* \brief Write an action frame into the bridge with data.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the frame into the bridge.
* \param action Type of bridge action frame.
* \param data Frame payload data to pass.
* \param datalen Frame payload data length to pass.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_action_data(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen);
/*!
* \brief Queue a control frame onto the bridge channel with data.
* \since 12.0.0
*
* \param bridge_channel Which channel to queue the frame onto.
* \param control Type of control frame.
* \param data Frame payload data to pass.
* \param datalen Frame payload data length to pass.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_queue_control_data(struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen);
/*!
* \brief Write a control frame into the bridge with data.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the frame into the bridge.
* \param control Type of control frame.
* \param data Frame payload data to pass.
* \param datalen Frame payload data length to pass.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_control_data(struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen);
/*!
* \brief Write a hold frame into the bridge.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the hold into the bridge.
* \param moh_class The suggested music class for the other end to use.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, const char *moh_class);
/*!
* \brief Write an unhold frame into the bridge.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the hold into the bridge.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Run an application on the bridge channel.
* \since 12.0.0
*
* \param bridge_channel Which channel to run the application on.
* \param app_name Dialplan application name.
* \param app_args Arguments for the application. (NULL tolerant)
* \param moh_class MOH class to request bridge peers to hear while application is running.
* NULL if no MOH.
* Empty if default MOH class.
*
* \note This is intended to be called by bridge hooks.
*
* \return Nothing
*/
void ast_bridge_channel_run_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class);
/*!
* \brief Write a bridge action run application frame into the bridge.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the frame into the bridge
* \param app_name Dialplan application name.
* \param app_args Arguments for the application. (NULL or empty for no arguments)
* \param moh_class MOH class to request bridge peers to hear while application is running.
* NULL if no MOH.
* Empty if default MOH class.
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class);
/*!
* \brief Queue a bridge action run application frame onto the bridge channel.
* \since 12.0.0
*
* \param bridge_channel Which channel to put the frame onto
* \param app_name Dialplan application name.
* \param app_args Arguments for the application. (NULL or empty for no arguments)
* \param moh_class MOH class to request bridge peers to hear while application is running.
* NULL if no MOH.
* Empty if default MOH class.
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_queue_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class);
/*!
* \brief Custom interpretation of the playfile name.
*
* \param bridge_channel Which channel to play the file on
* \param playfile Sound filename to play.
*
* \return Nothing
*/
typedef void (*ast_bridge_custom_play_fn)(struct ast_bridge_channel *bridge_channel, const char *playfile);
/*!
* \brief Play a file on the bridge channel.
* \since 12.0.0
*
* \param bridge_channel Which channel to play the file on
* \param custom_play Call this function to play the playfile. (NULL if normal sound file to play)
* \param playfile Sound filename to play.
* \param moh_class MOH class to request bridge peers to hear while file is played.
* NULL if no MOH.
* Empty if default MOH class.
*
* \note This is intended to be called by bridge hooks.
*
* \return Nothing
*/
void ast_bridge_channel_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class);
/*!
* \brief Write a bridge action play file frame into the bridge.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the frame into the bridge
* \param custom_play Call this function to play the playfile. (NULL if normal sound file to play)
* \param playfile Sound filename to play.
* \param moh_class MOH class to request bridge peers to hear while file is played.
* NULL if no MOH.
* Empty if default MOH class.
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class);
/*!
* \brief Queue a bridge action play file frame onto the bridge channel.
* \since 12.0.0
*
* \param bridge_channel Which channel to put the frame onto.
* \param custom_play Call this function to play the playfile. (NULL if normal sound file to play)
* \param playfile Sound filename to play.
* \param moh_class MOH class to request bridge peers to hear while file is played.
* NULL if no MOH.
* Empty if default MOH class.
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_queue_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class);
/*!
* \brief Custom callback run on a bridge channel.
*
* \param bridge_channel Which channel to operate on.
* \param payload Data to pass to the callback. (NULL if none).
* \param payload_size Size of the payload if payload is non-NULL. A number otherwise.
*
* \note The payload MUST NOT have any resources that need to be freed.
*
* \return Nothing
*/
typedef void (*ast_bridge_custom_callback_fn)(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size);
/*!
* \brief Write a bridge action custom callback frame into the bridge.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the frame into the bridge
* \param callback Custom callback run on a bridge channel.
* \param payload Data to pass to the callback. (NULL if none).
* \param payload_size Size of the payload if payload is non-NULL. A number otherwise.
*
* \note The payload MUST NOT have any resources that need to be freed.
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_callback(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_callback_fn callback, const void *payload, size_t payload_size);
/*!
* \brief Queue a bridge action custom callback frame onto the bridge channel.
* \since 12.0.0
*
* \param bridge_channel Which channel to put the frame onto.
* \param callback Custom callback run on a bridge channel.
* \param payload Data to pass to the callback. (NULL if none).
* \param payload_size Size of the payload if payload is non-NULL. A number otherwise.
*
* \note The payload MUST NOT have any resources that need to be freed.
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_queue_callback(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_callback_fn callback, const void *payload, size_t payload_size);
/*!
* \brief Have a bridge channel park a channel in the bridge
* \since 12.0.0
*
* \param bridge_channel Bridge channel performing the parking
* \param parkee_uuid Unique id of the channel we want to park
* \param parker_uuid Unique id of the channel parking the call
* \param app_data string indicating data used for park application (NULL allowed)
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_park(struct ast_bridge_channel *bridge_channel, const char *parkee_uuid,
const char *parker_uuid, const char *app_data);
/*!
* \brief Restore the formats of a bridge channel's channel to how they were before bridge_channel_join
* \since 12.0.0
*
* \param bridge_channel Channel to restore
*/
void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Get the peer bridge channel of a two party bridge.
* \since 12.0.0
*
* \param bridge_channel What to get the peer of.
*
* \note On entry, bridge_channel->bridge is already locked.
*
* \note This is an internal bridge function.
*
* \retval peer on success.
* \retval NULL no peer channel.
*/
struct ast_bridge_channel *ast_bridge_channel_peer(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Adjust the internal mixing sample rate of a bridge
* used during multimix mode.
@ -1810,6 +1146,7 @@ struct ast_channel *ast_bridge_peer(struct ast_bridge *bridge, struct ast_channe
* \return Nothing
*/
void ast_bridge_features_remove(struct ast_bridge_features *features, enum ast_bridge_hook_remove_flags flags);
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

@ -0,0 +1,576 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2013 Digium, Inc.
*
* Joshua Colp <jcolp@digium.com>
* Richard Mudgett <rmudgett@digium.com>
* Matt Jordan <mjordan@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!
* \file
* \brief Bridging Channel API
*
* An API that act on a channel in a bridge
*
* \author Joshua Colp <jcolp@digium.com>
* \author Richard Mudgett <rmudgett@digium.com>
* \author Matt Jordan <mjordan@digium.com>
*
* See Also:
* \ref bridging.h
* \arg \ref AstCREDITS
*/
#ifndef _ASTERISK_BRIDGING_CHANNEL_H
#define _ASTERISK_BRIDGING_CHANNEL_H
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#include "asterisk/bridging_technology.h"
/*! \brief State information about a bridged channel */
enum ast_bridge_channel_state {
/*! Waiting for a signal (Channel in the bridge) */
AST_BRIDGE_CHANNEL_STATE_WAIT = 0,
/*! Bridged channel was forced out and should be hung up (Bridge may dissolve.) */
AST_BRIDGE_CHANNEL_STATE_END,
/*! Bridged channel was forced out and should be hung up */
AST_BRIDGE_CHANNEL_STATE_HANGUP,
};
enum ast_bridge_channel_thread_state {
/*! Bridge channel thread is idle/waiting. */
AST_BRIDGE_CHANNEL_THREAD_IDLE,
/*! Bridge channel thread is writing a normal/simple frame. */
AST_BRIDGE_CHANNEL_THREAD_SIMPLE,
/*! Bridge channel thread is processing a frame. */
AST_BRIDGE_CHANNEL_THREAD_FRAME,
};
/*! \brief Actions that can be taken on a channel in a bridge */
enum ast_bridge_action_type {
/*! Bridged channel is to detect a feature hook */
AST_BRIDGE_ACTION_FEATURE,
/*! Bridged channel is to act on an interval hook */
AST_BRIDGE_ACTION_INTERVAL,
/*! Bridged channel is to send a DTMF stream out */
AST_BRIDGE_ACTION_DTMF_STREAM,
/*! Bridged channel is to indicate talking start */
AST_BRIDGE_ACTION_TALKING_START,
/*! Bridged channel is to indicate talking stop */
AST_BRIDGE_ACTION_TALKING_STOP,
/*! Bridge channel is to play the indicated sound file. */
AST_BRIDGE_ACTION_PLAY_FILE,
/*! Bridge channel is to run the indicated application. */
AST_BRIDGE_ACTION_RUN_APP,
/*! Bridge channel is to run the custom callback routine. */
AST_BRIDGE_ACTION_CALLBACK,
/*! Bridge channel is to get parked. */
AST_BRIDGE_ACTION_PARK,
/*! Bridge channel is to execute a blind transfer. */
AST_BRIDGE_ACTION_BLIND_TRANSFER,
/*! Bridge channel is to execute an attended transfer */
AST_BRIDGE_ACTION_ATTENDED_TRANSFER,
/*
* Bridge actions put after this comment must never be put onto
* the bridge_channel wr_queue because they have other resources
* that must be freed.
*/
/*! Bridge reconfiguration deferred technology destruction. */
AST_BRIDGE_ACTION_DEFERRED_TECH_DESTROY = 1000,
/*! Bridge deferred dissolving. */
AST_BRIDGE_ACTION_DEFERRED_DISSOLVING,
};
struct ast_bridge;
struct ast_bridge_tech_optimizations;
/*!
* \brief Structure that contains information regarding a channel in a bridge
*/
struct ast_bridge_channel {
/* BUGBUG cond is only here because of external party suspend/unsuspend support. */
/*! Condition, used if we want to wake up a thread waiting on the bridged channel */
ast_cond_t cond;
/*! Current bridged channel state */
enum ast_bridge_channel_state state;
/*! Asterisk channel participating in the bridge */
struct ast_channel *chan;
/*! Asterisk channel we are swapping with (if swapping) */
struct ast_channel *swap;
/*!
* \brief Bridge this channel is participating in
*
* \note The bridge pointer cannot change while the bridge or
* bridge_channel is locked.
*/
struct ast_bridge *bridge;
/*!
* \brief Bridge class private channel data.
*
* \note This information is added when the channel is pushed
* into the bridge and removed when it is pulled from the
* bridge.
*/
void *bridge_pvt;
/*!
* \brief Private information unique to the bridge technology.
*
* \note This information is added when the channel joins the
* bridge's technology and removed when it leaves the bridge's
* technology.
*/
void *tech_pvt;
/*! Thread handling the bridged channel (Needed by ast_bridge_depart) */
pthread_t thread;
/* v-- These flags change while the bridge is locked or before the channel is in the bridge. */
/*! TRUE if the channel is in a bridge. */
unsigned int in_bridge:1;
/*! TRUE if the channel just joined the bridge. */
unsigned int just_joined:1;
/*! TRUE if the channel is suspended from the bridge. */
unsigned int suspended:1;
/*! TRUE if the channel must wait for an ast_bridge_depart to reclaim the channel. */
unsigned int depart_wait:1;
/* ^-- These flags change while the bridge is locked or before the channel is in the bridge. */
/*! Features structure for features that are specific to this channel */
struct ast_bridge_features *features;
/*! Technology optimization parameters used by bridging technologies capable of
* optimizing based upon talk detection. */
struct ast_bridge_tech_optimizations tech_args;
/*! Copy of read format used by chan before join */
struct ast_format read_format;
/*! Copy of write format used by chan before join */
struct ast_format write_format;
/*! Call ID associated with bridge channel */
struct ast_callid *callid;
/*! A clone of the roles living on chan when the bridge channel joins the bridge. This may require some opacification */
struct bridge_roles_datastore *bridge_roles;
/*! Linked list information */
AST_LIST_ENTRY(ast_bridge_channel) entry;
/*! Queue of outgoing frames to the channel. */
AST_LIST_HEAD_NOLOCK(, ast_frame) wr_queue;
/*! Pipe to alert thread when frames are put into the wr_queue. */
int alert_pipe[2];
/*! TRUE if the bridge channel thread is waiting on channels (needs to be atomically settable) */
int waiting;
/*!
* \brief The bridge channel thread activity.
*
* \details Used by local channel optimization to determine if
* the thread is in an acceptable state to optimize.
*
* \note Needs to be atomically settable.
*/
enum ast_bridge_channel_thread_state activity;
};
/*!
* \brief Try locking the bridge_channel.
*
* \param bridge_channel What to try locking
*
* \retval 0 on success.
* \retval non-zero on error.
*/
#define ast_bridge_channel_trylock(bridge_channel) _ast_bridge_channel_trylock(bridge_channel, __FILE__, __PRETTY_FUNCTION__, __LINE__, #bridge_channel)
static inline int _ast_bridge_channel_trylock(struct ast_bridge_channel *bridge_channel, const char *file, const char *function, int line, const char *var)
{
return __ao2_trylock(bridge_channel, AO2_LOCK_REQ_MUTEX, file, function, line, var);
}
/*!
* \brief Lock the bridge_channel.
*
* \param bridge_channel What to lock
*
* \return Nothing
*/
#define ast_bridge_channel_lock(bridge_channel) _ast_bridge_channel_lock(bridge_channel, __FILE__, __PRETTY_FUNCTION__, __LINE__, #bridge_channel)
static inline void _ast_bridge_channel_lock(struct ast_bridge_channel *bridge_channel, const char *file, const char *function, int line, const char *var)
{
__ao2_lock(bridge_channel, AO2_LOCK_REQ_MUTEX, file, function, line, var);
}
/*!
* \brief Unlock the bridge_channel.
*
* \param bridge_channel What to unlock
*
* \return Nothing
*/
#define ast_bridge_channel_unlock(bridge_channel) _ast_bridge_channel_unlock(bridge_channel, __FILE__, __PRETTY_FUNCTION__, __LINE__, #bridge_channel)
static inline void _ast_bridge_channel_unlock(struct ast_bridge_channel *bridge_channel, const char *file, const char *function, int line, const char *var)
{
__ao2_unlock(bridge_channel, file, function, line, var);
}
/*!
* \brief Lock the bridge associated with the bridge channel.
* \since 12.0.0
*
* \param bridge_channel Channel that wants to lock the bridge.
*
* \details
* This is an upstream lock operation. The defined locking
* order is bridge then bridge_channel.
*
* \note On entry, neither the bridge nor bridge_channel is locked.
*
* \note The bridge_channel->bridge pointer changes because of a
* bridge-merge/channel-move operation between bridges.
*
* \return Nothing
*/
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Ask the bridged channel to leave the bridge it is currently in
*
* \param bridge_channel Channel to leave the bridge
*/
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Ask the bridged channel to leave the bridge it is currently in
*
* \param bridge_channel Channel to leave the bridge
*
* \note This function assumes the bridge_channel is locked.
*/
void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Write a frame to the specified bridge_channel.
* \since 12.0.0
*
* \param bridge_channel Channel to queue the frame.
* \param fr Frame to write.
*
* \retval 0 on success.
* \retval -1 on error.
*
* \note This API call is meant for internal bridging operations.
* \note BUGBUG This may get moved.
*/
int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *fr);
/*!
* \brief Used to queue an action frame onto a bridge channel and write an action frame into a bridge.
* \since 12.0.0
*
* \param bridge_channel Which channel work with.
* \param action Type of bridge action frame.
* \param data Frame payload data to pass.
* \param datalen Frame payload data length to pass.
*
* \retval 0 on success.
* \retval -1 on error.
*/
typedef int (*ast_bridge_channel_post_action_data)(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen);
/*!
* \brief Queue an action frame onto the bridge channel with data.
* \since 12.0.0
*
* \param bridge_channel Which channel to queue the frame onto.
* \param action Type of bridge action frame.
* \param data Frame payload data to pass.
* \param datalen Frame payload data length to pass.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_queue_action_data(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen);
/*!
* \brief Write an action frame into the bridge with data.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the frame into the bridge.
* \param action Type of bridge action frame.
* \param data Frame payload data to pass.
* \param datalen Frame payload data length to pass.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_action_data(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen);
/*!
* \brief Queue a control frame onto the bridge channel with data.
* \since 12.0.0
*
* \param bridge_channel Which channel to queue the frame onto.
* \param control Type of control frame.
* \param data Frame payload data to pass.
* \param datalen Frame payload data length to pass.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_queue_control_data(struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen);
/*!
* \brief Write a control frame into the bridge with data.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the frame into the bridge.
* \param control Type of control frame.
* \param data Frame payload data to pass.
* \param datalen Frame payload data length to pass.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_control_data(struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen);
/*!
* \brief Write a hold frame into the bridge.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the hold into the bridge.
* \param moh_class The suggested music class for the other end to use.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, const char *moh_class);
/*!
* \brief Write an unhold frame into the bridge.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the hold into the bridge.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Run an application on the bridge channel.
* \since 12.0.0
*
* \param bridge_channel Which channel to run the application on.
* \param app_name Dialplan application name.
* \param app_args Arguments for the application. (NULL tolerant)
* \param moh_class MOH class to request bridge peers to hear while application is running.
* NULL if no MOH.
* Empty if default MOH class.
*
* \note This is intended to be called by bridge hooks.
*
* \return Nothing
*/
void ast_bridge_channel_run_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class);
/*!
* \brief Write a bridge action run application frame into the bridge.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the frame into the bridge
* \param app_name Dialplan application name.
* \param app_args Arguments for the application. (NULL or empty for no arguments)
* \param moh_class MOH class to request bridge peers to hear while application is running.
* NULL if no MOH.
* Empty if default MOH class.
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class);
/*!
* \brief Queue a bridge action run application frame onto the bridge channel.
* \since 12.0.0
*
* \param bridge_channel Which channel to put the frame onto
* \param app_name Dialplan application name.
* \param app_args Arguments for the application. (NULL or empty for no arguments)
* \param moh_class MOH class to request bridge peers to hear while application is running.
* NULL if no MOH.
* Empty if default MOH class.
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_queue_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class);
/*!
* \brief Custom interpretation of the playfile name.
*
* \param bridge_channel Which channel to play the file on
* \param playfile Sound filename to play.
*
* \return Nothing
*/
typedef void (*ast_bridge_custom_play_fn)(struct ast_bridge_channel *bridge_channel, const char *playfile);
/*!
* \brief Play a file on the bridge channel.
* \since 12.0.0
*
* \param bridge_channel Which channel to play the file on
* \param custom_play Call this function to play the playfile. (NULL if normal sound file to play)
* \param playfile Sound filename to play.
* \param moh_class MOH class to request bridge peers to hear while file is played.
* NULL if no MOH.
* Empty if default MOH class.
*
* \note This is intended to be called by bridge hooks.
*
* \return Nothing
*/
void ast_bridge_channel_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class);
/*!
* \brief Write a bridge action play file frame into the bridge.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the frame into the bridge
* \param custom_play Call this function to play the playfile. (NULL if normal sound file to play)
* \param playfile Sound filename to play.
* \param moh_class MOH class to request bridge peers to hear while file is played.
* NULL if no MOH.
* Empty if default MOH class.
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class);
/*!
* \brief Queue a bridge action play file frame onto the bridge channel.
* \since 12.0.0
*
* \param bridge_channel Which channel to put the frame onto.
* \param custom_play Call this function to play the playfile. (NULL if normal sound file to play)
* \param playfile Sound filename to play.
* \param moh_class MOH class to request bridge peers to hear while file is played.
* NULL if no MOH.
* Empty if default MOH class.
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_queue_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class);
/*!
* \brief Custom callback run on a bridge channel.
*
* \param bridge_channel Which channel to operate on.
* \param payload Data to pass to the callback. (NULL if none).
* \param payload_size Size of the payload if payload is non-NULL. A number otherwise.
*
* \note The payload MUST NOT have any resources that need to be freed.
*
* \return Nothing
*/
typedef void (*ast_bridge_custom_callback_fn)(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size);
/*!
* \brief Write a bridge action custom callback frame into the bridge.
* \since 12.0.0
*
* \param bridge_channel Which channel is putting the frame into the bridge
* \param callback Custom callback run on a bridge channel.
* \param payload Data to pass to the callback. (NULL if none).
* \param payload_size Size of the payload if payload is non-NULL. A number otherwise.
*
* \note The payload MUST NOT have any resources that need to be freed.
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_callback(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_callback_fn callback, const void *payload, size_t payload_size);
/*!
* \brief Queue a bridge action custom callback frame onto the bridge channel.
* \since 12.0.0
*
* \param bridge_channel Which channel to put the frame onto.
* \param callback Custom callback run on a bridge channel.
* \param payload Data to pass to the callback. (NULL if none).
* \param payload_size Size of the payload if payload is non-NULL. A number otherwise.
*
* \note The payload MUST NOT have any resources that need to be freed.
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_queue_callback(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_callback_fn callback, const void *payload, size_t payload_size);
/*!
* \brief Have a bridge channel park a channel in the bridge
* \since 12.0.0
*
* \param bridge_channel Bridge channel performing the parking
* \param parkee_uuid Unique id of the channel we want to park
* \param parker_uuid Unique id of the channel parking the call
* \param app_data string indicating data used for park application (NULL allowed)
*
* \note This is intended to be called by bridge hooks.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_write_park(struct ast_bridge_channel *bridge_channel, const char *parkee_uuid,
const char *parker_uuid, const char *app_data);
/*!
* \brief Restore the formats of a bridge channel's channel to how they were before bridge_channel_join
* \since 12.0.0
*
* \param bridge_channel Channel to restore
*/
void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Get the peer bridge channel of a two party bridge.
* \since 12.0.0
*
* \param bridge_channel What to get the peer of.
*
* \note On entry, bridge_channel->bridge is already locked.
*
* \note This is an internal bridge function.
*
* \retval peer on success.
* \retval NULL no peer channel.
*/
struct ast_bridge_channel *ast_bridge_channel_peer(struct ast_bridge_channel *bridge_channel);
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif /* _ASTERISK_BRIDGING_CHANNEL_H */

@ -0,0 +1,156 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2013 Digium, Inc.
*
* Matt Jordan <mjordan@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!
* \file
* \brief Private Bridging Channel API
*
* \author Matt Jordan <mjordan@digium.com>
*
* A private API to manipulate channels in a bridge. These can be called on a channel in
* a bridge by the bridging API, but should not be called by external consumers of the
* Bridging API.
*
* See Also:
* \arg \ref AstCREDITS
*/
#ifndef _ASTERISK_PRIVATE_BRIDGING_CHANNEL_H
#define _ASTERISK_PRIVATE_BRIDGING_CHANNEL_H
struct blind_transfer_data {
char exten[AST_MAX_EXTENSION];
char context[AST_MAX_CONTEXT];
};
/*!
* \brief Adjust the bridge_channel's bridge merge inhibit request count.
* \since 12.0.0
*
* \param bridge_channel What to operate on.
* \param request Inhibit request increment.
* (Positive to add requests. Negative to remove requests.)
*
* \note This API call is meant for internal bridging operations.
*
* \retval bridge adjusted merge inhibit with reference count.
*/
struct ast_bridge *bridge_channel_merge_inhibit(struct ast_bridge_channel *bridge_channel, int request);
/*!
* \internal
* \brief Pull the bridge channel out of its current bridge.
* \since 12.0.0
*
* \param bridge_channel Channel to pull.
*
* \note On entry, bridge_channel->bridge is already locked.
*
* \return Nothing
*/
void bridge_channel_pull(struct ast_bridge_channel *bridge_channel);
/*!
* \internal
* \brief Push the bridge channel into its specified bridge.
* \since 12.0.0
*
* \param bridge_channel Channel to push.
*
* \note On entry, bridge_channel->bridge is already locked.
*
* \retval 0 on success.
* \retval -1 on failure. The channel did not get pushed.
*/
int bridge_channel_push(struct ast_bridge_channel *bridge_channel);
void bridge_channel_join(struct ast_bridge_channel *bridge_channel);
void bridge_channel_suspend_nolock(struct ast_bridge_channel *bridge_channel);
void bridge_channel_unsuspend_nolock(struct ast_bridge_channel *bridge_channel);
/*!
* \internal
* \brief Update the linkedids for all channels in a bridge
* \since 12.0.0
*
* \param bridge_channel The channel joining the bridge
* \param swap The channel being swapped out of the bridge. May be NULL.
*
* \note The bridge must be locked prior to calling this function. This should be called
* during a \ref bridge_channel_push operation, typically by a sub-class of a bridge
*/
void bridge_channel_update_linkedids(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
/*!
* \internal
* \brief Update the accountcodes for a channel entering a bridge
* \since 12.0.0
*
* This function updates the accountcode and peeraccount on channels in two-party
* bridges. In multi-party bridges, peeraccount is not set - it doesn't make much sense -
* however accountcode propagation will still occur if the channel joining has an
* accountcode.
*
* \param bridge_channel The channel joining the bridge
* \param swap The channel being swapped out of the bridge. May be NULL.
*
* \note The bridge must be locked prior to calling this function. This should be called
* during a \ref bridge_channel_push operation, typically by a sub-class of a bridge
*/
void bridge_channel_update_accountcodes(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
/*!
* \brief Set bridge channel state to leave bridge (if not leaving already) with no lock.
*
* \param bridge_channel Channel to change the state on
* \param new_state The new state to place the channel into
*
* \note This API call is only meant to be used within the
* bridging module and hook callbacks to request the channel
* exit the bridge.
*
* \note This function assumes the bridge_channel is locked.
*/
void ast_bridge_change_state_nolock(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state);
/*!
* \brief Set bridge channel state to leave bridge (if not leaving already).
*
* \param bridge_channel Channel to change the state on
* \param new_state The new state to place the channel into
*
* Example usage:
*
* \code
* ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
* \endcode
*
* This places the channel pointed to by bridge_channel into the
* state AST_BRIDGE_CHANNEL_STATE_HANGUP if it was
* AST_BRIDGE_CHANNEL_STATE_WAIT before.
*
* \note This API call is only meant to be used within the
* bridging module and hook callbacks to request the channel
* exit the bridge.
*/
void ast_bridge_change_state(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state);
#endif /* _ASTERISK_PRIVATE_BRIDGING_H */

@ -20,6 +20,11 @@
* \file
* \brief Private Bridging API
*
* Functions in this file are intended to be used by the Bridging API,
* bridge mixing technologies, and bridge sub-classes. Users of bridges
* that do not fit those three categories should *not* use the API
* defined in this file.
*
* \author Mark Michelson <mmichelson@digium.com>
*
* See Also:
@ -32,6 +37,72 @@
struct ast_bridge;
struct ast_bridge_channel;
/*!
* \brief Register the new bridge with the system.
* \since 12.0.0
*
* \param bridge What to register. (Tolerates a NULL pointer)
*
* \code
* struct ast_bridge *ast_bridge_basic_new(uint32_t capabilities, int flags, uint32 dtmf_features)
* {
* void *bridge;
*
* bridge = bridge_alloc(sizeof(struct ast_bridge_basic), &ast_bridge_basic_v_table);
* bridge = bridge_base_init(bridge, capabilities, flags);
* bridge = ast_bridge_basic_init(bridge, dtmf_features);
* bridge = bridge_register(bridge);
* return bridge;
* }
* \endcode
*
* \note This must be done after a bridge constructor has
* completed setting up the new bridge but before it returns.
*
* \note After a bridge is registered, ast_bridge_destroy() must
* eventually be called to get rid of the bridge.
*
* \retval bridge on success.
* \retval NULL on error.
*/
struct ast_bridge *bridge_register(struct ast_bridge *bridge);
/*!
* \internal
* \brief Allocate the bridge class object memory.
* \since 12.0.0
*
* \param size Size of the bridge class structure to allocate.
* \param v_table Bridge class virtual method table.
*
* \retval bridge on success.
* \retval NULL on error.
*/
struct ast_bridge *bridge_alloc(size_t size, const struct ast_bridge_methods *v_table);
/*!
* \brief Initialize the base class of the bridge.
*
* \param self Bridge to operate upon. (Tolerates a NULL pointer)
* \param capabilities The capabilities that we require to be used on the bridge
* \param flags Flags that will alter the behavior of the bridge
*
* \retval self on success
* \retval NULL on failure, self is already destroyed
*
* Example usage:
*
* \code
* struct ast_bridge *bridge;
* bridge = bridge_alloc(sizeof(*bridge), &ast_bridge_base_v_table);
* bridge = bridge_base_init(bridge, AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_FLAG_DISSOLVE_HANGUP);
* \endcode
*
* This creates a no frills two party bridge that will be
* destroyed once one of the channels hangs up.
*/
struct ast_bridge *bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags);
/*!
* \internal
* \brief Move a bridge channel from one bridge to another.
@ -47,7 +118,7 @@ struct ast_bridge_channel;
* \retval 0 on success.
* \retval -1 on failure.
*/
int bridge_move_do(struct ast_bridge *dst_bridge, struct ast_bridge_channel *bridge_channel,
int bridge_do_move(struct ast_bridge *dst_bridge, struct ast_bridge_channel *bridge_channel,
int attempt_recovery, unsigned int optimized);
/*!
@ -68,7 +139,7 @@ int bridge_move_do(struct ast_bridge *dst_bridge, struct ast_bridge_channel *bri
* This moves the channels in src_bridge into the bridge pointed
* to by dst_bridge.
*/
void bridge_merge_do(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge,
void bridge_do_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge,
struct ast_bridge_channel **kick_me, unsigned int num_kick, unsigned int optimized);
/*!
@ -83,6 +154,58 @@ void bridge_merge_do(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridg
* \retval bridge_channel if channel is in the bridge.
* \retval NULL if not in bridge.
*/
struct ast_bridge_channel *find_bridge_channel(struct ast_bridge *bridge, struct ast_channel *chan);
struct ast_bridge_channel *bridge_find_channel(struct ast_bridge *bridge, struct ast_channel *chan);
/*!
* \internal
* \brief Adjust the bridge merge inhibit request count.
* \since 12.0.0
*
* \param bridge What to operate on.
* \param request Inhibit request increment.
* (Positive to add requests. Negative to remove requests.)
*
* \note This function assumes bridge is locked.
*
* \return Nothing
*/
void bridge_merge_inhibit_nolock(struct ast_bridge *bridge, int request);
/*!
* \internal
* \brief Notify the bridge that it has been reconfigured.
* \since 12.0.0
*
* \param bridge Reconfigured bridge.
* \param colp_update Whether to perform COLP updates.
*
* \details
* After a series of bridge_channel_push and
* bridge_channel_pull calls, you need to call this function
* to cause the bridge to complete restructuring for the change
* in the channel makeup of the bridge.
*
* \note On entry, the bridge is already locked.
*
* \return Nothing
*/
void bridge_reconfigured(struct ast_bridge *bridge, unsigned int colp_update);
/*!
* \internal
* \brief Dissolve the bridge.
* \since 12.0.0
*
* \param bridge Bridge to eject all channels
*
* \details
* Force out all channels that are not already going out of the
* bridge. Any new channels joining will leave immediately.
*
* \note On entry, bridge is already locked.
*
* \return Nothing
*/
void bridge_dissolve(struct ast_bridge *bridge);
#endif /* _ASTERISK_PRIVATE_BRIDGING_H */

@ -41,6 +41,22 @@ enum ast_bridge_preference {
AST_BRIDGE_PREFERENCE_BASE_MULTIMIX = 10,
};
/*!
* \brief Structure specific to bridge technologies capable of
* performing talking optimizations.
*/
struct ast_bridge_tech_optimizations {
/*! The amount of time in ms that talking must be detected before
* the dsp determines that talking has occurred */
unsigned int talking_threshold;
/*! The amount of time in ms that silence must be detected before
* the dsp determines that talking has stopped */
unsigned int silence_threshold;
/*! Whether or not the bridging technology should drop audio
* detected as silence from the mix. */
unsigned int drop_silence:1;
};
/*!
* \brief Structure that is the essence of a bridge technology
*/

@ -4385,4 +4385,16 @@ int ast_channel_suppress(struct ast_channel *chan, unsigned int direction, enum
*/
int ast_channel_unsuppress(struct ast_channel *chan, unsigned int direction, enum ast_frame_type frametype);
/*!
* \brief Simulate a DTMF end on a broken bridge channel.
*
* \param chan Channel sending DTMF that has not ended.
* \param digit DTMF digit to stop.
* \param start DTMF digit start time.
* \param why Reason bridge broken.
*
* \return Nothing
*/
void ast_channel_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why);
#endif /* _ASTERISK_CHANNEL_H */

@ -146,25 +146,13 @@ int ast_masq_park_call(struct ast_channel *park_me, struct ast_channel *parker,
*/
int ast_masq_park_call_exten(struct ast_channel *park_me, struct ast_channel *parker, const char *park_exten, const char *park_context, int timeout, int *extout);
/*!
/*!
* \brief Determine if parking extension exists in a given context
* \retval 0 if extension does not exist
* \retval 1 if extension does exist
*/
int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context);
/*!
* \brief Simulate a DTMF end on a broken bridge channel.
*
* \param chan Channel sending DTMF that has not ended.
* \param digit DTMF digit to stop.
* \param start DTMF digit start time.
* \param why Reason bridge broken.
*
* \return Nothing
*/
void ast_bridge_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why);
/*! \brief Bridge a call, optionally allowing redirection */
int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer,struct ast_bridge_config *config);

File diff suppressed because it is too large Load Diff

@ -42,6 +42,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/bridging_internal.h"
#include "asterisk/bridging_channel_internal.h"
#include "asterisk/dial.h"
#include "asterisk/stasis_bridging.h"
@ -341,8 +342,8 @@ static int bridge_personality_normal_push(struct ast_bridge *self, struct ast_br
return -1;
}
ast_bridge_update_accountcodes(self, bridge_channel, swap);
ast_bridge_update_linkedids(self, bridge_channel, swap);
bridge_channel_update_accountcodes(bridge_channel, swap);
bridge_channel_update_linkedids(bridge_channel, swap);
return 0;
}
@ -1367,7 +1368,7 @@ static void bridge_unhold(struct ast_bridge *bridge)
}
/*!
* \brief Wrapper for \ref bridge_move_do
* \brief Wrapper for \ref bridge_do_move
*/
static int bridge_move(struct ast_bridge *dest, struct ast_bridge *src, struct ast_channel *channel, struct ast_channel *swap)
{
@ -1386,7 +1387,7 @@ static int bridge_move(struct ast_bridge *dest, struct ast_bridge *src, struct a
bridge_channel->swap = swap;
ao2_unlock(bridge_channel);
res = bridge_move_do(dest, bridge_channel, 1, 0);
res = bridge_do_move(dest, bridge_channel, 1, 0);
ast_bridge_unlock(dest);
ast_bridge_unlock(src);
@ -1395,7 +1396,7 @@ static int bridge_move(struct ast_bridge *dest, struct ast_bridge *src, struct a
}
/*!
* \brief Wrapper for \ref bridge_merge_do
* \brief Wrapper for \ref bridge_do_merge
*/
static void bridge_merge(struct ast_bridge *dest, struct ast_bridge *src, struct ast_channel **kick_channels, unsigned int num_channels)
{
@ -1409,9 +1410,9 @@ static void bridge_merge(struct ast_bridge *dest, struct ast_bridge *src, struct
for (i = 0; i < num_channels; ++i) {
struct ast_bridge_channel *kick_bridge_channel;
kick_bridge_channel = find_bridge_channel(src, kick_channels[i]);
kick_bridge_channel = bridge_find_channel(src, kick_channels[i]);
if (!kick_bridge_channel) {
kick_bridge_channel = find_bridge_channel(dest, kick_channels[i]);
kick_bridge_channel = bridge_find_channel(dest, kick_channels[i]);
}
/* It's possible (and fine) for the bridge channel to be NULL at this point if the
@ -1425,7 +1426,7 @@ static void bridge_merge(struct ast_bridge *dest, struct ast_bridge *src, struct
kick_bridge_channels[num_bridge_channels++] = kick_bridge_channel;
}
bridge_merge_do(dest, src, kick_bridge_channels, num_bridge_channels, 0);
bridge_do_merge(dest, src, kick_bridge_channels, num_bridge_channels, 0);
ast_bridge_unlock(dest);
ast_bridge_unlock(src);
}
@ -2658,7 +2659,7 @@ static int feature_attended_transfer(struct ast_bridge *bridge, struct ast_bridg
}
ast_bridge_channel_write_hold(bridge_channel, NULL);
props->transferee_bridge = ast_bridge_channel_merge_inhibit(bridge_channel, +1);
props->transferee_bridge = bridge_channel_merge_inhibit(bridge_channel, +1);
/* Grab the extension to transfer to */
if (grab_transfer(bridge_channel->chan, exten, sizeof(exten), props->context)) {
@ -2900,12 +2901,12 @@ struct ast_bridge *ast_bridge_basic_new(void)
{
struct ast_bridge *bridge;
bridge = ast_bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_basic_v_table);
bridge = ast_bridge_base_init(bridge,
bridge = bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_basic_v_table);
bridge = bridge_base_init(bridge,
AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX
| AST_BRIDGE_CAPABILITY_MULTIMIX, NORMAL_FLAGS);
bridge = bridge_basic_personality_alloc(bridge);
bridge = ast_bridge_register(bridge);
bridge = bridge_register(bridge);
return bridge;
}

File diff suppressed because it is too large Load Diff

@ -6740,7 +6740,7 @@ void ast_do_masquerade(struct ast_channel *original)
* The clonechan was sending a DTMF digit that was not completed
* before the masquerade.
*/
ast_bridge_end_dtmf(original, clone_sending_dtmf_digit, clone_sending_dtmf_tv,
ast_channel_end_dtmf(original, clone_sending_dtmf_digit, clone_sending_dtmf_tv,
"masquerade");
}
@ -10406,3 +10406,24 @@ int ast_channel_unsuppress(struct ast_channel *chan, unsigned int direction, enu
return 0;
}
void ast_channel_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why)
{
int dead;
long duration;
ast_channel_lock(chan);
dead = ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE)
|| (ast_channel_softhangup_internal_flag(chan)
& ~(AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE));
ast_channel_unlock(chan);
if (dead) {
/* Channel is a zombie or a real hangup. */
return;
}
duration = ast_tvdiff_ms(ast_tvnow(), start);
ast_senddigit_end(chan, digit, duration);
ast_log(LOG_DTMF, "DTMF end '%c' simulated on %s due to %s, duration %ld ms\n",
digit, ast_channel_name(chan), why, duration);
}

@ -3161,27 +3161,6 @@ static void clear_dialed_interfaces(struct ast_channel *chan)
ast_channel_unlock(chan);
}
void ast_bridge_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why)
{
int dead;
long duration;
ast_channel_lock(chan);
dead = ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE)
|| (ast_channel_softhangup_internal_flag(chan)
& ~(AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE));
ast_channel_unlock(chan);
if (dead) {
/* Channel is a zombie or a real hangup. */
return;
}
duration = ast_tvdiff_ms(ast_tvnow(), start);
ast_senddigit_end(chan, digit, duration);
ast_log(LOG_DTMF, "DTMF end '%c' simulated on %s due to %s, duration %ld ms\n",
digit, ast_channel_name(chan), why, duration);
}
/*!
* \internal
* \brief Setup bridge builtin features.

@ -24,12 +24,13 @@
*/
#include "asterisk.h"
#include "asterisk/logger.h"
#include "res_parking.h"
#include "asterisk/astobj2.h"
#include "asterisk/features.h"
#include "asterisk/logger.h"
#include "asterisk/say.h"
#include "asterisk/term.h"
#include "asterisk/features.h"
#include "asterisk/bridging_internal.h"
struct ast_bridge_parking
{
@ -447,11 +448,11 @@ struct ast_bridge *bridge_parking_new(struct parking_lot *bridge_lot)
{
void *bridge;
bridge = ast_bridge_alloc(sizeof(struct ast_bridge_parking), &ast_bridge_parking_v_table);
bridge = ast_bridge_base_init(bridge, AST_BRIDGE_CAPABILITY_HOLDING,
bridge = bridge_alloc(sizeof(struct ast_bridge_parking), &ast_bridge_parking_v_table);
bridge = bridge_base_init(bridge, AST_BRIDGE_CAPABILITY_HOLDING,
AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
| AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM);
bridge = ast_bridge_parking_init(bridge, bridge_lot);
bridge = ast_bridge_register(bridge);
bridge = bridge_register(bridge);
return bridge;
}

@ -33,6 +33,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/logger.h"
#include "asterisk/pbx.h"
#include "asterisk/bridging.h"
#include "asterisk/bridging_internal.h"
#include "asterisk/bridging_channel_internal.h"
#include "asterisk/bridging_channel.h"
#include "asterisk/bridging_features.h"
#include "asterisk/features.h"
#include "asterisk/say.h"

Loading…
Cancel
Save