[asterisk-commits] rmudgett: trunk r397355 - in /trunk: include/asterisk/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Aug 21 15:02:26 CDT 2013


Author: rmudgett
Date: Wed Aug 21 15:02:24 2013
New Revision: 397355

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=397355
Log:
* Move ast_bridge_channel_setup_features() into bridge_basic.c.

* Made application map hooks be removed on a basic bridge personality
change.

Modified:
    trunk/include/asterisk/bridge_basic.h
    trunk/main/bridge_basic.c
    trunk/main/features.c

Modified: trunk/include/asterisk/bridge_basic.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/bridge_basic.h?view=diff&rev=397355&r1=397354&r2=397355
==============================================================================
--- trunk/include/asterisk/bridge_basic.h (original)
+++ trunk/include/asterisk/bridge_basic.h Wed Aug 21 15:02:24 2013
@@ -104,17 +104,6 @@
  */
 int ast_bridge_features_ds_append(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;
 

Modified: trunk/main/bridge_basic.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/bridge_basic.c?view=diff&rev=397355&r1=397354&r2=397355
==============================================================================
--- trunk/main/bridge_basic.c (original)
+++ trunk/main/bridge_basic.c Wed Aug 21 15:02:24 2013
@@ -45,6 +45,7 @@
 #include "asterisk/app.h"
 #include "asterisk/dial.h"
 #include "asterisk/stasis_bridges.h"
+#include "asterisk/features.h"
 
 #define NORMAL_FLAGS	(AST_BRIDGE_FLAG_DISSOLVE_HANGUP | AST_BRIDGE_FLAG_DISSOLVE_EMPTY \
 			| AST_BRIDGE_FLAG_SMART)
@@ -329,11 +330,319 @@
 	struct personality_details details[BRIDGE_BASIC_PERSONALITY_END];
 };
 
