Wed Aug 18 22:34:32 2010

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 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)
ast_smdi_interfaceast_smdi_interface_find (const char *iface_name)
 Find an SMDI interface with the specified name.
void ast_smdi_interface_unref (struct ast_smdi_interface *iface)
void ast_smdi_md_message_destroy (struct ast_smdi_md_message *msg)
 ast_smdi_md_message destructor.
ast_smdi_md_messageast_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_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_messageast_smdi_md_message_wait (struct ast_smdi_interface *iface, int timeout)
 Get the next SMDI message from the queue.
void ast_smdi_mwi_message_destroy (struct ast_smdi_mwi_message *msg)
 ast_smdi_mwi_message destructor.
ast_smdi_mwi_messageast_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_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_messageast_smdi_mwi_message_wait (struct ast_smdi_interface *iface, int timeout)
 Get the next SMDI message from the queue.
ast_smdi_mwi_messageast_smdi_mwi_message_wait_station (struct ast_smdi_interface *iface, int timeout, const char *station)
int ast_smdi_mwi_set (struct ast_smdi_interface *iface, const char *mailbox)
 Set the MWI indicator for a mailbox.
int 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .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
   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.
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 DEFAULT_POLLING_INTERVAL   10

10 seconds

Definition at line 111 of file res_smdi.c.

#define SMDI_MSG_EXPIRY_TIME   30000

Definition at line 57 of file res_smdi.c.

Referenced by smdi_load().

#define SMDI_RETRIEVE_TIMEOUT_DEFAULT   3000

In milliseconds

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

00369      {
00370    OPT_SEARCH_TERMINAL = (1 << 0),
00371    OPT_SEARCH_NUMBER   = (1 << 1),
00372 };

enum smdi_message_type

Enumerator:
SMDI_MWI 
SMDI_MD 

Definition at line 245 of file res_smdi.c.

