From b816fe45b6bf3d61f873013b833908f500054d76 Mon Sep 17 00:00:00 2001 From: Richard Mudgett Date: Wed, 21 Aug 2013 20:02:24 +0000 Subject: * Move ast_bridge_channel_setup_features() into bridge_basic.c. * Made application map hooks be removed on a basic bridge personality change. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@397355 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- main/features.c | 296 -------------------------------------------------------- 1 file changed, 296 deletions(-) (limited to 'main/features.c') diff --git a/main/features.c b/main/features.c index 4d19fa6d7..2601a4106 100644 --- a/main/features.c +++ b/main/features.c @@ -323,23 +323,6 @@ static const struct ast_datastore_info channel_app_data_datastore = { .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); @@ -459,285 +442,6 @@ static void clear_dialed_interfaces(struct ast_channel *chan) 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) { if (config->end_sound) { -- cgit v1.2.3