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

SMDI support for Asterisk. More...

#include "asterisk.h"
#include <termios.h>
#include <sys/time.h>
#include <time.h>
#include <ctype.h>
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/smdi.h"
#include "asterisk/config.h"
#include "asterisk/io.h"
#include "asterisk/stringfields.h"
#include "asterisk/linkedlists.h"
#include "asterisk/app.h"
#include "asterisk/mwi.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
Include dependency graph for res_smdi.c:

Go to the source code of this file.

Data Structures

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

Macros

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

Enumerations

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

Functions

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

Variables

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

Detailed Description

SMDI support for Asterisk.

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

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

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

Definition in file res_smdi.c.

Macro Definition Documentation

◆ AST_API_MODULE

#define AST_API_MODULE

Definition at line 57 of file res_smdi.c.

◆ DEFAULT_POLLING_INTERVAL

#define DEFAULT_POLLING_INTERVAL   10

10 seconds

Definition at line 204 of file res_smdi.c.

Referenced by smdi_load().

◆ SMDI_MSG_EXPIRY_TIME

#define SMDI_MSG_EXPIRY_TIME   30000 /* 30 seconds */

Definition at line 69 of file res_smdi.c.

Referenced by smdi_load().

◆ SMDI_RETRIEVE_TIMEOUT_DEFAULT

#define SMDI_RETRIEVE_TIMEOUT_DEFAULT   3000

In milliseconds

Definition at line 1195 of file res_smdi.c.

Referenced by smdi_msg_retrieve_read().

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
OPT_SEARCH_TERMINAL 
OPT_SEARCH_NUMBER 

Definition at line 429 of file res_smdi.c.

429  {
430  OPT_SEARCH_TERMINAL = (1 << 0),
431  OPT_SEARCH_NUMBER = (1 << 1),
432 };

◆ smdi_message_type

Enumerator
SMDI_MWI 
SMDI_MD 

Definition at line 319 of file res_smdi.c.

319  {
320  SMDI_MWI,
321  SMDI_MD,
322 };

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1452 of file res_smdi.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1452 of file res_smdi.c.

◆ alloc_smdi_interface()

static struct ast_smdi_interface* alloc_smdi_interface ( void  )
static

Definition at line 914 of file res_smdi.c.

References ao2_alloc, AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_container_alloc_list, ast_cond_init, ast_mutex_init, ast_smdi_interface::md_q, ast_smdi_interface::md_q_cond, ast_smdi_interface::md_q_lock, ast_smdi_interface::mwi_q, ast_smdi_interface::mwi_q_cond, ast_smdi_interface::mwi_q_lock, NULL, smdi_interface_destroy(), smdi_md_q_cmp_fn(), and smdi_mwi_q_cmp_fn().

Referenced by smdi_load().

915 {
916  struct ast_smdi_interface *iface;
917 
918  if (!(iface = ao2_alloc(sizeof(*iface), smdi_interface_destroy))) {
919  return NULL;
920  }
921 
924 
925  ast_mutex_init(&iface->md_q_lock);
926  ast_cond_init(&iface->md_q_cond, NULL);
927 
928  ast_mutex_init(&iface->mwi_q_lock);
929  ast_cond_init(&iface->mwi_q_cond, NULL);
930 
931  return iface;
932 }
ast_mutex_t md_q_lock
Definition: res_smdi.c:170
static void smdi_interface_destroy(void *obj)
Definition: res_smdi.c:224
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define NULL
Definition: resample.c:96
static int smdi_mwi_q_cmp_fn(void *obj, void *data, int flags)
Definition: res_smdi.c:879
static int smdi_md_q_cmp_fn(void *obj, void *arg, int flags)
Definition: res_smdi.c:886
ast_cond_t mwi_q_cond
Definition: res_smdi.c:174
ast_mutex_t mwi_q_lock
Definition: res_smdi.c:173
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ao2_container * mwi_q
Definition: res_smdi.c:172
ast_cond_t md_q_cond
Definition: res_smdi.c:171
#define ast_mutex_init(pmutex)
Definition: lock.h:184
struct ao2_container * md_q
Definition: res_smdi.c:169

◆ AO2_GLOBAL_OBJ_STATIC()

static AO2_GLOBAL_OBJ_STATIC ( smdi_ifaces  )
static

◆ append_mailbox_mapping()

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

Definition at line 805 of file res_smdi.c.

References ao2_bump, ast_calloc_with_stringfields, AST_LIST_INSERT_TAIL, ast_mutex_lock, ast_mutex_unlock, ast_strdupa, ast_string_field_set, ast_strlen_zero, context, mailbox_mapping::iface, mailbox, ast_variable::name, mailbox_mapping::smdi, strsep(), and ast_variable::value.

Referenced by smdi_load().

806 {
807  struct mailbox_mapping *mm;
808  char *mailbox, *context;
809 
810  if (!(mm = ast_calloc_with_stringfields(1, struct mailbox_mapping, 32)))
811  return;
812 
813  ast_string_field_set(mm, smdi, var->name);
814 
815  context = ast_strdupa(var->value);
816  mailbox = strsep(&context, "@");
817  if (ast_strlen_zero(context))
818  context = "default";
819 
820  ast_string_field_set(mm, mailbox, mailbox);
821  ast_string_field_set(mm, context, context);
822 
823  mm->iface = ao2_bump(iface);
824 
826  AST_LIST_INSERT_TAIL(&mwi_monitor.mailbox_mappings, mm, entry);
828 }
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:426
#define ast_mutex_lock(a)
Definition: lock.h:187
A mapping between an SMDI mailbox ID and an Asterisk mailbox.
Definition: res_smdi.c:186
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_bump(obj)
Definition: astobj2.h:491
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
struct ast_smdi_interface * iface
Definition: res_smdi.c:191
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
char * strsep(char **str, const char *delims)
const ast_string_field smdi
Definition: res_smdi.c:199
Definition: search.h:40
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static struct @494 mwi_monitor
Data that gets used by the SMDI MWI monitoring thread.
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1452 of file res_smdi.c.

◆ ast_smdi_interface_find()

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

Find an SMDI interface with the specified name.

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

Definition at line 563 of file res_smdi.c.

References ao2_find, ao2_global_obj_ref, ao2_ref, c, NULL, and OBJ_SEARCH_KEY.

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

564 {
565  struct ao2_container *c;
566  struct ast_smdi_interface *iface = NULL;
567 
568  c = ao2_global_obj_ref(smdi_ifaces);
569  if (c) {
570  iface = ao2_find(c, iface_name, OBJ_SEARCH_KEY);
571  ao2_ref(c, -1);
572  }
573 
574  return iface;
575 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
static struct test_val c
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
Generic container type.

◆ ast_smdi_md_message_pop()

struct ast_smdi_md_message* AST_OPTIONAL_API_NAME() ast_smdi_md_message_pop ( struct ast_smdi_interface iface)

Get the next SMDI message from the queue.

Parameters
ifacea pointer to the interface to use.

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

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

Definition at line 534 of file res_smdi.c.

References SMDI_MD, and smdi_msg_pop().

535 {
536  return smdi_msg_pop(iface, SMDI_MD);
537 }
static void * smdi_msg_pop(struct ast_smdi_interface *iface, enum smdi_message_type type)
Definition: res_smdi.c:416

◆ ast_smdi_md_message_push()

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

Definition at line 260 of file res_smdi.c.

References ao2_link, ast_cond_broadcast, ast_mutex_lock, ast_mutex_unlock, ast_smdi_interface::md_q, ast_smdi_interface::md_q_cond, and ast_smdi_interface::md_q_lock.

Referenced by purge_old_messages(), and smdi_read().

261 {
262  ast_mutex_lock(&iface->md_q_lock);
263  ao2_link(iface->md_q, md_msg);
264  ast_cond_broadcast(&iface->md_q_cond);
265  ast_mutex_unlock(&iface->md_q_lock);
266 }
ast_mutex_t md_q_lock
Definition: res_smdi.c:170
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_cond_broadcast(cond)
Definition: lock.h:202
ast_cond_t md_q_cond
Definition: res_smdi.c:171
struct ao2_container * md_q
Definition: res_smdi.c:169
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ ast_smdi_md_message_wait()

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

Get the next SMDI message from the queue.

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

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

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

Definition at line 539 of file res_smdi.c.

References NULL, SMDI_MD, smdi_message_wait(), and timeout.

Referenced by __analog_ss_thread(), and analog_ss_thread().

540 {
541  struct ast_flags options = { 0 };
542  return smdi_message_wait(iface, timeout, SMDI_MD, NULL, options);
543 }
static int timeout
Definition: cdr_mysql.c:86
#define NULL
Definition: resample.c:96
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)
Definition: res_smdi.c:478
Structure used to handle boolean flags.
Definition: utils.h:199
static struct test_options options

◆ ast_smdi_mwi_message_pop()

struct ast_smdi_mwi_message* AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_pop ( struct ast_smdi_interface iface)

Get the next SMDI message from the queue.

Parameters
ifacea pointer to the interface to use.

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

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

Definition at line 545 of file res_smdi.c.

References smdi_msg_pop(), and SMDI_MWI.

