Wed Oct 28 13:33:34 2009

Asterisk developer's documentation


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/astobj.h"
#include "asterisk/io.h"
#include "asterisk/stringfields.h"
#include "asterisk/linkedlists.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"

Include dependency graph for res_smdi.c:

Go to the source code of this file.

Data Structures

struct  ast_smdi_interface
struct  ast_smdi_interface_container
 SMDI interface container. More...
struct  ast_smdi_md_queue
 SMDI message desk message queue. More...
struct  ast_smdi_mwi_queue
 SMDI message waiting indicator message queue. More...
struct  mailbox_mapping
 A mapping between an SMDI mailbox ID and an Asterisk mailbox. More...
struct  smdi_msg_datastore

Defines

#define AST_API_MODULE
#define DEFAULT_POLLING_INTERVAL   10
#define SMDI_MSG_EXPIRY_TIME   30000
#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 void append_mailbox_mapping (struct ast_variable *var, struct ast_smdi_interface *iface)
static void ast_smdi_interface_destroy (struct ast_smdi_interface *iface)
struct ast_smdi_interface
*AST_OPTIONAL_API_NAME() 
ast_smdi_interface_find (const char *iface_name)
 Find an SMDI interface with the specified name.
void AST_OPTIONAL_API_NAME() ast_smdi_interface_unref (struct ast_smdi_interface *iface)
void AST_OPTIONAL_API_NAME() ast_smdi_md_message_destroy (struct ast_smdi_md_message *msg)
 ast_smdi_md_message destructor.
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.
static void ast_smdi_md_message_push (struct ast_smdi_interface *iface, struct ast_smdi_md_message *md_msg)
void AST_OPTIONAL_API_NAME() ast_smdi_md_message_putback (struct ast_smdi_interface *iface, struct ast_smdi_md_message *md_msg)
 Put an SMDI message back in the front of the queue.
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.
void AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_destroy (struct ast_smdi_mwi_message *msg)
 ast_smdi_mwi_message destructor.
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.
static void ast_smdi_mwi_message_push (struct ast_smdi_interface *iface, struct ast_smdi_mwi_message *mwi_msg)
void AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_putback (struct ast_smdi_interface *iface, struct ast_smdi_mwi_message *mwi_msg)
 Put an SMDI message back in the front of the queue.
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.
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.
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_unset (struct ast_smdi_interface *iface, const char *mailbox)
 Unset the MWI indicator for a mailbox.
static void destroy_all_mailbox_mappings (void)
static void destroy_mailbox_mapping (struct mailbox_mapping *mm)
static int load_module (void)
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_load (int reload)
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 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)
static void unref_msg (void *msg, enum smdi_message_type type)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .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, .load = load_module, .unload = unload_module, .reload = reload, }
static 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.
static struct
ast_smdi_interface_container 
smdi_ifaces
 SMDI interface container.
static struct ast_datastore_info smdi_msg_datastore_info
static struct ast_custom_function smdi_msg_function
static int smdi_msg_id
static 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 <mnicholson@digium.com>

Russell Bryant <russell@digium.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.


Define Documentation

#define AST_API_MODULE

Definition at line 46 of file res_smdi.c.

#define DEFAULT_POLLING_INTERVAL   10

10 seconds

Definition at line 206 of file res_smdi.c.

Referenced by smdi_load().

#define SMDI_MSG_EXPIRY_TIME   30000

Definition at line 58 of file res_smdi.c.

Referenced by smdi_load().

#define SMDI_RETRIEVE_TIMEOUT_DEFAULT   3000

In milliseconds

Definition at line 1209 of file res_smdi.c.

Referenced by smdi_msg_retrieve_read().


Enumeration Type Documentation

anonymous enum

Enumerator:
OPT_SEARCH_TERMINAL 
OPT_SEARCH_NUMBER 

Definition at line 464 of file res_smdi.c.

00464      {
00465    OPT_SEARCH_TERMINAL = (1 << 0),
00466    OPT_SEARCH_NUMBER   = (1 << 1),
00467 };

Enumerator:
SMDI_MWI 
SMDI_MD 

Definition at line 340 of file res_smdi.c.

