[asterisk-commits] rmudgett: branch rmudgett/bridge_tasks r383630 - in /team/rmudgett/bridge_tas...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Mar 22 15:41:29 CDT 2013


Author: rmudgett
Date: Fri Mar 22 15:41:27 2013
New Revision: 383630

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=383630
Log:
* Remove marked feature hooks when a channel is pulled from the bridge.

* Add ability to specify if a hook is removed if the channel is pulled
from the bridge.

Modified:
    team/rmudgett/bridge_tasks/apps/app_bridgewait.c
    team/rmudgett/bridge_tasks/apps/confbridge/conf_config_parser.c
    team/rmudgett/bridge_tasks/bridges/bridge_builtin_features.c
    team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c
    team/rmudgett/bridge_tasks/include/asterisk/bridging_features.h
    team/rmudgett/bridge_tasks/main/bridging.c
    team/rmudgett/bridge_tasks/main/features.c

Modified: team/rmudgett/bridge_tasks/apps/app_bridgewait.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/apps/app_bridgewait.c?view=diff&rev=383630&r1=383629&r2=383630
==============================================================================
--- team/rmudgett/bridge_tasks/apps/app_bridgewait.c (original)
+++ team/rmudgett/bridge_tasks/apps/app_bridgewait.c Fri Mar 22 15:41:27 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);
 	ast_bridge_features_limits_destroy(&hold_limits);
 
 	return 0;

Modified: team/rmudgett/bridge_tasks/apps/confbridge/conf_config_parser.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/apps/confbridge/conf_config_parser.c?view=diff&rev=383630&r1=383629&r2=383630
==============================================================================
--- team/rmudgett/bridge_tasks/apps/confbridge/conf_config_parser.c (original)
+++ team/rmudgett/bridge_tasks/apps/confbridge/conf_config_parser.c Fri Mar 22 15:41:27 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/rmudgett/bridge_tasks/bridges/bridge_builtin_features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/bridges/bridge_builtin_features.c?view=diff&rev=383630&r1=383629&r2=383630
==============================================================================
--- team/rmudgett/bridge_tasks/bridges/bridge_builtin_features.c (original)
+++ team/rmudgett/bridge_tasks/bridges/bridge_builtin_features.c Fri Mar 22 15:41:27 2013
@@ -279,19 +279,19 @@
 	/* 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)
+			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)
+			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)
+			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)) {
+			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 */

Modified: team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c?view=diff&rev=383630&r1=383629&r2=383630
==============================================================================
--- team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c (original)
+++ team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c Fri Mar 22 15:41:27 2013
@@ -140,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;
 
@@ -167,7 +167,7 @@
 
 /* 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;
 	}
@@ -176,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/rmudgett/bridge_tasks/include/asterisk/bridging_features.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/include/asterisk/bridging_features.h?view=diff&rev=383630&r1=383629&r2=383630
==============================================================================
--- team/rmudgett/bridge_tasks/include/asterisk/bridging_features.h (original)
+++ team/rmudgett/bridge_tasks/include/asterisk/bridging_features.h Fri Mar 22 15:41:27 2013
@@ -165,7 +165,7 @@
 	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 */
@@ -176,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. */
@@ -306,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
@@ -323,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
@@ -350,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
@@ -369,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
@@ -379,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
@@ -399,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
@@ -409,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
@@ -426,7 +445,8 @@
 	unsigned int interval,
 	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 Set a callback on the features structure to receive talking notifications on.
@@ -451,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
@@ -494,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
@@ -505,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
  *
@@ -514,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/rmudgett/bridge_tasks/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/main/bridging.c?view=diff&rev=383630&r1=383629&r2=383630
==============================================================================
--- team/rmudgett/bridge_tasks/main/bridging.c (original)
+++ team/rmudgett/bridge_tasks/main/bridging.c Fri Mar 22 15:41:27 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];
 
 /*! Bridge manager service request */
 struct bridge_manager_request {
@@ -393,6 +394,7 @@
 	if (bridge->personality && bridge->personality->pull) {
 		bridge->personality->pull(bridge_channel);
 	}
+	bridge_features_remove_on_pull(bridge_channel->features);
 
 	bridge->reconfigured = 1;
 }
