Asterisk - The Open Source Telephony Project GIT-master-7e7a603
res_mwi_external.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2013, Digium, Inc.
5 *
6 * Richard Mudgett <rmudgett@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*!
20 * \file
21 * \brief Core external MWI support.
22 *
23 * \details
24 * The module manages the persistent message counts cache and supplies
25 * an API to allow the protocol specific modules to control the counts
26 * or a subset.
27 *
28 * \author Richard Mudgett <rmudgett@digium.com>
29 *
30 * See Also:
31 * \arg \ref AstCREDITS
32 */
33
34/*** MODULEINFO
35 <defaultenabled>no</defaultenabled>
36 <support_level>core</support_level>
37 ***/
38
39/*** DOCUMENTATION
40 <configInfo name="res_mwi_external" language="en_US">
41 <synopsis>Core external MWI support</synopsis>
42 <configFile name="sorcery.conf">
43 <configObject name="mailboxes">
44 <synopsis>Persistent cache of external MWI Mailboxs.</synopsis>
45 <description>
46 <para>Allows the alteration of sorcery backend mapping for
47 the persistent cache of external MWI mailboxes.</para>
48 </description>
49 </configObject>
50 </configFile>
51 </configInfo>
52 ***/
53
54
55#include "asterisk.h"
56
57#include "asterisk/app.h"
58#include "asterisk/mwi.h"
59#include "asterisk/module.h"
61#include "asterisk/sorcery.h"
62#include "asterisk/cli.h"
63
64/* ------------------------------------------------------------------- */
65
66/*!
67 * Define to include CLI commands to manipulate the external MWI mailboxes.
68 * Useful for testing the module functionality.
69 */
70//#define MWI_DEBUG_CLI 1
71
72#define MWI_ASTDB_PREFIX "mwi_external"
73#define MWI_MAILBOX_TYPE "mailboxes"
74
77 /*! Number of new messages in mailbox. */
78 unsigned int msgs_new;
79 /*! Number of old messages in mailbox. */
80 unsigned int msgs_old;
81};
82
83static struct ast_sorcery *mwi_sorcery;
84
85/*!
86 * \internal
87 * \brief Post an update event to the MWI counts.
88 * \since 12.1.0
89 */
91{
93 mailbox->msgs_new, mailbox->msgs_old);
94}
95
96static void mwi_observe_update(const void *obj)
97{
98 mwi_post_event(obj);
99}
100
101/*!
102 * \internal
103 * \brief Post a count clearing event to the MWI counts.
104 * \since 12.1.0
105 */
106static void mwi_observe_delete(const void *obj)
107{
108 const struct ast_mwi_mailbox_object *mailbox = obj;
109
110 if (mailbox->msgs_new || mailbox->msgs_old) {
111 /* Post a count clearing event. */
113 }
114
115 /* Post a cache remove event. */
117}
118
119static const struct ast_sorcery_observer mwi_observers = {
121 .updated = mwi_observe_update,
122 .deleted = mwi_observe_delete,
123};
124
125/*! \brief Internal function to allocate a mwi object */
126static void *mwi_sorcery_object_alloc(const char *id)
127{
129}
130
131/*!
132 * \internal
133 * \brief Initialize sorcery for external MWI.
134 * \since 12.1.0
135 *
136 * \retval 0 on success.
137 * \retval -1 on error.
138 */
139static int mwi_sorcery_init(void)
140{
141 int res;
142
144 if (!mwi_sorcery) {
145 ast_log(LOG_ERROR, "MWI external: Sorcery failed to open.\n");
146 return -1;
147 }
148
149 /* Map the external MWI wizards. */
152 ast_log(LOG_ERROR, "MWI external: Sorcery could not setup wizards.\n");
153 return -1;
154 }
155
158 if (res) {
159 ast_log(LOG_ERROR, "MWI external: Sorcery could not register object type '%s'.\n",
161 return -1;
162 }
163
164 /* Define the MWI_MAILBOX_TYPE object fields. */
166 "msgs_new", "0", OPT_UINT_T, 0, FLDSET(struct ast_mwi_mailbox_object, msgs_new));
168 "msgs_old", "0", OPT_UINT_T, 0, FLDSET(struct ast_mwi_mailbox_object, msgs_old));
169 return res ? -1 : 0;
170}
171
173{
176}
177
179{
181}
182
183const struct ast_mwi_mailbox_object *ast_mwi_mailbox_get(const char *mailbox_id)
184{
185 if (ast_strlen_zero(mailbox_id)) {
186 return NULL;
187 }
188
190}
191
192struct ast_mwi_mailbox_object *ast_mwi_mailbox_alloc(const char *mailbox_id)
193{
194 if (ast_strlen_zero(mailbox_id)) {
195 return NULL;
196 }
197
199}
200
202{
204}
205
207{
209}
210
212{
213 return mailbox->msgs_new;
214}
215
217{
218 return mailbox->msgs_old;
219}
220
222{
223 mailbox->msgs_new = num_msgs;
224}
225
227{
228 mailbox->msgs_old = num_msgs;
229}
230
232{
233 const struct ast_mwi_mailbox_object *exists;
234 int res;
235
238 if (exists) {
241 } else {
243 }
244 return res;
245}
246
247/*!
248 * \internal
249 * \brief Delete a mailbox.
250 * \since 12.1.0
251 *
252 * \param mailbox Mailbox object to delete from sorcery.
253 */
255{
257}
258
259/*!
260 * \internal
261 * \brief Delete all mailboxes in container.
262 * \since 12.1.0
263 *
264 * \param mailboxes Mailbox objects to delete from sorcery.
265 */
267{
269 struct ao2_iterator iter;
270
274 }
276}
277
279{
280 struct ao2_container *mailboxes;
281
283 if (mailboxes) {
285 ao2_ref(mailboxes, -1);
286 }
287 return 0;
288}
289
291{
292 struct ao2_container *mailboxes;
293
295 if (mailboxes) {
297 ao2_ref(mailboxes, -1);
298 }
299 return 0;
300}
301
302int ast_mwi_mailbox_delete(const char *mailbox_id)
303{
304 const struct ast_mwi_mailbox_object *mailbox;
305
306 if (ast_strlen_zero(mailbox_id)) {
307 return -1;
308 }
309
310 mailbox = ast_mwi_mailbox_get(mailbox_id);
311 if (mailbox) {
314 }
315 return 0;
316}
317
322};
323
324/*!
325 * \internal
326 * \brief Determine if the requested folder is valid for external MWI support.
327 * \since 12.1.0
328 *
329 * \param folder Folder name to check (NULL is valid).
330 *
331 * \return Enum of the supported folder.
332 */
333static enum folder_map mwi_folder_map(const char *folder)
334{
335 enum folder_map which_folder;
336
337 if (ast_strlen_zero(folder) || !strcasecmp(folder, "INBOX")) {
338 which_folder = FOLDER_INBOX;
339 } else if (!strcasecmp(folder, "Old")) {
340 which_folder = FOLDER_OLD;
341 } else {
342 which_folder = FOLDER_INVALID;
343 }
344 return which_folder;
345}
346
347/*!
348 * \internal
349 * \brief Gets the number of messages that exist in a mailbox folder.
350 * \since 12.1.0
351 *
352 * \param mailbox_id The mailbox name.
353 * \param folder The folder to look in. Default is INBOX if not provided.
354 *
355 * \return The number of messages in the mailbox folder (zero or more).
356 */
357static int mwi_messagecount(const char *mailbox_id, const char *folder)
358{
359 const struct ast_mwi_mailbox_object *mailbox;
360 int num_msgs;
361 enum folder_map which_folder;
362
363 which_folder = mwi_folder_map(folder);
364 if (which_folder == FOLDER_INVALID) {
365 return 0;
366 }
367
368 mailbox = ast_mwi_mailbox_get(mailbox_id);
369 if (!mailbox) {
370 return 0;
371 }
372 num_msgs = 0;
373 switch (which_folder) {
374 case FOLDER_INVALID:
375 break;
376 case FOLDER_INBOX:
377 num_msgs = mailbox->msgs_new;
378 break;
379 case FOLDER_OLD:
380 num_msgs = mailbox->msgs_old;
381 break;
382 }
384
385 return num_msgs;
386}
387
388/*!
389 * \internal
390 * \brief Determines if the given folder has messages.
391 * \since 12.1.0
392 *
393 * \param mailboxes Comma or & delimited list of mailboxes.
394 * \param folder The folder to look in. Default is INBOX if not provided.
395 *
396 * \retval 1 if the folder has one or more messages.
397 * \retval 0 otherwise.
398 */
399static int mwi_has_voicemail(const char *mailboxes, const char *folder)
400{
401 char *parse;
402 char *mailbox_id;
403 enum folder_map which_folder;
404
405 which_folder = mwi_folder_map(folder);
406 if (which_folder == FOLDER_INVALID) {
407 return 0;
408 }
409
410 /* For each mailbox in the list. */
411 parse = ast_strdupa(mailboxes);
412 while ((mailbox_id = strsep(&parse, ",&"))) {
413 const struct ast_mwi_mailbox_object *mailbox;
414 int num_msgs;
415
416 /* Get the specified mailbox. */
417 mailbox = ast_mwi_mailbox_get(mailbox_id);
418 if (!mailbox) {
419 continue;
420 }
421
422 /* Done if the found mailbox has any messages. */
423 num_msgs = 0;
424 switch (which_folder) {
425 case FOLDER_INVALID:
426 break;
427 case FOLDER_INBOX:
428 num_msgs = mailbox->msgs_new;
429 break;
430 case FOLDER_OLD:
431 num_msgs = mailbox->msgs_old;
432 break;
433 }
435 if (num_msgs) {
436 return 1;
437 }
438 }
439
440 return 0;
441}
442
443/*!
444 * \internal
445 * \brief Gets the number of messages that exist for the mailbox list.
446 * \since 12.1.0
447 *
448 * \param mailboxes Comma or space delimited list of mailboxes.
449 * \param newmsgs Where to put the count of new messages. (Can be NULL)
450 * \param oldmsgs Where to put the count of old messages. (Can be NULL)
451 *
452 * \details
453 * Simultaneously determines the count of new and old
454 * messages. The total messages would then be the sum of these.
455 *
456 * \retval 0 on success
457 * \retval -1 on failure
458 */
459static int mwi_inboxcount(const char *mailboxes, int *newmsgs, int *oldmsgs)
460{
461 char *parse;
462 char *mailbox_id;
463
464 if (!newmsgs && !oldmsgs) {
465 /* Nowhere to accumulate counts */
466 return 0;
467 }
468
469 /* For each mailbox in the list. */
470 parse = ast_strdupa(mailboxes);
471 while ((mailbox_id = strsep(&parse, ", "))) {
472 const struct ast_mwi_mailbox_object *mailbox;
473
474 /* Get the specified mailbox. */
475 mailbox = ast_mwi_mailbox_get(mailbox_id);
476 if (!mailbox) {
477 continue;
478 }
479
480 /* Accumulate the counts. */
481 if (newmsgs) {
482 *newmsgs += mailbox->msgs_new;
483 }
484 if (oldmsgs) {
485 *oldmsgs += mailbox->msgs_old;
486 }
487
489 }
490
491 return 0;
492}
493
494/*!
495 * \internal
496 * \brief Gets the number of messages that exist for the mailbox list.
497 * \since 12.1.0
498 *
499 * \param mailboxes Comma or space delimited list of mailboxes.
500 * \param urgentmsgs Where to put the count of urgent messages. (Can be NULL)
501 * \param newmsgs Where to put the count of new messages. (Can be NULL)
502 * \param oldmsgs Where to put the count of old messages. (Can be NULL)
503 *
504 * \details
505 * Simultaneously determines the count of new, old, and urgent
506 * messages. The total messages would then be the sum of these
507 * three.
508 *
509 * \retval 0 on success
510 * \retval -1 on failure
511 */
512static int mwi_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
513{
514 /*
515 * This module does not support urgentmsgs. Just ignore them.
516 * The global API call has already set the count to zero.
517 */
518 return mwi_inboxcount(mailboxes, newmsgs, oldmsgs);
519}
520
521static const struct ast_vm_functions vm_table = {
523 .module_name = AST_MODULE,
524
525 .has_voicemail = mwi_has_voicemail,
526 .inboxcount = mwi_inboxcount,
527 .inboxcount2 = mwi_inboxcount2,
528 .messagecount = mwi_messagecount,
529};
530
531#if defined(MWI_DEBUG_CLI)
532static char *complete_mailbox(const char *word, int state)
533{
534 struct ao2_iterator iter;
535 int wordlen = strlen(word);
536 int which = 0;
537 char *ret = NULL;
538 char *regex;
539 const struct ast_mwi_mailbox_object *mailbox;
541
542 regex = ast_alloca(2 + wordlen);
543 sprintf(regex, "^%s", word);/* Safe */
544
546 if (!mailboxes) {
547 return NULL;
548 }
549
550 iter = ao2_iterator_init(mailboxes, 0);
552 if (++which > state) {
555 break;
556 }
557 }
559
560 return ret;
561}
562#endif /* defined(MWI_DEBUG_CLI) */
563
564#if defined(MWI_DEBUG_CLI)
565static char *handle_mwi_delete_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
566{
567 switch (cmd) {
568 case CLI_INIT:
569 e->command = "mwi delete all";
570 e->usage =
571 "Usage: mwi delete all\n"
572 " Delete all external MWI mailboxes.\n";
573 return NULL;
574 case CLI_GENERATE:
575 return NULL;
576 }
577
579 ast_cli(a->fd, "Deleted all external MWI mailboxes.\n");
580 return CLI_SUCCESS;
581}
582#endif /* defined(MWI_DEBUG_CLI) */
583
584#if defined(MWI_DEBUG_CLI)
585static char *handle_mwi_delete_like(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
586{
587 const char *regex;
588
589 switch (cmd) {
590 case CLI_INIT:
591 e->command = "mwi delete like";
592 e->usage =
593 "Usage: mwi delete like <pattern>\n"
594 " Delete external MWI mailboxes matching a regular expression.\n";
595 return NULL;
596 case CLI_GENERATE:
597 return NULL;
598 }
599
600 if (a->argc != 4) {
601 return CLI_SHOWUSAGE;
602 }
603 regex = a->argv[3];
604
606 ast_cli(a->fd, "Deleted external MWI mailboxes matching '%s'.\n", regex);
607 return CLI_SUCCESS;
608}
609#endif /* defined(MWI_DEBUG_CLI) */
610
611#if defined(MWI_DEBUG_CLI)
612static char *handle_mwi_delete_mailbox(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
613{
614 const char *mailbox_id;
615
616 switch (cmd) {
617 case CLI_INIT:
618 e->command = "mwi delete mailbox";
619 e->usage =
620 "Usage: mwi delete mailbox <mailbox_id>\n"
621 " Delete a specific external MWI mailbox.\n";
622 return NULL;
623 case CLI_GENERATE:
624 if (a->pos == 3) {
625 return complete_mailbox(a->word, a->n);
626 }
627 return NULL;
628 }
629
630 if (a->argc != 4) {
631 return CLI_SHOWUSAGE;
632 }
633 mailbox_id = a->argv[3];
634
635 ast_mwi_mailbox_delete(mailbox_id);
636 ast_cli(a->fd, "Deleted external MWI mailbox '%s'.\n", mailbox_id);
637
638 return CLI_SUCCESS;
639}
640#endif /* defined(MWI_DEBUG_CLI) */
641
642#define FORMAT_MAILBOX_HDR "%6s %6s %s\n"
643#define FORMAT_MAILBOX_ROW "%6u %6u %s\n"
644
645#if defined(MWI_DEBUG_CLI)
646/*!
647 * \internal
648 * \brief Print a mailbox list line to CLI.
649 * \since 12.1.0
650 *
651 * \param cli_fd File descriptor for CLI output.
652 * \param mailbox What to list.
653 */
654static void mwi_cli_print_mailbox(int cli_fd, const struct ast_mwi_mailbox_object *mailbox)
655{
656 ast_cli(cli_fd, FORMAT_MAILBOX_ROW, mailbox->msgs_new, mailbox->msgs_old,
658}
659#endif /* defined(MWI_DEBUG_CLI) */
660
661#if defined(MWI_DEBUG_CLI)
662/*!
663 * \internal
664 * \brief List all mailboxes in the given container.
665 * \since 12.1.0
666 *
667 * \param cli_fd File descriptor for CLI output.
668 * \param mailboxes What to list.
669 */
670static void mwi_cli_list_mailboxes(int cli_fd, struct ao2_container *mailboxes)
671{
672 struct ao2_iterator iter;
673 const struct ast_mwi_mailbox_object *mailbox;
674
675 ast_cli(cli_fd, FORMAT_MAILBOX_HDR, "New", "Old", "Mailbox");
676
677 iter = ao2_iterator_init(mailboxes, 0);
679 mwi_cli_print_mailbox(cli_fd, mailbox);
680 }
682}
683#endif /* defined(MWI_DEBUG_CLI) */
684
685#undef FORMAT_MAILBOX_HDR
686#undef FORMAT_MAILBOX_ROW
687
688#if defined(MWI_DEBUG_CLI)
689static char *handle_mwi_list_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
690{
691 struct ao2_container *mailboxes;
692
693 switch (cmd) {
694 case CLI_INIT:
695 e->command = "mwi list all";
696 e->usage =
697 "Usage: mwi list all\n"
698 " List all external MWI mailboxes.\n";
699 return NULL;
700 case CLI_GENERATE:
701 return NULL;
702 }
703
705 if (!mailboxes) {
706 ast_cli(a->fd, "Failed to retrieve external MWI mailboxes.\n");
707 return CLI_SUCCESS;
708 }
709 mwi_cli_list_mailboxes(a->fd, mailboxes);
710 ao2_ref(mailboxes, -1);
711 return CLI_SUCCESS;
712}
713#endif /* defined(MWI_DEBUG_CLI) */
714
715#if defined(MWI_DEBUG_CLI)
716static char *handle_mwi_list_like(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
717{
718 struct ao2_container *mailboxes;
719 const char *regex;
720
721 switch (cmd) {
722 case CLI_INIT:
723 e->command = "mwi list like";
724 e->usage =
725 "Usage: mwi list like <pattern>\n"
726 " List external MWI mailboxes matching a regular expression.\n";
727 return NULL;
728 case CLI_GENERATE:
729 return NULL;
730 }
731
732 if (a->argc != 4) {
733 return CLI_SHOWUSAGE;
734 }
735 regex = a->argv[3];
736
738 if (!mailboxes) {
739 ast_cli(a->fd, "Failed to retrieve external MWI mailboxes.\n");
740 return CLI_SUCCESS;
741 }
742 mwi_cli_list_mailboxes(a->fd, mailboxes);
743 ao2_ref(mailboxes, -1);
744 return CLI_SUCCESS;
745}
746#endif /* defined(MWI_DEBUG_CLI) */
747
748#if defined(MWI_DEBUG_CLI)
749static char *handle_mwi_show_mailbox(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
750{
751 const struct ast_mwi_mailbox_object *mailbox;
752 const char *mailbox_id;
753
754 switch (cmd) {
755 case CLI_INIT:
756 e->command = "mwi show mailbox";
757 e->usage =
758 "Usage: mwi show mailbox <mailbox_id>\n"
759 " Show a specific external MWI mailbox.\n";
760 return NULL;
761 case CLI_GENERATE:
762 if (a->pos == 3) {
763 return complete_mailbox(a->word, a->n);
764 }
765 return NULL;
766 }
767
768 if (a->argc != 4) {
769 return CLI_SHOWUSAGE;
770 }
771 mailbox_id = a->argv[3];
772
773 mailbox = ast_mwi_mailbox_get(mailbox_id);
774 if (mailbox) {
775 ast_cli(a->fd,
776 "Mailbox: %s\n"
777 "NewMessages: %u\n"
778 "OldMessages: %u\n",
780 mailbox->msgs_new,
781 mailbox->msgs_old);
782
784 } else {
785 ast_cli(a->fd, "External MWI mailbox '%s' not found.\n", mailbox_id);
786 }
787
788 return CLI_SUCCESS;
789}
790#endif /* defined(MWI_DEBUG_CLI) */
791
792#if defined(MWI_DEBUG_CLI)
793static char *handle_mwi_update_mailbox(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
794{
796 const char *mailbox_id;
797 unsigned int num_new;
798 unsigned int num_old;
799
800 switch (cmd) {
801 case CLI_INIT:
802 e->command = "mwi update mailbox";
803 e->usage =
804 "Usage: mwi update mailbox <mailbox_id> [<new> [<old>]]\n"
805 " Update a specific external MWI mailbox.\n";
806 return NULL;
807 case CLI_GENERATE:
808 if (a->pos == 3) {
809 return complete_mailbox(a->word, a->n);
810 }
811 return NULL;
812 }
813
814 if (a->argc < 4 || 6 < a->argc) {
815 return CLI_SHOWUSAGE;
816 }
817 mailbox_id = a->argv[3];
818
819 num_new = 0;
820 if (4 < a->argc) {
821 const char *count_new = a->argv[4];
822
823 if (sscanf(count_new, "%u", &num_new) != 1) {
824 ast_cli(a->fd, "Invalid NewMessages: '%s'.\n", count_new);
825 return CLI_SHOWUSAGE;
826 }
827 }
828
829 num_old = 0;
830 if (5 < a->argc) {
831 const char *count_old = a->argv[5];
832
833 if (sscanf(count_old, "%u", &num_old) != 1) {
834 ast_cli(a->fd, "Invalid OldMessages: '%s'.\n", count_old);
835 return CLI_SHOWUSAGE;
836 }
837 }
838
839 mailbox = ast_mwi_mailbox_alloc(mailbox_id);
840 if (mailbox) {
844 ast_cli(a->fd, "Could not update mailbox %s.\n",
846 } else {
847 ast_cli(a->fd, "Updated mailbox %s.\n", ast_sorcery_object_get_id(mailbox));
848 }
849
851 }
852
853 return CLI_SUCCESS;
854}
855#endif /* defined(MWI_DEBUG_CLI) */
856
857#if defined(MWI_DEBUG_CLI)
858static struct ast_cli_entry mwi_cli[] = {
859 AST_CLI_DEFINE(handle_mwi_delete_all, "Delete all external MWI mailboxes"),
860 AST_CLI_DEFINE(handle_mwi_delete_like, "Delete external MWI mailboxes matching regex"),
861 AST_CLI_DEFINE(handle_mwi_delete_mailbox, "Delete a specific external MWI mailbox"),
862 AST_CLI_DEFINE(handle_mwi_list_all, "List all external MWI mailboxes"),
863 AST_CLI_DEFINE(handle_mwi_list_like, "List external MWI mailboxes matching regex"),
864 AST_CLI_DEFINE(handle_mwi_show_mailbox, "Show a specific external MWI mailbox"),
865 AST_CLI_DEFINE(handle_mwi_update_mailbox, "Update a specific external MWI mailbox"),
866};
867#endif /* defined(MWI_DEBUG_CLI) */
868
869/*!
870 * \internal
871 * \brief Post initial MWI count events.
872 * \since 12.1.0
873 */
874static void mwi_initial_events(void)
875{
876 struct ao2_container *mailboxes;
877 const struct ast_mwi_mailbox_object *mailbox;
878 struct ao2_iterator iter;
879
880 /* Get all mailbox counts. */
882 if (!mailboxes) {
883 return;
884 }
885
886 /* Post all mailbox counts. */
890 }
892
893 ao2_ref(mailboxes, -1);
894}
895
896static int unload_module(void)
897{
899#if defined(MWI_DEBUG_CLI)
900 ast_cli_unregister_multiple(mwi_cli, ARRAY_LEN(mwi_cli));
901#endif /* defined(MWI_DEBUG_CLI) */
903
906
907 return 0;
908}
909
910static int load_module(void)
911{
912 int res;
913
914 if (mwi_sorcery_init()
916#if defined(MWI_DEBUG_CLI)
917 || ast_cli_register_multiple(mwi_cli, ARRAY_LEN(mwi_cli))
918#endif /* defined(MWI_DEBUG_CLI) */
919 ) {
922 }
923
924 /* ast_vm_register may return DECLINE if another module registered for vm */
926 if (res) {
927 ast_log(LOG_ERROR, "Failure registering as a voicemail provider\n");
930 }
931
932 /* Post initial MWI count events. */
934
936}
937
939 .support_level = AST_MODULE_SUPPORT_CORE,
940 .load = load_module,
941 .unload = unload_module,
942 .load_pri = AST_MODPRI_CHANNEL_DEPEND - 5,
#define AST_MODULE
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
@ AO2_ITERATOR_UNLINK
Definition: astobj2.h:1863
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
short word
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
@ OPT_UINT_T
Type for default option handler for unsigned integers.
static int exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_logic.c:157
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define VM_MODULE_VERSION
void ast_vm_unregister(const char *module_name)
Unregister the specified voicemail provider.
Definition: main/app.c:400
#define ast_vm_register(vm_table)
See __ast_vm_register()
char * strsep(char **str, const char *delims)
#define LOG_ERROR
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:317
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition: module.h:316
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODPRI_CHANNEL_DEPEND
Definition: module.h:326
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
Asterisk MWI API.
#define ast_delete_mwi_state(mailbox, context)
Delete MWI state cached by stasis.
Definition: mwi.h:431
#define ast_publish_mwi_state(mailbox, context, new_msgs, old_msgs)
Publish a MWI state update via stasis.
Definition: mwi.h:378
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
folder_map
@ FOLDER_INVALID
@ FOLDER_OLD
@ FOLDER_INBOX
int ast_mwi_mailbox_update(struct ast_mwi_mailbox_object *mailbox)
Update the external MWI counts with the given object.
int ast_mwi_mailbox_delete_all(void)
Delete all external MWI objects.
static const struct ast_vm_functions vm_table
struct ast_mwi_mailbox_object * ast_mwi_mailbox_alloc(const char *mailbox_id)
Allocate an external MWI object.
int ast_mwi_mailbox_delete_by_regex(const char *regex)
Delete all external MWI objects selected by the regular expression.
#define MWI_ASTDB_PREFIX
#define FORMAT_MAILBOX_ROW
static void mwi_initial_events(void)
static void mwi_post_event(const struct ast_mwi_mailbox_object *mailbox)
static enum folder_map mwi_folder_map(const char *folder)
static void mwi_observe_update(const void *obj)
#define MWI_MAILBOX_TYPE
static int mwi_inboxcount(const char *mailboxes, int *newmsgs, int *oldmsgs)
static void mwi_observe_delete(const void *obj)
static struct ast_sorcery * mwi_sorcery
static const struct ast_sorcery_observer mwi_observers
int ast_mwi_mailbox_delete(const char *mailbox_id)
Delete matching external MWI object.
const struct ast_mwi_mailbox_object * ast_mwi_mailbox_get(const char *mailbox_id)
Get matching external MWI object.
static int mwi_has_voicemail(const char *mailboxes, const char *folder)
#define FORMAT_MAILBOX_HDR
static void mwi_mailbox_delete_all(struct ao2_container *mailboxes)
const char * ast_mwi_mailbox_get_id(const struct ast_mwi_mailbox_object *mailbox)
Get mailbox id.
unsigned int ast_mwi_mailbox_get_msgs_old(const struct ast_mwi_mailbox_object *mailbox)
Get the number of old messages.
void ast_mwi_mailbox_set_msgs_new(struct ast_mwi_mailbox_object *mailbox, unsigned int num_msgs)
Set the number of new messages.
static void mwi_mailbox_delete(struct ast_mwi_mailbox_object *mailbox)
struct ao2_container * ast_mwi_mailbox_get_all(void)
Get all external MWI objects.
static int load_module(void)
unsigned int ast_mwi_mailbox_get_msgs_new(const struct ast_mwi_mailbox_object *mailbox)
Get the number of new messages.
static int unload_module(void)
struct ao2_container * ast_mwi_mailbox_get_by_regex(const char *regex)
Get all external MWI objects selected by the regular expression.
struct ast_mwi_mailbox_object * ast_mwi_mailbox_copy(const struct ast_mwi_mailbox_object *mailbox)
Copy the external MWI counts object.
static int mwi_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
static int mwi_sorcery_init(void)
static int mwi_messagecount(const char *mailbox_id, const char *folder)
static void * mwi_sorcery_object_alloc(const char *id)
Internal function to allocate a mwi object.
void ast_mwi_mailbox_set_msgs_old(struct ast_mwi_mailbox_object *mailbox, unsigned int num_msgs)
Set the number of old messages.
Core external MWI support.
#define ast_mwi_mailbox_unref(mailbox)
Convenience unref function for mailbox object.
#define NULL
Definition: resample.c:96
Sorcery Data Access Layer API.
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
Definition: sorcery.h:1500
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2317
#define ast_sorcery_object_field_register_nodoc(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object without documentation.
Definition: sorcery.h:987
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
Definition: sorcery.c:2423
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
Definition: sorcery.h:120
@ AST_RETRIEVE_FLAG_ALL
Perform no matching, return all objects.
Definition: sorcery.h:123
int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
Create and potentially persist an object using an available wizard.
Definition: sorcery.c:2062
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition: sorcery.h:837
struct ao2_container * ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
Retrieve multiple objects using a regular expression on their id.
Definition: sorcery.c:1954
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
Definition: sorcery.c:2391
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1728
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
Definition: sorcery.c:1744
int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
Update an object.
Definition: sorcery.c:2150
#define ast_sorcery_apply_default(sorcery, type, name, data)
Definition: sorcery.h:476
#define ast_sorcery_open()
Open a new sorcery structure.
Definition: sorcery.h:406
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1897
int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
Delete an object.
Definition: sorcery.c:2238
void * ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
Create a copy of an object.
Definition: sorcery.c:1778
@ AST_SORCERY_APPLY_FAIL
Definition: sorcery.h:425
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Interface for a sorcery object type observer.
Definition: sorcery.h:332
void(* created)(const void *object)
Callback for when an object is created.
Definition: sorcery.h:334
Full structure for sorcery.
Definition: sorcery.c:230
Voicemail function table definition.
unsigned int module_version
The version of this function table.
const char * module_name
The name of the module that provides the voicemail functionality.
static struct test_val a
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ARRAY_LEN(a)
Definition: utils.h:666