[asterisk-commits] mmichelson: branch mmichelson/features_config r389538 - /team/mmichelson/feat...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed May 22 17:58:06 CDT 2013


Author: mmichelson
Date: Wed May 22 17:58:02 2013
New Revision: 389538

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=389538
Log:
Add applicationmap handling.


Modified:
    team/mmichelson/features_config/main/features_config.c

Modified: team/mmichelson/features_config/main/features_config.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/main/features_config.c?view=diff&rev=389538&r1=389537&r2=389538
==============================================================================
--- team/mmichelson/features_config/main/features_config.c (original)
+++ team/mmichelson/features_config/main/features_config.c Wed May 22 17:58:02 2013
@@ -23,6 +23,7 @@
 #include "asterisk/datastore.h"
 #include "asterisk/channel.h"
 #include "asterisk/pbx.h"
+#include "asterisk/app.h"
 
 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT				3000	/*!< ms */
 #define DEFAULT_FEATURE_DIGIT_TIMEOUT				1000	/*!< ms */
@@ -37,14 +38,68 @@
 	struct ast_features_pickup_config *pickup;
 };
 
-struct features_applicationmap {
-	/* XXX STUB */
+struct applicationmap_item {
+	AST_DECLARE_STRING_FIELDS (
+		AST_STRING_FIELD(name);
+		AST_STRING_FIELD(dtmf);
+		AST_STRING_FIELD(app);
+		AST_STRING_FIELD(app_data);
+		AST_STRING_FIELD(moh_class);
+	);
+	unsigned int activate_on_self;
 };
+
+static void applicationmap_item_destructor(void *obj)
+{
+	struct applicationmap_item *item = obj;
+
+	ast_string_field_free_memory(item);
+}
+
+static int applicationmap_hash(const void *obj, int flags)
+{
+	const struct applicationmap_item *item;
+	const char *key;
+
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	case OBJ_KEY:
+		key = obj;
+		return ast_str_case_hash(key);
+	case OBJ_PARTIAL_KEY:
+		ast_assert(0);
+		return 0;
+	case OBJ_POINTER:
+	default:
+		item = obj;
+		return ast_str_case_hash(item->name);
+	}
+}
+
+static int applicationmap_cmp(void *obj, void *arg, int flags)
+{
+	struct applicationmap_item *item1 = obj;
+	struct applicationmap_item *item2;
+	const char *key2;
+
+	switch(flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	case OBJ_KEY:
+		key2 = arg;
+		return strcasecmp(item1->name, key2) ? 0 : CMP_MATCH;
+	case OBJ_PARTIAL_KEY:
+		key2 = arg;
+		return strncasecmp(item1->name, key2, strlen(key2)) ? 0 : CMP_MATCH;
+	case OBJ_POINTER:
+		item2 = arg;
+		return strcasecmp(item1->name, item2->name) ? 0 : CMP_MATCH;
+	default:
+		return CMP_STOP;
+	}
+}
 
 struct features_config {
 	struct features_global_config *global;
 	struct ast_featuremap_config *featuremap;
-	struct features_applicationmap *applicationmap;
+	struct ao2_container *applicationmap;
 };
 
 static struct aco_type global_option = {
@@ -98,11 +153,6 @@
 	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;
@@ -154,7 +204,7 @@
 	return cfg;
 }
 
-static void *features_config_alloc(void)
+static struct features_config *__features_config_alloc(int allocate_applicationmap)
 {
 	RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
 
@@ -173,14 +223,22 @@
 		return NULL;
 	}
 
-	cfg->applicationmap = ao2_alloc(sizeof(*cfg->applicationmap),
-			applicationmap_config_destructor);
-	if (!cfg->applicationmap) {
-		return NULL;
+	if (allocate_applicationmap) {
+		cfg->applicationmap = ao2_container_alloc(11, applicationmap_hash,
+				applicationmap_cmp);
+		if (!cfg->applicationmap) {
+			return NULL;
+		}
 	}
 
 	ao2_ref(cfg, +1);
 	return cfg;
+
+}
+
+static void *features_config_alloc(void)
+{
+	return __features_config_alloc(1);
 }
 
 static void general_copy(struct ast_features_general_config *dest, const struct ast_features_general_config *src)