@@ -2583,7 +2585,7 @@
 	return 0;
 }
 
-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)
 {
 	if (ARRAY_LEN(builtin_interval_handlers) <= interval
 		|| builtin_interval_handlers[interval]) {
@@ -2635,11 +2637,16 @@
  * \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 hook on success.
  * \retval NULL on error.
  */
-static struct ast_bridge_hook *bridge_hook_generic(size_t size, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor)
+static struct ast_bridge_hook *bridge_hook_generic(size_t size,
+	ast_bridge_hook_callback callback,
+	void *hook_pvt,
+	ast_bridge_hook_pvt_destructor destructor,
+	int remove_on_pull)
 {
 	struct ast_bridge_hook *hook;
 
@@ -2649,6 +2656,7 @@
 		hook->callback = callback;
 		hook->destructor = destructor;
 		hook->hook_pvt = hook_pvt;
+		hook->remove_on_pull = remove_on_pull;
 	}
 
 	return hook;
@@ -2658,13 +2666,15 @@
 	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)
 {
 	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);
+	hook = bridge_hook_generic(sizeof(*hook), callback, hook_pvt, destructor,
+		remove_on_pull);
 	if (!hook) {
 		return -1;
 	}
@@ -2680,13 +2690,15 @@
 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)
 {
 	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);
+	hook = bridge_hook_generic(sizeof(*hook), callback, hook_pvt, destructor,
+		remove_on_pull);
 	if (!hook) {
 		return -1;
 	}
@@ -2712,7 +2724,8 @@
 	unsigned int interval,
 	ast_bridge_hook_callback callback,
 	void *hook_pvt,
-	ast_bridge_hook_pvt_destructor destructor)
+	ast_bridge_hook_pvt_destructor destructor,
+	int remove_on_pull)
 {
 	struct ast_bridge_hook *hook;
 	int res;
@@ -2730,7 +2743,8 @@
 	}
 
 	/* Allocate new hook and setup it's various variables */
-	hook = bridge_hook_generic(sizeof(*hook), callback, hook_pvt, destructor);
+	hook = bridge_hook_generic(sizeof(*hook), callback, hook_pvt, destructor,
+		remove_on_pull);
 	if (!hook) {
 		return -1;
 	}
@@ -2751,7 +2765,12 @@
 	return res ? -1 : 0;
 }
 
-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)
 {
 	if (ARRAY_LEN(builtin_features_handlers) <= feature
 		|| !builtin_features_handlers[feature]) {
@@ -2773,7 +2792,8 @@
 	 * The rest is basically pretty easy.  We create another hook
 	 * using the built in feature's DTMF callback.  Easy as pie.
 	 */
-	return ast_bridge_dtmf_hook(features, dtmf, builtin_features_handlers[feature], config, destructor);
+	return ast_bridge_dtmf_hook(features, dtmf, builtin_features_handlers[feature],
+		config, destructor, remove_on_pull);
 }
 
 int ast_bridge_features_limits_construct(struct ast_bridge_features_limits *limits)
@@ -2793,13 +2813,13 @@
 	ast_string_field_free_memory(limits);
 }
 