546 {
547  return smdi_msg_pop(iface, SMDI_MWI);
548 }
static void * smdi_msg_pop(struct ast_smdi_interface *iface, enum smdi_message_type type)
Definition: res_smdi.c:416

◆ ast_smdi_mwi_message_push()

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

Definition at line 274 of file res_smdi.c.

References ao2_link, ast_cond_broadcast, ast_mutex_lock, ast_mutex_unlock, ast_smdi_interface::mwi_q, ast_smdi_interface::mwi_q_cond, and ast_smdi_interface::mwi_q_lock.

Referenced by purge_old_messages(), and smdi_read().

275 {
276  ast_mutex_lock(&iface->mwi_q_lock);
277  ao2_link(iface->mwi_q, mwi_msg);
279  ast_mutex_unlock(&iface->mwi_q_lock);
280 }
#define ast_mutex_lock(a)
Definition: lock.h:187
ast_cond_t mwi_q_cond
Definition: res_smdi.c:174
#define ast_cond_broadcast(cond)
Definition: lock.h:202
ast_mutex_t mwi_q_lock
Definition: res_smdi.c:173
struct ao2_container * mwi_q
Definition: res_smdi.c:172
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ ast_smdi_mwi_message_wait()

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

Get the next SMDI message from the queue.

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

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

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

Definition at line 550 of file res_smdi.c.

References NULL, smdi_message_wait(), SMDI_MWI, and timeout.

551 {
552  struct ast_flags options = { 0 };
553  return smdi_message_wait(iface, timeout, SMDI_MWI, NULL, options);
554 }
static int timeout
Definition: cdr_mysql.c:86
#define NULL
Definition: resample.c:96
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)
Definition: res_smdi.c:478
Structure used to handle boolean flags.
Definition: utils.h:199
static struct test_options options

◆ ast_smdi_mwi_message_wait_station()

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

References smdi_message_wait(), and SMDI_MWI.

Referenced by run_externnotify().

558 {
559  struct ast_flags options = { 0 };
560  return smdi_message_wait(iface, timeout, SMDI_MWI, station, options);
561 }
static int timeout
Definition: cdr_mysql.c:86
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)
Definition: res_smdi.c:478
Structure used to handle boolean flags.
Definition: utils.h:199
static struct test_options options

◆ ast_smdi_mwi_set()

int AST_OPTIONAL_API_NAME() ast_smdi_mwi_set ( struct ast_smdi_interface iface,
const char *  mailbox 
)

Set the MWI indicator for a mailbox.

Parameters
ifacethe interface to use.
mailboxthe mailbox to use.

Definition at line 309 of file res_smdi.c.

References mailbox, and smdi_toggle_mwi().

Referenced by poll_mailbox(), and run_externnotify().

310 {
311  return smdi_toggle_mwi(iface, mailbox, 1);
312 }
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
static int smdi_toggle_mwi(struct ast_smdi_interface *iface, const char *mailbox, int on)
Definition: res_smdi.c:282

◆ ast_smdi_mwi_unset()

int AST_OPTIONAL_API_NAME() ast_smdi_mwi_unset ( struct ast_smdi_interface iface,
const char *  mailbox 
)

Unset the MWI indicator for a mailbox.

Parameters
ifacethe interface to use.
mailboxthe mailbox to use.

Definition at line 314 of file res_smdi.c.

References mailbox, and smdi_toggle_mwi().

Referenced by poll_mailbox(), and run_externnotify().

315 {
316  return smdi_toggle_mwi(iface, mailbox, 0);
317 }
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
static int smdi_toggle_mwi(struct ast_smdi_interface *iface, const char *mailbox, int on)
Definition: res_smdi.c:282

◆ destroy_all_mailbox_mappings()

static void destroy_all_mailbox_mappings ( void  )
static

Definition at line 795 of file res_smdi.c.

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

Referenced by smdi_load(), and unload_module().

796 {
797  struct mailbox_mapping *mm;
798 
800  while ((mm = AST_LIST_REMOVE_HEAD(&mwi_monitor.mailbox_mappings, entry)))
803 }
static void destroy_mailbox_mapping(struct mailbox_mapping *mm)
Definition: res_smdi.c:788
#define ast_mutex_lock(a)
Definition: lock.h:187
A mapping between an SMDI mailbox ID and an Asterisk mailbox.
Definition: res_smdi.c:186
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
Definition: search.h:40
static struct @494 mwi_monitor
Data that gets used by the SMDI MWI monitoring thread.
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ destroy_mailbox_mapping()

static void destroy_mailbox_mapping ( struct mailbox_mapping mm)
static

Definition at line 788 of file res_smdi.c.

References ao2_ref, ast_free, ast_string_field_free_memory, and mailbox_mapping::iface.

Referenced by destroy_all_mailbox_mappings().

789 {
791  ao2_ref(mm->iface, -1);
792  ast_free(mm);
793 }
struct ast_smdi_interface * iface
Definition: res_smdi.c:191
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_free(a)
Definition: astmm.h:182
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ load_module()

static int load_module ( void  )
static

Load the module.

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

Definition at line 1411 of file res_smdi.c.

References ast_cond_init, ast_custom_function_register, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_mutex_init, LOG_NOTICE, NULL, smdi_load(), and unload_module().

Referenced by reload().

1412 {
1413  int res;
1414 
1415  ast_mutex_init(&mwi_monitor.lock);
1416  ast_cond_init(&mwi_monitor.cond, NULL);
1417 
1418  /* load the config and start the listener threads*/
1419  res = smdi_load(0);
1420  if (res < 0) {
1421  unload_module();
1422  return AST_MODULE_LOAD_DECLINE;
1423  } else if (res == 1) {
1424  ast_log(LOG_NOTICE, "No SMDI interfaces are available to listen on, not starting SMDI listener.\n");
1425  }
1426 
1429 
1430  return AST_MODULE_LOAD_SUCCESS;
1431 }
static int smdi_load(int reload)
Definition: res_smdi.c:952
static struct ast_custom_function smdi_msg_retrieve_function
Definition: res_smdi.c:1370
#define ast_cond_init(cond, attr)
Definition: lock.h:199
static struct ast_custom_function smdi_msg_function
Definition: res_smdi.c:1375
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define LOG_NOTICE
Definition: logger.h:263
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static int unload_module(void)
Definition: res_smdi.c:1380
#define ast_mutex_init(pmutex)
Definition: lock.h:184
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
static struct @494 mwi_monitor
Data that gets used by the SMDI MWI monitoring thread.

◆ lock_msg_q()

static int lock_msg_q ( struct ast_smdi_interface iface,
enum smdi_message_type  type 
)
inlinestatic

Definition at line 324 of file res_smdi.c.

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

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

325 {
326  switch (type) {
327  case SMDI_MWI:
328  return ast_mutex_lock(&iface->mwi_q_lock);
329  case SMDI_MD:
330  return ast_mutex_lock(&iface->md_q_lock);
331  }
332 
333  return -1;
334 }
static const char type[]
Definition: chan_ooh323.c:109
ast_mutex_t md_q_lock
Definition: res_smdi.c:170
#define ast_mutex_lock(a)
Definition: lock.h:187
ast_mutex_t mwi_q_lock
Definition: res_smdi.c:173

◆ msg_timestamp()

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

Definition at line 360 of file res_smdi.c.

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

Referenced by purge_old_messages().

361 {
362  struct ast_smdi_md_message *md_msg = msg;
363  struct ast_smdi_mwi_message *mwi_msg = msg;
364 
365  switch (type) {
366  case SMDI_MWI:
367  return mwi_msg->timestamp;
368  case SMDI_MD:
369  return md_msg->timestamp;
370  }
371 
372  return ast_tv(0, 0);
373 }
static const char type[]
Definition: chan_ooh323.c:109
An SMDI message desk message.
Definition: smdi.h:65
struct timeval timestamp
Definition: smdi.h:55
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226
struct timeval timestamp
Definition: smdi.h:72
An SMDI message waiting indicator message.
Definition: smdi.h:51

◆ mwi_monitor_handler()

static void* mwi_monitor_handler ( void *  data)
static

Definition at line 852 of file res_smdi.c.

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

Referenced by smdi_load().

853 {
854  while (!mwi_monitor.stop) {
855  struct timespec ts = { 0, };
856  struct timeval polltime;
857  struct mailbox_mapping *mm;
858 
860 
861  mwi_monitor.last_poll = ast_tvnow();
862 
863  AST_LIST_TRAVERSE(&mwi_monitor.mailbox_mappings, mm, entry)
864  poll_mailbox(mm);
865 
866  /* Sleep up to the configured polling interval. Allow unload_module()
867  * to signal us to wake up and exit. */
868  polltime = ast_tvadd(mwi_monitor.last_poll, ast_tv(mwi_monitor.polling_interval, 0));
869  ts.tv_sec = polltime.tv_sec;
870  ts.tv_nsec = polltime.tv_usec * 1000;
871  ast_cond_timedwait(&mwi_monitor.cond, &mwi_monitor.lock, &ts);
872 
874  }
875 
876  return NULL;
877 }
static void poll_mailbox(struct mailbox_mapping *mm)
Definition: res_smdi.c:833
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_mutex_lock(a)
Definition: lock.h:187
A mapping between an SMDI mailbox ID and an Asterisk mailbox.
Definition: res_smdi.c:186
#define NULL
Definition: resample.c:96
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226
Definition: search.h:40
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
static struct @494 mwi_monitor
Data that gets used by the SMDI MWI monitoring thread.
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ poll_mailbox()

