57 #define AST_API_MODULE
69 #define SMDI_MSG_EXPIRY_TIME 30000
168 char name[SMDI_MAX_FILENAME_LEN];
171 ast_cond_t md_q_cond;
174 ast_cond_t mwi_q_cond;
204 #define DEFAULT_POLLING_INTERVAL 10
221 .thread = AST_PTHREADT_NULL,
224 static void smdi_interface_destroy(
void *obj)
227 int mod_unref_defer = 0;
229 if (iface->thread != AST_PTHREADT_NULL && iface->thread != AST_PTHREADT_STOP) {
230 pthread_cancel(iface->thread);
231 pthread_join(iface->thread, NULL);
235 iface->thread = AST_PTHREADT_STOP;
241 ao2_cleanup(iface->md_q);
242 ast_mutex_destroy(&iface->md_q_lock);
243 ast_cond_destroy(&iface->md_q_cond);
245 ao2_cleanup(iface->mwi_q);
246 ast_mutex_destroy(&iface->mwi_q_lock);
247 ast_cond_destroy(&iface->mwi_q_cond);
249 if (mod_unref_defer) {
262 ast_mutex_lock(&iface->md_q_lock);
264 ast_cond_broadcast(&iface->md_q_cond);
265 ast_mutex_unlock(&iface->md_q_lock);
276 ast_mutex_lock(&iface->mwi_q_lock);
278 ast_cond_broadcast(&iface->mwi_q_cond);
279 ast_mutex_unlock(&iface->mwi_q_lock);
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));
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);
311 return smdi_toggle_mwi(iface, mailbox, 1);
316 return smdi_toggle_mwi(iface, mailbox, 0);
319 enum smdi_message_type {
324 static inline int lock_msg_q(
struct ast_smdi_interface *iface,
enum smdi_message_type type)
328 return ast_mutex_lock(&iface->mwi_q_lock);
330 return ast_mutex_lock(&iface->md_q_lock);
336 static inline int unlock_msg_q(
struct ast_smdi_interface *iface,
enum smdi_message_type type)
340 return ast_mutex_unlock(&iface->mwi_q_lock);
342 return ast_mutex_unlock(&iface->md_q_lock);
348 static inline void *unlink_from_msg_q(
struct ast_smdi_interface *iface,
enum smdi_message_type type)
360 static inline struct timeval msg_timestamp(void *msg,
enum smdi_message_type type)
367 return mwi_msg->timestamp;
369 return md_msg->timestamp;
375 static void purge_old_messages(
struct ast_smdi_interface *iface,
enum smdi_message_type type)
381 lock_msg_q(iface, type);
382 msg = unlink_from_msg_q(iface, type);
383 unlock_msg_q(iface, type);
389 if (elapsed > iface->msg_expiry) {
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);
397 lock_msg_q(iface, type);
398 msg = unlink_from_msg_q(iface, type);
399 unlock_msg_q(iface, type);
404 ast_smdi_md_message_push(iface, msg);
407 ast_smdi_mwi_message_push(iface, msg);
416 static void *smdi_msg_pop(
struct ast_smdi_interface *iface,
enum smdi_message_type type)
420 purge_old_messages(iface, type);
422 lock_msg_q(iface, type);
423 msg = unlink_from_msg_q(iface, type);
424 unlock_msg_q(iface, type);
430 OPT_SEARCH_TERMINAL = (1 << 0),
431 OPT_SEARCH_NUMBER = (1 << 1),
435 enum smdi_message_type type,
const char *search_key,
struct ast_flags options)
439 purge_old_messages(iface, type);
443 if (ast_strlen_zero(search_key)) {
448 }
else if (ast_test_flag(&options, OPT_SEARCH_TERMINAL)) {
451 strncpy(md_msg.mesg_desk_term, search_key, SMDI_MESG_DESK_TERM_LEN);
453 }
else if (ast_test_flag(&options, OPT_SEARCH_NUMBER)) {
456 strncpy(md_msg.mesg_desk_num, search_key, SMDI_MESG_DESK_NUM_LEN);
464 if (ast_strlen_zero(search_key)) {
479 enum smdi_message_type type,
const char *search_key,
struct ast_flags options)
481 struct timeval start;
484 ast_cond_t *cond = NULL;
489 cond = &iface->mwi_q_cond;
490 lock = &iface->mwi_q_lock;
493 cond = &iface->md_q_cond;
494 lock = &iface->md_q_lock;
500 while (diff < timeout) {
501 struct timespec ts = { 0, };
504 lock_msg_q(iface, type);
506 if ((msg = smdi_msg_find(iface, type, search_key, options))) {
507 unlock_msg_q(iface, type);
512 ts.tv_sec = wait.tv_sec;
513 ts.tv_nsec = wait.tv_usec * 1000;
518 ast_cond_timedwait(cond, lock, &ts);
520 if ((msg = smdi_msg_find(iface, type, search_key, options))) {
521 unlock_msg_q(iface, type);
525 unlock_msg_q(iface, type);
536 return smdi_msg_pop(iface, SMDI_MD);
542 return smdi_message_wait(iface, timeout, SMDI_MD, NULL, options);
547 return smdi_msg_pop(iface, SMDI_MWI);
553 return smdi_message_wait(iface, timeout, SMDI_MWI, NULL, options);
560 return smdi_message_wait(iface, timeout, SMDI_MWI, station, options);
586 static void *smdi_read(
void *iface_p)
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");
612 md_msg = ao2_alloc(
sizeof(*md_msg), NULL);
618 for (i = 0; i <
sizeof(md_msg->mesg_desk_num) - 1; i++) {
619 c = fgetc(iface->file);
621 ast_log(LOG_ERROR,
"Unexpected EOF while reading MD message\n");
625 md_msg->mesg_desk_num[i] = (char) c;
626 ast_debug(1,
"Read a '%c'\n", md_msg->mesg_desk_num[i]);
629 md_msg->mesg_desk_num[
sizeof(md_msg->mesg_desk_num) - 1] =
'\0';
631 ast_debug(1,
"The message desk number is '%s'\n", md_msg->mesg_desk_num);
634 for (i = 0; i <
sizeof(md_msg->mesg_desk_term) - 1; i++) {
635 c = fgetc(iface->file);
637 ast_log(LOG_ERROR,
"Unexpected EOF while reading SMDI message\n");
641 md_msg->mesg_desk_term[i] = (char) c;
642 ast_debug(1,
"Read a '%c'\n", md_msg->mesg_desk_term[i]);
645 md_msg->mesg_desk_term[
sizeof(md_msg->mesg_desk_term) - 1] =
'\0';
647 ast_debug(1,
"The message desk terminal is '%s'\n", md_msg->mesg_desk_term);
650 c = fgetc(iface->file);
652 ast_log(LOG_ERROR,
"Unexpected EOF while reading SMDI message\n");
656 md_msg->type = (char) c;
658 ast_debug(1,
"Message type is '%c'\n", md_msg->type);
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)) ==
' ') {
665 ast_debug(1,
"Read a space, done looking for the forwarding station\n");
670 if (i >= iface->msdstrip) {
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);
679 md_msg->fwd_st[
sizeof(md_msg->fwd_st) - 1] =
'\0';
682 ast_debug(1,
"The forwarding station is '%s'\n", md_msg->fwd_st);
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)))) {
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);
704 if (i >= iface->msdstrip) {
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);
713 md_msg->calling_st[
sizeof(md_msg->calling_st) - 1] =
'\0';
716 ast_debug(1,
"The calling station is '%s'\n", md_msg->calling_st);
720 ast_smdi_md_message_push(iface, md_msg);
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");
730 mwi_msg = ao2_alloc(
sizeof(*mwi_msg), NULL);
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)) ==
' ') {
747 if (i >= iface->msdstrip)
752 mwi_msg->fwd_st[
sizeof(mwi_msg->fwd_st) - 1] =
'\0';
757 ast_copy_string(mwi_msg->name, mwi_msg->fwd_st,
sizeof(mwi_msg->name));
760 for (i = 0; i <
sizeof(mwi_msg->cause) - 1; i++) {
761 c = fgetc(iface->file);
763 ast_log(LOG_ERROR,
"Unexpected EOF while reading MWI message\n");
767 mwi_msg->cause[i] = (char) c;
770 mwi_msg->cause[
sizeof(mwi_msg->cause) - 1] =
'\0';
774 ast_smdi_mwi_message_push(iface, mwi_msg);
775 ast_debug(1,
"Received SMDI MWI message on %s\n", iface->name);
779 ast_log(LOG_ERROR,
"Unknown SMDI message type received on %s (M%c).\n", iface->name, c);
784 ast_log(LOG_ERROR,
"Error reading from SMDI interface %s, stopping listener thread\n", iface->name);
795 static void destroy_all_mailbox_mappings(
void)
801 destroy_mailbox_mapping(mm);
816 mailbox = strsep(&context,
"@");
817 if (ast_strlen_zero(context))
852 static void *mwi_monitor_handler(
void *data)
855 struct timespec ts = { 0, };
856 struct timeval polltime;
869 ts.tv_sec = polltime.tv_sec;
870 ts.tv_nsec = polltime.tv_usec * 1000;
879 static
int smdi_mwi_q_cmp_fn(
void *obj,
void *data,
int flags)
886 static int smdi_md_q_cmp_fn(
void *obj,
void *arg,
int flags)
890 const char *search_key = arg;
895 if (!ast_strlen_zero(search_msg->mesg_desk_num)) {
896 cmp = strcmp(msg->mesg_desk_num, search_msg->mesg_desk_num);
898 if (!ast_strlen_zero(search_msg->mesg_desk_term)) {
899 cmp |= strcmp(msg->mesg_desk_term, search_msg->mesg_desk_term);
903 cmp = strcmp(msg->name, search_key);
918 if (!(iface = ao2_alloc(
sizeof(*iface), smdi_interface_destroy))) {
925 ast_mutex_init(&iface->md_q_lock);
926 ast_cond_init(&iface->md_q_cond, NULL);
928 ast_mutex_init(&iface->mwi_q_lock);
929 ast_cond_init(&iface->mwi_q_cond, NULL);
934 static int smdi_ifaces_cmp_fn(
void *obj,
void *data,
int flags)
952 static int smdi_load(
int reload)
963 speed_t baud_rate = B9600;
964 tcflag_t paritybit = PARENB;
965 tcflag_t charsize = CS7;
969 long msg_expiry = SMDI_MSG_EXPIRY_TIME;
973 ast_log(LOG_NOTICE,
"Unable to reload config %s: SMDI untouched\n",
config_file);
975 ast_log(LOG_NOTICE,
"Unable to load config %s: SMDI disabled\n",
config_file);
977 }
else if (conf == CONFIG_STATUS_FILEUNCHANGED)
986 for (v = ast_variable_browse(conf,
"interfaces"); v; v = v->
next) {
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"))
999 ast_log(LOG_NOTICE,
"Invalid baud rate '%s' specified in %s (line %d), using default\n", v->
value,
config_file, v->lineno);
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);
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);
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;
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;
1023 ast_log(LOG_NOTICE,
"Invalid parity bit setting in %s (line %d), using default\n",
config_file, v->lineno);
1026 }
else if (!strcasecmp(v->
name,
"charsize")) {
1027 if (!strcasecmp(v->
value,
"7"))
1029 else if (!strcasecmp(v->
value,
"8"))
1032 ast_log(LOG_NOTICE,
"Invalid character size setting in %s (line %d), using default\n",
config_file, v->lineno);
1035 }
else if (!strcasecmp(v->
name,
"twostopbits")) {
1037 }
else if (!strcasecmp(v->
name,
"smdiport")) {
1038 if (reload && old_ifaces) {
1050 ast_log(LOG_NOTICE,
"SMDI interface %s already running, not restarting\n", iface->name);
1056 if (!(iface = alloc_smdi_interface()))
1061 iface->thread = AST_PTHREADT_NULL;
1063 if (!(iface->file = fopen(iface->name,
"r"))) {
1064 ast_log(LOG_ERROR,
"Error opening SMDI interface %s (%s)\n", iface->name, strerror(errno));
1068 iface->fd = fileno(iface->file);
1073 if (tcgetattr(iface->fd, &iface->mode)) {
1074 ast_log(LOG_ERROR,
"Error getting attributes of %s (%s)\n", iface->name, strerror(errno));
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));
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)) {
1098 ast_log(LOG_ERROR,
"Error setting attributes on %s (%s)\n", iface->name, strerror(errno));
1103 iface->msdstrip = msdstrip;
1106 iface->msg_expiry = msg_expiry;
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);
1124 ast_log(LOG_NOTICE,
"Ignoring unknown option %s in %s\n", v->
name,
config_file);
1128 destroy_all_mailbox_mappings();
1131 for (v = ast_variable_browse(conf,
"mailboxes"); v; v = v->
next) {
1132 if (!strcasecmp(v->
name,
"smdiport")) {
1133 ao2_cleanup(mailbox_iface);
1136 ast_log(LOG_NOTICE,
"SMDI interface %s not found\n", v->
value);
1139 }
else if (!strcasecmp(v->
name,
"pollinginterval")) {
1141 ast_log(LOG_ERROR,
"Invalid value for pollinginterval: %s\n", v->
value);
1145 if (!mailbox_iface) {
1146 ast_log(LOG_ERROR,
"Mailbox mapping ignored, no valid SMDI interface specified in mailboxes section\n");
1149 append_mailbox_mapping(v, mailbox_iface);
1152 ao2_cleanup(mailbox_iface);
1159 && ast_pthread_create_background(&
mwi_monitor.thread, NULL, mwi_monitor_handler, NULL)) {
1160 ast_log(LOG_ERROR,
"Failed to start MWI monitoring thread. This module will not operate.\n");
1177 static void smdi_msg_datastore_destroy(
void *data)
1181 ao2_cleanup(smd->iface);
1182 ao2_cleanup(smd->md_msg);
1189 .destroy = smdi_msg_datastore_destroy,
1192 static int smdi_msg_id;
1195 #define SMDI_RETRIEVE_TIMEOUT_DEFAULT 3000
1202 static int smdi_msg_retrieve_read(
struct ast_channel *chan,
const char *cmd,
char *data,
char *buf,
size_t len)
1220 u = ast_module_user_add(chan);
1222 if (ast_strlen_zero(data)) {
1223 ast_log(LOG_ERROR,
"SMDI_MSG_RETRIEVE requires an argument\n");
1228 ast_log(LOG_ERROR,
"SMDI_MSG_RETRIEVE must be used with a channel\n");
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");
1243 ast_log(LOG_ERROR,
"SMDI port '%s' not found\n", args.port);
1247 if (!ast_strlen_zero(args.options)) {
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);
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);
1270 snprintf(buf, len,
"%u", smd->id);
1272 if (!(datastore = ast_datastore_alloc(&smdi_msg_datastore_info, buf)))
1275 datastore->
data = smd;
1277 ast_channel_lock(chan);
1279 ast_channel_unlock(chan);
1285 ao2_cleanup(md_msg);
1287 if (smd && !datastore)
1288 smdi_msg_datastore_destroy(smd);
1293 ast_module_user_remove(u);
1298 static int smdi_msg_read(
struct ast_channel *chan,
const char *cmd,
char *data,
char *buf,
size_t len)
1310 u = ast_module_user_add(chan);
1313 ast_log(LOG_ERROR,
"SMDI_MSG can not be called without a channel\n");
1317 if (ast_strlen_zero(data)) {
1318 ast_log(LOG_WARNING,
"SMDI_MSG requires an argument\n");
1325 if (ast_strlen_zero(args.id)) {
1326 ast_log(LOG_WARNING,
"ID must be supplied to SMDI_MSG\n");
1330 if (ast_strlen_zero(args.component)) {
1331 ast_log(LOG_WARNING,
"ID must be supplied to SMDI_MSG\n");
1335 ast_channel_lock(chan);
1337 ast_channel_unlock(chan);
1340 ast_log(LOG_WARNING,
"No SMDI message found for message ID '%s'\n", args.id);
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")) {
1355 snprintf(buf, len,
"%c", smd->md_msg->type);
1357 ast_log(LOG_ERROR,
"'%s' is not a valid message component for SMDI_MSG\n",
1365 ast_module_user_remove(u);
1371 .
name =
"SMDI_MSG_RETRIEVE",
1372 .read = smdi_msg_retrieve_read,
1377 .read = smdi_msg_read,
1380 static int unload_module(
void)
1384 destroy_all_mailbox_mappings();
1423 }
else if (res == 1) {
1424 ast_log(LOG_NOTICE,
"No SMDI interfaces are available to listen on, not starting SMDI listener.\n");
1433 static int reload(
void)
1440 }
else if (res == 1) {
1441 ast_log(LOG_WARNING,
"No SMDI interfaces were specified to listen on, not starting SDMI listener.\n");
1446 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER,
"Simplified Message Desk Interface (SMDI) Resource",
1447 .support_level = AST_MODULE_SUPPORT_EXTENDED,
1449 .unload = unload_module,
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
Main Channel structure associated with a channel.
Asterisk locking-related definitions:
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.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
The arg parameter is a search key, but is not an object.
unsigned int polling_interval
const ast_string_field context
Time-related functions and macros.
static void poll_mailbox(struct mailbox_mapping *mm)
struct @483::@486 mailbox_mappings
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
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)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Structure for variables, used for configurations and for channel variables.
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 ao2_global_obj_ref(holder)
Get a reference to the object stored in the global 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.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
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.
I/O Management (derived from Cheops-NG)
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.
All configuration options for http media cache.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Configuration File Parser.
static const char config_file[]
#define SMDI_RETRIEVE_TIMEOUT_DEFAULT
struct ast_smdi_interface * iface
#define ast_config_load(filename, flags)
Load a config file.
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 ast_strdupa(s)
duplicate a string in memory from the stack
#define DEFAULT_POLLING_INTERVAL
Data structure associated with a custom dialplan function.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define AST_STRING_FIELD(name)
Declare a string field.
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
Set the MWI indicator for a mailbox.
A set of macros to manage forward-linked lists.
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
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.
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 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_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".
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
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_module_ref(mod)
Hold a reference to the module.
#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.
#define ast_calloc(num, len)
A wrapper for calloc()
SMDI support for Asterisk.
Module has failed to load, may be in an inconsistent state.
Structure used to handle boolean flags.
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.
static int load_module(void)
Load the module.
#define ast_module_unref(mod)
Release a reference to the module.
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
The arg parameter is an object of the same type.
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_OPTIONAL_API_NAME(name)
Expands to the name of the implementation function.
Search option field mask.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
#define AO2_GLOBAL_OBJ_STATIC(name)
Define a global object holder to be used to hold an ao2 object, statically initialized.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
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_custom_function_register(acf)
Register a custom function.
Structure for mutex and tracking information.
An SMDI message waiting indicator message.
static struct @483 mwi_monitor
Data that gets used by the SMDI MWI monitoring thread.
#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.
#define ao2_link(container, obj)
Add an object to a container.