69#define SMDI_MSG_EXPIRY_TIME 30000
204#define DEFAULT_POLLING_INTERVAL 10
227 int mod_unref_defer = 0;
230 pthread_cancel(iface->
thread);
249 if (mod_unref_defer) {
287 if (!(
file = fopen(iface->
name,
"w"))) {
294 fprintf(
file,
"%s:MWI ", on ?
"OP" :
"RMV");
296 for (i = 0; i < iface->
msdstrip; i++)
393 "Message was %ld milliseconds too old.\n",
481 struct timeval start;
500 while (diff < timeout) {
501 struct timespec ts = { 0, };
512 ts.tv_sec = wait.tv_sec;
513 ts.tv_nsec = wait.tv_usec * 1000;
596 while ((
c = fgetc(iface->
file))) {
601 ast_debug(1,
"Read an 'M' to start an SMDI message\n");
610 ast_debug(1,
"Read a 'D' ... it's an MD message.\n");
619 c = fgetc(iface->
file);
635 c = fgetc(iface->
file);
650 c = fgetc(iface->
file);
656 md_msg->
type = (char)
c;
662 for (i = 0; i <
sizeof(md_msg->
fwd_st) - 1; i++) {
663 if ((
c = fgetc(iface->
file)) ==
' ') {
665 ast_debug(1,
"Read a space, done looking for the forwarding station\n");
671 ast_debug(1,
"Read a '%c' and stored it in the forwarding station buffer\n",
c);
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);
690 for (i = 0; i <
sizeof(md_msg->
calling_st) - 1; i++) {
691 if (!isdigit((
c = fgetc(iface->
file)))) {
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);
705 ast_debug(1,
"Read a '%c' and stored it in the calling station buffer\n",
c);
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);
721 ast_debug(1,
"Received SMDI MD message on %s\n", iface->
name);
725 }
else if (
c ==
'W') {
728 ast_debug(1,
"Read a 'W', it's an MWI message. (No more debug coming for MWI messages)\n");
740 for (i = 0; i <
sizeof(mwi_msg->
fwd_st) - 1; i++) {
741 if ((
c = fgetc(iface->
file)) ==
' ') {
760 for (i = 0; i <
sizeof(mwi_msg->
cause) - 1; i++) {
761 c = fgetc(iface->
file);
767 mwi_msg->
cause[i] = (char)
c;
770 mwi_msg->
cause[
sizeof(mwi_msg->
cause) - 1] =
'\0';
775 ast_debug(1,
"Received SMDI MWI message on %s\n", iface->
name);
784 ast_log(
LOG_ERROR,
"Error reading from SMDI interface %s, stopping listener thread\n", iface->
name);
855 struct timespec ts = { 0, };
856 struct timeval polltime;
869 ts.tv_sec = polltime.tv_sec;
870 ts.tv_nsec = polltime.tv_usec * 1000;
890 const char *search_key = arg;
903 cmp = strcmp(msg->
name, search_key);
963 speed_t baud_rate = B9600;
964 tcflag_t paritybit = PARENB;
965 tcflag_t charsize = CS7;
989 if (!strcasecmp(v->
name,
"baudrate")) {
990 if (!strcasecmp(v->
value,
"9600"))
992 else if (!strcasecmp(v->
value,
"4800"))
994 else if (!strcasecmp(v->
value,
"2400"))
996 else if (!strcasecmp(v->
value,
"1200"))
1002 }
else if (!strcasecmp(v->
name,
"msdstrip")) {
1010 }
else if (!strcasecmp(v->
name,
"msgexpirytime")) {
1015 }
else if (!strcasecmp(v->
name,
"paritybit")) {
1016 if (!strcasecmp(v->
value,
"even"))
1018 else if (!strcasecmp(v->
value,
"odd"))
1019 paritybit = PARENB | PARODD;
1020 else if (!strcasecmp(v->
value,
"none"))
1021 paritybit = ~PARENB;
1026 }
else if (!strcasecmp(v->
name,
"charsize")) {
1027 if (!strcasecmp(v->
value,
"7"))
1029 else if (!strcasecmp(v->
value,
"8"))
1035 }
else if (!strcasecmp(v->
name,
"twostopbits")) {
1037 }
else if (!strcasecmp(v->
name,
"smdiport")) {
1038 if (
reload && old_ifaces) {
1063 if (!(iface->
file = fopen(iface->
name,
"r"))) {
1068 iface->
fd = fileno(iface->
file);
1073 if (tcgetattr(iface->
fd, &iface->
mode)) {
1079 if (cfsetispeed(&iface->
mode, baud_rate) || cfsetospeed(&iface->
mode, baud_rate)) {
1086 iface->
mode.c_cflag = iface->
mode.c_cflag | CSTOPB;
1088 iface->
mode.c_cflag = iface->
mode.c_cflag & ~CSTOPB;
1091 iface->
mode.c_cflag = (iface->
mode.c_cflag & ~PARENB & ~PARODD) | paritybit;
1094 iface->
mode.c_cflag = (iface->
mode.c_cflag & ~CSIZE) | charsize;
1097 if (tcsetattr(iface->
fd, TCSAFLUSH, &iface->
mode)) {
1115 ast_verb(3,
"Starting SMDI monitor thread for %s\n", iface->
name);
1132 if (!strcasecmp(v->
name,
"smdiport")) {
1139 }
else if (!strcasecmp(v->
name,
"pollinginterval")) {
1145 if (!mailbox_iface) {
1146 ast_log(
LOG_ERROR,
"Mailbox mapping ignored, no valid SMDI interface specified in mailboxes section\n");
1160 ast_log(
LOG_ERROR,
"Failed to start MWI monitoring thread. This module will not operate.\n");
1195#define SMDI_RETRIEVE_TIMEOUT_DEFAULT 3000
1252 if (sscanf(
args.timeout,
"%30u", &timeout) != 1) {
1260 "waiting %u ms.\n",
args.search_key, timeout);
1275 datastore->
data = smd;
1287 if (smd && !datastore)
1344 smd = datastore->
data;
1346 if (!strcasecmp(
args.component,
"number")) {
1348 }
else if (!strcasecmp(
args.component,
"terminal")) {
1350 }
else if (!strcasecmp(
args.component,
"station")) {
1352 }
else if (!strcasecmp(
args.component,
"callerid")) {
1354 }
else if (!strcasecmp(
args.component,
"type")) {
1371 .
name =
"SMDI_MSG_RETRIEVE",
1423 }
else if (res == 1) {
1424 ast_log(
LOG_NOTICE,
"No SMDI interfaces are available to listen on, not starting SMDI listener.\n");
1440 }
else if (res == 1) {
1441 ast_log(
LOG_WARNING,
"No SMDI interfaces were specified to listen on, not starting SDMI listener.\n");
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_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.
char * strsep(char **str, const char *delims)
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.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
@ CONFIG_FLAG_FILEUNCHANGED
#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)
static struct @475 mwi_monitor
Data that gets used by the SMDI MWI monitoring thread.
#define DEFAULT_POLLING_INTERVAL
struct @475::@478 mailbox_mappings
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 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 AO2_GLOBAL_OBJ_STATIC(smdi_ifaces)
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)
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::@477 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)