[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