[asterisk-commits] rmudgett: branch group/bridge_construction r385036 - in /team/group/bridge_co...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Apr 8 15:43:03 CDT 2013
Author: rmudgett
Date: Mon Apr 8 15:42:59 2013
New Revision: 385036
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=385036
Log:
Add hooks for successful bridge join and leave.
Modified:
team/group/bridge_construction/include/asterisk/bridging_features.h
team/group/bridge_construction/main/bridging.c
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=385036&r1=385035&r2=385036
==============================================================================
--- team/group/bridge_construction/include/asterisk/bridging_features.h (original)
+++ team/group/bridge_construction/include/asterisk/bridging_features.h Mon Apr 8 15:42:59 2013
@@ -197,6 +197,10 @@
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 */
@@ -358,6 +362,66 @@
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
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=385036&r1=385035&r2=385036
==============================================================================
--- team/group/bridge_construction/main/bridging.c (original)
+++ team/group/bridge_construction/main/bridging.c Mon Apr 8 15:42:59 2013
@@ -2156,6 +2156,76 @@
ast_bridge_channel_unlock(bridge_channel);
}
+/*!
+ * \internal
+ * \brief Handle bridge channel join event.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Which channel is joining.
+ *
+ * \return Nothing
+ */
+static void bridge_channel_handle_join(struct ast_bridge_channel *bridge_channel)
+{
+ struct ast_bridge_features *features;
+
+ features = bridge_channel->features;
+ if (features) {
+ struct ast_bridge_hook *hook;
+ struct ao2_iterator iter;
+
+ /* Run any join hooks. */
+ iter = ao2_iterator_init(features->join_hooks, AO2_ITERATOR_UNLINK);
+ hook = ao2_iterator_next(&iter);
+ if (hook) {
+ bridge_channel_suspend(bridge_channel);
+ ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
+ do {
+ hook->callback(bridge_channel->bridge, bridge_channel, hook->hook_pvt);
+ ao2_ref(hook, -1);
+ } while ((hook = ao2_iterator_next(&iter)));
+ ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
+ bridge_channel_unsuspend(bridge_channel);
+ }
+ ao2_iterator_destroy(&iter);
+ }
+}
+
+/*!
+ * \internal
+ * \brief Handle bridge channel leave event.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Which channel is leaving.
+ *
+ * \return Nothing
+ */
+static void bridge_channel_handle_leave(struct ast_bridge_channel *bridge_channel)
+{
+ struct ast_bridge_features *features;
+
+ features = bridge_channel->features;
+ if (features) {
+ struct ast_bridge_hook *hook;
+ struct ao2_iterator iter;
+
+ /* Run any leave hooks. */
+ iter = ao2_iterator_init(features->leave_hooks, AO2_ITERATOR_UNLINK);
+ hook = ao2_iterator_next(&iter);
+ if (hook) {
+ bridge_channel_suspend(bridge_channel);
+ ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
+ do {
+ hook->callback(bridge_channel->bridge, bridge_channel, hook->hook_pvt);
+ ao2_ref(hook, -1);
+ } while ((hook = ao2_iterator_next(&iter)));
+ ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
+ bridge_channel_unsuspend(bridge_channel);
+ }
+ ao2_iterator_destroy(&iter);
+ }
+}
+
/*! \brief Join a channel to a bridge and handle anything the bridge may want us to do */
static void bridge_channel_join(struct ast_bridge_channel *bridge_channel)
{
@@ -2179,25 +2249,29 @@
bridge_channel_push(bridge_channel);
bridge_reconfigured(bridge_channel->bridge);
- /*
- * Indicate a source change since this channel is entering the
- * bridge system only if the bridge technology is not MULTIMIX
- * capable. The MULTIMIX technology has already done it.
- */
- if (!(bridge_channel->bridge->technology->capabilities
- & AST_BRIDGE_CAPABILITY_MULTIMIX)) {
- ast_indicate(bridge_channel->chan, AST_CONTROL_SRCCHANGE);
- }
-
- /* Wait for something to do. */
- ast_bridge_unlock(bridge_channel->bridge);
- while (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
- /* Update bridge pointer on channel */
- ast_channel_internal_bridge_set(bridge_channel->chan, bridge_channel->bridge);
-
- bridge_channel_wait(bridge_channel);
- }
- ast_bridge_channel_lock_bridge(bridge_channel);
+ if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
+ /*
+ * Indicate a source change since this channel is entering the
+ * bridge system only if the bridge technology is not MULTIMIX
+ * capable. The MULTIMIX technology has already done it.
+ */
+ if (!(bridge_channel->bridge->technology->capabilities
+ & AST_BRIDGE_CAPABILITY_MULTIMIX)) {
+ ast_indicate(bridge_channel->chan, AST_CONTROL_SRCCHANGE);
+ }
+
+ ast_bridge_unlock(bridge_channel->bridge);
+ bridge_channel_handle_join(bridge_channel);
+ while (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
+ /* Update bridge pointer on channel */
+ ast_channel_internal_bridge_set(bridge_channel->chan, bridge_channel->bridge);
+
+ /* Wait for something to do. */
+ bridge_channel_wait(bridge_channel);
+ }
+ bridge_channel_handle_leave(bridge_channel);
+ ast_bridge_channel_lock_bridge(bridge_channel);
+ }
bridge_channel_pull(bridge_channel);
bridge_reconfigured(bridge_channel->bridge);
@@ -3198,6 +3272,52 @@
return res;
}
+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)
+{
+ struct ast_bridge_hook *hook;
+ int res;
+
+ /* Allocate new hook and setup it's various variables */
+ hook = bridge_hook_generic(sizeof(*hook), callback, hook_pvt, destructor,
+ remove_on_pull);
+ if (!hook) {
+ return -1;
+ }
+
+ /* Once done we put it in the container. */
+ res = ao2_link(features->join_hooks, hook) ? 0 : -1;
+ ao2_ref(hook, -1);
+
+ return res;
+}
+
+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)
+{
+ struct ast_bridge_hook *hook;
+ int res;
+
+ /* Allocate new hook and setup it's various variables */
+ hook = bridge_hook_generic(sizeof(*hook), callback, hook_pvt, destructor,
+ remove_on_pull);
+ if (!hook) {
+ return -1;
+ }
+
+ /* Once done we put it in the container. */
+ res = ao2_link(features->leave_hooks, hook) ? 0 : -1;
+ ao2_ref(hook, -1);
+
+ return res;
+}
+
void ast_bridge_features_set_talk_detector(struct ast_bridge_features *features,
ast_bridge_talking_indicate_callback talker_cb,
ast_bridge_talking_indicate_destructor talker_destructor,
@@ -3412,6 +3532,8 @@
hooks_remove_on_pull_container(features->dtmf_hooks);
hooks_remove_on_pull_container(features->hangup_hooks);
+ hooks_remove_on_pull_container(features->join_hooks);
+ hooks_remove_on_pull_container(features->leave_hooks);
hooks_remove_on_pull_heap(features->interval_hooks);
}
@@ -3488,6 +3610,20 @@
return -1;
}
+ /* Initialize the join hooks container */
+ features->join_hooks = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL,
+ NULL);
+ if (!features->join_hooks) {
+ return -1;
+ }
+
+ /* Initialize the leave hooks container */
+ features->leave_hooks = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL,
+ NULL);
+ if (!features->leave_hooks) {
+ return -1;
+ }
+
/* Initialize the interval hooks heap */
features->interval_hooks = ast_heap_create(8, interval_hook_time_cmp,
offsetof(struct ast_bridge_hook, parms.timer.heap_index));
@@ -3527,6 +3663,14 @@
features->talker_destructor_cb(features->talker_pvt_data);
features->talker_pvt_data = NULL;
}
+
+ /* Destroy the leave hooks container. */
+ ao2_cleanup(features->leave_hooks);
+ features->leave_hooks = NULL;
+
+ /* Destroy the join hooks container. */
+ ao2_cleanup(features->join_hooks);
+ features->join_hooks = NULL;
/* Destroy the hangup hooks container. */
ao2_cleanup(features->hangup_hooks);
More information about the asterisk-commits
mailing list