69#define SMDI_MSG_EXPIRY_TIME    30000  
  210#define DEFAULT_POLLING_INTERVAL 10 
  233    int mod_unref_defer = 0;
 
  236        pthread_cancel(iface->
thread);
 
  255    if (mod_unref_defer) {
 
 
  293    if (!(
file = fopen(iface->
name, 
"w"))) {
 
  300    fprintf(
file, 
"%s:MWI ", on ? 
"OP" : 
"RMV");
 
  302    for (i = 0; i < iface->
msdstrip; i++)
 
  305    fprintf(
file, 
"%s!\x04", mailbox);
 
  310    ast_debug(1, 
"Sent MWI set message for %s on %s\n", mailbox, iface->
name);
 
 
  399                "Message was %ld milliseconds too old.\n",
 
 
  487    struct timeval start;
 
  506    while (diff < timeout) {
 
  507        struct timespec ts = { 0, };
 
  518        ts.tv_sec = wait.tv_sec;
 
  519        ts.tv_nsec = wait.tv_usec * 1000;
 
 
  602    while ((
c = fgetc(iface->
file))) {
 
  607                ast_debug(1, 
"Read an 'M' to start an SMDI message\n");
 
  616            ast_debug(1, 
"Read a 'D' ... it's an MD message.\n");
 
  625                c = fgetc(iface->
file);
 
  641                c = fgetc(iface->
file);
 
  656            c = fgetc(iface->
file);
 
  662            md_msg->
type = (char) 
c;
 
  668            for (i = 0; i < 
sizeof(md_msg->
fwd_st) - 1; i++) {
 
  669                if ((
c = fgetc(iface->
file)) == 
' ') {
 
  671                    ast_debug(1, 
"Read a space, done looking for the forwarding station\n");
 
  677                    ast_debug(1, 
"Read a '%c' and stored it in the forwarding station buffer\n", 
c);
 
  680                    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);
 
  696            for (i = 0; i < 
sizeof(md_msg->
calling_st) - 1; i++) {
 
  697                if (!isdigit((
c = fgetc(iface->
file)))) {
 
  699                    ast_debug(1, 
"Read a '%c', but didn't store it in the calling station buffer because it's not a digit\n", 
c);
 
  711                    ast_debug(1, 
"Read a '%c' and stored it in the calling station buffer\n", 
c);
 
  714                    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);
 
  727            ast_debug(1, 
"Received SMDI MD message on %s\n", iface->
name);
 
  731        } 
else if (
c == 
'W') { 
 
  734            ast_debug(1, 
"Read a 'W', it's an MWI message. (No more debug coming for MWI messages)\n");
 
  746            for (i = 0; i < 
sizeof(mwi_msg->
fwd_st) - 1; i++) {
 
  747                if ((
c = fgetc(iface->
file)) == 
' ') {
 
  766            for (i = 0; i < 
sizeof(mwi_msg->
cause) - 1; i++) {
 
  767                c = fgetc(iface->
file);
 
  773                mwi_msg->
cause[i] = (char) 
c;
 
  776            mwi_msg->
cause[
sizeof(mwi_msg->
cause) - 1] = 
'\0';
 
  781            ast_debug(1, 
"Received SMDI MWI message on %s\n", iface->
name);
 
  790    ast_log(
LOG_ERROR, 
"Error reading from SMDI interface %s, stopping listener thread\n", iface->
name);
 
 
  861        struct timespec ts = { 0, };
 
  862        struct timeval polltime;
 
  875        ts.tv_sec = polltime.tv_sec;
 
  876        ts.tv_nsec = polltime.tv_usec * 1000;
 
 
  896    const char *search_key = arg;
 
  909        cmp = strcmp(msg->
name, search_key);
 
 
  969    speed_t baud_rate = B9600;     
 
  970    tcflag_t paritybit = PARENB;   
 
  971    tcflag_t charsize = CS7;       
 
  995        if (!strcasecmp(v->
name, 
"baudrate")) {
 
  996            if (!strcasecmp(v->
value, 
"9600"))
 
  998            else if (!strcasecmp(v->
value, 
"4800"))
 
 1000            else if (!strcasecmp(v->
value, 
"2400"))
 
 1002            else if (!strcasecmp(v->
value, 
"1200"))
 
 1008        } 
else if (!strcasecmp(v->
name, 
"msdstrip")) {
 
 1016        } 
else if (!strcasecmp(v->
name, 
"msgexpirytime")) {
 
 1021        } 
else if (!strcasecmp(v->
name, 
"paritybit")) {
 
 1022            if (!strcasecmp(v->
value, 
"even"))
 
 1024            else if (!strcasecmp(v->
value, 
"odd"))
 
 1025                paritybit = PARENB | PARODD;
 
 1026            else if (!strcasecmp(v->
value, 
"none"))
 
 1027                paritybit = ~PARENB;
 
 1032        } 
else if (!strcasecmp(v->
name, 
"charsize")) {
 
 1033            if (!strcasecmp(v->
value, 
"7"))
 
 1035            else if (!strcasecmp(v->
value, 
"8"))
 
 1041        } 
else if (!strcasecmp(v->
name, 
"twostopbits")) {
 
 1043        } 
else if (!strcasecmp(v->
name, 
"smdiport")) {
 
 1044            if (
reload && old_ifaces) {
 
 1069            if (!(iface->
file = fopen(iface->
name, 
"r"))) {
 
 1074            iface->
fd = fileno(iface->
file);
 
 1079            if (tcgetattr(iface->
fd, &iface->
mode)) {
 
 1085            if (cfsetispeed(&iface->
mode, baud_rate) || cfsetospeed(&iface->
mode, baud_rate)) {
 
 1092                iface->
mode.c_cflag = iface->
mode.c_cflag | CSTOPB;   
 
 1094                iface->
mode.c_cflag = iface->
mode.c_cflag & ~CSTOPB;  
 
 1097            iface->
mode.c_cflag = (iface->
mode.c_cflag & ~PARENB & ~PARODD) | paritybit;
 
 1100            iface->
mode.c_cflag = (iface->
mode.c_cflag & ~CSIZE) | charsize;
 
 1103            if (tcsetattr(iface->
fd, TCSAFLUSH, &iface->
mode)) {
 
 1121            ast_verb(3, 
"Starting SMDI monitor thread for %s\n", iface->
name);
 
 1138        if (!strcasecmp(v->
name, 
"smdiport")) {
 
 1145        } 
else if (!strcasecmp(v->
name, 
"pollinginterval")) {
 
 1151            if (!mailbox_iface) {
 
 1152                ast_log(
LOG_ERROR, 
"Mailbox mapping ignored, no valid SMDI interface specified in mailboxes section\n");
 
 1166        ast_log(
LOG_ERROR, 
"Failed to start MWI monitoring thread.  This module will not operate.\n");
 
 
 1201#define SMDI_RETRIEVE_TIMEOUT_DEFAULT 3000 
 1258        if (sscanf(
args.timeout, 
"%30u", &timeout) != 1) {
 
 1266            "waiting %u ms.\n", 
args.search_key, timeout);
 
 1281    datastore->
data = smd;
 
 1293    if (smd && !datastore)
 
 
 1350    smd = datastore->
data;
 
 1352    if (!strcasecmp(
args.component, 
"number")) {
 
 1354    } 
else if (!strcasecmp(
args.component, 
"terminal")) {
 
 1356    } 
else if (!strcasecmp(
args.component, 
"station")) {
 
 1358    } 
else if (!strcasecmp(
args.component, 
"callerid")) {
 
 1360    } 
else if (!strcasecmp(
args.component, 
"type")) {
 
 
 1377    .
name = 
"SMDI_MSG_RETRIEVE",
 
 
 1429    } 
else if (res == 1) {
 
 1430        ast_log(
LOG_NOTICE, 
"No SMDI interfaces are available to listen on, not starting SMDI listener.\n");
 
 
 1446    } 
else if (res == 1) {
 
 1447        ast_log(
LOG_WARNING, 
"No SMDI interfaces were specified to listen on, not starting SDMI listener.\n");
 
 
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_calloc(num, len)
A wrapper for calloc()
#define AO2_GLOBAL_OBJ_STATIC(name)
Define a global object holder to be used to hold an ao2 object, statically initialized.
#define ao2_link(container, obj)
Add an object to a container.
@ AO2_ALLOC_OPT_LOCK_NOLOCK
@ AO2_ALLOC_OPT_LOCK_MUTEX
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
#define ao2_find(container, arg, flags)
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
@ OBJ_SEARCH_MASK
Search option field mask.
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
#define ao2_alloc(data_size, destructor_fn)
General Asterisk PBX channel definitions.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
#define ast_channel_lock(chan)
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
#define ast_channel_unlock(chan)
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.
#define ast_datastore_alloc(info, uid)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
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"....
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
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.
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
@ CONFIG_FLAG_FILEUNCHANGED
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
I/O Management (derived from Cheops-NG)
A set of macros to manage forward-linked lists.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Asterisk locking-related definitions:
#define ast_cond_destroy(cond)
#define AST_PTHREADT_NULL
#define ast_cond_init(cond, attr)
#define ast_cond_timedwait(cond, mutex, time)
#define ast_mutex_init(pmutex)
#define AST_PTHREADT_STOP
#define ast_mutex_unlock(a)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
#define ast_cond_broadcast(cond)
pthread_cond_t ast_cond_t
#define ast_mutex_destroy(a)
#define ast_mutex_lock(a)
#define ast_cond_signal(cond)
Asterisk module definitions.
@ AST_MODFLAG_GLOBAL_SYMBOLS
#define ast_module_unref(mod)
Release a reference to the module.
#define ast_module_ref(mod)
Hold a reference to the module.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_CHANNEL_DEPEND
#define ast_module_user_remove(user)
@ AST_MODULE_SUPPORT_EXTENDED
#define ast_module_user_add(chan)
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
#define AST_OPTIONAL_API_NAME(name)
Expands to the name of the implementation function.
Core PBX routines and definitions.
#define ast_custom_function_register(acf)
Register a custom function.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static const struct ast_app_option smdi_msg_ret_options[128]
static void * smdi_msg_pop(struct ast_smdi_interface *iface, enum smdi_message_type type)
#define SMDI_MSG_EXPIRY_TIME
static struct ast_smdi_interface * alloc_smdi_interface(void)
static struct ast_custom_function smdi_msg_function
static int smdi_ifaces_cmp_fn(void *obj, void *data, int flags)
static struct timeval msg_timestamp(void *msg, enum smdi_message_type type)
#define DEFAULT_POLLING_INTERVAL
unsigned int polling_interval
#define SMDI_RETRIEVE_TIMEOUT_DEFAULT
static int smdi_md_q_cmp_fn(void *obj, void *arg, int flags)
static void ast_smdi_md_message_push(struct ast_smdi_interface *iface, struct ast_smdi_md_message *md_msg)
static void * smdi_msg_find(struct ast_smdi_interface *iface, enum smdi_message_type type, const char *search_key, struct ast_flags options)
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.
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox)
Unset the MWI indicator for a mailbox.
static void destroy_mailbox_mapping(struct mailbox_mapping *mm)
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.
static int smdi_msg_retrieve_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
Set the MWI indicator for a mailbox.
static void poll_mailbox(struct mailbox_mapping *mm)
static void smdi_interface_destroy(void *obj)
static struct @513 mwi_monitor
Data that gets used by the SMDI MWI monitoring thread.
static const struct ast_datastore_info smdi_msg_datastore_info
static void smdi_msg_datastore_destroy(void *data)
static int smdi_toggle_mwi(struct ast_smdi_interface *iface, const char *mailbox, int on)
static int smdi_msg_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static void * smdi_read(void *iface_p)
static void purge_old_messages(struct ast_smdi_interface *iface, enum smdi_message_type type)
static void ast_smdi_mwi_message_push(struct ast_smdi_interface *iface, struct ast_smdi_mwi_message *mwi_msg)
struct ast_smdi_md_message *AST_OPTIONAL_API_NAME() ast_smdi_md_message_pop(struct ast_smdi_interface *iface)
Get the next SMDI message from the queue.
static void destroy_all_mailbox_mappings(void)
static int lock_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
static void * mwi_monitor_handler(void *data)
static const char config_file[]
static void * unlink_from_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
static int load_module(void)
Load the module.
struct ast_smdi_interface *AST_OPTIONAL_API_NAME() ast_smdi_interface_find(const char *iface_name)
Find an SMDI interface with the specified name.
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 int unload_module(void)
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)
static struct ast_custom_function smdi_msg_retrieve_function
static int smdi_load(int reload)
static void append_mailbox_mapping(struct ast_variable *var, struct ast_smdi_interface *iface)
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.
static int unlock_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
static int smdi_mwi_q_cmp_fn(void *obj, void *data, int flags)
struct @513::@516 mailbox_mappings
SMDI support for Asterisk.
#define SMDI_MESG_DESK_TERM_LEN
#define SMDI_MESG_DESK_NUM_LEN
#define SMDI_MAX_FILENAME_LEN
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
#define AST_STRING_FIELD(name)
Declare a string field.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Main Channel structure associated with a channel.
Data structure associated with a custom dialplan function.
Structure for a data store type.
Structure for a data store object.
Structure used to handle boolean flags.
Structure for mutex and tracking information.
char name[SMDI_MAX_FILENAME_LEN]
struct ao2_container * mwi_q
struct ao2_container * md_q
An SMDI message desk message.
char mesg_desk_term[SMDI_MESG_DESK_TERM_LEN+1]
char name[SMDI_MESG_NAME_LEN]
char calling_st[SMDI_MAX_STATION_NUM_LEN+1]
char mesg_desk_num[SMDI_MESG_DESK_NUM_LEN+1]
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
An SMDI message waiting indicator message.
char name[SMDI_MESG_NAME_LEN]
char cause[SMDI_MWI_FAIL_CAUSE_LEN+1]
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
All configuration options for http media cache.
A mapping between an SMDI mailbox ID and an Asterisk mailbox.
struct ast_smdi_interface * iface
const ast_string_field smdi
const ast_string_field context
struct mailbox_mapping::@515 entry
const ast_string_field mailbox
struct ast_smdi_interface * iface
struct ast_smdi_md_message * md_msg
Time-related functions and macros.
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
#define ast_test_flag(p, flag)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_pthread_create_background(a, b, c, d)