#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/astobj.h"
#include "asterisk/io.h"
#include "asterisk/stringfields.h"
#include "asterisk/linkedlists.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
Go to the source code of this file.
Data Structures | |
struct | ast_smdi_interface |
struct | ast_smdi_interface_container |
SMDI interface container. More... | |
struct | ast_smdi_md_queue |
SMDI message desk message queue. More... | |
struct | ast_smdi_mwi_queue |
SMDI message waiting indicator message queue. More... | |
struct | mailbox_mapping |
A mapping between an SMDI mailbox ID and an Asterisk mailbox. More... | |
struct | smdi_msg_datastore |
Defines | |
#define | AST_API_MODULE |
#define | DEFAULT_POLLING_INTERVAL 10 |
#define | SMDI_MSG_EXPIRY_TIME 30000 |
#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 int | _unload_module (int fromload) |
static struct ast_smdi_interface * | alloc_smdi_interface (void) |
static void | append_mailbox_mapping (struct ast_variable *var, struct ast_smdi_interface *iface) |
static void | ast_smdi_interface_destroy (struct ast_smdi_interface *iface) |
ast_smdi_interface *AST_OPTIONAL_API_NAME() | ast_smdi_interface_find (const char *iface_name) |
Find an SMDI interface with the specified name. | |
void AST_OPTIONAL_API_NAME() | ast_smdi_interface_unref (struct ast_smdi_interface *iface) |
void AST_OPTIONAL_API_NAME() | ast_smdi_md_message_destroy (struct ast_smdi_md_message *msg) |
ast_smdi_md_message destructor. | |
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 | ast_smdi_md_message_push (struct ast_smdi_interface *iface, struct ast_smdi_md_message *md_msg) |
void AST_OPTIONAL_API_NAME() | ast_smdi_md_message_putback (struct ast_smdi_interface *iface, struct ast_smdi_md_message *md_msg) |
Put an SMDI message back in the front of the queue. | |
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. | |
void AST_OPTIONAL_API_NAME() | ast_smdi_mwi_message_destroy (struct ast_smdi_mwi_message *msg) |
ast_smdi_mwi_message destructor. | |
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. | |
static void | ast_smdi_mwi_message_push (struct ast_smdi_interface *iface, struct ast_smdi_mwi_message *mwi_msg) |
void AST_OPTIONAL_API_NAME() | ast_smdi_mwi_message_putback (struct ast_smdi_interface *iface, struct ast_smdi_mwi_message *mwi_msg) |
Put an SMDI message back in the front of the queue. | |
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. | |
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. | |
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_all_mailbox_mappings (void) |
static void | destroy_mailbox_mapping (struct mailbox_mapping *mm) |
static int | load_module (void) |
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_load (int reload) |
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 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) |
static void | unref_msg (void *msg, 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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static const char | config_file [] = "smdi.conf" |
struct { | |
ast_cond_t cond | |
timeval last_poll | |
ast_mutex_t lock | |
struct { | |
mailbox_mapping * first | |
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. | |
static struct ast_smdi_interface_container | smdi_ifaces |
SMDI interface container. | |
static int | smdi_loaded |
static struct ast_datastore_info | smdi_msg_datastore_info |
static struct ast_custom_function | smdi_msg_function |
static int | smdi_msg_id |
static 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 |
Russell Bryant <russell@digium.com>
Definition in file res_smdi.c.
#define AST_API_MODULE |
Definition at line 46 of file res_smdi.c.
#define DEFAULT_POLLING_INTERVAL 10 |
10 seconds
Definition at line 207 of file res_smdi.c.
#define SMDI_MSG_EXPIRY_TIME 30000 |
#define SMDI_RETRIEVE_TIMEOUT_DEFAULT 3000 |
anonymous enum |
Definition at line 465 of file res_smdi.c.
00465 { 00466 OPT_SEARCH_TERMINAL = (1 << 0), 00467 OPT_SEARCH_NUMBER = (1 << 1), 00468 };
enum smdi_message_type |
static void __reg_module | ( | void | ) | [static] |
Definition at line 1479 of file res_smdi.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1479 of file res_smdi.c.
static int _unload_module | ( | int | fromload | ) | [static] |
Definition at line 1424 of file res_smdi.c.
References ast_cond_signal, ast_custom_function_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, ast_smdi_interface_destroy(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, destroy_all_mailbox_mappings(), mwi_monitor, smdi_ifaces, smdi_msg_function, and smdi_msg_retrieve_function.
Referenced by load_module(), and unload_module().
01425 { 01426 if (!smdi_loaded) { 01427 return 0; 01428 } 01429 01430 /* this destructor stops any running smdi_read threads */ 01431 ASTOBJ_CONTAINER_DESTROYALL(&smdi_ifaces, ast_smdi_interface_destroy); 01432 ASTOBJ_CONTAINER_DESTROY(&smdi_ifaces); 01433 01434 destroy_all_mailbox_mappings(); 01435 01436 ast_mutex_lock(&mwi_monitor.lock); 01437 mwi_monitor.stop = 1; 01438 ast_cond_signal(&mwi_monitor.cond); 01439 ast_mutex_unlock(&mwi_monitor.lock); 01440 01441 if (mwi_monitor.thread != AST_PTHREADT_NULL) { 01442 pthread_join(mwi_monitor.thread, NULL); 01443 } 01444 01445 if (!fromload) { 01446 ast_custom_function_unregister(&smdi_msg_retrieve_function); 01447 ast_custom_function_unregister(&smdi_msg_function); 01448 } 01449 01450 smdi_loaded = 0; 01451 return 0; 01452 }
static struct ast_smdi_interface* alloc_smdi_interface | ( | void | ) | [static] |
Definition at line 921 of file res_smdi.c.
References ast_calloc, ast_cond_init, ast_mutex_init, ASTOBJ_CONTAINER_INIT, and ASTOBJ_INIT.
00922 { 00923 struct ast_smdi_interface *iface; 00924 00925 if (!(iface = ast_calloc(1, sizeof(*iface)))) 00926 return NULL; 00927 00928 ASTOBJ_INIT(iface); 00929 ASTOBJ_CONTAINER_INIT(&iface->md_q); 00930 ASTOBJ_CONTAINER_INIT(&iface->mwi_q); 00931 00932 ast_mutex_init(&iface->md_q_lock); 00933 ast_cond_init(&iface->md_q_cond, NULL); 00934 00935 ast_mutex_init(&iface->mwi_q_lock); 00936 ast_cond_init(&iface->mwi_q_cond, NULL); 00937 00938 return iface; 00939 }
static void append_mailbox_mapping | ( | struct ast_variable * | var, | |
struct ast_smdi_interface * | iface | |||
) | [static] |
Definition at line 847 of file res_smdi.c.
References ast_calloc_with_stringfields, AST_LIST_INSERT_TAIL, ast_mutex_lock, ast_mutex_unlock, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ASTOBJ_REF, context, mailbox_mapping::entry, mailbox_mapping::iface, mailbox, mwi_monitor, mailbox_mapping::smdi, strsep(), and var.
00848 { 00849 struct mailbox_mapping *mm; 00850 char *mailbox, *context; 00851 00852 if (!(mm = ast_calloc_with_stringfields(1, struct mailbox_mapping, 32))) 00853 return; 00854 00855 ast_string_field_set(mm, smdi, var->name); 00856 00857 context = ast_strdupa(var->value); 00858 mailbox = strsep(&context, "@"); 00859 if (ast_strlen_zero(context)) 00860 context = "default"; 00861 00862 ast_string_field_set(mm, mailbox, mailbox); 00863 ast_string_field_set(mm, context, context); 00864 00865 mm->iface = ASTOBJ_REF(iface); 00866 00867 ast_mutex_lock(&mwi_monitor.lock); 00868 AST_LIST_INSERT_TAIL(&mwi_monitor.mailbox_mappings, mm, entry); 00869 ast_mutex_unlock(&mwi_monitor.lock); 00870 }
static void ast_smdi_interface_destroy | ( | struct ast_smdi_interface * | iface | ) | [static] |
Definition at line 227 of file res_smdi.c.
References ast_cond_destroy, ast_module_unref(), ast_mutex_destroy, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_smdi_md_message_destroy(), ast_smdi_mwi_message_destroy(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ast_smdi_interface::file, free, mailbox_mapping::iface, 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, and ast_smdi_interface::thread.
Referenced by _unload_module(), ast_smdi_interface_unref(), destroy_mailbox_mapping(), smdi_msg_datastore_destroy(), smdi_msg_retrieve_read(), and smdi_read().
00228 { 00229 if (iface->thread != AST_PTHREADT_NULL && iface->thread != AST_PTHREADT_STOP) { 00230 pthread_cancel(iface->thread); 00231 pthread_join(iface->thread, NULL); 00232 } 00233 00234 iface->thread = AST_PTHREADT_STOP; 00235 00236 if (iface->file) 00237 fclose(iface->file); 00238 00239 ASTOBJ_CONTAINER_DESTROYALL(&iface->md_q, ast_smdi_md_message_destroy); 00240 ASTOBJ_CONTAINER_DESTROYALL(&iface->mwi_q, ast_smdi_mwi_message_destroy); 00241 ASTOBJ_CONTAINER_DESTROY(&iface->md_q); 00242 ASTOBJ_CONTAINER_DESTROY(&iface->mwi_q); 00243 00244 ast_mutex_destroy(&iface->md_q_lock); 00245 ast_cond_destroy(&iface->md_q_cond); 00246 00247 ast_mutex_destroy(&iface->mwi_q_lock); 00248 ast_cond_destroy(&iface->mwi_q_cond); 00249 00250 free(iface); 00251 00252 ast_module_unref(ast_module_info->self); 00253 }
struct ast_smdi_interface* AST_OPTIONAL_API_NAME() ast_smdi_interface_find | ( | const char * | iface_name | ) |
Find an SMDI interface with the specified name.
iface_name | the name/port of the interface to search for. |
Definition at line 623 of file res_smdi.c.
References ASTOBJ_CONTAINER_FIND, and smdi_ifaces.
Referenced by load_config(), and smdi_msg_retrieve_read().
00624 { 00625 return (ASTOBJ_CONTAINER_FIND(&smdi_ifaces, iface_name)); 00626 }
void AST_OPTIONAL_API_NAME() ast_smdi_interface_unref | ( | struct ast_smdi_interface * | iface | ) |
Definition at line 255 of file res_smdi.c.
References ast_smdi_interface_destroy(), ASTOBJ_UNREF, and mailbox_mapping::iface.
Referenced by destroy_dahdi_pvt().
00256 { 00257 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00258 }
void AST_OPTIONAL_API_NAME() ast_smdi_md_message_destroy | ( | struct ast_smdi_md_message * | msg | ) |
ast_smdi_md_message destructor.
Definition at line 820 of file res_smdi.c.
References ast_free.
Referenced by __analog_ss_thread(), ast_smdi_interface_destroy(), smdi_msg_datastore_destroy(), smdi_msg_retrieve_read(), and unref_msg().
00821 { 00822 ast_free(msg); 00823 }
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.
iface | a pointer to the interface to use. |
Definition at line 594 of file res_smdi.c.
References SMDI_MD, and smdi_msg_pop().
00595 { 00596 return smdi_msg_pop(iface, SMDI_MD); 00597 }
static void ast_smdi_md_message_push | ( | struct ast_smdi_interface * | iface, | |
struct ast_smdi_md_message * | md_msg | |||
) | [static] |
Definition at line 266 of file res_smdi.c.
References ast_cond_broadcast, ast_mutex_lock, ast_mutex_unlock, ASTOBJ_CONTAINER_LINK_END, mailbox_mapping::iface, ast_smdi_interface::md_q, ast_smdi_interface::md_q_cond, and ast_smdi_interface::md_q_lock.
Referenced by purge_old_messages().
00267 { 00268 ast_mutex_lock(&iface->md_q_lock); 00269 ASTOBJ_CONTAINER_LINK_END(&iface->md_q, md_msg); 00270 ast_cond_broadcast(&iface->md_q_cond); 00271 ast_mutex_unlock(&iface->md_q_lock); 00272 }
void AST_OPTIONAL_API_NAME() ast_smdi_md_message_putback | ( | struct ast_smdi_interface * | iface, | |
struct ast_smdi_md_message * | msg | |||
) |
Put an SMDI message back in the front of the queue.
iface | a pointer to the interface to use. | |
msg | a pointer to the message to use. |
Definition at line 325 of file res_smdi.c.
References ast_cond_broadcast, ast_mutex_lock, ast_mutex_unlock, ASTOBJ_CONTAINER_LINK_START, mailbox_mapping::iface, ast_smdi_interface::md_q, ast_smdi_interface::md_q_cond, and ast_smdi_interface::md_q_lock.
00326 { 00327 ast_mutex_lock(&iface->md_q_lock); 00328 ASTOBJ_CONTAINER_LINK_START(&iface->md_q, md_msg); 00329 ast_cond_broadcast(&iface->md_q_cond); 00330 ast_mutex_unlock(&iface->md_q_lock); 00331 }
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.
iface | a pointer to the interface to use. | |
timeout | the time to wait before returning in milliseconds. |
Definition at line 599 of file res_smdi.c.
References SMDI_MD, and smdi_message_wait().
Referenced by __analog_ss_thread(), and analog_ss_thread().
00600 { 00601 struct ast_flags options = { 0 }; 00602 return smdi_message_wait(iface, timeout, SMDI_MD, NULL, options); 00603 }
void AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_destroy | ( | struct ast_smdi_mwi_message * | msg | ) |
ast_smdi_mwi_message destructor.
Definition at line 825 of file res_smdi.c.
References ast_free.
Referenced by ast_smdi_interface_destroy(), run_externnotify(), and unref_msg().
00826 { 00827 ast_free(msg); 00828 }
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.
iface | a pointer to the interface to use. |
Definition at line 605 of file res_smdi.c.
References smdi_msg_pop(), and SMDI_MWI.
00606 { 00607 return smdi_msg_pop(iface, SMDI_MWI); 00608 }
static void ast_smdi_mwi_message_push | ( | struct ast_smdi_interface * | iface, | |
struct ast_smdi_mwi_message * | mwi_msg | |||
) | [static] |
Definition at line 280 of file res_smdi.c.
References ast_cond_broadcast, ast_mutex_lock, ast_mutex_unlock, ASTOBJ_CONTAINER_LINK_END, mailbox_mapping::iface, ast_smdi_interface::mwi_q, ast_smdi_interface::mwi_q_cond, and ast_smdi_interface::mwi_q_lock.
Referenced by purge_old_messages().
00281 { 00282 ast_mutex_lock(&iface->mwi_q_lock); 00283 ASTOBJ_CONTAINER_LINK_END(&iface->mwi_q, mwi_msg); 00284 ast_cond_broadcast(&iface->mwi_q_cond); 00285 ast_mutex_unlock(&iface->mwi_q_lock); 00286 }
void AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_putback | ( | struct ast_smdi_interface * | iface, | |
struct ast_smdi_mwi_message * | msg | |||
) |
Put an SMDI message back in the front of the queue.
iface | a pointer to the interface to use. | |
msg | a pointer to the message to use. |
Definition at line 333 of file res_smdi.c.
References ast_cond_broadcast, ast_mutex_lock, ast_mutex_unlock, ASTOBJ_CONTAINER_LINK_START, mailbox_mapping::iface, ast_smdi_interface::mwi_q, ast_smdi_interface::mwi_q_cond, and ast_smdi_interface::mwi_q_lock.
00334 { 00335 ast_mutex_lock(&iface->mwi_q_lock); 00336 ASTOBJ_CONTAINER_LINK_START(&iface->mwi_q, mwi_msg); 00337 ast_cond_broadcast(&iface->mwi_q_cond); 00338 ast_mutex_unlock(&iface->mwi_q_lock); 00339 }
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.
iface | a pointer to the interface to use. | |
timeout | the time to wait before returning in milliseconds. |
Definition at line 610 of file res_smdi.c.
References smdi_message_wait(), and SMDI_MWI.
00611 { 00612 struct ast_flags options = { 0 }; 00613 return smdi_message_wait(iface, timeout, SMDI_MWI, NULL, options); 00614 }
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 616 of file res_smdi.c.
References smdi_message_wait(), and SMDI_MWI.
Referenced by run_externnotify().
00618 { 00619 struct ast_flags options = { 0 }; 00620 return smdi_message_wait(iface, timeout, SMDI_MWI, station, options); 00621 }
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_set | ( | struct ast_smdi_interface * | iface, | |
const char * | mailbox | |||
) |
Set the MWI indicator for a mailbox.
iface | the interface to use. | |
mailbox | the mailbox to use. |
Definition at line 315 of file res_smdi.c.
References mailbox_mapping::iface, mailbox_mapping::mailbox, and smdi_toggle_mwi().
Referenced by poll_mailbox(), and run_externnotify().
00316 { 00317 return smdi_toggle_mwi(iface, mailbox, 1); 00318 }
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_unset | ( | struct ast_smdi_interface * | iface, | |
const char * | mailbox | |||
) |
Unset the MWI indicator for a mailbox.
iface | the interface to use. | |
mailbox | the mailbox to use. |
Definition at line 320 of file res_smdi.c.
References mailbox_mapping::iface, mailbox_mapping::mailbox, and smdi_toggle_mwi().
Referenced by poll_mailbox(), and run_externnotify().
00321 { 00322 return smdi_toggle_mwi(iface, mailbox, 0); 00323 }
static void destroy_all_mailbox_mappings | ( | void | ) | [static] |
Definition at line 837 of file res_smdi.c.
References AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, destroy_mailbox_mapping(), mailbox_mapping::entry, and mwi_monitor.
Referenced by _unload_module().
00838 { 00839 struct mailbox_mapping *mm; 00840 00841 ast_mutex_lock(&mwi_monitor.lock); 00842 while ((mm = AST_LIST_REMOVE_HEAD(&mwi_monitor.mailbox_mappings, entry))) 00843 destroy_mailbox_mapping(mm); 00844 ast_mutex_unlock(&mwi_monitor.lock); 00845 }
static void destroy_mailbox_mapping | ( | struct mailbox_mapping * | mm | ) | [static] |
Definition at line 830 of file res_smdi.c.
References ast_smdi_interface_destroy(), ast_string_field_free_memory, ASTOBJ_UNREF, free, and mailbox_mapping::iface.
Referenced by destroy_all_mailbox_mappings().
00831 { 00832 ast_string_field_free_memory(mm); 00833 ASTOBJ_UNREF(mm->iface, ast_smdi_interface_destroy); 00834 free(mm); 00835 }
static int load_module | ( | void | ) | [static] |
Definition at line 1395 of file res_smdi.c.
References _unload_module(), ast_cond_init, ast_custom_function_register, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_mutex_init, ASTOBJ_CONTAINER_INIT, LOG_NOTICE, mwi_monitor, smdi_ifaces, smdi_load(), smdi_msg_function, and smdi_msg_retrieve_function.
01396 { 01397 int res; 01398 smdi_loaded = 1; 01399 01400 /* initialize our containers */ 01401 memset(&smdi_ifaces, 0, sizeof(smdi_ifaces)); 01402 ASTOBJ_CONTAINER_INIT(&smdi_ifaces); 01403 01404 ast_mutex_init(&mwi_monitor.lock); 01405 ast_cond_init(&mwi_monitor.cond, NULL); 01406 01407 /* load the config and start the listener threads*/ 01408 res = smdi_load(0); 01409 if (res < 0) { 01410 _unload_module(1); 01411 return res; 01412 } else if (res == 1) { 01413 _unload_module(1); 01414 ast_log(LOG_NOTICE, "No SMDI interfaces are available to listen on, not starting SMDI listener.\n"); 01415 return AST_MODULE_LOAD_DECLINE; 01416 } 01417 01418 ast_custom_function_register(&smdi_msg_retrieve_function); 01419 ast_custom_function_register(&smdi_msg_function); 01420 01421 return AST_MODULE_LOAD_SUCCESS; 01422 }
static int lock_msg_q | ( | struct ast_smdi_interface * | iface, | |
enum smdi_message_type | type | |||
) | [inline, static] |
Definition at line 346 of file res_smdi.c.
References ast_mutex_lock, mailbox_mapping::iface, 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().
00347 { 00348 switch (type) { 00349 case SMDI_MWI: 00350 return ast_mutex_lock(&iface->mwi_q_lock); 00351 case SMDI_MD: 00352 return ast_mutex_lock(&iface->md_q_lock); 00353 } 00354 00355 return -1; 00356 }
static struct timeval msg_timestamp | ( | void * | msg, | |
enum smdi_message_type | type | |||
) | [inline, static] |
Definition at line 381 of file res_smdi.c.
References ast_tv(), SMDI_MD, SMDI_MWI, ast_smdi_mwi_message::timestamp, and type.
Referenced by purge_old_messages().
00382 { 00383 struct ast_smdi_md_message *md_msg = msg; 00384 struct ast_smdi_mwi_message *mwi_msg = msg; 00385 00386 switch (type) { 00387 case SMDI_MWI: 00388 return mwi_msg->timestamp; 00389 case SMDI_MD: 00390 return md_msg->timestamp; 00391 } 00392 00393 return ast_tv(0, 0); 00394 }
static void* mwi_monitor_handler | ( | void * | data | ) | [static] |
Definition at line 894 of file res_smdi.c.
References ast_cond_timedwait, AST_LIST_TRAVERSE, ast_mutex_lock, ast_mutex_unlock, ast_tv(), ast_tvadd(), ast_tvnow(), mailbox_mapping::entry, mwi_monitor, and poll_mailbox().
00895 { 00896 while (!mwi_monitor.stop) { 00897 struct timespec ts = { 0, }; 00898 struct timeval polltime; 00899 struct mailbox_mapping *mm; 00900 00901 ast_mutex_lock(&mwi_monitor.lock); 00902 00903 mwi_monitor.last_poll = ast_tvnow(); 00904 00905 AST_LIST_TRAVERSE(&mwi_monitor.mailbox_mappings, mm, entry) 00906 poll_mailbox(mm); 00907 00908 /* Sleep up to the configured polling interval. Allow unload_module() 00909 * to signal us to wake up and exit. */ 00910 polltime = ast_tvadd(mwi_monitor.last_poll, ast_tv(mwi_monitor.polling_interval, 0)); 00911 ts.tv_sec = polltime.tv_sec; 00912 ts.tv_nsec = polltime.tv_usec * 1000; 00913 ast_cond_timedwait(&mwi_monitor.cond, &mwi_monitor.lock, &ts); 00914 00915 ast_mutex_unlock(&mwi_monitor.lock); 00916 } 00917 00918 return NULL; 00919 }
static void poll_mailbox | ( | struct mailbox_mapping * | mm | ) | [static] |
Definition at line 875 of file res_smdi.c.
References ast_app_has_voicemail(), ast_smdi_mwi_set(), ast_smdi_mwi_unset(), mailbox_mapping::context, mailbox_mapping::cur_state, mailbox_mapping::iface, mailbox_mapping::mailbox, and mailbox_mapping::smdi.
Referenced by mwi_monitor_handler().
00876 { 00877 char buf[1024]; 00878 unsigned int state; 00879 00880 snprintf(buf, sizeof(buf), "%s@%s", mm->mailbox, mm->context); 00881 00882 state = !!ast_app_has_voicemail(mm->mailbox, NULL); 00883 00884 if (state != mm->cur_state) { 00885 if (state) 00886 ast_smdi_mwi_set(mm->iface, mm->smdi); 00887 else 00888 ast_smdi_mwi_unset(mm->iface, mm->smdi); 00889 00890 mm->cur_state = state; 00891 } 00892 }
static void purge_old_messages | ( | struct ast_smdi_interface * | iface, | |
enum smdi_message_type | type | |||
) | [static] |
Definition at line 411 of file res_smdi.c.
References ast_log(), ast_smdi_md_message_push(), ast_smdi_mwi_message_push(), ast_tvdiff_ms(), ast_tvnow(), mailbox_mapping::iface, lock_msg_q(), LOG_NOTICE, ast_smdi_interface::msg_expiry, msg_timestamp(), ast_smdi_interface::name, SMDI_MD, SMDI_MWI, unlink_from_msg_q(), unlock_msg_q(), and unref_msg().
Referenced by smdi_msg_find(), and smdi_msg_pop().
00412 { 00413 struct timeval now = ast_tvnow(); 00414 long elapsed = 0; 00415 void *msg; 00416 00417 lock_msg_q(iface, type); 00418 msg = unlink_from_msg_q(iface, type); 00419 unlock_msg_q(iface, type); 00420 00421 /* purge old messages */ 00422 while (msg) { 00423 elapsed = ast_tvdiff_ms(now, msg_timestamp(msg, type)); 00424 00425 if (elapsed > iface->msg_expiry) { 00426 /* found an expired message */ 00427 unref_msg(msg, type); 00428 ast_log(LOG_NOTICE, "Purged expired message from %s SMDI %s message queue. " 00429 "Message was %ld milliseconds too old.\n", 00430 iface->name, (type == SMDI_MD) ? "MD" : "MWI", 00431 elapsed - iface->msg_expiry); 00432 00433 lock_msg_q(iface, type); 00434 msg = unlink_from_msg_q(iface, type); 00435 unlock_msg_q(iface, type); 00436 } else { 00437 /* good message, put it back and return */ 00438 switch (type) { 00439 case SMDI_MD: 00440 ast_smdi_md_message_push(iface, msg); 00441 break; 00442 case SMDI_MWI: 00443 ast_smdi_mwi_message_push(iface, msg); 00444 break; 00445 } 00446 unref_msg(msg, type); 00447 break; 00448 } 00449 } 00450 }
static int reload | ( | void | ) | [static] |
Definition at line 1459 of file res_smdi.c.
References ast_log(), LOG_WARNING, and smdi_load().
01460 { 01461 int res; 01462 01463 res = smdi_load(1); 01464 01465 if (res < 0) { 01466 return res; 01467 } else if (res == 1) { 01468 ast_log(LOG_WARNING, "No SMDI interfaces were specified to listen on, not starting SDMI listener.\n"); 01469 return 0; 01470 } else 01471 return 0; 01472 }
static int smdi_load | ( | int | reload | ) | [static] |
Definition at line 951 of file res_smdi.c.
References ast_config_load, ast_log(), ast_variable_browse(), ASTOBJ_CONTAINER_MARKALL, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, ast_variable::lineno, LOG_NOTICE, ast_variable::name, ast_variable::next, smdi_ifaces, SMDI_MSG_EXPIRY_TIME, and ast_variable::value.
Referenced by load_module(), and reload().
00952 { 00953 struct ast_config *conf; 00954 struct ast_variable *v; 00955 struct ast_smdi_interface *iface = NULL; 00956 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 00957 int res = 0; 00958 00959 /* Config options */ 00960 speed_t baud_rate = B9600; /* 9600 baud rate */ 00961 tcflag_t paritybit = PARENB; /* even parity checking */ 00962 tcflag_t charsize = CS7; /* seven bit characters */ 00963 int stopbits = 0; /* One stop bit */ 00964 00965 int msdstrip = 0; /* strip zero digits */ 00966 long msg_expiry = SMDI_MSG_EXPIRY_TIME; 00967 00968 if (!(conf = ast_config_load(config_file, config_flags)) || conf == CONFIG_STATUS_FILEINVALID) { 00969 if (reload) 00970 ast_log(LOG_NOTICE, "Unable to reload config %s: SMDI untouched\n", config_file); 00971 else 00972 ast_log(LOG_NOTICE, "Unable to load config %s: SMDI disabled\n", config_file); 00973 return 1; 00974 } else if (conf == CONFIG_STATUS_FILEUNCHANGED) 00975 return 0; 00976 00977 /* Mark all interfaces that we are listening on. We will unmark them 00978 * as we find them in the config file, this way we know any interfaces 00979 * still marked after we have finished parsing the config file should 00980 * be stopped. 00981 */ 00982 if (reload) 00983 ASTOBJ_CONTAINER_MARKALL(&smdi_ifaces); 00984 00985 for (v = ast_variable_browse(conf, "interfaces"); v; v = v->next) { 00986 if (!strcasecmp(v->name, "baudrate")) { 00987 if (!strcasecmp(v->value, "9600")) 00988 baud_rate = B9600; 00989 else if (!strcasecmp(v->value, "4800")) 00990 baud_rate = B4800; 00991 else if (!strcasecmp(v->value, "2400")) 00992 baud_rate = B2400; 00993 else if (!strcasecmp(v->value, "1200")) 00994 baud_rate = B1200; 00995 else { 00996 ast_log(LOG_NOTICE, "Invalid baud rate '%s' specified in %s (line %d), using default\n", v->value, config_file, v->lineno); 00997 baud_rate = B9600; 00998 } 00999 } else if (!strcasecmp(v->name, "msdstrip")) { 01000 if (!sscanf(v->value, "%30d", &msdstrip)) { 01001 ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno); 01002 msdstrip = 0; 01003 } else if (0 > msdstrip || msdstrip > 9) { 01004 ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno); 01005 msdstrip = 0; 01006 } 01007 } else if (!strcasecmp(v->name, "msgexpirytime")) { 01008 if (!sscanf(v->value, "%30ld", &msg_expiry)) { 01009 ast_log(LOG_NOTICE, "Invalid msgexpirytime value in %s (line %d), using default\n", config_file, v->lineno); 01010 msg_expiry = SMDI_MSG_EXPIRY_TIME; 01011 } 01012 } else if (!strcasecmp(v->name, "paritybit")) { 01013 if (!strcasecmp(v->value, "even")) 01014 paritybit = PARENB; 01015 else if (!strcasecmp(v->value, "odd")) 01016 paritybit = PARENB | PARODD; 01017 else if (!strcasecmp(v->value, "none")) 01018 paritybit = ~PARENB; 01019 else { 01020 ast_log(LOG_NOTICE, "Invalid parity bit setting in %s (line %d), using default\n", config_file, v->lineno); 01021 paritybit = PARENB; 01022 } 01023 } else if (!strcasecmp(v->name, "charsize")) { 01024 if (!strcasecmp(v->value, "7")) 01025 charsize = CS7; 01026 else if (!strcasecmp(v->value, "8")) 01027 charsize = CS8; 01028 else { 01029 ast_log(LOG_NOTICE, "Invalid character size setting in %s (line %d), using default\n", config_file, v->lineno); 01030 charsize = CS7; 01031 } 01032 } else if (!strcasecmp(v->name, "twostopbits")) { 01033 stopbits = ast_true(v->name); 01034 } else if (!strcasecmp(v->name, "smdiport")) { 01035 if (reload) { 01036 /* we are reloading, check if we are already 01037 * monitoring this interface, if we are we do 01038 * not want to start it again. This also has 01039 * the side effect of not updating different 01040 * setting for the serial port, but it should 01041 * be trivial to rewrite this section so that 01042 * options on the port are changed without 01043 * restarting the interface. Or the interface 01044 * could be restarted with out emptying the 01045 * queue. */ 01046 if ((iface = ASTOBJ_CONTAINER_FIND(&smdi_ifaces, v->value))) { 01047 ast_log(LOG_NOTICE, "SMDI interface %s already running, not restarting\n", iface->name); 01048 ASTOBJ_UNMARK(iface); 01049 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01050 continue; 01051 } 01052 } 01053 01054 if (!(iface = alloc_smdi_interface())) 01055 continue; 01056 01057 ast_copy_string(iface->name, v->value, sizeof(iface->name)); 01058 01059 iface->thread = AST_PTHREADT_NULL; 01060 01061 if (!(iface->file = fopen(iface->name, "r"))) { 01062 ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s)\n", iface->name, strerror(errno)); 01063 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01064 continue; 01065 } 01066 01067 iface->fd = fileno(iface->file); 01068 01069 /* Set the proper attributes for our serial port. */ 01070 01071 /* get the current attributes from the port */ 01072 if (tcgetattr(iface->fd, &iface->mode)) { 01073 ast_log(LOG_ERROR, "Error getting atributes of %s (%s)\n", iface->name, strerror(errno)); 01074 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01075 continue; 01076 } 01077 01078 /* set the desired speed */ 01079 if (cfsetispeed(&iface->mode, baud_rate) || cfsetospeed(&iface->mode, baud_rate)) { 01080 ast_log(LOG_ERROR, "Error setting baud rate on %s (%s)\n", iface->name, strerror(errno)); 01081 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01082 continue; 01083 } 01084 01085 /* set the stop bits */ 01086 if (stopbits) 01087 iface->mode.c_cflag = iface->mode.c_cflag | CSTOPB; /* set two stop bits */ 01088 else 01089 iface->mode.c_cflag = iface->mode.c_cflag & ~CSTOPB; /* set one stop bit */ 01090 01091 /* set the parity */ 01092 iface->mode.c_cflag = (iface->mode.c_cflag & ~PARENB & ~PARODD) | paritybit; 01093 01094 /* set the character size */ 01095 iface->mode.c_cflag = (iface->mode.c_cflag & ~CSIZE) | charsize; 01096 01097 /* commit the desired attributes */ 01098 if (tcsetattr(iface->fd, TCSAFLUSH, &iface->mode)) { 01099 ast_log(LOG_ERROR, "Error setting attributes on %s (%s)\n", iface->name, strerror(errno)); 01100 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01101 continue; 01102 } 01103 01104 /* set the msdstrip */ 01105 iface->msdstrip = msdstrip; 01106 01107 /* set the message expiry time */ 01108 iface->msg_expiry = msg_expiry; 01109 01110 /* start the listener thread */ 01111 ast_verb(3, "Starting SMDI monitor thread for %s\n", iface->name); 01112 if (ast_pthread_create_background(&iface->thread, NULL, smdi_read, iface)) { 01113 ast_log(LOG_ERROR, "Error starting SMDI monitor thread for %s\n", iface->name); 01114 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01115 continue; 01116 } 01117 01118 ASTOBJ_CONTAINER_LINK(&smdi_ifaces, iface); 01119 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01120 ast_module_ref(ast_module_info->self); 01121 } else { 01122 ast_log(LOG_NOTICE, "Ignoring unknown option %s in %s\n", v->name, config_file); 01123 } 01124 } 01125 01126 destroy_all_mailbox_mappings(); 01127 mwi_monitor.polling_interval = DEFAULT_POLLING_INTERVAL; 01128 01129 iface = NULL; 01130 01131 for (v = ast_variable_browse(conf, "mailboxes"); v; v = v->next) { 01132 if (!strcasecmp(v->name, "smdiport")) { 01133 if (iface) 01134 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01135 01136 if (!(iface = ASTOBJ_CONTAINER_FIND(&smdi_ifaces, v->value))) { 01137 ast_log(LOG_NOTICE, "SMDI interface %s not found\n", v->value); 01138 continue; 01139 } 01140 } else if (!strcasecmp(v->name, "pollinginterval")) { 01141 if (sscanf(v->value, "%30u", &mwi_monitor.polling_interval) != 1) { 01142 ast_log(LOG_ERROR, "Invalid value for pollinginterval: %s\n", v->value); 01143 mwi_monitor.polling_interval = DEFAULT_POLLING_INTERVAL; 01144 } 01145 } else { 01146 if (!iface) { 01147 ast_log(LOG_ERROR, "Mailbox mapping ignored, no valid SMDI interface specified in mailboxes section\n"); 01148 continue; 01149 } 01150 append_mailbox_mapping(v, iface); 01151 } 01152 } 01153 01154 if (iface) 01155 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01156 01157 ast_config_destroy(conf); 01158 01159 if (!AST_LIST_EMPTY(&mwi_monitor.mailbox_mappings) && mwi_monitor.thread == AST_PTHREADT_NULL 01160 && ast_pthread_create_background(&mwi_monitor.thread, NULL, mwi_monitor_handler, NULL)) { 01161 ast_log(LOG_ERROR, "Failed to start MWI monitoring thread. This module will not operate.\n"); 01162 return AST_MODULE_LOAD_FAILURE; 01163 } 01164 01165 /* Prune any interfaces we should no longer monitor. */ 01166 if (reload) 01167 ASTOBJ_CONTAINER_PRUNE_MARKED(&smdi_ifaces, ast_smdi_interface_destroy); 01168 01169 ASTOBJ_CONTAINER_RDLOCK(&smdi_ifaces); 01170 /* TODO: this is bad, we need an ASTOBJ method for this! */ 01171 if (!smdi_ifaces.head) 01172 res = 1; 01173 ASTOBJ_CONTAINER_UNLOCK(&smdi_ifaces); 01174 01175 return res; 01176 }
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 538 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, 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().
00540 { 00541 struct timeval start; 00542 long diff = 0; 00543 void *msg; 00544 ast_cond_t *cond = NULL; 00545 ast_mutex_t *lock = NULL; 00546 00547 switch (type) { 00548 case SMDI_MWI: 00549 cond = &iface->mwi_q_cond; 00550 lock = &iface->mwi_q_lock; 00551 break; 00552 case SMDI_MD: 00553 cond = &iface->md_q_cond; 00554 lock = &iface->md_q_lock; 00555 break; 00556 } 00557 00558 start = ast_tvnow(); 00559 00560 while (diff < timeout) { 00561 struct timespec ts = { 0, }; 00562 struct timeval wait; 00563 00564 lock_msg_q(iface, type); 00565 00566 if ((msg = smdi_msg_find(iface, type, search_key, options))) { 00567 unlock_msg_q(iface, type); 00568 return msg; 00569 } 00570 00571 wait = ast_tvadd(start, ast_tv(0, timeout)); 00572 ts.tv_sec = wait.tv_sec; 00573 ts.tv_nsec = wait.tv_usec * 1000; 00574 00575 /* If there were no messages in the queue, then go to sleep until one 00576 * arrives. */ 00577 00578 ast_cond_timedwait(cond, lock, &ts); 00579 00580 if ((msg = smdi_msg_find(iface, type, search_key, options))) { 00581 unlock_msg_q(iface, type); 00582 return msg; 00583 } 00584 00585 unlock_msg_q(iface, type); 00586 00587 /* check timeout */ 00588 diff = ast_tvdiff_ms(ast_tvnow(), start); 00589 } 00590 00591 return NULL; 00592 }
static void smdi_msg_datastore_destroy | ( | void * | data | ) | [static] |
Definition at line 1184 of file res_smdi.c.
References ast_smdi_interface_destroy(), ast_smdi_md_message_destroy(), ASTOBJ_UNREF, free, smdi_msg_datastore::iface, and smdi_msg_datastore::md_msg.
Referenced by smdi_msg_retrieve_read().
01185 { 01186 struct smdi_msg_datastore *smd = data; 01187 01188 if (smd->iface) 01189 ASTOBJ_UNREF(smd->iface, ast_smdi_interface_destroy); 01190 01191 if (smd->md_msg) 01192 ASTOBJ_UNREF(smd->md_msg, ast_smdi_md_message_destroy); 01193 01194 free(smd); 01195 }
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 470 of file res_smdi.c.
References ast_strlen_zero(), ast_test_flag, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_REF, mailbox_mapping::iface, ast_smdi_interface::md_q, OPT_SEARCH_TERMINAL, purge_old_messages(), and SMDI_MD.
Referenced by smdi_message_wait().
00472 { 00473 void *msg = NULL; 00474 00475 purge_old_messages(iface, type); 00476 00477 switch (type) { 00478 case SMDI_MD: 00479 if (ast_strlen_zero(search_key)) { 00480 struct ast_smdi_md_message *md_msg = NULL; 00481 00482 /* No search key provided (the code from chan_dahdi does this). 00483 * Just pop the top message off of the queue. */ 00484 00485 ASTOBJ_CONTAINER_TRAVERSE(&iface->md_q, !md_msg, do { 00486 md_msg = ASTOBJ_REF(iterator); 00487 } while (0); ); 00488 00489 msg = md_msg; 00490 } else if (ast_test_flag(&options, OPT_SEARCH_TERMINAL)) { 00491 struct ast_smdi_md_message *md_msg = NULL; 00492 00493 /* Searching by the message desk terminal */ 00494 00495 ASTOBJ_CONTAINER_TRAVERSE(&iface->md_q, !md_msg, do { 00496 if (!strcasecmp(iterator->mesg_desk_term, search_key)) 00497 md_msg = ASTOBJ_REF(iterator); 00498 } while (0); ); 00499 00500 msg = md_msg; 00501 } else if (ast_test_flag(&options, OPT_SEARCH_NUMBER)) { 00502 struct ast_smdi_md_message *md_msg = NULL; 00503 00504 /* Searching by the message desk number */ 00505 00506 ASTOBJ_CONTAINER_TRAVERSE(&iface->md_q, !md_msg, do { 00507 if (!strcasecmp(iterator->mesg_desk_num, search_key)) 00508 md_msg = ASTOBJ_REF(iterator); 00509 } while (0); ); 00510 00511 msg = md_msg; 00512 } else { 00513 /* Searching by the forwarding station */ 00514 msg = ASTOBJ_CONTAINER_FIND(&iface->md_q, search_key); 00515 } 00516 break; 00517 case SMDI_MWI: 00518 if (ast_strlen_zero(search_key)) { 00519 struct ast_smdi_mwi_message *mwi_msg = NULL; 00520 00521 /* No search key provided (the code from chan_dahdi does this). 00522 * Just pop the top message off of the queue. */ 00523 00524 ASTOBJ_CONTAINER_TRAVERSE(&iface->mwi_q, !mwi_msg, do { 00525 mwi_msg = ASTOBJ_REF(iterator); 00526 } while (0); ); 00527 00528 msg = mwi_msg; 00529 } else { 00530 msg = ASTOBJ_CONTAINER_FIND(&iface->mwi_q, search_key); 00531 } 00532 break; 00533 } 00534 00535 return msg; 00536 }
static void* smdi_msg_pop | ( | struct ast_smdi_interface * | iface, | |
enum smdi_message_type | type | |||
) | [static] |
Definition at line 452 of file res_smdi.c.
References mailbox_mapping::iface, 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().
00453 { 00454 void *msg; 00455 00456 purge_old_messages(iface, type); 00457 00458 lock_msg_q(iface, type); 00459 msg = unlink_from_msg_q(iface, type); 00460 unlock_msg_q(iface, type); 00461 00462 return msg; 00463 }
static int smdi_msg_read | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 1311 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, parse(), smdi_msg_datastore_info, and ast_smdi_md_message::type.
01312 { 01313 struct ast_module_user *u; 01314 int res = -1; 01315 AST_DECLARE_APP_ARGS(args, 01316 AST_APP_ARG(id); 01317 AST_APP_ARG(component); 01318 ); 01319 char *parse; 01320 struct ast_datastore *datastore = NULL; 01321 struct smdi_msg_datastore *smd = NULL; 01322 01323 u = ast_module_user_add(chan); 01324 01325 if (!chan) { 01326 ast_log(LOG_ERROR, "SMDI_MSG can not be called without a channel\n"); 01327 goto return_error; 01328 } 01329 01330 if (ast_strlen_zero(data)) { 01331 ast_log(LOG_WARNING, "SMDI_MSG requires an argument\n"); 01332 goto return_error; 01333 } 01334 01335 parse = ast_strdupa(data); 01336 AST_STANDARD_APP_ARGS(args, parse); 01337 01338 if (ast_strlen_zero(args.id)) { 01339 ast_log(LOG_WARNING, "ID must be supplied to SMDI_MSG\n"); 01340 goto return_error; 01341 } 01342 01343 if (ast_strlen_zero(args.component)) { 01344 ast_log(LOG_WARNING, "ID must be supplied to SMDI_MSG\n"); 01345 goto return_error; 01346 } 01347 01348 ast_channel_lock(chan); 01349 datastore = ast_channel_datastore_find(chan, &smdi_msg_datastore_info, args.id); 01350 ast_channel_unlock(chan); 01351 01352 if (!datastore) { 01353 ast_log(LOG_WARNING, "No SMDI message found for message ID '%s'\n", args.id); 01354 goto return_error; 01355 } 01356 01357 smd = datastore->data; 01358 01359 if (!strcasecmp(args.component, "number")) { 01360 ast_copy_string(buf, smd->md_msg->mesg_desk_num, len); 01361 } else if (!strcasecmp(args.component, "terminal")) { 01362 ast_copy_string(buf, smd->md_msg->mesg_desk_term, len); 01363 } else if (!strcasecmp(args.component, "station")) { 01364 ast_copy_string(buf, smd->md_msg->fwd_st, len); 01365 } else if (!strcasecmp(args.component, "callerid")) { 01366 ast_copy_string(buf, smd->md_msg->calling_st, len); 01367 } else if (!strcasecmp(args.component, "type")) { 01368 snprintf(buf, len, "%c", smd->md_msg->type); 01369 } else { 01370 ast_log(LOG_ERROR, "'%s' is not a valid message component for SMDI_MSG\n", 01371 args.component); 01372 goto return_error; 01373 } 01374 01375 res = 0; 01376 01377 return_error: 01378 ast_module_user_remove(u); 01379 01380 return res; 01381 }
static int smdi_msg_retrieve_read | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 1212 of file res_smdi.c.
References 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_destroy(), ast_smdi_interface_find(), ast_smdi_md_message_destroy(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ASTOBJ_REF, ASTOBJ_UNREF, ast_datastore::data, LOG_ERROR, LOG_WARNING, parse(), SMDI_MD, smdi_message_wait(), smdi_msg_datastore_destroy(), smdi_msg_datastore_info, smdi_msg_ret_options, and SMDI_RETRIEVE_TIMEOUT_DEFAULT.
01213 { 01214 struct ast_module_user *u; 01215 AST_DECLARE_APP_ARGS(args, 01216 AST_APP_ARG(port); 01217 AST_APP_ARG(search_key); 01218 AST_APP_ARG(timeout); 01219 AST_APP_ARG(options); 01220 ); 01221 struct ast_flags options = { 0 }; 01222 unsigned int timeout = SMDI_RETRIEVE_TIMEOUT_DEFAULT; 01223 int res = -1; 01224 char *parse = NULL; 01225 struct smdi_msg_datastore *smd = NULL; 01226 struct ast_datastore *datastore = NULL; 01227 struct ast_smdi_interface *iface = NULL; 01228 struct ast_smdi_md_message *md_msg = NULL; 01229 01230 u = ast_module_user_add(chan); 01231 01232 if (ast_strlen_zero(data)) { 01233 ast_log(LOG_ERROR, "SMDI_MSG_RETRIEVE requires an argument\n"); 01234 goto return_error; 01235 } 01236 01237 if (!chan) { 01238 ast_log(LOG_ERROR, "SMDI_MSG_RETRIEVE must be used with a channel\n"); 01239 goto return_error; 01240 } 01241 01242 ast_autoservice_start(chan); 01243 01244 parse = ast_strdupa(data); 01245 AST_STANDARD_APP_ARGS(args, parse); 01246 01247 if (ast_strlen_zero(args.port) || ast_strlen_zero(args.search_key)) { 01248 ast_log(LOG_ERROR, "Invalid arguments provided to SMDI_MSG_RETRIEVE\n"); 01249 goto return_error; 01250 } 01251 01252 if (!(iface = ast_smdi_interface_find(args.port))) { 01253 ast_log(LOG_ERROR, "SMDI port '%s' not found\n", args.port); 01254 goto return_error; 01255 } 01256 01257 if (!ast_strlen_zero(args.options)) { 01258 ast_app_parse_options(smdi_msg_ret_options, &options, NULL, args.options); 01259 } 01260 01261 if (!ast_strlen_zero(args.timeout)) { 01262 if (sscanf(args.timeout, "%30u", &timeout) != 1) { 01263 ast_log(LOG_ERROR, "'%s' is not a valid timeout\n", args.timeout); 01264 timeout = SMDI_RETRIEVE_TIMEOUT_DEFAULT; 01265 } 01266 } 01267 01268 if (!(md_msg = smdi_message_wait(iface, timeout, SMDI_MD, args.search_key, options))) { 01269 ast_log(LOG_WARNING, "No SMDI message retrieved for search key '%s' after " 01270 "waiting %u ms.\n", args.search_key, timeout); 01271 goto return_error; 01272 } 01273 01274 if (!(smd = ast_calloc(1, sizeof(*smd)))) 01275 goto return_error; 01276 01277 smd->iface = ASTOBJ_REF(iface); 01278 smd->md_msg = ASTOBJ_REF(md_msg); 01279 smd->id = ast_atomic_fetchadd_int((int *) &smdi_msg_id, 1); 01280 snprintf(buf, len, "%u", smd->id); 01281 01282 if (!(datastore = ast_datastore_alloc(&smdi_msg_datastore_info, buf))) 01283 goto return_error; 01284 01285 datastore->data = smd; 01286 01287 ast_channel_lock(chan); 01288 ast_channel_datastore_add(chan, datastore); 01289 ast_channel_unlock(chan); 01290 01291 res = 0; 01292 01293 return_error: 01294 if (iface) 01295 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01296 01297 if (md_msg) 01298 ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy); 01299 01300 if (smd && !datastore) 01301 smdi_msg_datastore_destroy(smd); 01302 01303 if (parse) 01304 ast_autoservice_stop(chan); 01305 01306 ast_module_user_remove(u); 01307 01308 return res; 01309 }
static void* smdi_read | ( | void * | iface_p | ) | [static] |
Definition at line 637 of file res_smdi.c.
References ast_calloc, ast_copy_string(), ast_log(), ast_smdi_interface_destroy(), ASTOBJ_INIT, ASTOBJ_UNREF, ast_smdi_md_message::calling_st, ast_smdi_interface::file, ast_smdi_md_message::fwd_st, LOG_DEBUG, ast_smdi_interface::msdstrip, and ast_smdi_md_message::name.
00638 { 00639 struct ast_smdi_interface *iface = iface_p; 00640 struct ast_smdi_md_message *md_msg; 00641 struct ast_smdi_mwi_message *mwi_msg; 00642 char c = '\0'; 00643 char *cp = NULL; 00644 int i; 00645 int start = 0; 00646 00647 /* read an smdi message */ 00648 while ((c = fgetc(iface->file))) { 00649 00650 /* check if this is the start of a message */ 00651 if (!start) { 00652 if (c == 'M') { 00653 ast_log(LOG_DEBUG, "Read an 'M' to start an SMDI message\n"); 00654 start = 1; 00655 } 00656 continue; 00657 } 00658 00659 if (c == 'D') { /* MD message */ 00660 start = 0; 00661 00662 ast_log(LOG_DEBUG, "Read a 'D' ... it's an MD message.\n"); 00663 00664 if (!(md_msg = ast_calloc(1, sizeof(*md_msg)))) { 00665 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00666 return NULL; 00667 } 00668 00669 ASTOBJ_INIT(md_msg); 00670 00671 /* read the message desk number */ 00672 for (i = 0; i < sizeof(md_msg->mesg_desk_num) - 1; i++) { 00673 md_msg->mesg_desk_num[i] = fgetc(iface->file); 00674 ast_log(LOG_DEBUG, "Read a '%c'\n", md_msg->mesg_desk_num[i]); 00675 } 00676 00677 md_msg->mesg_desk_num[sizeof(md_msg->mesg_desk_num) - 1] = '\0'; 00678 00679 ast_log(LOG_DEBUG, "The message desk number is '%s'\n", md_msg->mesg_desk_num); 00680 00681 /* read the message desk terminal number */ 00682 for (i = 0; i < sizeof(md_msg->mesg_desk_term) - 1; i++) { 00683 md_msg->mesg_desk_term[i] = fgetc(iface->file); 00684 ast_log(LOG_DEBUG, "Read a '%c'\n", md_msg->mesg_desk_term[i]); 00685 } 00686 00687 md_msg->mesg_desk_term[sizeof(md_msg->mesg_desk_term) - 1] = '\0'; 00688 00689 ast_log(LOG_DEBUG, "The message desk terminal is '%s'\n", md_msg->mesg_desk_term); 00690 00691 /* read the message type */ 00692 md_msg->type = fgetc(iface->file); 00693 00694 ast_log(LOG_DEBUG, "Message type is '%c'\n", md_msg->type); 00695 00696 /* read the forwarding station number (may be blank) */ 00697 cp = &md_msg->fwd_st[0]; 00698 for (i = 0; i < sizeof(md_msg->fwd_st) - 1; i++) { 00699 if ((c = fgetc(iface->file)) == ' ') { 00700 *cp = '\0'; 00701 ast_log(LOG_DEBUG, "Read a space, done looking for the forwarding station\n"); 00702 break; 00703 } 00704 00705 /* store c in md_msg->fwd_st */ 00706 if (i >= iface->msdstrip) { 00707 ast_log(LOG_DEBUG, "Read a '%c' and stored it in the forwarding station buffer\n", c); 00708 *cp++ = c; 00709 } else { 00710 ast_log(LOG_DEBUG, "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); 00711 } 00712 } 00713 00714 /* make sure the value is null terminated, even if this truncates it */ 00715 md_msg->fwd_st[sizeof(md_msg->fwd_st) - 1] = '\0'; 00716 cp = NULL; 00717 00718 ast_log(LOG_DEBUG, "The forwarding station is '%s'\n", md_msg->fwd_st); 00719 00720 /* Put the fwd_st in the name field so that we can use ASTOBJ_FIND to look 00721 * up a message on this field */ 00722 ast_copy_string(md_msg->name, md_msg->fwd_st, sizeof(md_msg->name)); 00723 00724 /* read the calling station number (may be blank) */ 00725 cp = &md_msg->calling_st[0]; 00726 for (i = 0; i < sizeof(md_msg->calling_st) - 1; i++) { 00727 if (!isdigit((c = fgetc(iface->file)))) { 00728 *cp = '\0'; 00729 ast_log(LOG_DEBUG, "Read a '%c', but didn't store it in the calling station buffer because it's not a digit\n", c); 00730 if (c == ' ') { 00731 /* Don't break on a space. We may read the space before the calling station 00732 * here if the forwarding station buffer filled up. */ 00733 i--; /* We're still on the same character */ 00734 continue; 00735 } 00736 break; 00737 } 00738 00739 /* store c in md_msg->calling_st */ 00740 if (i >= iface->msdstrip) { 00741 ast_log(LOG_DEBUG, "Read a '%c' and stored it in the calling station buffer\n", c); 00742 *cp++ = c; 00743 } else { 00744 ast_log(LOG_DEBUG, "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); 00745 } 00746 } 00747 00748 /* make sure the value is null terminated, even if this truncates it */ 00749 md_msg->calling_st[sizeof(md_msg->calling_st) - 1] = '\0'; 00750 cp = NULL; 00751 00752 ast_log(LOG_DEBUG, "The calling station is '%s'\n", md_msg->calling_st); 00753 00754 /* add the message to the message queue */ 00755 md_msg->timestamp = ast_tvnow(); 00756 ast_smdi_md_message_push(iface, md_msg); 00757 ast_log(LOG_DEBUG, "Received SMDI MD message on %s\n", iface->name); 00758 00759 ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy); 00760 00761 } else if (c == 'W') { /* MWI message */ 00762 start = 0; 00763 00764 ast_log(LOG_DEBUG, "Read a 'W', it's an MWI message. (No more debug coming for MWI messages)\n"); 00765 00766 if (!(mwi_msg = ast_calloc(1, sizeof(*mwi_msg)))) { 00767 ASTOBJ_UNREF(iface,ast_smdi_interface_destroy); 00768 return NULL; 00769 } 00770 00771 ASTOBJ_INIT(mwi_msg); 00772 00773 /* discard the 'I' (from 'MWI') */ 00774 fgetc(iface->file); 00775 00776 /* read the forwarding station number (may be blank) */ 00777 cp = &mwi_msg->fwd_st[0]; 00778 for (i = 0; i < sizeof(mwi_msg->fwd_st) - 1; i++) { 00779 if ((c = fgetc(iface->file)) == ' ') { 00780 *cp = '\0'; 00781 break; 00782 } 00783 00784 /* store c in md_msg->fwd_st */ 00785 if (i >= iface->msdstrip) 00786 *cp++ = c; 00787 } 00788 00789 /* make sure the station number is null terminated, even if this will truncate it */ 00790 mwi_msg->fwd_st[sizeof(mwi_msg->fwd_st) - 1] = '\0'; 00791 cp = NULL; 00792 00793 /* Put the fwd_st in the name field so that we can use ASTOBJ_FIND to look 00794 * up a message on this field */ 00795 ast_copy_string(mwi_msg->name, mwi_msg->fwd_st, sizeof(mwi_msg->name)); 00796 00797 /* read the mwi failure cause */ 00798 for (i = 0; i < sizeof(mwi_msg->cause) - 1; i++) 00799 mwi_msg->cause[i] = fgetc(iface->file); 00800 00801 mwi_msg->cause[sizeof(mwi_msg->cause) - 1] = '\0'; 00802 00803 /* add the message to the message queue */ 00804 mwi_msg->timestamp = ast_tvnow(); 00805 ast_smdi_mwi_message_push(iface, mwi_msg); 00806 ast_log(LOG_DEBUG, "Received SMDI MWI message on %s\n", iface->name); 00807 00808 ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy); 00809 } else { 00810 ast_log(LOG_ERROR, "Unknown SMDI message type received on %s (M%c).\n", iface->name, c); 00811 start = 0; 00812 } 00813 } 00814 00815 ast_log(LOG_ERROR, "Error reading from SMDI interface %s, stopping listener thread\n", iface->name); 00816 ASTOBJ_UNREF(iface,ast_smdi_interface_destroy); 00817 return NULL; 00818 }
static int smdi_toggle_mwi | ( | struct ast_smdi_interface * | iface, | |
const char * | mailbox, | |||
int | on | |||
) | [static] |
Definition at line 288 of file res_smdi.c.
References ast_debug, ast_log(), ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, errno, ast_smdi_interface::file, mailbox_mapping::iface, LOG_ERROR, ast_smdi_interface::msdstrip, and ast_smdi_interface::name.
Referenced by ast_smdi_mwi_set(), and ast_smdi_mwi_unset().
00289 { 00290 FILE *file; 00291 int i; 00292 00293 if (!(file = fopen(iface->name, "w"))) { 00294 ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s) for writing\n", iface->name, strerror(errno)); 00295 return 1; 00296 } 00297 00298 ASTOBJ_WRLOCK(iface); 00299 00300 fprintf(file, "%s:MWI ", on ? "OP" : "RMV"); 00301 00302 for (i = 0; i < iface->msdstrip; i++) 00303 fprintf(file, "0"); 00304 00305 fprintf(file, "%s!\x04", mailbox); 00306 00307 fclose(file); 00308 00309 ASTOBJ_UNLOCK(iface); 00310 ast_debug(1, "Sent MWI set message for %s on %s\n", mailbox, iface->name); 00311 00312 return 0; 00313 }
static void* unlink_from_msg_q | ( | struct ast_smdi_interface * | iface, | |
enum smdi_message_type | type | |||
) | [inline, static] |
Definition at line 370 of file res_smdi.c.
References ASTOBJ_CONTAINER_UNLINK_START, mailbox_mapping::iface, ast_smdi_interface::md_q, ast_smdi_interface::mwi_q, SMDI_MD, and SMDI_MWI.
Referenced by purge_old_messages(), and smdi_msg_pop().
00371 { 00372 switch (type) { 00373 case SMDI_MWI: 00374 return ASTOBJ_CONTAINER_UNLINK_START(&iface->mwi_q); 00375 case SMDI_MD: 00376 return ASTOBJ_CONTAINER_UNLINK_START(&iface->md_q); 00377 } 00378 return NULL; 00379 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1454 of file res_smdi.c.
References _unload_module().
01455 { 01456 return _unload_module(0); 01457 }
static int unlock_msg_q | ( | struct ast_smdi_interface * | iface, | |
enum smdi_message_type | type | |||
) | [inline, static] |
Definition at line 358 of file res_smdi.c.
References ast_mutex_unlock, mailbox_mapping::iface, 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().
00359 { 00360 switch (type) { 00361 case SMDI_MWI: 00362 return ast_mutex_unlock(&iface->mwi_q_lock); 00363 case SMDI_MD: 00364 return ast_mutex_unlock(&iface->md_q_lock); 00365 } 00366 00367 return -1; 00368 }
static void unref_msg | ( | void * | msg, | |
enum smdi_message_type | type | |||
) | [inline, static] |
Definition at line 396 of file res_smdi.c.
References ast_smdi_md_message_destroy(), ast_smdi_mwi_message_destroy(), ASTOBJ_UNREF, SMDI_MD, and SMDI_MWI.
Referenced by purge_old_messages().
00397 { 00398 struct ast_smdi_md_message *md_msg = msg; 00399 struct ast_smdi_mwi_message *mwi_msg = msg; 00400 00401 switch (type) { 00402 case SMDI_MWI: 00403 ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy); 00404 break; 00405 case SMDI_MD: 00406 ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy); 00407 break; 00408 } 00409 }
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 1479 of file res_smdi.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1479 of file res_smdi.c.
Definition at line 214 of file res_smdi.c.
const char config_file[] = "smdi.conf" [static] |
Definition at line 154 of file res_smdi.c.
struct mailbox_mapping* first |
Definition at line 216 of file res_smdi.c.
struct mailbox_mapping* last |
Definition at line 216 of file res_smdi.c.
struct timeval last_poll |
The time that the last poll began
Definition at line 222 of file res_smdi.c.
Definition at line 213 of file res_smdi.c.
struct { ... } mailbox_mappings |
A list of mailboxes that need to be monitored
struct { ... } mwi_monitor [static] |
Data that gets used by the SMDI MWI monitoring thread.
Referenced by _unload_module(), append_mailbox_mapping(), destroy_all_mailbox_mappings(), load_module(), and mwi_monitor_handler().
unsigned int polling_interval |
Polling Interval for checking mailbox status
Definition at line 218 of file res_smdi.c.
struct ast_smdi_interface_container smdi_ifaces [static] |
SMDI interface container.
Referenced by _unload_module(), ast_smdi_interface_find(), load_module(), and smdi_load().
int smdi_loaded [static] |
Definition at line 155 of file res_smdi.c.
struct ast_datastore_info smdi_msg_datastore_info [static] |
Initial value:
{ .type = "SMDIMSG", .destroy = smdi_msg_datastore_destroy, }
Definition at line 1197 of file res_smdi.c.
Referenced by smdi_msg_read(), and smdi_msg_retrieve_read().
struct ast_custom_function smdi_msg_function [static] |
Initial value:
{ .name = "SMDI_MSG", .read = smdi_msg_read, }
Definition at line 1388 of file res_smdi.c.
Referenced by _unload_module(), and load_module().
int smdi_msg_id [static] |
Definition at line 1202 of file res_smdi.c.
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 [static] |
Initial value:
{ .name = "SMDI_MSG_RETRIEVE", .read = smdi_msg_retrieve_read, }
Definition at line 1383 of file res_smdi.c.
Referenced by _unload_module(), and load_module().
unsigned int stop |
Set to 1 to tell the polling thread to stop
Definition at line 220 of file res_smdi.c.
pthread_t thread |
The thread ID
Definition at line 212 of file res_smdi.c.