summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/asterisk/_private.h18
-rw-r--r--include/asterisk/abstract_jb.h28
-rw-r--r--include/asterisk/bridging.h1242
-rw-r--r--include/asterisk/bridging_basic.h107
-rw-r--r--include/asterisk/bridging_features.h476
-rw-r--r--include/asterisk/bridging_roles.h135
-rw-r--r--include/asterisk/bridging_technology.h116
-rw-r--r--include/asterisk/ccss.h10
-rw-r--r--include/asterisk/channel.h76
-rw-r--r--include/asterisk/config_options.h10
-rw-r--r--include/asterisk/core_local.h98
-rw-r--r--include/asterisk/core_unreal.h191
-rw-r--r--include/asterisk/frame.h2
-rw-r--r--include/asterisk/framehook.h2
-rw-r--r--include/asterisk/manager.h57
-rw-r--r--include/asterisk/parking.h184
-rw-r--r--include/asterisk/rtp_engine.h28
-rw-r--r--include/asterisk/stasis_bridging.h238
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 */