00340                        {
00341    SMDI_MWI,
00342    SMDI_MD,
00343 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1469 of file res_smdi.c.

static void __unreg_module ( void   )  [static]

Definition at line 1469 of file res_smdi.c.

static struct ast_smdi_interface* alloc_smdi_interface ( void   )  [static, read]

Definition at line 925 of file res_smdi.c.

References ast_calloc, ast_cond_init(), ast_mutex_init(), ASTOBJ_CONTAINER_INIT, ASTOBJ_INIT, ast_smdi_interface::md_q, ast_smdi_interface::md_q_cond, ast_smdi_interface::md_q_lock, ast_smdi_interface::mwi_q, ast_smdi_interface::mwi_q_cond, and ast_smdi_interface::mwi_q_lock.

Referenced by smdi_load().

00926 {
00927    struct ast_smdi_interface *iface;
00928 
00929    if (!(iface = ast_calloc(1, sizeof(*iface))))
00930       return NULL;
00931 
00932    ASTOBJ_INIT(iface);
00933    ASTOBJ_CONTAINER_INIT(&iface->md_q);
00934    ASTOBJ_CONTAINER_INIT(&iface->mwi_q);
00935 
00936    ast_mutex_init(&iface->md_q_lock);
00937    ast_cond_init(&iface->md_q_cond, NULL);
00938 
00939    ast_mutex_init(&iface->mwi_q_lock);
00940    ast_cond_init(&iface->mwi_q_cond, NULL);
00941 
00942    return iface;
00943 }

static void append_mailbox_mapping ( struct ast_variable var,
struct ast_smdi_interface iface 
) [static]

Definition at line 846 of file res_smdi.c.

References ast_calloc, AST_LIST_INSERT_TAIL, ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ASTOBJ_REF, context, free, mailbox_mapping::iface, mailbox, mwi_monitor, ast_variable::name, mailbox_mapping::smdi, strsep(), and ast_variable::value.

Referenced by smdi_load().

00847 {
00848    struct mailbox_mapping *mm;
00849    char *mailbox, *context;
00850 
00851    if (!(mm = ast_calloc(1, sizeof(*mm))))
00852       return;
00853    
00854    if (ast_string_field_init(mm, 32)) {
00855       free(mm);
00856       return;
00857    }
00858 
00859    ast_string_field_set(mm, smdi, var->name);
00860 
00861    context = ast_strdupa(var->value);
00862    mailbox = strsep(&context, "@");
00863    if (ast_strlen_zero(context))
00864       context = "default";
00865 
00866    ast_string_field_set(mm, mailbox, mailbox);
00867    ast_string_field_set(mm, context, context);
00868 
00869    mm->iface = ASTOBJ_REF(iface);
00870 
00871    ast_mutex_lock(&mwi_monitor.lock);
00872    AST_LIST_INSERT_TAIL(&mwi_monitor.mailbox_mappings, mm, entry);
00873    ast_mutex_unlock(&mwi_monitor.lock);
00874 }

static void ast_smdi_interface_destroy ( struct ast_smdi_interface iface  )  [static]

Definition at line 226 of file res_smdi.c.

References ast_cond_destroy(), ast_module_unref(), ast_mutex_destroy(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_smdi_md_message_destroy(), ast_smdi_mwi_message_destroy(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ast_smdi_interface::file, free, ast_smdi_interface::md_q, ast_smdi_interface::md_q_cond, ast_smdi_interface::md_q_lock, ast_smdi_interface::mwi_q, ast_smdi_interface::mwi_q_cond, ast_smdi_interface::mwi_q_lock, and ast_smdi_interface::thread.

Referenced by ast_smdi_interface_unref(), destroy_mailbox_mapping(), smdi_load(), smdi_msg_datastore_destroy(), smdi_msg_retrieve_read(), smdi_read(), and unload_module().

00227 {
00228    if (iface->thread != AST_PTHREADT_NULL && iface->thread != AST_PTHREADT_STOP) {
00229       pthread_cancel(iface->thread);
00230       pthread_join(iface->thread, NULL);
00231    }
00232    
00233    iface->thread = AST_PTHREADT_STOP;
00234    
00235    if (iface->file) 
00236       fclose(iface->file);
00237    
00238    ASTOBJ_CONTAINER_DESTROYALL(&iface->md_q, ast_smdi_md_message_destroy);
00239    ASTOBJ_CONTAINER_DESTROYALL(&iface->mwi_q, ast_smdi_mwi_message_destroy);
00240    ASTOBJ_CONTAINER_DESTROY(&iface->md_q);
00241    ASTOBJ_CONTAINER_DESTROY(&iface->mwi_q);
00242 
00243    ast_mutex_destroy(&iface->md_q_lock);
00244    ast_cond_destroy(&iface->md_q_cond);
00245 
00246    ast_mutex_destroy(&iface->mwi_q_lock);
00247    ast_cond_destroy(&iface->mwi_q_cond);
00248 
00249    free(iface);
00250 
00251    ast_module_unref(ast_module_info->self);
00252 }

struct ast_smdi_interface* AST_OPTIONAL_API_NAME() ast_smdi_interface_find ( const char *  iface_name  )  [read]

Find an SMDI interface with the specified name.

Parameters:
iface_name the name/port of the interface to search for.
Returns:
a pointer to the interface located or NULL if none was found. This actually returns an ASTOBJ reference and should be released using ASTOBJ_UNREF(iface, ast_smdi_interface_destroy).

Definition at line 622 of file res_smdi.c.

References ASTOBJ_CONTAINER_FIND, and smdi_ifaces.

Referenced by load_config(), mkintf(), and smdi_msg_retrieve_read().

00623 {
00624    return (ASTOBJ_CONTAINER_FIND(&smdi_ifaces, iface_name));
00625 }

void AST_OPTIONAL_API_NAME() ast_smdi_interface_unref ( struct ast_smdi_interface iface  ) 

Definition at line 254 of file res_smdi.c.

References ast_smdi_interface_destroy(), ASTOBJ_UNREF, and mailbox_mapping::iface.

Referenced by destroy_dahdi_pvt().

00255 {
00256    ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
00257 }

void AST_OPTIONAL_API_NAME() ast_smdi_md_message_destroy ( struct ast_smdi_md_message msg  ) 

ast_smdi_md_message destructor.

Definition at line 819 of file res_smdi.c.

References ast_free, and msg.

Referenced by analog_ss_thread(), ast_smdi_interface_destroy(), smdi_msg_datastore_destroy(), smdi_msg_retrieve_read(), smdi_read(), and unref_msg().

00820 {
00821    ast_free(msg);
00822 }

struct ast_smdi_md_message* AST_OPTIONAL_API_NAME() ast_smdi_md_message_pop ( struct ast_smdi_interface iface  )  [read]

Get the next SMDI message from the queue.

Parameters:
iface a 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 593 of file res_smdi.c.

References SMDI_MD, and smdi_msg_pop().

00594 {
00595    return smdi_msg_pop(iface, SMDI_MD);
00596 }

static void ast_smdi_md_message_push ( struct ast_smdi_interface iface,
struct ast_smdi_md_message md_msg 
) [static]

void AST_OPTIONAL_API_NAME() ast_smdi_md_message_putback ( struct ast_smdi_interface iface,
struct ast_smdi_md_message msg 
)

Put an SMDI message back in the front of the queue.

Parameters:
iface a pointer to the interface to use.
md_msg a pointer to the message to use.
This function puts a message back in the front of the specified queue. It should be used if a message was popped but is not going to be processed for some reason, and the message needs to be returned to the queue.

Definition at line 324 of file res_smdi.c.

References ast_cond_broadcast(), ast_mutex_lock(), ast_mutex_unlock(), ASTOBJ_CONTAINER_LINK_START, mailbox_mapping::iface, ast_smdi_interface::md_q, ast_smdi_interface::md_q_cond, and ast_smdi_interface::md_q_lock.

00325 {
00326    ast_mutex_lock(&iface->md_q_lock);
00327    ASTOBJ_CONTAINER_LINK_START(&iface->md_q, md_msg);
00328    ast_cond_broadcast(&iface->md_q_cond);
00329    ast_mutex_unlock(&iface->md_q_lock);
00330 }

struct ast_smdi_md_message* AST_OPTIONAL_API_NAME() ast_smdi_md_message_wait ( struct ast_smdi_interface iface,
int  timeout 
) [read]

Get the next SMDI message from the queue.

Parameters:
iface a pointer to the interface to use.
timeout the 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 598 of file res_smdi.c.

References SMDI_MD, and smdi_message_wait().

Referenced by analog_ss_thread().

00599 {
00600    struct ast_flags options = { 0 };
00601    return smdi_message_wait(iface, timeout, SMDI_MD, NULL, options);
00602 }

void AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_destroy ( struct ast_smdi_mwi_message msg  ) 

ast_smdi_mwi_message destructor.

Definition at line 824 of file res_smdi.c.

References ast_free, and msg.

Referenced by ast_smdi_interface_destroy(), run_externnotify(), smdi_read(), and unref_msg().

00825 {
00826    ast_free(msg);
00827 }

struct ast_smdi_mwi_message* AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_pop ( struct ast_smdi_interface iface  )  [read]

Get the next SMDI message from the queue.

Parameters:
iface a 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 604 of file res_smdi.c.

References smdi_msg_pop(), and SMDI_MWI.

00605 {
00606    return smdi_msg_pop(iface, SMDI_MWI);
00607 }

static void ast_smdi_mwi_message_push ( struct ast_smdi_interface iface,
struct ast_smdi_mwi_message mwi_msg 
) [static]

void AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_putback ( struct ast_smdi_interface iface,
struct ast_smdi_mwi_message msg 
)

Put an SMDI message back in the front of the queue.

Parameters:
iface a pointer to the interface to use.
mwi_msg a pointer to the message to use.
This function puts a message back in the front of the specified queue. It should be used if a message was popped but is not going to be processed for some reason, and the message needs to be returned to the queue.

Definition at line 332 of file res_smdi.c.

References ast_cond_broadcast(), ast_mutex_lock(), ast_mutex_unlock(), ASTOBJ_CONTAINER_LINK_START, mailbox_mapping::iface, ast_smdi_interface::mwi_q, ast_smdi_interface::mwi_q_cond, and ast_smdi_interface::mwi_q_lock.

00333 {
00334    ast_mutex_lock(&iface->mwi_q_lock);
00335    ASTOBJ_CONTAINER_LINK_START(&iface->mwi_q, mwi_msg);
00336    ast_cond_broadcast(&iface->mwi_q_cond);
00337    ast_mutex_unlock(&iface->mwi_q_lock);
00338 }

struct ast_smdi_mwi_message* AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_wait ( struct ast_smdi_interface iface,
int  timeout 
) [read]

Get the next SMDI message from the queue.

Parameters:
iface a pointer to the interface to use.
timeout the 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 609 of file res_smdi.c.

References smdi_message_wait(), and SMDI_MWI.

00610 {
00611    struct ast_flags options = { 0 };
00612    return smdi_message_wait(iface, timeout, SMDI_MWI, NULL, options);
00613 }

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 
) [read]

Definition at line 615 of file res_smdi.c.

References smdi_message_wait(), and SMDI_MWI.

Referenced by run_externnotify().

00617 {
00618    struct ast_flags options = { 0 };
00619    return smdi_message_wait(iface, timeout, SMDI_MWI, station, options);
00620 }

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:
iface the interface to use.
mailbox the mailbox to use.

Definition at line 314 of file res_smdi.c.

References mailbox_mapping::iface, mailbox_mapping::mailbox, and smdi_toggle_mwi().

Referenced by poll_mailbox(), and run_externnotify().

00315 {
00316    return smdi_toggle_mwi(iface, mailbox, 1);
00317 }

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:
iface the interface to use.
mailbox the mailbox to use.

Definition at line 319 of file res_smdi.c.

References mailbox_mapping::iface, mailbox_mapping::mailbox, and smdi_toggle_mwi().

Referenced by poll_mailbox(), and run_externnotify().

00320 {
00321    return smdi_toggle_mwi(iface, mailbox, 0);
00322 }

static void destroy_all_mailbox_mappings ( void   )  [static]

Definition at line 836 of file res_smdi.c.

References AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), destroy_mailbox_mapping(), and mwi_monitor.

Referenced by smdi_load(), and unload_module().

00837 {
00838    struct mailbox_mapping *mm;
00839 
00840    ast_mutex_lock(&mwi_monitor.lock);
00841    while ((mm = AST_LIST_REMOVE_HEAD(&mwi_monitor.mailbox_mappings, entry)))
00842       destroy_mailbox_mapping(mm);
00843    ast_mutex_unlock(&mwi_monitor.lock);
00844 }

static void destroy_mailbox_mapping ( struct mailbox_mapping mm  )  [static]

static int load_module ( void   )  [static]

Definition at line 1399 of file res_smdi.c.

References ast_cond_init(), ast_custom_function_register, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_mutex_init(), ASTOBJ_CONTAINER_INIT, LOG_NOTICE, mwi_monitor, smdi_ifaces, smdi_load(), and unload_module.

01400 {
01401    int res;
01402    
01403    /* initialize our containers */
01404    memset(&smdi_ifaces, 0, sizeof(smdi_ifaces));
01405    ASTOBJ_CONTAINER_INIT(&smdi_ifaces);
01406    
01407    ast_mutex_init(&mwi_monitor.lock);
01408    ast_cond_init(&mwi_monitor.cond, NULL);
01409 
01410    ast_custom_function_register(&smdi_msg_retrieve_function);
01411    ast_custom_function_register(&smdi_msg_function);
01412 
01413    /* load the config and start the listener threads*/
01414    res = smdi_load(0);
01415    if (res < 0) {
01416       unload_module();
01417       return res;
01418    } else if (res == 1) {
01419       unload_module();
01420       ast_log(LOG_NOTICE, "No SMDI interfaces are available to listen on, not starting SMDI listener.\n");
01421       return AST_MODULE_LOAD_DECLINE;
01422    }
01423    
01424    return AST_MODULE_LOAD_SUCCESS;
01425 }

static int lock_msg_q ( struct ast_smdi_interface iface,
enum smdi_message_type  type 
) [inline, static]

Definition at line 345 of file res_smdi.c.

References ast_mutex_lock(), ast_smdi_interface::md_q_lock, ast_smdi_interface::mwi_q_lock, SMDI_MD, and SMDI_MWI.

Referenced by purge_old_messages(), smdi_message_wait(), and smdi_msg_pop().

00346 {
00347    switch (type) {
00348    case SMDI_MWI:
00349       return ast_mutex_lock(&iface->mwi_q_lock);
00350    case SMDI_MD:  
00351       return ast_mutex_lock(&iface->md_q_lock);
00352    }
00353    
00354    return -1;
00355 }

static struct timeval msg_timestamp ( void *  msg,
enum smdi_message_type  type 
) [static, read]

Definition at line 380 of file res_smdi.c.

References ast_tv(), msg, SMDI_MD, SMDI_MWI, ast_smdi_md_message::timestamp, ast_smdi_mwi_message::timestamp, and type.

Referenced by purge_old_messages().

00381 {
00382    struct ast_smdi_md_message *md_msg = msg;
00383    struct ast_smdi_mwi_message *mwi_msg = msg;
00384 
00385    switch (type) {
00386    case SMDI_MWI:
00387       return mwi_msg->timestamp;
00388    case SMDI_MD:
00389       return md_msg->timestamp;
00390    }
00391 
00392    return ast_tv(0, 0);
00393 }

static void* mwi_monitor_handler ( void *  data  )  [static]

Definition at line 898 of file res_smdi.c.

References ast_cond_timedwait(), AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_tv(), ast_tvadd(), ast_tvnow(), mwi_monitor, and poll_mailbox().

Referenced by smdi_load().

00899 {
00900    while (!mwi_monitor.stop) {
00901       struct timespec ts = { 0, };
00902       struct timeval polltime;
00903       struct mailbox_mapping *mm;
00904 
00905       ast_mutex_lock(&mwi_monitor.lock);
00906 
00907       mwi_monitor.last_poll = ast_tvnow();
00908 
00909       AST_LIST_TRAVERSE(&mwi_monitor.mailbox_mappings, mm, entry)
00910          poll_mailbox(mm);
00911 
00912       /* Sleep up to the configured polling interval.  Allow unload_module()
00913        * to signal us to wake up and exit. */
00914       polltime = ast_tvadd(mwi_monitor.last_poll, ast_tv(mwi_monitor.polling_interval, 0));
00915       ts.tv_sec = polltime.tv_sec;
00916       ts.tv_nsec = polltime.tv_usec * 1000;
00917       ast_cond_timedwait(&mwi_monitor.cond, &mwi_monitor.lock, &ts);
00918 
00919       ast_mutex_unlock(&mwi_monitor.lock);
00920    }
00921 
00922    return NULL;
00923 }

static void poll_mailbox ( struct mailbox_mapping mm  )  [static]

Note:
Called with the mwi_monitor.lock locked

Definition at line 879 of file res_smdi.c.

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

Referenced by mwi_monitor_handler().

00880 {
00881    char buf[1024];
00882    unsigned int state;
00883 
00884    snprintf(buf, sizeof(buf), "%s@%s", mm->mailbox, mm->context);
00885 
00886    state = !!ast_app_has_voicemail(mm->mailbox, NULL);
00887 
00888    if (state != mm->cur_state) {
00889       if (state)
00890          ast_smdi_mwi_set(mm->iface, mm->smdi);
00891       else
00892          ast_smdi_mwi_unset(mm->iface, mm->smdi);
00893 
00894       mm->cur_state = state;
00895    }
00896 }

static void purge_old_messages ( struct ast_smdi_interface iface,
enum smdi_message_type  type 
) [static]

Definition at line 410 of file res_smdi.c.

References ast_log(), ast_smdi_md_message_push(), ast_smdi_mwi_message_push(), ast_tvdiff_ms(), ast_tvnow(), lock_msg_q(), LOG_NOTICE, msg, ast_smdi_interface::msg_expiry, msg_timestamp(), ast_smdi_interface::name, SMDI_MD, SMDI_MWI, unlink_from_msg_q(), unlock_msg_q(), and unref_msg().

Referenced by smdi_msg_find(), and smdi_msg_pop().

00411 {
00412    struct timeval now = ast_tvnow();
00413    long elapsed = 0;
00414    void *msg;
00415    
00416    lock_msg_q(iface, type);
00417    msg = unlink_from_msg_q(iface, type);
00418    unlock_msg_q(iface, type);
00419 
00420    /* purge old messages */
00421    while (msg) {
00422       elapsed = ast_tvdiff_ms(now, msg_timestamp(msg, type));
00423 
00424       if (elapsed > iface->msg_expiry) {
00425          /* found an expired message */
00426          unref_msg(msg, type);
00427          ast_log(LOG_NOTICE, "Purged expired message from %s SMDI %s message queue.  "
00428             "Message was %ld milliseconds too old.\n",
00429             iface->name, (type == SMDI_MD) ? "MD" : "MWI", 
00430             elapsed - iface->msg_expiry);
00431 
00432          lock_msg_q(iface, type);
00433          msg = unlink_from_msg_q(iface, type);
00434          unlock_msg_q(iface, type);
00435       } else {
00436          /* good message, put it back and return */
00437          switch (type) {
00438          case SMDI_MD:
00439             ast_smdi_md_message_push(iface, msg);
00440             break;
00441          case SMDI_MWI:
00442             ast_smdi_mwi_message_push(iface, msg);
00443             break;
00444          }
00445          unref_msg(msg, type);
00446          break;
00447       }
00448    }
00449 }

static int reload ( void   )  [static]

Definition at line 1450 of file res_smdi.c.

References ast_log(), LOG_WARNING, and smdi_load().

01451 {
01452    int res;
01453 
01454    res = smdi_load(1);
01455 
01456    if (res < 0) {
01457       return res;
01458    } else if (res == 1) {
01459       ast_log(LOG_WARNING, "No SMDI interfaces were specified to listen on, not starting SDMI listener.\n");
01460       return 0;
01461    } else
01462       return 0;
01463 }

static int smdi_load ( int  reload  )  [static]

Definition at line 955 of file res_smdi.c.

References alloc_smdi_interface(), append_mailbox_mapping(), ast_config_destroy(), ast_config_load, ast_copy_string(), AST_LIST_EMPTY, ast_log(), AST_MODULE_LOAD_FAILURE, ast_module_ref(), ast_pthread_create_background, AST_PTHREADT_NULL, ast_smdi_interface_destroy(), ast_true(), ast_variable_browse(), ast_verb, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_CONTAINER_PRUNE_MARKED, ASTOBJ_CONTAINER_RDLOCK, ASTOBJ_CONTAINER_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_POLLING_INTERVAL, destroy_all_mailbox_mappings(), errno, ast_smdi_interface::fd, ast_smdi_interface::file, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, ast_smdi_interface::mode, ast_smdi_interface::msdstrip, ast_smdi_interface::msg_expiry, mwi_monitor, mwi_monitor_handler(), ast_smdi_interface::name, ast_variable::name, ast_variable::next, smdi_ifaces, SMDI_MSG_EXPIRY_TIME, smdi_read(), ast_smdi_interface::thread, and ast_variable::value.

Referenced by load_module(), and reload().

00956 {
00957    struct ast_config *conf;
00958    struct ast_variable *v;
00959    struct ast_smdi_interface *iface = NULL;
00960    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00961    int res = 0;
00962 
00963    /* Config options */
00964    speed_t baud_rate = B9600;     /* 9600 baud rate */
00965    tcflag_t paritybit = PARENB;   /* even parity checking */
00966    tcflag_t charsize = CS7;       /* seven bit characters */
00967    int stopbits = 0;              /* One stop bit */
00968    
00969    int msdstrip = 0;              /* strip zero digits */
00970    long msg_expiry = SMDI_MSG_EXPIRY_TIME;
00971 
00972    if (!(conf = ast_config_load(config_file, config_flags)) || conf == CONFIG_STATUS_FILEINVALID) {
00973       if (reload)
00974          ast_log(LOG_NOTICE, "Unable to reload config %s: SMDI untouched\n", config_file);
00975       else
00976          ast_log(LOG_NOTICE, "Unable to load config %s: SMDI disabled\n", config_file);
00977       return 1;
00978    } else if (conf == CONFIG_STATUS_FILEUNCHANGED)
00979       return 0;
00980 
00981    /* Mark all interfaces that we are listening on.  We will unmark them
00982     * as we find them in the config file, this way we know any interfaces
00983     * still marked after we have finished parsing the config file should
00984     * be stopped.
00985     */
00986    if (reload)
00987       ASTOBJ_CONTAINER_MARKALL(&smdi_ifaces);
00988 
00989    for (v = ast_variable_browse(conf, "interfaces"); v; v = v->next) {
00990       if (!strcasecmp(v->name, "baudrate")) {
00991          if (!strcasecmp(v->value, "9600"))
00992             baud_rate = B9600;
00993          else if (!strcasecmp(v->value, "4800"))
00994             baud_rate = B4800;
00995          else if (!strcasecmp(v->value, "2400"))
00996             baud_rate = B2400;
00997          else if (!strcasecmp(v->value, "1200"))
00998             baud_rate = B1200;
00999          else {
01000             ast_log(LOG_NOTICE, "Invalid baud rate '%s' specified in %s (line %d), using default\n", v->value, config_file, v->lineno);
01001             baud_rate = B9600;
01002          }
01003       } else if (!strcasecmp(v->name, "msdstrip")) {
01004          if (!sscanf(v->value, "%30d", &msdstrip)) {
01005             ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno);
01006             msdstrip = 0;
01007          } else if (0 > msdstrip || msdstrip > 9) {
01008             ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno);
01009             msdstrip = 0;
01010          }
01011       } else if (!strcasecmp(v->name, "msgexpirytime")) {
01012          if (!sscanf(v->value, "%30ld", &msg_expiry)) {
01013             ast_log(LOG_NOTICE, "Invalid msgexpirytime value in %s (line %d), using default\n", config_file, v->lineno);
01014             msg_expiry = SMDI_MSG_EXPIRY_TIME;
01015          }
01016       } else if (!strcasecmp(v->name, "paritybit")) {
01017          if (!strcasecmp(v->value, "even"))
01018             paritybit = PARENB;
01019          else if (!strcasecmp(v->value, "odd"))
01020             paritybit = PARENB | PARODD;
01021          else if (!strcasecmp(v->value, "none"))
01022             paritybit = ~PARENB;
01023          else {
01024             ast_log(LOG_NOTICE, "Invalid parity bit setting in %s (line %d), using default\n", config_file, v->lineno);
01025             paritybit = PARENB;
01026          }
01027       } else if (!strcasecmp(v->name, "charsize")) {
01028          if (!strcasecmp(v->value, "7"))
01029             charsize = CS7;
01030          else if (!strcasecmp(v->value, "8"))
01031             charsize = CS8;
01032          else {
01033             ast_log(LOG_NOTICE, "Invalid character size setting in %s (line %d), using default\n", config_file, v->lineno);
01034             charsize = CS7;
01035          }
01036       } else if (!strcasecmp(v->name, "twostopbits")) {
01037          stopbits = ast_true(v->name);
01038       } else if (!strcasecmp(v->name, "smdiport")) {
01039          if (reload) {
01040             /* we are reloading, check if we are already
01041              * monitoring this interface, if we are we do
01042              * not want to start it again.  This also has
01043              * the side effect of not updating different
01044              * setting for the serial port, but it should
01045              * be trivial to rewrite this section so that
01046              * options on the port are changed without
01047              * restarting the interface.  Or the interface
01048              * could be restarted with out emptying the
01049              * queue. */
01050             if ((iface = ASTOBJ_CONTAINER_FIND(&smdi_ifaces, v->value))) {
01051                ast_log(LOG_NOTICE, "SMDI interface %s already running, not restarting\n", iface->name);
01052                ASTOBJ_UNMARK(iface);
01053                ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01054                continue;
01055             }
01056          }
01057          
01058          if (!(iface = alloc_smdi_interface()))
01059             continue;
01060 
01061          ast_copy_string(iface->name, v->value, sizeof(iface->name));
01062 
01063          iface->thread = AST_PTHREADT_NULL;
01064 
01065          if (!(iface->file = fopen(iface->name, "r"))) {
01066             ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s)\n", iface->name, strerror(errno));
01067             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01068             continue;
01069          }
01070 
01071          iface->fd = fileno(iface->file);
01072 
01073          /* Set the proper attributes for our serial port. */
01074 
01075          /* get the current attributes from the port */
01076          if (tcgetattr(iface->fd, &iface->mode)) {
01077             ast_log(LOG_ERROR, "Error getting atributes of %s (%s)\n", iface->name, strerror(errno));
01078             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01079             continue;
01080          }
01081 
01082          /* set the desired speed */
01083          if (cfsetispeed(&iface->mode, baud_rate) || cfsetospeed(&iface->mode, baud_rate)) {
01084             ast_log(LOG_ERROR, "Error setting baud rate on %s (%s)\n", iface->name, strerror(errno));
01085             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01086             continue;
01087          }
01088          
01089          /* set the stop bits */
01090          if (stopbits)
01091             iface->mode.c_cflag = iface->mode.c_cflag | CSTOPB;   /* set two stop bits */
01092          else
01093             iface->mode.c_cflag = iface->mode.c_cflag & ~CSTOPB;  /* set one stop bit */
01094          
01095          /* set the parity */
01096          iface->mode.c_cflag = (iface->mode.c_cflag & ~PARENB & ~PARODD) | paritybit;
01097          
01098          /* set the character size */
01099          iface->mode.c_cflag = (iface->mode.c_cflag & ~CSIZE) | charsize;
01100          
01101          /* commit the desired attributes */
01102          if (tcsetattr(iface->fd, TCSAFLUSH, &iface->mode)) {
01103             ast_log(LOG_ERROR, "Error setting attributes on %s (%s)\n", iface->name, strerror(errno));
01104             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01105             continue;
01106          }
01107 
01108          /* set the msdstrip */
01109          iface->msdstrip = msdstrip;
01110 
01111          /* set the message expiry time */
01112          iface->msg_expiry = msg_expiry;
01113 
01114          /* start the listener thread */
01115          ast_verb(3, "Starting SMDI monitor thread for %s\n", iface->name);
01116          if (ast_pthread_create_background(&iface->thread, NULL, smdi_read, iface)) {
01117             ast_log(LOG_ERROR, "Error starting SMDI monitor thread for %s\n", iface->name);
01118             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01119             continue;
01120          }
01121 
01122          ASTOBJ_CONTAINER_LINK(&smdi_ifaces, iface);
01123          ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01124          ast_module_ref(ast_module_info->self);
01125       } else {
01126          ast_log(LOG_NOTICE, "Ignoring unknown option %s in %s\n", v->name, config_file);
01127       }
01128    }
01129 
01130    destroy_all_mailbox_mappings();
01131    mwi_monitor.polling_interval = DEFAULT_POLLING_INTERVAL;
01132    
01133    iface = NULL;
01134 
01135    for (v = ast_variable_browse(conf, "mailboxes"); v; v = v->next) {
01136       if (!strcasecmp(v->name, "smdiport")) {
01137          if (iface)
01138             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01139 
01140          if (!(iface = ASTOBJ_CONTAINER_FIND(&smdi_ifaces, v->value))) {
01141             ast_log(LOG_NOTICE, "SMDI interface %s not found\n", v->value);
01142             continue;
01143          }
01144       } else if (!strcasecmp(v->name, "pollinginterval")) {
01145          if (sscanf(v->value, "%30u", &mwi_monitor.polling_interval) != 1) {
01146             ast_log(LOG_ERROR, "Invalid value for pollinginterval: %s\n", v->value);
01147             mwi_monitor.polling_interval = DEFAULT_POLLING_INTERVAL;
01148          }
01149       } else {
01150          if (!iface) {
01151             ast_log(LOG_ERROR, "Mailbox mapping ignored, no valid SMDI interface specified in mailboxes section\n");
01152             continue;
01153          }
01154          append_mailbox_mapping(v, iface);
01155       }
01156    }
01157 
01158    if (iface)
01159       ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01160 
01161    ast_config_destroy(conf);
01162    
01163    if (!AST_LIST_EMPTY(&mwi_monitor.mailbox_mappings) && mwi_monitor.thread == AST_PTHREADT_NULL
01164       && ast_pthread_create_background(&mwi_monitor.thread, NULL, mwi_monitor_handler, NULL)) {
01165       ast_log(LOG_ERROR, "Failed to start MWI monitoring thread.  This module will not operate.\n");
01166       return AST_MODULE_LOAD_FAILURE;
01167    }
01168 
01169    /* Prune any interfaces we should no longer monitor. */
01170    if (reload)
01171       ASTOBJ_CONTAINER_PRUNE_MARKED(&smdi_ifaces, ast_smdi_interface_destroy);
01172    
01173    ASTOBJ_CONTAINER_RDLOCK(&smdi_ifaces);
01174    /* TODO: this is bad, we need an ASTOBJ method for this! */
01175    if (!smdi_ifaces.head)
01176       res = 1;
01177    ASTOBJ_CONTAINER_UNLOCK(&smdi_ifaces);
01178    
01179    return res;
01180 }

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]

