Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Macros | Enumerations | Functions | Variables
res_smdi.c File Reference

SMDI support for Asterisk. More...

#include "asterisk.h"
#include <termios.h>
#include <sys/time.h>
#include <time.h>
#include <ctype.h>
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/smdi.h"
#include "asterisk/config.h"
#include "asterisk/io.h"
#include "asterisk/stringfields.h"
#include "asterisk/linkedlists.h"
#include "asterisk/app.h"
#include "asterisk/mwi.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"

Go to the source code of this file.

Data Structures

struct  ast_smdi_interface
 
struct  mailbox_mapping
 A mapping between an SMDI mailbox ID and an Asterisk mailbox. More...
 
struct  smdi_msg_datastore
 

Macros

#define AST_API_MODULE
 
#define DEFAULT_POLLING_INTERVAL   10
 
#define SMDI_MSG_EXPIRY_TIME   30000 /* 30 seconds */
 
#define SMDI_RETRIEVE_TIMEOUT_DEFAULT   3000
 

Enumerations

enum  { OPT_SEARCH_TERMINAL = (1 << 0), OPT_SEARCH_NUMBER = (1 << 1) }
 
enum  smdi_message_type { SMDI_MWI, SMDI_MD }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static struct ast_smdi_interfacealloc_smdi_interface (void)
 
static AO2_GLOBAL_OBJ_STATIC (smdi_ifaces)
 
static void append_mailbox_mapping (struct ast_variable *var, struct ast_smdi_interface *iface)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
struct ast_smdi_interface *AST_OPTIONAL_API_NAME() ast_smdi_interface_find (const char *iface_name)
 Find an SMDI interface with the specified name. More...
 
struct ast_smdi_md_message *AST_OPTIONAL_API_NAME() ast_smdi_md_message_pop (struct ast_smdi_interface *iface)
 Get the next SMDI message from the queue. More...
 
static void ast_smdi_md_message_push (struct ast_smdi_interface *iface, struct ast_smdi_md_message *md_msg)
 
struct ast_smdi_md_message *AST_OPTIONAL_API_NAME() ast_smdi_md_message_wait (struct ast_smdi_interface *iface, int timeout)
 Get the next SMDI message from the queue. More...
 
struct ast_smdi_mwi_message *AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_pop (struct ast_smdi_interface *iface)
 Get the next SMDI message from the queue. More...
 
static void ast_smdi_mwi_message_push (struct ast_smdi_interface *iface, struct ast_smdi_mwi_message *mwi_msg)
 
struct ast_smdi_mwi_message *AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_wait (struct ast_smdi_interface *iface, int timeout)
 Get the next SMDI message from the queue. More...
 
struct ast_smdi_mwi_message *AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_wait_station (struct ast_smdi_interface *iface, int timeout, const char *station)
 
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_set (struct ast_smdi_interface *iface, const char *mailbox)
 Set the MWI indicator for a mailbox. More...
 
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_unset (struct ast_smdi_interface *iface, const char *mailbox)
 Unset the MWI indicator for a mailbox. More...
 
static void destroy_all_mailbox_mappings (void)
 
static void destroy_mailbox_mapping (struct mailbox_mapping *mm)
 
static int load_module (void)
 Load the module. More...
 
static int lock_msg_q (struct ast_smdi_interface *iface, enum smdi_message_type type)
 
static struct timeval msg_timestamp (void *msg, enum smdi_message_type type)
 
static void * mwi_monitor_handler (void *data)
 
static void poll_mailbox (struct mailbox_mapping *mm)
 
static void purge_old_messages (struct ast_smdi_interface *iface, enum smdi_message_type type)
 
static int reload (void)
 
static int smdi_ifaces_cmp_fn (void *obj, void *data, int flags)
 
static void smdi_interface_destroy (void *obj)
 
static int smdi_load (int reload)
 
static int smdi_md_q_cmp_fn (void *obj, void *arg, int flags)
 
static void * smdi_message_wait (struct ast_smdi_interface *iface, int timeout, enum smdi_message_type type, const char *search_key, struct ast_flags options)
 
static void smdi_msg_datastore_destroy (void *data)
 
static void * smdi_msg_find (struct ast_smdi_interface *iface, enum smdi_message_type type, const char *search_key, struct ast_flags options)
 
static void * smdi_msg_pop (struct ast_smdi_interface *iface, enum smdi_message_type type)
 
static int smdi_msg_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int smdi_msg_retrieve_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int smdi_mwi_q_cmp_fn (void *obj, void *data, int flags)
 
static void * smdi_read (void *iface_p)
 
static int smdi_toggle_mwi (struct ast_smdi_interface *iface, const char *mailbox, int on)
 
static void * unlink_from_msg_q (struct ast_smdi_interface *iface, enum smdi_message_type type)
 
static int unload_module (void)
 
static int unlock_msg_q (struct ast_smdi_interface *iface, enum smdi_message_type type)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Simplified Message Desk Interface (SMDI) Resource" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const char config_file [] = "smdi.conf"
 
