diff options
author | Richard Mudgett <rmudgett@digium.com> | 2013-05-21 18:00:22 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2013-05-21 18:00:22 +0000 |
commit | 3d63833bd6c869b7efa383e8dea14be1a6eff998 (patch) | |
tree | 34957dd051b8f67c7cc58a510e24ee3873a61ad4 /include/asterisk/bridging.h | |
parent | e1e1cc2deefb92f8b43825f1f34e619354737842 (diff) |
Merge in the bridge_construction branch to make the system use the Bridging API.
Breaks many things until they can be reworked. A partial list:
chan_agent
chan_dahdi, chan_misdn, chan_iax2 native bridging
app_queue
COLP updates
DTMF attended transfers
Protocol attended transfers
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@389378 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'include/asterisk/bridging.h')
-rw-r--r-- | include/asterisk/bridging.h | 1242 |
1 files changed, 1107 insertions, 135 deletions
diff --git a/include/asterisk/bridging.h b/include/asterisk/bridging.h index 2890b1dfa..77fb54e8d 100644 --- a/include/asterisk/bridging.h +++ b/include/asterisk/bridging.h @@ -1,8 +1,9 @@ /* * Asterisk -- An open source telephony toolkit. * - * Copyright (C) 2007 - 2009, Digium, Inc. + * Copyright (C) 2007 - 2009, 2013 Digium, Inc. * + * Richard Mudgett <rmudgett@digium.com> * Joshua Colp <jcolp@digium.com> * * See http://www.asterisk.org for more information about @@ -16,10 +17,16 @@ * at the top of the source tree. */ -/*! \file +/*! + * \file * \brief Channel Bridging API + * + * \author Richard Mudgett <rmudgett@digium.com> * \author Joshua Colp <jcolp@digium.com> * \ref AstBridging + * + * See Also: + * \arg \ref AstCREDITS */ /*! @@ -63,54 +70,41 @@ extern "C" { #endif #include "asterisk/bridging_features.h" +#include "asterisk/bridging_roles.h" #include "asterisk/dsp.h" +#include "asterisk/uuid.h" /*! \brief Capabilities for a bridge technology */ enum ast_bridge_capability { - /*! Bridge is only capable of mixing 2 channels */ - AST_BRIDGE_CAPABILITY_1TO1MIX = (1 << 1), - /*! Bridge is capable of mixing 2 or more channels */ - AST_BRIDGE_CAPABILITY_MULTIMIX = (1 << 2), - /*! Bridge should natively bridge two channels if possible */ - AST_BRIDGE_CAPABILITY_NATIVE = (1 << 3), - /*! Bridge should run using the multithreaded model */ - AST_BRIDGE_CAPABILITY_MULTITHREADED = (1 << 4), - /*! Bridge should run a central bridge thread */ - AST_BRIDGE_CAPABILITY_THREAD = (1 << 5), - /*! Bridge technology can do video mixing (or something along those lines) */ - AST_BRIDGE_CAPABILITY_VIDEO = (1 << 6), - /*! Bridge technology can optimize things based on who is talking */ - AST_BRIDGE_CAPABILITY_OPTIMIZE = (1 << 7), + /*! Bridge technology can service calls on hold. */ + AST_BRIDGE_CAPABILITY_HOLDING = (1 << 0), + /*! Bridge waits for channel to answer. Passes early media. (XXX Not supported yet) */ + AST_BRIDGE_CAPABILITY_EARLY = (1 << 1), + /*! Bridge is capable of natively bridging two channels. (Smart bridge only) */ + AST_BRIDGE_CAPABILITY_NATIVE = (1 << 2), + /*! Bridge is capable of mixing at most two channels. (Smart bridgeable) */ + AST_BRIDGE_CAPABILITY_1TO1MIX = (1 << 3), + /*! Bridge is capable of mixing an arbitrary number of channels. (Smart bridgeable) */ + 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 has ended itself (it has hung up) */ + /*! 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, - /*! Bridged channel was ast_bridge_depart() from the bridge without being hung up */ - AST_BRIDGE_CHANNEL_STATE_DEPART, - /*! Bridged channel is executing a feature hook */ - AST_BRIDGE_CHANNEL_STATE_FEATURE, - /*! Bridged channel is sending a DTMF stream out */ - AST_BRIDGE_CHANNEL_STATE_DTMF, - /*! Bridged channel began talking */ - AST_BRIDGE_CHANNEL_STATE_START_TALKING, - /*! Bridged channel has stopped talking */ - AST_BRIDGE_CHANNEL_STATE_STOP_TALKING, }; -/*! \brief Return values for bridge technology write function */ -enum ast_bridge_write_result { - /*! Bridge technology wrote out frame fine */ - AST_BRIDGE_WRITE_SUCCESS = 0, - /*! Bridge technology attempted to write out the frame but failed */ - AST_BRIDGE_WRITE_FAILED, - /*! Bridge technology does not support writing out a frame of this type */ - AST_BRIDGE_WRITE_UNSUPPORTED, +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; @@ -136,6 +130,7 @@ 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 */ @@ -144,29 +139,103 @@ struct ast_bridge_channel { struct ast_channel *chan; /*! Asterisk channel we are swapping with (if swapping) */ struct ast_channel *swap; - /*! Bridge this channel is participating in */ + /*! + * \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; - /*! Private information unique to the bridge technology */ + /*! + * \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; - /*! Thread handling the bridged channel */ + /*! + * \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; - /*! Additional file descriptors to look at */ - int fds[4]; - /*! Bit to indicate whether the channel is suspended from the bridge or not */ + /* 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; - /*! Bit to indicate if a imparted channel is allowed to get hungup after leaving the bridge by the bridging core. */ - unsigned int allow_impart_hangup: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; - /*! Queue of DTMF digits used for DTMF streaming */ - char dtmf_stream_q[8]; + /*! 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 get parked. */ + AST_BRIDGE_ACTION_PARK, + /*! Bridge channel is to run the indicated application. */ + AST_BRIDGE_ACTION_RUN_APP, + /*! Bridge channel is to execute a blind transfer. */ + AST_BRIDGE_ACTION_BLIND_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, }; enum ast_bridge_video_mode_type { @@ -207,13 +276,151 @@ struct ast_bridge_video_mode { }; /*! + * \brief Destroy the bridge. + * + * \param self Bridge to operate upon. + * + * \return Nothing + */ +typedef void (*ast_bridge_destructor_fn)(struct ast_bridge *self); + +/*! + * \brief The bridge is being dissolved. + * + * \param self Bridge to operate upon. + * + * \details + * The bridge is being dissolved. Remove any external + * references to the bridge so it can be destroyed. + * + * \note On entry, self must NOT be locked. + * + * \return Nothing + */ +typedef void (*ast_bridge_dissolving_fn)(struct ast_bridge *self); + +/*! + * \brief Push this channel into the bridge. + * + * \param self Bridge to operate upon. + * \param bridge_channel Bridge channel to push. + * \param swap Bridge channel to swap places with if not NULL. + * + * \details + * Setup any channel hooks controlled by the bridge. Allocate + * bridge_channel->bridge_pvt and initialize any resources put + * in bridge_channel->bridge_pvt if needed. If there is a swap + * channel, use it as a guide to setting up the bridge_channel. + * + * \note On entry, self is already locked. + * + * \retval 0 on success. + * \retval -1 on failure. The channel did not get pushed. + */ +typedef int (*ast_bridge_push_channel_fn)(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap); + +/*! + * \brief Pull this channel from the bridge. + * + * \param self Bridge to operate upon. + * \param bridge_channel Bridge channel to pull. + * + * \details + * Remove any channel hooks controlled by the bridge. Release + * any resources held by bridge_channel->bridge_pvt and release + * bridge_channel->bridge_pvt. + * + * \note On entry, self is already locked. + * + * \return Nothing + */ +typedef void (*ast_bridge_pull_channel_fn)(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel); + +/*! + * \brief Notify the bridge that this channel was just masqueraded. + * + * \param self Bridge to operate upon. + * \param bridge_channel Bridge channel that was masqueraded. + * + * \details + * A masquerade just happened to this channel. The bridge needs + * to re-evaluate this a channel in the bridge. + * + * \note On entry, self is already locked. + * + * \return Nothing + */ +typedef void (*ast_bridge_notify_masquerade_fn)(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel); + +/*! + * \brief Get the merge priority of this bridge. + * + * \param self Bridge to operate upon. + * + * \note On entry, self is already locked. + * + * \return Merge priority + */ +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. + */ +struct ast_bridge_methods { + /*! Bridge class name for log messages. */ + const char *name; + /*! Destroy the bridge. */ + ast_bridge_destructor_fn destroy; + /*! The bridge is being dissolved. Remove any references to the bridge. */ + ast_bridge_dissolving_fn dissolving; + /*! Push the bridge channel into the bridge. */ + ast_bridge_push_channel_fn push; + /*! Pull the bridge channel from the bridge. */ + ast_bridge_pull_channel_fn pull; + /*! Notify the bridge of a masquerade with the channel. */ + ast_bridge_notify_masquerade_fn notify_masquerade; + /*! Get the bridge merge priority. */ + ast_bridge_merge_priority_fn get_merge_priority; +}; + +/*! * \brief Structure that contains information about a bridge */ struct ast_bridge { - /*! Number of channels participating in the bridge */ - int num; + /*! Bridge virtual method table. */ + const struct ast_bridge_methods *v_table; + /*! Immutable bridge UUID. */ + char uniqueid[AST_UUID_STR_LEN]; + /*! Bridge technology that is handling the bridge */ + struct ast_bridge_technology *technology; + /*! Private information unique to the bridge technology */ + void *tech_pvt; + /*! Call ID associated with the bridge */ + struct ast_callid *callid; + /*! Linked list of channels participating in the bridge */ + AST_LIST_HEAD_NOLOCK(, ast_bridge_channel) channels; + /*! Queue of actions to perform on the bridge. */ + AST_LIST_HEAD_NOLOCK(, ast_frame) action_queue; /*! The video mode this bridge is using */ struct ast_bridge_video_mode video_mode; + /*! Bridge flags to tweak behavior */ + struct ast_flags feature_flags; + /*! Allowed bridge technology capabilities when AST_BRIDGE_FLAG_SMART enabled. */ + uint32_t allowed_capabilities; + /*! Number of channels participating in the bridge */ + unsigned int num_channels; + /*! Number of active channels in the bridge. */ + unsigned int num_active; + /*! + * \brief Count of the active temporary requests to inhibit bridge merges. + * Zero if merges are allowed. + * + * \note Temporary as in try again in a moment. + */ + unsigned int inhibit_merge; /*! The internal sample rate this bridge is mixed at when multiple channels are being mixed. * If this value is 0, the bridge technology may auto adjust the internal mixing rate. */ unsigned int internal_sample_rate; @@ -221,36 +428,83 @@ struct ast_bridge { * for bridge technologies that mix audio. When set to 0, the bridge tech must choose a * default interval for itself. */ unsigned int internal_mixing_interval; - /*! Bit to indicate that the bridge thread is waiting on channels in the bridge array */ - unsigned int waiting:1; - /*! Bit to indicate the bridge thread should stop */ - unsigned int stop:1; - /*! Bit to indicate the bridge thread should refresh itself */ - unsigned int refresh:1; - /*! Bridge flags to tweak behavior */ - struct ast_flags feature_flags; - /*! Bridge technology that is handling the bridge */ - struct ast_bridge_technology *technology; - /*! Private information unique to the bridge technology */ - void *bridge_pvt; - /*! Thread running the bridge */ - pthread_t thread; - /*! Enabled features information */ - struct ast_bridge_features features; - /*! Array of channels that the bridge thread is currently handling */ - struct ast_channel **array; - /*! Number of channels in the above array */ - size_t array_num; - /*! Number of channels the array can handle */ - size_t array_size; - /*! Call ID associated with the bridge */ - struct ast_callid *callid; - /*! Linked list of channels participating in the bridge */ - AST_LIST_HEAD_NOLOCK(, ast_bridge_channel) channels; - }; + /*! TRUE if the bridge was reconfigured. */ + unsigned int reconfigured:1; + /*! TRUE if the bridge has been dissolved. Any channel that now tries to join is immediately ejected. */ + unsigned int dissolved:1; +}; + +/*! + * \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 Create a new bridge + * \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 * * \param capabilities The capabilities that we require to be used on the bridge * \param flags Flags that will alter the behavior of the bridge @@ -262,13 +516,27 @@ struct ast_bridge { * * \code * struct ast_bridge *bridge; - * bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_FLAG_DISSOLVE); + * bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_FLAG_DISSOLVE_HANGUP); * \endcode * - * This creates a simple two party bridge that will be destroyed once one of - * the channels hangs up. + * This creates a no frills two party bridge that will be + * destroyed once one of the channels hangs up. */ -struct ast_bridge *ast_bridge_new(uint32_t capabilities, int flags); +struct ast_bridge *ast_bridge_base_new(uint32_t capabilities, unsigned int flags); + +/*! + * \brief Try locking the bridge. + * + * \param bridge Bridge to try locking + * + * \retval 0 on success. + * \retval non-zero on error. + */ +#define ast_bridge_trylock(bridge) _ast_bridge_trylock(bridge, __FILE__, __PRETTY_FUNCTION__, __LINE__, #bridge) +static inline int _ast_bridge_trylock(struct ast_bridge *bridge, const char *file, const char *function, int line, const char *var) +{ + return __ao2_trylock(bridge, AO2_LOCK_REQ_MUTEX, file, function, line, var); +} /*! * \brief Lock the bridge. @@ -296,24 +564,18 @@ static inline void _ast_bridge_unlock(struct ast_bridge *bridge, const char *fil __ao2_unlock(bridge, file, function, line, var); } -/*! - * \brief See if it is possible to create a bridge - * - * \param capabilities The capabilities that the bridge will use - * - * \retval 1 if possible - * \retval 0 if not possible - * - * Example usage: - * - * \code - * int possible = ast_bridge_check(AST_BRIDGE_CAPABILITY_1TO1MIX); - * \endcode - * - * This sees if it is possible to create a bridge capable of bridging two channels - * together. - */ -int ast_bridge_check(uint32_t capabilities); +/*! \brief Lock two bridges. */ +#define ast_bridge_lock_both(bridge1, bridge2) \ + do { \ + for (;;) { \ + ast_bridge_lock(bridge1); \ + if (!ast_bridge_trylock(bridge2)) { \ + break; \ + } \ + ast_bridge_unlock(bridge1); \ + sched_yield(); \ + } \ + } while (0) /*! * \brief Destroy a bridge @@ -329,11 +591,21 @@ int ast_bridge_check(uint32_t capabilities); * ast_bridge_destroy(bridge); * \endcode * - * This destroys a bridge that was previously created using ast_bridge_new. + * This destroys a bridge that was previously created. */ int ast_bridge_destroy(struct ast_bridge *bridge); /*! + * \brief Notify bridging that this channel was just masqueraded. + * \since 12.0.0 + * + * \param chan Channel just involved in a masquerade + * + * \return Nothing + */ +void ast_bridge_notify_masquerade(struct ast_channel *chan); + +/*! * \brief Join (blocking) a channel to a bridge * * \param bridge Bridge to join @@ -341,13 +613,17 @@ int ast_bridge_destroy(struct ast_bridge *bridge); * \param swap Channel to swap out if swapping * \param features Bridge features structure * \param tech_args Optional Bridging tech optimization parameters for this channel. + * \param pass_reference TRUE if the bridge reference is being passed by the caller. + * + * \note Absolutely _NO_ locks should be held before calling + * this function since it blocks. * * \retval state that channel exited the bridge with * * Example usage: * * \code - * ast_bridge_join(bridge, chan, NULL, NULL); + * ast_bridge_join(bridge, chan, NULL, NULL, NULL, 0); * \endcode * * This adds a channel pointed to by the chan pointer to the bridge pointed to by @@ -365,16 +641,23 @@ enum ast_bridge_channel_state ast_bridge_join(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, - struct ast_bridge_tech_optimizations *tech_args); + struct ast_bridge_tech_optimizations *tech_args, + int pass_reference); /*! * \brief Impart (non-blocking) a channel onto a bridge * * \param bridge Bridge to impart on * \param chan Channel to impart - * \param swap Channel to swap out if swapping - * \param features Bridge features structure - * \param allow_hangup Indicates if the bridge thread should manage hanging up of the channel or not. + * \param swap Channel to swap out if swapping. NULL if not swapping. + * \param features Bridge features structure. + * \param independent TRUE if caller does not want to reclaim the channel using ast_bridge_depart(). + * + * \note The features parameter must be NULL or obtained by + * ast_bridge_features_new(). You must not dereference features + * after calling even if the call fails. + * + * \note chan is locked by this function. * * \retval 0 on success * \retval -1 on failure @@ -385,42 +668,60 @@ enum ast_bridge_channel_state ast_bridge_join(struct ast_bridge *bridge, * ast_bridge_impart(bridge, chan, NULL, NULL, 0); * \endcode * - * This adds a channel pointed to by the chan pointer to the bridge pointed to by - * the bridge pointer. This function will return immediately and will not wait - * until the channel is no longer part of the bridge. - * - * If this channel will be replacing another channel the other channel can be specified - * in the swap parameter. The other channel will be thrown out of the bridge in an - * atomic fashion. - * - * If channel specific features are enabled a pointer to the features structure - * can be specified in the features parameter. + * \details + * This adds a channel pointed to by the chan pointer to the + * bridge pointed to by the bridge pointer. This function will + * return immediately and will not wait until the channel is no + * longer part of the bridge. + * + * If this channel will be replacing another channel the other + * channel can be specified in the swap parameter. The other + * channel will be thrown out of the bridge in an atomic + * fashion. + * + * If channel specific features are enabled, a pointer to the + * features structure can be specified in the features + * parameter. + * + * \note If you impart a channel as not independent you MUST + * ast_bridge_depart() the channel if this call succeeds. The + * bridge channel thread is created join-able. The implication + * is that the channel is special and will not behave like a + * normal channel. + * + * \note If you impart a channel as independent you must not + * ast_bridge_depart() the channel. The bridge channel thread + * is created non-join-able. The channel must be treated as if + * it were placed into the bridge by ast_bridge_join(). + * Channels placed into a bridge by ast_bridge_join() are + * removed by a third party using ast_bridge_remove(). */ -int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, int allow_hangup); +int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, int independent); /*! * \brief Depart a channel from a bridge * - * \param bridge Bridge to depart from * \param chan Channel to depart * + * \note chan is locked by this function. + * * \retval 0 on success * \retval -1 on failure * * Example usage: * * \code - * ast_bridge_depart(bridge, chan); + * ast_bridge_depart(chan); * \endcode * - * This removes the channel pointed to by the chan pointer from the bridge - * pointed to by the bridge pointer and gives control to the calling thread. + * This removes the channel pointed to by the chan pointer from any bridge + * it may be in and gives control to the calling thread. * This does not hang up the channel. * * \note This API call can only be used on channels that were added to the bridge - * using the ast_bridge_impart API call. + * using the ast_bridge_impart API call with the independent flag FALSE. */ -int ast_bridge_depart(struct ast_bridge *bridge, struct ast_channel *chan); +int ast_bridge_depart(struct ast_channel *chan); /*! * \brief Remove a channel from a bridge @@ -449,8 +750,14 @@ int ast_bridge_remove(struct ast_bridge *bridge, struct ast_channel *chan); /*! * \brief Merge two bridges together * - * \param bridge0 First bridge - * \param bridge1 Second bridge + * \param dst_bridge Destination bridge of merge. + * \param src_bridge Source bridge of merge. + * \param merge_best_direction TRUE if don't care about which bridge merges into the other. + * \param kick_me Array of channels to kick from the bridges. + * \param num_kick Number of channels in the kick_me array. + * + * \note Absolutely _NO_ bridge or channel locks should be held + * before calling this function. * * \retval 0 on success * \retval -1 on failure @@ -458,16 +765,57 @@ int ast_bridge_remove(struct ast_bridge *bridge, struct ast_channel *chan); * Example usage: * * \code - * ast_bridge_merge(bridge0, bridge1); + * ast_bridge_merge(dst_bridge, src_bridge, 0, NULL, 0); * \endcode * - * This merges the bridge pointed to by bridge1 with the bridge pointed to by bridge0. - * In reality all of the channels in bridge1 are simply moved to bridge0. + * This moves the channels in src_bridge into the bridge pointed + * to by dst_bridge. + */ +int ast_bridge_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, int merge_best_direction, struct ast_channel **kick_me, unsigned int num_kick); + +/*! + * \brief Move a channel from one bridge to another. + * \since 12.0.0 + * + * \param dst_bridge Destination bridge of bridge channel move. + * \param src_bridge Source bridge of bridge channel move. + * \param chan Channel to move. + * \param swap Channel to replace in dst_bridge. + * \param attempt_recovery TRUE if failure attempts to push channel back into original bridge. + * + * \note Absolutely _NO_ bridge or channel locks should be held + * before calling this function. * - * \note The second bridge specified is not destroyed when this operation is - * completed. + * \retval 0 on success. + * \retval -1 on failure. */ -int ast_bridge_merge(struct ast_bridge *bridge0, struct ast_bridge *bridge1); +int ast_bridge_move(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, struct ast_channel *chan, struct ast_channel *swap, int attempt_recovery); + +/*! + * \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.) + * + * \return Nothing + */ +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 @@ -517,7 +865,94 @@ int ast_bridge_suspend(struct ast_bridge *bridge, struct ast_channel *chan); int ast_bridge_unsuspend(struct ast_bridge *bridge, struct ast_channel *chan); /*! - * \brief Change the state of a bridged channel + * \brief Check and optimize out the unreal channels between bridges. + * \since 12.0.0 + * + * \param chan Unreal channel writing a frame into the channel driver. + * \param peer Other unreal channel in the pair. + * + * \note It is assumed that chan is already locked. + * + * \retval 0 if unreal channels were not optimized out. + * \retval non-zero if unreal channels were optimized out. + */ +int ast_bridge_unreal_optimized_out(struct ast_channel *chan, struct ast_channel *peer); + +/*! + * \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 @@ -525,18 +960,266 @@ int ast_bridge_unsuspend(struct ast_bridge *bridge, struct ast_channel *chan); * Example usage: * * \code - * ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT); + * 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_WAIT. + * 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 in feature hook callbacks to - * make sure the channel either hangs up or returns to the bridge. + * \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 + * + * \param bridge What to queue the action on. + * \param action What to do. + * + * \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_queue_action(struct ast_bridge *bridge, struct ast_frame *action); + +/*! + * \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. + * + * \return Nothing + */ +typedef void (*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. + * + * \return Nothing + */ +void 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. + * + * \return Nothing + */ +void 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. + * + * \return Nothing + */ +void 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. + * + * \return Nothing + */ +void 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 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. + * + * \return Nothing + */ +void 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. + * + * \return Nothing + */ +void 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 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. + * + * \return Nothing + */ +void ast_bridge_channel_write_park(struct ast_bridge_channel *bridge_channel, const char *parkee_uuid, + const char *parker_uuid, const char *app_data); + +/*! + * \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. + * + * \return Nothing + */ +void 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. + * + * \return Nothing + */ +void 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 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. * @@ -594,8 +1277,297 @@ int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan) */ void ast_bridge_remove_video_src(struct ast_bridge *bridge, struct ast_channel *chan); +enum ast_transfer_result { + /*! The transfer completed successfully */ + AST_BRIDGE_TRANSFER_SUCCESS, + /*! A bridge involved does not permit transferring */ + AST_BRIDGE_TRANSFER_NOT_PERMITTED, + /*! The current bridge setup makes transferring an invalid operation */ + AST_BRIDGE_TRANSFER_INVALID, + /*! The transfer operation failed for a miscellaneous reason */ + AST_BRIDGE_TRANSFER_FAIL, +}; + +typedef void (*transfer_channel_cb)(struct ast_channel *chan, void *user_data); + +/*! + * \brief Blind transfer target to the extension and context provided + * + * The channel given is bridged to one or multiple channels. Depending on + * the bridge and the number of participants, the entire bridge could be + * transferred to the given destination, or a single channel may be redirected. + * + * Callers may also provide a callback to be called on the channel that will + * be running dialplan. The user data passed into ast_bridge_transfer_blind + * will be given as the argument to the callback to be interpreted as desired. + * This callback is guaranteed to be called in the same thread as + * ast_bridge_transfer_blind() and before ast_bridge_transfer_blind() returns. + * + * \note Absolutely _NO_ channel locks should be held before + * calling this function. + * + * \param transferer The channel performing the blind transfer + * \param exten The dialplan extension to send the call to + * \param context The dialplan context to send the call to + * \param new_channel_cb A callback to be called on the channel that will + * be executing dialplan + * \param user_data Argument for new_channel_cb + * \return The success or failure result of the blind transfer + */ +enum ast_transfer_result ast_bridge_transfer_blind(struct ast_channel *transferer, + const char *exten, const char *context, + transfer_channel_cb new_channel_cb, void *user_data); + +/*! + * \brief Attended transfer + * + * The two channels are both transferer channels. The first is the channel + * that is bridged to the transferee (or if unbridged, the 'first' call of + * the transfer). The second is the channel that is bridged to the transfer + * target (or if unbridged, the 'second' call of the transfer). + * + * Like with a blind transfer, a frame hook can be provided to monitor the + * resulting call after the transfer completes. If the transfer fails, the + * hook will not be attached to any call. + * + * \note Absolutely _NO_ channel locks should be held before + * calling this function. + * + * \param to_transferee Transferer channel on initial call (presumably bridged to transferee) + * \param to_transfer_target Transferer channel on consultation call (presumably bridged to transfer target) + * \param hook A frame hook to attach to the resultant call + * \return The success or failure of the attended transfer + */ +enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, + struct ast_channel *to_transfer_target, struct ast_framehook *hook); +/*! + * \brief Set channel to goto specific location after the bridge. + * \since 12.0.0 + * + * \param chan Channel to setup after bridge goto location. + * \param context Context to goto after bridge. + * \param exten Exten to goto after bridge. + * \param priority Priority to goto after bridge. + * + * \note chan is locked by this function. + * + * \details Add a channel datastore to setup the goto location + * when the channel leaves the bridge and run a PBX from there. + * + * \return Nothing + */ +void ast_after_bridge_set_goto(struct ast_channel *chan, const char *context, const char *exten, int priority); + +/*! + * \brief Set channel to run the h exten after the bridge. + * \since 12.0.0 + * + * \param chan Channel to setup after bridge goto location. + * \param context Context to goto after bridge. + * + * \note chan is locked by this function. + * + * \details Add a channel datastore to setup the goto location + * when the channel leaves the bridge and run a PBX from there. + * + * \return Nothing + */ +void ast_after_bridge_set_h(struct ast_channel *chan, const char *context); + +/*! + * \brief Set channel to go on in the dialplan after the bridge. + * \since 12.0.0 + * + * \param chan Channel to setup after bridge goto location. + * \param context Current context of the caller channel. + * \param exten Current exten of the caller channel. + * \param priority Current priority of the caller channel + * \param parseable_goto User specified goto string from dialplan. + * + * \note chan is locked by this function. + * + * \details Add a channel datastore to setup the goto location + * when the channel leaves the bridge and run a PBX from there. + * + * If parseable_goto then use the given context/exten/priority + * as the relative position for the parseable_goto. + * Else goto the given context/exten/priority+1. + * + * \return Nothing + */ +void ast_after_bridge_set_go_on(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *parseable_goto); + +/*! + * \brief Setup any after bridge goto location to begin execution. + * \since 12.0.0 + * + * \param chan Channel to setup after bridge goto location. + * + * \note chan is locked by this function. + * + * \details Pull off any after bridge goto location datastore and + * setup for dialplan execution there. + * + * \retval 0 on success. The goto location is set for a PBX to run it. + * \retval non-zero on error or no goto location. + * + * \note If the after bridge goto is set to run an h exten it is + * run here immediately. + */ +int ast_after_bridge_goto_setup(struct ast_channel *chan); + +/*! + * \brief Run a PBX on any after bridge goto location. + * \since 12.0.0 + * + * \param chan Channel to execute after bridge goto location. + * + * \note chan is locked by this function. + * + * \details Pull off any after bridge goto location datastore + * and run a PBX at that location. + * + * \note On return, the chan pointer is no longer valid because + * the channel has hung up. + * + * \return Nothing + */ +void ast_after_bridge_goto_run(struct ast_channel *chan); + +/*! + * \brief Discard channel after bridge goto location. + * \since 12.0.0 + * + * \param chan Channel to discard after bridge goto location. + * + * \note chan is locked by this function. + * + * \return Nothing + */ +void ast_after_bridge_goto_discard(struct ast_channel *chan); + +/*! Reason the the after bridge callback will not be called. */ +enum ast_after_bridge_cb_reason { + /*! The datastore is being destroyed. Likely due to hangup. */ + AST_AFTER_BRIDGE_CB_REASON_DESTROY, + /*! Something else replaced the callback with another. */ + AST_AFTER_BRIDGE_CB_REASON_REPLACED, + /*! The callback was removed because of a masquerade. (fixup) */ + AST_AFTER_BRIDGE_CB_REASON_MASQUERADE, + /*! The channel departed bridge. */ + AST_AFTER_BRIDGE_CB_REASON_DEPART, + /*! Was explicitly removed by external code. */ + AST_AFTER_BRIDGE_CB_REASON_REMOVED, +}; + +/*! + * \brief After bridge callback failed. + * \since 12.0.0 + * + * \param reason Reason callback is failing. + * \param data Extra data what setup the callback wanted to pass. + * + * \return Nothing + */ +typedef void (*ast_after_bridge_cb_failed)(enum ast_after_bridge_cb_reason reason, void *data); + +/*! + * \brief After bridge callback function. + * \since 12.0.0 + * + * \param chan Channel just leaving bridging system. + * \param data Extra data what setup the callback wanted to pass. + * + * \return Nothing + */ +typedef void (*ast_after_bridge_cb)(struct ast_channel *chan, void *data); + +/*! + * \brief Discard channel after bridge callback. + * \since 12.0.0 + * + * \param chan Channel to discard after bridge callback. + * \param reason Why are we doing this. + * + * \note chan is locked by this function. + * + * \return Nothing + */ +void ast_after_bridge_callback_discard(struct ast_channel *chan, enum ast_after_bridge_cb_reason reason); + +/*! + * \brief Setup an after bridge callback for when the channel leaves the bridging system. + * \since 12.0.0 + * + * \param chan Channel to setup an after bridge callback on. + * \param callback Function to call when the channel leaves the bridging system. + * \param failed Function to call when it will not be calling the callback. + * \param data Extra data to pass with the callback. + * + * \note chan is locked by this function. + * + * \retval 0 on success. + * \retval -1 on error. + */ +int ast_after_bridge_callback_set(struct ast_channel *chan, ast_after_bridge_cb callback, ast_after_bridge_cb_failed failed, void *data); + +/*! + * \brief Get a container of all channels in the bridge + * \since 12.0.0 + * + * \param bridge The bridge which is already locked. + * + * \retval NULL Failed to create container + * \retval non-NULL Container of channels in the bridge + */ +struct ao2_container *ast_bridge_peers_nolock(struct ast_bridge *bridge); + +/*! + * \brief Get a container of all channels in the bridge + * \since 12.0.0 + * + * \param bridge The bridge + * + * \note The returned container is a snapshot of channels in the + * bridge when called. + * + * \retval NULL Failed to create container + * \retval non-NULL Container of channels in the bridge + */ +struct ao2_container *ast_bridge_peers(struct ast_bridge *bridge); + +/*! + * \brief Get the channel's bridge peer only if the bridge is two-party. + * \since 12.0.0 + * + * \param bridge The bridge which is already locked. + * \param chan Channel desiring the bridge peer channel. + * + * \note The returned peer channel is the current peer in the + * bridge when called. + * + * \retval NULL Channel not in a bridge or the bridge is not two-party. + * \retval non-NULL Reffed peer channel at time of calling. + */ +struct ast_channel *ast_bridge_peer_nolock(struct ast_bridge *bridge, struct ast_channel *chan); + +/*! + * \brief Get the channel's bridge peer only if the bridge is two-party. + * \since 12.0.0 + * + * \param bridge The bridge + * \param chan Channel desiring the bridge peer channel. + * + * \note The returned peer channel is the current peer in the + * bridge when called. + * + * \retval NULL Channel not in a bridge or the bridge is not two-party. + * \retval non-NULL Reffed peer channel at time of calling. + */ +struct ast_channel *ast_bridge_peer(struct ast_bridge *bridge, struct ast_channel *chan); + #if defined(__cplusplus) || defined(c_plusplus) } #endif -#endif /* _ASTERISK_BRIDGING_H */ +#endif /* _ASTERISK_BRIDGING_H */ |