Definition at line 537 of file res_smdi.c.

References ast_cond_timedwait(), ast_tv(), ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), cond, lock, lock_msg_q(), ast_smdi_interface::md_q_cond, ast_smdi_interface::md_q_lock, msg, ast_smdi_interface::mwi_q_cond, ast_smdi_interface::mwi_q_lock, SMDI_MD, smdi_msg_find(), SMDI_MWI, and unlock_msg_q().

Referenced by ast_smdi_md_message_wait(), ast_smdi_mwi_message_wait(), ast_smdi_mwi_message_wait_station(), and smdi_msg_retrieve_read().

00539 {
00540    struct timeval start;
00541    long diff = 0;
00542    void *msg;
00543    ast_cond_t *cond = NULL;
00544    ast_mutex_t *lock = NULL;
00545 
00546    switch (type) {
00547    case SMDI_MWI:
00548       cond = &iface->mwi_q_cond;
00549       lock = &iface->mwi_q_lock;
00550       break;
00551    case SMDI_MD:
00552       cond = &iface->md_q_cond;
00553       lock = &iface->md_q_lock;
00554       break;
00555    }
00556 
00557    start = ast_tvnow();
00558 
00559    while (diff < timeout) {
00560       struct timespec ts = { 0, };
00561       struct timeval wait;
00562 
00563       lock_msg_q(iface, type);
00564 
00565       if ((msg = smdi_msg_find(iface, type, search_key, options))) {
00566          unlock_msg_q(iface, type);
00567          return msg;
00568       }
00569 
00570       wait = ast_tvadd(start, ast_tv(0, timeout));
00571       ts.tv_sec = wait.tv_sec;
00572       ts.tv_nsec = wait.tv_usec * 1000;
00573 
00574       /* If there were no messages in the queue, then go to sleep until one
00575        * arrives. */
00576 
00577       ast_cond_timedwait(cond, lock, &ts);
00578 
00579       if ((msg = smdi_msg_find(iface, type, search_key, options))) {
00580          unlock_msg_q(iface, type);
00581          return msg;
00582       }
00583 
00584       unlock_msg_q(iface, type);
00585 
00586       /* check timeout */
00587       diff = ast_tvdiff_ms(ast_tvnow(), start);
00588    }
00589 
00590    return NULL;
00591 }