static void poll_mailbox ( struct mailbox_mapping mm)
static
Note
Called with the mwi_monitor.lock locked

Definition at line 833 of file res_smdi.c.

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

Referenced by mwi_monitor_handler().

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

◆ purge_old_messages()

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

Definition at line 375 of file res_smdi.c.

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

Referenced by smdi_msg_find(), and smdi_msg_pop().

376 {
377  struct timeval now = ast_tvnow();
378  long elapsed = 0;
379  void *msg;
380 
381  lock_msg_q(iface, type);
382  msg = unlink_from_msg_q(iface, type);
383  unlock_msg_q(iface, type);
384 
385  /* purge old messages */
386  while (msg) {
387  elapsed = ast_tvdiff_ms(now, msg_timestamp(msg, type));
388 
389  if (elapsed > iface->msg_expiry) {
390  /* found an expired message */
391  ao2_ref(msg, -1);
392  ast_log(LOG_NOTICE, "Purged expired message from %s SMDI %s message queue. "
393  "Message was %ld milliseconds too old.\n",
394  iface->name, (type == SMDI_MD) ? "MD" : "MWI",
395  elapsed - iface->msg_expiry);
396 
397  lock_msg_q(iface, type);
398  msg = unlink_from_msg_q(iface, type);
399  unlock_msg_q(iface, type);
400  } else {
401  /* good message, put it back and return */
402  switch (type) {
403  case SMDI_MD:
404  ast_smdi_md_message_push(iface, msg);
405  break;
406  case SMDI_MWI:
407  ast_smdi_mwi_message_push(iface, msg);
408  break;
409  }
410  ao2_ref(msg, -1);
411  break;
412  }
413  }
414 }
static const char type[]
Definition: chan_ooh323.c:109
static int unlock_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
Definition: res_smdi.c:336
char name[SMDI_MAX_FILENAME_LEN]
Definition: res_smdi.c:168
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
static void ast_smdi_mwi_message_push(struct ast_smdi_interface *iface, struct ast_smdi_mwi_message *mwi_msg)
Definition: res_smdi.c:274
#define ast_log
Definition: astobj2.c:42
static struct timeval msg_timestamp(void *msg, enum smdi_message_type type)
Definition: res_smdi.c:360
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void * unlink_from_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
Definition: res_smdi.c:348
#define LOG_NOTICE
Definition: logger.h:263
static int lock_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
Definition: res_smdi.c:324
static void ast_smdi_md_message_push(struct ast_smdi_interface *iface, struct ast_smdi_md_message *md_msg)
Definition: res_smdi.c:260

◆ reload()

static int reload ( void  )
static

Definition at line 1433 of file res_smdi.c.

References ast_log, AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CHANNEL_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_EXTENDED, ASTERISK_GPL_KEY, load_module(), LOG_WARNING, smdi_load(), and unload_module().

1434 {
1435  int res;
1436 
1437  res = smdi_load(1);
1438  if (res < 0) {
1439  return res;
1440  } else if (res == 1) {
1441  ast_log(LOG_WARNING, "No SMDI interfaces were specified to listen on, not starting SDMI listener.\n");
1442  }
1443  return 0;
1444 }
static int smdi_load(int reload)
Definition: res_smdi.c:952
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42

◆ smdi_ifaces_cmp_fn()

static int smdi_ifaces_cmp_fn ( void *  obj,
void *  data,
int  flags 
)
static

Definition at line 934 of file res_smdi.c.

References CMP_MATCH, CMP_STOP, ast_smdi_interface::name, and str.

Referenced by smdi_load().

935 {
936  struct ast_smdi_interface *iface = obj;
937 
938  char *str = data;
939  return !strcmp(iface->name, str) ? CMP_MATCH | CMP_STOP : 0;
940 }
char name[SMDI_MAX_FILENAME_LEN]
Definition: res_smdi.c:168
const char * str
Definition: app_jack.c:147

◆ smdi_interface_destroy()

static void smdi_interface_destroy ( void *  obj)
static

Definition at line 224 of file res_smdi.c.

References ao2_cleanup, ast_cond_destroy, ast_module_unref, ast_mutex_destroy, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_smdi_interface::file, 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, NULL, ast_module_info::self, and ast_smdi_interface::thread.

Referenced by alloc_smdi_interface().

225 {
226  struct ast_smdi_interface *iface = obj;
227  int mod_unref_defer = 0;
228 
229  if (iface->thread != AST_PTHREADT_NULL && iface->thread != AST_PTHREADT_STOP) {
230  pthread_cancel(iface->thread);
231  pthread_join(iface->thread, NULL);
232  mod_unref_defer = 1;
233  }
234 
235  iface->thread = AST_PTHREADT_STOP;
236 
237  if (iface->file) {
238  fclose(iface->file);
239  }
240 
241  ao2_cleanup(iface->md_q);
242  ast_mutex_destroy(&iface->md_q_lock);
243  ast_cond_destroy(&iface->md_q_cond);
244 
245  ao2_cleanup(iface->mwi_q);
246  ast_mutex_destroy(&iface->mwi_q_lock);
247  ast_cond_destroy(&iface->mwi_q_cond);
248 
249  if (mod_unref_defer) {
251  }
252 }
ast_mutex_t md_q_lock
Definition: res_smdi.c:170
#define NULL
Definition: resample.c:96
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
ast_cond_t mwi_q_cond
Definition: res_smdi.c:174
struct ast_module * self
Definition: module.h:342
#define AST_PTHREADT_NULL
Definition: lock.h:66
ast_mutex_t mwi_q_lock
Definition: res_smdi.c:173
pthread_t thread
Definition: res_smdi.c:177
#define ast_cond_destroy(cond)
Definition: lock.h:200
struct ao2_container * mwi_q
Definition: res_smdi.c:172
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
ast_cond_t md_q_cond
Definition: res_smdi.c:171
#define AST_PTHREADT_STOP
Definition: lock.h:67
#define ast_mutex_destroy(a)
Definition: lock.h:186
struct ao2_container * md_q
Definition: res_smdi.c:169

◆ smdi_load()

static int smdi_load ( int  reload)
static

Definition at line 952 of file res_smdi.c.

References alloc_smdi_interface(), AO2_ALLOC_OPT_LOCK_MUTEX, ao2_cleanup, ao2_container_alloc_list, ao2_container_count(), ao2_find, ao2_global_obj_ref, ao2_global_obj_replace_unref, ao2_link, append_mailbox_mapping(), ast_config_destroy(), ast_config_load, ast_copy_string(), AST_LIST_EMPTY, ast_log, ast_module_ref, ast_pthread_create_background, AST_PTHREADT_NULL, ast_true(), ast_variable_browse(), ast_verb, config_file, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_POLLING_INTERVAL, destroy_all_mailbox_mappings(), errno, ast_smdi_interface::fd, ast_smdi_interface::file, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, ast_smdi_interface::mode, ast_smdi_interface::msdstrip, ast_smdi_interface::msg_expiry, mwi_monitor_handler(), ast_variable::name, ast_smdi_interface::name, ast_variable::next, NULL, OBJ_SEARCH_KEY, RAII_VAR, ast_module_info::self, smdi_ifaces_cmp_fn(), SMDI_MSG_EXPIRY_TIME, smdi_read(), ast_smdi_interface::thread, and ast_variable::value.

Referenced by load_module(), and reload().

