[Asterisk-code-review] realtime: Fix ast load realtime multientry handling (asterisk[master])

Sean Bright asteriskteam at digium.com
Tue Feb 21 13:06:30 CST 2017


Sean Bright has uploaded a new change for review. ( https://gerrit.asterisk.org/5051 )

Change subject: realtime: Fix ast_load_realtime_multientry handling
......................................................................

realtime: Fix ast_load_realtime_multientry handling

ast_load_realtime_multientry() returns an ast_config structure whose
ast_categorys are keyed with the empty strings. Several modules were
giving semantic meaning to the category names causing problems at
runtime.

* app_directory: Treated the category name as the mailbox name, and
  would fail to direct calls to the appropriate extension after an
  entry was chosen.

* app_queue: Queues, queue members, and queue rules were all affected
  and needed to be updated.

* pbx_realtime: Pattern matching would never succeed because the
  extension entered by the user was always compared to the empty
  string.

Change-Id: Ie7e44986344b0b76ea8f6ddb5879f5040c6ca8a7
---
M apps/app_directory.c
M apps/app_queue.c
M pbx/pbx_realtime.c
3 files changed, 52 insertions(+), 44 deletions(-)


  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/51/5051/1

diff --git a/apps/app_directory.c b/apps/app_directory.c
index 642b9b2..dd80c34 100644
--- a/apps/app_directory.c
+++ b/apps/app_directory.c
@@ -464,7 +464,7 @@
 	struct ast_config *rtdata = NULL;
 	struct ast_category *cat;
 	struct ast_variable *var;
-	char *mailbox;
+	char *category = NULL;
 	const char *fullname;
 	const char *hidefromdir, *searchcontexts = NULL;
 	struct ast_flags config_flags = { 0 };
@@ -505,13 +505,12 @@
 		return cfg;
 	}
 
