[Asterisk-code-review] app voicemail: Add Mailbox Aliases (asterisk[16])

George Joseph asteriskteam at digium.com
Tue Dec 11 14:09:32 CST 2018


George Joseph has uploaded this change for review. ( https://gerrit.asterisk.org/10800


Change subject: app_voicemail:  Add Mailbox Aliases
......................................................................

app_voicemail:  Add Mailbox Aliases

You can now define an "aliases" context in voicemail.conf
whose entries point to actual mailboxes.  These can be used anywhere
the mailbox is specified.

Example:
[default]
1234 at default = yadayada

[aliases]
4321 at devices = 1234 at default

Now you can use 4321 at devices to refer to the 1234 at default mailbox.

Change-Id: I395b9205c91523a334fe971be0d1de4522067b04
---
M CHANGES
M apps/app_voicemail.c
M configs/samples/voicemail.conf.sample
M res/res_pjsip_mwi.c
4 files changed, 231 insertions(+), 44 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/00/10800/1

diff --git a/CHANGES b/CHANGES
index 465f337..d379977 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,15 @@
 ==============================================================================
 
 ------------------------------------------------------------------------------
+--- Functionality changes from Asterisk 16.1.0 to Asterisk 16.2.0 ------------
+------------------------------------------------------------------------------
+
+app_voicemail
+------------------
+ * You can now specify a special context named "aliases" in voicemail.conf
+   which will allow you to create aliases for physical mailboxes. 
+
+------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 16.0.0 to Asterisk 16.1.0 ------------
 ------------------------------------------------------------------------------
 
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 13dedd3..77309ff 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -1051,6 +1051,27 @@
 
 static AST_RWLIST_HEAD_STATIC(mwi_subs, mwi_sub);
 
+struct alias_mailbox_mapping {
+	char *alias;
+	char *mailbox;
+	char buf[0];
+};
+
+struct mailbox_alias_mapping {
+	char *alias;
+	char *mailbox;
+	char buf[0];
+};
+
+#define MAPPING_BUCKETS 511
+static struct ao2_container *alias_mailbox_mappings;
+AO2_STRING_FIELD_HASH_FN(alias_mailbox_mapping, alias);
+AO2_STRING_FIELD_CMP_FN(alias_mailbox_mapping, alias);
+
+static struct ao2_container *mailbox_alias_mappings;
+AO2_STRING_FIELD_HASH_FN(mailbox_alias_mapping, mailbox);
+AO2_STRING_FIELD_CMP_FN(mailbox_alias_mapping, mailbox);
+
 /* custom audio control prompts for voicemail playback */
 static char listen_control_forward_key[12];
 static char listen_control_reverse_key[12];
@@ -1765,9 +1786,31 @@
 			ast_set2_flag(vmu, !ivm, VM_ALLOCED);
 			AST_LIST_NEXT(vmu, list) = NULL;
 		}
-	} else
-		vmu = find_user_realtime(ivm, context, mailbox);
+	}
 	AST_LIST_UNLOCK(&users);
+	if (!vmu) {
+		vmu = find_user_realtime(ivm, context, mailbox);
+	}
+	if (!vmu) {
+		struct alias_mailbox_mapping *mapping;
+		size_t len = sizeof(vmu->mailbox) + sizeof(vmu->context) + sizeof('@') + 1;
+		char *search_string = ast_alloca(len);
+
+		len = snprintf(search_string, len, "%s%s%s",
+			mailbox,
+			ast_strlen_zero(context) ? "" : "@",
+			S_OR(context, ""));
+
+		mapping = ao2_find(alias_mailbox_mappings, search_string, OBJ_SEARCH_KEY);
+		if (mapping) {
+			char *search_mailbox;
+			char *search_context;
+
+			separate_mailbox(ast_strdupa(mapping->mailbox), &search_mailbox, &search_context);
+			vmu = find_user(ivm, search_mailbox, search_context);
+		}
+	}
+
 	return vmu;
 }
 