953 {
954  struct ast_config *conf;
955  struct ast_variable *v;
956  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
957  int res = 0;
958  RAII_VAR(struct ao2_container *, new_ifaces, NULL, ao2_cleanup);
959  RAII_VAR(struct ao2_container *, old_ifaces, ao2_global_obj_ref(smdi_ifaces), ao2_cleanup);
960  struct ast_smdi_interface *mailbox_iface = NULL;
961 
962  /* Config options */
963  speed_t baud_rate = B9600; /* 9600 baud rate */
964  tcflag_t paritybit = PARENB; /* even parity checking */
965  tcflag_t charsize = CS7; /* seven bit characters */
966  int stopbits = 0; /* One stop bit */
967 
968  int msdstrip = 0; /* strip zero digits */
970 
971  if (!(conf = ast_config_load(config_file, config_flags)) || conf == CONFIG_STATUS_FILEINVALID) {
972  if (reload)
973  ast_log(LOG_NOTICE, "Unable to reload config %s: SMDI untouched\n", config_file);
974  else
975  ast_log(LOG_NOTICE, "Unable to load config %s: SMDI disabled\n", config_file);
976  return 1;
977  } else if (conf == CONFIG_STATUS_FILEUNCHANGED)
978  return 0;
979 
981  if (!new_ifaces) {
982  ast_config_destroy(conf);
983  return -1;
984  }
985 
986  for (v = ast_variable_browse(conf, "interfaces"); v; v = v->next) {
987  RAII_VAR(struct ast_smdi_interface *, iface, NULL, ao2_cleanup);
988 
989  if (!strcasecmp(v->name, "baudrate")) {
990  if (!strcasecmp(v->value, "9600"))
991  baud_rate = B9600;
992  else if (!strcasecmp(v->value, "4800"))
993  baud_rate = B4800;
994  else if (!strcasecmp(v->value, "2400"))
995  baud_rate = B2400;
996  else if (!strcasecmp(v->value, "1200"))
997  baud_rate = B1200;
998  else {
999  ast_log(LOG_NOTICE, "Invalid baud rate '%s' specified in %s (line %d), using default\n", v->value, config_file, v->lineno);
1000  baud_rate = B9600;
1001  }
1002  } else if (!strcasecmp(v->name, "msdstrip")) {
1003  if (!sscanf(v->value, "%30d", &msdstrip)) {
1004  ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno);
1005  msdstrip = 0;
1006  } else if (0 > msdstrip || msdstrip > 9) {
1007  ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno);
1008  msdstrip = 0;
1009  }
1010  } else if (!strcasecmp(v->name, "msgexpirytime")) {
1011  if (!sscanf(v->value, "%30ld", &msg_expiry)) {
1012  ast_log(LOG_NOTICE, "Invalid msgexpirytime value in %s (line %d), using default\n", config_file, v->lineno);
1013  msg_expiry = SMDI_MSG_EXPIRY_TIME;
1014  }
1015  } else if (!strcasecmp(v->name, "paritybit")) {
1016  if (!strcasecmp(v->value, "even"))
1017  paritybit = PARENB;
1018  else if (!strcasecmp(v->value, "odd"))
1019  paritybit = PARENB | PARODD;
1020  else if (!strcasecmp(v->value, "none"))
1021  paritybit = ~PARENB;
1022  else {
1023  ast_log(LOG_NOTICE, "Invalid parity bit setting in %s (line %d), using default\n", config_file, v->lineno);
1024  paritybit = PARENB;
1025  }
1026  } else if (!strcasecmp(v->name, "charsize")) {
1027  if (!strcasecmp(v->value, "7"))
1028  charsize = CS7;
1029  else if (!strcasecmp(v->value, "8"))
1030  charsize = CS8;
1031  else {
1032  ast_log(LOG_NOTICE, "Invalid character size setting in %s (line %d), using default\n", config_file, v->lineno);
1033  charsize = CS7;
1034  }
1035  } else if (!strcasecmp(v->name, "twostopbits")) {
1036  stopbits = ast_true(v->name);
1037  } else if (!strcasecmp(v->name, "smdiport")) {
1038  if (reload && old_ifaces) {
1039  /* we are reloading, check if we are already
1040  * monitoring this interface, if we are we do
1041  * not want to start it again. This also has
1042  * the side effect of not updating different
1043  * setting for the serial port, but it should
1044  * be trivial to rewrite this section so that
1045  * options on the port are changed without
1046  * restarting the interface. Or the interface
1047  * could be restarted with out emptying the
1048  * queue. */
1049  if ((iface = ao2_find(old_ifaces, v->value, OBJ_SEARCH_KEY))) {
1050  ast_log(LOG_NOTICE, "SMDI interface %s already running, not restarting\n", iface->name);
1051  ao2_link(new_ifaces, iface);
1052  continue;
1053  }
1054  }
1055 
1056  if (!(iface = alloc_smdi_interface()))
1057  continue;
1058 
1059  ast_copy_string(iface->name, v->value, sizeof(iface->name));
1060 
1061  iface->thread = AST_PTHREADT_NULL;
1062 
1063  if (!(iface->file = fopen(iface->name, "r"))) {
1064  ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s)\n", iface->name, strerror(errno));
1065  continue;
1066  }
1067 
1068  iface->fd = fileno(iface->file);
1069 
1070  /* Set the proper attributes for our serial port. */
1071 
1072  /* get the current attributes from the port */
1073  if (tcgetattr(iface->fd, &iface->mode)) {
1074  ast_log(LOG_ERROR, "Error getting atributes of %s (%s)\n", iface->name, strerror(errno));
1075  continue;
1076  }
1077 
1078  /* set the desired speed */
1079  if (cfsetispeed(&iface->mode, baud_rate) || cfsetospeed(&iface->mode, baud_rate)) {
1080  ast_log(LOG_ERROR, "Error setting baud rate on %s (%s)\n", iface->name, strerror(errno));
1081  continue;
1082  }
1083 
1084  /* set the stop bits */
1085  if (stopbits)
1086  iface->mode.c_cflag = iface->mode.c_cflag | CSTOPB; /* set two stop bits */
1087  else
1088  iface->mode.c_cflag = iface->mode.c_cflag & ~CSTOPB; /* set one stop bit */
1089 
1090  /* set the parity */
1091  iface->mode.c_cflag = (iface->mode.c_cflag & ~PARENB & ~PARODD) | paritybit;
1092 
1093  /* set the character size */
1094  iface->mode.c_cflag = (iface->mode.c_cflag & ~CSIZE) | charsize;
1095 
1096  /* commit the desired attributes */
1097  if (tcsetattr(iface->fd, TCSAFLUSH, &iface->mode)) {
1098  ast_log(LOG_ERROR, "Error setting attributes on %s (%s)\n", iface->name, strerror(errno));
1099  continue;
1100  }
1101 
1102  /* set the msdstrip */
1103  iface->msdstrip = msdstrip;
1104 
1105  /* set the message expiry time */
1106  iface->msg_expiry = msg_expiry;
1107 
1108  /*
1109  * start the listener thread
1110  *
1111  * The listener thread does not actually hold a ref to iface. When all
1112  * external refs go away, the destructor will stop the listener thread
1113  * before actually destroying the iface object.
1114  */
1115  ast_verb(3, "Starting SMDI monitor thread for %s\n", iface->name);
1116  if (ast_pthread_create_background(&iface->thread, NULL, smdi_read, iface)) {
1117  ast_log(LOG_ERROR, "Error starting SMDI monitor thread for %s\n", iface->name);
1118  continue;
1119  }
1120 
1121  ao2_link(new_ifaces, iface);
1123  } else {
1124  ast_log(LOG_NOTICE, "Ignoring unknown option %s in %s\n", v->name, config_file);
1125  }
1126  }
1127 
1129  mwi_monitor.polling_interval = DEFAULT_POLLING_INTERVAL;
1130 
1131  for (v = ast_variable_browse(conf, "mailboxes"); v; v = v->next) {
1132  if (!strcasecmp(v->name, "smdiport")) {
1133  ao2_cleanup(mailbox_iface);
1134 
1135  if (!(mailbox_iface = ao2_find(new_ifaces, v->value, OBJ_SEARCH_KEY))) {
1136  ast_log(LOG_NOTICE, "SMDI interface %s not found\n", v->value);
1137  continue;
1138  }
1139  } else if (!strcasecmp(v->name, "pollinginterval")) {
1140  if (sscanf(v->value, "%30u", &mwi_monitor.polling_interval) != 1) {
1141  ast_log(LOG_ERROR, "Invalid value for pollinginterval: %s\n", v->value);
1142  mwi_monitor.polling_interval = DEFAULT_POLLING_INTERVAL;
1143  }
1144  } else {
1145  if (!mailbox_iface) {
1146  ast_log(LOG_ERROR, "Mailbox mapping ignored, no valid SMDI interface specified in mailboxes section\n");
1147  continue;
1148  }
1149  append_mailbox_mapping(v, mailbox_iface);
1150  }
1151  }
1152  ao2_cleanup(mailbox_iface);
1153 
1154  ast_config_destroy(conf);
1155 
1156  ao2_global_obj_replace_unref(smdi_ifaces, new_ifaces);
1157 
1158  if (!AST_LIST_EMPTY(&mwi_monitor.mailbox_mappings) && mwi_monitor.thread == AST_PTHREADT_NULL
1160  ast_log(LOG_ERROR, "Failed to start MWI monitoring thread. This module will not operate.\n");
1161  return -1;
1162  }
1163 
1164  if (!ao2_container_count(new_ifaces)) {
1165  res = 1;
1166  }
1167 
1168  return res;
1169 }
struct ast_variable * next
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define CONFIG_STATUS_FILEINVALID
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
Structure for variables, used for configurations and for channel variables.
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
All configuration options for statsd client.
Definition: res_statsd.c:95
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
static void destroy_all_mailbox_mappings(void)
Definition: res_smdi.c:795
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
struct ast_module * self
Definition: module.h:342
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define DEFAULT_POLLING_INTERVAL
Definition: res_smdi.c:204
#define AST_PTHREADT_NULL
Definition: lock.h:66
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define CONFIG_STATUS_FILEUNCHANGED
#define LOG_ERROR
Definition: logger.h:285
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
static int smdi_ifaces_cmp_fn(void *obj, void *data, int flags)
Definition: res_smdi.c:934
int errno
#define LOG_NOTICE
Definition: logger.h:263
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
Structure used to handle boolean flags.
Definition: utils.h:199
static void append_mailbox_mapping(struct ast_variable *var, struct ast_smdi_interface *iface)
Definition: res_smdi.c:805
#define ao2_global_obj_replace_unref(holder, obj)
Definition: astobj2.h:908
static void * mwi_monitor_handler(void *data)
Definition: res_smdi.c:852
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int reload(void)
Definition: res_smdi.c:1433
#define SMDI_MSG_EXPIRY_TIME
Definition: res_smdi.c:69
static void * smdi_read(void *iface_p)
Definition: res_smdi.c:586
static struct ast_smdi_interface * alloc_smdi_interface(void)
Definition: res_smdi.c:914
Generic container type.
static const char config_file[]
Definition: res_smdi.c:165
static struct @494 mwi_monitor
Data that gets used by the SMDI MWI monitoring thread.
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:443
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ smdi_md_q_cmp_fn()