00245                        {
00246    SMDI_MWI,
00247    SMDI_MD,
00248 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1409 of file res_smdi.c.

static void __unreg_module ( void   )  [static]

Definition at line 1409 of file res_smdi.c.

static struct ast_smdi_interface* alloc_smdi_interface ( void   )  [static]

Definition at line 830 of file res_smdi.c.

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

00831 {
00832    struct ast_smdi_interface *iface;
00833 
00834    if (!(iface = ast_calloc(1, sizeof(*iface))))
00835       return NULL;
00836 
00837    ASTOBJ_INIT(iface);
00838    ASTOBJ_CONTAINER_INIT(&iface->md_q);
00839    ASTOBJ_CONTAINER_INIT(&iface->mwi_q);
00840 
00841    ast_mutex_init(&iface->md_q_lock);
00842    ast_cond_init(&iface->md_q_cond, NULL);
00843 
00844    ast_mutex_init(&iface->mwi_q_lock);
00845    ast_cond_init(&iface->mwi_q_cond, NULL);
00846 
00847    return iface;
00848 }

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

Definition at line 751 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, mailbox_mapping::entry, free, mailbox_mapping::iface, mailbox, mwi_monitor, mailbox_mapping::smdi, strsep(), and var.

00752 {
00753    struct mailbox_mapping *mm;
00754    char *mailbox, *context;
00755 
00756    if (!(mm = ast_calloc(1, sizeof(*mm))))
00757       return;
00758    
00759    if (ast_string_field_init(mm, 32)) {
00760       free(mm);
00761       return;
00762    }
00763 
00764    ast_string_field_set(mm, smdi, var->name);
00765 
00766    context = ast_strdupa(var->value);
00767    mailbox = strsep(&context, "@");
00768    if (ast_strlen_zero(context))
00769       context = "default";
00770 
00771    ast_string_field_set(mm, mailbox, mailbox);
00772    ast_string_field_set(mm, context, context);
00773 
00774    mm->iface = ASTOBJ_REF(iface);
00775 
00776    ast_mutex_lock(&mwi_monitor.lock);
00777    AST_LIST_INSERT_TAIL(&mwi_monitor.mailbox_mappings, mm, entry);
00778    ast_mutex_unlock(&mwi_monitor.lock);
00779 }

static void ast_smdi_interface_destroy ( struct ast_smdi_interface iface  )  [static]

Definition at line 131 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 ast_smdi_interface_unref(), destroy_mailbox_mapping(), smdi_msg_datastore_destroy(), smdi_msg_retrieve_read(), smdi_read(), and unload_module().

00132 {
00133    if (iface->thread != AST_PTHREADT_NULL && iface->thread != AST_PTHREADT_STOP) {
00134       pthread_cancel(iface->thread);
00135       pthread_join(iface->thread, NULL);
00136    }
00137    
00138    iface->thread = AST_PTHREADT_STOP;
00139    
00140    if (iface->file) 
00141       fclose(iface->file);
00142    
00143    ASTOBJ_CONTAINER_DESTROYALL(&iface->md_q, ast_smdi_md_message_destroy);
00144    ASTOBJ_CONTAINER_DESTROYALL(&iface->mwi_q, ast_smdi_mwi_message_destroy);
00145    ASTOBJ_CONTAINER_DESTROY(&iface->md_q);
00146    ASTOBJ_CONTAINER_DESTROY(&iface->mwi_q);
00147 
00148    ast_mutex_destroy(&iface->md_q_lock);
00149    ast_cond_destroy(&iface->md_q_cond);
00150 
00151    ast_mutex_destroy(&iface->mwi_q_lock);
00152    ast_cond_destroy(&iface->mwi_q_cond);
00153 
00154    free(iface);
00155 
00156    ast_module_unref(ast_module_info->self);
00157 }

struct ast_smdi_interface* 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 527 of file res_smdi.c.

References ASTOBJ_CONTAINER_FIND, and smdi_ifaces.

Referenced by load_config(), and smdi_msg_retrieve_read().

00528 {
00529    return (ASTOBJ_CONTAINER_FIND(&smdi_ifaces, iface_name));
00530 }

void ast_smdi_interface_unref ( struct ast_smdi_interface iface  ) 

Definition at line 159 of file res_smdi.c.

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

Referenced by destroy_dahdi_pvt().

void ast_smdi_md_message_destroy ( struct ast_smdi_md_message msg  ) 

ast_smdi_md_message destructor.

Definition at line 724 of file res_smdi.c.

References ast_free, and msg.

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

00725 {
00726    ast_free(msg);
00727 }

struct ast_smdi_md_message* 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 498 of file res_smdi.c.

References SMDI_MD, and smdi_msg_pop().

00499 {
00500    return smdi_msg_pop(iface, SMDI_MD);
00501 }

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

Definition at line 170 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_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 229 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_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 503 of file res_smdi.c.

References SMDI_MD, and smdi_message_wait().

Referenced by ss_thread().

00504 {
00505    struct ast_flags options = { 0 };
00506    return smdi_message_wait(iface, timeout, SMDI_MD, NULL, options);
00507 }

void ast_smdi_mwi_message_destroy ( struct ast_smdi_mwi_message msg  ) 

ast_smdi_mwi_message destructor.

Definition at line 729 of file res_smdi.c.

References ast_free, and msg.

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

00730 {
00731    ast_free(msg);
00732 }

struct ast_smdi_mwi_message* 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 509 of file res_smdi.c.

References smdi_msg_pop(), and SMDI_MWI.

00510 {
00511    return smdi_msg_pop(iface, SMDI_MWI);
00512 }

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

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

00185 {
00186    ast_mutex_lock(&iface->mwi_q_lock);
00187    ASTOBJ_CONTAINER_LINK_END(&iface->mwi_q, mwi_msg);
00188    ast_cond_broadcast(&iface->mwi_q_cond);
00189    ast_mutex_unlock(&iface->mwi_q_lock);
00190 }

void 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 237 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.

00238 {
00239    ast_mutex_lock(&iface->mwi_q_lock);
00240    ASTOBJ_CONTAINER_LINK_START(&iface->mwi_q, mwi_msg);
00241    ast_cond_broadcast(&iface->mwi_q_cond);
00242    ast_mutex_unlock(&iface->mwi_q_lock);
00243 }

struct ast_smdi_mwi_message* 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 514 of file res_smdi.c.

References smdi_message_wait(), and SMDI_MWI.

00515 {
00516    struct ast_flags options = { 0 };
00517    return smdi_message_wait(iface, timeout, SMDI_MWI, NULL, options);
00518 }

struct ast_smdi_mwi_message* ast_smdi_mwi_message_wait_station ( struct ast_smdi_interface iface,
int  timeout,
const char *  station 
)

Definition at line 520 of file res_smdi.c.

References smdi_message_wait(), and SMDI_MWI.

Referenced by run_externnotify().

00522 {
00523    struct ast_flags options = { 0 };
00524    return smdi_message_wait(iface, timeout, SMDI_MWI, station, options);
00525 }

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

References mailbox_mapping::iface, and smdi_toggle_mwi().

Referenced by poll_mailbox(), and run_externnotify().

00220 {
00221    return smdi_toggle_mwi(iface, mailbox, 1);
00222 }

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

References mailbox_mapping::iface, and smdi_toggle_mwi().

Referenced by poll_mailbox(), and run_externnotify().

00225 {
00226    return smdi_toggle_mwi(iface, mailbox, 0);
00227 }

static void destroy_all_mailbox_mappings ( void   )  [static]

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

00742 {
00743    struct mailbox_mapping *mm;
00744 
00745    ast_mutex_lock(&mwi_monitor.lock);
00746    while ((mm = AST_LIST_REMOVE_HEAD(&mwi_monitor.mailbox_mappings, entry)))
00747       destroy_mailbox_mapping(mm);
00748    ast_mutex_unlock(&mwi_monitor.lock);
00749 }

static void destroy_mailbox_mapping ( struct mailbox_mapping mm  )  [static]

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

00735 {
00736    ast_string_field_free_memory(mm);
00737    ASTOBJ_UNREF(mm->iface, ast_smdi_interface_destroy);
00738    free(mm);
00739 }

static int load_module ( void   )  [static]

Definition at line 1339 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(), smdi_msg_function, smdi_msg_retrieve_function, and unload_module().

01340 {
01341    int res;
01342    
01343    /* initialize our containers */
01344    memset(&smdi_ifaces, 0, sizeof(smdi_ifaces));
01345    ASTOBJ_CONTAINER_INIT(&smdi_ifaces);
01346    
01347    ast_mutex_init(&mwi_monitor.lock);
01348    ast_cond_init(&mwi_monitor.cond, NULL);
01349 
01350    ast_custom_function_register(&smdi_msg_retrieve_function);
01351    ast_custom_function_register(&smdi_msg_function);
01352 
01353    /* load the config and start the listener threads*/
01354    res = smdi_load(0);
01355    if (res < 0) {
01356       unload_module();
01357       return res;
01358    } else if (res == 1) {
01359       unload_module();
01360       ast_log(LOG_NOTICE, "No SMDI interfaces are available to listen on, not starting SMDI listener.\n");
01361       return AST_MODULE_LOAD_DECLINE;
01362    }
01363    
01364    return AST_MODULE_LOAD_SUCCESS;
01365 }

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

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

00251 {
00252    switch (type) {
00253    case SMDI_MWI:
00254       return ast_mutex_lock(&iface->mwi_q_lock);
00255    case SMDI_MD:  
00256       return ast_mutex_lock(&iface->md_q_lock);
00257    }
00258    
00259    return -1;
00260 }

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

Definition at line 285 of file res_smdi.c.

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

Referenced by purge_old_messages().

00286 {
00287    struct ast_smdi_md_message *md_msg = msg;
00288    struct ast_smdi_mwi_message *mwi_msg = msg;
00289 
00290    switch (type) {
00291    case SMDI_MWI:
00292       return mwi_msg->timestamp;
00293    case SMDI_MD:
00294       return md_msg->timestamp;
00295    }
00296 
00297    return ast_tv(0, 0);
00298 }

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

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

00804 {
00805    while (!mwi_monitor.stop) {
00806       struct timespec ts = { 0, };
00807       struct timeval polltime;
00808       struct mailbox_mapping *mm;
00809 
00810       ast_mutex_lock(&mwi_monitor.lock);
00811 
00812       mwi_monitor.last_poll = ast_tvnow();
00813 
00814       AST_LIST_TRAVERSE(&mwi_monitor.mailbox_mappings, mm, entry)
00815          poll_mailbox(mm);
00816 
00817       /* Sleep up to the configured polling interval.  Allow unload_module()
00818        * to signal us to wake up and exit. */
00819       polltime = ast_tvadd(mwi_monitor.last_poll, ast_tv(mwi_monitor.polling_interval, 0));
00820       ts.tv_sec = polltime.tv_sec;
00821       ts.tv_nsec = polltime.tv_usec * 1000;
00822       ast_cond_timedwait(&mwi_monitor.cond, &mwi_monitor.lock, &ts);
00823 
00824       ast_mutex_unlock(&mwi_monitor.lock);
00825    }
00826 
00827    return NULL;
00828 }

static void poll_mailbox ( struct mailbox_mapping mm  )  [static]

Note:
Called with the mwi_monitor.lock locked

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

00785 {
00786    char buf[1024];
00787    unsigned int state;
00788 
00789    snprintf(buf, sizeof(buf), "%s@%s", mm->mailbox, mm->context);
00790 
00791    state = !!ast_app_has_voicemail(mm->mailbox, NULL);
00792 
00793    if (state != mm->cur_state) {
00794       if (state)
00795          ast_smdi_mwi_set(mm->iface, mm->smdi);
00796       else
00797          ast_smdi_mwi_unset(mm->iface, mm->smdi);
00798 
00799       mm->cur_state = state;
00800    }
00801 }

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

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

00316 {
00317    struct timeval now = ast_tvnow();
00318    long elapsed = 0;
00319    void *msg;
00320    
00321    lock_msg_q(iface, type);
00322    msg = unlink_from_msg_q(iface, type);
00323    unlock_msg_q(iface, type);
00324 
00325    /* purge old messages */
00326    while (msg) {
00327       elapsed = ast_tvdiff_ms(now, msg_timestamp(msg, type));
00328 
00329       if (elapsed > iface->msg_expiry) {
00330          /* found an expired message */
00331          unref_msg(msg, type);
00332          ast_log(LOG_NOTICE, "Purged expired message from %s SMDI %s message queue.  "
00333             "Message was %ld milliseconds too old.\n",
00334             iface->name, (type == SMDI_MD) ? "MD" : "MWI", 
00335             elapsed - iface->msg_expiry);
00336 
00337          lock_msg_q(iface, type);
00338          msg = unlink_from_msg_q(iface, type);
00339          unlock_msg_q(iface, type);
00340       } else {
00341          /* good message, put it back and return */
00342          switch (type) {
00343          case SMDI_MD:
00344             ast_smdi_md_message_push(iface, msg);
00345             break;
00346          case SMDI_MWI:
00347             ast_smdi_mwi_message_push(iface, msg);
00348             break;
00349          }
00350          unref_msg(msg, type);
00351          break;
00352       }
00353    }
00354 }

static int reload ( void   )  [static]

Definition at line 1390 of file res_smdi.c.

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

01391 {
01392    int res;
01393 
01394    res = smdi_load(1);
01395 
01396    if (res < 0) {
01397       return res;
01398    } else if (res == 1) {
01399       ast_log(LOG_WARNING, "No SMDI interfaces were specified to listen on, not starting SDMI listener.\n");
01400       return 0;
01401    } else
01402       return 0;
01403 }

static int smdi_load ( int  reload  )  [static]

Definition at line 860 of file res_smdi.c.

References ast_config_load, ast_log(), ast_variable_browse(), ASTOBJ_CONTAINER_MARKALL, CONFIG_FLAG_FILEUNCHANGED, config_flags, 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().

00861 {
00862    struct ast_config *conf;
00863    struct ast_variable *v;
00864    struct ast_smdi_interface *iface = NULL;
00865    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00866    int res = 0;
00867 
00868    /* Config options */
00869    speed_t baud_rate = B9600;     /* 9600 baud rate */
00870    tcflag_t paritybit = PARENB;   /* even parity checking */
00871    tcflag_t charsize = CS7;       /* seven bit characters */
00872    int stopbits = 0;              /* One stop bit */
00873    
00874    int msdstrip = 0;              /* strip zero digits */
00875    long msg_expiry = SMDI_MSG_EXPIRY_TIME;
00876 
00877    if (!(conf = ast_config_load(config_file, config_flags))) {
00878       if (reload)
00879          ast_log(LOG_NOTICE, "Unable to reload config %s: SMDI untouched\n", config_file);
00880       else
00881          ast_log(LOG_NOTICE, "Unable to load config %s: SMDI disabled\n", config_file);
00882       return 1;
00883    } else if (conf == CONFIG_STATUS_FILEUNCHANGED)
00884       return 0;
00885 
00886    /* Mark all interfaces that we are listening on.  We will unmark them
00887     * as we find them in the config file, this way we know any interfaces
00888     * still marked after we have finished parsing the config file should
00889     * be stopped.
00890     */
00891    if (reload)
00892       ASTOBJ_CONTAINER_MARKALL(&smdi_ifaces);
00893 
00894    for (v = ast_variable_browse(conf, "interfaces"); v; v = v->next) {
00895       if (!strcasecmp(v->name, "baudrate")) {
00896          if (!strcasecmp(v->value, "9600"))
00897             baud_rate = B9600;
00898          else if (!strcasecmp(v->value, "4800"))
00899             baud_rate = B4800;
00900          else if (!strcasecmp(v->value, "2400"))
00901             baud_rate = B2400;
00902          else if (!strcasecmp(v->value, "1200"))
00903             baud_rate = B1200;
00904          else {
00905             ast_log(LOG_NOTICE, "Invalid baud rate '%s' specified in %s (line %d), using default\n", v->value, config_file, v->lineno);
00906             baud_rate = B9600;
00907          }
00908       } else if (!strcasecmp(v->name, "msdstrip")) {
00909          if (!sscanf(v->value, "%30d", &msdstrip)) {
00910             ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno);
00911             msdstrip = 0;
00912          } else if (0 > msdstrip || msdstrip > 9) {
00913             ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno);
00914             msdstrip = 0;
00915          }
00916       } else if (!strcasecmp(v->name, "msgexpirytime")) {
00917          if (!sscanf(v->value, "%30ld", &msg_expiry)) {
00918             ast_log(LOG_NOTICE, "Invalid msgexpirytime value in %s (line %d), using default\n", config_file, v->lineno);
00919             msg_expiry = SMDI_MSG_EXPIRY_TIME;
00920          }
00921       } else if (!strcasecmp(v->name, "paritybit")) {
00922          if (!strcasecmp(v->value, "even"))
00923             paritybit = PARENB;
00924          else if (!strcasecmp(v->value, "odd"))
00925             paritybit = PARENB | PARODD;
00926          else if (!strcasecmp(v->value, "none"))
00927             paritybit = ~PARENB;
00928          else {
00929             ast_log(LOG_NOTICE, "Invalid parity bit setting in %s (line %d), using default\n", config_file, v->lineno);
00930             paritybit = PARENB;
00931          }
00932       } else if (!strcasecmp(v->name, "charsize")) {
00933          if (!strcasecmp(v->value, "7"))
00934             charsize = CS7;
00935          else if (!strcasecmp(v->value, "8"))
00936             charsize = CS8;
00937          else {
00938             ast_log(LOG_NOTICE, "Invalid character size setting in %s (line %d), using default\n", config_file, v->lineno);
00939             charsize = CS7;
00940          }
00941       } else if (!strcasecmp(v->name, "twostopbits")) {
00942          stopbits = ast_true(v->name);
00943       } else if (!strcasecmp(v->name, "smdiport")) {
00944          if (reload) {
00945             /* we are reloading, check if we are already
00946              * monitoring this interface, if we are we do
00947              * not want to start it again.  This also has
00948              * the side effect of not updating different
00949              * setting for the serial port, but it should
00950              * be trivial to rewrite this section so that
00951              * options on the port are changed without
00952              * restarting the interface.  Or the interface
00953              * could be restarted with out emptying the
00954              * queue. */
00955             if ((iface = ASTOBJ_CONTAINER_FIND(&smdi_ifaces, v->value))) {
00956                ast_log(LOG_NOTICE, "SMDI interface %s already running, not restarting\n", iface->name);
00957                ASTOBJ_UNMARK(iface);
00958                ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
00959                continue;
00960             }
00961          }
00962          
00963          if (!(iface = alloc_smdi_interface()))
00964             continue;
00965 
00966          ast_copy_string(iface->name, v->value, sizeof(iface->name));
00967 
00968          iface->thread = AST_PTHREADT_NULL;
00969 
00970          if (!(iface->file = fopen(iface->name, "r"))) {
00971             ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s)\n", iface->name, strerror(errno));
00972             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
00973             continue;
00974          }
00975 
00976          iface->fd = fileno(iface->file);
00977 
00978          /* Set the proper attributes for our serial port. */
00979 
00980          /* get the current attributes from the port */
00981          if (tcgetattr(iface->fd, &iface->mode)) {
00982             ast_log(LOG_ERROR, "Error getting atributes of %s (%s)\n", iface->name, strerror(errno));
00983             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
00984             continue;
00985          }
00986 
00987          /* set the desired speed */
00988          if (cfsetispeed(&iface->mode, baud_rate) || cfsetospeed(&iface->mode, baud_rate)) {
00989             ast_log(LOG_ERROR, "Error setting baud rate on %s (%s)\n", iface->name, strerror(errno));
00990             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
00991             continue;
00992          }
00993          
00994          /* set the stop bits */
00995          if (stopbits)
00996             iface->mode.c_cflag = iface->mode.c_cflag | CSTOPB;   /* set two stop bits */
00997          else
00998             iface->mode.c_cflag = iface->mode.c_cflag & ~CSTOPB;  /* set one stop bit */
00999          
01000          /* set the parity */
01001          iface->mode.c_cflag = (iface->mode.c_cflag & ~PARENB & ~PARODD) | paritybit;
01002          
01003          /* set the character size */
01004          iface->mode.c_cflag = (iface->mode.c_cflag & ~CSIZE) | charsize;
01005          
01006          /* commit the desired attributes */
01007          if (tcsetattr(iface->fd, TCSAFLUSH, &iface->mode)) {
01008             ast_log(LOG_ERROR, "Error setting attributes on %s (%s)\n", iface->name, strerror(errno));
01009             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01010             continue;
01011          }
01012 
01013          /* set the msdstrip */
01014          iface->msdstrip = msdstrip;
01015 
01016          /* set the message expiry time */
01017          iface->msg_expiry = msg_expiry;
01018 
01019          /* start the listener thread */
01020          ast_verb(3, "Starting SMDI monitor thread for %s\n", iface->name);
01021          if (ast_pthread_create_background(&iface->thread, NULL, smdi_read, iface)) {
01022             ast_log(LOG_ERROR, "Error starting SMDI monitor thread for %s\n", iface->name);
01023             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01024             continue;
01025          }
01026 
01027          ASTOBJ_CONTAINER_LINK(&smdi_ifaces, iface);
01028          ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01029          ast_module_ref(ast_module_info->self);
01030       } else {
01031          ast_log(LOG_NOTICE, "Ignoring unknown option %s in %s\n", v->name, config_file);
01032       }
01033    }
01034 
01035    destroy_all_mailbox_mappings();
01036    mwi_monitor.polling_interval = DEFAULT_POLLING_INTERVAL;
01037    
01038    iface = NULL;
01039 
01040    for (v = ast_variable_browse(conf, "mailboxes"); v; v = v->next) {
01041       if (!strcasecmp(v->name, "smdiport")) {
01042          if (iface)
01043             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01044 
01045          if (!(iface = ASTOBJ_CONTAINER_FIND(&smdi_ifaces, v->value))) {
01046             ast_log(LOG_NOTICE, "SMDI interface %s not found\n", iface->name);
01047             continue;
01048          }
01049       } else if (!strcasecmp(v->name, "pollinginterval")) {
01050          if (sscanf(v->value, "%30u", &mwi_monitor.polling_interval) != 1) {
01051             ast_log(LOG_ERROR, "Invalid value for pollinginterval: %s\n", v->value);
01052             mwi_monitor.polling_interval = DEFAULT_POLLING_INTERVAL;
01053          }
01054       } else {
01055          if (!iface) {
01056             ast_log(LOG_ERROR, "Mailbox mapping ignored, no valid SMDI interface specified in mailboxes section\n");
01057             continue;
01058          }
01059          append_mailbox_mapping(v, iface);
01060       }
01061    }
01062 
01063    if (iface)
01064       ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01065 
01066    ast_config_destroy(conf);
01067    
01068    if (!AST_LIST_EMPTY(&mwi_monitor.mailbox_mappings) && mwi_monitor.thread == AST_PTHREADT_NULL
01069       && ast_pthread_create_background(&mwi_monitor.thread, NULL, mwi_monitor_handler, NULL)) {
01070       ast_log(LOG_ERROR, "Failed to start MWI monitoring thread.  This module will not operate.\n");
01071       return AST_MODULE_LOAD_FAILURE;
01072    }
01073 
01074    /* Prune any interfaces we should no longer monitor. */
01075    if (reload)
01076       ASTOBJ_CONTAINER_PRUNE_MARKED(&smdi_ifaces, ast_smdi_interface_destroy);
01077    
01078    ASTOBJ_CONTAINER_RDLOCK(&smdi_ifaces);
01079    /* TODO: this is bad, we need an ASTOBJ method for this! */
01080    if (!smdi_ifaces.head)
01081       res = 1;
01082    ASTOBJ_CONTAINER_UNLOCK(&smdi_ifaces);
01083    
01084    return res;
01085 }

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 442 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().

