[asterisk-commits] rmudgett: branch group/bridge_construction r383793 - in /team/group/bridge_co...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Mar 25 17:28:57 CDT 2013
Author: rmudgett
Date: Mon Mar 25 17:28:53 2013
New Revision: 383793
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=383793
Log:
Bridge API Enhancements - add subclassing ability to ast_bridge
* Added ability to subclass struct ast_bridge to create new bridge types.
Parking, Queues, and ConfBridge are examples of subclassing ast_bridge.
* Made callers of ast_bridge_features_init(), ast_bridge_hangup_hook(),
ast_bridge_dtmf_hook(), and ast_bridge_interval_hook() pay attention to
the return value.
* Made bridging code use the ast_bridge_lock(), ast_bridge_unlock(),
ast_bridge_trylock(), ast_bridge_channel_lock(),
ast_bridge_channel_unlock(), and ast_bridge_channel_trylock() wrapper
functions to easily find where they are used.
* Converted the DTMF, hangup, and interval hooks to use ao2 objects and
ao2 containers.
* Made remove marked hooks on a channel when it is pulled from the bridge.
(closes issue ASTERISK-21270)
Reported by: Matt Jordan
Modified:
team/group/bridge_construction/apps/app_bridgewait.c
team/group/bridge_construction/apps/app_confbridge.c
team/group/bridge_construction/apps/confbridge/conf_config_parser.c
team/group/bridge_construction/bridges/bridge_builtin_features.c
team/group/bridge_construction/bridges/bridge_builtin_interval_features.c
team/group/bridge_construction/bridges/bridge_softmix.c
team/group/bridge_construction/include/asterisk/bridging.h
team/group/bridge_construction/include/asterisk/bridging_features.h
team/group/bridge_construction/main/bridging.c
team/group/bridge_construction/main/channel.c
team/group/bridge_construction/main/features.c
Modified: team/group/bridge_construction/apps/app_bridgewait.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/apps/app_bridgewait.c?view=diff&rev=383793&r1=383792&r2=383793
==============================================================================
--- team/group/bridge_construction/apps/app_bridgewait.c (original)
+++ team/group/bridge_construction/apps/app_bridgewait.c Mon Mar 25 17:28:53 2013
@@ -140,7 +140,7 @@
/* Limits struct holds time as milliseconds, so muliply 1000x */
hold_limits.duration *= 1000;
- ast_bridge_features_set_limits(features, &hold_limits);
+ ast_bridge_features_set_limits(features, &hold_limits, 1 /* remove_on_pull */);
ast_bridge_features_limits_destroy(&hold_limits);
return 0;
@@ -195,10 +195,10 @@
ast_mutex_lock(&bridgewait_lock);
if (!holding_bridge) {
- holding_bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_HOLDING, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM);
+ holding_bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_HOLDING,
+ AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM);
}
ast_mutex_unlock(&bridgewait_lock);
-
if (!holding_bridge) {
ast_log(LOG_ERROR, "Could not create holding bridge for '%s'.\n", ast_channel_name(chan));
return -1;
@@ -207,7 +207,10 @@
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
- ast_bridge_features_init(&chan_features);
+ if (ast_bridge_features_init(&chan_features)) {
+ ast_bridge_features_cleanup(&chan_features);
+ return -1;
+ }
if (args.options) {
char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
Modified: team/group/bridge_construction/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/apps/app_confbridge.c?view=diff&rev=383793&r1=383792&r2=383793
==============================================================================
--- team/group/bridge_construction/apps/app_confbridge.c (original)
+++ team/group/bridge_construction/apps/app_confbridge.c Mon Mar 25 17:28:53 2013
@@ -1285,8 +1285,9 @@
conf_bridge_profile_copy(&conference->b_profile, &user->b_profile);
/* Create an actual bridge that will do the audio mixing */
- if (!(conference->bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_MULTIMIX,
- AST_BRIDGE_FLAG_MASQUERADE_ONLY))) {
+ conference->bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_MULTIMIX,
+ AST_BRIDGE_FLAG_MASQUERADE_ONLY);
+ if (!conference->bridge) {
ao2_ref(conference, -1);
conference = NULL;
ao2_unlock(conference_bridges);
@@ -1644,10 +1645,14 @@
AST_APP_ARG(u_profile_name);
AST_APP_ARG(menu_name);
);
- ast_bridge_features_init(&user.features);
if (ast_channel_state(chan) != AST_STATE_UP) {
ast_answer(chan);
+ }
+
+ if (ast_bridge_features_init(&user.features)) {
+ res = -1;
+ goto confbridge_cleanup;
}
if (ast_strlen_zero(data)) {
Modified: team/group/bridge_construction/apps/confbridge/conf_config_parser.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/apps/confbridge/conf_config_parser.c?view=diff&rev=383793&r1=383792&r2=383793
==============================================================================
--- team/group/bridge_construction/apps/confbridge/conf_config_parser.c (original)
+++ team/group/bridge_construction/apps/confbridge/conf_config_parser.c Mon Mar 25 17:28:53 2013
@@ -2053,7 +2053,8 @@
ao2_ref(menu, +1);
pvt->menu = menu;
- ast_bridge_dtmf_hook(&user->features, pvt->menu_entry.dtmf, menu_hook_callback, pvt, menu_hook_destroy);
+ ast_bridge_dtmf_hook(&user->features, pvt->menu_entry.dtmf, menu_hook_callback,
+ pvt, menu_hook_destroy, 0);
}
ao2_unlock(menu);
Modified: team/group/bridge_construction/bridges/bridge_builtin_features.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/bridges/bridge_builtin_features.c?view=diff&rev=383793&r1=383792&r2=383793
==============================================================================
--- team/group/bridge_construction/bridges/bridge_builtin_features.c (original)
+++ team/group/bridge_construction/bridges/bridge_builtin_features.c Mon Mar 25 17:28:53 2013
@@ -269,16 +269,42 @@
/* Get a channel that is the destination we wish to call */
peer = dial_transfer(bridge_channel->chan, exten, context);
if (!peer) {
+/* BUGBUG beeperr needs to be configurable from features.conf */
ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
return 0;
}
-/* BUGBUG we need to wait for Party C (peer) to answer before dumping into the transient B-C bridge. */
+/* BUGBUG bridging API features does not support features.conf featuremap */
+/* BUGBUG bridging API features does not support the features.conf atxfer bounce between C & B channels */
+ /* Setup a DTMF menu to control the transfer. */
+ if (ast_bridge_features_init(&caller_features)
+ || ast_bridge_hangup_hook(&caller_features,
+ attended_transfer_complete, &transfer_code, NULL, 0)
+ || ast_bridge_dtmf_hook(&caller_features,
+ attended_transfer && !ast_strlen_zero(attended_transfer->abort)
+ ? attended_transfer->abort : "*1",
+ attended_transfer_abort, &transfer_code, NULL, 0)
+ || ast_bridge_dtmf_hook(&caller_features,
+ attended_transfer && !ast_strlen_zero(attended_transfer->complete)
+ ? attended_transfer->complete : "*2",
+ attended_transfer_complete, &transfer_code, NULL, 0)
+ || ast_bridge_dtmf_hook(&caller_features,
+ attended_transfer && !ast_strlen_zero(attended_transfer->threeway)
+ ? attended_transfer->threeway : "*3",
+ attended_transfer_threeway, &transfer_code, NULL, 0)) {
+ ast_bridge_features_cleanup(&caller_features);
+ ast_hangup(peer);
+/* BUGBUG beeperr needs to be configurable from features.conf */
+ ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
+ return 0;
+ }
/* Create a bridge to use to talk to the person we are calling */
- attended_bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX,
+ attended_bridge = ast_bridge_base_new(
+ AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX,
AST_BRIDGE_FLAG_DISSOLVE_HANGUP);
if (!attended_bridge) {
+ ast_bridge_features_cleanup(&caller_features);
ast_hangup(peer);
/* BUGBUG beeperr needs to be configurable from features.conf */
ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
@@ -289,29 +315,12 @@
/* BUGBUG we should impart the peer as an independent and move it to the original bridge. */
if (ast_bridge_impart(attended_bridge, peer, NULL, NULL, 0)) {
ast_bridge_destroy(attended_bridge);
+ ast_bridge_features_cleanup(&caller_features);
ast_hangup(peer);
+/* BUGBUG beeperr needs to be configurable from features.conf */
ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
return 0;
}
-
- /* Setup a DTMF menu to control the transfer. */
- ast_bridge_features_init(&caller_features);
-/* BUGBUG bridging API features does not support features.conf featuremap */
-/* BUGBUG bridging API features does not support the features.conf atxfer bounce between C & B channels */
- ast_bridge_hangup_hook(&caller_features,
- attended_transfer_complete, &transfer_code, NULL);
- ast_bridge_dtmf_hook(&caller_features,
- attended_transfer && !ast_strlen_zero(attended_transfer->abort)
- ? attended_transfer->abort : "*1",
- attended_transfer_abort, &transfer_code, NULL);
- ast_bridge_dtmf_hook(&caller_features,
- attended_transfer && !ast_strlen_zero(attended_transfer->complete)
- ? attended_transfer->complete : "*2",
- attended_transfer_complete, &transfer_code, NULL);
- ast_bridge_dtmf_hook(&caller_features,
- attended_transfer && !ast_strlen_zero(attended_transfer->threeway)
- ? attended_transfer->threeway : "*3",
- attended_transfer_threeway, &transfer_code, NULL);
/*
* For the caller we want to join the bridge in a blocking
@@ -329,8 +338,8 @@
}
/* Now that all channels are out of it we can destroy the bridge and the feature structures */
+ ast_bridge_destroy(attended_bridge);
ast_bridge_features_cleanup(&caller_features);
- ast_bridge_destroy(attended_bridge);
xfer_failed = -1;
switch (transfer_code) {
Modified: team/group/bridge_construction/bridges/bridge_builtin_interval_features.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/bridges/bridge_builtin_interval_features.c?view=diff&rev=383793&r1=383792&r2=383793
==============================================================================
--- team/group/bridge_construction/bridges/bridge_builtin_interval_features.c (original)
+++ team/group/bridge_construction/bridges/bridge_builtin_interval_features.c Mon Mar 25 17:28:53 2013
@@ -125,11 +125,7 @@
limits_interval_playback(bridge, bridge_channel, limits, limits->warning_sound);
}
- if (limits->frequency) {
- ast_bridge_interval_hook_update(bridge_channel, limits->frequency);
- }
-
- return !limits->frequency ? -1 : 0;
+ return !limits->frequency ? -1 : limits->frequency;
}
static void copy_bridge_features_limits(struct ast_bridge_features_limits *dst, struct ast_bridge_features_limits *src)
@@ -144,7 +140,7 @@
ast_string_field_set(dst, connect_sound, src->connect_sound);
}
-static int bridge_builtin_set_limits(struct ast_bridge_features *features, struct ast_bridge_features_limits *limits)
+static int bridge_builtin_set_limits(struct ast_bridge_features *features, struct ast_bridge_features_limits *limits, int remove_on_pull)
{
struct ast_bridge_features_limits *feature_limits;
@@ -169,8 +165,9 @@
copy_bridge_features_limits(feature_limits, limits);
features->limits = feature_limits;
+/* BUGBUG feature interval hooks need to be reimplemented to be more stand alone. */
if (ast_bridge_interval_hook(features, feature_limits->duration,
- bridge_features_duration_callback, feature_limits, NULL)) {
+ bridge_features_duration_callback, feature_limits, NULL, remove_on_pull)) {
ast_log(LOG_ERROR, "Failed to schedule the duration limiter to the bridge channel.\n");
return -1;
}
@@ -179,14 +176,14 @@
if (!ast_strlen_zero(feature_limits->connect_sound)) {
if (ast_bridge_interval_hook(features, 1,
- bridge_features_connect_callback, feature_limits, NULL)) {
+ bridge_features_connect_callback, feature_limits, NULL, remove_on_pull)) {
ast_log(LOG_WARNING, "Failed to schedule connect sound to the bridge channel.\n");
}
}
if (feature_limits->warning && feature_limits->warning < feature_limits->duration) {
if (ast_bridge_interval_hook(features, feature_limits->duration - feature_limits->warning,
- bridge_features_warning_callback, feature_limits, NULL)) {
+ bridge_features_warning_callback, feature_limits, NULL, remove_on_pull)) {
ast_log(LOG_WARNING, "Failed to schedule warning sound playback to the bridge channel.\n");
}
}
Modified: team/group/bridge_construction/bridges/bridge_softmix.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/bridges/bridge_softmix.c?view=diff&rev=383793&r1=383792&r2=383793
==============================================================================
--- team/group/bridge_construction/bridges/bridge_softmix.c (original)
+++ team/group/bridge_construction/bridges/bridge_softmix.c Mon Mar 25 17:28:53 2013
@@ -845,17 +845,17 @@
}
stat_iteration_counter--;
- ao2_unlock(bridge);
+ ast_bridge_unlock(bridge);
/* cleanup any translation frame data from the previous mixing iteration. */
softmix_translate_helper_cleanup(&trans_helper);
/* Wait for the timing source to tell us to wake up and get things done */
ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
if (ast_timer_ack(timer, 1) < 0) {
ast_log(LOG_ERROR, "Failed to acknowledge timer in softmix bridge.\n");
- ao2_lock(bridge);
+ ast_bridge_lock(bridge);
goto softmix_cleanup;
}
- ao2_lock(bridge);
+ ast_bridge_lock(bridge);
/* make sure to detect mixing interval changes if they occur. */
if (bridge->internal_mixing_interval && (bridge->internal_mixing_interval != softmix_data->internal_mixing_interval)) {
@@ -887,7 +887,7 @@
struct ast_bridge *bridge = data;
struct softmix_bridge_data *softmix_data;
- ao2_lock(bridge);
+ ast_bridge_lock(bridge);
if (bridge->callid) {
ast_callid_threadassoc_add(bridge->callid);
}
@@ -898,13 +898,13 @@
while (!softmix_data->stop) {
if (!bridge->num_active) {
/* Wait for something to happen to the bridge. */
- ao2_unlock(bridge);
+ ast_bridge_unlock(bridge);
ast_mutex_lock(&softmix_data->lock);
if (!softmix_data->stop) {
ast_cond_wait(&softmix_data->cond, &softmix_data->lock);
}
ast_mutex_unlock(&softmix_data->lock);
- ao2_lock(bridge);
+ ast_bridge_lock(bridge);
continue;
}
@@ -913,13 +913,13 @@
* A mixing error occurred. Sleep and try again later so we
* won't flood the logs.
*/
- ao2_unlock(bridge);
+ ast_bridge_unlock(bridge);
sleep(1);
- ao2_lock(bridge);
- }
- }
-
- ao2_unlock(bridge);
+ ast_bridge_lock(bridge);
+ }
+ }
+
+ ast_bridge_unlock(bridge);
ast_debug(1, "Stopping mixing thread for bridge %p\n", bridge);
Modified: team/group/bridge_construction/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/include/asterisk/bridging.h?view=diff&rev=383793&r1=383792&r2=383793
==============================================================================
--- team/group/bridge_construction/include/asterisk/bridging.h (original)
+++ team/group/bridge_construction/include/asterisk/bridging.h Mon Mar 25 17:28:53 2013
@@ -118,6 +118,7 @@
* \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 */
@@ -128,7 +129,21 @@
struct ast_channel *swap;
/*! Bridge this channel is participating in */
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;
+ /*!
+ * \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;
@@ -214,15 +229,125 @@
};
/*!
+ * \brief Destroy the bridge.
+ *
+ * \param self Bridge to operate upon.
+ *
+ * \return Nothing
+ */
+typedef void (*ast_bridge_destructor_fn)(struct ast_bridge *self);
+
+/*!
+ * \brief Can this channel be pushed into the bridge.
+ *
+ * \param self Bridge to operate upon.
+ * \param bridge_channel Bridge channel wanting to push.
+ * \param swap Bridge channel to swap places with if not NULL.
+ *
+ * \note On entry, self is already locked.
+ *
+ * \retval TRUE if can push this channel into the bridge.
+ */
+typedef int (*ast_bridge_can_push_channel_fn)(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
+
+/*!
+ * \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
+ */
+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 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;
+ /*! TRUE if can push the bridge channel into the bridge. */
+ ast_bridge_can_push_channel_fn can_push;
+ /*! 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;
+};
+
+/*!
* \brief Structure that contains information about a bridge
*/
struct ast_bridge {
+ /*! Bridge virtual method table. */
+ const struct ast_bridge_methods *v_table;
+ /*! 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;
/*! Number of channels participating in the bridge */
unsigned int num_channels;
/*! Number of active channels in the bridge. */
unsigned int num_active;
- /*! The video mode this bridge is using */
- struct ast_bridge_video_mode video_mode;
/*!
* \brief Count of the active temporary requests to inhibit bridge merges.
* Zero if merges are allowed.
@@ -241,26 +366,53 @@
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;
- /*! 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 *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;
};
/*!
- * \brief Create a new bridge
- *
+ * \internal
+ * \brief Allocate the bridge class object memory.
+ * \since 12.0.0
+ *
+ * \param size Size of the bridge class structure to allocate.
+ * \param v_table Bridge class virtual method table.
+ *
+ * \retval bridge on success.
+ * \retval NULL on error.
+ */
+struct ast_bridge *ast_bridge_alloc(size_t size, const struct ast_bridge_methods *v_table);
+
+/*! \brief Bridge base class virtual method table. */
+extern struct ast_bridge_methods ast_bridge_base_v_table;
+
+/*!
+ * \brief Initialize the base class of the bridge.
+ *
+ * \param self Bridge to operate upon. (Tollerates 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, 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
+ *
* \retval a pointer to a new bridge on success
* \retval NULL on failure
*
@@ -268,13 +420,27 @@
*
* \code
* struct ast_bridge *bridge;
- * bridge = ast_bridge_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.
- */
-struct ast_bridge *ast_bridge_new(uint32_t capabilities, int flags);
+ * bridge = ast_bridge_base_new(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_new(uint32_t capabilities, 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.
@@ -335,9 +501,19 @@
* 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
@@ -558,6 +734,46 @@
int ast_bridge_unsuspend(struct ast_bridge *bridge, struct ast_channel *chan);
/*!
+ * \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 Set bridge channel state to leave bridge (if not leaving already) with no lock.
*
* \param bridge_channel Channel to change the state on
Modified: team/group/bridge_construction/include/asterisk/bridging_features.h
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/include/asterisk/bridging_features.h?view=diff&rev=383793&r1=383792&r2=383793
==============================================================================
--- team/group/bridge_construction/include/asterisk/bridging_features.h (original)
+++ team/group/bridge_construction/include/asterisk/bridging_features.h Mon Mar 25 17:28:53 2013
@@ -32,16 +32,19 @@
enum ast_bridge_feature_flags {
/*! 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),
- /*! This channel leaves the bridge if all participants have this flag set. */
- AST_BRIDGE_FLAG_LONELY = (1 << 2),
+ 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 can be moved to another bridge only by masquerade (ConfBridge) */
AST_BRIDGE_FLAG_MASQUERADE_ONLY = (1 << 5),
+
+ /*! This channel leaves the bridge if all participants have this flag set. */
+ AST_BRIDGE_FLAG_LONELY = (1 << 10),
};
/*! \brief Built in DTMF features */
@@ -103,6 +106,12 @@
* \param bridge_channel Channel executing the feature
* \param hook_pvt Private data passed in when the hook was created
*
+ * 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.
*/
@@ -149,14 +158,14 @@
/*! Time at which the hook should actually trip */
struct timeval trip_time;
/*! Heap index for interval hook */
- ssize_t __heap_index;
+ 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 ast_bridge_hook needs to be turned into ao2 objects so bridge push/pulls can add/remove hooks */
+/* 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 */
@@ -167,6 +176,8 @@
ast_bridge_hook_pvt_destructor destructor;
/*! Unique data that was passed into us */
void *hook_pvt;
+ /*! 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. */
@@ -182,13 +193,10 @@
* \brief Structure that contains features information
*/
struct ast_bridge_features {
-/* BUGBUG dtmf_hooks needs to be an ao2_container so it would be possible to iterate without keeping a lock */
/*! Attached DTMF feature hooks */
- AST_LIST_HEAD_NOLOCK(, ast_bridge_hook) dtmf_hooks;
-/* BUGBUG hangup_hooks needs to be an ao2_container so it would be possible to iterate without keeping a lock */
- /*! Attached hangup interception hooks */
- AST_LIST_HEAD_NOLOCK(, ast_bridge_hook) hangup_hooks;
-/* BUGBUG use of interval_hooks needs to be made ao2 safe */
+ struct ao2_container *dtmf_hooks;
+ /*! Attached hangup interception hooks container */
+ struct ao2_container *hangup_hooks;
/*! Attached interval hooks */
struct ast_heap *interval_hooks;
/*! Used to determine when interval based features should be checked */
@@ -300,6 +308,18 @@
int ast_bridge_features_unregister(enum ast_bridge_builtin_feature feature);
/*!
+ * \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
@@ -317,7 +337,7 @@
* 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, void *callback);
+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
@@ -344,16 +364,17 @@
* \param callback Function to execute upon activation
* \param hook_pvt Unique data
* \param destructor Optional destructor callback for hook_pvt data
- *
- * \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);
+ * \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
@@ -363,7 +384,8 @@
int ast_bridge_hangup_hook(struct ast_bridge_features *features,
ast_bridge_hook_callback callback,
void *hook_pvt,
- ast_bridge_hook_pvt_destructor destructor);
+ ast_bridge_hook_pvt_destructor destructor,
+ int remove_on_pull);
/*!
* \brief Attach a DTMF hook to a bridge features structure
@@ -373,16 +395,17 @@
* \param callback Function to execute upon activation
* \param hook_pvt Unique data
* \param destructor Optional destructor callback for hook_pvt data
- *
- * \retval 0 on success
- * \retval -1 on failure
- *
- * Example usage:
- *
- * \code
- * struct ast_bridge_features features;
- * ast_bridge_features_init(&features);
- * ast_bridge_dtmf_hook(&features, "#", pound_callback, NULL, NULL);
+ * \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_dtmf_hook(&features, "#", pound_callback, NULL, NULL, 0);
* \endcode
*
* This makes the bridging core call pound_callback if a channel that has this
@@ -393,7 +416,8 @@
const char *dtmf,
ast_bridge_hook_callback callback,
void *hook_pvt,
- ast_bridge_hook_pvt_destructor destructor);
+ ast_bridge_hook_pvt_destructor destructor,
+ int remove_on_pull);
/*!
* \brief attach an interval hook to a bridge features structure
@@ -403,14 +427,15 @@
* \param callback Function to execute upon activation
* \param hook_pvt Unique data
* \param destructor Optional destructor callback for hook_pvt data
- *
- * \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);
+ * \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
@@ -420,29 +445,8 @@
unsigned int interval,
ast_bridge_hook_callback callback,
void *hook_pvt,
- ast_bridge_hook_pvt_destructor destructor);
-
-/*!
- * \brief Update the interval on an interval hook that is currently executing a callback
- *
- * \param bridge_channel The bridge channel that is executing the callback
- * \param interval The new interval value or 0 to remove the interval hook
- *
- * \retval 0 on success
- * \retval 1 on failure
- *
- * Example usage:
- *
- * \code
- * ast_bridge_interval_hook_update(bridge_channel, 10000);
- * \endcode
- *
- * This updates the executing interval hook so that it will be triggered next in 10 seconds.
- *
- * \note This can only be called from the context of the interval hook callback itself. If this
- * is called outside the callback then behavior is undefined.
- */
-int ast_bridge_interval_hook_update(struct ast_bridge_channel *bridge_channel, unsigned int interval);
+ ast_bridge_hook_pvt_destructor destructor,
+ int remove_on_pull);
/*!
* \brief Set a callback on the features structure to receive talking notifications on.
@@ -467,23 +471,29 @@
* \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
- *
- * \retval 0 on success
- * \retval -1 on failure
- *
- * Example usage:
- *
- * \code
- * struct ast_bridge_features features;
- * ast_bridge_features_init(&features);
- * ast_bridge_features_enable(&features, AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, NULL, NULL);
+ * \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_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, ast_bridge_hook_pvt_destructor destructor);
+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
@@ -510,6 +520,7 @@
*
* \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
@@ -521,7 +532,7 @@
* struct ast_bridge_features_limits limits;
* ast_bridge_features_init(&features);
* ast_bridge_features_limits_construct(&limits);
- * ast_bridge_features_set_limits(&features, &limits);
+ * ast_bridge_features_set_limits(&features, &limits, 0);
* ast_bridge_features_limits_destroy(&limits);
* \endcode
*
@@ -530,7 +541,7 @@
* \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 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 features structure
Modified: team/group/bridge_construction/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/main/bridging.c?view=diff&rev=383793&r1=383792&r2=383793
==============================================================================
--- team/group/bridge_construction/main/bridging.c (original)
+++ team/group/bridge_construction/main/bridging.c Mon Mar 25 17:28:53 2013
@@ -66,6 +66,7 @@
static void cleanup_video_mode(struct ast_bridge *bridge);
static int bridge_make_compatible(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
+static void bridge_features_remove_on_pull(struct ast_bridge_features *features);
/*! Default DTMF keys for built in features */
static char builtin_features_dtmf[AST_BRIDGE_BUILTIN_END][MAXIMUM_DTMF_FEATURE_STRING];
@@ -74,7 +75,7 @@
static void *builtin_features_handlers[AST_BRIDGE_BUILTIN_END];
/*! Function handlers for built in interval features */
-static void *builtin_interval_handlers[AST_BRIDGE_BUILTIN_INTERVAL_END];
+static ast_bridge_builtin_set_limits_fn builtin_interval_handlers[AST_BRIDGE_BUILTIN_INTERVAL_END];
[... 2026 lines stripped ...]
More information about the asterisk-commits
mailing list