static void smdi_msg_datastore_destroy ( void *  data  )  [static]

Definition at line 1188 of file res_smdi.c.

References ast_smdi_interface_destroy(), ast_smdi_md_message_destroy(), ASTOBJ_UNREF, free, smdi_msg_datastore::iface, and smdi_msg_datastore::md_msg.

Referenced by smdi_msg_retrieve_read().

01189 {
01190    struct smdi_msg_datastore *smd = data;
01191 
01192    if (smd->iface)
01193       ASTOBJ_UNREF(smd->iface, ast_smdi_interface_destroy);
01194 
01195    if (smd->md_msg)
01196       ASTOBJ_UNREF(smd->md_msg, ast_smdi_md_message_destroy);
01197 
01198    free(smd);
01199 }

static void* smdi_msg_find ( struct ast_smdi_interface iface,
enum smdi_message_type  type,
const char *  search_key,
struct ast_flags  options 
) [static]

Definition at line 469 of file res_smdi.c.

References ast_strlen_zero(), ast_test_flag, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_REF, ast_smdi_interface::md_q, msg, OPT_SEARCH_TERMINAL, purge_old_messages(), and SMDI_MD.

Referenced by smdi_message_wait().

00471 {
00472    void *msg = NULL;
00473 
00474    purge_old_messages(iface, type);
00475 
00476    switch (type) {
00477    case SMDI_MD:
00478       if (ast_strlen_zero(search_key)) {
00479          struct ast_smdi_md_message *md_msg = NULL;
00480 
00481          /* No search key provided (the code from chan_dahdi does this).
00482           * Just pop the top message off of the queue. */
00483 
00484          ASTOBJ_CONTAINER_TRAVERSE(&iface->md_q, !md_msg, do {
00485             md_msg = ASTOBJ_REF(iterator);
00486          } while (0); );
00487 
00488          msg = md_msg;
00489       } else if (ast_test_flag(&options, OPT_SEARCH_TERMINAL)) {
00490          struct ast_smdi_md_message *md_msg = NULL;
00491 
00492          /* Searching by the message desk terminal */
00493 
00494          ASTOBJ_CONTAINER_TRAVERSE(&iface->md_q, !md_msg, do {
00495             if (!strcasecmp(iterator->mesg_desk_term, search_key))
00496                md_msg = ASTOBJ_REF(iterator);
00497          } while (0); );
00498 
00499          msg = md_msg;
00500       } else if (ast_test_flag(&options, OPT_SEARCH_NUMBER)) {
00501          struct ast_smdi_md_message *md_msg = NULL;
00502 
00503          /* Searching by the message desk number */
00504 
00505          ASTOBJ_CONTAINER_TRAVERSE(&iface->md_q, !md_msg, do {
00506             if (!strcasecmp(iterator->mesg_desk_num, search_key))
00507                md_msg = ASTOBJ_REF(iterator);
00508          } while (0); );
00509 
00510          msg = md_msg;
00511       } else {
00512          /* Searching by the forwarding station */
00513          msg = ASTOBJ_CONTAINER_FIND(&iface->md_q, search_key);
00514       }
00515       break;
00516    case SMDI_MWI:
00517       if (ast_strlen_zero(search_key)) {
00518          struct ast_smdi_mwi_message *mwi_msg = NULL;
00519 
00520          /* No search key provided (the code from chan_dahdi does this).
00521           * Just pop the top message off of the queue. */
00522 
00523          ASTOBJ_CONTAINER_TRAVERSE(&iface->mwi_q, !mwi_msg, do {
00524             mwi_msg = ASTOBJ_REF(iterator);
00525          } while (0); );
00526 
00527          msg = mwi_msg;
00528       } else {
00529          msg = ASTOBJ_CONTAINER_FIND(&iface->mwi_q, search_key);
00530       }
00531       break;
00532    }
00533 
00534    return msg;
00535 }