00444 {
00445    struct timeval start;
00446    long diff = 0;
00447    void *msg;
00448    ast_cond_t *cond = NULL;
00449    ast_mutex_t *lock = NULL;
00450 
00451    switch (type) {
00452    case SMDI_MWI:
00453       cond = &iface->mwi_q_cond;
00454       lock = &iface->mwi_q_lock;
00455       break;
00456    case SMDI_MD:
00457       cond = &iface->md_q_cond;
00458       lock = &iface->md_q_lock;
00459       break;
00460    }
00461 
00462    start = ast_tvnow();
00463 
00464    while (diff < timeout) {
00465       struct timespec ts = { 0, };
00466       struct timeval wait;
00467 
00468       lock_msg_q(iface, type);
00469 
00470       if ((msg = smdi_msg_find(iface, type, search_key, options))) {
00471          unlock_msg_q(iface, type);
00472          return msg;
00473       }
00474 
00475       wait = ast_tvadd(start, ast_tv(0, timeout));
00476       ts.tv_sec = wait.tv_sec;
00477       ts.tv_nsec = wait.tv_usec * 1000;
00478 
00479       /* If there were no messages in the queue, then go to sleep until one
00480        * arrives. */
00481 
00482       ast_cond_timedwait(cond, lock, &ts);
00483 
00484       if ((msg = smdi_msg_find(iface, type, search_key, options))) {
00485          unlock_msg_q(iface, type);
00486          return msg;
00487       }
00488 
00489       unlock_msg_q(iface, type);
00490 
00491       /* check timeout */
00492       diff = ast_tvdiff_ms(ast_tvnow(), start);
00493    }
00494 
00495    return NULL;
00496 }