static int smdi_md_q_cmp_fn ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 886 of file res_smdi.c.

References ast_strlen_zero, CMP_MATCH, ast_smdi_md_message::mesg_desk_num, ast_smdi_md_message::mesg_desk_term, ast_smdi_md_message::name, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, and OBJ_SEARCH_OBJECT.

Referenced by alloc_smdi_interface().

887 {
888  const struct ast_smdi_md_message *msg = obj;
889  const struct ast_smdi_md_message *search_msg = arg;
890  const char *search_key = arg;
891  int cmp = 0;
892 
893  switch (flags & OBJ_SEARCH_MASK) {
894  case OBJ_SEARCH_OBJECT:
895  if (!ast_strlen_zero(search_msg->mesg_desk_num)) {
896  cmp = strcmp(msg->mesg_desk_num, search_msg->mesg_desk_num);
897  }
898  if (!ast_strlen_zero(search_msg->mesg_desk_term)) {
899  cmp |= strcmp(msg->mesg_desk_term, search_msg->mesg_desk_term);
900  }
901  break;
902  case OBJ_SEARCH_KEY:
903  cmp = strcmp(msg->name, search_key);
904  break;
905  }
906 
907  if (cmp) {
908  return 0;
909  }
910 
911  return CMP_MATCH;
912 }
char name[SMDI_MESG_NAME_LEN]
Definition: smdi.h:66
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
char mesg_desk_num[SMDI_MESG_DESK_NUM_LEN+1]
Definition: smdi.h:67
#define ast_strlen_zero(foo)
Definition: strings.h:52
An SMDI message desk message.
Definition: smdi.h:65
char mesg_desk_term[SMDI_MESG_DESK_TERM_LEN+1]
Definition: smdi.h:68
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076

◆ smdi_message_wait()

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

480 {
481  struct timeval start;
482  long diff = 0;
483  void *msg;
484  ast_cond_t *cond = NULL;
485  ast_mutex_t *lock = NULL;
486 
487  switch (type) {
488  case SMDI_MWI:
489  cond = &iface->mwi_q_cond;
490  lock = &iface->mwi_q_lock;
491  break;
492  case SMDI_MD:
493  cond = &iface->md_q_cond;
494  lock = &iface->md_q_lock;
495  break;
496  }
497 
498  start = ast_tvnow();
499 
500  while (diff < timeout) {
501  struct timespec ts = { 0, };
502  struct timeval wait;
503 
504  lock_msg_q(iface, type);
505 
506  if ((msg = smdi_msg_find(iface, type, search_key, options))) {
507  unlock_msg_q(iface, type);
508  return msg;
509  }
510 
511  wait = ast_tvadd(start, ast_tv(0, timeout));
512  ts.tv_sec = wait.tv_sec;
513  ts.tv_nsec = wait.tv_usec * 1000;
514 
515  /* If there were no messages in the queue, then go to sleep until one
516  * arrives. */
517 
518  ast_cond_timedwait(cond, lock, &ts);
519 
520  if ((msg = smdi_msg_find(iface, type, search_key, options))) {
521  unlock_msg_q(iface, type);
522  return msg;
523  }
524 
525  unlock_msg_q(iface, type);
526 
527  /* check timeout */
528  diff = ast_tvdiff_ms(ast_tvnow(), start);
529  }
530 
531  return NULL;
532 }
static const char type[]
Definition: chan_ooh323.c:109
ast_mutex_t md_q_lock
Definition: res_smdi.c:170
static int unlock_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
Definition: res_smdi.c:336
static int timeout
Definition: cdr_mysql.c:86
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
static void * smdi_msg_find(struct ast_smdi_interface *iface, enum smdi_message_type type, const char *search_key, struct ast_flags options)
Definition: res_smdi.c:434
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define NULL
Definition: resample.c:96
pthread_cond_t ast_cond_t
Definition: lock.h:176
ast_cond_t mwi_q_cond
Definition: res_smdi.c:174
ast_mutex_t mwi_q_lock
Definition: res_smdi.c:173
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
ast_mutex_t lock
Definition: res_smdi.c:210
static int lock_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
Definition: res_smdi.c:324
ast_cond_t md_q_cond
Definition: res_smdi.c:171
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226
ast_cond_t cond
Definition: res_smdi.c:211
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
Structure for mutex and tracking information.
Definition: lock.h:135

◆ smdi_msg_datastore_destroy()

static void smdi_msg_datastore_destroy ( void *  data)
static

Definition at line 1177 of file res_smdi.c.

References ao2_cleanup, ast_free, smdi_msg_datastore::iface, and smdi_msg_datastore::md_msg.

Referenced by smdi_msg_retrieve_read().

1178 {
1179  struct smdi_msg_datastore *smd = data;
1180 
1181  ao2_cleanup(smd->iface);
1182  ao2_cleanup(smd->md_msg);
1183 
1184  ast_free(smd);
1185 }
struct ast_smdi_interface * iface
Definition: res_smdi.c:1173
#define ast_free(a)
Definition: astmm.h:182
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_smdi_md_message * md_msg
Definition: res_smdi.c:1174

◆ smdi_msg_find()

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

References ao2_callback, ao2_find, ast_strlen_zero, ast_test_flag, ast_smdi_interface::md_q, ast_smdi_md_message::mesg_desk_num, ast_smdi_md_message::mesg_desk_term, ast_smdi_interface::mwi_q, ast_smdi_md_message::name, NULL, OBJ_SEARCH_KEY, OBJ_SEARCH_OBJECT, OPT_SEARCH_NUMBER, OPT_SEARCH_TERMINAL, purge_old_messages(), SMDI_MD, SMDI_MESG_DESK_NUM_LEN, SMDI_MESG_DESK_TERM_LEN, and SMDI_MWI.

Referenced by smdi_message_wait().

436 {
437  void *msg = NULL;
438 
439  purge_old_messages(iface, type);
440 
441  switch (type) {
442  case SMDI_MD:
443  if (ast_strlen_zero(search_key)) {
444  /* No search key provided (the code from chan_dahdi does this).
445  * Just pop the top message off of the queue. */
446 
447  msg = ao2_callback(iface->md_q, 0, NULL, NULL);
448  } else if (ast_test_flag(&options, OPT_SEARCH_TERMINAL)) {
449  /* Searching by the message desk terminal */
450  struct ast_smdi_md_message md_msg = { .name = "" };
451  strncpy(md_msg.mesg_desk_term, search_key, SMDI_MESG_DESK_TERM_LEN);
452  msg = ao2_find(iface->md_q, &md_msg, OBJ_SEARCH_OBJECT);
453  } else if (ast_test_flag(&options, OPT_SEARCH_NUMBER)) {
454  /* Searching by the message desk number */
455  struct ast_smdi_md_message md_msg = { .name = "" };
456  strncpy(md_msg.mesg_desk_num, search_key, SMDI_MESG_DESK_NUM_LEN);
457  msg = ao2_find(iface->md_q, &md_msg, OBJ_SEARCH_OBJECT);
458  } else {
459  /* Searching by the forwarding station */
460  msg = ao2_find(iface->md_q, search_key, OBJ_SEARCH_KEY);
461  }
462  break;
463  case SMDI_MWI:
464  if (ast_strlen_zero(search_key)) {
465  /* No search key provided (the code from chan_dahdi does this).
466  * Just pop the top message off of the queue. */
467 
468  msg = ao2_callback(iface->mwi_q, 0, NULL, NULL);
469  } else {
470  msg = ao2_find(iface->mwi_q, search_key, OBJ_SEARCH_KEY);
471  }
472  break;
473  }
474 
475  return msg;
476 }
static const char type[]
Definition: chan_ooh323.c:109
char name[SMDI_MESG_NAME_LEN]
Definition: smdi.h:66
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_test_flag(p, flag)
Definition: utils.h:63
static void purge_old_messages(struct ast_smdi_interface *iface, enum smdi_message_type type)
Definition: res_smdi.c:375
char mesg_desk_num[SMDI_MESG_DESK_NUM_LEN+1]
Definition: smdi.h:67
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define SMDI_MESG_DESK_NUM_LEN
Definition: smdi.h:38
#define SMDI_MESG_DESK_TERM_LEN
Definition: smdi.h:39
An SMDI message desk message.
Definition: smdi.h:65
char mesg_desk_term[SMDI_MESG_DESK_TERM_LEN+1]
Definition: smdi.h:68
struct ao2_container * mwi_q
Definition: res_smdi.c:172
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
struct ao2_container * md_q
Definition: res_smdi.c:169