static void* smdi_msg_pop ( struct ast_smdi_interface iface,
enum smdi_message_type  type 
) [static]

Definition at line 451 of file res_smdi.c.

References lock_msg_q(), msg, purge_old_messages(), unlink_from_msg_q(), and unlock_msg_q().

Referenced by ast_smdi_md_message_pop(), and ast_smdi_mwi_message_pop().

00452 {
00453    void *msg;
00454 
00455    purge_old_messages(iface, type);
00456 
00457    lock_msg_q(iface, type);
00458    msg = unlink_from_msg_q(iface, type);
00459    unlock_msg_q(iface, type);
00460 
00461    return msg;
00462 }

static int smdi_msg_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 1315 of file res_smdi.c.

References AST_APP_ARG, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), ast_module_user_add, ast_module_user_remove, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_smdi_md_message::calling_st, ast_datastore::data, ast_smdi_md_message::fwd_st, LOG_ERROR, LOG_WARNING, smdi_msg_datastore::md_msg, ast_smdi_md_message::mesg_desk_num, ast_smdi_md_message::mesg_desk_term, parse(), and ast_smdi_md_message::type.

01316 {
01317    struct ast_module_user *u;
01318    int res = -1;
01319    AST_DECLARE_APP_ARGS(args,
01320       AST_APP_ARG(id);
01321       AST_APP_ARG(component);
01322    );
01323    char *parse;
01324    struct ast_datastore *datastore = NULL;
01325    struct smdi_msg_datastore *smd = NULL;
01326 
01327    u = ast_module_user_add(chan);
01328 
01329    if (!chan) {
01330       ast_log(LOG_ERROR, "SMDI_MSG can not be called without a channel\n");
01331       goto return_error;
01332    }
01333 
01334    if (ast_strlen_zero(data)) {
01335       ast_log(LOG_WARNING, "SMDI_MSG requires an argument\n");
01336       goto return_error;
01337    }
01338 
01339    parse = ast_strdupa(data);
01340    AST_STANDARD_APP_ARGS(args, parse);
01341 
01342    if (ast_strlen_zero(args.id)) {
01343       ast_log(LOG_WARNING, "ID must be supplied to SMDI_MSG\n");
01344       goto return_error;
01345    }
01346 
01347    if (ast_strlen_zero(args.component)) {
01348       ast_log(LOG_WARNING, "ID must be supplied to SMDI_MSG\n");
01349       goto return_error;
01350    }
01351 
01352    ast_channel_lock(chan);
01353    datastore = ast_channel_datastore_find(chan, &smdi_msg_datastore_info, args.id);
01354    ast_channel_unlock(chan);
01355    
01356    if (!datastore) {
01357       ast_log(LOG_WARNING, "No SMDI message found for message ID '%s'\n", args.id);
01358       goto return_error;
01359    }
01360 
01361    smd = datastore->data;
01362 
01363    if (!strcasecmp(args.component, "number")) {
01364       ast_copy_string(buf, smd->md_msg->mesg_desk_num, len);
01365    } else if (!strcasecmp(args.component, "terminal")) {
01366       ast_copy_string(buf, smd->md_msg->mesg_desk_term, len);
01367    } else if (!strcasecmp(args.component, "station")) {
01368       ast_copy_string(buf, smd->md_msg->fwd_st, len);
01369    } else if (!strcasecmp(args.component, "callerid")) {
01370       ast_copy_string(buf, smd->md_msg->calling_st, len);
01371    } else if (!strcasecmp(args.component, "type")) {
01372       snprintf(buf, len, "%c", smd->md_msg->type);
01373    } else {
01374       ast_log(LOG_ERROR, "'%s' is not a valid message component for SMDI_MSG\n",
01375          args.component);
01376       goto return_error;
01377    }
01378 
01379    res = 0;
01380 
01381 return_error:
01382    ast_module_user_remove(u);
01383 
01384    return res;
01385 }