static void smdi_msg_datastore_destroy ( void *  data  )  [static]

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

01094 {
01095    struct smdi_msg_datastore *smd = data;
01096 
01097    if (smd->iface)
01098       ASTOBJ_UNREF(smd->iface, ast_smdi_interface_destroy);
01099 
01100    if (smd->md_msg)
01101       ASTOBJ_UNREF(smd->md_msg, ast_smdi_md_message_destroy);
01102 
01103    free(smd);
01104 }

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 374 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, msg, OPT_SEARCH_TERMINAL, purge_old_messages(), and SMDI_MD.

Referenced by smdi_message_wait().

00376 {
00377    void *msg = NULL;
00378 
00379    purge_old_messages(iface, type);
00380 
00381    switch (type) {
00382    case SMDI_MD:
00383       if (ast_strlen_zero(search_key)) {
00384          struct ast_smdi_md_message *md_msg = NULL;
00385 
00386          /* No search key provided (the code from chan_dahdi does this).
00387           * Just pop the top message off of the queue. */
00388 
00389          ASTOBJ_CONTAINER_TRAVERSE(&iface->md_q, !md_msg, do {
00390             md_msg = ASTOBJ_REF(iterator);
00391          } while (0); );
00392 
00393          msg = md_msg;
00394       } else if (ast_test_flag(&options, OPT_SEARCH_TERMINAL)) {
00395          struct ast_smdi_md_message *md_msg = NULL;
00396 
00397          /* Searching by the message desk terminal */
00398 
00399          ASTOBJ_CONTAINER_TRAVERSE(&iface->md_q, !md_msg, do {
00400             if (!strcasecmp(iterator->mesg_desk_term, search_key))
00401                md_msg = ASTOBJ_REF(iterator);
00402          } while (0); );
00403 
00404          msg = md_msg;
00405       } else if (ast_test_flag(&options, OPT_SEARCH_NUMBER)) {
00406          struct ast_smdi_md_message *md_msg = NULL;
00407 
00408          /* Searching by the message desk number */
00409 
00410          ASTOBJ_CONTAINER_TRAVERSE(&iface->md_q, !md_msg, do {
00411             if (!strcasecmp(iterator->mesg_desk_num, search_key))
00412                md_msg = ASTOBJ_REF(iterator);
00413          } while (0); );
00414 
00415          msg = md_msg;
00416       } else {
00417          /* Searching by the forwarding station */
00418          msg = ASTOBJ_CONTAINER_FIND(&iface->md_q, search_key);
00419       }
00420       break;
00421    case SMDI_MWI:
00422       if (ast_strlen_zero(search_key)) {
00423          struct ast_smdi_mwi_message *mwi_msg = NULL;
00424 
00425          /* No search key provided (the code from chan_dahdi does this).
00426           * Just pop the top message off of the queue. */
00427 
00428          ASTOBJ_CONTAINER_TRAVERSE(&iface->mwi_q, !mwi_msg, do {
00429             mwi_msg = ASTOBJ_REF(iterator);
00430          } while (0); );
00431 
00432          msg = mwi_msg;
00433       } else {
00434          msg = ASTOBJ_CONTAINER_FIND(&iface->mwi_q, search_key);
00435       }
00436       break;
00437    }
00438 
00439    return msg;
00440 }

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