@@ -6046,7 +6089,11 @@
 	DIR *dir;
 	struct dirent *de;
 	char fn[256];
+	char tmp[256];
 	int ret = 0;
+	struct alias_mailbox_mapping *mapping;
+	char *c;
+	char *m;
 
 	/* If no mailbox, return immediately */
 	if (ast_strlen_zero(mailbox))
@@ -6057,7 +6104,17 @@
 	if (ast_strlen_zero(context))
 		context = "default";
 
-	snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
+	snprintf(tmp, sizeof(tmp), "%s@%s", mailbox, context);
+	mapping = ao2_find(alias_mailbox_mappings, tmp, OBJ_SEARCH_KEY);
+	if (mapping) {
+		separate_mailbox(ast_strdupa(mapping->mailbox), &m, &c);
+		ao2_ref(mapping, -1);
+	} else {
+		c = (char *)context;
+		m = (char *)mailbox;
+	}
+
+	snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, c, m, folder);
 
 	if (!(dir = opendir(fn)))
 		return 0;
@@ -8081,12 +8138,26 @@
 {
 	char *mailbox;
 	char *context;
+	struct ao2_iterator *aliases;
+	struct mailbox_alias_mapping *mapping;
 
 	if (separate_mailbox(ast_strdupa(box), &mailbox, &context)) {
 		return;
 	}
 
+	ast_debug(3, "Queueing event for mailbox %s\n", box);
 	ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
+
+	aliases = ao2_find(mailbox_alias_mappings, box, OBJ_SEARCH_KEY | OBJ_MULTIPLE);
+	while ((mapping = ao2_iterator_next(aliases))) {
+		mailbox = NULL;
+		context = NULL;
+		ast_debug(3, "Found alias mapping: %s -> %s\n", mapping->alias, box);
+		separate_mailbox(ast_strdupa(mapping->alias), &mailbox, &context);
+		ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
+		ao2_ref(mapping, -1);
+	}
+	ao2_iterator_destroy(aliases);
 }
 
 /*!
@@ -13234,7 +13305,6 @@
 	if (stasis_message_type(msg) != stasis_subscription_change_type()) {
 		return;
 	}
-
 	change = stasis_message_data(msg);
 	if (change->topic == ast_mwi_topic_all()) {
 		return;
@@ -13652,11 +13722,95 @@
 }
 #endif
 
+static struct alias_mailbox_mapping *alias_mailbox_mapping_create(const char *alias, const char *mailbox)
+{
+	struct alias_mailbox_mapping *mapping;
+	size_t from_len = strlen(alias) + 1;
+	size_t to_len = strlen(mailbox) + 1;
+
+	mapping = ao2_alloc(sizeof(*mapping) + from_len + to_len, NULL);
+	if (!mapping) {
+		return NULL;
+	}
+	mapping->alias = mapping->buf;
+	mapping->mailbox = mapping->buf + from_len;
+	strcpy(mapping->alias, alias); /* Safe */
+	strcpy(mapping->mailbox, mailbox); /* Safe */
+
+	return mapping;
+}
+
+static void load_aliases(struct ast_config *cfg)
+{
+	struct ast_variable *var;
+
+	var = ast_variable_browse(cfg, "aliases");
+	while (var) {
+		struct alias_mailbox_mapping *mapping = alias_mailbox_mapping_create(var->name, var->value);
+		if (mapping) {
+			ao2_link(alias_mailbox_mappings, mapping);
+			ao2_link(mailbox_alias_mappings, mapping);
+			ao2_ref(mapping, -1);
+		}
+		var = var->next;
+	}
+}
+
+static void load_zonemessages(struct ast_config *cfg)
+{
+	struct ast_variable *var;
+
+	var = ast_variable_browse(cfg, "zonemessages");
+	while (var) {
+		struct vm_zone *z;
+		char *msg_format, *tzone;
+
+		z = ast_malloc(sizeof(*z));
+		if (!z) {
+			return;
+		}
+
+		msg_format = ast_strdupa(var->value);
+		tzone = strsep(&msg_format, "|,");
+		if (msg_format) {
+			ast_copy_string(z->name, var->name, sizeof(z->name));
+			ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
+			ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
+			AST_LIST_LOCK(&zones);
+			AST_LIST_INSERT_HEAD(&zones, z, list);
+			AST_LIST_UNLOCK(&zones);
+		} else {
+			ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
+			ast_free(z);
+		}
+		var = var->next;
+	}
+}
+
+static void load_users(struct ast_config *cfg)
+{
+	struct ast_variable *var;
+	char *cat = NULL;
+
+	while ((cat = ast_category_browse(cfg, cat))) {
+		if (strcasecmp(cat, "general") == 0
+			|| strcasecmp(cat, "aliases") == 0
+			|| strcasecmp(cat, "zonemessages") == 0) {
+			continue;
+		}
+
+		var = ast_variable_browse(cfg, cat);
+		while (var) {
+			append_mailbox(cat, var->name, var->value);
+			var = var->next;
+		}
+	}
+}
+
 static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg)
 {
 	struct ast_vm_user *current;
 	char *cat;
-	struct ast_variable *var;
 	const char *val;
 	char *q, *stringp, *tmp;
 	int x;
@@ -13685,6 +13839,10 @@
 	/* Free all the zones structure */
 	free_vm_zones();
 
+	/* Remove all aliases */
+	ao2_callback(alias_mailbox_mappings, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
+	ao2_callback(mailbox_alias_mappings, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
+
 	AST_LIST_LOCK(&users);
 
 	memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
@@ -14297,45 +14455,16 @@
 		}
 
 		/* load mailboxes from voicemail.conf */
-		cat = ast_category_browse(cfg, NULL);
-		while (cat) {
-			if (strcasecmp(cat, "general")) {
-				var = ast_variable_browse(cfg, cat);
-				if (strcasecmp(cat, "zonemessages")) {
-					/* Process mailboxes in this context */
-					while (var) {
-						append_mailbox(cat, var->name, var->value);
-						var = var->next;
-					}
-				} else {
-					/* Timezones in this context */
-					while (var) {
-						struct vm_zone *z;
-						if ((z = ast_malloc(sizeof(*z)))) {
-							char *msg_format, *tzone;
-							msg_format = ast_strdupa(var->value);
-							tzone = strsep(&msg_format, "|,");
-							if (msg_format) {
-								ast_copy_string(z->name, var->name, sizeof(z->name));
-								ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
-								ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
-								AST_LIST_LOCK(&zones);
-								AST_LIST_INSERT_HEAD(&zones, z, list);
-								AST_LIST_UNLOCK(&zones);
-							} else {
-								ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
-								ast_free(z);
-							}
-						} else {
-							AST_LIST_UNLOCK(&users);
-							return -1;
-						}
-						var = var->next;
-					}
-				}
-			}
-			cat = ast_category_browse(cfg, cat);
-		}
+
+		/*
+		 * Aliases must be loaded before users or the aliases won't be notified
+		 * if there's existing voicemail in the user mailbox.
+		 */
+		load_aliases(cfg);
+
+		load_zonemessages(cfg);
+
+		load_users(cfg);
 
 		AST_LIST_UNLOCK(&users);
 
@@ -15086,6 +15215,16 @@
 	return res;
 }
 
+static void print_mappings(void *v_obj, void *where, ao2_prnt_fn *prnt)
+{
+	struct alias_mailbox_mapping *mapping = v_obj;
+
+	if (!mapping) {
+		return;
+	}
+	prnt(where, "Alias: %s Mailbox: %s", mapping->alias, mapping->mailbox);
+}
+
 /*!
  * \brief Load the module
  *
@@ -15112,6 +15251,38 @@
 		return AST_MODULE_LOAD_DECLINE;
 	}
 
+	alias_mailbox_mappings = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, MAPPING_BUCKETS,
+		alias_mailbox_mapping_hash_fn, NULL, alias_mailbox_mapping_cmp_fn);
+	if (!alias_mailbox_mappings) {
+		ast_log(LOG_ERROR, "Unable to create alias_mailbox_mappings container\n");
+		ao2_cleanup(inprocess_container);
+		return AST_MODULE_LOAD_DECLINE;
+	}
+	res = ao2_container_register("voicemail_alias_mailbox_mappings", alias_mailbox_mappings, print_mappings);
+	if (res) {
+		ast_log(LOG_ERROR, "Unable to register alias_mailbox_mappings container\n");
+		ao2_cleanup(inprocess_container);
+		ao2_cleanup(alias_mailbox_mappings);
+		return AST_MODULE_LOAD_DECLINE;
+	}
+
+	mailbox_alias_mappings = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, MAPPING_BUCKETS,
+		mailbox_alias_mapping_hash_fn, NULL, mailbox_alias_mapping_cmp_fn);
+	if (!mailbox_alias_mappings) {
+		ast_log(LOG_ERROR, "Unable to create mailbox_alias_mappings container\n");
+		ao2_cleanup(inprocess_container);
+		ao2_cleanup(alias_mailbox_mappings);
+		return AST_MODULE_LOAD_DECLINE;
+	}
+	res = ao2_container_register("voicemail_mailbox_alias_mappings", mailbox_alias_mappings, print_mappings);
+	if (res) {
+		ast_log(LOG_ERROR, "Unable to register mailbox_alias_mappings container\n");
+		ao2_cleanup(inprocess_container);
+		ao2_cleanup(alias_mailbox_mappings);
+		ao2_cleanup(mailbox_alias_mappings);
+		return AST_MODULE_LOAD_DECLINE;
+	}
+
 	/* compute the location of the voicemail spool directory */
 	snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
 
diff --git a/configs/samples/voicemail.conf.sample b/configs/samples/voicemail.conf.sample
index e4130d3..aae1eda 100644
--- a/configs/samples/voicemail.conf.sample
+++ b/configs/samples/voicemail.conf.sample
@@ -452,6 +452,11 @@
 ;4235 => 1234,Jim Holmes,jim at astricon.ips,,Tz=european
 
 
+; aliases allow alternate references to mailboxes.
+[aliases]
+1234 at devices => 1234 at default
+;6200 at devices => 4200 at default
+
 ;
 ; Mailboxes may be organized into multiple contexts for
 ; voicemail virtualhosting
diff --git a/res/res_pjsip_mwi.c b/res/res_pjsip_mwi.c
index eeb8a18..dff8565 100644
--- a/res/res_pjsip_mwi.c
+++ b/res/res_pjsip_mwi.c
@@ -436,6 +436,7 @@
 	struct ast_sip_message_accumulator *counter = arg;
 	struct ast_mwi_state *mwi_state;
 
+	ast_debug(2, "Searching for %s\n", mwi_stasis->mailbox);
 	msg = stasis_cache_get(ast_mwi_state_cache(), ast_mwi_state_type(), mwi_stasis->mailbox);
 	if (!msg) {
 		return 0;
@@ -444,6 +445,7 @@
 	mwi_state = stasis_message_data(msg);
 	counter->old_msgs += mwi_state->old_msgs;
 	counter->new_msgs += mwi_state->new_msgs;
+	ast_debug(2, "Found %s Old: %d New: %d\n", mwi_stasis->mailbox, counter->old_msgs, counter->new_msgs);
 
 	ao2_ref(msg, -1);
 

-- 
To view, visit https://gerrit.asterisk.org/10800
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 16
Gerrit-MessageType: newchange
Gerrit-Change-Id: I395b9205c91523a334fe971be0d1de4522067b04
Gerrit-Change-Number: 10800
Gerrit-PatchSet: 1
Gerrit-Owner: George Joseph <gjoseph at digium.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20181211/e7a5cfad/attachment-0001.html>


More information about the asterisk-code-review mailing list