+/*
+ * \internal
+ * \brief Get the extension for a given builtin feature.
+ *
+ * \param chan Get the feature extension for this channel.
+ * \param feature_name features.conf name of feature.
+ * \param buf Where to put the extension.
+ * \param len Length of the given extension buffer.
+ *
+ * \retval 0 success
+ * \retval non-zero failiure
+ */
+static int builtin_feature_get_exten(struct ast_channel *chan, const char *feature_name, char *buf, size_t len)
+{
+	SCOPED_CHANNELLOCK(lock, chan);
+
+	return ast_get_builtin_feature(chan, feature_name, buf, len);
+}
+
+/*!
+ * \internal
+ * \brief Helper to add a builtin DTMF feature hook to the features struct.
+ * \since 12.0.0
+ *
+ * \param features Bridge features to setup.
+ * \param chan Get features from this channel.
+ * \param flags Feature flags on the channel.
+ * \param feature_flag Feature flag to test.
+ * \param feature_name features.conf name of feature.
+ * \param feature_bridge Bridge feature enum to get hook callback.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int builtin_features_helper(struct ast_bridge_features *features, struct ast_channel *chan,
+	struct ast_flags *flags, unsigned int feature_flag, const char *feature_name, enum ast_bridge_builtin_feature feature_bridge)
+{
+	char dtmf[AST_FEATURE_MAX_LEN];
+	int res;
+
+	res = 0;
+	if (ast_test_flag(flags, feature_flag)
+		&& !builtin_feature_get_exten(chan, feature_name, dtmf, sizeof(dtmf))
+		&& !ast_strlen_zero(dtmf)) {
+		res = ast_bridge_features_enable(features, feature_bridge, dtmf, NULL, NULL,
+			AST_BRIDGE_HOOK_REMOVE_ON_PULL | AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE);
+		if (res) {
+			ast_log(LOG_ERROR, "Channel %s: Requested DTMF feature %s not available.\n",
+				ast_channel_name(chan), feature_name);
+		}
+	}
+
+	return res;
+}
+
+/*!
+ * \internal
+ * \brief Setup bridge builtin features.
+ * \since 12.0.0
+ *
+ * \param features Bridge features to setup.
+ * \param chan Get features from this channel.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int setup_bridge_features_builtin(struct ast_bridge_features *features, struct ast_channel *chan)
+{
+	struct ast_flags *flags;
+	int res;
+
+	ast_channel_lock(chan);
+	flags = ast_bridge_features_ds_get(chan);
+	ast_channel_unlock(chan);
+	if (!flags) {
+		return 0;
+	}
+
+	res = 0;
+	res |= builtin_features_helper(features, chan, flags, AST_FEATURE_REDIRECT, "blindxfer", AST_BRIDGE_BUILTIN_BLINDTRANSFER);
+	res |= builtin_features_helper(features, chan, flags, AST_FEATURE_REDIRECT, "atxfer", AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER);
+	res |= builtin_features_helper(features, chan, flags, AST_FEATURE_DISCONNECT, "disconnect", AST_BRIDGE_BUILTIN_HANGUP);
+	res |= builtin_features_helper(features, chan, flags, AST_FEATURE_PARKCALL, "parkcall", AST_BRIDGE_BUILTIN_PARKCALL);
+	res |= builtin_features_helper(features, chan, flags, AST_FEATURE_AUTOMON, "automon", AST_BRIDGE_BUILTIN_AUTOMON);
+	res |= builtin_features_helper(features, chan, flags, AST_FEATURE_AUTOMIXMON, "automixmon", AST_BRIDGE_BUILTIN_AUTOMIXMON);
+
+	return res ? -1 : 0;
+}
+
+struct dynamic_dtmf_hook_run {
+	/*! Offset into app_name[] where the channel name that activated the hook starts. */
+	int activated_offset;
+	/*! Offset into app_name[] where the dynamic feature name starts. */
+	int feature_offset;
+	/*! Offset into app_name[] where the MOH class name starts.  (zero if no MOH) */
+	int moh_offset;
+	/*! Offset into app_name[] where the application argument string starts. (zero if no arguments) */
+	int app_args_offset;
+	/*! Application name to run. */
+	char app_name[0];
+};
+
+static void dynamic_dtmf_hook_callback(struct ast_bridge_channel *bridge_channel,
+	const void *payload, size_t payload_size)
+{
+	struct ast_channel *chan = bridge_channel->chan;
+	const struct dynamic_dtmf_hook_run *run_data = payload;
+
+	pbx_builtin_setvar_helper(chan, "DYNAMIC_FEATURENAME",
+		&run_data->app_name[run_data->feature_offset]);
+	pbx_builtin_setvar_helper(chan, "DYNAMIC_WHO_ACTIVATED",
+		&run_data->app_name[run_data->activated_offset]);
+
+	ast_bridge_channel_run_app(bridge_channel, run_data->app_name,
+		run_data->app_args_offset ? &run_data->app_name[run_data->app_args_offset] : NULL,
+		run_data->moh_offset ? &run_data->app_name[run_data->moh_offset] : NULL);
+}
+
+struct dynamic_dtmf_hook_data {
+	/*! Which side of bridge to run app (AST_FEATURE_FLAG_ONSELF/AST_FEATURE_FLAG_ONPEER) */
+	unsigned int flags;
+	/*! Offset into app_name[] where the dynamic feature name starts. */
+	int feature_offset;
+	/*! Offset into app_name[] where the MOH class name starts.  (zero if no MOH) */
+	int moh_offset;
+	/*! Offset into app_name[] where the application argument string starts. (zero if no arguments) */
+	int app_args_offset;
+	/*! Application name to run. */
+	char app_name[0];
+};
+
+/*!
+ * \internal
+ * \brief Activated dynamic DTMF feature hook.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Channel executing the feature
+ * \param hook_pvt Private data passed in when the hook was created
+ *
+ * \retval 0 Keep the callback hook.
+ * \retval -1 Remove the callback hook.
+ */
+static int dynamic_dtmf_hook_trip(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
+{
+	struct dynamic_dtmf_hook_data *pvt = hook_pvt;
+	struct dynamic_dtmf_hook_run *run_data;
+	const char *activated_name;
+	size_t len_name;
+	size_t len_args;
+	size_t len_moh;
+	size_t len_feature;
+	size_t len_activated;
+	size_t len_data;
+
+	/* Determine lengths of things. */
+	len_name = strlen(pvt->app_name) + 1;
+	len_args = pvt->app_args_offset ? strlen(&pvt->app_name[pvt->app_args_offset]) + 1 : 0;
+	len_moh = pvt->moh_offset ? strlen(&pvt->app_name[pvt->moh_offset]) + 1 : 0;
+	len_feature = strlen(&pvt->app_name[pvt->feature_offset]) + 1;
+	ast_channel_lock(bridge_channel->chan);
+	activated_name = ast_strdupa(ast_channel_name(bridge_channel->chan));
+	ast_channel_unlock(bridge_channel->chan);
+	len_activated = strlen(activated_name) + 1;
+	len_data = sizeof(*run_data) + len_name + len_args + len_moh + len_feature + len_activated;
+
+	/* Fill in dynamic feature run hook data. */
+	run_data = ast_alloca(len_data);
+	run_data->app_args_offset = len_args ? len_name : 0;
+	run_data->moh_offset = len_moh ? len_name + len_args : 0;
+	run_data->feature_offset = len_name + len_args + len_moh;
+	run_data->activated_offset = len_name + len_args + len_moh + len_feature;
+	strcpy(run_data->app_name, pvt->app_name);/* Safe */
+	if (len_args) {
+		strcpy(&run_data->app_name[run_data->app_args_offset],
+			&pvt->app_name[pvt->app_args_offset]);/* Safe */
+	}
+	if (len_moh) {
+		strcpy(&run_data->app_name[run_data->moh_offset],
+			&pvt->app_name[pvt->moh_offset]);/* Safe */
+	}
+	strcpy(&run_data->app_name[run_data->feature_offset],
+		&pvt->app_name[pvt->feature_offset]);/* Safe */
+	strcpy(&run_data->app_name[run_data->activated_offset], activated_name);/* Safe */
+
+	if (ast_test_flag(pvt, AST_FEATURE_FLAG_ONPEER)) {
+		ast_bridge_channel_write_callback(bridge_channel,
+			AST_BRIDGE_CHANNEL_CB_OPTION_MEDIA,
+			dynamic_dtmf_hook_callback, run_data, len_data);
+	} else {
+		dynamic_dtmf_hook_callback(bridge_channel, run_data, len_data);
+	}
+	return 0;
+}
+
+/*!
+ * \internal
+ * \brief Add a dynamic DTMF feature hook to the bridge features.
+ * \since 12.0.0
+ *
+ * \param features Bridge features to setup.
+ * \param flags Which side of bridge to run app (AST_FEATURE_FLAG_ONSELF/AST_FEATURE_FLAG_ONPEER).
+ * \param dtmf DTMF trigger sequence.
+ * \param feature_name Name of the dynamic feature.
+ * \param app_name Dialplan application name to run.
+ * \param app_args Dialplan application arguments. (Empty or NULL if no arguments)
+ * \param moh_class MOH class to play to peer. (Empty or NULL if no MOH played)
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int dynamic_dtmf_hook_add(struct ast_bridge_features *features, unsigned int flags, const char *dtmf, const char *feature_name, const char *app_name, const char *app_args, const char *moh_class)
+{
+	struct dynamic_dtmf_hook_data *hook_data;
+	size_t len_name = strlen(app_name) + 1;
+	size_t len_args = ast_strlen_zero(app_args) ? 0 : strlen(app_args) + 1;
+	size_t len_moh = ast_strlen_zero(moh_class) ? 0 : strlen(moh_class) + 1;
+	size_t len_feature = strlen(feature_name) + 1;
+	size_t len_data = sizeof(*hook_data) + len_name + len_args + len_moh + len_feature;
+	int res;
+
+	/* Fill in application run hook data. */
+	hook_data = ast_malloc(len_data);
+	if (!hook_data) {
+		return -1;
+	}
+	hook_data->flags = flags;
+	hook_data->app_args_offset = len_args ? len_name : 0;
+	hook_data->moh_offset = len_moh ? len_name + len_args : 0;
+	hook_data->feature_offset = len_name + len_args + len_moh;
+	strcpy(hook_data->app_name, app_name);/* Safe */
+	if (len_args) {
+		strcpy(&hook_data->app_name[hook_data->app_args_offset], app_args);/* Safe */
+	}
+	if (len_moh) {
+		strcpy(&hook_data->app_name[hook_data->moh_offset], moh_class);/* Safe */
+	}
+	strcpy(&hook_data->app_name[hook_data->feature_offset], feature_name);/* Safe */
+
+	res = ast_bridge_dtmf_hook(features, dtmf, dynamic_dtmf_hook_trip, hook_data,
+		ast_free_ptr,
+		AST_BRIDGE_HOOK_REMOVE_ON_PULL | AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE);
+	if (res) {
+		ast_free(hook_data);
+	}
+	return res;
+}
+
+static int setup_dynamic_feature(void *obj, void *arg, void *data, int flags)
+{
+	struct ast_applicationmap_item *item = obj;
+	struct ast_bridge_features *features = arg;
+	int *res = data;
+
+	*res |= dynamic_dtmf_hook_add(features,
+		item->activate_on_self ? AST_FEATURE_FLAG_ONSELF : AST_FEATURE_FLAG_ONPEER,
+		item->dtmf, item->name, item->app, item->app_data, item->moh_class);
+
+	return 0;
+}
+
+/*!
+ * \internal
+ * \brief Setup bridge dynamic features.
+ * \since 12.0.0
+ *
+ * \param features Bridge features to setup.
+ * \param chan Get features from this channel.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int setup_bridge_features_dynamic(struct ast_bridge_features *features, struct ast_channel *chan)
+{
+	RAII_VAR(struct ao2_container *, applicationmap, NULL, ao2_cleanup);
+	int res = 0;
+
+	ast_channel_lock(chan);
+	applicationmap = ast_get_chan_applicationmap(chan);
+	ast_channel_unlock(chan);
+	if (!applicationmap) {
+		return 0;
+	}
+
+	ao2_callback_data(applicationmap, 0, setup_dynamic_feature, features, &res);
+
+	return res;
+}
+
+/*!
+ * \internal
+ * \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.
+ */
+static int bridge_basic_setup_features(struct ast_bridge_channel *bridge_channel)
+{
+	int res = 0;
+
+	res |= setup_bridge_features_builtin(bridge_channel->features, bridge_channel->chan);
+	res |= setup_bridge_features_dynamic(bridge_channel->features, bridge_channel->chan);
+
+	return res;
+}
+
 static int add_normal_hooks(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 {
 	return ast_bridge_hangup_hook(bridge_channel->features, basic_hangup_hook,
 			NULL, NULL, AST_BRIDGE_HOOK_REMOVE_ON_PULL)
-		|| ast_bridge_channel_setup_features(bridge_channel);
+		|| bridge_basic_setup_features(bridge_channel);
 }
 
 /*!

Modified: trunk/main/features.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/features.c?view=diff&rev=397355&r1=397354&r2=397355
==============================================================================
--- trunk/main/features.c (original)
+++ trunk/main/features.c Wed Aug 21 15:02:24 2013
@@ -323,23 +323,6 @@
 	.destroy = ast_free_ptr,
 };
 
-/*
- * \internal
- * \brief Get the extension for a given builtin feature
- *
- * \pre expects features_lock to be readlocked
- *
- * \retval 0 success
- * \retval non-zero failiure
- */
-static int builtin_feature_get_exten(struct ast_channel *chan, const char *feature_name,
-		char *buf, size_t len)
-{
-	SCOPED_CHANNELLOCK(lock, chan);
-
-	return ast_get_builtin_feature(chan, feature_name, buf, len);
-}
-
 static void set_config_flags(struct ast_channel *chan, struct ast_bridge_config *config)
 {
 	ast_clear_flag(config, AST_FLAGS_ALL);
@@ -457,285 +440,6 @@
 		}
 	}
 	ast_channel_unlock(chan);