static int smdi_msg_retrieve_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 1216 of file res_smdi.c.

References AST_APP_ARG, ast_app_parse_options(), ast_atomic_fetchadd_int(), ast_autoservice_start(), ast_autoservice_stop(), ast_calloc, ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, AST_DECLARE_APP_ARGS, ast_log(), ast_module_user_add, ast_module_user_remove, ast_smdi_interface_destroy(), ast_smdi_interface_find(), ast_smdi_md_message_destroy(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ASTOBJ_REF, ASTOBJ_UNREF, ast_datastore::data, smdi_msg_datastore::id, smdi_msg_datastore::iface, LOG_ERROR, LOG_WARNING, smdi_msg_datastore::md_msg, parse(), SMDI_MD, smdi_message_wait(), smdi_msg_datastore_destroy(), smdi_msg_ret_options, and SMDI_RETRIEVE_TIMEOUT_DEFAULT.

01217 {
01218    struct ast_module_user *u;
01219    AST_DECLARE_APP_ARGS(args,
01220       AST_APP_ARG(port);
01221       AST_APP_ARG(search_key);
01222       AST_APP_ARG(timeout);
01223       AST_APP_ARG(options);
01224    );
01225    struct ast_flags options = { 0 };
01226    unsigned int timeout = SMDI_RETRIEVE_TIMEOUT_DEFAULT;
01227    int res = -1;
01228    char *parse = NULL;
01229    struct smdi_msg_datastore *smd = NULL;
01230    struct ast_datastore *datastore = NULL;
01231    struct ast_smdi_interface *iface = NULL;
01232    struct ast_smdi_md_message *md_msg = NULL;
01233 
01234    u = ast_module_user_add(chan);
01235 
01236    if (ast_strlen_zero(data)) {
01237       ast_log(LOG_ERROR, "SMDI_MSG_RETRIEVE requires an argument\n");
01238       goto return_error;
01239    }
01240 
01241    if (!chan) {
01242       ast_log(LOG_ERROR, "SMDI_MSG_RETRIEVE must be used with a channel\n");
01243       goto return_error;
01244    }
01245 
01246    ast_autoservice_start(chan);
01247 
01248    parse = ast_strdupa(data);
01249    AST_STANDARD_APP_ARGS(args, parse);
01250 
01251    if (ast_strlen_zero(args.port) || ast_strlen_zero(args.search_key)) {
01252       ast_log(LOG_ERROR, "Invalid arguments provided to SMDI_MSG_RETRIEVE\n");
01253       goto return_error;
01254    }
01255 
01256    if (!(iface = ast_smdi_interface_find(args.port))) {
01257       ast_log(LOG_ERROR, "SMDI port '%s' not found\n", args.port);
01258       goto return_error;
01259    }
01260 
01261    if (!ast_strlen_zero(args.options)) {
01262       ast_app_parse_options(smdi_msg_ret_options, &options, NULL, args.options);
01263    }
01264 
01265    if (!ast_strlen_zero(args.timeout)) {
01266       if (sscanf(args.timeout, "%30u", &timeout) != 1) {
01267          ast_log(LOG_ERROR, "'%s' is not a valid timeout\n", args.timeout);
01268          timeout = SMDI_RETRIEVE_TIMEOUT_DEFAULT;
01269       }
01270    }
01271 
01272    if (!(md_msg = smdi_message_wait(iface, timeout, SMDI_MD, args.search_key, options))) {
01273       ast_log(LOG_WARNING, "No SMDI message retrieved for search key '%s' after "
01274          "waiting %u ms.\n", args.search_key, timeout);
01275       goto return_error;
01276    }
01277 
01278    if (!(smd = ast_calloc(1, sizeof(*smd))))
01279       goto return_error;
01280 
01281    smd->iface = ASTOBJ_REF(iface);
01282    smd->md_msg = ASTOBJ_REF(md_msg);
01283    smd->id = ast_atomic_fetchadd_int((int *) &smdi_msg_id, 1);
01284    snprintf(buf, len, "%u", smd->id);
01285 
01286    if (!(datastore = ast_datastore_alloc(&smdi_msg_datastore_info, buf)))
01287       goto return_error;
01288 
01289    datastore->data = smd;
01290 
01291    ast_channel_lock(chan);
01292    ast_channel_datastore_add(chan, datastore);
01293    ast_channel_unlock(chan);
01294 
01295    res = 0;
01296 
01297 return_error:
01298    if (iface)
01299       ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01300 
01301    if (md_msg)
01302       ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy);
01303 
01304    if (smd && !datastore)
01305       smdi_msg_datastore_destroy(smd);
01306 
01307    if (parse)
01308       ast_autoservice_stop(chan);
01309 
01310    ast_module_user_remove(u);
01311 
01312    return res;
01313 }