-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)
 {
 	if (builtin_interval_handlers[AST_BRIDGE_BUILTIN_INTERVAL_LIMITS]) {
-		int (*bridge_features_set_limits_callback)(struct ast_bridge_features *features, struct ast_bridge_features_limits *limits);
+		ast_bridge_builtin_set_limits_fn bridge_features_set_limits_callback;
 
 		bridge_features_set_limits_callback = builtin_interval_handlers[AST_BRIDGE_BUILTIN_INTERVAL_LIMITS];
-		return bridge_features_set_limits_callback(features, limits);
+		return bridge_features_set_limits_callback(features, limits, remove_on_pull);
 	}
 
 	ast_log(LOG_ERROR, "Attempted to set limits without an AST_BRIDGE_BUILTIN_INTERVAL_LIMITS callback registered.\n");
@@ -2810,6 +2830,101 @@
 {
 	ast_set_flag(&features->feature_flags, flag);
 	features->usable = 1;
+}
+
+/*!
+ * \internal
+ * \brief ao2 object match remove_on_pull hooks.
+ * \since 12.0.0
+ *
+ * \param obj Feature hook object.
+ * \param arg Not used
+ * \param flags Not used
+ *
+ * \retval CMP_MATCH if hook has remove_on_pull set.
+ * \retval 0 if not match.
+ */
+static int hook_remove_on_pull_match(void *obj, void *arg, int flags)
+{
+	struct ast_bridge_hook *hook = obj;
+
+	if (hook->remove_on_pull) {
+		return CMP_MATCH;
+	} else {
+		return 0;
+	}
+}
+
+/*!
+ * \internal
+ * \brief Remove all remove_on_pull hooks in the container.
+ * \since 12.0.0
+ *
+ * \param hooks Hooks container to work on.
+ *
+ * \return Nothing
+ */
+static void hooks_remove_on_pull_container(struct ao2_container *hooks)
+{
+	if (hooks) {
+		ao2_callback(hooks, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE,
+			hook_remove_on_pull_match, NULL);
+	}
+}
+
+/*!
+ * \internal
+ * \brief Remove all remove_on_pull hooks in the heap.
+ * \since 12.0.0
+ *
+ * \param hooks Hooks heap to work on.
+ *
+ * \return Nothing
+ */
+static void hooks_remove_on_pull_heap(struct ast_heap *hooks)
+{
+	struct ast_bridge_hook *hook;
+	int changed;
+
+	if (!hooks) {
+		return;
+	}
+
+	ast_heap_wrlock(hooks);
+	do {
+		int idx;
+
+		changed = 0;
+		for (idx = ast_heap_size(hooks); idx; --idx) {
+			hook = ast_heap_peek(hooks, idx);
+			if (hook->remove_on_pull) {
+				ast_heap_remove(hooks, hook);
+				ao2_ref(hook, -1);
+				changed = 1;
+			}
+		}
+	} while (changed);
+	ast_heap_unlock(hooks);
+}
+
+/*!
+ * \internal
+ * \brief Remove marked bridge channel feature hooks.
+ * \since 12.0.0
+ *
+ * \param features Bridge featues structure
+ *
+ * \return Nothing
+ */
+static void bridge_features_remove_on_pull(struct ast_bridge_features *features)
+{
+	if (!features) {
+		return;
+	}
+
+	hooks_remove_on_pull_container(features->dtmf_hooks);
+	hooks_remove_on_pull_container(features->hangup_hooks);
+	hooks_remove_on_pull_heap(features->interval_hooks);
 }
 
 static int interval_hook_time_cmp(void *a, void *b)

Modified: team/rmudgett/bridge_tasks/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/main/features.c?view=diff&rev=383630&r1=383629&r2=383630
==============================================================================
--- team/rmudgett/bridge_tasks/main/features.c (original)
+++ team/rmudgett/bridge_tasks/main/features.c Fri Mar 22 15:41:27 2013
@@ -4259,12 +4259,12 @@
 		dtmf = ast_find_call_feature("blindxfer");
 		if (dtmf && !ast_strlen_zero(dtmf->exten)) {
 /* BUGBUG need to supply a blind transfer structure and destructor to use other than defaults */
-			res |= ast_bridge_features_enable(features, AST_BRIDGE_BUILTIN_BLINDTRANSFER, dtmf->exten, NULL, NULL);
+			res |= ast_bridge_features_enable(features, AST_BRIDGE_BUILTIN_BLINDTRANSFER, dtmf->exten, NULL, NULL, 0);
 		}
 		dtmf = ast_find_call_feature("atxfer");
 		if (dtmf && !ast_strlen_zero(dtmf->exten)) {
 /* BUGBUG need to supply an attended transfer structure and destructor to use other than defaults */
-			res |= ast_bridge_features_enable(features, AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, dtmf->exten, NULL, NULL);
+			res |= ast_bridge_features_enable(features, AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, dtmf->exten, NULL, NULL, 0);
 		}
 		ast_rwlock_unlock(&features_lock);
 	}