◆ smdi_msg_pop()

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

Definition at line 416 of file res_smdi.c.

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

417 {
418  void *msg;
419 
420  purge_old_messages(iface, type);
421 
422  lock_msg_q(iface, type);
423  msg = unlink_from_msg_q(iface, type);
424  unlock_msg_q(iface, type);
425 
426  return msg;
427 }
static const char type[]
Definition: chan_ooh323.c:109
static int unlock_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
Definition: res_smdi.c:336
static void purge_old_messages(struct ast_smdi_interface *iface, enum smdi_message_type type)
Definition: res_smdi.c:375
static void * unlink_from_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
Definition: res_smdi.c:348
static int lock_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
Definition: res_smdi.c:324

◆ smdi_msg_read()

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

Definition at line 1298 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, NULL, parse(), and ast_smdi_md_message::type.

1299 {
1300  struct ast_module_user *u;
1301  int res = -1;
1303  AST_APP_ARG(id);
1304  AST_APP_ARG(component);
1305  );
1306  char *parse;
1307  struct ast_datastore *datastore = NULL;
1308  struct smdi_msg_datastore *smd = NULL;
1309 
1310  u = ast_module_user_add(chan);
1311 
1312  if (!chan) {
1313  ast_log(LOG_ERROR, "SMDI_MSG can not be called without a channel\n");
1314  goto return_error;
1315  }
1316 
1317  if (ast_strlen_zero(data)) {
1318  ast_log(LOG_WARNING, "SMDI_MSG requires an argument\n");
1319  goto return_error;
1320  }
1321 
1322  parse = ast_strdupa(data);
1323  AST_STANDARD_APP_ARGS(args, parse);
1324 
1325  if (ast_strlen_zero(args.id)) {
1326  ast_log(LOG_WARNING, "ID must be supplied to SMDI_MSG\n");
1327  goto return_error;
1328  }
1329 
1330  if (ast_strlen_zero(args.component)) {
1331  ast_log(LOG_WARNING, "ID must be supplied to SMDI_MSG\n");
1332  goto return_error;
1333  }
1334 
1335  ast_channel_lock(chan);
1337  ast_channel_unlock(chan);
1338 
1339  if (!datastore) {
1340  ast_log(LOG_WARNING, "No SMDI message found for message ID '%s'\n", args.id);
1341  goto return_error;
1342  }
1343 
1344  smd = datastore->data;
1345 
1346  if (!strcasecmp(args.component, "number")) {
1348  } else if (!strcasecmp(args.component, "terminal")) {
1350  } else if (!strcasecmp(args.component, "station")) {
1351  ast_copy_string(buf, smd->md_msg->fwd_st, len);
1352  } else if (!strcasecmp(args.component, "callerid")) {
1354  } else if (!strcasecmp(args.component, "type")) {
1355  snprintf(buf, len, "%c", smd->md_msg->type);
1356  } else {
1357  ast_log(LOG_ERROR, "'%s' is not a valid message component for SMDI_MSG\n",
1358  args.component);
1359  goto return_error;
1360  }
1361 
1362  res = 0;
1363 
1364 return_error:
1366 
1367  return res;
1368 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:69
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char mesg_desk_num[SMDI_MESG_DESK_NUM_LEN+1]
Definition: smdi.h:67
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
char calling_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:70
#define LOG_WARNING
Definition: logger.h:274
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
const char * args
#define NULL
Definition: resample.c:96
static const struct ast_datastore_info smdi_msg_datastore_info
Definition: res_smdi.c:1187
#define ast_module_user_remove(user)
Definition: module.h:427
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_module_user_add(chan)
Definition: module.h:426
char mesg_desk_term[SMDI_MESG_DESK_TERM_LEN+1]
Definition: smdi.h:68
#define LOG_ERROR
Definition: logger.h:285
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
void * data
Definition: datastore.h:70
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
struct ast_smdi_md_message * md_msg
Definition: res_smdi.c:1174
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ smdi_msg_retrieve_read()

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

Definition at line 1202 of file res_smdi.c.

References ao2_bump, ao2_cleanup, 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_find(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, ast_datastore::data, smdi_msg_datastore::id, smdi_msg_datastore::iface, LOG_ERROR, LOG_WARNING, smdi_msg_datastore::md_msg, NULL, options, parse(), SMDI_MD, smdi_message_wait(), smdi_msg_datastore_destroy(), smdi_msg_ret_options, and SMDI_RETRIEVE_TIMEOUT_DEFAULT.

1203 {
1204  struct ast_module_user *u;
1206  AST_APP_ARG(port);
1207  AST_APP_ARG(search_key);
1210  );
1211  struct ast_flags options = { 0 };
1212  unsigned int timeout = SMDI_RETRIEVE_TIMEOUT_DEFAULT;
1213  int res = -1;
1214  char *parse = NULL;
1215  struct smdi_msg_datastore *smd = NULL;
1216  struct ast_datastore *datastore = NULL;
1217  struct ast_smdi_interface *iface = NULL;
1218  struct ast_smdi_md_message *md_msg = NULL;
1219 
1220  u = ast_module_user_add(chan);
1221 
1222  if (ast_strlen_zero(data)) {
1223  ast_log(LOG_ERROR, "SMDI_MSG_RETRIEVE requires an argument\n");
1224  goto return_error;
1225  }
1226 
1227  if (!chan) {
1228  ast_log(LOG_ERROR, "SMDI_MSG_RETRIEVE must be used with a channel\n");
1229  goto return_error;
1230  }
1231 
1232  ast_autoservice_start(chan);
1233 
1234  parse = ast_strdupa(data);
1235  AST_STANDARD_APP_ARGS(args, parse);
1236 
1237  if (ast_strlen_zero(args.port) || ast_strlen_zero(args.search_key)) {
1238  ast_log(LOG_ERROR, "Invalid arguments provided to SMDI_MSG_RETRIEVE\n");
1239  goto return_error;
1240  }
1241 
1242  if (!(iface = ast_smdi_interface_find(args.port))) {
1243  ast_log(LOG_ERROR, "SMDI port '%s' not found\n", args.port);
1244  goto return_error;
1245  }
1246 
1247  if (!ast_strlen_zero(args.options)) {
1248  ast_app_parse_options(smdi_msg_ret_options, &options, NULL, args.options);
1249  }
1250 
1251  if (!ast_strlen_zero(args.timeout)) {
1252  if (sscanf(args.timeout, "%30u", &timeout) != 1) {
1253  ast_log(LOG_ERROR, "'%s' is not a valid timeout\n", args.timeout);
1255  }
1256  }
1257 
1258  if (!(md_msg = smdi_message_wait(iface, timeout, SMDI_MD, args.search_key, options))) {
1259  ast_log(LOG_WARNING, "No SMDI message retrieved for search key '%s' after "
1260  "waiting %u ms.\n", args.search_key, timeout);
1261  goto return_error;
1262  }
1263 
1264  if (!(smd = ast_calloc(1, sizeof(*smd))))
1265  goto return_error;
1266 
1267  smd->iface = ao2_bump(iface);
1268  smd->md_msg = ao2_bump(md_msg);
1269  smd->id = ast_atomic_fetchadd_int((int *) &smdi_msg_id, 1);
1270  snprintf(buf, len, "%u", smd->id);
1271 
1272  if (!(datastore = ast_datastore_alloc(&smdi_msg_datastore_info, buf)))
1273  goto return_error;
1274 
1275  datastore->data = smd;
1276 
1277  ast_channel_lock(chan);
1278  ast_channel_datastore_add(chan, datastore);
1279  ast_channel_unlock(chan);
1280 
1281  res = 0;
1282 
1283 return_error:
1284  ao2_cleanup(iface);
1285  ao2_cleanup(md_msg);
1286 
1287  if (smd && !datastore)
1289 
1290  if (parse)
1291  ast_autoservice_stop(chan);
1292 
1294 
1295  return res;
1296 }
static const struct ast_app_option smdi_msg_ret_options[128]
Definition: res_smdi.c:1200
#define ast_channel_lock(chan)
Definition: channel.h:2945
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
static int timeout
Definition: cdr_mysql.c:86
Structure for a data store object.
Definition: datastore.h:68
const char * args
#define NULL
Definition: resample.c:96
static const struct ast_datastore_info smdi_msg_datastore_info
Definition: res_smdi.c:1187
struct ast_smdi_interface * iface
Definition: res_smdi.c:1173
#define ast_module_user_remove(user)
Definition: module.h:427
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_bump(obj)
Definition: astobj2.h:491
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)
Definition: res_smdi.c:478
#define SMDI_RETRIEVE_TIMEOUT_DEFAULT
Definition: res_smdi.c:1195
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
An SMDI message desk message.
Definition: smdi.h:65
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2906
#define ast_module_user_add(chan)
Definition: module.h:426
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
#define LOG_ERROR
Definition: logger.h:285
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static void smdi_msg_datastore_destroy(void *data)
Definition: res_smdi.c:1177
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
Structure used to handle boolean flags.
Definition: utils.h:199
static int smdi_msg_id
Definition: res_smdi.c:1192
void * data
Definition: datastore.h:70
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
unsigned int id
Definition: res_smdi.c:1172
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
struct ast_smdi_md_message * md_msg
Definition: res_smdi.c:1174
static struct test_options options
struct ast_smdi_interface *AST_OPTIONAL_API_NAME() ast_smdi_interface_find(const char *iface_name)
Find an SMDI interface with the specified name.
Definition: res_smdi.c:563
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ smdi_mwi_q_cmp_fn()

