72 #define MWI_ASTDB_PREFIX "mwi_external"
73 #define MWI_MAILBOX_TYPE "mailboxes"
76 SORCERY_OBJECT(details);
96 static void mwi_observe_update(
const void *obj)
106 static void mwi_observe_delete(
const void *obj)
121 .updated = mwi_observe_update,
122 .deleted = mwi_observe_delete,
139 static int mwi_sorcery_init(
void)
145 ast_log(LOG_ERROR,
"MWI external: Sorcery failed to open.\n");
150 if (ast_sorcery_apply_default(mwi_sorcery, MWI_MAILBOX_TYPE,
"astdb",
152 ast_log(LOG_ERROR,
"MWI external: Sorcery could not setup wizards.\n");
159 ast_log(LOG_ERROR,
"MWI external: Sorcery could not register object type '%s'.\n",
185 if (ast_strlen_zero(mailbox_id)) {
194 if (ast_strlen_zero(mailbox_id)) {
273 mwi_mailbox_delete(mailbox);
284 mwi_mailbox_delete_all(mailboxes);
296 mwi_mailbox_delete_all(mailboxes);
306 if (ast_strlen_zero(mailbox_id)) {
333 static enum folder_map mwi_folder_map(
const char *folder)
335 enum folder_map which_folder;
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;
342 which_folder = FOLDER_INVALID;
357 static int mwi_messagecount(
const char *mailbox_id,
const char *folder)
361 enum folder_map which_folder;
363 which_folder = mwi_folder_map(folder);
364 if (which_folder == FOLDER_INVALID) {
373 switch (which_folder) {
399 static int mwi_has_voicemail(
const char *mailboxes,
const char *folder)
403 enum folder_map which_folder;
405 which_folder = mwi_folder_map(folder);
406 if (which_folder == FOLDER_INVALID) {
412 while ((mailbox_id = strsep(&parse,
",&"))) {
424 switch (which_folder) {
459 static int mwi_inboxcount(
const char *mailboxes,
int *newmsgs,
int *oldmsgs)
464 if (!newmsgs && !oldmsgs) {
471 while ((mailbox_id = strsep(&parse,
", "))) {
512 static int mwi_inboxcount2(
const char *mailboxes,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
518 return mwi_inboxcount(mailboxes, newmsgs, oldmsgs);
523 .module_name = AST_MODULE,
525 .has_voicemail = mwi_has_voicemail,
526 .inboxcount = mwi_inboxcount,
527 .inboxcount2 = mwi_inboxcount2,
528 .messagecount = mwi_messagecount,
531 #if defined(MWI_DEBUG_CLI)
532 static char *complete_mailbox(
const char *word,
int state)
535 int wordlen = strlen(word);
543 sprintf(regex,
"^%s", word);
552 if (++which > state) {
564 #if defined(MWI_DEBUG_CLI)
571 "Usage: mwi delete all\n"
572 " Delete all external MWI mailboxes.\n";
579 ast_cli(a->fd,
"Deleted all external MWI mailboxes.\n");
584 #if defined(MWI_DEBUG_CLI)
591 e->
command =
"mwi delete like";
593 "Usage: mwi delete like <pattern>\n"
594 " Delete external MWI mailboxes matching a regular expression.\n";
601 return CLI_SHOWUSAGE;
606 ast_cli(a->fd,
"Deleted external MWI mailboxes matching '%s'.\n", regex);
611 #if defined(MWI_DEBUG_CLI)
614 const char *mailbox_id;
618 e->
command =
"mwi delete mailbox";
620 "Usage: mwi delete mailbox <mailbox_id>\n"
621 " Delete a specific external MWI mailbox.\n";
625 return complete_mailbox(a->word, a->n);
631 return CLI_SHOWUSAGE;
633 mailbox_id = a->argv[3];
636 ast_cli(a->fd,
"Deleted external MWI mailbox '%s'.\n", mailbox_id);
642 #define FORMAT_MAILBOX_HDR "%6s %6s %s\n"
643 #define FORMAT_MAILBOX_ROW "%6u %6u %s\n"
645 #if defined(MWI_DEBUG_CLI)
661 #if defined(MWI_DEBUG_CLI)
670 static void mwi_cli_list_mailboxes(
int cli_fd,
struct ao2_container *mailboxes)
675 ast_cli(cli_fd, FORMAT_MAILBOX_HDR,
"New",
"Old",
"Mailbox");
679 mwi_cli_print_mailbox(cli_fd, mailbox);
685 #undef FORMAT_MAILBOX_HDR
686 #undef FORMAT_MAILBOX_ROW
688 #if defined(MWI_DEBUG_CLI)
697 "Usage: mwi list all\n"
698 " List all external MWI mailboxes.\n";
706 ast_cli(a->fd,
"Failed to retrieve external MWI mailboxes.\n");
709 mwi_cli_list_mailboxes(a->fd, mailboxes);
715 #if defined(MWI_DEBUG_CLI)
725 "Usage: mwi list like <pattern>\n"
726 " List external MWI mailboxes matching a regular expression.\n";
733 return CLI_SHOWUSAGE;
739 ast_cli(a->fd,
"Failed to retrieve external MWI mailboxes.\n");
742 mwi_cli_list_mailboxes(a->fd, mailboxes);
748 #if defined(MWI_DEBUG_CLI)
752 const char *mailbox_id;
756 e->
command =
"mwi show mailbox";
758 "Usage: mwi show mailbox <mailbox_id>\n"
759 " Show a specific external MWI mailbox.\n";
763 return complete_mailbox(a->word, a->n);
769 return CLI_SHOWUSAGE;
771 mailbox_id = a->argv[3];
785 ast_cli(a->fd,
"External MWI mailbox '%s' not found.\n", mailbox_id);
792 #if defined(MWI_DEBUG_CLI)
796 const char *mailbox_id;
797 unsigned int num_new;
798 unsigned int num_old;
802 e->
command =
"mwi update mailbox";
804 "Usage: mwi update mailbox <mailbox_id> [<new> [<old>]]\n"
805 " Update a specific external MWI mailbox.\n";
809 return complete_mailbox(a->word, a->n);
814 if (a->argc < 4 || 6 < a->argc) {
815 return CLI_SHOWUSAGE;
817 mailbox_id = a->argv[3];
821 const char *count_new = a->argv[4];
823 if (sscanf(count_new,
"%u", &num_new) != 1) {
824 ast_cli(a->fd,
"Invalid NewMessages: '%s'.\n", count_new);
825 return CLI_SHOWUSAGE;
831 const char *count_old = a->argv[5];
833 if (sscanf(count_old,
"%u", &num_old) != 1) {
834 ast_cli(a->fd,
"Invalid OldMessages: '%s'.\n", count_old);
835 return CLI_SHOWUSAGE;
844 ast_cli(a->fd,
"Could not update mailbox %s.\n",
857 #if defined(MWI_DEBUG_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"),
874 static void mwi_initial_events(
void)
889 mwi_post_event(mailbox);
896 static int unload_module(
void)
899 #if defined(MWI_DEBUG_CLI)
910 static int load_module(
void)
914 if (mwi_sorcery_init()
916 #
if defined(MWI_DEBUG_CLI)
927 ast_log(LOG_ERROR,
"Failure registering as a voicemail provider\n");
933 mwi_initial_events();
938 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER,
"Core external MWI resource",
939 .support_level = AST_MODULE_SUPPORT_CORE,
941 .unload = unload_module,
#define ast_sorcery_object_field_register_nodoc(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object without documentation.
Asterisk main include file. File version handling, generic pbx functions.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
descriptor for a cli entry.
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
void(* created)(const void *object)
Callback for when an object is created.
int ast_mwi_mailbox_update(struct ast_mwi_mailbox_object *mailbox)
Update the external MWI counts with the given object.
Perform no matching, return all objects.
Full structure for sorcery.
const struct ast_mwi_mailbox_object * ast_mwi_mailbox_get(const char *mailbox_id)
Get matching external MWI object.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void ast_vm_unregister(const char *module_name)
Unregister the specified voicemail provider.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
Return all matching objects.
void ast_mwi_mailbox_set_msgs_old(struct ast_mwi_mailbox_object *mailbox, unsigned int num_msgs)
Set the number of old messages.
#define ast_strdup(str)
A wrapper for strdup()
Core external MWI support.
#define ast_publish_mwi_state(mailbox, context, new_msgs, old_msgs)
Publish a MWI state update via stasis.
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.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
Create and potentially persist an object using an available wizard.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
Type for default option handler for unsigned integers.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
int ast_mwi_mailbox_delete(const char *mailbox_id)
Delete matching external MWI object.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
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.
struct ast_mwi_mailbox_object * ast_mwi_mailbox_alloc(const char *mailbox_id)
Allocate an external MWI object.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_vm_register(vm_table)
See __ast_vm_register()
int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
Delete an object.
void ast_mwi_mailbox_set_msgs_new(struct ast_mwi_mailbox_object *mailbox, unsigned int num_msgs)
Set the number of new messages.
Interface for a sorcery object type observer.
struct ao2_container * ast_mwi_mailbox_get_all(void)
Get all external MWI objects.
const char * ast_mwi_mailbox_get_id(const struct ast_mwi_mailbox_object *mailbox)
Get mailbox id.
unsigned int ast_mwi_mailbox_get_msgs_new(const struct ast_mwi_mailbox_object *mailbox)
Get the number of new messages.
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
#define ast_delete_mwi_state(mailbox, context)
Delete MWI state cached by stasis.
#define ast_mwi_mailbox_unref(mailbox)
Convenience unref function for mailbox object.
Module has failed to load, may be in an inconsistent state.
int ast_mwi_mailbox_delete_by_regex(const char *regex)
Delete all external MWI objects selected by the regular expression.
struct ao2_container * ast_mwi_mailbox_get_by_regex(const char *regex)
Get all external MWI objects selected by the regular expression.
unsigned int ast_mwi_mailbox_get_msgs_old(const struct ast_mwi_mailbox_object *mailbox)
Get the number of old messages.
struct ast_mwi_mailbox_object * ast_mwi_mailbox_copy(const struct ast_mwi_mailbox_object *mailbox)
Copy the external MWI counts object.
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.
const char * module_name
The name of the module that provides the voicemail functionality.
static void * mwi_sorcery_object_alloc(const char *id)
Internal function to allocate a mwi object.
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.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Standard Command Line Interface.
void * ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
Create a copy of an object.
int ast_mwi_mailbox_delete_all(void)
Delete all external MWI objects.
#define ast_sorcery_open()
Open a new sorcery structure.
unsigned int module_version
The version of this function table.
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
Voicemail function table definition.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
Sorcery Data Access Layer API.
int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
Update an object.