[asterisk-commits] mmichelson: branch mmichelson/features_config r389447 - in /team/mmichelson/f...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue May 21 16:31:04 CDT 2013
Author: mmichelson
Date: Tue May 21 16:31:01 2013
New Revision: 389447
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=389447
Log:
Get feature configuration options using the config API.
This also adds some APIs to retrieve configured values. The APIs
are a bit lacking for now since they only grab the global values
and are not tweaked to take into account per-channel settings that
may have been applied in the dialplan.
Modified:
team/mmichelson/features_config/include/asterisk/features.h
team/mmichelson/features_config/main/features.c
Modified: team/mmichelson/features_config/include/asterisk/features.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/include/asterisk/features.h?view=diff&rev=389447&r1=389446&r2=389447
==============================================================================
--- team/mmichelson/features_config/include/asterisk/features.h (original)
+++ team/mmichelson/features_config/include/asterisk/features.h Tue May 21 16:31:01 2013
@@ -251,6 +251,72 @@
*/
struct ast_call_feature *ast_find_call_feature(const char *name);
+
+/*!
+ * \brief General features configuration items
+ */
+struct ast_features_general_config {
+ /*! Milliseconds allowed between digit presses when entering feature code */
+ unsigned int featuredigittimeout;
+};
+
+/*!
+ * \brief Get the general configuration options
+ *
+ * The returned value has its reference count incremented.
+ */
+struct ast_features_general_config *ast_get_features_general_config(void);
+
+/*!
+ * \brief Feature configuration relating to transfers
+ */
+struct ast_features_xfer_config {
+ AST_DECLARE_STRING_FIELDS (
+ /*! Sound to play to transferee when transfer succeeds */
+ AST_STRING_FIELD(xfersound);
+ /*! Sound to play to transferee when transfer fails */
+ AST_STRING_FIELD(xferfailsound);
+ );
+ /*! Milliseconds allowed between digit presses when dialing transfer destination */
+ unsigned int transferdigittimeout;
+ /*! Milliseconds to wait for the transfer target to answer a transferred call */
+ unsigned int atxfernoanswertimeout;
+ /*! Milliseconds to wait before attempting to re-dial the transfer target */
+ unsigned int atxferloopdelay;
+ /*! Number of times to re-attempt dialing the transfer target */
+ unsigned int atxfercallbackretries;
+ /*! Determines if the call is dropped on attended transfer failure */
+ unsigned int atxferdropcall;
+};
+
+/*!
+ * \brief Get the transfer configuration options
+ *
+ * The returned value has its reference count incremented
+ */
+struct ast_features_xfer_config *ast_get_features_xfer_config(void);
+
+/*!
+ * \brief Configuration relating to call pickup
+ */
+struct ast_features_pickup_config {
+ AST_DECLARE_STRING_FIELDS (
+ /*! Digit sequence to press to pick up a ringing call */
+ AST_STRING_FIELD(pickupexten);
+ /*! Sound to play to picker when pickup succeeds */
+ AST_STRING_FIELD(pickupsound);
+ /*! Sound to play to picker when pickup fails */
+ AST_STRING_FIELD(pickupfailsound);
+ );
+};
+
+/*!
+ * \brief Get the pickup configuration options
+ *
+ * The returned value has its reference count incremented
+ */
+struct ast_features_pickup_config *ast_get_features_pickup_config(void);
+
void ast_rdlock_call_features(void);
void ast_unlock_call_features(void);
Modified: team/mmichelson/features_config/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/main/features.c?view=diff&rev=389447&r1=389446&r2=389447
==============================================================================
--- team/mmichelson/features_config/main/features.c (original)
+++ team/mmichelson/features_config/main/features.c Tue May 21 16:31:01 2013
@@ -74,6 +74,7 @@
#include "asterisk/test.h"
#include "asterisk/bridging.h"
#include "asterisk/bridging_basic.h"
+#include "asterisk/config_options.h"
/*
* Party A - transferee
@@ -6404,6 +6405,353 @@
return 0;
}
+struct features_global_config {
+ struct ast_features_general_config *general;
+ struct ast_features_xfer_config *xfer;
+ struct ast_features_pickup_config *pickup;
+};
+
+struct features_featuremap {
+ AST_DECLARE_STRING_FIELDS (
+ AST_STRING_FIELD(blindxfer);
+ AST_STRING_FIELD(disconnect);
+ AST_STRING_FIELD(automon);
+ AST_STRING_FIELD(atxfer);
+ AST_STRING_FIELD(parkcall);
+ AST_STRING_FIELD(automixmon);
+ );
+};
+
+struct features_applicationmap {
+ /* XXX STUB */
+};
+
+struct features_config {
+ struct features_global_config *global;
+ struct features_featuremap *featuremap;
+ struct features_applicationmap *applicationmap;
+};
+
+static struct aco_type global_option = {
+ .type = ACO_GLOBAL,
+ .name = "globals",
+ .category_match = ACO_WHITELIST,
+ .category = "^general$",
+ .item_offset = offsetof(struct features_config, global),
+};
+
+static struct aco_type featuremap_option = {
+ .type = ACO_GLOBAL,
+ .name = "featuremap",
+ .category_match = ACO_WHITELIST,
+ .category = "^featuremap$",
+ .item_offset = offsetof(struct features_config, featuremap),
+};
+
+static struct aco_type applicationmap_option = {
+ .type = ACO_GLOBAL,
+ .name = "applicationmap",
+ .category_match = ACO_WHITELIST,
+ .category = "^applicationmap$",
+ .item_offset = offsetof(struct features_config, applicationmap),
+};
+
+struct aco_type *global_options[] = ACO_TYPES(&global_option);
+struct aco_type *featuremap_options[] = ACO_TYPES(&featuremap_option);
+struct aco_type *applicationmap_options[] = ACO_TYPES(&applicationmap_option);
+
+struct aco_file features_conf = {
+ .filename = "features.conf",
+ .types = ACO_TYPES(&global_option, &featuremap_option, &applicationmap_option),
+};
+
+AO2_GLOBAL_OBJ_STATIC(globals);
+
+static void features_config_destructor(void *obj)
+{
+ struct features_config *cfg = obj;
+
+ ao2_cleanup(cfg->global);
+ ao2_cleanup(cfg->featuremap);
+ ao2_cleanup(cfg->applicationmap);
+}
+
+static void featuremap_config_destructor(void *obj)
+{
+ struct features_featuremap *cfg = obj;
+
+ ast_string_field_free_memory(cfg);
+}
+
+static void applicationmap_config_destructor (void *obj)
+{
+ /* XXX STUB */
+}
+
+static void global_config_destructor(void *obj)
+{
+ struct features_global_config *cfg = obj;
+
+ ao2_cleanup(cfg->general);
+ ao2_cleanup(cfg->xfer);
+ ao2_cleanup(cfg->pickup);
+}
+
+static void xfer_destructor(void *obj)
+{
+ struct ast_features_xfer_config *cfg = obj;
+
+ ast_string_field_free_memory(cfg);
+}
+
+static void pickup_destructor(void *obj)
+{
+ struct ast_features_pickup_config *cfg = obj;
+
+ ast_string_field_free_memory(cfg);
+}
+
+static struct features_global_config *global_config_alloc(void)
+{
+ RAII_VAR(struct features_global_config *, cfg, NULL, ao2_cleanup);
+
+ cfg = ao2_alloc(sizeof(*cfg), global_config_destructor);
+ if (!cfg) {
+ return NULL;
+ }
+
+ cfg->general = ao2_alloc(sizeof(*cfg->general), NULL);
+ if (!cfg->general) {
+ return NULL;
+ }
+
+ cfg->xfer = ao2_alloc(sizeof(*cfg->xfer), xfer_destructor);
+ if (!cfg->xfer || ast_string_field_init(cfg->xfer, 32)) {
+ return NULL;
+ }
+
+ cfg->pickup = ao2_alloc(sizeof(*cfg->pickup), pickup_destructor);
+ if (!cfg->pickup || ast_string_field_init(cfg->pickup, 32)) {
+ return NULL;
+ }
+
+ ao2_ref(cfg, +1);
+ return cfg;
+}
+
+static void *features_config_alloc(void)
+{
+ RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
+
+ cfg = ao2_alloc(sizeof(*cfg), features_config_destructor);
+ if (!cfg) {
+ return NULL;
+ }
+
+ cfg->global = global_config_alloc();;
+ if (!cfg->global) {
+ return NULL;
+ }
+
+ cfg->featuremap = ao2_alloc(sizeof(*cfg->featuremap), featuremap_config_destructor);
+ if (!cfg->featuremap || ast_string_field_init(cfg->featuremap, 32)) {
+ return NULL;
+ }
+
+ cfg->applicationmap = ao2_alloc(sizeof(*cfg->applicationmap),
+ applicationmap_config_destructor);
+ if (!cfg->applicationmap) {
+ return NULL;
+ }
+
+ ao2_ref(cfg, +1);
+ return cfg;
+}
+
+CONFIG_INFO_CORE("features", cfg_info, globals, features_config_alloc,
+ .files = ACO_FILES(&features_conf),
+);
+
+struct ast_features_general_config *ast_get_features_general_config(void)
+{
+ RAII_VAR(struct features_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+
+ if (!cfg) {
+ return NULL;
+ }
+
+ ast_assert(cfg->global && cfg->global->general);
+
+ ao2_ref(cfg->global->general, +1);
+ return cfg->global->general;
+}
+
+struct ast_features_xfer_config *ast_get_features_xfer_config(void)
+{
+ RAII_VAR(struct features_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+
+ if (!cfg) {
+ return NULL;
+ }
+
+ ast_assert(cfg->global && cfg->global->xfer);
+
+ ao2_ref(cfg->global->xfer, +1);
+ return cfg->global->xfer;
+}
+
+struct ast_features_pickup_config *ast_get_features_pickup_config(void)
+{
+ RAII_VAR(struct features_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+
+ if (!cfg) {
+ return NULL;
+ }
+
+ ast_assert(cfg->global && cfg->global->pickup);
+
+ ao2_ref(cfg->global->pickup, +1);
+ return cfg->global->pickup;
+}
+
+static int applicationmap_handler(const struct aco_option *opt,
+ struct ast_variable *var, void *obj)
+{
+ /* XXX STUB */
+ return 0;
+}
+
+static int general_handler(const struct aco_option *opt,
+ struct ast_variable *var, void *obj)
+{
+ struct features_global_config *global = obj;
+ struct ast_features_general_config *general = global->general;
+
+ if (!strcasecmp(var->name, "featuredigittimeout")) {
+ return ast_parse_arg(var->value, PARSE_INT32, &general->featuredigittimeout);
+ } else {
+ /* Unrecognized option */
+ return -1;
+ }
+}
+
+static int xfer_handler(const struct aco_option *opt,
+ struct ast_variable *var, void *obj)
+{
+ struct features_global_config *global = obj;
+ struct ast_features_xfer_config *xfer = global->xfer;
+
+ if (!strcasecmp(var->name, "transferdigittimeout")) {
+ return ast_parse_arg(var->value, PARSE_INT32, &xfer->transferdigittimeout);
+ } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
+ return ast_parse_arg(var->value, PARSE_INT32, &xfer->atxfernoanswertimeout);
+ } else if (!strcasecmp(var->name, "atxferloopdelay")) {
+ return ast_parse_arg(var->value, PARSE_INT32, &xfer->atxferloopdelay);
+ } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
+ return ast_parse_arg(var->value, PARSE_INT32, &xfer->atxfercallbackretries);
+ } else if (!strcasecmp(var->name, "atxferdropcall")) {
+ xfer->atxferdropcall = ast_true(var->value);
+ return 0;
+ } else if (!strcasecmp(var->name, "xfersound")) {
+ ast_string_field_set(xfer, xfersound, var->value);
+ return 0;
+ } else if (!strcasecmp(var->name, "xferfailsound")) {
+ ast_string_field_set(xfer, xferfailsound, var->value);
+ return 0;
+ } else {
+ /* Unrecognized option */
+ return -1;
+ }
+}
+
+static int pickup_handler(const struct aco_option *opt,
+ struct ast_variable *var, void *obj)
+{
+ struct features_global_config *global = obj;
+ struct ast_features_pickup_config *pickup = global->pickup;
+
+ if (!strcasecmp(var->name, "pickupsound")) {
+ ast_string_field_set(pickup, pickupsound, var->value);
+ return 0;
+ } else if (!strcasecmp(var->name, "pickupfailsound")) {
+ ast_string_field_set(pickup, pickupfailsound, var->value);
+ return 0;
+ } else if (!strcasecmp(var->name, "pickupexten")) {
+ ast_string_field_set(pickup, pickupexten, var->value);
+ return 0;
+ } else {
+ /* Unrecognized option */
+ return -1;
+ }
+}
+
+static int really_load_config(int reload)
+{
+ if (!reload && aco_info_init(&cfg_info)) {
+ ast_log(LOG_ERROR, "Unable to initialize configuration info for features\n");
+ return -1;
+ }
+
+ aco_option_register_custom(&cfg_info, "featuredigittimeout", ACO_EXACT, global_options,
+ __stringify(DEFAULT_FEATURE_DIGIT_TIMEOUT), general_handler, 0);
+
+ aco_option_register_custom(&cfg_info, "transferdigittimeout", ACO_EXACT, global_options,
+ __stringify(DEFAULT_TRANSFER_DIGIT_TIMEOUT), xfer_handler, 0)
+ aco_option_register_custom(&cfg_info, "atxfernoanswertimeout", ACO_EXACT, global_options,
+ __stringify(DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER), xfer_handler, 0);
+ aco_option_register_custom(&cfg_info, "atxferdropcall", ACO_EXACT, global_options,
+ __stringify(DEFAULT_ATXFER_DROP_CALL), xfer_handler, 0);
+ aco_option_register_custom(&cfg_info, "atxferloopdelay", ACO_EXACT, global_options,
+ __stringify(DEFAULT_ATXFER_LOOP_DELAY), xfer_handler, 0);
+ aco_option_register_custom(&cfg_info, "atxfercallbackretries", ACO_EXACT, global_options,
+ __stringify(DEFAULT_ATXFER_CALLBACK_RETRIES), xfer_handler, 0);
+ aco_option_register_custom(&cfg_info, "xfersound", ACO_EXACT, global_options,
+ "beep", xfer_handler, 0);
+ aco_option_register_custom(&cfg_info, "xferfailsound", ACO_EXACT, global_options,
+ "beeperr", xfer_handler, 0);
+
+ aco_option_register_custom(&cfg_info, "pickupexten", ACO_EXACT, global_options,
+ "*8", pickup_handler, 0);
+ aco_option_register_custom(&cfg_info, "pickupsound", ACO_EXACT, global_options,
+ "", pickup_handler, 0);
+ aco_option_register_custom(&cfg_info, "pickupfailsound", ACO_EXACT, global_options,
+ "", pickup_handler, 0);
+
+ aco_option_register(&cfg_info, "blindxfer", ACO_EXACT, featuremap_options,
+ "#", OPT_STRINGFIELD_T, 0, STRFLDSET(struct features_featuremap, blindxfer));
+ aco_option_register(&cfg_info, "disconnect", ACO_EXACT, featuremap_options,
+ "*", OPT_STRINGFIELD_T, 0, STRFLDSET(struct features_featuremap, disconnect));
+ aco_option_register(&cfg_info, "automon", ACO_EXACT, featuremap_options,
+ "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct features_featuremap, automon));
+ aco_option_register(&cfg_info, "atxfer", ACO_EXACT, featuremap_options,
+ "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct features_featuremap, atxfer));
+ aco_option_register(&cfg_info, "parkcall", ACO_EXACT, featuremap_options,
+ "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct features_featuremap, parkcall));
+ aco_option_register(&cfg_info, "automixmon", ACO_EXACT, featuremap_options,
+ "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct features_featuremap, automixmon));
+
+ /* XXX This regex may need to be more specific */
+ aco_option_register_custom(&cfg_info, "^.*$", ACO_REGEX, applicationmap_options,
+ "", applicationmap_handler, 0);
+
+#if 0
+ /* XXX This regex may need to be more specific */
+ aco_option_register_custom(&cfg_info, "^.*$", ACO_REGEX, dynamicfeaturemap_options,
+ "", dynamic_feature_handler, 0);
+#endif
+
+ if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
+ ast_log(LOG_ERROR, "Failed to process features.conf configuration!\n");
+ if (!reload) {
+ aco_info_destroy(&cfg_info);
+ ao2_global_obj_release(globals);
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
static int load_config(int reload)
{
struct ast_flags config_flags = {
@@ -6571,6 +6919,7 @@
}
res = load_config(1);
+ res = really_load_config(1);
ast_mutex_unlock(&features_reload_lock);
return res;
@@ -8188,7 +8537,7 @@
return -1;
}
- res = load_config(0);
+ res = really_load_config(0);
if (res) {
return res;
}
More information about the asterisk-commits
mailing list