static int smdi_mwi_q_cmp_fn ( void *  obj,
void *  data,
int  flags 
)
static

Definition at line 879 of file res_smdi.c.

References CMP_MATCH, CMP_STOP, ast_smdi_mwi_message::name, and str.

Referenced by alloc_smdi_interface().

880 {
881  struct ast_smdi_mwi_message *msg = obj;
882  char *str = data;
883  return !strcmp(msg->name, str) ? CMP_MATCH | CMP_STOP : 0;
884 }
const char * str
Definition: app_jack.c:147
char name[SMDI_MESG_NAME_LEN]
Definition: smdi.h:52
An SMDI message waiting indicator message.
Definition: smdi.h:51

◆ smdi_read()

static void* smdi_read ( void *  iface_p)
static

Definition at line 586 of file res_smdi.c.

References ao2_alloc, ao2_ref, ast_copy_string(), ast_debug, ast_log, ast_smdi_md_message_push(), ast_smdi_mwi_message_push(), ast_tvnow(), c, ast_smdi_md_message::calling_st, ast_smdi_mwi_message::cause, ast_smdi_interface::file, ast_smdi_mwi_message::fwd_st, ast_smdi_md_message::fwd_st, LOG_ERROR, ast_smdi_md_message::mesg_desk_num, ast_smdi_md_message::mesg_desk_term, ast_smdi_interface::msdstrip, ast_smdi_mwi_message::name, ast_smdi_md_message::name, ast_smdi_interface::name, NULL, ast_smdi_mwi_message::timestamp, ast_smdi_md_message::timestamp, and ast_smdi_md_message::type.

Referenced by smdi_load().