Definition at line 356 of file res_smdi.c.

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

00357 {
00358    void *msg;
00359 
00360    purge_old_messages(iface, type);
00361 
00362    lock_msg_q(iface, type);
00363    msg = unlink_from_msg_q(iface, type);
00364    unlock_msg_q(iface, type);
00365 
00366    return msg;
00367 }

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

Definition at line 1220 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, chan, 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.

01221 {
01222    struct ast_module_user *u;
01223    int res = -1;
01224    AST_DECLARE_APP_ARGS(args,
01225       AST_APP_ARG(id);
01226       AST_APP_ARG(component);
01227    );
01228    char *parse;
01229    struct ast_datastore *datastore = NULL;
01230    struct smdi_msg_datastore *smd = NULL;
01231 
01232    u = ast_module_user_add(chan);
01233 
01234    if (!chan) {
01235       ast_log(LOG_ERROR, "SMDI_MSG can not be called without a channel\n");
01236       goto return_error;
01237    }
01238 
01239    if (ast_strlen_zero(data)) {
01240       ast_log(LOG_WARNING, "SMDI_MSG requires an argument\n");
01241       goto return_error;
01242    }
01243 
01244    parse = ast_strdupa(data);
01245    AST_STANDARD_APP_ARGS(args, parse);
01246 
01247    if (ast_strlen_zero(args.id)) {
01248       ast_log(LOG_WARNING, "ID must be supplied to SMDI_MSG\n");
01249       goto return_error;
01250    }
01251 
01252    if (ast_strlen_zero(args.component)) {
01253       ast_log(LOG_WARNING, "ID must be supplied to SMDI_MSG\n");
01254       goto return_error;
01255    }
01256 
01257    ast_channel_lock(chan);
01258    datastore = ast_channel_datastore_find(chan, &smdi_msg_datastore_info, args.id);
01259    ast_channel_unlock(chan);
01260    
01261    if (!datastore) {
01262       ast_log(LOG_WARNING, "No SMDI message found for message ID '%s'\n", args.id);
01263       goto return_error;
01264    }
01265 
01266    smd = datastore->data;
01267 
01268    if (!strcasecmp(args.component, "number")) {
01269       ast_copy_string(buf, smd->md_msg->mesg_desk_num, len);
01270    } else if (!strcasecmp(args.component, "terminal")) {
01271       ast_copy_string(buf, smd->md_msg->mesg_desk_term, len);
01272    } else if (!strcasecmp(args.component, "station")) {
01273       ast_copy_string(buf, smd->md_msg->fwd_st, len);
01274    } else if (!strcasecmp(args.component, "callerid")) {
01275       ast_copy_string(buf, smd->md_msg->calling_st, len);
01276    } else if (!strcasecmp(args.component, "type")) {
01277       snprintf(buf, len, "%c", smd->md_msg->type);
01278    } else {
01279       ast_log(LOG_ERROR, "'%s' is not a valid message component for SMDI_MSG\n",
01280          args.component);
01281       goto return_error;
01282    }
01283 
01284    res = 0;
01285 
01286 return_error:
01287    ast_module_user_remove(u);
01288 
01289    return res;
01290 }

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

