External MWI AMI support.
authorRichard Mudgett <rmudgett@digium.com>
Mon, 6 Jan 2014 17:49:05 +0000 (17:49 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Mon, 6 Jan 2014 17:49:05 +0000 (17:49 +0000)
The external MWI AMI interface provides a thin wrapper around the core
external MWI resource.

The resource adds the following AMI actions:
MWIGet,
MWIDelete, and
MWIUpdate.

(closes issue AFS-46)

Review: https://reviewboard.asterisk.org/r/3061/
........

Merged revisions 404954 from http://svn.asterisk.org/svn/asterisk/branches/12

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@404955 65c4cc65-6c06-0410-ace0-fbb531ad65f3

res/res_mwi_external_ami.c [new file with mode: 0644]

diff --git a/res/res_mwi_external_ami.c b/res/res_mwi_external_ami.c
new file mode 100644 (file)
index 0000000..1abb7b5
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Digium, Inc.
+ *
+ * Richard Mudgett <rmudgett@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief AMI wrapper for external MWI.
+ *
+ * \author Richard Mudgett <rmudgett@digium.com>
+ *
+ * See Also:
+ * \arg \ref AstCREDITS
+ */
+
+/*** MODULEINFO
+       <depend>res_mwi_external</depend>
+       <support_level>core</support_level>
+ ***/
+
+
+/*** DOCUMENTATION
+       <manager name="MWIGet" language="en_US">
+               <synopsis>
+                       Get selected mailboxes with message counts.
+               </synopsis>
+               <syntax>
+                       <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+                       <parameter name="Mailbox" required="true">
+                               <para>Mailbox ID in the form of
+                               /<replaceable>regex</replaceable>/ for all mailboxes matching the regular
+                               expression.  Otherwise it is for a specific mailbox.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Get a list of mailboxes with their message counts.</para>
+               </description>
+       </manager>
+       <managerEvent language="en_US" name="MWIGet">
+               <managerEventInstance class="EVENT_FLAG_REPORTING">
+                       <synopsis>
+                               Raised in response to a MWIGet command.
+                       </synopsis>
+                       <syntax>
+                               <parameter name="ActionID" required="false"/>
+                               <parameter name="Mailbox">
+                                       <para>Specific mailbox ID.</para>
+                               </parameter>
+                               <parameter name="OldMessages">
+                                       <para>The number of old messages in the mailbox.</para>
+                               </parameter>
+                               <parameter name="NewMessages">
+                                       <para>The number of new messages in the mailbox.</para>
+                               </parameter>
+                       </syntax>
+                       <see-also>
+                               <ref type="manager">MWIGet</ref>
+                       </see-also>
+               </managerEventInstance>
+       </managerEvent>
+       <managerEvent language="en_US" name="MWIGetComplete">
+               <managerEventInstance class="EVENT_FLAG_REPORTING">
+                       <synopsis>
+                               Raised in response to a MWIGet command.
+                       </synopsis>
+                       <syntax>
+                               <parameter name="ActionID" required="false"/>
+                               <parameter name="EventList" />
+                               <parameter name="ListItems">
+                                       <para>The number of mailboxes reported.</para>
+                               </parameter>
+                       </syntax>
+                       <see-also>
+                               <ref type="manager">MWIGet</ref>
+                       </see-also>
+               </managerEventInstance>
+       </managerEvent>
+       <manager name="MWIDelete" language="en_US">
+               <synopsis>
+                       Delete selected mailboxes.
+               </synopsis>
+               <syntax>
+                       <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+                       <xi:include xpointer="xpointer(/docs/manager[@name='MWIGet']/syntax/parameter[@name='Mailbox'])" />
+               </syntax>
+               <description>
+                       <para>Delete the specified mailboxes.</para>
+               </description>
+       </manager>
+       <manager name="MWIUpdate" language="en_US">
+               <synopsis>
+                       Update the mailbox message counts.
+               </synopsis>
+               <syntax>
+                       <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+                       <parameter name="Mailbox" required="true">
+                               <para>Specific mailbox ID.</para>
+                       </parameter>
+                       <parameter name="OldMessages">
+                               <para>The number of old messages in the mailbox.  Defaults
+                               to zero if missing.</para>
+                       </parameter>
+                       <parameter name="NewMessages">
+                               <para>The number of new messages in the mailbox.  Defaults
+                               to zero if missing.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Update the mailbox message counts.</para>
+               </description>
+       </manager>
+ ***/
+
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/module.h"
+#include "asterisk/res_mwi_external.h"
+#include "asterisk/manager.h"
+
+/* ------------------------------------------------------------------- */
+
+/*!
+ * \internal
+ * \brief Get the requested mailboxes.
+ * \since 12.1.0
+ *
+ * \param s AMI session.
+ * \param m AMI message.
+ *
+ * \retval 0 to keep AMI connection.
+ * \retval -1 to disconnect AMI connection.
+ */
+static int mwi_mailbox_get(struct mansession *s, const struct message *m)
+{
+       char id_text[256];
+       const char *id;
+       const char *mailbox_id = astman_get_header(m, "Mailbox");
+       const struct ast_mwi_mailbox_object *mailbox;
+       struct ao2_container *mailboxes;
+       unsigned count;
+       struct ao2_iterator iter;
+
+       if (ast_strlen_zero(mailbox_id)) {
+               astman_send_error(s, m, "Missing mailbox parameter in request");
+               return 0;
+       }
+
+       if (*mailbox_id == '/') {
+               struct ast_str *regex_string;
+
+               regex_string = ast_str_create(strlen(mailbox_id) + 1);
+               if (!regex_string) {
+                       astman_send_error(s, m, "Memory Allocation Failure");
+                       return 0;
+               }
+
+               /* Make "/regex/" into "regex" */
+               if (ast_regex_string_to_regex_pattern(mailbox_id, &regex_string) != 0) {
+                       astman_send_error_va(s, m, "Mailbox regex format invalid in: %s", mailbox_id);
+                       ast_free(regex_string);
+                       return 0;
+               }
+
+               mailboxes = ast_mwi_mailbox_get_by_regex(ast_str_buffer(regex_string));
+               ast_free(regex_string);
+       } else {
+               mailboxes = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL, NULL);
+               if (mailboxes) {
+                       mailbox = ast_mwi_mailbox_get(mailbox_id);
+                       if (mailbox) {
+                               if (!ao2_link(mailboxes, (void *) mailbox)) {
+                                       ao2_ref(mailboxes, -1);
+                                       mailboxes = NULL;
+                               }
+                               ast_mwi_mailbox_unref(mailbox);
+                       }
+               }
+       }
+       if (!mailboxes) {
+               astman_send_error(s, m, "Mailbox container creation failure");
+               return 0;
+       }
+
+       astman_send_listack(s, m, "Mailboxes will follow", "start");
+
+       id = astman_get_header(m, "ActionID");
+       if (!ast_strlen_zero(id)) {
+               snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
+       } else {
+               id_text[0] = '\0';
+       }
+
+       /* Output mailbox list. */
+       count = 0;
+       iter = ao2_iterator_init(mailboxes, AO2_ITERATOR_UNLINK);
+       for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) {
+               ++count;
+               astman_append(s,
+                       "Event: MWIGet\r\n"
+                       "Mailbox: %s\r\n"
+                       "OldMessages: %u\r\n"
+                       "NewMessages: %u\r\n"
+                       "%s"
+                       "\r\n",
+                       ast_mwi_mailbox_get_id(mailbox),
+                       ast_mwi_mailbox_get_msgs_old(mailbox),
+                       ast_mwi_mailbox_get_msgs_new(mailbox),
+                       id_text);
+       }
+       ao2_iterator_destroy(&iter);
+       ao2_ref(mailboxes, -1);
+
+       astman_append(s,
+               "Event: MWIGetComplete\r\n"
+               "EventList: Complete\r\n"
+               "ListItems: %d\r\n"
+               "%s"
+               "\r\n", count, id_text);
+
+       return 0;
+}
+
+/*!
+ * \internal
+ * \brief Delete the requested mailboxes.
+ * \since 12.1.0
+ *
+ * \param s AMI session.
+ * \param m AMI message.
+ *
+ * \retval 0 to keep AMI connection.
+ * \retval -1 to disconnect AMI connection.
+ */
+static int mwi_mailbox_delete(struct mansession *s, const struct message *m)
+{
+       const char *mailbox_id = astman_get_header(m, "Mailbox");
+
+       if (ast_strlen_zero(mailbox_id)) {
+               astman_send_error(s, m, "Missing mailbox parameter in request");
+               return 0;
+       }
+
+       if (*mailbox_id == '/') {
+               struct ast_str *regex_string;
+
+               regex_string = ast_str_create(strlen(mailbox_id) + 1);
+               if (!regex_string) {
+                       astman_send_error(s, m, "Memory Allocation Failure");
+                       return 0;
+               }
+
+               /* Make "/regex/" into "regex" */
+               if (ast_regex_string_to_regex_pattern(mailbox_id, &regex_string) != 0) {
+                       astman_send_error_va(s, m, "Mailbox regex format invalid in: %s", mailbox_id);
+                       ast_free(regex_string);
+                       return 0;
+               }
+
+               ast_mwi_mailbox_delete_by_regex(ast_str_buffer(regex_string));
+               ast_free(regex_string);
+       } else {
+               ast_mwi_mailbox_delete(mailbox_id);
+       }
+
+       astman_send_ack(s, m, NULL);
+       return 0;
+}
+
+/*!
+ * \internal
+ * \brief Update the specified mailbox.
+ * \since 12.1.0
+ *
+ * \param s AMI session.
+ * \param m AMI message.
+ *
+ * \retval 0 to keep AMI connection.
+ * \retval -1 to disconnect AMI connection.
+ */
+static int mwi_mailbox_update(struct mansession *s, const struct message *m)
+{
+       const char *mailbox_id = astman_get_header(m, "Mailbox");
+       const char *msgs_old = astman_get_header(m, "OldMessages");
+       const char *msgs_new = astman_get_header(m, "NewMessages");
+       struct ast_mwi_mailbox_object *mailbox;
+       unsigned int num_old;
+       unsigned int num_new;
+
+       if (ast_strlen_zero(mailbox_id)) {
+               astman_send_error(s, m, "Missing mailbox parameter in request");
+               return 0;
+       }
+
+       num_old = 0;
+       if (!ast_strlen_zero(msgs_old)) {
+               if (sscanf(msgs_old, "%u", &num_old) != 1) {
+                       astman_send_error_va(s, m, "Invalid OldMessages: %s", msgs_old);
+                       return 0;
+               }
+       }
+
+       num_new = 0;
+       if (!ast_strlen_zero(msgs_new)) {
+               if (sscanf(msgs_new, "%u", &num_new) != 1) {
+                       astman_send_error_va(s, m, "Invalid NewMessages: %s", msgs_new);
+                       return 0;
+               }
+       }
+
+       mailbox = ast_mwi_mailbox_alloc(mailbox_id);
+       if (!mailbox) {
+               astman_send_error(s, m, "Mailbox object creation failure");
+               return 0;
+       }
+
+       /* Update external mailbox. */
+       ast_mwi_mailbox_set_msgs_old(mailbox, num_old);
+       ast_mwi_mailbox_set_msgs_new(mailbox, num_new);
+       if (ast_mwi_mailbox_update(mailbox)) {
+               astman_send_error(s, m, "Update attempt failed");
+       } else {
+               astman_send_ack(s, m, NULL);
+       }
+       ast_mwi_mailbox_unref(mailbox);
+
+       return 0;
+}
+
+static int unload_module(void)
+{
+       ast_manager_unregister("MWIGet");
+       ast_manager_unregister("MWIDelete");
+       ast_manager_unregister("MWIUpdate");
+
+       /* Must be done last */
+       ast_mwi_external_unref();
+       return 0;
+}
+
+static int load_module(void)
+{
+       int res;
+
+       /* Must be done first */
+       ast_mwi_external_ref();
+
+       res = 0;
+       res |= ast_manager_register_xml_core("MWIGet", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, mwi_mailbox_get);
+       res |= ast_manager_register_xml_core("MWIDelete", EVENT_FLAG_CALL, mwi_mailbox_delete);
+       res |= ast_manager_register_xml_core("MWIUpdate", EVENT_FLAG_CALL, mwi_mailbox_update);
+       if (res) {
+               unload_module();
+               return AST_MODULE_LOAD_DECLINE;
+       }
+
+       return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "AMI support for external MWI",
+       .load = load_module,
+       .unload = unload_module,
+);
+