static void* smdi_read ( void *  iface_p  )  [static]

Definition at line 636 of file res_smdi.c.

References ast_calloc, ast_copy_string(), ast_log(), ast_smdi_interface_destroy(), ast_smdi_md_message_destroy(), ast_smdi_md_message_push(), ast_smdi_mwi_message_destroy(), ast_smdi_mwi_message_push(), ast_tvnow(), ASTOBJ_INIT, ASTOBJ_UNREF, ast_smdi_md_message::calling_st, ast_smdi_mwi_message::cause, ast_smdi_interface::file, ast_smdi_mwi_message::fwd_st, ast_smdi_md_message::fwd_st, LOG_DEBUG, LOG_ERROR, ast_smdi_md_message::mesg_desk_num, ast_smdi_md_message::mesg_desk_term, ast_smdi_interface::msdstrip, ast_smdi_mwi_message::name, ast_smdi_interface::name, ast_smdi_md_message::name, ast_smdi_mwi_message::timestamp, ast_smdi_md_message::timestamp, and ast_smdi_md_message::type.

Referenced by smdi_load().

00637 {
00638    struct ast_smdi_interface *iface = iface_p;
00639    struct ast_smdi_md_message *md_msg;
00640    struct ast_smdi_mwi_message *mwi_msg;
00641    char c = '\0';
00642    char *cp = NULL;
00643    int i;
00644    int start = 0;
00645       
00646    /* read an smdi message */
00647    while ((c = fgetc(iface->file))) {
00648 
00649       /* check if this is the start of a message */
00650       if (!start) {
00651          if (c == 'M') {
00652             ast_log(LOG_DEBUG, "Read an 'M' to start an SMDI message\n");
00653             start = 1;
00654          }
00655          continue;
00656       }
00657       
00658       if (c == 'D') { /* MD message */
00659          start = 0;
00660 
00661          ast_log(LOG_DEBUG, "Read a 'D' ... it's an MD message.\n");
00662 
00663          if (!(md_msg = ast_calloc(1, sizeof(*md_msg)))) {
00664             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
00665             return NULL;
00666          }
00667          
00668          ASTOBJ_INIT(md_msg);
00669 
00670          /* read the message desk number */
00671          for (i = 0; i < sizeof(md_msg->mesg_desk_num) - 1; i++) {
00672             md_msg->mesg_desk_num[i] = fgetc(iface->file);
00673             ast_log(LOG_DEBUG, "Read a '%c'\n", md_msg->mesg_desk_num[i]);
00674          }
00675 
00676          md_msg->mesg_desk_num[sizeof(md_msg->mesg_desk_num) - 1] = '\0';
00677          
00678          ast_log(LOG_DEBUG, "The message desk number is '%s'\n", md_msg->mesg_desk_num);
00679 
00680          /* read the message desk terminal number */
00681          for (i = 0; i < sizeof(md_msg->mesg_desk_term) - 1; i++) {
00682             md_msg->mesg_desk_term[i] = fgetc(iface->file);
00683             ast_log(LOG_DEBUG, "Read a '%c'\n", md_msg->mesg_desk_term[i]);
00684          }
00685 
00686          md_msg->mesg_desk_term[sizeof(md_msg->mesg_desk_term) - 1] = '\0';
00687 
00688          ast_log(LOG_DEBUG, "The message desk terminal is '%s'\n", md_msg->mesg_desk_term);
00689 
00690          /* read the message type */
00691          md_msg->type = fgetc(iface->file);
00692        
00693          ast_log(LOG_DEBUG, "Message type is '%c'\n", md_msg->type);
00694 
00695          /* read the forwarding station number (may be blank) */
00696          cp = &md_msg->fwd_st[0];
00697          for (i = 0; i < sizeof(md_msg->fwd_st) - 1; i++) {
00698             if ((c = fgetc(iface->file)) == ' ') {
00699                *cp = '\0';
00700                ast_log(LOG_DEBUG, "Read a space, done looking for the forwarding station\n");
00701                break;
00702             }
00703 
00704             /* store c in md_msg->fwd_st */
00705             if (i >= iface->msdstrip) {
00706                ast_log(LOG_DEBUG, "Read a '%c' and stored it in the forwarding station buffer\n", c);
00707                *cp++ = c;
00708             } else {
00709                ast_log(LOG_DEBUG, "Read a '%c', but didn't store it in the fwd station buffer, because of the msdstrip setting (%d < %d)\n", c, i, iface->msdstrip);
00710             }
00711          }
00712 
00713          /* make sure the value is null terminated, even if this truncates it */
00714          md_msg->fwd_st[sizeof(md_msg->fwd_st) - 1] = '\0';
00715          cp = NULL;
00716 
00717          ast_log(LOG_DEBUG, "The forwarding station is '%s'\n", md_msg->fwd_st);
00718 
00719          /* Put the fwd_st in the name field so that we can use ASTOBJ_FIND to look
00720           * up a message on this field */
00721          ast_copy_string(md_msg->name, md_msg->fwd_st, sizeof(md_msg->name));
00722 
00723          /* read the calling station number (may be blank) */
00724          cp = &md_msg->calling_st[0];
00725          for (i = 0; i < sizeof(md_msg->calling_st) - 1; i++) {
00726             if (!isdigit((c = fgetc(iface->file)))) {
00727                *cp = '\0';
00728                ast_log(LOG_DEBUG, "Read a '%c', but didn't store it in the calling station buffer because it's not a digit\n", c);
00729                if (c == ' ') {
00730                   /* Don't break on a space.  We may read the space before the calling station
00731                    * here if the forwarding station buffer filled up. */
00732                   i--; /* We're still on the same character */
00733                   continue;
00734                }
00735                break;
00736             }
00737 
00738             /* store c in md_msg->calling_st */
00739             if (i >= iface->msdstrip) {
00740                ast_log(LOG_DEBUG, "Read a '%c' and stored it in the calling station buffer\n", c);
00741                *cp++ = c;
00742             } else {
00743                ast_log(LOG_DEBUG, "Read a '%c', but didn't store it in the calling station buffer, because of the msdstrip setting (%d < %d)\n", c, i, iface->msdstrip);
00744             }
00745          }
00746 
00747          /* make sure the value is null terminated, even if this truncates it */
00748          md_msg->calling_st[sizeof(md_msg->calling_st) - 1] = '\0';
00749          cp = NULL;
00750 
00751          ast_log(LOG_DEBUG, "The calling station is '%s'\n", md_msg->calling_st);
00752 
00753          /* add the message to the message queue */
00754          md_msg->timestamp = ast_tvnow();
00755          ast_smdi_md_message_push(iface, md_msg);
00756          ast_log(LOG_DEBUG, "Received SMDI MD message on %s\n", iface->name);
00757          
00758          ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy);
00759 
00760       } else if (c == 'W') { /* MWI message */
00761          start = 0;
00762 
00763          ast_log(LOG_DEBUG, "Read a 'W', it's an MWI message. (No more debug coming for MWI messages)\n");
00764 
00765          if (!(mwi_msg = ast_calloc(1, sizeof(*mwi_msg)))) {
00766             ASTOBJ_UNREF(iface,ast_smdi_interface_destroy);
00767             return NULL;
00768          }
00769 
00770          ASTOBJ_INIT(mwi_msg);
00771 
00772          /* discard the 'I' (from 'MWI') */
00773          fgetc(iface->file);
00774          
00775          /* read the forwarding station number (may be blank) */
00776          cp = &mwi_msg->fwd_st[0];
00777          for (i = 0; i < sizeof(mwi_msg->fwd_st) - 1; i++) {
00778             if ((c = fgetc(iface->file)) == ' ') {
00779                *cp = '\0';
00780                break;
00781             }
00782 
00783             /* store c in md_msg->fwd_st */
00784             if (i >= iface->msdstrip)
00785                *cp++ = c;
00786          }
00787 
00788          /* make sure the station number is null terminated, even if this will truncate it */
00789          mwi_msg->fwd_st[sizeof(mwi_msg->fwd_st) - 1] = '\0';
00790          cp = NULL;
00791          
00792          /* Put the fwd_st in the name field so that we can use ASTOBJ_FIND to look
00793           * up a message on this field */
00794          ast_copy_string(mwi_msg->name, mwi_msg->fwd_st, sizeof(mwi_msg->name));
00795 
00796          /* read the mwi failure cause */
00797          for (i = 0; i < sizeof(mwi_msg->cause) - 1; i++)
00798             mwi_msg->cause[i] = fgetc(iface->file);
00799 
00800          mwi_msg->cause[sizeof(mwi_msg->cause) - 1] = '\0';
00801 
00802          /* add the message to the message queue */
00803          mwi_msg->timestamp = ast_tvnow();
00804          ast_smdi_mwi_message_push(iface, mwi_msg);
00805          ast_log(LOG_DEBUG, "Received SMDI MWI message on %s\n", iface->name);
00806          
00807          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
00808       } else {
00809          ast_log(LOG_ERROR, "Unknown SMDI message type received on %s (M%c).\n", iface->name, c);
00810          start = 0;
00811       }
00812    }
00813 
00814    ast_log(LOG_ERROR, "Error reading from SMDI interface %s, stopping listener thread\n", iface->name);
00815    ASTOBJ_UNREF(iface,ast_smdi_interface_destroy);
00816    return NULL;
00817 }