@@ -4272,7 +4272,7 @@
 		ast_rwlock_rdlock(&features_lock);
 		dtmf = ast_find_call_feature("disconnect");
 		if (dtmf && !ast_strlen_zero(dtmf->exten)) {
-			res |= ast_bridge_features_enable(features, AST_BRIDGE_BUILTIN_HANGUP, dtmf->exten, NULL, NULL);
+			res |= ast_bridge_features_enable(features, AST_BRIDGE_BUILTIN_HANGUP, dtmf->exten, NULL, NULL, 0);
 		}
 		ast_rwlock_unlock(&features_lock);
 	}
@@ -4280,7 +4280,7 @@
 		ast_rwlock_rdlock(&features_lock);
 		dtmf = ast_find_call_feature("parkcall");
 		if (dtmf && !ast_strlen_zero(dtmf->exten)) {
-			res |= ast_bridge_features_enable(features, AST_BRIDGE_BUILTIN_PARKCALL, dtmf->exten, NULL, NULL);
+			res |= ast_bridge_features_enable(features, AST_BRIDGE_BUILTIN_PARKCALL, dtmf->exten, NULL, NULL, 0);
 		}
 		ast_rwlock_unlock(&features_lock);
 	}
@@ -4288,7 +4288,7 @@
 		ast_rwlock_rdlock(&features_lock);
 		dtmf = ast_find_call_feature("automon");
 		if (dtmf && !ast_strlen_zero(dtmf->exten)) {
-			res |= ast_bridge_features_enable(features, AST_BRIDGE_BUILTIN_AUTOMON, dtmf->exten, NULL, NULL);
+			res |= ast_bridge_features_enable(features, AST_BRIDGE_BUILTIN_AUTOMON, dtmf->exten, NULL, NULL, 0);
 		}
 		ast_rwlock_unlock(&features_lock);
 	}
@@ -4296,7 +4296,7 @@
 		ast_rwlock_rdlock(&features_lock);
 		dtmf = ast_find_call_feature("automixmon");
 		if (dtmf && !ast_strlen_zero(dtmf->exten)) {
-			res |= ast_bridge_features_enable(features, AST_BRIDGE_BUILTIN_AUTOMIXMON, dtmf->exten, NULL, NULL);
+			res |= ast_bridge_features_enable(features, AST_BRIDGE_BUILTIN_AUTOMIXMON, dtmf->exten, NULL, NULL, 0);
 		}
 		ast_rwlock_unlock(&features_lock);
 	}
@@ -4518,10 +4518,10 @@
 
 		bridge_config_set_limits(config, &call_duration_limits_chan, &call_duration_limits_peer);
 
-		if (ast_bridge_features_set_limits(&chan_features, &call_duration_limits_chan)) {
+		if (ast_bridge_features_set_limits(&chan_features, &call_duration_limits_chan, 0)) {
 			abandon_call = 1;
 		}
-		if (ast_bridge_features_set_limits(peer_features, &call_duration_limits_peer)) {
+		if (ast_bridge_features_set_limits(peer_features, &call_duration_limits_peer, 0)) {
 			abandon_call = 1;
 		}
 




More information about the asterisk-commits mailing list