@@ -215,23 +273,21 @@
 	ast_string_fields_copy(dest, src);
 }
 
-static void applicationmap_copy(struct features_applicationmap *dest, const struct features_applicationmap *src)
-{
-	/* XXX STUB */
-}
-
 static void features_copy(struct features_config *dest, const struct features_config *src)
 {
 	global_copy(dest->global, src->global);
 	featuremap_copy(dest->featuremap, src->featuremap);
-	applicationmap_copy(dest->applicationmap, src->applicationmap);
+
+	/* No deep copy is needed because applicationmap cannot change */
+	ao2_ref(src->applicationmap, +1);
+	dest->applicationmap = src->applicationmap;
 }
 
 static struct features_config *features_config_dup(const struct features_config *orig)
 {
 	struct features_config *dup;
 
-	dup = features_config_alloc();
+	dup = __features_config_alloc(0);
 	if (!dup) {
 		return NULL;
 	}
@@ -612,7 +668,76 @@
 static int applicationmap_handler(const struct aco_option *opt,
 		struct ast_variable *var, void *obj)
 {
-	/* XXX STUB */
+	RAII_VAR(struct applicationmap_item *, item, NULL, ao2_cleanup);
+	struct ao2_container *applicationmap = obj;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(dtmf);
+		AST_APP_ARG(activate_on);
+		AST_APP_ARG(app);
+		AST_APP_ARG(app_data);
+		AST_APP_ARG(moh_class);
+	);
+	char *parse = ast_strdupa(var->value);
+	char *slash;
+	char *paren;
+	unsigned int activate_on_self;
+
+	AST_STANDARD_APP_ARGS(args, parse);
+
+	/* features.conf used to have an "activated_by" portion
+	 * in addition to activate_on. Get rid of whatever may be
+	 * there
+	 */
+	slash = strchr(args.activate_on, '/');
+	if (slash) {
+		*slash = '\0';
+	}
+
+	/* Two syntaxes allowed for applicationmap:
+	 * Old: foo = *1,self,NoOp,Boo!,default
+	 * New: foo = *1,self,NoOp(Boo!),default
+	 *
+	 * We need to handle both
+	 */
+	paren = strchr(args.app, '(');
+	if (paren) {
+		/* New syntax */
+		args.moh_class = args.app_data;
+		args.app_data = ast_strip_quoted(paren, "(", ")");
+	}
+
+	if (ast_strlen_zero(args.dtmf) ||
+			ast_strlen_zero(args.activate_on) ||
+			ast_strlen_zero(args.app)) {
+		ast_log(LOG_WARNING, "Invalid applicationmap syntax for '%s'. Missing required argument\n", var->name);
+		return -1;
+	}
+
+	if (!strcasecmp(args.activate_on, "self")) {
+		activate_on_self = 1;
+	} else if (!strcasecmp(args.activate_on, "peer")) {
+		activate_on_self = 0;
+	} else {
+		ast_log(LOG_WARNING, "Invalid 'activate_on' value %s for applicationmap item %s\n",
+			args.activate_on, var->name);
+		return -1;
+	}
+
+	item = ao2_alloc(sizeof(*item), applicationmap_item_destructor);
+
+	if (!item || ast_string_field_init(item, 64)) {
+		return -1;
+	}
+
+	ast_string_field_set(item, name, var->name);
+	ast_string_field_set(item, dtmf, args.dtmf);
+	ast_string_field_set(item, app, args.app);
+	ast_string_field_set(item, app_data, args.app_data);
+	ast_string_field_set(item, moh_class, args.moh_class);
+	item->activate_on_self = activate_on_self;
+
+	ao2_link(applicationmap, item);
+
 	return 0;
 }
 




More information about the asterisk-commits mailing list