-	mailbox = NULL;
-	while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) {
-		struct ast_variable *alias;
-		const char *ctx = ast_variable_retrieve(rtdata, mailbox, "context");
+	while ((category = ast_category_browse(rtdata, category))) {
+		const char *mailbox = ast_variable_retrieve(rtdata, category, "mailbox");
+		const char *ctx = ast_variable_retrieve(rtdata, category, "context");
 
-		fullname = ast_variable_retrieve(rtdata, mailbox, "fullname");
-		hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir");
+		fullname = ast_variable_retrieve(rtdata, category, "fullname");
+		hidefromdir = ast_variable_retrieve(rtdata, category, "hidefromdir");
 		if (ast_true(hidefromdir)) {
 			/* Skip hidden */
 			continue;
@@ -519,8 +518,9 @@
 
 		/* password,Full Name,email,pager,options */
 		ast_str_set(&tmp, 0, "no-password,%s,,,", S_OR(fullname, ""));
-		if (ast_variable_retrieve(rtdata, mailbox, "alias")) {
-			for (alias = ast_variable_browse(rtdata, mailbox); alias; alias = alias->next) {
+		if (ast_variable_retrieve(rtdata, category, "alias")) {
+			struct ast_variable *alias;
+			for (alias = ast_variable_browse(rtdata, category); alias; alias = alias->next) {
 				if (!strcasecmp(alias->name, "alias")) {
 					ast_str_append(&tmp, 0, "|alias=%s", alias->value);
 				}
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 95f4c0e..204b4b2 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -2914,13 +2914,19 @@
 		ast_log(LOG_WARNING, "Failed to load queue rules from realtime\n");
 		return 0;
 	}
-	while ((rulecat = ast_category_browse(cfg, rulecat)) && !ast_strlen_zero(rulecat)) {
-		const char *timestr, *maxstr, *minstr;
+	while ((rulecat = ast_category_browse(cfg, rulecat))) {
+		const char *timestr, *maxstr, *minstr, *rule_name;
 		int penaltychangetime, rule_exists = 0, inserted = 0;
 		int max_penalty = 0, min_penalty = 0, min_relative = 0, max_relative = 0;
 		struct penalty_rule *new_penalty_rule = NULL;
+
+		rule_name = ast_variable_retrieve(cfg, rulecat, "rule_name");
+		if (ast_strlen_zero(rule_name)) {
+			continue;
+		}
+
 		AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
-			if (!(strcasecmp(rl_iter->name, rulecat))) {
+			if (!(strcasecmp(rl_iter->name, rule_name))) {
 				rule_exists = 1;
 				new_rl = rl_iter;
 				break;
@@ -2931,13 +2937,13 @@
 				ast_config_destroy(cfg);
 				return -1;
 			}
-			ast_copy_string(new_rl->name, rulecat, sizeof(new_rl->name));
+			ast_copy_string(new_rl->name, rule_name, sizeof(new_rl->name));
 			AST_LIST_INSERT_TAIL(&rule_lists, new_rl, list);
 		}
 		timestr = ast_variable_retrieve(cfg, rulecat, "time");
 		if (!(timestr) || sscanf(timestr, "%30d", &penaltychangetime) != 1) {
 			ast_log(LOG_NOTICE, "Failed to parse time (%s) for one of the %s rules,	skipping it\n",
-				(ast_strlen_zero(timestr) ? "invalid value" : timestr), rulecat);
+				(ast_strlen_zero(timestr) ? "invalid value" : timestr), rule_name);
 			continue;
 		}
 		if (!(new_penalty_rule = ast_calloc(1, sizeof(*new_penalty_rule)))) {
@@ -3272,7 +3278,7 @@
  * Search for member in queue, if found update penalty/paused state,
  * if no member exists create one flag it as a RT member and add to queue member list.
 */
-static void rt_handle_member_record(struct call_queue *q, char *interface, struct ast_config *member_config)
+static void rt_handle_member_record(struct call_queue *q, char *category, struct ast_config *member_config)
 {
 	struct member *m;
 	struct ao2_iterator mem_iter;
@@ -3282,11 +3288,12 @@
 	int ringinuse = q->ringinuse;
 
 	const char *config_val;
-	const char *rt_uniqueid = ast_variable_retrieve(member_config, interface, "uniqueid");
-	const char *membername = S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface);
-	const char *state_interface = S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface);
-	const char *penalty_str = ast_variable_retrieve(member_config, interface, "penalty");
-	const char *paused_str = ast_variable_retrieve(member_config, interface, "paused");
+	const char *interface = ast_variable_retrieve(member_config, category, "interface");
+	const char *rt_uniqueid = ast_variable_retrieve(member_config, category, "uniqueid");
+	const char *membername = S_OR(ast_variable_retrieve(member_config, category, "membername"), interface);
+	const char *state_interface = S_OR(ast_variable_retrieve(member_config, category, "state_interface"), interface);
+	const char *penalty_str = ast_variable_retrieve(member_config, category, "penalty");
+	const char *paused_str = ast_variable_retrieve(member_config, category, "paused");
 
 	if (ast_strlen_zero(rt_uniqueid)) {
 		ast_log(LOG_WARNING, "Realtime field uniqueid is empty for member %s\n", S_OR(membername, "NULL"));
@@ -3309,7 +3316,7 @@
 		}
 	}
 
-	if ((config_val = ast_variable_retrieve(member_config, interface, realtime_ringinuse_field))) {
+	if ((config_val = ast_variable_retrieve(member_config, category, realtime_ringinuse_field))) {
 		if (ast_true(config_val)) {
 			ringinuse = 1;
 		} else if (ast_false(config_val)) {
@@ -3425,7 +3432,7 @@
 	};
 	struct member *m;
 	struct ao2_iterator mem_iter;
-	char *interface = NULL;
+	char *category = NULL;
 	const char *tmp_name;
 	char *tmp;
 	char tmpbuf[64];	/* Must be longer than the longest queue param name. */
@@ -3526,8 +3533,8 @@
 	}
 	ao2_iterator_destroy(&mem_iter);
 
-	while ((interface = ast_category_browse(member_config, interface))) {
-		rt_handle_member_record(q, interface, member_config);
+	while ((category = ast_category_browse(member_config, category))) {
+		rt_handle_member_record(q, category, member_config);
 	}
 
 	/* Delete all realtime members that have been deleted in DB. */
@@ -3636,7 +3643,7 @@
 {
 	struct ast_config *member_config = NULL;
 	struct member *m;
-	char *interface = NULL;
+	char *category = NULL;
 	struct ao2_iterator mem_iter;
 
 	if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , SENTINEL))) {
@@ -3669,8 +3676,8 @@
 	}
 	ao2_iterator_destroy(&mem_iter);
 
-	while ((interface = ast_category_browse(member_config, interface))) {
-		rt_handle_member_record(q, interface, member_config);
+	while ((category = ast_category_browse(member_config, category))) {
+		rt_handle_member_record(q, category, member_config);
 	}
 
 	/* Delete all realtime members that have been deleted in DB. */
@@ -7471,12 +7478,11 @@
 
 	if (ast_strlen_zero(queuename)) { /* This means we need to iterate through all the queues. */
 		if (ast_check_realtime("queues")) {
-			char *name;
 			queue_config = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
 			if (queue_config) {
-				for (name = ast_category_browse(queue_config, NULL);
-					 !ast_strlen_zero(name);
-					 name = ast_category_browse(queue_config, name)) {
+				char *category = NULL;
+				while ((category = ast_category_browse(queue_config, category))) {
+					const char *name = ast_variable_retrieve(queue_config, category, "name");
 					if ((q = find_load_queue_rt_friendly(name))) {
 						foundqueue++;
 						foundinterface += set_member_value_help_members(q, interface, property, value);
@@ -9381,9 +9387,10 @@
 		 * which have not yet been added to the in-core container
 		 */
 		struct ast_config *cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
-		char *queuename;
 		if (cfg) {
-			for (queuename = ast_category_browse(cfg, NULL); !ast_strlen_zero(queuename); queuename = ast_category_browse(cfg, queuename)) {
+			char *category = NULL;
+			while ((category = ast_category_browse(cfg, category))) {
+				const char *queuename = ast_variable_retrieve(cfg, category, "name");
 				if ((q = find_load_queue_rt_friendly(queuename))) {
 					queue_t_unref(q, "Done with temporary pointer");
 				}
@@ -9452,7 +9459,8 @@
 				ast_str_set(&out, 0, "      %s", mem->membername);
 				if (strcasecmp(mem->membername, mem->interface)) {
 					ast_str_append(&out, 0, " (%s", mem->interface);
-					if (!ast_strlen_zero(mem->state_interface)) {
+					if (!ast_strlen_zero(mem->state_interface)
+						&& strcmp(mem->state_interface, mem->interface)) {
 						ast_str_append(&out, 0, " from %s", mem->state_interface);
 					}
 					ast_str_append(&out, 0, ")");
@@ -11044,14 +11052,13 @@
 	struct ao2_iterator i;
 	struct call_queue *queue, *queue_realtime = NULL;
 	struct ast_config *cfg;
-	char *queuename;
 
 	/* load realtime queues. */
 	cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
 	if (cfg) {
-		for (queuename = ast_category_browse(cfg, NULL);
-				!ast_strlen_zero(queuename);
-				queuename = ast_category_browse(cfg, queuename)) {
+		char *category = NULL;
+		while ((category = ast_category_browse(cfg, category))) {
+			const char *queuename = ast_variable_retrieve(cfg, category, "name");
 			if ((queue = find_load_queue_rt_friendly(queuename))) {
 				queue_unref(queue);
 			}
diff --git a/pbx/pbx_realtime.c b/pbx/pbx_realtime.c
index 08c90aa..6f5d137 100644
--- a/pbx/pbx_realtime.c
+++ b/pbx/pbx_realtime.c
@@ -189,25 +189,26 @@
 	if (!var && !ast_test_flag(&flags, OPTION_PATTERNS_DISABLED)) {
 		cfg = ast_load_realtime_multientry(table, "exten LIKE", "\\_%", "context", context, "priority", pri, SENTINEL);	
 		if (cfg) {
-			char *cat = ast_category_browse(cfg, NULL);
+			char *cat = NULL;
 
-			while(cat) {
+			while ((cat = ast_category_browse(cfg, cat))) {
+				const char *realtime_exten = ast_variable_retrieve(cfg, cat, "exten");
+
 				switch(mode) {
 				case MODE_MATCHMORE:
-					match = ast_extension_close(cat, exten, 1);
+					match = ast_extension_close(realtime_exten, exten, 1);
 					break;
 				case MODE_CANMATCH:
-					match = ast_extension_close(cat, exten, 0);
+					match = ast_extension_close(realtime_exten, exten, 0);
 					break;
 				case MODE_MATCH:
 				default:
-					match = ast_extension_match(cat, exten);
+					match = ast_extension_match(realtime_exten, exten);
 				}
 				if (match) {
 					var = ast_category_detach_variables(ast_category_get(cfg, cat, NULL));
 					break;
 				}
-				cat = ast_category_browse(cfg, cat);
 			}
 			ast_config_destroy(cfg);
 		}

-- 
To view, visit https://gerrit.asterisk.org/5051
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie7e44986344b0b76ea8f6ddb5879f5040c6ca8a7
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Owner: Sean Bright <sean.bright at gmail.com>



More information about the asterisk-code-review mailing list