static int smdi_toggle_mwi ( struct ast_smdi_interface iface,
const char *  mailbox,
int  on 
) [static]

Definition at line 287 of file res_smdi.c.

References ast_debug, ast_log(), ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, errno, ast_smdi_interface::file, LOG_ERROR, ast_smdi_interface::msdstrip, and ast_smdi_interface::name.

Referenced by ast_smdi_mwi_set(), and ast_smdi_mwi_unset().

00288 {
00289    FILE *file;
00290    int i;
00291    
00292    if (!(file = fopen(iface->name, "w"))) {
00293       ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s) for writing\n", iface->name, strerror(errno));
00294       return 1;
00295    }  
00296    
00297    ASTOBJ_WRLOCK(iface);
00298    
00299    fprintf(file, "%s:MWI ", on ? "OP" : "RMV");
00300    
00301    for (i = 0; i < iface->msdstrip; i++)
00302       fprintf(file, "0");
00303 
00304    fprintf(file, "%s!\x04", mailbox);
00305 
00306    fclose(file);
00307 
00308    ASTOBJ_UNLOCK(iface);
00309    ast_debug(1, "Sent MWI set message for %s on %s\n", mailbox, iface->name);
00310 
00311    return 0;
00312 }

static void* unlink_from_msg_q ( struct ast_smdi_interface iface,
enum smdi_message_type  type 
) [inline, static]

Definition at line 369 of file res_smdi.c.

References ASTOBJ_CONTAINER_UNLINK_START, ast_smdi_interface::md_q, ast_smdi_interface::mwi_q, SMDI_MD, and SMDI_MWI.

Referenced by purge_old_messages(), and smdi_msg_pop().

00370 {
00371    switch (type) {
00372    case SMDI_MWI:
00373       return ASTOBJ_CONTAINER_UNLINK_START(&iface->mwi_q);
00374    case SMDI_MD:
00375       return ASTOBJ_CONTAINER_UNLINK_START(&iface->md_q);
00376    }
00377    return NULL;
00378 }

static int unload_module ( void   )  [static]

static int unlock_msg_q ( struct ast_smdi_interface iface,
enum smdi_message_type  type 
) [inline, static]

Definition at line 357 of file res_smdi.c.

References ast_mutex_unlock(), ast_smdi_interface::md_q_lock, ast_smdi_interface::mwi_q_lock, SMDI_MD, and SMDI_MWI.

Referenced by purge_old_messages(), smdi_message_wait(), and smdi_msg_pop().

00358 {
00359    switch (type) {
00360    case SMDI_MWI:
00361       return ast_mutex_unlock(&iface->mwi_q_lock);
00362    case SMDI_MD:
00363       return ast_mutex_unlock(&iface->md_q_lock);
00364    }
00365 
00366    return -1;
00367 }

static void unref_msg ( void *  msg,
enum smdi_message_type  type 
) [inline, static]

Definition at line 395 of file res_smdi.c.

References ast_smdi_md_message_destroy(), ast_smdi_mwi_message_destroy(), ASTOBJ_UNREF, SMDI_MD, and SMDI_MWI.

Referenced by purge_old_messages().

00396 {
00397    struct ast_smdi_md_message *md_msg = msg;
00398    struct ast_smdi_mwi_message *mwi_msg = msg;
00399 
00400    switch (type) {
00401    case SMDI_MWI:
00402       ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
00403       break;
00404    case SMDI_MD:
00405       ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy);
00406       break;
00407    }
00408 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .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, .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1469 of file res_smdi.c.

Definition at line 1469 of file res_smdi.c.

Definition at line 213 of file res_smdi.c.

const char config_file[] = "smdi.conf" [static]

Definition at line 154 of file res_smdi.c.

Definition at line 215 of file res_smdi.c.

Definition at line 215 of file res_smdi.c.

struct timeval last_poll

The time that the last poll began

Definition at line 221 of file res_smdi.c.

Definition at line 212 of file res_smdi.c.

struct { ... } mailbox_mappings

A list of mailboxes that need to be monitored

struct { ... } mwi_monitor [static]

Data that gets used by the SMDI MWI monitoring thread.

Referenced by append_mailbox_mapping(), destroy_all_mailbox_mappings(), load_module(), mwi_monitor_handler(), smdi_load(), and unload_module().

unsigned int polling_interval

Polling Interval for checking mailbox status

Definition at line 217 of file res_smdi.c.

SMDI interface container.

Referenced by ast_smdi_interface_find(), load_module(), smdi_load(), and unload_module().

Initial value:

 {
   .type = "SMDIMSG",
   .destroy = smdi_msg_datastore_destroy,
}

Definition at line 1201 of file res_smdi.c.

Initial value:

 {
   .name = "SMDI_MSG",
   .read = smdi_msg_read,
}

Definition at line 1392 of file res_smdi.c.

int smdi_msg_id [static]

Definition at line 1206 of file res_smdi.c.

struct ast_app_option smdi_msg_ret_options[128] = { [ 't' ] = { .flag = OPT_SEARCH_TERMINAL }, [ 'n' ] = { .flag = OPT_SEARCH_NUMBER }, } [static]

Definition at line 1214 of file res_smdi.c.

Referenced by smdi_msg_retrieve_read().

Initial value:

 {
   .name = "SMDI_MSG_RETRIEVE",
   .read = smdi_msg_retrieve_read,
}

Definition at line 1387 of file res_smdi.c.

unsigned int stop

Set to 1 to tell the polling thread to stop

Definition at line 219 of file res_smdi.c.

pthread_t thread

The thread ID

Definition at line 211 of file res_smdi.c.


Generated on Wed Oct 28 13:33:34 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6