Wed Apr 6 11:30:09 2011

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"

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 int _unload_module (int fromload)
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)
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.
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.
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.
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.
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.
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 | 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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
static struct ast_module_infoast_module_info = &__mod_info
static const char config_file [] = "smdi.conf"
struct {
   ast_cond_t   cond
   timeval   last_poll
   ast_mutex_t   lock
   struct {
      mailbox_mapping *   first
      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 int smdi_loaded
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 207 of file res_smdi.c.

#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 1205 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 465 of file res_smdi.c.

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

enum smdi_message_type

Enumerator:
SMDI_MWI 
SMDI_MD 

Definition at line 341 of file res_smdi.c.

00341                        {
00342    SMDI_MWI,
00343    SMDI_MD,
00344 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1479 of file res_smdi.c.

static void __unreg_module ( void   )  [static]

Definition at line 1479 of file res_smdi.c.

static int _unload_module ( int  fromload  )  [static]

Definition at line 1424 of file res_smdi.c.

References ast_cond_signal, ast_custom_function_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, ast_smdi_interface_destroy(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, destroy_all_mailbox_mappings(), mwi_monitor, smdi_ifaces, smdi_msg_function, and smdi_msg_retrieve_function.

Referenced by load_module(), and unload_module().

01425 {
01426    if (!smdi_loaded) {
01427       return 0;
01428    }
01429 
01430    /* this destructor stops any running smdi_read threads */
01431    ASTOBJ_CONTAINER_DESTROYALL(&smdi_ifaces, ast_smdi_interface_destroy);
01432    ASTOBJ_CONTAINER_DESTROY(&smdi_ifaces);
01433 
01434    destroy_all_mailbox_mappings();
01435 
01436    ast_mutex_lock(&mwi_monitor.lock);
01437    mwi_monitor.stop = 1;
01438    ast_cond_signal(&mwi_monitor.cond);
01439    ast_mutex_unlock(&mwi_monitor.lock);
01440 
01441    if (mwi_monitor.thread != AST_PTHREADT_NULL) {
01442       pthread_join(mwi_monitor.thread, NULL);
01443    }
01444 
01445    if (!fromload) {
01446       ast_custom_function_unregister(&smdi_msg_retrieve_function);
01447       ast_custom_function_unregister(&smdi_msg_function);
01448    }
01449 
01450    smdi_loaded = 0;
01451    return 0;
01452 }

static struct ast_smdi_interface* alloc_smdi_interface ( void   )  [static]

Definition at line 921 of file res_smdi.c.

References ast_calloc, ast_cond_init, ast_mutex_init, ASTOBJ_CONTAINER_INIT, and ASTOBJ_INIT.

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

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

Definition at line 847 of file res_smdi.c.

References ast_calloc_with_stringfields, AST_LIST_INSERT_TAIL, ast_mutex_lock, ast_mutex_unlock, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ASTOBJ_REF, context, mailbox_mapping::entry, mailbox_mapping::iface, mailbox, mwi_monitor, mailbox_mapping::smdi, strsep(), and var.

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

static void ast_smdi_interface_destroy ( struct ast_smdi_interface iface  )  [static]

Definition at line 227 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, mailbox_mapping::iface, 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 _unload_module(), ast_smdi_interface_unref(), destroy_mailbox_mapping(), smdi_msg_datastore_destroy(), smdi_msg_retrieve_read(), and smdi_read().

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

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_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 623 of file res_smdi.c.

References ASTOBJ_CONTAINER_FIND, and smdi_ifaces.

Referenced by load_config(), and smdi_msg_retrieve_read().

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

void AST_OPTIONAL_API_NAME() ast_smdi_interface_unref ( struct ast_smdi_interface iface  ) 

Definition at line 255 of file res_smdi.c.

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

Referenced by destroy_dahdi_pvt().

void AST_OPTIONAL_API_NAME() ast_smdi_md_message_destroy ( struct ast_smdi_md_message msg  ) 

ast_smdi_md_message destructor.

Definition at line 820 of file res_smdi.c.

References ast_free.

Referenced by __analog_ss_thread(), ast_smdi_interface_destroy(), smdi_msg_datastore_destroy(), smdi_msg_retrieve_read(), and unref_msg().

00821 {
00822    ast_free(msg);
00823 }

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:
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 594 of file res_smdi.c.

References SMDI_MD, and smdi_msg_pop().

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

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

Definition at line 266 of file res_smdi.c.

References ast_cond_broadcast, ast_mutex_lock, ast_mutex_unlock, ASTOBJ_CONTAINER_LINK_END, mailbox_mapping::iface, ast_smdi_interface::md_q, ast_smdi_interface::md_q_cond, and ast_smdi_interface::md_q_lock.

Referenced by purge_old_messages().

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.
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 325 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.

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:
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 599 of file res_smdi.c.

References SMDI_MD, and smdi_message_wait().

Referenced by __analog_ss_thread(), and analog_ss_thread().

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

void AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_destroy ( struct ast_smdi_mwi_message msg  ) 

ast_smdi_mwi_message destructor.

Definition at line 825 of file res_smdi.c.

References ast_free.

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

00826 {
00827    ast_free(msg);
00828 }

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:
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 605 of file res_smdi.c.

References smdi_msg_pop(), and SMDI_MWI.

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

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

Definition at line 280 of file res_smdi.c.

References ast_cond_broadcast, ast_mutex_lock, ast_mutex_unlock, ASTOBJ_CONTAINER_LINK_END, mailbox_mapping::iface, ast_smdi_interface::mwi_q, ast_smdi_interface::mwi_q_cond, and ast_smdi_interface::mwi_q_lock.

Referenced by purge_old_messages().

00281 {
00282    ast_mutex_lock(&iface->mwi_q_lock);
00283    ASTOBJ_CONTAINER_LINK_END(&iface->mwi_q, mwi_msg);
00284    ast_cond_broadcast(&iface->mwi_q_cond);
00285    ast_mutex_unlock(&iface->mwi_q_lock);
00286 }

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.
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 333 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.

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

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:
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 610 of file res_smdi.c.

References smdi_message_wait(), and SMDI_MWI.

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

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 
)

Definition at line 616 of file res_smdi.c.

References smdi_message_wait(), and SMDI_MWI.

Referenced by run_externnotify().

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

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 315 of file res_smdi.c.

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

Referenced by poll_mailbox(), and run_externnotify().

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

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 320 of file res_smdi.c.

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

Referenced by poll_mailbox(), and run_externnotify().

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

static void destroy_all_mailbox_mappings ( void   )  [static]

Definition at line 837 of file res_smdi.c.

References AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, destroy_mailbox_mapping(), mailbox_mapping::entry, and mwi_monitor.

Referenced by _unload_module().

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

static void destroy_mailbox_mapping ( struct mailbox_mapping mm  )  [static]

Definition at line 830 of file res_smdi.c.

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

Referenced by destroy_all_mailbox_mappings().

00831 {
00832    ast_string_field_free_memory(mm);
00833    ASTOBJ_UNREF(mm->iface, ast_smdi_interface_destroy);
00834    free(mm);
00835 }

static int load_module ( void   )  [static]

Definition at line 1395 of file res_smdi.c.

References _unload_module(), 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(), smdi_msg_function, and smdi_msg_retrieve_function.

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

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

Definition at line 346 of file res_smdi.c.

References ast_mutex_lock, mailbox_mapping::iface, 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().

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

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

Definition at line 381 of file res_smdi.c.

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

Referenced by purge_old_messages().

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

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

Definition at line 894 of file res_smdi.c.

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

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

static void poll_mailbox ( struct mailbox_mapping mm  )  [static]

Note:
Called with the mwi_monitor.lock locked

Definition at line 875 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.

Referenced by mwi_monitor_handler().

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

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

Definition at line 411 of file res_smdi.c.

References ast_log(), ast_smdi_md_message_push(), ast_smdi_mwi_message_push(), ast_tvdiff_ms(), ast_tvnow(), mailbox_mapping::iface, lock_msg_q(), LOG_NOTICE, 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().

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

static int reload ( void   )  [static]

Definition at line 1459 of file res_smdi.c.

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

01460 {
01461    int res;
01462 
01463    res = smdi_load(1);
01464 
01465    if (res < 0) {
01466       return res;
01467    } else if (res == 1) {
01468       ast_log(LOG_WARNING, "No SMDI interfaces were specified to listen on, not starting SDMI listener.\n");
01469       return 0;
01470    } else
01471       return 0;
01472 }

static int smdi_load ( int  reload  )  [static]

Definition at line 951 of file res_smdi.c.

References ast_config_load, ast_log(), ast_variable_browse(), ASTOBJ_CONTAINER_MARKALL, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, ast_variable::lineno, LOG_NOTICE, ast_variable::name, ast_variable::next, smdi_ifaces, SMDI_MSG_EXPIRY_TIME, and ast_variable::value.

Referenced by load_module(), and reload().

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

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 538 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, 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().

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

static void smdi_msg_datastore_destroy ( void *  data  )  [static]

Definition at line 1184 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().

01185 {
01186    struct smdi_msg_datastore *smd = data;
01187 
01188    if (smd->iface)
01189       ASTOBJ_UNREF(smd->iface, ast_smdi_interface_destroy);
01190 
01191    if (smd->md_msg)
01192       ASTOBJ_UNREF(smd->md_msg, ast_smdi_md_message_destroy);
01193 
01194    free(smd);
01195 }

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 470 of file res_smdi.c.

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

Referenced by smdi_message_wait().

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

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

Definition at line 452 of file res_smdi.c.

References mailbox_mapping::iface, lock_msg_q(), purge_old_messages(), unlink_from_msg_q(), and unlock_msg_q().

Referenced by ast_smdi_md_message_pop(), and ast_smdi_mwi_message_pop().

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

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

Definition at line 1311 of file res_smdi.c.

References args, 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(), smdi_msg_datastore_info, and ast_smdi_md_message::type.

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

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

Definition at line 1212 of file res_smdi.c.

References args, 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, LOG_ERROR, LOG_WARNING, parse(), SMDI_MD, smdi_message_wait(), smdi_msg_datastore_destroy(), smdi_msg_datastore_info, smdi_msg_ret_options, and SMDI_RETRIEVE_TIMEOUT_DEFAULT.

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

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

Definition at line 637 of file res_smdi.c.

References ast_calloc, ast_copy_string(), ast_log(), ast_smdi_interface_destroy(), ASTOBJ_INIT, ASTOBJ_UNREF, ast_smdi_md_message::calling_st, ast_smdi_interface::file, ast_smdi_md_message::fwd_st, LOG_DEBUG, ast_smdi_interface::msdstrip, and ast_smdi_md_message::name.

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

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

Definition at line 288 of file res_smdi.c.

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

Referenced by ast_smdi_mwi_set(), and ast_smdi_mwi_unset().

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

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

Definition at line 370 of file res_smdi.c.

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

Referenced by purge_old_messages(), and smdi_msg_pop().

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

static int unload_module ( void   )  [static]

Definition at line 1454 of file res_smdi.c.

References _unload_module().

01455 {
01456    return _unload_module(0);
01457 }

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

Definition at line 358 of file res_smdi.c.

References ast_mutex_unlock, mailbox_mapping::iface, 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().

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

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

Definition at line 396 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().

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


Variable Documentation

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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static]

Definition at line 1479 of file res_smdi.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1479 of file res_smdi.c.

ast_cond_t cond

Definition at line 214 of file res_smdi.c.

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

Definition at line 154 of file res_smdi.c.

struct mailbox_mapping* first

Definition at line 216 of file res_smdi.c.

struct mailbox_mapping* last

Definition at line 216 of file res_smdi.c.

struct timeval last_poll

The time that the last poll began

Definition at line 222 of file res_smdi.c.

ast_mutex_t lock

Definition at line 213 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 _unload_module(), append_mailbox_mapping(), destroy_all_mailbox_mappings(), load_module(), and mwi_monitor_handler().

unsigned int polling_interval

Polling Interval for checking mailbox status

Definition at line 218 of file res_smdi.c.

struct ast_smdi_interface_container smdi_ifaces [static]

SMDI interface container.

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

int smdi_loaded [static]

Definition at line 155 of file res_smdi.c.

struct ast_datastore_info smdi_msg_datastore_info [static]

Initial value:

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

Definition at line 1197 of file res_smdi.c.

Referenced by smdi_msg_read(), and smdi_msg_retrieve_read().

struct ast_custom_function smdi_msg_function [static]

Initial value:

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

Definition at line 1388 of file res_smdi.c.

Referenced by _unload_module(), and load_module().

int smdi_msg_id [static]

Definition at line 1202 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 1210 of file res_smdi.c.

Referenced by smdi_msg_retrieve_read().

struct ast_custom_function smdi_msg_retrieve_function [static]

Initial value:

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

Definition at line 1383 of file res_smdi.c.

Referenced by _unload_module(), and load_module().

unsigned int stop

Set to 1 to tell the polling thread to stop

Definition at line 220 of file res_smdi.c.

pthread_t thread

The thread ID

Definition at line 212 of file res_smdi.c.


Generated on Wed Apr 6 11:30:09 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7