Add VoicemailRefresh AMI Action
authorKinsey Moore <kmoore@digium.com>
Thu, 27 Sep 2012 17:02:13 +0000 (17:02 +0000)
committerKinsey Moore <kmoore@digium.com>
Thu, 27 Sep 2012 17:02:13 +0000 (17:02 +0000)
Currently, if there are modifications to mailboxes that Asterisk is
not aware of, the user needs to add "pollmailboxes" to their mailbox
configuration, which repeatedly polls the subscribed mailboxes for
changes. This results in a lot of extra work for the CPU. This patch
introduces the AMI command VoicemailRefresh which permits external
applications to trigger the refresh themselves. The refresh can apply
to a specified mailbox only, an entire context, or all configured
mailboxes. Even a refresh performed on every mailbox would not consume
as much CPU as the pollmailboxes option, given that pollmailboxes runs
continuously and this only runs on demand.

(closes issue ASTERISK-17206)
(closes issue ASTERISK-19908)
Reported-by: Jeff Hutchins
Reported-by: Tilghman Lesher
Patch-by: Tilghman Lesher

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

CHANGES
apps/app_voicemail.c

diff --git a/CHANGES b/CHANGES
index e2fea7b..8372850 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -17,6 +17,9 @@ AMI (Asterisk Manager Interface)
    that the request is against a known peer. It also issues a new event,
    'SIPqualifypeerdone', once the qualify action has been completed.
 
+ * Added VoicemailRefresh action to allow an external entity to trigger mailbox
+   updates when changes occur instead of requiring the use of pollmailboxes.
+
 Logging
 -------------------
  * When performing queue pause/unpause on an interface without specifying an
index 4ee9e43..5e8b4e8 100644 (file)
@@ -455,6 +455,33 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
                <description>
                </description>
        </manager>
+       <manager name="VoicemailRefresh" language="en_US">
+               <synopsis>
+                       Tell Asterisk to poll mailboxes for a change
+               </synopsis>
+               <syntax>
+                       <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+                       <parameter name="Context" />
+                       <parameter name="Mailbox" />
+               </syntax>
+               <description>
+                       <para>Normally, MWI indicators are only sent when Asterisk itself
+                       changes a mailbox.  With external programs that modify the content
+                       of a mailbox from outside the application, an option exists called
+                       <literal>pollmailboxes</literal> that will cause voicemail to
+                       continually scan all mailboxes on a system for changes.  This can
+                       cause a large amount of load on a system.  This command allows
+                       external applications to signal when a particular mailbox has
+                       changed, thus permitting external applications to modify mailboxes
+                       and MWI to work without introducing considerable CPU load.</para>
+                       <para>If <replaceable>Context</replaceable> is not specified, all
+                       mailboxes on the system will be polled for changes.  If
+                       <replaceable>Context</replaceable> is specified, but
+                       <replaceable>Mailbox</replaceable> is omitted, then all mailboxes
+                       within <replaceable>Context</replaceable> will be polled.
+                       Otherwise, only a single mailbox will be polled for changes.</para>
+               </description>
+       </manager>
  ***/
 
 #ifdef IMAP_STORAGE
@@ -12646,6 +12673,42 @@ static void stop_poll_thread(void)
        poll_thread = AST_PTHREADT_NULL;
 }
 
+static int manager_voicemail_refresh(struct mansession *s, const struct message *m)
+{
+       const char *context = astman_get_header(m, "Context");
+       const char *mailbox = astman_get_header(m, "Mailbox");
+       struct mwi_sub *mwi_sub;
+       const char *at;
+
+       AST_RWLIST_RDLOCK(&mwi_subs);
+       AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
+               if (!ast_strlen_zero(mwi_sub->mailbox)) {
+                       if (
+                               /* First case: everything matches */
+                               (ast_strlen_zero(context) && ast_strlen_zero(mailbox)) ||
+                               /* Second case: match the mailbox only */
+                               (ast_strlen_zero(context) && !ast_strlen_zero(mailbox) &&
+                                       (at = strchr(mwi_sub->mailbox, '@')) &&
+                                       strncmp(mailbox, mwi_sub->mailbox, at - mwi_sub->mailbox) == 0) ||
+                               /* Third case: match the context only */
+                               (!ast_strlen_zero(context) && ast_strlen_zero(mailbox) &&
+                                       (at = strchr(mwi_sub->mailbox, '@')) &&
+                                       strcmp(context, at + 1) == 0) ||
+                               /* Final case: match an exact specified mailbox */
+                               (!ast_strlen_zero(context) && !ast_strlen_zero(mailbox) &&
+                                       (at = strchr(mwi_sub->mailbox, '@')) &&
+                                       strncmp(mailbox, mwi_sub->mailbox, at - mwi_sub->mailbox) == 0 &&
+                                       strcmp(context, at + 1) == 0)
+                       ) {
+                               poll_subscribed_mailbox(mwi_sub);
+                       }
+               }
+       }
+       AST_RWLIST_UNLOCK(&mwi_subs);
+       astman_send_ack(s, m, "Refresh sent");
+       return RESULT_SUCCESS;
+}
+
 /*! \brief Manager list voicemail users command */
 static int manager_list_voicemail_users(struct mansession *s, const struct message *m)
 {
@@ -14185,6 +14248,7 @@ static int unload_module(void)
        res |= ast_custom_function_unregister(&mailbox_exists_acf);
        res |= ast_custom_function_unregister(&vm_info_acf);
        res |= ast_manager_unregister("VoicemailUsersList");
+       res |= ast_manager_unregister("VoicemailRefresh");
        res |= ast_data_unregister(NULL);
 #ifdef TEST_FRAMEWORK
        res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
@@ -14242,6 +14306,7 @@ static int load_module(void)
        res |= ast_custom_function_register(&mailbox_exists_acf);
        res |= ast_custom_function_register(&vm_info_acf);
        res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
+       res |= ast_manager_register_xml("VoicemailRefresh", EVENT_FLAG_USER, manager_voicemail_refresh);
 #ifdef TEST_FRAMEWORK
        res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
        res |= AST_TEST_REGISTER(test_voicemail_msgcount);