[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