Definition at line 1121 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, chan, 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.

01122 {
01123    struct ast_module_user *u;
01124    AST_DECLARE_APP_ARGS(args,
01125       AST_APP_ARG(port);
01126       AST_APP_ARG(search_key);
01127       AST_APP_ARG(timeout);
01128       AST_APP_ARG(options);
01129    );
01130    struct ast_flags options = { 0 };
01131    unsigned int timeout = SMDI_RETRIEVE_TIMEOUT_DEFAULT;
01132    int res = -1;
01133    char *parse = NULL;
01134    struct smdi_msg_datastore *smd = NULL;
01135    struct ast_datastore *datastore = NULL;
01136    struct ast_smdi_interface *iface = NULL;
01137    struct ast_smdi_md_message *md_msg = NULL;
01138 
01139    u = ast_module_user_add(chan);
01140 
01141    if (ast_strlen_zero(data)) {
01142       ast_log(LOG_ERROR, "SMDI_MSG_RETRIEVE requires an argument\n");
01143       goto return_error;
01144    }
01145 
01146    if (!chan) {
01147       ast_log(LOG_ERROR, "SMDI_MSG_RETRIEVE must be used with a channel\n");
01148       goto return_error;
01149    }
01150 
01151    ast_autoservice_start(chan);
01152 
01153    parse = ast_strdupa(data);
01154    AST_STANDARD_APP_ARGS(args, parse);
01155 
01156    if (ast_strlen_zero(args.port) || ast_strlen_zero(args.search_key)) {
01157       ast_log(LOG_ERROR, "Invalid arguments provided to SMDI_MSG_RETRIEVE\n");
01158       goto return_error;
01159    }
01160 
01161    if (!(iface = ast_smdi_interface_find(args.port))) {
01162       ast_log(LOG_ERROR, "SMDI port '%s' not found\n", args.port);
01163       goto return_error;
01164    }
01165 
01166    if (!ast_strlen_zero(args.options)) {
01167       ast_app_parse_options(smdi_msg_ret_options, &options, NULL, args.options);
01168    }
01169 
01170    if (!ast_strlen_zero(args.timeout)) {
01171       if (sscanf(args.timeout, "%30u", &timeout) != 1) {
01172          ast_log(LOG_ERROR, "'%s' is not a valid timeout\n", args.timeout);
01173          timeout = SMDI_RETRIEVE_TIMEOUT_DEFAULT;
01174       }
01175    }
01176 
01177    if (!(md_msg = smdi_message_wait(iface, timeout, SMDI_MD, args.search_key, options))) {
01178       ast_log(LOG_WARNING, "No SMDI message retrieved for search key '%s' after "
01179          "waiting %u ms.\n", args.search_key, timeout);
01180       goto return_error;
01181    }
01182 
01183    if (!(smd = ast_calloc(1, sizeof(*smd))))
01184       goto return_error;
01185 
01186    smd->iface = ASTOBJ_REF(iface);
01187    smd->md_msg = ASTOBJ_REF(md_msg);
01188    smd->id = ast_atomic_fetchadd_int((int *) &smdi_msg_id, 1);
01189    snprintf(buf, len, "%u", smd->id);
01190 
01191    if (!(datastore = ast_datastore_alloc(&smdi_msg_datastore_info, buf)))
01192       goto return_error;
01193 
01194    datastore->data = smd;
01195 
01196    ast_channel_lock(chan);
01197    ast_channel_datastore_add(chan, datastore);
01198    ast_channel_unlock(chan);
01199 
01200    res = 0;
01201 
01202 return_error:
01203    if (iface)
01204       ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
01205 
01206    if (md_msg)
01207       ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy);
01208 
01209    if (smd && !datastore)
01210       smdi_msg_datastore_destroy(smd);
01211 
01212    if (parse)
01213       ast_autoservice_stop(chan);
01214 
01215    ast_module_user_remove(u);
01216 
01217    return res;
01218 }

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

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

