diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/asterisk/_private.h | 18 | ||||
-rw-r--r-- | include/asterisk/abstract_jb.h | 28 | ||||
-rw-r--r-- | include/asterisk/bridging.h | 1242 | ||||
-rw-r--r-- | include/asterisk/bridging_basic.h | 107 | ||||
-rw-r--r-- | include/asterisk/bridging_features.h | 476 | ||||
-rw-r--r-- | include/asterisk/bridging_roles.h | 135 | ||||
-rw-r--r-- | include/asterisk/bridging_technology.h | 116 | ||||
-rw-r--r-- | include/asterisk/ccss.h | 10 | ||||
-rw-r--r-- | include/asterisk/channel.h | 76 | ||||
-rw-r--r-- | include/asterisk/config_options.h | 10 | ||||
-rw-r--r-- | include/asterisk/core_local.h | 98 | ||||
-rw-r--r-- | include/asterisk/core_unreal.h | 191 | ||||
-rw-r--r-- | include/asterisk/frame.h | 2 | ||||
-rw-r--r-- | include/asterisk/framehook.h | 2 | ||||
-rw-r--r-- | include/asterisk/manager.h | 57 | ||||
-rw-r--r-- | include/asterisk/parking.h | 184 | ||||
-rw-r--r-- | include/asterisk/rtp_engine.h | 28 | ||||
-rw-r--r-- | include/asterisk/stasis_bridging.h | 238 |
18 files changed, 2747 insertions, 271 deletions
diff --git a/include/asterisk/_private.h b/include/asterisk/_private.h index 7e1ef13ec..3fe35e58c 100644 --- a/include/asterisk/_private.h +++ b/include/asterisk/_private.h @@ -52,6 +52,24 @@ void ast_msg_shutdown(void); /*!< Provided by message.c */ int aco_init(void); /*!< Provided by config_options.c */ /*! + * \brief Initialize the bridging system. + * \since 12.0.0 + * + * \retval 0 on success. + * \retval -1 on error. + */ +int ast_bridging_init(void); + +/*! + * \brief Initialize the local proxy channel. + * \since 12.0.0 + * + * \retval 0 on success. + * \retval -1 on error. + */ +int ast_local_init(void); + +/*! * \brief Reload asterisk modules. * \param name the name of the module to reload * diff --git a/include/asterisk/abstract_jb.h b/include/asterisk/abstract_jb.h index 3e6bedd26..6a4d0610d 100644 --- a/include/asterisk/abstract_jb.h +++ b/include/asterisk/abstract_jb.h @@ -246,6 +246,14 @@ void ast_jb_destroy(struct ast_channel *chan); */ int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value); +/*! + * \since 12.0 + * \brief Sets a jitterbuffer frame hook on the channel based on the channel's stored + * jitterbuffer configuration + * + * \param chan Which channel is being set up + */ +void ast_jb_enable_for_channel(struct ast_channel *chan); /*! * \brief Configures a jitterbuffer on a channel. @@ -257,7 +265,6 @@ int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char * */ void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf); - /*! * \brief Copies a channel's jitterbuffer configuration. * \param chan channel. @@ -274,6 +281,25 @@ void ast_jb_empty_and_reset(struct ast_channel *c0, struct ast_channel *c1); const struct ast_jb_impl *ast_jb_get_impl(enum ast_jb_type type); +/*! + * \since 12 + * \brief Sets the contents of an ast_jb_conf struct to the default jitterbuffer settings + * + * \param conf Which jitterbuffer is being set + */ +void ast_jb_conf_default(struct ast_jb_conf *conf); + +/*! + * \since 12 + * \brief Applies a jitterbuffer framehook to a channel based on a provided jitterbuffer config + * + * \param chan Which channel the jitterbuffer is being set on + * \param jb_conf Configuration to use for the jitterbuffer + * \param prefer_existing If this is true and a jitterbuffer already exists for the channel, + * use the existing jitterbuffer + */ +void ast_jb_create_framehook(struct ast_channel *chan, struct ast_jb_conf *jb_conf, int prefer_existing); + #if defined(__cplusplus) || defined(c_plusplus) } #endif 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 */ diff --git a/include/asterisk/bridging_basic.h b/include/asterisk/bridging_basic.h new file mode 100644 index 000000000..cc42354dc --- /dev/null +++ b/include/asterisk/bridging_basic.h @@ -0,0 +1,107 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2013 Digium, Inc. + * + * Richard Mudgett <rmudgett@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 Basic bridge subclass API. + * + * \author Richard Mudgett <rmudgett@digium.com> + * + * See Also: + * \arg \ref AstCREDITS + */ + +#ifndef _ASTERISK_BRIDGING_BASIC_H +#define _ASTERISK_BRIDGING_BASIC_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +/* ------------------------------------------------------------------- */ + +/*! + * \brief Get DTMF feature flags from the channel. + * \since 12.0.0 + * + * \param chan Channel to get DTMF features datastore. + * + * \note The channel should be locked before calling this function. + * + * \retval flags on success. + * \retval NULL on error. + */ +struct ast_flags *ast_bridge_features_ds_get(struct ast_channel *chan); + +/*! + * \brief Set basic bridge DTMF feature flags datastore on the channel. + * \since 12.0.0 + * + * \param chan Channel to set DTMF features datastore. + * \param flags Builtin DTMF feature flags. (ast_bridge_config flags) + * + * \note The channel must be locked before calling this function. + * + * \retval 0 on success. + * \retval -1 on error. + */ +int ast_bridge_features_ds_set(struct ast_channel *chan, struct ast_flags *flags); + +/*! + * \brief Setup DTMF feature hooks using the channel features datastore property. + * \since 12.0.0 + * + * \param bridge_channel What to setup DTMF features on. + * + * \retval 0 on success. + * \retval -1 on error. + */ +int ast_bridge_channel_setup_features(struct ast_bridge_channel *bridge_channel); + +/*! \brief Bridge basic class virtual method table. */ +extern struct ast_bridge_methods ast_bridge_basic_v_table; + +/*! + * \brief Create a new basic class bridge + * + * \retval a pointer to a new bridge on success + * \retval NULL on failure + * + * Example usage: + * + * \code + * struct ast_bridge *bridge; + * bridge = ast_bridge_basic_new(); + * \endcode + * + * This creates a basic two party bridge with any configured + * DTMF features enabled that will be destroyed once one of the + * channels hangs up. + */ +struct ast_bridge *ast_bridge_basic_new(void); + +/*! Initialize the basic bridge class for use by the system. */ +void ast_bridging_init_basic(void); + +/* ------------------------------------------------------------------- */ + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* _ASTERISK_BRIDGING_BASIC_H */ diff --git a/include/asterisk/bridging_features.h b/include/asterisk/bridging_features.h index 1323a6da9..bb792a815 100644 --- a/include/asterisk/bridging_features.h +++ b/include/asterisk/bridging_features.h @@ -30,10 +30,36 @@ extern "C" { /*! \brief Flags used for bridge features */ enum ast_bridge_feature_flags { - /*! Upon hangup the bridge should be discontinued */ - AST_BRIDGE_FLAG_DISSOLVE = (1 << 0), + /*! Upon channel hangup all bridge participants should be kicked out. */ + AST_BRIDGE_FLAG_DISSOLVE_HANGUP = (1 << 0), + /*! The last channel to leave the bridge dissolves it. */ + AST_BRIDGE_FLAG_DISSOLVE_EMPTY = (1 << 1), /*! Move between bridging technologies as needed. */ - AST_BRIDGE_FLAG_SMART = (1 << 1), + AST_BRIDGE_FLAG_SMART = (1 << 2), + /*! Bridge channels cannot be merged from this bridge. */ + AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM = (1 << 3), + /*! Bridge channels cannot be merged to this bridge. */ + AST_BRIDGE_FLAG_MERGE_INHIBIT_TO = (1 << 4), + /*! Bridge channels cannot be local channel swap optimized from this bridge. */ + AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM = (1 << 5), + /*! Bridge channels cannot be local channel swap optimized to this bridge. */ + AST_BRIDGE_FLAG_SWAP_INHIBIT_TO = (1 << 6), + /*! Bridge channels can be moved to another bridge only by masquerade (ConfBridge) */ + AST_BRIDGE_FLAG_MASQUERADE_ONLY = (1 << 7), + /*! Bridge does not allow transfers of channels out */ + AST_BRIDGE_FLAG_TRANSFER_PROHIBITED = (1 << 6), + /*! Bridge transfers require transfer of entire bridge rather than individual channels */ + AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY = (1 << 7), +}; + +/*! \brief Flags used for per bridge channel features */ +enum ast_bridge_channel_feature_flags { + /*! Upon channel hangup all bridge participants should be kicked out. */ + AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP = (1 << 0), + /*! This channel leaves the bridge if all participants have this flag set. */ + AST_BRIDGE_CHANNEL_FLAG_LONELY = (1 << 1), + /*! This channel cannot be moved to another bridge. */ + AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE = (1 << 2), }; /*! \brief Built in DTMF features */ @@ -52,32 +78,66 @@ enum ast_bridge_builtin_feature { * AST_BRIDGE_CHANNEL_STATE_END. */ AST_BRIDGE_BUILTIN_HANGUP, + /*! + * DTMF based Park + * + * \details The bridge is parked and the channel hears the + * parking slot to which it was parked. + */ + AST_BRIDGE_BUILTIN_PARKCALL, +/* BUGBUG does Monitor and/or MixMonitor require a two party bridge? MixMonitor is used by ConfBridge so maybe it doesn't. */ + /*! + * DTMF one-touch-record toggle using Monitor app. + * + * \note Only valid on two party bridges. + */ + AST_BRIDGE_BUILTIN_AUTOMON, + /*! + * DTMF one-touch-record toggle using MixMonitor app. + * + * \note Only valid on two party bridges. + */ + AST_BRIDGE_BUILTIN_AUTOMIXMON, /*! End terminator for list of built in features. Must remain last. */ AST_BRIDGE_BUILTIN_END }; +enum ast_bridge_builtin_interval { + /*! Apply Call Duration Limits */ + AST_BRIDGE_BUILTIN_INTERVAL_LIMITS, + + /*! End terminator for list of built in interval features. Must remain last. */ + AST_BRIDGE_BUILTIN_INTERVAL_END +}; + struct ast_bridge; struct ast_bridge_channel; /*! - * \brief Features hook callback type + * \brief Hook callback type * * \param bridge The bridge that the channel is part of * \param bridge_channel Channel executing the feature * \param hook_pvt Private data passed in when the hook was created * - * \retval 0 success - * \retval -1 failure + * For interval hooks: + * \retval 0 Setup to fire again at the last interval. + * \retval positive Setup to fire again at the new interval returned. + * \retval -1 Remove the callback hook. + * + * For other hooks: + * \retval 0 Keep the callback hook. + * \retval -1 Remove the callback hook. */ -typedef int (*ast_bridge_features_hook_callback)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt); +typedef int (*ast_bridge_hook_callback)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt); /*! - * \brief Features hook pvt destructor callback + * \brief Hook pvt destructor callback * - * \param hook_pvt Private data passed in when the hook was create to destroy + * \param hook_pvt Private data passed in when the hook was created to destroy */ -typedef void (*ast_bridge_features_hook_pvt_destructor)(void *hook_pvt); +typedef void (*ast_bridge_hook_pvt_destructor)(void *hook_pvt); /*! * \brief Talking indicator callback @@ -86,13 +146,13 @@ typedef void (*ast_bridge_features_hook_pvt_destructor)(void *hook_pvt); * to receive updates on when a bridge_channel has started and stopped * talking * - * \param bridge The bridge that the channel is part of * \param bridge_channel Channel executing the feature + * \param talking TRUE if the channel is now talking * * \retval 0 success * \retval -1 failure */ -typedef void (*ast_bridge_talking_indicate_callback)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *pvt_data); +typedef void (*ast_bridge_talking_indicate_callback)(struct ast_bridge_channel *bridge_channel, void *pvt_data, int talking); typedef void (*ast_bridge_talking_indicate_destructor)(void *pvt_data); @@ -100,30 +160,68 @@ typedef void (*ast_bridge_talking_indicate_destructor)(void *pvt_data); /*! * \brief Maximum length of a DTMF feature string */ -#define MAXIMUM_DTMF_FEATURE_STRING 8 +#define MAXIMUM_DTMF_FEATURE_STRING (11 + 1) -/*! - * \brief Structure that is the essence of a features hook - */ -struct ast_bridge_features_hook { +/*! Extra parameters for a DTMF feature hook. */ +struct ast_bridge_hook_dtmf { /*! DTMF String that is examined during a feature hook lookup */ - char dtmf[MAXIMUM_DTMF_FEATURE_STRING]; - /*! Callback that is called when DTMF string is matched */ - ast_bridge_features_hook_callback callback; + char code[MAXIMUM_DTMF_FEATURE_STRING]; +}; + +/*! Extra parameters for an interval timer hook. */ +struct ast_bridge_hook_timer { + /*! Time at which the hook should actually trip */ + struct timeval trip_time; + /*! Heap index for interval hook */ + ssize_t heap_index; + /*! Interval that the hook should execute at in milliseconds */ + unsigned int interval; + /*! Sequence number for the hook to ensure expiration ordering */ + unsigned int seqno; +}; + +/* BUGBUG Need to be able to selectively remove DTMF, hangup, and interval hooks. */ +/*! \brief Structure that is the essence of a feature hook. */ +struct ast_bridge_hook { + /*! Linked list information */ + AST_LIST_ENTRY(ast_bridge_hook) entry; + /*! Callback that is called when hook is tripped */ + ast_bridge_hook_callback callback; /*! Callback to destroy hook_pvt data right before destruction. */ - ast_bridge_features_hook_pvt_destructor destructor; + ast_bridge_hook_pvt_destructor destructor; /*! Unique data that was passed into us */ void *hook_pvt; - /*! Linked list information */ - AST_LIST_ENTRY(ast_bridge_features_hook) entry; + /*! TRUE if the hook is removed when the channel is pulled from the bridge. */ + unsigned int remove_on_pull:1; + /*! Extra hook parameters. */ + union { + /*! Extra parameters for a DTMF feature hook. */ + struct ast_bridge_hook_dtmf dtmf; + /*! Extra parameters for an interval timer hook. */ + struct ast_bridge_hook_timer timer; + } parms; }; +#define BRIDGE_FEATURES_INTERVAL_RATE 10 + /*! * \brief Structure that contains features information */ struct ast_bridge_features { - /*! Attached DTMF based feature hooks */ - AST_LIST_HEAD_NOLOCK(, ast_bridge_features_hook) hooks; + /*! Attached DTMF feature hooks */ + struct ao2_container *dtmf_hooks; + /*! Attached hangup interception hooks container */ + struct ao2_container *hangup_hooks; + /*! Attached bridge channel join interception hooks container */ + struct ao2_container *join_hooks; + /*! Attached bridge channel leave interception hooks container */ + struct ao2_container *leave_hooks; + /*! Attached interval hooks */ + struct ast_heap *interval_hooks; + /*! Used to determine when interval based features should be checked */ + struct ast_timer *interval_timer; + /*! Limits feature data */ + struct ast_bridge_features_limits *limits; /*! Callback to indicate when a bridge channel has started and stopped talking */ ast_bridge_talking_indicate_callback talker_cb; /*! Callback to destroy any pvt data stored for the talker. */ @@ -132,19 +230,21 @@ struct ast_bridge_features { void *talker_pvt_data; /*! Feature flags that are enabled */ struct ast_flags feature_flags; - /*! Bit to indicate that the feature_flags and hook list is setup */ + /*! Used to assign the sequence number to the next interval hook added. */ + unsigned int interval_sequence; + /*! TRUE if feature_flags is setup */ unsigned int usable:1; - /*! Bit to indicate whether the channel/bridge is muted or not */ + /*! TRUE if the channel/bridge is muted. */ unsigned int mute:1; - /*! Bit to indicate whether DTMF should be passed into the bridge tech or not. */ + /*! TRUE if DTMF should be passed into the bridge tech. */ unsigned int dtmf_passthrough:1; - }; /*! * \brief Structure that contains configuration information for the blind transfer built in feature */ struct ast_bridge_features_blind_transfer { +/* BUGBUG the context should be figured out based upon TRANSFER_CONTEXT channel variable of A/B or current context of A/B. More appropriate for when channel moved to other bridges. */ /*! Context to use for transfers */ char context[AST_MAX_CONTEXT]; }; @@ -153,14 +253,38 @@ struct ast_bridge_features_blind_transfer { * \brief Structure that contains configuration information for the attended transfer built in feature */ struct ast_bridge_features_attended_transfer { +/* BUGBUG the context should be figured out based upon TRANSFER_CONTEXT channel variable of A/B or current context of A/B. More appropriate for when channel moved to other bridges. */ + /*! Context to use for transfers */ + char context[AST_MAX_CONTEXT]; /*! DTMF string used to abort the transfer */ char abort[MAXIMUM_DTMF_FEATURE_STRING]; /*! DTMF string used to turn the transfer into a three way conference */ char threeway[MAXIMUM_DTMF_FEATURE_STRING]; /*! DTMF string used to complete the transfer */ char complete[MAXIMUM_DTMF_FEATURE_STRING]; - /*! Context to use for transfers */ - char context[AST_MAX_CONTEXT]; +}; + +/*! + * \brief Structure that contains configuration information for the limits feature + */ +struct ast_bridge_features_limits { + /*! Maximum duration that the channel is allowed to be in the bridge (specified in milliseconds) */ + unsigned int duration; + /*! Duration into the call when warnings should begin (specified in milliseconds or 0 to disable) */ + unsigned int warning; + /*! Interval between the warnings (specified in milliseconds or 0 to disable) */ + unsigned int frequency; + + AST_DECLARE_STRING_FIELDS( + /*! Sound file to play when the maximum duration is reached (if empty, then nothing will be played) */ + AST_STRING_FIELD(duration_sound); + /*! Sound file to play when the warning time is reached (if empty, then the remaining time will be played) */ + AST_STRING_FIELD(warning_sound); + /*! Sound file to play when the call is first entered (if empty, then the remaining time will be played) */ + AST_STRING_FIELD(connect_sound); + ); + /*! Time when the bridge will be terminated by the limits feature */ + struct timeval quitting_time; }; /*! @@ -182,7 +306,7 @@ struct ast_bridge_features_attended_transfer { * This registers the function bridge_builtin_attended_transfer as the function responsible for the built in * attended transfer feature. */ -int ast_bridge_features_register(enum ast_bridge_builtin_feature feature, ast_bridge_features_hook_callback callback, const char *dtmf); +int ast_bridge_features_register(enum ast_bridge_builtin_feature feature, ast_bridge_hook_callback callback, const char *dtmf); /*! * \brief Unregister a handler for a built in feature @@ -203,13 +327,154 @@ int ast_bridge_features_register(enum ast_bridge_builtin_feature feature, ast_br int ast_bridge_features_unregister(enum ast_bridge_builtin_feature feature); /*! - * \brief Attach a custom hook to a bridge features structure + * \brief Attach interval hooks to a bridge features structure + * + * \param features Bridge features structure + * \param limits Configured limits applicable to the channel + * \param remove_on_pull TRUE if remove the hook when the channel is pulled from the bridge. + * + * \retval 0 on success + * \retval -1 on failure + */ +typedef int (*ast_bridge_builtin_set_limits_fn)(struct ast_bridge_features *features, struct ast_bridge_features_limits *limits, int remove_on_pull); + +/*! + * \brief Register a handler for a built in interval feature + * + * \param interval The interval feature that the handler will be responsible for + * \param callback the Callback function that will handle it + * + * \retval 0 on success + * \retval -1 on failure + * + * Example usage: + * + * \code + * ast_bridge_interval_register(AST_BRIDGE_BUILTIN_INTERVAL_LIMITS, bridge_builtin_set_limits); + * \endcode + * + * This registers the function bridge_builtin_set_limits as the function responsible for the built in + * duration limit feature. + */ +int ast_bridge_interval_register(enum ast_bridge_builtin_interval interval, ast_bridge_builtin_set_limits_fn callback); + +/*! + * \brief Unregisters a handler for a built in interval feature + * + * \param interval the interval feature to unregister + * + * \retval 0 on success + * \retval -1 on failure + * + * Example usage: + * + * \code + * ast_bridge_interval_unregister(AST_BRIDGE_BULTIN_INTERVAL_LIMITS) + * /endcode + * + * This unregisters the function that is handling the built in duration limit feature. + */ +int ast_bridge_interval_unregister(enum ast_bridge_builtin_interval interval); + +/*! + * \brief Attach a bridge channel join hook to a bridge features structure + * + * \param features Bridge features structure + * \param callback Function to execute upon activation + * \param hook_pvt Unique data + * \param destructor Optional destructor callback for hook_pvt data + * \param remove_on_pull TRUE if remove the hook when the channel is pulled from the bridge. + * + * \retval 0 on success + * \retval -1 on failure + * + * Example usage: + * + * \code + * struct ast_bridge_features features; + * ast_bridge_features_init(&features); + * ast_bridge_join_hook(&features, join_callback, NULL, NULL, 0); + * \endcode + * + * This makes the bridging core call join_callback when a + * channel successfully joins the bridging system. A pointer to + * useful data may be provided to the hook_pvt parameter. + */ +int ast_bridge_join_hook(struct ast_bridge_features *features, + ast_bridge_hook_callback callback, + void *hook_pvt, + ast_bridge_hook_pvt_destructor destructor, + int remove_on_pull); + +/*! + * \brief Attach a bridge channel leave hook to a bridge features structure + * + * \param features Bridge features structure + * \param callback Function to execute upon activation + * \param hook_pvt Unique data + * \param destructor Optional destructor callback for hook_pvt data + * \param remove_on_pull TRUE if remove the hook when the channel is pulled from the bridge. + * + * \retval 0 on success + * \retval -1 on failure + * + * Example usage: + * + * \code + * struct ast_bridge_features features; + * ast_bridge_features_init(&features); + * ast_bridge_leave_hook(&features, leave_callback, NULL, NULL, 0); + * \endcode + * + * This makes the bridging core call leave_callback when a + * channel successfully leaves the bridging system. A pointer + * to useful data may be provided to the hook_pvt parameter. + */ +int ast_bridge_leave_hook(struct ast_bridge_features *features, + ast_bridge_hook_callback callback, + void *hook_pvt, + ast_bridge_hook_pvt_destructor destructor, + int remove_on_pull); + +/*! + * \brief Attach a hangup hook to a bridge features structure + * + * \param features Bridge features structure + * \param callback Function to execute upon activation + * \param hook_pvt Unique data + * \param destructor Optional destructor callback for hook_pvt data + * \param remove_on_pull TRUE if remove the hook when the channel is pulled from the bridge. + * + * \retval 0 on success + * \retval -1 on failure + * + * Example usage: + * + * \code + * struct ast_bridge_features features; + * ast_bridge_features_init(&features); + * ast_bridge_hangup_hook(&features, hangup_callback, NULL, NULL, 0); + * \endcode + * + * This makes the bridging core call hangup_callback if a + * channel that has this hook hangs up. A pointer to useful + * data may be provided to the hook_pvt parameter. + */ +int ast_bridge_hangup_hook(struct ast_bridge_features *features, + ast_bridge_hook_callback callback, + void *hook_pvt, + ast_bridge_hook_pvt_destructor destructor, + int remove_on_pull); + +/*! + * \brief Attach a DTMF hook to a bridge features structure * * \param features Bridge features structure * \param dtmf DTMF string to be activated upon * \param callback Function to execute upon activation * \param hook_pvt Unique data * \param destructor Optional destructor callback for hook_pvt data + * \param remove_on_pull TRUE if remove the hook when the channel is pulled from the bridge. * * \retval 0 on success * \retval -1 on failure @@ -219,21 +484,48 @@ int ast_bridge_features_unregister(enum ast_bridge_builtin_feature feature); * \code * struct ast_bridge_features features; * ast_bridge_features_init(&features); - * ast_bridge_features_hook(&features, "#", pound_callback, NULL, NULL); + * ast_bridge_dtmf_hook(&features, "#", pound_callback, NULL, NULL, 0); * \endcode * * This makes the bridging core call pound_callback if a channel that has this * feature structure inputs the DTMF string '#'. A pointer to useful data may be * provided to the hook_pvt parameter. - * - * \note It is important that the callback set the bridge channel state back to - * AST_BRIDGE_CHANNEL_STATE_WAIT or the bridge thread will not service the channel. */ -int ast_bridge_features_hook(struct ast_bridge_features *features, +int ast_bridge_dtmf_hook(struct ast_bridge_features *features, const char *dtmf, - ast_bridge_features_hook_callback callback, + ast_bridge_hook_callback callback, void *hook_pvt, - ast_bridge_features_hook_pvt_destructor destructor); + ast_bridge_hook_pvt_destructor destructor, + int remove_on_pull); + +/*! + * \brief attach an interval hook to a bridge features structure + * + * \param features Bridge features structure + * \param interval The interval that the hook should execute at in milliseconds + * \param callback Function to execute upon activation + * \param hook_pvt Unique data + * \param destructor Optional destructor callback for hook_pvt data + * \param remove_on_pull TRUE if remove the hook when the channel is pulled from the bridge. + * + * \retval 0 on success + * \retval -1 on failure + * + * \code + * struct ast_bridge_features features; + * ast_bridge_features_init(&features); + * ast_bridge_interval_hook(&features, 1000, playback_callback, NULL, NULL, 0); + * \endcode + * + * This makes the bridging core call playback_callback every second. A pointer to useful + * data may be provided to the hook_pvt parameter. + */ +int ast_bridge_interval_hook(struct ast_bridge_features *features, + unsigned int interval, + ast_bridge_hook_callback callback, + void *hook_pvt, + ast_bridge_hook_pvt_destructor destructor, + int remove_on_pull); /*! * \brief Set a callback on the features structure to receive talking notifications on. @@ -257,6 +549,8 @@ void ast_bridge_features_set_talk_detector(struct ast_bridge_features *features, * \param feature Feature to enable * \param dtmf Optionally the DTMF stream to trigger the feature, if not specified it will be the default * \param config Configuration structure unique to the built in type + * \param destructor Optional destructor callback for config data + * \param remove_on_pull TRUE if remove the hook when the channel is pulled from the bridge. * * \retval 0 on success * \retval -1 on failure @@ -266,19 +560,72 @@ void ast_bridge_features_set_talk_detector(struct ast_bridge_features *features, * \code * struct ast_bridge_features features; * ast_bridge_features_init(&features); - * ast_bridge_features_enable(&features, AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, NULL); + * ast_bridge_features_enable(&features, AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, NULL, NULL, 0); * \endcode * * This enables the attended transfer DTMF option using the default DTMF string. An alternate * string may be provided using the dtmf parameter. Internally this is simply setting up a hook * to a built in feature callback function. */ -int ast_bridge_features_enable(struct ast_bridge_features *features, enum ast_bridge_builtin_feature feature, const char *dtmf, void *config); +int ast_bridge_features_enable(struct ast_bridge_features *features, + enum ast_bridge_builtin_feature feature, + const char *dtmf, + void *config, + ast_bridge_hook_pvt_destructor destructor, + int remove_on_pull); + +/*! + * \brief Constructor function for ast_bridge_features_limits + * + * \param limits pointer to a ast_bridge_features_limits struct that has been allocted, but not initialized + * + * \retval 0 on success + * \retval -1 on failure + */ +int ast_bridge_features_limits_construct(struct ast_bridge_features_limits *limits); + +/*! + * \brief Destructor function for ast_bridge_features_limits + * + * \param limits pointer to an ast_bridge_features_limits struct that needs to be destroyed + * + * This function does not free memory allocated to the ast_bridge_features_limits struct, it only frees elements within the struct. + * You must still call ast_free on the the struct if you allocated it with malloc. + */ +void ast_bridge_features_limits_destroy(struct ast_bridge_features_limits *limits); /*! - * \brief Set a flag on a bridge features structure + * \brief Limit the amount of time a channel may stay in the bridge and optionally play warning messages as time runs out * * \param features Bridge features structure + * \param limits Configured limits applicable to the channel + * \param remove_on_pull TRUE if remove the hook when the channel is pulled from the bridge. + * + * \retval 0 on success + * \retval -1 on failure + * + * Example usage: + * + * \code + * struct ast_bridge_features features; + * struct ast_bridge_features_limits limits; + * ast_bridge_features_init(&features); + * ast_bridge_features_limits_construct(&limits); + * ast_bridge_features_set_limits(&features, &limits, 0); + * ast_bridge_features_limits_destroy(&limits); + * \endcode + * + * This sets the maximum time the channel can be in the bridge to 10 seconds and does not play any warnings. + * + * \note This API call can only be used on a features structure that will be used in association with a bridge channel. + * \note The ast_bridge_features_limits structure must remain accessible for the lifetime of the features structure. + */ +int ast_bridge_features_set_limits(struct ast_bridge_features *features, struct ast_bridge_features_limits *limits, int remove_on_pull); + +/*! + * \brief Set a flag on a bridge channel features structure + * + * \param features Bridge channel features structure * \param flag Flag to enable * * \return Nothing @@ -288,13 +635,13 @@ int ast_bridge_features_enable(struct ast_bridge_features *features, enum ast_br * \code * struct ast_bridge_features features; * ast_bridge_features_init(&features); - * ast_bridge_features_set_flag(&features, AST_BRIDGE_FLAG_DISSOLVE); + * ast_bridge_features_set_flag(&features, AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP); * \endcode * - * This sets the AST_BRIDGE_FLAG_DISSOLVE feature to be enabled on the features structure - * 'features'. + * This sets the AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP feature + * to be enabled on the features structure 'features'. */ -void ast_bridge_features_set_flag(struct ast_bridge_features *features, enum ast_bridge_feature_flags flag); +void ast_bridge_features_set_flag(struct ast_bridge_features *features, unsigned int flag); /*! * \brief Initialize bridge features structure @@ -341,26 +688,39 @@ int ast_bridge_features_init(struct ast_bridge_features *features); void ast_bridge_features_cleanup(struct ast_bridge_features *features); /*! - * \brief Play a DTMF stream into a bridge, optionally not to a given channel + * \brief Allocate a new bridge features struct. + * \since 12.0.0 * - * \param bridge Bridge to play stream into - * \param dtmf DTMF to play - * \param chan Channel to optionally not play to + * Example usage: * - * \retval 0 on success - * \retval -1 on failure + * \code + * struct ast_bridge_features *features; + * features = ast_bridge_features_new(); + * ast_bridge_features_destroy(features); + * \endcode + * + * \retval features New allocated features struct. + * \retval NULL on error. + */ +struct ast_bridge_features *ast_bridge_features_new(void); + +/*! + * \brief Destroy an allocated bridge features struct. + * \since 12.0.0 + * + * \param features Bridge features structure * * Example usage: * * \code - * ast_bridge_dtmf_stream(bridge, "0123456789", NULL); + * struct ast_bridge_features *features; + * features = ast_bridge_features_new(); + * ast_bridge_features_destroy(features); * \endcode * - * This sends the DTMF digits '0123456789' to all channels in the bridge pointed to - * by the bridge pointer. Optionally a channel may be excluded by passing it's channel pointer - * using the chan parameter. + * \return Nothing */ -int ast_bridge_dtmf_stream(struct ast_bridge *bridge, const char *dtmf, struct ast_channel *chan); +void ast_bridge_features_destroy(struct ast_bridge_features *features); #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/include/asterisk/bridging_roles.h b/include/asterisk/bridging_roles.h new file mode 100644 index 000000000..3acb67fae --- /dev/null +++ b/include/asterisk/bridging_roles.h @@ -0,0 +1,135 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2013, Digium, Inc. + * + * Jonathan Rose <jrose@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 Channel Bridging Roles API + * \author Jonathan Rose <jrose@digium.com> + */ + +#ifndef _ASTERISK_BRIDGING_ROLES_H +#define _ASTERISK_BRIDGING_ROLES_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include "asterisk/linkedlists.h" + +#define AST_ROLE_LEN 32 + +/*! + * \brief Adds a bridge role to a channel + * + * \param chan Acquirer of the requested role + * \param role_name Name of the role being attached + * + * \retval 0 on success + * \retval -1 on failure + */ +int ast_channel_add_bridge_role(struct ast_channel *chan, const char *role_name); + +/*! + * \brief Removes a bridge role from a channel + * + * \param chan Channel the role is being removed from + * \param role_name Name of the role being removed + */ +void ast_channel_remove_bridge_role(struct ast_channel *chan, const char *role_name); + +/*! + * \brief Set a role option on a channel + * \param channel Channel receiving the role option + * \param role_name Role the role option is applied to + * \param option Name of the option + * \param value Value of the option + * + * \param 0 on success + * \retval -1 on failure + */ +int ast_channel_set_bridge_role_option(struct ast_channel *channel, const char *role_name, const char *option, const char *value); + +/*! + * \brief Check to see if a bridge channel inherited a specific role from its channel + * + * \param bridge_channel The bridge channel being checked + * \param role_name Name of the role being checked + * + * \retval 0 The bridge channel does not have the requested role + * \retval 1 The bridge channel does have the requested role + * + * \note Before a bridge_channel can effectively check roles against a bridge, ast_bridge_roles_bridge_channel_establish_roles + * should be called on the bridge_channel so that roles and their respective role options can be copied from the channel + * datastore into the bridge_channel roles list. Otherwise this function will just return 0 because the list will be NULL. + */ +int ast_bridge_channel_has_role(struct ast_bridge_channel *bridge_channel, const char *role_name); + +/*! + * \brief Retrieve the value of a requested role option from a bridge channel + * + * \param bridge_channel The bridge channel we are retrieving the option from + * \param role_name Name of the role the option will be retrieved from + * \param option Name of the option we are retrieving the value of + * + * \retval NULL If either the role does not exist on the bridge_channel or the role does exist but the option has not been set + * \retval The value of the option + * + * \note See ast_bridge_roles_channel_set_role_option note about the need to call ast_bridge_roles_bridge_channel_establish_roles. + * + * \note The returned character pointer is only valid as long as the bridge_channel is guaranteed to be alive and hasn't had + * ast_bridge_roles_bridge_channel_clear_roles called against it (as this will free all roles and role options in the bridge + * channel). If you need this value after one of these destruction events occurs, you must make a local copy while it is + * still valid. + */ +const char *ast_bridge_channel_get_role_option(struct ast_bridge_channel *bridge_channel, const char *role_name, const char *option); + +/*! + * \brief Clone the roles from a bridge_channel's attached ast_channel onto the bridge_channel's role list + * + * \param bridge_channel The bridge channel that we are preparing + * + * \retval 0 on success + * \retval -1 on failure + * + * \details + * This function should always be called when the bridge_channel binds to an ast_channel at some point before the bridge_channel + * joins or is imparted onto a bridge. Failure to do so will result in an empty role list. While the list remains established, + * changes to roles on the ast_channel will not propogate to the bridge channel and roles can not be re-established on the bridge + * channel without first clearing the roles with ast_bridge_roles_bridge_channel_clear_roles. + */ +int ast_bridge_channel_establish_roles(struct ast_bridge_channel *bridge_channel); + +/*! + * \brief Clear all roles from a bridge_channel's role list + * + * \param bridge_channel the bridge channel that we are scrubbing + * + * \details + * If roles are already established on a bridge channel, ast_bridge_roles_bridge_channel_establish_roles will fail unconditionally + * without changing any roles. In order to update a bridge channel's roles, they must first be cleared from the bridge channel using + * this function. + * + * \note + * ast_bridge_roles_bridge_channel_clear_roles also serves as the destructor for the role list of a bridge channel. + */ +void ast_bridge_channel_clear_roles(struct ast_bridge_channel *bridge_channel); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* _ASTERISK_BRIDGING_ROLES_H */ diff --git a/include/asterisk/bridging_technology.h b/include/asterisk/bridging_technology.h index d09c4bec4..2bb2170f0 100644 --- a/include/asterisk/bridging_technology.h +++ b/include/asterisk/bridging_technology.h @@ -28,14 +28,17 @@ extern "C" { #endif -/*! \brief Preference for choosing the bridge technology */ +/*! + * \brief Base preference values for choosing a bridge technology. + * + * \note Higher is more preference. + */ enum ast_bridge_preference { - /*! Bridge technology should have high precedence over other bridge technologies */ - AST_BRIDGE_PREFERENCE_HIGH = 0, - /*! Bridge technology is decent, not the best but should still be considered over low */ - AST_BRIDGE_PREFERENCE_MEDIUM, - /*! Bridge technology is low, it should not be considered unless it is absolutely needed */ - AST_BRIDGE_PREFERENCE_LOW, + AST_BRIDGE_PREFERENCE_BASE_HOLDING = 50, + AST_BRIDGE_PREFERENCE_BASE_EARLY = 100, + AST_BRIDGE_PREFERENCE_BASE_NATIVE = 90, + AST_BRIDGE_PREFERENCE_BASE_1TO1MIX = 50, + AST_BRIDGE_PREFERENCE_BASE_MULTIMIX = 10, }; /*! @@ -49,31 +52,68 @@ struct ast_bridge_technology { uint32_t capabilities; /*! Preference level that should be used when determining whether to use this bridge technology or not */ enum ast_bridge_preference preference; - /*! Callback for when a bridge is being created */ + /*! + * \brief Callback for when a bridge is being created. + * + * \retval 0 on success + * \retval -1 on failure + * + * \note On entry, bridge may or may not already be locked. + * However, it can be accessed as if it were locked. + */ int (*create)(struct ast_bridge *bridge); - /*! Callback for when a bridge is being destroyed */ - int (*destroy)(struct ast_bridge *bridge); - /*! Callback for when a channel is being added to a bridge */ + /*! + * \brief Callback for when a bridge is being destroyed + * + * \note On entry, bridge must NOT be locked. + */ + void (*destroy)(struct ast_bridge *bridge); + /*! + * \brief Callback for when a channel is being added to a bridge. + * + * \retval 0 on success + * \retval -1 on failure + * + * \note On entry, bridge is already locked. + */ int (*join)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel); - /*! Callback for when a channel is leaving a bridge */ - int (*leave)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel); - /*! Callback for when a channel is suspended from the bridge */ + /*! + * \brief Callback for when a channel is leaving a bridge + * + * \note On entry, bridge is already locked. + */ + void (*leave)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel); + /*! + * \brief Callback for when a channel is suspended from the bridge + * + * \note On entry, bridge is already locked. + */ void (*suspend)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel); - /*! Callback for when a channel is unsuspended from the bridge */ + /*! + * \brief Callback for when a channel is unsuspended from the bridge + * + * \note On entry, bridge is already locked. + */ void (*unsuspend)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel); - /*! Callback to see if a channel is compatible with the bridging technology */ - int (*compatible)(struct ast_bridge_channel *bridge_channel); - /*! Callback for writing a frame into the bridging technology */ - enum ast_bridge_write_result (*write)(struct ast_bridge *bridge, struct ast_bridge_channel *bridged_channel, struct ast_frame *frame); - /*! Callback for when a file descriptor trips */ - int (*fd)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, int fd); - /*! Callback for replacement thread function */ - int (*thread)(struct ast_bridge *bridge); - /*! Callback for poking a bridge thread */ - int (*poke)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel); + /*! + * \brief Callback to see if the bridge is compatible with the bridging technology. + * + * \retval 0 if not compatible + * \retval non-zero if compatible + */ + int (*compatible)(struct ast_bridge *bridge); + /*! + * \brief Callback for writing a frame into the bridging technology. + * + * \retval 0 on success + * \retval -1 on failure + * + * \note On entry, bridge is already locked. + */ + int (*write)(struct ast_bridge *bridge, struct ast_bridge_channel *bridged_channel, struct ast_frame *frame); /*! Formats that the bridge technology supports */ struct ast_format_cap *format_capabilities; - /*! Bit to indicate whether the bridge technology is currently suspended or not */ + /*! TRUE if the bridge technology is currently suspended. */ unsigned int suspended:1; /*! Module this bridge technology belongs to. Is used for reference counting when creating/destroying a bridge. */ struct ast_module *mod; @@ -126,27 +166,6 @@ int __ast_bridge_technology_register(struct ast_bridge_technology *technology, s int ast_bridge_technology_unregister(struct ast_bridge_technology *technology); /*! - * \brief Feed notification that a frame is waiting on a channel into the bridging core - * - * \param bridge The bridge that the notification should influence - * \param bridge_channel Bridge channel the notification was received on (if known) - * \param chan Channel the notification was received on (if known) - * \param outfd File descriptor that the notification was received on (if known) - * - * Example usage: - * - * \code - * ast_bridge_handle_trip(bridge, NULL, chan, -1); - * \endcode - * - * This tells the bridging core that a frame has been received on - * the channel pointed to by chan and that it should be read and handled. - * - * \note This should only be used by bridging technologies. - */ -void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_channel *chan, int outfd); - -/*! * \brief Lets the bridging indicate when a bridge channel has stopped or started talking. * * \note All DSP functionality on the bridge has been pushed down to the lowest possible @@ -155,12 +174,11 @@ void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel * application, this function has been created to allow the bridging technology to communicate * that information with the bridging core. * - * \param bridge The bridge that the channel is a part of. * \param bridge_channel The bridge channel that has either started or stopped talking. * \param started_talking set to 1 when this indicates the channel has started talking set to 0 * when this indicates the channel has stopped talking. */ -void ast_bridge_notify_talking(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, int started_talking); +void ast_bridge_notify_talking(struct ast_bridge_channel *bridge_channel, int started_talking); /*! * \brief Suspend a bridge technology from consideration diff --git a/include/asterisk/ccss.h b/include/asterisk/ccss.h index cf2f21996..d8101cddf 100644 --- a/include/asterisk/ccss.h +++ b/include/asterisk/ccss.h @@ -1485,10 +1485,12 @@ int ast_cc_agent_set_interfaces_chanvar(struct ast_channel *chan); * \verbatim extension@context \endverbatim as a starting point * * \details - * The CC_INTERFACES channel variable will have the interfaces that should be - * called back for a specific PBX instance. This version of the function is used - * mainly by chan_local, wherein we need to set CC_INTERFACES based on an extension - * and context that appear in the middle of the tree of dialed interfaces + * The CC_INTERFACES channel variable will have the interfaces + * that should be called back for a specific PBX instance. This + * version of the function is used mainly by local channels, + * wherein we need to set CC_INTERFACES based on an extension + * and context that appear in the middle of the tree of dialed + * interfaces. * * \note * This function will lock the channel as well as the list of monitors stored diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 939c8db51..91373cfbd 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -643,6 +643,7 @@ struct ast_channel_tech { /*! \brief Handle an exception, reading a frame */ struct ast_frame * (* const exception)(struct ast_channel *chan); +/* BUGBUG this tech callback is to be removed. */ /*! \brief Bridge two channels of the same type together */ enum ast_bridge_result (* const bridge)(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms); @@ -671,6 +672,7 @@ struct ast_channel_tech { /*! \brief Write a text frame, in standard format */ int (* const write_text)(struct ast_channel *chan, struct ast_frame *frame); +/* BUGBUG this tech callback is to be removed. */ /*! \brief Find bridged channel */ struct ast_channel *(* const bridged_channel)(struct ast_channel *chan, struct ast_channel *bridge); @@ -686,6 +688,7 @@ struct ast_channel_tech { */ int (* func_channel_write)(struct ast_channel *chan, const char *function, char *data, const char *value); +/* BUGBUG this tech callback is to be removed. */ /*! \brief Retrieve base channel (agent and local) */ struct ast_channel* (* get_base_channel)(struct ast_channel *chan); @@ -896,10 +899,6 @@ enum { * a message aimed at preventing a subsequent hangup exten being run at the pbx_run * level */ AST_FLAG_BRIDGE_HANGUP_RUN = (1 << 17), - /*! This flag indicates that the hangup exten should NOT be run when the - * bridge terminates, this will allow the hangup in the pbx loop to be run instead. - * */ - AST_FLAG_BRIDGE_HANGUP_DONT = (1 << 18), /*! Disable certain workarounds. This reintroduces certain bugs, but allows * some non-traditional dialplans (like AGI) to continue to function. */ @@ -928,7 +927,6 @@ enum { AST_FEATURE_AUTOMON = (1 << 4), AST_FEATURE_PARKCALL = (1 << 5), AST_FEATURE_AUTOMIXMON = (1 << 6), - AST_FEATURE_NO_H_EXTEN = (1 << 7), AST_FEATURE_WARNING_ACTIVE = (1 << 8), }; @@ -4038,6 +4036,9 @@ void ast_channel_timingfunc_set(struct ast_channel *chan, ast_timing_func_t valu struct ast_bridge *ast_channel_internal_bridge(const struct ast_channel *chan); void ast_channel_internal_bridge_set(struct ast_channel *chan, struct ast_bridge *value); +struct ast_bridge_channel *ast_channel_internal_bridge_channel(const struct ast_channel *chan); +void ast_channel_internal_bridge_channel_set(struct ast_channel *chan, struct ast_bridge_channel *value); + struct ast_channel *ast_channel_internal_bridged_channel(const struct ast_channel *chan); void ast_channel_internal_bridged_channel_set(struct ast_channel *chan, struct ast_channel *value); @@ -4138,4 +4139,69 @@ struct varshead *ast_channel_get_manager_vars(struct ast_channel *chan); */ struct stasis_topic *ast_channel_topic(struct ast_channel *chan); +/*! + * \brief Get the bridge associated with a channel + * \since 12.0.0 + * + * \param chan The channel whose bridge we want + * + * \details + * The bridge returned has its reference count incremented. Use + * ao2_cleanup() or ao2_ref() in order to decrement the + * reference count when you are finished with the bridge. + * + * \note This function expects the channel to be locked prior to + * being called and will not grab the channel lock. + * + * \retval NULL No bridge present on the channel + * \retval non-NULL The bridge the channel is in + */ +struct ast_bridge *ast_channel_get_bridge(const struct ast_channel *chan); + +/*! + * \brief Determine if a channel is in a bridge + * \since 12.0.0 + * + * \param chan The channel to test + * + * \note This function expects the channel to be locked prior to + * being called and will not grab the channel lock. + * + * \retval 0 The channel is not bridged + * \retval non-zero The channel is bridged + */ +int ast_channel_is_bridged(const struct ast_channel *chan); + +/*! + * \brief Get the channel's bridge peer only if the bridge is two-party. + * \since 12.0.0 + * + * \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_channel_bridge_peer(struct ast_channel *chan); + +/*! + * \brief Get a reference to the channel's bridge pointer. + * \since 12.0.0 + * + * \param chan The channel whose bridge channel is desired + * + * \note This increases the reference count of the bridge_channel. + * Use ao2_ref() or ao2_cleanup() to decrement the refcount when + * you are finished with it. + * + * \note It is expected that the channel is locked prior to + * placing this call. + * + * \retval NULL The channel has no bridge_channel + * \retval non-NULL A reference to the bridge_channel + */ +struct ast_bridge_channel *ast_channel_get_bridge_channel(struct ast_channel *chan); + #endif /* _ASTERISK_CHANNEL_H */ diff --git a/include/asterisk/config_options.h b/include/asterisk/config_options.h index 64d8d5089..739d83130 100644 --- a/include/asterisk/config_options.h +++ b/include/asterisk/config_options.h @@ -575,6 +575,16 @@ int __aco_option_register(struct aco_info *info, const char *name, enum aco_matc */ int aco_option_register_deprecated(struct aco_info *info, const char *name, struct aco_type **types, const char *aliased_to); +/*! + * \brief Read the flags of a config option - useful when using a custom callback for a config option + * \since 12 + * + * \param option Pointer to the aco_option struct + * + * \retval value of the flags on the config option + */ +unsigned int aco_option_get_flags(const struct aco_option *option); + /*! \note Everything below this point is to handle converting varargs * containing field names, to varargs containing a count of args, followed * by the offset of each of the field names in the struct type that is diff --git a/include/asterisk/core_local.h b/include/asterisk/core_local.h new file mode 100644 index 000000000..693c93b46 --- /dev/null +++ b/include/asterisk/core_local.h @@ -0,0 +1,98 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2013 Digium, Inc. + * + * Richard Mudgett <rmudgett@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 Local proxy channel special access. + * + * \author Richard Mudgett <rmudgett@digium.com> + * + * See Also: + * \arg \ref AstCREDITS + */ + +#ifndef _ASTERISK_CORE_LOCAL_H +#define _ASTERISK_CORE_LOCAL_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +/* Forward declare some struct names */ +struct ast_channel; +struct ast_bridge; +struct ast_bridge_features; + +/* ------------------------------------------------------------------- */ + +/*! + * \brief Get the other local channel in the pair. + * \since 12.0.0 + * + * \param ast Local channel to get peer. + * + * \note On entry, ast must be locked. + * + * \retval peer reffed on success. + * \retval NULL if no peer or error. + */ +struct ast_channel *ast_local_get_peer(struct ast_channel *ast); + +/*! + * \brief Setup the outgoing local channel to join a bridge on ast_call(). + * \since 12.0.0 + * + * \param ast Either channel of a local channel pair. + * \param bridge Bridge to join. + * \param swap Channel to swap with when joining. + * \param features Bridge features structure. + * + * \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 Intended to be called after ast_request() and before + * ast_call() on a local channel. + * + * \retval 0 on success. + * \retval -1 on error. + */ +int ast_local_setup_bridge(struct ast_channel *ast, struct ast_bridge *bridge, struct ast_channel *swap, struct ast_bridge_features *features); + +/*! + * \brief Setup the outgoing local channel to masquerade into a channel on ast_call(). + * \since 12.0.0 + * + * \param ast Either channel of a local channel pair. + * \param masq Channel to masquerade into. + * + * \note Intended to be called after ast_request() and before + * ast_call() on a local channel. + * + * \retval 0 on success. + * \retval -1 on error. + */ +int ast_local_setup_masquerade(struct ast_channel *ast, struct ast_channel *masq); + +/* ------------------------------------------------------------------- */ + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* _ASTERISK_CORE_LOCAL_H */ diff --git a/include/asterisk/core_unreal.h b/include/asterisk/core_unreal.h new file mode 100644 index 000000000..7cb68f162 --- /dev/null +++ b/include/asterisk/core_unreal.h @@ -0,0 +1,191 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2013 Digium, Inc. + * + * Richard Mudgett <rmudgett@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 Unreal channel derivative framework. + * + * \author Richard Mudgett <rmudgett@digium.com> + * + * See Also: + * \arg \ref AstCREDITS + */ + +#ifndef _ASTERISK_CORE_UNREAL_H +#define _ASTERISK_CORE_UNREAL_H + +#include "asterisk/astobj2.h" +#include "asterisk/channel.h" +#include "asterisk/abstract_jb.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +/* Forward declare some struct names */ +struct ast_format_cap; +struct ast_callid; + +/* ------------------------------------------------------------------- */ + +/*! + * \brief The base pvt structure for local channel derivatives. + * + * The unreal pvt has two ast_chan objects - the "owner" and the "next channel", the outbound channel + * + * ast_chan owner -> ast_unreal_pvt -> ast_chan chan + */ +struct ast_unreal_pvt { + struct ast_channel *owner; /*!< Master Channel - ;1 side */ + struct ast_channel *chan; /*!< Outbound channel - ;2 side */ + struct ast_format_cap *reqcap; /*!< Requested format capabilities */ + struct ast_jb_conf jb_conf; /*!< jitterbuffer configuration */ + unsigned int flags; /*!< Private option flags */ + /*! Base name of the unreal channels. exten@context or other name. */ + char name[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2]; +}; + +#define AST_UNREAL_IS_OUTBOUND(a, b) ((a) == (b)->chan ? 1 : 0) + +#define AST_UNREAL_CARETAKER_THREAD (1 << 0) /*!< The ;2 side launched a PBX, was pushed into a bridge, or was masqueraded into an application. */ +#define AST_UNREAL_NO_OPTIMIZATION (1 << 1) /*!< Do not optimize out the unreal channels */ +#define AST_UNREAL_MOH_INTERCEPT (1 << 2) /*!< Intercept and act on hold/unhold control frames */ + +/*! + * \brief Send an unreal pvt in with no locks held and get all locks + * + * \note NO locks should be held prior to calling this function + * \note The pvt must have a ref held before calling this function + * \note if outchan or outowner is set != NULL after calling this function + * those channels are locked and reffed. + * \note Batman. + */ +void ast_unreal_lock_all(struct ast_unreal_pvt *p, struct ast_channel **outchan, struct ast_channel **outowner); + +/*! + * \brief Hangup one end (maybe both ends) of an unreal channel derivative. + * \since 12.0.0 + * + * \param p Private channel struct (reffed) + * \param ast Channel being hung up. (locked) + * + * \note Common hangup code for unreal channels. Derived + * channels will need to deal with any additional resources. + * + * \retval 0 on success. + * \retval -1 on error. + */ +int ast_unreal_hangup(struct ast_unreal_pvt *p, struct ast_channel *ast); + +/*! Unreal channel framework struct ast_channel_tech.send_digit_begin callback */ +int ast_unreal_digit_begin(struct ast_channel *ast, char digit); + +/*! Unreal channel framework struct ast_channel_tech.send_digit_end callback */ +int ast_unreal_digit_end(struct ast_channel *ast, char digit, unsigned int duration); + +/*! Unreal channel framework struct ast_channel_tech.answer callback */ +int ast_unreal_answer(struct ast_channel *ast); + +/*! Unreal channel framework struct ast_channel_tech.read and struct ast_channel_tech.exception callback */ +struct ast_frame *ast_unreal_read(struct ast_channel *ast); + +/*! Unreal channel framework struct ast_channel_tech.write callback */ +int ast_unreal_write(struct ast_channel *ast, struct ast_frame *f); + +/*! Unreal channel framework struct ast_channel_tech.indicate callback */ +int ast_unreal_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen); + +/*! Unreal channel framework struct ast_channel_tech.fixup callback */ +int ast_unreal_fixup(struct ast_channel *oldchan, struct ast_channel *newchan); + +/*! Unreal channel framework struct ast_channel_tech.send_html callback */ +int ast_unreal_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen); + +/*! Unreal channel framework struct ast_channel_tech.send_text callback */ +int ast_unreal_sendtext(struct ast_channel *ast, const char *text); + +/*! Unreal channel framework struct ast_channel_tech.queryoption callback */ +int ast_unreal_queryoption(struct ast_channel *ast, int option, void *data, int *datalen); + +/*! Unreal channel framework struct ast_channel_tech.setoption callback */ +int ast_unreal_setoption(struct ast_channel *chan, int option, void *data, int datalen); + +/*! + * \brief struct ast_unreal_pvt destructor. + * \since 12.0.0 + * + * \param vdoomed Object to destroy. + * + * \return Nothing + */ +void ast_unreal_destructor(void *vdoomed); + +/*! + * \brief Allocate the base unreal struct for a derivative. + * \since 12.0.0 + * + * \param size Size of the unreal struct to allocate. + * \param destructor Destructor callback. + * \param cap Format capabilities to give the unreal private struct. + * + * \retval pvt on success. + * \retval NULL on error. + */ +struct ast_unreal_pvt *ast_unreal_alloc(size_t size, ao2_destructor_fn destructor, struct ast_format_cap *cap); + +/*! + * \brief Create the semi1 and semi2 unreal channels. + * \since 12.0.0 + * + * \param p Unreal channel private struct. + * \param tech Channel technology to use. + * \param semi1_state State to start the semi1(owner) channel in. + * \param semi2_state State to start the semi2(outgoing chan) channel in. + * \param exten Exten to start the chennels in. (NULL if s) + * \param context Context to start the channels in. (NULL if default) + * \param requestor Channel requesting creation. (NULL if none) + * \param callid Thread callid to use. + * + * \retval semi1_channel on success. + * \retval NULL on error. + */ +struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p, + const struct ast_channel_tech *tech, int semi1_state, int semi2_state, + const char *exten, const char *context, const struct ast_channel *requestor, + struct ast_callid *callid); + +/*! + * \brief Setup unreal owner and chan channels before initiating call. + * \since 12.0.0 + * + * \param semi1 Owner channel of unreal channel pair. + * \param semi2 Outgoing channel of unreal channel pair. + * + * \note On entry, the semi1 and semi2 channels are already locked. + * + * \return Nothing + */ +void ast_unreal_call_setup(struct ast_channel *semi1, struct ast_channel *semi2); + +/* ------------------------------------------------------------------- */ + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* _ASTERISK_CORE_UNREAL_H */ diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h index abb0c2e28..bedc3a25d 100644 --- a/include/asterisk/frame.h +++ b/include/asterisk/frame.h @@ -120,6 +120,8 @@ enum ast_frame_type { AST_FRAME_MODEM, /*! DTMF begin event, subclass is the digit */ AST_FRAME_DTMF_BEGIN, + /*! Internal bridge module action. */ + AST_FRAME_BRIDGE_ACTION, }; #define AST_FRAME_DTMF AST_FRAME_DTMF_END diff --git a/include/asterisk/framehook.h b/include/asterisk/framehook.h index 52993b55c..10d525ca7 100644 --- a/include/asterisk/framehook.h +++ b/include/asterisk/framehook.h @@ -228,7 +228,7 @@ struct ast_framehook_interface { * provide it during the event and destruction callbacks. It is entirely up to the * application using this API to manage the memory associated with the data pointer. * - * \retval On success, positive id representing this hook on the channel + * \retval On success, non-negative id representing this hook on the channel * \retval On failure, -1 */ int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i); diff --git a/include/asterisk/manager.h b/include/asterisk/manager.h index e0160c6b5..4e9b8d14a 100644 --- a/include/asterisk/manager.h +++ b/include/asterisk/manager.h @@ -347,6 +347,55 @@ struct ast_str *ast_manager_build_channel_state_string_suffix( struct ast_str *ast_manager_build_channel_state_string( const struct ast_channel_snapshot *snapshot); +/*! \brief Struct representing a snapshot of bridge state */ +struct ast_bridge_snapshot; + +/*! + * \brief Generate the AMI message body from a bridge snapshot + * \since 12 + * + * \param snapshot the bridge snapshot for which to generate an AMI message + * body + * + * \retval NULL on error + * \retval ast_str* on success (must be ast_freed by caller) + */ +struct ast_str *ast_manager_build_bridge_state_string( + const struct ast_bridge_snapshot *snapshot, + const char *suffix); + +/*! \brief Struct containing info for an AMI event to send out. */ +struct ast_manager_event_blob { + int event_flags; /*!< Flags the event should be raised with. */ + const char *manager_event; /*!< The event to be raised, should be a string literal. */ + AST_DECLARE_STRING_FIELDS( + AST_STRING_FIELD(extra_fields); /*!< Extra fields to include in the event. */ + ); +}; + +/*! + * \since 12 + * \brief Construct a \ref snapshot_manager_event. + * + * \param event_flags Flags the event should be raised with. + * \param manager_event The event to be raised, should be a string literal. + * \param extra_fields_fmt Format string for extra fields to include. + * Or NO_EXTRA_FIELDS for no extra fields. + * + * \return New \ref ast_manager_snapshot_event object. + * \return \c NULL on error. + */ +struct ast_manager_event_blob * +__attribute__((format(printf, 3, 4))) +ast_manager_event_blob_create( + int event_flags, + const char *manager_event, + const char *extra_fields_fmt, + ...); + +/*! GCC warns about blank or NULL format strings. So, shenanigans! */ +#define NO_EXTRA_FIELDS "%s", "" + /*! * \brief Initialize support for AMI channel events. * \return 0 on success. @@ -355,4 +404,12 @@ struct ast_str *ast_manager_build_channel_state_string( */ int manager_channels_init(void); +/*! + * \brief Initialize support for AMI channel events. + * \return 0 on success. + * \return non-zero on error. + * \since 12 + */ +int manager_bridging_init(void); + #endif /* _ASTERISK_MANAGER_H */ diff --git a/include/asterisk/parking.h b/include/asterisk/parking.h new file mode 100644 index 000000000..176eddb04 --- /dev/null +++ b/include/asterisk/parking.h @@ -0,0 +1,184 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2013, Digium, Inc. + * + * Jonathan Rose <jrose@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 Call Parking API + * + * \author Jonathan Rose <jrose@digium.com> + */ + +#include "asterisk/stringfields.h" + +#define PARK_APPLICATION "Park" + +/*! + * \brief Defines the type of parked call message being published + * \since 12 + */ +enum ast_parked_call_event_type { + PARKED_CALL = 0, + PARKED_CALL_TIMEOUT, + PARKED_CALL_GIVEUP, + PARKED_CALL_UNPARKED, + PARKED_CALL_FAILED, +}; + +/*! + * \brief A parked call message payload + * \since 12 + */ +struct ast_parked_call_payload { + struct ast_channel_snapshot *parkee; /*!< Snapshot of the channel that is parked */ + struct ast_channel_snapshot *parker; /*!< Snapshot of the channel that parked the call */ + struct ast_channel_snapshot *retriever; /*!< Snapshot of the channel that retrieved the call */ + enum ast_parked_call_event_type event_type; /*!< Reason for issuing the parked call message */ + long unsigned int timeout; /*!< Time remaining before the call times out (seconds ) */ + long unsigned int duration; /*!< How long the parkee has been parked (seconds) */ + unsigned int parkingspace; /*!< Which Parking Space the parkee occupies */ + AST_DECLARE_STRING_FIELDS( + AST_STRING_FIELD(parkinglot); /*!< Name of the parking lot used to park the parkee */ + ); +}; + +/*! + * \brief Constructor for parked_call_payload objects + * \since 12 + * + * \param event_type What kind of parked call event is happening + * \param parkee_snapshot channel snapshot of the parkee + * \param parker_snapshot channel snapshot of the parker + * \param retriever_snapshot channel snapshot of the retriever (NULL allowed) + * \param parkinglot name of the parking lot where the parked call is parked + * \param parkingspace what numerical parking space the parked call is parked in + * \param timeout how long the parked call can remain at the point this snapshot is created before timing out + * \param duration how long the parked call has currently been parked + * + * \retval NULL if the parked call payload can't be allocated + * \retval reference to a newly created parked call payload + */ +struct ast_parked_call_payload *ast_parked_call_payload_create(enum ast_parked_call_event_type event_type, + struct ast_channel_snapshot *parkee_snapshot, struct ast_channel_snapshot *parker_snapshot, + struct ast_channel_snapshot *retriever_snapshot, const char *parkinglot, + unsigned int parkingspace, unsigned long int timeout, unsigned long int duration); + +/*! + * \brief initialize parking stasis types + * \since 12 + */ +void ast_parking_stasis_init(void); + +/*! + * \brief disable parking stasis types + * \since 12 + */ +void ast_parking_stasis_disable(void); + +/*! + * \brief accessor for the parking stasis topic + * \since 12 + * + * \retval NULL if the parking topic hasn't been created or has been disabled + * \retval a pointer to the parking topic + */ +struct stasis_topic *ast_parking_topic(void); + +/*! + * \brief accessor for the parked call stasis message type + * \since 12 + * + * \retval NULL if the parking topic hasn't been created or has been canceled + * \retval a pointer to the parked call message type + */ +struct stasis_message_type *ast_parked_call_type(void); + +/*! + * \brief invoke an installable park callback to asynchronously park a bridge_channel in a bridge + * \since 12 + * + * \param bridge_channel the bridge channel that initiated parking + * \parkee_uuid channel id of the channel being parked + * \parker_uuid channel id of the channel that initiated parking + * \param app_data string of application data that might be applied to parking + */ +void ast_bridge_channel_park(struct ast_bridge_channel *bridge_channel, + const char *parkee_uuid, + const char *parker_uuid, + const char *app_data); + +typedef int (*ast_park_blind_xfer_fn)(struct ast_bridge *bridge, struct ast_bridge_channel *parker, + struct ast_exten *park_exten); + +/*! + * \brief install a callback for handling blind transfers to a parking extension + * \since 12 + * + * \param parking_func Function to use for transfers to 'Park' applications + */ +void ast_install_park_blind_xfer_func(ast_park_blind_xfer_fn park_blind_xfer_func); + +/*! + * \brief uninstall a callback for handling blind transfers to a parking extension + * \since 12 + */ +void ast_uninstall_park_blind_xfer_func(void); + +/*! + * \brief use the installed park blind xfer func + * \since 12 + * + * \param bridge Bridge being transferred from + * \param bridge_channel Bridge channel initiating the transfer + * \param app_data arguments to the park application + * + * \retval 0 on success + * \retval -1 on failure + */ +int ast_park_blind_xfer(struct ast_bridge *bridge, struct ast_bridge_channel *parker, + struct ast_exten *park_exten); + +typedef void (*ast_bridge_channel_park_fn)(struct ast_bridge_channel *parkee, const char *parkee_uuid, + const char *parker_uuid, const char *app_data); + +/*! + * \brief Install a function for ast_bridge_channel_park + * \since 12 + * + * \param bridge_channel_park_func function callback to use for ast_bridge_channel_park + */ +void ast_install_bridge_channel_park_func(ast_bridge_channel_park_fn bridge_channel_park_func); + +/*! + * \brief Uninstall the ast_bridge_channel_park function callback + * \since 12 + */ +void ast_uninstall_bridge_channel_park_func(void); + + +/*! + * \brief Determines whether a certain extension is a park application extension or not. + * \since 12 + * + * \param exten_str string representation of the extension sought + * \param chan channel the extension is sought for + * \param context context the extension is sought from + * + * \retval pointer to the extension if the extension is a park extension + * \retval NULL if the extension was not a park extension + */ +struct ast_exten *ast_get_parking_exten(const char *exten_str, struct ast_channel *chan, const char *context); diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h index c8a144b73..e2567f508 100644 --- a/include/asterisk/rtp_engine.h +++ b/include/asterisk/rtp_engine.h @@ -1541,24 +1541,6 @@ int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp); struct ast_rtp_glue *ast_rtp_instance_get_glue(const char *type); /*! - * \brief Bridge two channels that use RTP instances - * - * \param c0 First channel part of the bridge - * \param c1 Second channel part of the bridge - * \param flags Bridging flags - * \param fo If a frame needs to be passed up it is stored here - * \param rc Channel that passed the above frame up - * \param timeoutms How long the channels should be bridged for - * - * \retval Bridge result - * - * \note This should only be used by channel drivers in their technology declaration. - * - * \since 1.8 - */ -enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms); - -/*! * \brief Get the other RTP instance that an instance is bridged to * * \param instance The RTP instance that we want @@ -1579,6 +1561,16 @@ enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct as struct ast_rtp_instance *ast_rtp_instance_get_bridged(struct ast_rtp_instance *instance); /*! + * \brief Set the other RTP instance that an instance is bridged to + * + * \param instance The RTP instance that we want to set the bridged value on + * \param bridged The RTP instance they are bridged to + * + * \since 12 + */ +void ast_rtp_instance_set_bridged(struct ast_rtp_instance *instance, struct ast_rtp_instance *bridged); + +/*! * \brief Make two channels compatible for early bridging * * \param c0 First channel part of the bridge diff --git a/include/asterisk/stasis_bridging.h b/include/asterisk/stasis_bridging.h new file mode 100644 index 000000000..1b547a7d5 --- /dev/null +++ b/include/asterisk/stasis_bridging.h @@ -0,0 +1,238 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2013 Digium, Inc. + * + * Kinsey Moore <kmoore@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. + */ + +#ifndef _STASIS_BRIDGING_H +#define _STASIS_BRIDGING_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include "asterisk/stringfields.h" +#include "asterisk/utils.h" +#include "asterisk/lock.h" +#include "asterisk/linkedlists.h" +#include "asterisk/channel.h" +#include "asterisk/bridging.h" + +/*! + * \brief Structure that contains a snapshot of information about a bridge + */ +struct ast_bridge_snapshot { + AST_DECLARE_STRING_FIELDS( + /*! Immutable bridge UUID. */ + AST_STRING_FIELD(uniqueid); + /*! Bridge technology that is handling the bridge */ + AST_STRING_FIELD(technology); + ); + /*! AO2 container of bare channel uniqueid strings participating in the bridge. + * Allocated from ast_str_container_alloc() */ + struct ao2_container *channels; + /*! Bridge flags to tweak behavior */ + struct ast_flags feature_flags; + /*! Number of channels participating in the bridge */ + unsigned int num_channels; + /*! Number of active channels in the bridge. */ + unsigned int num_active; +}; + +/*! + * \since 12 + * \brief Generate a snapshot of the bridge state. This is an ao2 object, so + * ao2_cleanup() to deallocate. + * + * \param bridge The bridge from which to generate a snapshot + * + * \retval AO2 refcounted snapshot on success + * \retval NULL on error + */ +struct ast_bridge_snapshot *ast_bridge_snapshot_create(struct ast_bridge *bridge); + +/*! + * \since 12 + * \brief Message type for \ref ast_bridge_snapshot. + * + * \retval Message type for \ref ast_bridge_snapshot. + */ +struct stasis_message_type *ast_bridge_snapshot_type(void); + +/*! + * \since 12 + * \brief A topic which publishes the events for a particular bridge. + * + * If the given \a bridge is \c NULL, ast_bridge_topic_all() is returned. + * + * \param bridge Bridge for which to get a topic or \c NULL. + * + * \retval Topic for bridge's events. + * \retval ast_bridge_topic_all() if \a bridge is \c NULL. + */ +struct stasis_topic *ast_bridge_topic(struct ast_bridge *bridge); + +/*! + * \since 12 + * \brief A topic which publishes the events for all bridges. + * \retval Topic for all bridge events. + */ +struct stasis_topic *ast_bridge_topic_all(void); + +/*! + * \since 12 + * \brief A caching topic which caches \ref ast_bridge_snapshot messages from + * ast_bridge_events_all(void). + * + * \retval Caching topic for all bridge events. + */ +struct stasis_caching_topic *ast_bridge_topic_all_cached(void); + +/*! + * \since 12 + * \brief Publish the state of a bridge + * + * \param bridge The bridge for which to publish state + */ +void ast_bridge_publish_state(struct ast_bridge *bridge); + +/*! \brief Message representing the merge of two bridges */ +struct ast_bridge_merge_message { + struct ast_bridge_snapshot *from; /*!< Bridge from which channels will be removed during the merge */ + struct ast_bridge_snapshot *to; /*!< Bridge to which channels will be added during the merge */ +}; + +/*! + * \since 12 + * \brief Message type for \ref ast_bridge_merge_message. + * + * \retval Message type for \ref ast_bridge_merge_message. + */ +struct stasis_message_type *ast_bridge_merge_message_type(void); + +/*! + * \since 12 + * \brief Publish a bridge merge + * + * \param to The bridge to which channels are being added + * \param from The bridge from which channels are being removed + */ +void ast_bridge_publish_merge(struct ast_bridge *to, struct ast_bridge *from); + +/*! + * \since 12 + * \brief Blob of data associated with a bridge. + * + * The \c blob is actually a JSON object of structured data. It has a "type" field + * which contains the type string describing this blob. + */ +struct ast_bridge_blob { + /*! Bridge blob is associated with (or NULL for global/all bridges) */ + struct ast_bridge_snapshot *bridge; + /*! Channel blob is associated with (may be NULL for some messages) */ + struct ast_channel_snapshot *channel; + /*! JSON blob of data */ + struct ast_json *blob; +}; + +/*! + * \since 12 + * \brief Message type for \ref channel enter bridge blob messages. + * + * \retval Message type for \ref channel enter bridge blob messages. + */ +struct stasis_message_type *ast_channel_entered_bridge_type(void); + +/*! + * \since 12 + * \brief Message type for \ref channel leave bridge blob messages. + * + * \retval Message type for \ref channel leave bridge blob messages. + */ +struct stasis_message_type *ast_channel_left_bridge_type(void); + +/*! + * \since 12 + * \brief Creates a \ref ast_bridge_blob message. + * + * The \a blob JSON object requires a \c "type" field describing the blob. It + * should also be treated as immutable and not modified after it is put into the + * message. + * + * \param bridge Channel blob is associated with, or NULL for global/all bridges. + * \param blob JSON object representing the data. + * \return \ref ast_bridge_blob message. + * \return \c NULL on error + */ +struct stasis_message *ast_bridge_blob_create(struct stasis_message_type *type, + struct ast_bridge *bridge, + struct ast_channel *chan, + struct ast_json *blob); + +/*! + * \since 12 + * \brief Extracts the type field from a \ref ast_bridge_blob. + * + * Returned \c char* is still owned by \a obj + * + * \param obj Channel blob object. + * + * \retval Type field value from the blob. + * \retval \c NULL on error. + */ +const char *ast_bridge_blob_json_type(struct ast_bridge_blob *obj); + +/*! + * \since 12 + * \brief Publish a bridge channel enter event + * + * \param bridge The bridge a channel entered + * \param chan The channel that entered the bridge + */ +void ast_bridge_publish_enter(struct ast_bridge *bridge, struct ast_channel *chan); + +/*! + * \since 12 + * \brief Publish a bridge channel leave event + * + * \param bridge The bridge a channel left + * \param chan The channel that left the bridge + */ +void ast_bridge_publish_leave(struct ast_bridge *bridge, struct ast_channel *chan); + +/*! + * \brief Build a JSON object from a \ref ast_bridge_snapshot. + * \return JSON object representing bridge snapshot. + * \return \c NULL on error + */ +struct ast_json *ast_bridge_snapshot_to_json(const struct ast_bridge_snapshot *snapshot); + +/*! + * \brief Dispose of the stasis bridging topics and message types + */ +void ast_stasis_bridging_shutdown(void); + +/*! + * \brief Initialize the stasis bridging topic and message types + * \retval 0 on success + * \retval -1 on failure + */ +int ast_stasis_bridging_init(void); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* _STASIS_BRIDGING_H */ |