-}
-
-/*!
- * \internal
- * \brief Helper to add a builtin DTMF feature hook to the features struct.
- * \since 12.0.0
- *
- * \param features Bridge features to setup.
- * \param chan Get features from this channel.
- * \param flags Feature flags on the channel.
- * \param feature_flag Feature flag to test.
- * \param feature_name features.conf name of feature.
- * \param feature_bridge Bridge feature enum to get hook callback.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int builtin_features_helper(struct ast_bridge_features *features, struct ast_channel *chan,
-	struct ast_flags *flags, unsigned int feature_flag, const char *feature_name, enum ast_bridge_builtin_feature feature_bridge)
-{
-	char dtmf[AST_FEATURE_MAX_LEN];
-	int res;
-
-	res = 0;
-	if (ast_test_flag(flags, feature_flag)
-		&& !builtin_feature_get_exten(chan, feature_name, dtmf, sizeof(dtmf))
-		&& !ast_strlen_zero(dtmf)) {
-		res = ast_bridge_features_enable(features, feature_bridge, dtmf, NULL, NULL,
-			AST_BRIDGE_HOOK_REMOVE_ON_PULL | AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE);
-		if (res) {
-			ast_log(LOG_ERROR, "Channel %s: Requested DTMF feature %s not available.\n",
-				ast_channel_name(chan), feature_name);
-		}
-	}
-
-	return res;
-}
-
-/*!
- * \internal
- * \brief Setup bridge builtin features.
- * \since 12.0.0
- *
- * \param features Bridge features to setup.
- * \param chan Get features from this channel.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int setup_bridge_features_builtin(struct ast_bridge_features *features, struct ast_channel *chan)
-{
-	struct ast_flags *flags;
-	int res;
-
-	ast_channel_lock(chan);
-	flags = ast_bridge_features_ds_get(chan);
-	ast_channel_unlock(chan);
-	if (!flags) {
-		return 0;
-	}
-
-	res = 0;
-	res |= builtin_features_helper(features, chan, flags, AST_FEATURE_REDIRECT, "blindxfer", AST_BRIDGE_BUILTIN_BLINDTRANSFER);
-	res |= builtin_features_helper(features, chan, flags, AST_FEATURE_REDIRECT, "atxfer", AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER);
-	res |= builtin_features_helper(features, chan, flags, AST_FEATURE_DISCONNECT, "disconnect", AST_BRIDGE_BUILTIN_HANGUP);
-	res |= builtin_features_helper(features, chan, flags, AST_FEATURE_PARKCALL, "parkcall", AST_BRIDGE_BUILTIN_PARKCALL);
-	res |= builtin_features_helper(features, chan, flags, AST_FEATURE_AUTOMON, "automon", AST_BRIDGE_BUILTIN_AUTOMON);
-	res |= builtin_features_helper(features, chan, flags, AST_FEATURE_AUTOMIXMON, "automixmon", AST_BRIDGE_BUILTIN_AUTOMIXMON);
-
-	return res ? -1 : 0;
-}
-
-struct dynamic_dtmf_hook_run {
-	/*! Offset into app_name[] where the channel name that activated the hook starts. */
-	int activated_offset;
-	/*! Offset into app_name[] where the dynamic feature name starts. */
-	int feature_offset;
-	/*! Offset into app_name[] where the MOH class name starts.  (zero if no MOH) */
-	int moh_offset;
-	/*! Offset into app_name[] where the application argument string starts. (zero if no arguments) */
-	int app_args_offset;
-	/*! Application name to run. */
-	char app_name[0];
-};
-
-static void dynamic_dtmf_hook_callback(struct ast_bridge_channel *bridge_channel,
-	const void *payload, size_t payload_size)
-{
-	struct ast_channel *chan = bridge_channel->chan;
-	const struct dynamic_dtmf_hook_run *run_data = payload;
-
-	pbx_builtin_setvar_helper(chan, "DYNAMIC_FEATURENAME",
-		&run_data->app_name[run_data->feature_offset]);
-	pbx_builtin_setvar_helper(chan, "DYNAMIC_WHO_ACTIVATED",
-		&run_data->app_name[run_data->activated_offset]);
-
-	ast_bridge_channel_run_app(bridge_channel, run_data->app_name,
-		run_data->app_args_offset ? &run_data->app_name[run_data->app_args_offset] : NULL,
-		run_data->moh_offset ? &run_data->app_name[run_data->moh_offset] : NULL);
-}
-
-struct dynamic_dtmf_hook_data {
-	/*! Which side of bridge to run app (AST_FEATURE_FLAG_ONSELF/AST_FEATURE_FLAG_ONPEER) */
-	unsigned int flags;
-	/*! Offset into app_name[] where the dynamic feature name starts. */
-	int feature_offset;
-	/*! Offset into app_name[] where the MOH class name starts.  (zero if no MOH) */
-	int moh_offset;
-	/*! Offset into app_name[] where the application argument string starts. (zero if no arguments) */
-	int app_args_offset;
-	/*! Application name to run. */
-	char app_name[0];
-};
-
-/*!
- * \internal
- * \brief Activated dynamic DTMF feature hook.
- * \since 12.0.0
- *
- * \param bridge_channel Channel executing the feature
- * \param hook_pvt Private data passed in when the hook was created
- *
- * \retval 0 Keep the callback hook.
- * \retval -1 Remove the callback hook.
- */
-static int dynamic_dtmf_hook_trip(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
-{
-	struct dynamic_dtmf_hook_data *pvt = hook_pvt;
-	struct dynamic_dtmf_hook_run *run_data;
-	const char *activated_name;
-	size_t len_name;
-	size_t len_args;
-	size_t len_moh;
-	size_t len_feature;
-	size_t len_activated;
-	size_t len_data;
-
-	/* Determine lengths of things. */
-	len_name = strlen(pvt->app_name) + 1;
-	len_args = pvt->app_args_offset ? strlen(&pvt->app_name[pvt->app_args_offset]) + 1 : 0;
-	len_moh = pvt->moh_offset ? strlen(&pvt->app_name[pvt->moh_offset]) + 1 : 0;
-	len_feature = strlen(&pvt->app_name[pvt->feature_offset]) + 1;
-	ast_channel_lock(bridge_channel->chan);
-	activated_name = ast_strdupa(ast_channel_name(bridge_channel->chan));
-	ast_channel_unlock(bridge_channel->chan);
-	len_activated = strlen(activated_name) + 1;
-	len_data = sizeof(*run_data) + len_name + len_args + len_moh + len_feature + len_activated;
-
-	/* Fill in dynamic feature run hook data. */
-	run_data = ast_alloca(len_data);
-	run_data->app_args_offset = len_args ? len_name : 0;
-	run_data->moh_offset = len_moh ? len_name + len_args : 0;
-	run_data->feature_offset = len_name + len_args + len_moh;
-	run_data->activated_offset = len_name + len_args + len_moh + len_feature;
-	strcpy(run_data->app_name, pvt->app_name);/* Safe */
-	if (len_args) {
-		strcpy(&run_data->app_name[run_data->app_args_offset],
-			&pvt->app_name[pvt->app_args_offset]);/* Safe */
-	}
-	if (len_moh) {
-		strcpy(&run_data->app_name[run_data->moh_offset],
-			&pvt->app_name[pvt->moh_offset]);/* Safe */
-	}
-	strcpy(&run_data->app_name[run_data->feature_offset],
-		&pvt->app_name[pvt->feature_offset]);/* Safe */
-	strcpy(&run_data->app_name[run_data->activated_offset], activated_name);/* Safe */
-
-	if (ast_test_flag(pvt, AST_FEATURE_FLAG_ONPEER)) {
-		ast_bridge_channel_write_callback(bridge_channel,
-			AST_BRIDGE_CHANNEL_CB_OPTION_MEDIA,
-			dynamic_dtmf_hook_callback, run_data, len_data);
-	} else {
-		dynamic_dtmf_hook_callback(bridge_channel, run_data, len_data);
-	}
-	return 0;
-}
-
-/*!
- * \internal
- * \brief Add a dynamic DTMF feature hook to the bridge features.
- * \since 12.0.0
- *
- * \param features Bridge features to setup.
- * \param flags Which side of bridge to run app (AST_FEATURE_FLAG_ONSELF/AST_FEATURE_FLAG_ONPEER).
- * \param dtmf DTMF trigger sequence.
- * \param feature_name Name of the dynamic feature.
- * \param app_name Dialplan application name to run.
- * \param app_args Dialplan application arguments. (Empty or NULL if no arguments)
- * \param moh_class MOH class to play to peer. (Empty or NULL if no MOH played)
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int dynamic_dtmf_hook_add(struct ast_bridge_features *features, unsigned int flags, const char *dtmf, const char *feature_name, const char *app_name, const char *app_args, const char *moh_class)
-{
-	struct dynamic_dtmf_hook_data *hook_data;
-	size_t len_name = strlen(app_name) + 1;
-	size_t len_args = ast_strlen_zero(app_args) ? 0 : strlen(app_args) + 1;
-	size_t len_moh = ast_strlen_zero(moh_class) ? 0 : strlen(moh_class) + 1;
-	size_t len_feature = strlen(feature_name) + 1;
-	size_t len_data = sizeof(*hook_data) + len_name + len_args + len_moh + len_feature;
-	int res;
-
-	/* Fill in application run hook data. */
-	hook_data = ast_malloc(len_data);
-	if (!hook_data) {
-		return -1;
-	}
-	hook_data->flags = flags;
-	hook_data->app_args_offset = len_args ? len_name : 0;
-	hook_data->moh_offset = len_moh ? len_name + len_args : 0;
-	hook_data->feature_offset = len_name + len_args + len_moh;
-	strcpy(hook_data->app_name, app_name);/* Safe */
-	if (len_args) {
-		strcpy(&hook_data->app_name[hook_data->app_args_offset], app_args);/* Safe */
-	}
-	if (len_moh) {
-		strcpy(&hook_data->app_name[hook_data->moh_offset], moh_class);/* Safe */
-	}
-	strcpy(&hook_data->app_name[hook_data->feature_offset], feature_name);/* Safe */
-
-	res = ast_bridge_dtmf_hook(features, dtmf, dynamic_dtmf_hook_trip, hook_data,
-		ast_free_ptr, AST_BRIDGE_HOOK_REMOVE_ON_PULL);
-	if (res) {
-		ast_free(hook_data);
-	}
-	return res;
-}
-
-static int setup_dynamic_feature(void *obj, void *arg, void *data, int flags)
-{
-	struct ast_applicationmap_item *item = obj;
-	struct ast_bridge_features *features = arg;
-	int *res = data;
-
-	*res |= dynamic_dtmf_hook_add(features,
-		item->activate_on_self ? AST_FEATURE_FLAG_ONSELF : AST_FEATURE_FLAG_ONPEER,
-		item->dtmf, item->name, item->app, item->app_data, item->moh_class);
-
-	return 0;
-}
-
-/*!
- * \internal
- * \brief Setup bridge dynamic features.
- * \since 12.0.0
- *
- * \param features Bridge features to setup.
- * \param chan Get features from this channel.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int setup_bridge_features_dynamic(struct ast_bridge_features *features, struct ast_channel *chan)
-{
-	RAII_VAR(struct ao2_container *, applicationmap, NULL, ao2_cleanup);
-	int res = 0;
-
-	ast_channel_lock(chan);
-	applicationmap = ast_get_chan_applicationmap(chan);
-	ast_channel_unlock(chan);
-	if (!applicationmap) {
-		return 0;
-	}
-
-	ao2_callback_data(applicationmap, 0, setup_dynamic_feature, features, &res);
-
-	return res;
-}
-
-/* BUGBUG this really should be made a private function of bridge_basic.c after struct ast_call_feature is made an ao2 object. */
-int ast_bridge_channel_setup_features(struct ast_bridge_channel *bridge_channel)
-{
-	int res = 0;
-
-	res |= setup_bridge_features_builtin(bridge_channel->features, bridge_channel->chan);
-	res |= setup_bridge_features_dynamic(bridge_channel->features, bridge_channel->chan);
-
-	return res;
 }
 
 static void bridge_config_set_limits_warning_values(struct ast_bridge_config *config, struct ast_bridge_features_limits *limits)




More information about the asterisk-commits mailing list