00542 {
00543    struct ast_smdi_interface *iface = iface_p;
00544    struct ast_smdi_md_message *md_msg;
00545    struct ast_smdi_mwi_message *mwi_msg;
00546    char c = '\0';
00547    char *cp = NULL;
00548    int i;
00549    int start = 0;
00550       
00551    /* read an smdi message */
00552    while ((c = fgetc(iface->file))) {
00553 
00554       /* check if this is the start of a message */
00555       if (!start) {
00556          if (c == 'M') {
00557             ast_log(LOG_DEBUG, "Read an 'M' to start an SMDI message\n");
00558             start = 1;
00559          }
00560          continue;
00561       }
00562       
00563       if (c == 'D') { /* MD message */
00564          start = 0;
00565 
00566          ast_log(LOG_DEBUG, "Read a 'D' ... it's an MD message.\n");
00567 
00568          if (!(md_msg = ast_calloc(1, sizeof(*md_msg)))) {
00569             ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
00570             return NULL;
00571          }
00572          
00573          ASTOBJ_INIT(md_msg);
00574 
00575          /* read the message desk number */
00576          for (i = 0; i < sizeof(md_msg->mesg_desk_num) - 1; i++) {
00577             md_msg->mesg_desk_num[i] = fgetc(iface->file);
00578             ast_log(LOG_DEBUG, "Read a '%c'\n", md_msg->mesg_desk_num[i]);
00579          }
00580 
00581          md_msg->mesg_desk_num[sizeof(md_msg->mesg_desk_num) - 1] = '\0';
00582          
00583          ast_log(LOG_DEBUG, "The message desk number is '%s'\n", md_msg->mesg_desk_num);
00584 
00585          /* read the message desk terminal number */
00586          for (i = 0; i < sizeof(md_msg->mesg_desk_term) - 1; i++) {
00587             md_msg->mesg_desk_term[i] = fgetc(iface->file);
00588             ast_log(LOG_DEBUG, "Read a '%c'\n", md_msg->mesg_desk_term[i]);
00589          }
00590 
00591          md_msg->mesg_desk_term[sizeof(md_msg->mesg_desk_term) - 1] = '\0';
00592 
00593          ast_log(LOG_DEBUG, "The message desk terminal is '%s'\n", md_msg->mesg_desk_term);
00594 
00595          /* read the message type */
00596          md_msg->type = fgetc(iface->file);
00597        
00598          ast_log(LOG_DEBUG, "Message type is '%c'\n", md_msg->type);
00599 
00600          /* read the forwarding station number (may be blank) */
00601          cp = &md_msg->fwd_st[0];
00602          for (i = 0; i < sizeof(md_msg->fwd_st) - 1; i++) {
00603             if ((c = fgetc(iface->file)) == ' ') {
00604                *cp = '\0';
00605                ast_log(LOG_DEBUG, "Read a space, done looking for the forwarding station\n");
00606                break;
00607             }
00608 
00609             /* store c in md_msg->fwd_st */
00610             if (i >= iface->msdstrip) {
00611                ast_log(LOG_DEBUG, "Read a '%c' and stored it in the forwarding station buffer\n", c);
00612                *cp++ = c;
00613             } else {
00614                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);
00615             }
00616          }
00617 
00618          /* make sure the value is null terminated, even if this truncates it */
00619          md_msg->fwd_st[sizeof(md_msg->fwd_st) - 1] = '\0';
00620          cp = NULL;
00621 
00622          ast_log(LOG_DEBUG, "The forwarding station is '%s'\n", md_msg->fwd_st);
00623 
00624          /* Put the fwd_st in the name field so that we can use ASTOBJ_FIND to look
00625           * up a message on this field */
00626          ast_copy_string(md_msg->name, md_msg->fwd_st, sizeof(md_msg->name));
00627 
00628          /* read the calling station number (may be blank) */
00629          cp = &md_msg->calling_st[0];
00630          for (i = 0; i < sizeof(md_msg->calling_st) - 1; i++) {
00631             if (!isdigit((c = fgetc(iface->file)))) {
00632                *cp = '\0';
00633                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);
00634                if (c == ' ') {
00635                   /* Don't break on a space.  We may read the space before the calling station
00636                    * here if the forwarding station buffer filled up. */
00637                   i--; /* We're still on the same character */
00638                   continue;
00639                }
00640                break;
00641             }
00642 
00643             /* store c in md_msg->calling_st */
00644             if (i >= iface->msdstrip) {
00645                ast_log(LOG_DEBUG, "Read a '%c' and stored it in the calling station buffer\n", c);
00646                *cp++ = c;
00647             } else {
00648                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);
00649             }
00650          }
00651 
00652          /* make sure the value is null terminated, even if this truncates it */
00653          md_msg->calling_st[sizeof(md_msg->calling_st) - 1] = '\0';
00654          cp = NULL;
00655 
00656          ast_log(LOG_DEBUG, "The calling station is '%s'\n", md_msg->calling_st);
00657 
00658          /* add the message to the message queue */
00659          md_msg->timestamp = ast_tvnow();
00660          ast_smdi_md_message_push(iface, md_msg);
00661          ast_log(LOG_DEBUG, "Received SMDI MD message on %s\n", iface->name);
00662          
00663          ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy);
00664 
00665       } else if (c == 'W') { /* MWI message */
00666          start = 0;
00667 
00668          ast_log(LOG_DEBUG, "Read a 'W', it's an MWI message. (No more debug coming for MWI messages)\n");
00669 
00670          if (!(mwi_msg = ast_calloc(1, sizeof(*mwi_msg)))) {
00671             ASTOBJ_UNREF(iface,ast_smdi_interface_destroy);
00672             return NULL;
00673          }
00674 
00675          ASTOBJ_INIT(mwi_msg);
00676 
00677          /* discard the 'I' (from 'MWI') */
00678          fgetc(iface->file);
00679          
00680          /* read the forwarding station number (may be blank) */
00681          cp = &mwi_msg->fwd_st[0];
00682          for (i = 0; i < sizeof(mwi_msg->fwd_st) - 1; i++) {
00683             if ((c = fgetc(iface->file)) == ' ') {
00684                *cp = '\0';
00685                break;
00686             }
00687 
00688             /* store c in md_msg->fwd_st */
00689             if (i >= iface->msdstrip)
00690                *cp++ = c;
00691          }
00692 
00693          /* make sure the station number is null terminated, even if this will truncate it */
00694          mwi_msg->fwd_st[sizeof(mwi_msg->fwd_st) - 1] = '\0';
00695          cp = NULL;
00696          
00697          /* Put the fwd_st in the name field so that we can use ASTOBJ_FIND to look
00698           * up a message on this field */
00699          ast_copy_string(mwi_msg->name, mwi_msg->fwd_st, sizeof(mwi_msg->name));
00700 
00701          /* read the mwi failure cause */
00702          for (i = 0; i < sizeof(mwi_msg->cause) - 1; i++)
00703             mwi_msg->cause[i] = fgetc(iface->file);
00704 
00705          mwi_msg->cause[sizeof(mwi_msg->cause) - 1] = '\0';
00706 
00707          /* add the message to the message queue */
00708          mwi_msg->timestamp = ast_tvnow();
00709          ast_smdi_mwi_message_push(iface, mwi_msg);
00710          ast_log(LOG_DEBUG, "Received SMDI MWI message on %s\n", iface->name);
00711          
00712          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
00713       } else {
00714          ast_log(LOG_ERROR, "Unknown SMDI message type received on %s (M%c).\n", iface->name, c);
00715          start = 0;
00716       }
00717    }
00718 
00719    ast_log(LOG_ERROR, "Error reading from SMDI interface %s, stopping listener thread\n", iface->name);
00720    ASTOBJ_UNREF(iface,ast_smdi_interface_destroy);
00721    return NULL;
00722 }

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