587 {
588  struct ast_smdi_interface *iface = iface_p;
589  struct ast_smdi_md_message *md_msg;
590  struct ast_smdi_mwi_message *mwi_msg;
591  char *cp = NULL;
592  int i, c;
593  int start = 0;
594 
595  /* read an smdi message */
596  while ((c = fgetc(iface->file))) {
597 
598  /* check if this is the start of a message */
599  if (!start) {
600  if (c == 'M') {
601  ast_debug(1, "Read an 'M' to start an SMDI message\n");
602  start = 1;
603  }
604  continue;
605  }
606 
607  if (c == 'D') { /* MD message */
608  start = 0;
609 
610  ast_debug(1, "Read a 'D' ... it's an MD message.\n");
611 
612  md_msg = ao2_alloc(sizeof(*md_msg), NULL);
613  if (!md_msg) {
614  return NULL;
615  }
616 
617  /* read the message desk number */
618  for (i = 0; i < sizeof(md_msg->mesg_desk_num) - 1; i++) {
619  c = fgetc(iface->file);
620  if (c == EOF) {
621  ast_log(LOG_ERROR, "Unexpected EOF while reading MD message\n");
622  ao2_ref(md_msg, -1);
623  return NULL;
624  }
625  md_msg->mesg_desk_num[i] = (char) c;
626  ast_debug(1, "Read a '%c'\n", md_msg->mesg_desk_num[i]);
627  }
628 
629  md_msg->mesg_desk_num[sizeof(md_msg->mesg_desk_num) - 1] = '\0';
630 
631  ast_debug(1, "The message desk number is '%s'\n", md_msg->mesg_desk_num);
632 
633  /* read the message desk terminal number */
634  for (i = 0; i < sizeof(md_msg->mesg_desk_term) - 1; i++) {
635  c = fgetc(iface->file);
636  if (c == EOF) {
637  ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n");
638  ao2_ref(md_msg, -1);
639  return NULL;
640  }
641  md_msg->mesg_desk_term[i] = (char) c;
642  ast_debug(1, "Read a '%c'\n", md_msg->mesg_desk_term[i]);
643  }
644 
645  md_msg->mesg_desk_term[sizeof(md_msg->mesg_desk_term) - 1] = '\0';
646 
647  ast_debug(1, "The message desk terminal is '%s'\n", md_msg->mesg_desk_term);
648 
649  /* read the message type */
650  c = fgetc(iface->file);
651  if (c == EOF) {
652  ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n");
653  ao2_ref(md_msg, -1);
654  return NULL;
655  }
656  md_msg->type = (char) c;
657 
658  ast_debug(1, "Message type is '%c'\n", md_msg->type);
659 
660  /* read the forwarding station number (may be blank) */
661  cp = &md_msg->fwd_st[0];
662  for (i = 0; i < sizeof(md_msg->fwd_st) - 1; i++) {
663  if ((c = fgetc(iface->file)) == ' ') {
664  *cp = '\0';
665  ast_debug(1, "Read a space, done looking for the forwarding station\n");
666  break;
667  }
668 
669  /* store c in md_msg->fwd_st */
670  if (i >= iface->msdstrip) {
671  ast_debug(1, "Read a '%c' and stored it in the forwarding station buffer\n", c);
672  *cp++ = c;
673  } else {
674  ast_debug(1, "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);
675  }
676  }
677 
678  /* make sure the value is null terminated, even if this truncates it */
679  md_msg->fwd_st[sizeof(md_msg->fwd_st) - 1] = '\0';
680  cp = NULL;
681 
682  ast_debug(1, "The forwarding station is '%s'\n", md_msg->fwd_st);
683 
684  /* Put the fwd_st in the name field so that we can use ao2_find to look
685  * up a message on this field */
686  ast_copy_string(md_msg->name, md_msg->fwd_st, sizeof(md_msg->name));
687 
688  /* read the calling station number (may be blank) */
689  cp = &md_msg->calling_st[0];
690  for (i = 0; i < sizeof(md_msg->calling_st) - 1; i++) {
691  if (!isdigit((c = fgetc(iface->file)))) {
692  *cp = '\0';
693  ast_debug(1, "Read a '%c', but didn't store it in the calling station buffer because it's not a digit\n", c);
694  if (c == ' ') {
695  /* Don't break on a space. We may read the space before the calling station
696  * here if the forwarding station buffer filled up. */
697  i--; /* We're still on the same character */
698  continue;
699  }
700  break;
701  }
702 
703  /* store c in md_msg->calling_st */
704  if (i >= iface->msdstrip) {
705  ast_debug(1, "Read a '%c' and stored it in the calling station buffer\n", c);
706  *cp++ = c;
707  } else {
708  ast_debug(1, "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);
709  }
710  }
711 
712  /* make sure the value is null terminated, even if this truncates it */
713  md_msg->calling_st[sizeof(md_msg->calling_st) - 1] = '\0';
714  cp = NULL;
715 
716  ast_debug(1, "The calling station is '%s'\n", md_msg->calling_st);
717 
718  /* add the message to the message queue */
719  md_msg->timestamp = ast_tvnow();
720  ast_smdi_md_message_push(iface, md_msg);
721  ast_debug(1, "Received SMDI MD message on %s\n", iface->name);
722 
723  ao2_ref(md_msg, -1);
724 
725  } else if (c == 'W') { /* MWI message */
726  start = 0;
727 
728  ast_debug(1, "Read a 'W', it's an MWI message. (No more debug coming for MWI messages)\n");
729 
730  mwi_msg = ao2_alloc(sizeof(*mwi_msg), NULL);
731  if (!mwi_msg) {
732  return NULL;
733  }
734 
735  /* discard the 'I' (from 'MWI') */
736  fgetc(iface->file);
737 
738  /* read the forwarding station number (may be blank) */
739  cp = &mwi_msg->fwd_st[0];
740  for (i = 0; i < sizeof(mwi_msg->fwd_st) - 1; i++) {
741  if ((c = fgetc(iface->file)) == ' ') {
742  *cp = '\0';
743  break;
744  }
745 
746  /* store c in md_msg->fwd_st */
747  if (i >= iface->msdstrip)
748  *cp++ = c;
749  }
750 
751  /* make sure the station number is null terminated, even if this will truncate it */
752  mwi_msg->fwd_st[sizeof(mwi_msg->fwd_st) - 1] = '\0';
753  cp = NULL;
754 
755  /* Put the fwd_st in the name field so that we can use ao2_find to look
756  * up a message on this field */
757  ast_copy_string(mwi_msg->name, mwi_msg->fwd_st, sizeof(mwi_msg->name));
758 
759  /* read the mwi failure cause */
760  for (i = 0; i < sizeof(mwi_msg->cause) - 1; i++) {
761  c = fgetc(iface->file);
762  if (c == EOF) {
763  ast_log(LOG_ERROR, "Unexpected EOF while reading MWI message\n");
764  ao2_ref(mwi_msg, -1);
765  return NULL;
766  }
767  mwi_msg->cause[i] = (char) c;
768  }
769 
770  mwi_msg->cause[sizeof(mwi_msg->cause) - 1] = '\0';
771 
772  /* add the message to the message queue */
773  mwi_msg->timestamp = ast_tvnow();
774  ast_smdi_mwi_message_push(iface, mwi_msg);
775  ast_debug(1, "Received SMDI MWI message on %s\n", iface->name);
776 
777  ao2_ref(mwi_msg, -1);
778  } else {
779  ast_log(LOG_ERROR, "Unknown SMDI message type received on %s (M%c).\n", iface->name, c);
780  start = 0;
781  }
782  }
783 
784  ast_log(LOG_ERROR, "Error reading from SMDI interface %s, stopping listener thread\n", iface->name);
785  return NULL;
786 }
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:69
char name[SMDI_MESG_NAME_LEN]
Definition: smdi.h:66
char name[SMDI_MAX_FILENAME_LEN]
Definition: res_smdi.c:168
char mesg_desk_num[SMDI_MESG_DESK_NUM_LEN+1]
Definition: smdi.h:67
char calling_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:70
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
static struct test_val c
#define NULL
Definition: resample.c:96
char name[SMDI_MESG_NAME_LEN]
Definition: smdi.h:52
char cause[SMDI_MWI_FAIL_CAUSE_LEN+1]
Definition: smdi.h:54
static void ast_smdi_mwi_message_push(struct ast_smdi_interface *iface, struct ast_smdi_mwi_message *mwi_msg)
Definition: res_smdi.c:274
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
An SMDI message desk message.
Definition: smdi.h:65
char mesg_desk_term[SMDI_MESG_DESK_TERM_LEN+1]
Definition: smdi.h:68
#define LOG_ERROR
Definition: logger.h:285
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:53
struct timeval timestamp
Definition: smdi.h:55
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
struct timeval timestamp
Definition: smdi.h:72
static void ast_smdi_md_message_push(struct ast_smdi_interface *iface, struct ast_smdi_md_message *md_msg)
Definition: res_smdi.c:260
An SMDI message waiting indicator message.
Definition: smdi.h:51

◆ smdi_toggle_mwi()

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

Definition at line 282 of file res_smdi.c.

References ao2_unlock, ao2_wrlock, ast_debug, ast_log, errno, ast_smdi_interface::file, LOG_ERROR, ast_smdi_interface::msdstrip, and ast_smdi_interface::name.

Referenced by ast_smdi_mwi_set(), and ast_smdi_mwi_unset().

283 {
284  FILE *file;
285  int i;
286 
287  if (!(file = fopen(iface->name, "w"))) {
288  ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s) for writing\n", iface->name, strerror(errno));
289  return 1;
290  }
291 
292  ao2_wrlock(iface);
293 
294  fprintf(file, "%s:MWI ", on ? "OP" : "RMV");
295 
296  for (i = 0; i < iface->msdstrip; i++)
297  fprintf(file, "0");
298 
299  fprintf(file, "%s!\x04", mailbox);
300 
301  fclose(file);
302 
303  ao2_unlock(iface);
304  ast_debug(1, "Sent MWI set message for %s on %s\n", mailbox, iface->name);
305 
306  return 0;
307 }
char name[SMDI_MAX_FILENAME_LEN]
Definition: res_smdi.c:168
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ao2_wrlock(a)
Definition: astobj2.h:720
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
int errno

◆ unlink_from_msg_q()

static void* unlink_from_msg_q ( struct ast_smdi_interface iface,
enum smdi_message_type  type 
)
inlinestatic

Definition at line 348 of file res_smdi.c.

References ao2_callback, ast_smdi_interface::md_q, ast_smdi_interface::mwi_q, NULL, OBJ_UNLINK, SMDI_MD, and SMDI_MWI.

Referenced by purge_old_messages(), and smdi_msg_pop().

349 {
350  switch (type) {
351  case SMDI_MWI:
352  return ao2_callback(iface->mwi_q, OBJ_UNLINK, NULL, NULL);
353  case SMDI_MD:
354  return ao2_callback(iface->md_q, OBJ_UNLINK, NULL, NULL);
355  }
356 
357  return NULL;
358 }
static const char type[]
Definition: chan_ooh323.c:109
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define NULL
Definition: resample.c:96
struct ao2_container * mwi_q
Definition: res_smdi.c:172
struct ao2_container * md_q
Definition: res_smdi.c:169

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1380 of file res_smdi.c.

References ao2_global_obj_release, ast_cond_signal, ast_custom_function_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, destroy_all_mailbox_mappings(), and NULL.

Referenced by load_module(), and reload().

1381 {
1382  ao2_global_obj_release(smdi_ifaces);
1383 
1385 
1386  ast_mutex_lock(&mwi_monitor.lock);
1387  mwi_monitor.stop = 1;
1390 
1391  if (mwi_monitor.thread != AST_PTHREADT_NULL) {
1392  pthread_join(mwi_monitor.thread, NULL);
1393  }
1394 
1397 
1398  return 0;
1399 }
static struct ast_custom_function smdi_msg_retrieve_function
Definition: res_smdi.c:1370
#define ast_mutex_lock(a)
Definition: lock.h:187
static struct ast_custom_function smdi_msg_function
Definition: res_smdi.c:1375
#define NULL
Definition: resample.c:96
#define ast_cond_signal(cond)
Definition: lock.h:201
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static void destroy_all_mailbox_mappings(void)
Definition: res_smdi.c:795
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ao2_global_obj_release(holder)
Definition: astobj2.h:865
static struct @494 mwi_monitor
Data that gets used by the SMDI MWI monitoring thread.
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ unlock_msg_q()

static int unlock_msg_q ( struct ast_smdi_interface iface,
enum smdi_message_type  type 
)
inlinestatic

Definition at line 336 of file res_smdi.c.

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

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

337 {
338  switch (type) {
339  case SMDI_MWI:
340  return ast_mutex_unlock(&iface->mwi_q_lock);
341  case SMDI_MD:
342  return ast_mutex_unlock(&iface->md_q_lock);
343  }
344 
345  return -1;
346 }
static const char type[]
Definition: chan_ooh323.c:109
ast_mutex_t md_q_lock
Definition: res_smdi.c:170
ast_mutex_t mwi_q_lock
Definition: res_smdi.c:173
#define ast_mutex_unlock(a)
Definition: lock.h:188

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Simplified Message Desk Interface (SMDI) Resource" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
static

Definition at line 1452 of file res_smdi.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1452 of file res_smdi.c.

◆ cond

ast_cond_t cond

Definition at line 211 of file res_smdi.c.

Referenced by smdi_message_wait().

◆ config_file

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

Definition at line 165 of file res_smdi.c.

Referenced by smdi_load().

◆ first

struct mailbox_mapping* first

Definition at line 213 of file res_smdi.c.

◆ last

struct mailbox_mapping* last

Definition at line 213 of file res_smdi.c.

◆ last_poll

struct timeval last_poll

The time that the last poll began

Definition at line 219 of file res_smdi.c.

◆ lock

Definition at line 210 of file res_smdi.c.

Referenced by smdi_message_wait().

◆ mailbox_mappings

struct { ... } mailbox_mappings

A list of mailboxes that need to be monitored

◆ mwi_monitor

struct { ... } mwi_monitor
Initial value:
= {
.thread = AST_PTHREADT_NULL,
}
#define AST_PTHREADT_NULL
Definition: lock.h:66

Data that gets used by the SMDI MWI monitoring thread.

◆ polling_interval

unsigned int polling_interval

Polling Interval for checking mailbox status

Definition at line 215 of file res_smdi.c.

◆ smdi_msg_datastore_info

const struct ast_datastore_info smdi_msg_datastore_info
static
Initial value:
= {
.type = "SMDIMSG",
}
static void smdi_msg_datastore_destroy(void *data)
Definition: res_smdi.c:1177

Definition at line 1187 of file res_smdi.c.

◆ smdi_msg_function

struct ast_custom_function smdi_msg_function
static
Initial value:
= {
.name = "SMDI_MSG",
.read = smdi_msg_read,
}
static int smdi_msg_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: res_smdi.c:1298

Definition at line 1375 of file res_smdi.c.

◆ smdi_msg_id

int smdi_msg_id
static

Definition at line 1192 of file res_smdi.c.

◆ smdi_msg_ret_options

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

Definition at line 1200 of file res_smdi.c.

Referenced by smdi_msg_retrieve_read().

◆ smdi_msg_retrieve_function

struct ast_custom_function smdi_msg_retrieve_function
static
Initial value:
= {
.name = "SMDI_MSG_RETRIEVE",
}
static int smdi_msg_retrieve_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: res_smdi.c:1202

Definition at line 1370 of file res_smdi.c.

◆ stop

unsigned int stop

Set to 1 to tell the polling thread to stop

Definition at line 217 of file res_smdi.c.

◆ thread

pthread_t thread

The thread ID

Definition at line 209 of file res_smdi.c.