57 #define AST_API_MODULE 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++)
299 fprintf(file,
"%s!\x04", mailbox);
304 ast_debug(1,
"Sent MWI set message for %s on %s\n", mailbox, iface->
name);
393 "Message was %ld milliseconds too old.\n",
481 struct timeval start;
500 while (diff < timeout) {
501 struct timespec ts = { 0, };
506 if ((msg =
smdi_msg_find(iface, type, search_key, options))) {
512 ts.tv_sec = wait.tv_sec;
513 ts.tv_nsec = wait.tv_usec * 1000;
520 if ((msg =
smdi_msg_find(iface, type, search_key, options))) {
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);
816 mailbox =
strsep(&context,
"@");
854 while (!mwi_monitor.stop) {
855 struct timespec ts = { 0, };
856 struct timeval polltime;
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;
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")) {
1003 if (!sscanf(v->
value,
"%30d", &msdstrip)) {
1006 }
else if (0 > msdstrip || msdstrip > 9) {
1010 }
else if (!strcasecmp(v->
name,
"msgexpirytime")) {
1011 if (!sscanf(v->
value,
"%30ld", &msg_expiry)) {
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")) {
1140 if (sscanf(v->
value,
"%30u", &mwi_monitor.polling_interval) != 1) {
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);
1270 snprintf(buf, len,
"%u", smd->
id);
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",
1387 mwi_monitor.stop = 1;
1392 pthread_join(mwi_monitor.thread,
NULL);
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");
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.
struct ast_variable * next
enum sip_cc_notify_state state
static const struct ast_app_option smdi_msg_ret_options[128]
#define ast_channel_lock(chan)
Main Channel structure associated with a channel.
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Asterisk locking-related definitions:
static int unlock_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
char name[SMDI_MESG_NAME_LEN]
static void * smdi_msg_pop(struct ast_smdi_interface *iface, enum smdi_message_type type)
static int smdi_load(int reload)
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
char name[SMDI_MAX_FILENAME_LEN]
static void smdi_interface_destroy(void *obj)
The arg parameter is a search key, but is not an object.
#define ast_test_flag(p, flag)
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
unsigned int polling_interval
const ast_string_field context
Time-related functions and macros.
static void purge_old_messages(struct ast_smdi_interface *iface, enum smdi_message_type type)
static void poll_mailbox(struct mailbox_mapping *mm)
static struct ast_custom_function smdi_msg_retrieve_function
char mesg_desk_num[SMDI_MESG_DESK_NUM_LEN+1]
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
char calling_st[SMDI_MAX_STATION_NUM_LEN+1]
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox)
Unset the MWI indicator for a mailbox.
#define ao2_callback(c, flags, cb_fn, arg)
#define CONFIG_STATUS_FILEINVALID
static void destroy_mailbox_mapping(struct mailbox_mapping *mm)
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Structure for variables, used for configurations and for channel variables.
static int smdi_msg_retrieve_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
#define SMDI_MAX_FILENAME_LEN
Structure for a data store type.
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
#define ast_cond_init(cond, attr)
#define ao2_global_obj_ref(holder)
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
static void * smdi_msg_find(struct ast_smdi_interface *iface, enum smdi_message_type type, const char *search_key, struct ast_flags options)
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define ast_mutex_lock(a)
A mapping between an SMDI mailbox ID and an Asterisk mailbox.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Structure for a data store object.
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.
static struct ast_custom_function smdi_msg_function
I/O Management (derived from Cheops-NG)
static int smdi_mwi_q_cmp_fn(void *obj, void *data, int flags)
static const struct ast_datastore_info smdi_msg_datastore_info
struct ast_smdi_interface * iface
#define ast_module_user_remove(user)
char name[SMDI_MESG_NAME_LEN]
#define ast_cond_signal(cond)
#define ast_verb(level,...)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static AO2_GLOBAL_OBJ_STATIC(smdi_ifaces)
#define ast_module_unref(mod)
Release a reference to the module.
pthread_cond_t ast_cond_t
#define ast_strlen_zero(foo)
char cause[SMDI_MWI_FAIL_CAUSE_LEN+1]
All configuration options for statsd client.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define ast_pthread_create_background(a, b, c, d)
static void ast_smdi_mwi_message_push(struct ast_smdi_interface *iface, struct ast_smdi_mwi_message *mwi_msg)
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)
Configuration File Parser.
static void destroy_all_mailbox_mappings(void)
static int smdi_md_q_cmp_fn(void *obj, void *arg, int flags)
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
#define SMDI_RETRIEVE_TIMEOUT_DEFAULT
#define ast_debug(level,...)
Log a DEBUG message.
#define SMDI_MESG_DESK_NUM_LEN
struct ast_smdi_interface * iface
#define ast_config_load(filename, flags)
Load a config file.
static struct timeval msg_timestamp(void *msg, enum smdi_message_type type)
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.
General Asterisk PBX channel definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define DEFAULT_POLLING_INTERVAL
#define AST_PTHREADT_NULL
Data structure associated with a custom dialplan function.
#define AST_STRING_FIELD(name)
Declare a string field.
#define ao2_ref(o, delta)
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
Set the MWI indicator for a mailbox.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
#define SMDI_MESG_DESK_TERM_LEN
#define ast_strdupa(s)
duplicate a string in memory from the stack
A set of macros to manage forward-linked lists.
#define ast_cond_broadcast(cond)
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
AST_LIST_HEAD_NOLOCK(contactliststruct, contact)
static int smdi_toggle_mwi(struct ast_smdi_interface *iface, const char *mailbox, int on)
An SMDI message desk message.
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.
#define ast_module_user_add(chan)
Core PBX routines and definitions.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
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.
#define CONFIG_STATUS_FILEUNCHANGED
char mesg_desk_term[SMDI_MESG_DESK_TERM_LEN+1]
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
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".
static void * unlink_from_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
#define ao2_global_obj_release(holder)
static int smdi_ifaces_cmp_fn(void *obj, void *data, int flags)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const ast_string_field mailbox
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
#define ast_cond_destroy(cond)
#define ao2_alloc(data_size, destructor_fn)
static void smdi_msg_datastore_destroy(void *data)
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)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
struct ao2_container * mwi_q
#define ast_channel_unlock(chan)
static void parse(struct mgcp_request *req)
#define ast_calloc(num, len)
A wrapper for calloc()
SMDI support for Asterisk.
Module has failed to load, may be in an inconsistent state.
#define ao2_find(container, arg, flags)
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Structure used to handle boolean flags.
static int unload_module(void)
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.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
static int lock_msg_q(struct ast_smdi_interface *iface, enum smdi_message_type type)
static int load_module(void)
Load the module.
static void append_mailbox_mapping(struct ast_variable *var, struct ast_smdi_interface *iface)
static int smdi_msg_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
#define ao2_global_obj_replace_unref(holder, obj)
The arg parameter is an object of the same type.
static void * mwi_monitor_handler(void *data)
char * strsep(char **str, const char *delims)
const ast_string_field smdi
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
#define AST_PTHREADT_STOP
#define SMDI_MSG_EXPIRY_TIME
static void * smdi_read(void *iface_p)
static struct ast_smdi_interface * alloc_smdi_interface(void)
#define ast_datastore_alloc(info, uid)
struct ast_smdi_md_message * md_msg
#define AST_OPTIONAL_API_NAME(name)
Expands to the name of the implementation function.
#define ast_mutex_init(pmutex)
Search option field mask.
static char context[AST_MAX_CONTEXT]
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
static void ast_smdi_md_message_push(struct ast_smdi_interface *iface, struct ast_smdi_md_message *md_msg)
#define ast_mutex_destroy(a)
struct ao2_container * md_q
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
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.
struct ast_smdi_interface *AST_OPTIONAL_API_NAME() ast_smdi_interface_find(const char *iface_name)
Find an SMDI interface with the specified name.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_cond_timedwait(cond, mutex, time)
#define ast_custom_function_register(acf)
Register a custom function.
static const char config_file[]
Structure for mutex and tracking information.
An SMDI message waiting indicator message.
static struct @494 mwi_monitor
Data that gets used by the SMDI MWI monitoring thread.
#define ast_mutex_unlock(a)
#define AST_APP_ARG(name)
Define an application argument.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
struct @494::@497 mailbox_mappings
#define ast_module_ref(mod)
Hold a reference to the module.
#define ao2_link(container, obj)