Definition at line 192 of file res_smdi.c.

References ast_debug, ast_log(), ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, errno, 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().

00193 {
00194    FILE *file;
00195    int i;
00196    
00197    if (!(file = fopen(iface->name, "w"))) {
00198       ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s) for writing\n", iface->name, strerror(errno));
00199       return 1;
00200    }  
00201    
00202    ASTOBJ_WRLOCK(iface);
00203    
00204    fprintf(file, "%s:MWI ", on ? "OP" : "RMV");
00205    
00206    for (i = 0; i < iface->msdstrip; i++)
00207       fprintf(file, "0");
00208 
00209    fprintf(file, "%s!\x04", mailbox);
00210 
00211    fclose(file);
00212 
00213    ASTOBJ_UNLOCK(iface);
00214    ast_debug(1, "Sent MWI set message for %s on %s\n", mailbox, iface->name);
00215 
00216    return 0;
00217 }

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

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

00275 {
00276    switch (type) {
00277    case SMDI_MWI:
00278       return ASTOBJ_CONTAINER_UNLINK_START(&iface->mwi_q);
00279    case SMDI_MD:
00280       return ASTOBJ_CONTAINER_UNLINK_START(&iface->md_q);
00281    }
00282    return NULL;
00283 }

static int unload_module ( void   )  [static]

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

01368 {
01369    /* this destructor stops any running smdi_read threads */
01370    ASTOBJ_CONTAINER_DESTROYALL(&smdi_ifaces, ast_smdi_interface_destroy);
01371    ASTOBJ_CONTAINER_DESTROY(&smdi_ifaces);
01372 
01373    destroy_all_mailbox_mappings();
01374 
01375    ast_mutex_lock(&mwi_monitor.lock);
01376    mwi_monitor.stop = 1;
01377    ast_cond_signal(&mwi_monitor.cond);
01378    ast_mutex_unlock(&mwi_monitor.lock);
01379 
01380    if (mwi_monitor.thread != AST_PTHREADT_NULL) {
01381       pthread_join(mwi_monitor.thread, NULL);
01382    }
01383 
01384    ast_custom_function_unregister(&smdi_msg_retrieve_function);
01385    ast_custom_function_unregister(&smdi_msg_function);
01386 
01387    return 0;
01388 }

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

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

00263 {
00264    switch (type) {
00265    case SMDI_MWI:
00266       return ast_mutex_unlock(&iface->mwi_q_lock);
00267    case SMDI_MD:
00268       return ast_mutex_unlock(&iface->md_q_lock);
00269    }
00270 
00271    return -1;
00272 }

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

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

00301 {
00302    struct ast_smdi_md_message *md_msg = msg;
00303    struct ast_smdi_mwi_message *mwi_msg = msg;
00304 
00305    switch (type) {
00306    case SMDI_MWI:
00307       ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
00308       break;
00309    case SMDI_MD:
00310       ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy);
00311       break;
00312    }
00313 }


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

Definition at line 1409 of file res_smdi.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1409 of file res_smdi.c.

ast_cond_t cond

Definition at line 118 of file res_smdi.c.

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

Definition at line 59 of file res_smdi.c.

struct mailbox_mapping* first

Definition at line 120 of file res_smdi.c.

struct mailbox_mapping* last

Definition at line 120 of file res_smdi.c.

struct timeval last_poll

The time that the last poll began

Definition at line 126 of file res_smdi.c.

ast_mutex_t lock

Definition at line 117 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(), and unload_module().

unsigned int polling_interval

Polling Interval for checking mailbox status

Definition at line 122 of file res_smdi.c.

struct ast_smdi_interface_container smdi_ifaces

SMDI interface container.

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

struct ast_datastore_info smdi_msg_datastore_info [static]

Initial value:

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

Definition at line 1106 of file res_smdi.c.

Referenced by smdi_msg_read(), and smdi_msg_retrieve_read().

struct ast_custom_function smdi_msg_function [static]

Definition at line 1316 of file res_smdi.c.

Referenced by load_module(), and unload_module().

int smdi_msg_id [static]

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

Referenced by smdi_msg_retrieve_read().

struct ast_custom_function smdi_msg_retrieve_function [static]

Definition at line 1292 of file res_smdi.c.

Referenced by load_module(), and unload_module().

unsigned int stop

Set to 1 to tell the polling thread to stop

Definition at line 124 of file res_smdi.c.

pthread_t thread

The thread ID

Definition at line 116 of file res_smdi.c.


Generated on Wed Aug 18 22:34:32 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7