struct {
   ast_cond_t   cond
 
   struct timeval   last_poll
 
   ast_mutex_t   lock
 
   struct {
      struct mailbox_mapping *   first
 
      struct mailbox_mapping *   last
 
   }   mailbox_mappings
 
   unsigned int   polling_interval
 
   unsigned int   stop:1
 
   pthread_t   thread
 
mwi_monitor
 Data that gets used by the SMDI MWI monitoring thread. More...
 
static const struct ast_datastore_info smdi_msg_datastore_info
 
static struct ast_custom_function smdi_msg_function
 
static int smdi_msg_id
 
static const struct ast_app_option smdi_msg_ret_options [128] = { [ 't' ] = { .flag = OPT_SEARCH_TERMINAL }, [ 'n' ] = { .flag = OPT_SEARCH_NUMBER }, }
 
static struct ast_custom_function smdi_msg_retrieve_function
 

Detailed Description

SMDI support for Asterisk.

Author
Matthew A. Nicholson mnich.nosp@m.olso.nosp@m.n@dig.nosp@m.ium..nosp@m.com
Russell Bryant russe.nosp@m.ll@d.nosp@m.igium.nosp@m..com

Here is a useful mailing list post that describes SMDI protocol details: http://lists.digium.com/pipermail/asterisk-dev/2003-June/000884.html

Todo:
This module currently has its own mailbox monitoring thread. This should be converted to MWI subscriptions and just let the optional global voicemail polling thread handle it.

Definition in file res_smdi.c.

Macro Definition Documentation

#define DEFAULT_POLLING_INTERVAL   10

10 seconds

Definition at line 204 of file res_smdi.c.

#define SMDI_RETRIEVE_TIMEOUT_DEFAULT   3000

In milliseconds

Definition at line 1195 of file res_smdi.c.

Function Documentation

struct ast_smdi_interface* AST_OPTIONAL_API_NAME() ast_smdi_interface_find ( const char *  iface_name)

Find an SMDI interface with the specified name.

Parameters
iface_namethe name/port of the interface to search for.
Returns
an ao2 reference to the interface located or NULL if none was found.

Definition at line 563 of file res_smdi.c.

References ao2_global_obj_ref, ao2_ref, mailbox_mapping::iface, and OBJ_SEARCH_KEY.

Referenced by mkintf().

564 {
565  struct ao2_container *c;
566  struct ast_smdi_interface *iface = NULL;
567 
568  c = ao2_global_obj_ref(smdi_ifaces);
569  if (c) {
570  iface = ao2_find(c, iface_name, OBJ_SEARCH_KEY);
571  ao2_ref(c, -1);
572  }
573 
574  return iface;
575 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
Generic container type.
struct ast_smdi_md_message* AST_OPTIONAL_API_NAME() ast_smdi_md_message_pop ( struct ast_smdi_interface iface)

Get the next SMDI message from the queue.

Parameters
ifacea pointer to the interface to use.

This function pulls the first unexpired message from the SMDI message queue on the specified interface. It will purge all expired SMDI messages before returning.

Returns
the next SMDI message, or NULL if there were no pending messages.

Definition at line 534 of file res_smdi.c.

535 {
536  return smdi_msg_pop(iface, SMDI_MD);
537 }
struct ast_smdi_md_message* AST_OPTIONAL_API_NAME() ast_smdi_md_message_wait ( struct ast_smdi_interface iface,
int  timeout 
)

Get the next SMDI message from the queue.

Parameters
ifacea pointer to the interface to use.
timeoutthe time to wait before returning in milliseconds.

This function pulls a message from the SMDI message queue on the specified interface. If no message is available this function will wait the specified amount of time before returning.

Returns
the next SMDI message, or NULL if there were no pending messages and the timeout has expired.

Definition at line 539 of file res_smdi.c.

540 {
541  struct ast_flags options = { 0 };
542  return smdi_message_wait(iface, timeout, SMDI_MD, NULL, options);
543 }
Structure used to handle boolean flags.
Definition: utils.h:199
struct ast_smdi_mwi_message* AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_pop ( struct ast_smdi_interface iface)

Get the next SMDI message from the queue.

Parameters
ifacea pointer to the interface to use.

This function pulls the first unexpired message from the SMDI message queue on the specified interface. It will purge all expired SMDI messages before returning.

Returns
the next SMDI message, or NULL if there were no pending messages.

Definition at line 545 of file res_smdi.c.

546 {
547  return smdi_msg_pop(iface, SMDI_MWI);
548 }
struct ast_smdi_mwi_message* AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_wait ( struct ast_smdi_interface iface,
int  timeout 
)

Get the next SMDI message from the queue.

Parameters
ifacea pointer to the interface to use.
timeoutthe time to wait before returning in milliseconds.

This function pulls a message from the SMDI message queue on the specified interface. If no message is available this function will wait the specified amount of time before returning.

Returns
the next SMDI message, or NULL if there were no pending messages and the timeout has expired.

Definition at line 550 of file res_smdi.c.

551 {
552  struct ast_flags options = { 0 };
553  return smdi_message_wait(iface, timeout, SMDI_MWI, NULL, options);
554 }
Structure used to handle boolean flags.
Definition: utils.h:199
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_set ( struct ast_smdi_interface iface,
const char *  mailbox 
)

Set the MWI indicator for a mailbox.

Parameters
ifacethe interface to use.
mailboxthe mailbox to use.

Definition at line 309 of file res_smdi.c.

Referenced by poll_mailbox().

310 {
311  return smdi_toggle_mwi(iface, mailbox, 1);
312 }
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_unset ( struct ast_smdi_interface iface,
const char *  mailbox 
)

Unset the MWI indicator for a mailbox.

Parameters
ifacethe interface to use.
mailboxthe mailbox to use.

Definition at line 314 of file res_smdi.c.

Referenced by poll_mailbox().

315 {
316  return smdi_toggle_mwi(iface, mailbox, 0);
317 }
static int load_module ( void  )
static

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 1411 of file res_smdi.c.

References ast_custom_function_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, and mwi_monitor.

1412 {
1413  int res;
1414 
1415  ast_mutex_init(&mwi_monitor.lock);
1416  ast_cond_init(&mwi_monitor.cond, NULL);
1417 
1418  /* load the config and start the listener threads*/
1419  res = smdi_load(0);
1420  if (res < 0) {
1421  unload_module();
1422  return AST_MODULE_LOAD_DECLINE;
1423  } else if (res == 1) {
1424  ast_log(LOG_NOTICE, "No SMDI interfaces are available to listen on, not starting SMDI listener.\n");
1425  }
1426 
1427  ast_custom_function_register(&smdi_msg_retrieve_function);
1428  ast_custom_function_register(&smdi_msg_function);
1429 
1430  return AST_MODULE_LOAD_SUCCESS;
1431 }
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
static struct @483 mwi_monitor
Data that gets used by the SMDI MWI monitoring thread.
static void poll_mailbox ( struct mailbox_mapping mm)
static
Note
Called with the mwi_monitor.lock locked

Definition at line 833 of file res_smdi.c.

References ast_app_has_voicemail(), ast_smdi_mwi_set(), ast_smdi_mwi_unset(), mailbox_mapping::context, mailbox_mapping::cur_state, mailbox_mapping::iface, mailbox_mapping::mailbox, and mailbox_mapping::smdi.

834 {
835  char buf[1024];
836  unsigned int state;
837 
838  snprintf(buf, sizeof(buf), "%s@%s", mm->mailbox, mm->context);
839 
840  state = !!ast_app_has_voicemail(mm->mailbox, NULL);
841 
842  if (state != mm->cur_state) {
843  if (state)
844  ast_smdi_mwi_set(mm->iface, mm->smdi);
845  else
846  ast_smdi_mwi_unset(mm->iface, mm->smdi);
847 
848  mm->cur_state = state;
849  }
850 }
unsigned int cur_state
Definition: res_smdi.c:189
const ast_string_field context
Definition: res_smdi.c:199
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox)
Unset the MWI indicator for a mailbox.
Definition: res_smdi.c:314
struct ast_smdi_interface * iface
Definition: res_smdi.c:191
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
Set the MWI indicator for a mailbox.
Definition: res_smdi.c:309
const ast_string_field mailbox
Definition: res_smdi.c:199
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
Definition: main/app.c:582
const ast_string_field smdi
Definition: res_smdi.c:199

Variable Documentation

struct timeval last_poll

The time that the last poll began

Definition at line 219 of file res_smdi.c.

struct { ... } mailbox_mappings

A list of mailboxes that need to be monitored

struct { ... } mwi_monitor
Initial value:
= {
.thread = AST_PTHREADT_NULL,
}

Data that gets used by the SMDI MWI monitoring thread.

Referenced by load_module().

unsigned int polling_interval

Polling Interval for checking mailbox status

Definition at line 215 of file res_smdi.c.

const struct ast_datastore_info smdi_msg_datastore_info
static
Initial value:
= {
.type = "SMDIMSG",
.destroy = smdi_msg_datastore_destroy,
}

Definition at line 1187 of file res_smdi.c.

struct ast_custom_function smdi_msg_function
static
Initial value:
= {
.name = "SMDI_MSG",
.read = smdi_msg_read,
}

Definition at line 1375 of file res_smdi.c.

struct ast_custom_function smdi_msg_retrieve_function
static
Initial value:
= {
.name = "SMDI_MSG_RETRIEVE",
.read = smdi_msg_retrieve_read,
}

Definition at line 1370 of file res_smdi.c.

unsigned int stop

Set to 1 to tell the polling thread to stop

Definition at line 217 of file res_smdi.c.

Referenced by queue_exec().

pthread_t thread

The thread ID

Definition at line 209 of file res_smdi.c.