SMDI support for Asterisk. More...
#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 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) |
| struct ast_smdi_interface * | ast_smdi_interface_find (const char *iface_name) |
| Find an SMDI interface with the specified name. | |
| void | ast_smdi_interface_unref (struct ast_smdi_interface *iface) |
| void | ast_smdi_md_message_destroy (struct ast_smdi_md_message *msg) |
| ast_smdi_md_message destructor. | |
| struct ast_smdi_md_message * | 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_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. | |
| struct ast_smdi_md_message * | ast_smdi_md_message_wait (struct ast_smdi_interface *iface, int timeout) |
| Get the next SMDI message from the queue. | |
| void | ast_smdi_mwi_message_destroy (struct ast_smdi_mwi_message *msg) |
| ast_smdi_mwi_message destructor. | |
| struct ast_smdi_mwi_message * | 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_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. | |
| struct ast_smdi_mwi_message * | ast_smdi_mwi_message_wait (struct ast_smdi_interface *iface, int timeout) |
| Get the next SMDI message from the queue. | |
| struct ast_smdi_mwi_message * | ast_smdi_mwi_message_wait_station (struct ast_smdi_interface *iface, int timeout, const char *station) |
| int | ast_smdi_mwi_set (struct ast_smdi_interface *iface, const char *mailbox) |
| Set the MWI indicator for a mailbox. | |
| int | 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 , .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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static const char | config_file [] = "smdi.conf" |
| struct { | |
| ast_cond_t cond | |
| struct timeval last_poll | |
| ast_mutex_t lock | |
| struct { | |
| struct mailbox_mapping * first | |
| struct 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. | |
| struct ast_smdi_interface_container | smdi_ifaces |
| SMDI interface container. | |
| 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 |
SMDI support for Asterisk.
Here is a useful mailing list post that describes SMDI protocol details: http://lists.digium.com/pipermail/asterisk-dev/2003-June/000884.html
Definition in file res_smdi.c.
| #define AST_API_MODULE |
Definition at line 46 of file res_smdi.c.
| #define DEFAULT_POLLING_INTERVAL 10 |
| #define SMDI_MSG_EXPIRY_TIME 30000 |
Definition at line 58 of file res_smdi.c.
Referenced by smdi_load().
| #define SMDI_RETRIEVE_TIMEOUT_DEFAULT 3000 |
| anonymous enum |
Definition at line 370 of file res_smdi.c.
00370 { 00371 OPT_SEARCH_TERMINAL = (1 << 0), 00372 OPT_SEARCH_NUMBER = (1 << 1), 00373 };
| enum smdi_message_type |
Definition at line 246 of file res_smdi.c.
| static void __reg_module | ( | void | ) | [static] |
Definition at line 1410 of file res_smdi.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 1410 of file res_smdi.c.
| static struct ast_smdi_interface* alloc_smdi_interface | ( | void | ) | [static, read] |
Definition at line 831 of file res_smdi.c.
References ast_calloc, ast_cond_init(), ast_mutex_init(), ASTOBJ_CONTAINER_INIT, ASTOBJ_INIT, 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, and ast_smdi_interface::mwi_q_lock.
Referenced by smdi_load().
00832 { 00833 struct ast_smdi_interface *iface; 00834 00835 if (!(iface = ast_calloc(1, sizeof(*iface)))) 00836 return NULL; 00837 00838 ASTOBJ_INIT(iface); 00839 ASTOBJ_CONTAINER_INIT(&iface->md_q); 00840 ASTOBJ_CONTAINER_INIT(&iface->mwi_q); 00841 00842 ast_mutex_init(&iface->md_q_lock); 00843 ast_cond_init(&iface->md_q_cond, NULL); 00844 00845 ast_mutex_init(&iface->mwi_q_lock); 00846 ast_cond_init(&iface->mwi_q_cond, NULL); 00847 00848 return iface; 00849 }
| static void append_mailbox_mapping | ( | struct ast_variable * | var, | |
| struct ast_smdi_interface * | iface | |||
| ) | [static] |
Definition at line 752 of file res_smdi.c.
References ast_calloc, AST_LIST_INSERT_TAIL, ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ASTOBJ_REF, context, free, mailbox_mapping::iface, mailbox, mwi_monitor, ast_variable::name, mailbox_mapping::smdi, and ast_variable::value.
Referenced by smdi_load().
00753 { 00754 struct mailbox_mapping *mm; 00755 char *mailbox, *context; 00756 00757 if (!(mm = ast_calloc(1, sizeof(*mm)))) 00758 return; 00759 00760 if (ast_string_field_init(mm, 32)) { 00761 free(mm); 00762 return; 00763 } 00764 00765 ast_string_field_set(mm, smdi, var->name); 00766 00767 context = ast_strdupa(var->value); 00768 mailbox = strsep(&context, "@"); 00769 if (ast_strlen_zero(context)) 00770 context = "default"; 00771 00772 ast_string_field_set(mm, mailbox, mailbox); 00773 ast_string_field_set(mm, context, context); 00774 00775 mm->iface = ASTOBJ_REF(iface); 00776 00777 ast_mutex_lock(&mwi_monitor.lock); 00778 AST_LIST_INSERT_TAIL(&mwi_monitor.mailbox_mappings, mm, entry); 00779 ast_mutex_unlock(&mwi_monitor.lock); 00780 }
| static void ast_smdi_interface_destroy | ( | struct ast_smdi_interface * | iface | ) | [static] |
Definition at line 132 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, 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 ast_smdi_interface_unref(), destroy_mailbox_mapping(), smdi_load(), smdi_msg_datastore_destroy(), smdi_msg_retrieve_read(), smdi_read(), and unload_module().
00133 { 00134 if (iface->thread != AST_PTHREADT_NULL && iface->thread != AST_PTHREADT_STOP) { 00135 pthread_cancel(iface->thread); 00136 pthread_join(iface->thread, NULL); 00137 } 00138 00139 iface->thread = AST_PTHREADT_STOP; 00140 00141 if (iface->file) 00142 fclose(iface->file); 00143 00144 ASTOBJ_CONTAINER_DESTROYALL(&iface->md_q, ast_smdi_md_message_destroy); 00145 ASTOBJ_CONTAINER_DESTROYALL(&iface->mwi_q, ast_smdi_mwi_message_destroy); 00146 ASTOBJ_CONTAINER_DESTROY(&iface->md_q); 00147 ASTOBJ_CONTAINER_DESTROY(&iface->mwi_q); 00148 00149 ast_mutex_destroy(&iface->md_q_lock); 00150 ast_cond_destroy(&iface->md_q_cond); 00151 00152 ast_mutex_destroy(&iface->mwi_q_lock); 00153 ast_cond_destroy(&iface->mwi_q_cond); 00154 00155 free(iface); 00156 00157 ast_module_unref(ast_module_info->self); 00158 }
| struct ast_smdi_interface* ast_smdi_interface_find | ( | const char * | iface_name | ) | [read] |
Find an SMDI interface with the specified name.
| iface_name | the name/port of the interface to search for. |
Definition at line 528 of file res_smdi.c.
References ASTOBJ_CONTAINER_FIND, and smdi_ifaces.
Referenced by load_config(), mkintf(), and smdi_msg_retrieve_read().
00529 { 00530 return (ASTOBJ_CONTAINER_FIND(&smdi_ifaces, iface_name)); 00531 }
| void ast_smdi_interface_unref | ( | struct ast_smdi_interface * | iface | ) |
Definition at line 160 of file res_smdi.c.
References ast_smdi_interface_destroy(), and ASTOBJ_UNREF.
Referenced by destroy_dahdi_pvt().
00161 { 00162 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00163 }
| void ast_smdi_md_message_destroy | ( | struct ast_smdi_md_message * | msg | ) |
ast_smdi_md_message destructor.
Definition at line 725 of file res_smdi.c.
References ast_free.
Referenced by ast_smdi_interface_destroy(), smdi_msg_datastore_destroy(), smdi_msg_retrieve_read(), smdi_read(), ss_thread(), and unref_msg().
00726 { 00727 ast_free(msg); 00728 }
| struct ast_smdi_md_message* ast_smdi_md_message_pop | ( | struct ast_smdi_interface * | iface | ) | [read] |
Get the next SMDI message from the queue.
| iface | a pointer to the interface to use. |
This function pulls the first unexpired message from the SMDI message queue on the specified interface. It will purge all expired SMDI messages before returning.
Definition at line 499 of file res_smdi.c.
References SMDI_MD, and smdi_msg_pop().
00500 { 00501 return smdi_msg_pop(iface, SMDI_MD); 00502 }
| static void ast_smdi_md_message_push | ( | struct ast_smdi_interface * | iface, | |
| struct ast_smdi_md_message * | md_msg | |||
| ) | [static] |
Definition at line 171 of file res_smdi.c.
References ast_cond_broadcast(), ast_mutex_lock(), ast_mutex_unlock(), ASTOBJ_CONTAINER_LINK_END, ast_smdi_interface::md_q, ast_smdi_interface::md_q_cond, and ast_smdi_interface::md_q_lock.
Referenced by purge_old_messages(), and smdi_read().
00172 { 00173 ast_mutex_lock(&iface->md_q_lock); 00174 ASTOBJ_CONTAINER_LINK_END(&iface->md_q, md_msg); 00175 ast_cond_broadcast(&iface->md_q_cond); 00176 ast_mutex_unlock(&iface->md_q_lock); 00177 }
| void 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. | |
| md_msg | a pointer to the message to use. |
This function puts a message back in the front of the specified queue. It should be used if a message was popped but is not going to be processed for some reason, and the message needs to be returned to the queue.
Definition at line 230 of file res_smdi.c.
References ast_cond_broadcast(), ast_mutex_lock(), ast_mutex_unlock(), ASTOBJ_CONTAINER_LINK_START, ast_smdi_interface::md_q, ast_smdi_interface::md_q_cond, and ast_smdi_interface::md_q_lock.
00231 { 00232 ast_mutex_lock(&iface->md_q_lock); 00233 ASTOBJ_CONTAINER_LINK_START(&iface->md_q, md_msg); 00234 ast_cond_broadcast(&iface->md_q_cond); 00235 ast_mutex_unlock(&iface->md_q_lock); 00236 }
| struct ast_smdi_md_message* ast_smdi_md_message_wait | ( | struct ast_smdi_interface * | iface, | |
| int | timeout | |||
| ) | [read] |
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. |
This function pulls a message from the SMDI message queue on the specified interface. If no message is available this function will wait the specified amount of time before returning.
Definition at line 504 of file res_smdi.c.
References SMDI_MD, and smdi_message_wait().
Referenced by ss_thread().
00505 { 00506 struct ast_flags options = { 0 }; 00507 return smdi_message_wait(iface, timeout, SMDI_MD, NULL, options); 00508 }
| void ast_smdi_mwi_message_destroy | ( | struct ast_smdi_mwi_message * | msg | ) |
ast_smdi_mwi_message destructor.
Definition at line 730 of file res_smdi.c.
References ast_free.
Referenced by ast_smdi_interface_destroy(), run_externnotify(), smdi_read(), and unref_msg().
00731 { 00732 ast_free(msg); 00733 }
| struct ast_smdi_mwi_message* ast_smdi_mwi_message_pop | ( | struct ast_smdi_interface * | iface | ) | [read] |
Get the next SMDI message from the queue.
| iface | a pointer to the interface to use. |
This function pulls the first unexpired message from the SMDI message queue on the specified interface. It will purge all expired SMDI messages before returning.
Definition at line 510 of file res_smdi.c.
References smdi_msg_pop(), and SMDI_MWI.
00511 { 00512 return smdi_msg_pop(iface, SMDI_MWI); 00513 }
| static void ast_smdi_mwi_message_push | ( | struct ast_smdi_interface * | iface, | |
| struct ast_smdi_mwi_message * | mwi_msg | |||
| ) | [static] |
Definition at line 185 of file res_smdi.c.
References ast_cond_broadcast(), ast_mutex_lock(), ast_mutex_unlock(), ASTOBJ_CONTAINER_LINK_END, ast_smdi_interface::mwi_q, ast_smdi_interface::mwi_q_cond, and ast_smdi_interface::mwi_q_lock.
Referenced by purge_old_messages(), and smdi_read().
00186 { 00187 ast_mutex_lock(&iface->mwi_q_lock); 00188 ASTOBJ_CONTAINER_LINK_END(&iface->mwi_q, mwi_msg); 00189 ast_cond_broadcast(&iface->mwi_q_cond); 00190 ast_mutex_unlock(&iface->mwi_q_lock); 00191 }
| void 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. | |
| mwi_msg | a pointer to the message to use. |
This function puts a message back in the front of the specified queue. It should be used if a message was popped but is not going to be processed for some reason, and the message needs to be returned to the queue.
Definition at line 238 of file res_smdi.c.
References ast_cond_broadcast(), ast_mutex_lock(), ast_mutex_unlock(), ASTOBJ_CONTAINER_LINK_START, ast_smdi_interface::mwi_q, ast_smdi_interface::mwi_q_cond, and ast_smdi_interface::mwi_q_lock.
00239 { 00240 ast_mutex_lock(&iface->mwi_q_lock); 00241 ASTOBJ_CONTAINER_LINK_START(&iface->mwi_q, mwi_msg); 00242 ast_cond_broadcast(&iface->mwi_q_cond); 00243 ast_mutex_unlock(&iface->mwi_q_lock); 00244 }
| struct ast_smdi_mwi_message* ast_smdi_mwi_message_wait | ( | struct ast_smdi_interface * | iface, | |
| int | timeout | |||
| ) | [read] |
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. |
This function pulls a message from the SMDI message queue on the specified interface. If no message is available this function will wait the specified amount of time before returning.
Definition at line 515 of file res_smdi.c.
References smdi_message_wait(), and SMDI_MWI.
00516 { 00517 struct ast_flags options = { 0 }; 00518 return smdi_message_wait(iface, timeout, SMDI_MWI, NULL, options); 00519 }
| struct ast_smdi_mwi_message* ast_smdi_mwi_message_wait_station | ( | struct ast_smdi_interface * | iface, | |
| int | timeout, | |||
| const char * | station | |||
| ) | [read] |
Definition at line 521 of file res_smdi.c.
References smdi_message_wait(), and SMDI_MWI.
Referenced by run_externnotify().
00523 { 00524 struct ast_flags options = { 0 }; 00525 return smdi_message_wait(iface, timeout, SMDI_MWI, station, options); 00526 }
| int 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 220 of file res_smdi.c.
References smdi_toggle_mwi().
Referenced by poll_mailbox(), and run_externnotify().
00221 { 00222 return smdi_toggle_mwi(iface, mailbox, 1); 00223 }
| int 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 225 of file res_smdi.c.
References smdi_toggle_mwi().
Referenced by poll_mailbox(), and run_externnotify().
00226 { 00227 return smdi_toggle_mwi(iface, mailbox, 0); 00228 }
| static void destroy_all_mailbox_mappings | ( | void | ) | [static] |
Definition at line 742 of file res_smdi.c.
References AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), destroy_mailbox_mapping(), and mwi_monitor.
Referenced by smdi_load(), and unload_module().
00743 { 00744 struct mailbox_mapping *mm; 00745 00746 ast_mutex_lock(&mwi_monitor.lock); 00747 while ((mm = AST_LIST_REMOVE_HEAD(&mwi_monitor.mailbox_mappings, entry))) 00748 destroy_mailbox_mapping(mm); 00749 ast_mutex_unlock(&mwi_monitor.lock); 00750 }
| static void destroy_mailbox_mapping | ( | struct mailbox_mapping * | mm | ) | [static] |
Definition at line 735 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().
00736 { 00737 ast_string_field_free_memory(mm); 00738 ASTOBJ_UNREF(mm->iface, ast_smdi_interface_destroy); 00739 free(mm); 00740 }
| static int load_module | ( | void | ) | [static] |
Definition at line 1340 of file res_smdi.c.
References 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(), and unload_module.
01341 { 01342 int res; 01343 01344 /* initialize our containers */ 01345 memset(&smdi_ifaces, 0, sizeof(smdi_ifaces)); 01346 ASTOBJ_CONTAINER_INIT(&smdi_ifaces); 01347 01348 ast_mutex_init(&mwi_monitor.lock); 01349 ast_cond_init(&mwi_monitor.cond, NULL); 01350 01351 ast_custom_function_register(&smdi_msg_retrieve_function); 01352 ast_custom_function_register(&smdi_msg_function); 01353 01354 /* load the config and start the listener threads*/ 01355 res = smdi_load(0); 01356 if (res < 0) { 01357 unload_module(); 01358 return res; 01359 } else if (res == 1) { 01360 unload_module(); 01361 ast_log(LOG_NOTICE, "No SMDI interfaces are available to listen on, not starting SMDI listener.\n"); 01362 return AST_MODULE_LOAD_DECLINE; 01363 } 01364 01365 return AST_MODULE_LOAD_SUCCESS; 01366 }
| static int lock_msg_q | ( | struct ast_smdi_interface * | iface, | |
| enum smdi_message_type | type | |||
| ) | [inline, static] |
Definition at line 251 of file res_smdi.c.
References ast_mutex_lock(), 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().
00252 { 00253 switch (type) { 00254 case SMDI_MWI: 00255 return ast_mutex_lock(&iface->mwi_q_lock); 00256 case SMDI_MD: 00257 return ast_mutex_lock(&iface->md_q_lock); 00258 } 00259 00260 return -1; 00261 }
| static struct timeval msg_timestamp | ( | void * | msg, | |
| enum smdi_message_type | type | |||
| ) | [static, read] |
Definition at line 286 of file res_smdi.c.
References ast_tv(), msg, SMDI_MD, SMDI_MWI, ast_smdi_md_message::timestamp, ast_smdi_mwi_message::timestamp, and type.
Referenced by purge_old_messages().
00287 { 00288 struct ast_smdi_md_message *md_msg = msg; 00289 struct ast_smdi_mwi_message *mwi_msg = msg; 00290 00291 switch (type) { 00292 case SMDI_MWI: 00293 return mwi_msg->timestamp; 00294 case SMDI_MD: 00295 return md_msg->timestamp; 00296 } 00297 00298 return ast_tv(0, 0); 00299 }
| static void* mwi_monitor_handler | ( | void * | data | ) | [static] |
Definition at line 804 of file res_smdi.c.
References ast_cond_timedwait(), AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_tv(), ast_tvadd(), ast_tvnow(), mwi_monitor, and poll_mailbox().
Referenced by smdi_load().
00805 { 00806 while (!mwi_monitor.stop) { 00807 struct timespec ts = { 0, }; 00808 struct timeval polltime; 00809 struct mailbox_mapping *mm; 00810 00811 ast_mutex_lock(&mwi_monitor.lock); 00812 00813 mwi_monitor.last_poll = ast_tvnow(); 00814 00815 AST_LIST_TRAVERSE(&mwi_monitor.mailbox_mappings, mm, entry) 00816 poll_mailbox(mm); 00817 00818 /* Sleep up to the configured polling interval. Allow unload_module() 00819 * to signal us to wake up and exit. */ 00820 polltime = ast_tvadd(mwi_monitor.last_poll, ast_tv(mwi_monitor.polling_interval, 0)); 00821 ts.tv_sec = polltime.tv_sec; 00822 ts.tv_nsec = polltime.tv_usec * 1000; 00823 ast_cond_timedwait(&mwi_monitor.cond, &mwi_monitor.lock, &ts); 00824 00825 ast_mutex_unlock(&mwi_monitor.lock); 00826 } 00827 00828 return NULL; 00829 }
| static void poll_mailbox | ( | struct mailbox_mapping * | mm | ) | [static] |
Definition at line 785 of file res_smdi.c.
References ast_app_has_voicemail(), ast_smdi_mwi_set(), ast_smdi_mwi_unset(), buf, mailbox_mapping::context, mailbox_mapping::cur_state, mailbox_mapping::iface, mailbox_mapping::mailbox, and mailbox_mapping::smdi.
Referenced by mwi_monitor_handler().
00786 { 00787 char buf[1024]; 00788 unsigned int state; 00789 00790 snprintf(buf, sizeof(buf), "%s@%s", mm->mailbox, mm->context); 00791 00792 state = !!ast_app_has_voicemail(mm->mailbox, NULL); 00793 00794 if (state != mm->cur_state) { 00795 if (state) 00796 ast_smdi_mwi_set(mm->iface, mm->smdi); 00797 else 00798 ast_smdi_mwi_unset(mm->iface, mm->smdi); 00799 00800 mm->cur_state = state; 00801 } 00802 }
| static void purge_old_messages | ( | struct ast_smdi_interface * | iface, | |
| enum smdi_message_type | type | |||
| ) | [static] |
Definition at line 316 of file res_smdi.c.
References ast_log(), ast_smdi_md_message_push(), ast_smdi_mwi_message_push(), ast_tvdiff_ms(), ast_tvnow(), lock_msg_q(), LOG_NOTICE, msg, 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().
00317 { 00318 struct timeval now = ast_tvnow(); 00319 long elapsed = 0; 00320 void *msg; 00321 00322 lock_msg_q(iface, type); 00323 msg = unlink_from_msg_q(iface, type); 00324 unlock_msg_q(iface, type); 00325 00326 /* purge old messages */ 00327 while (msg) { 00328 elapsed = ast_tvdiff_ms(now, msg_timestamp(msg, type)); 00329 00330 if (elapsed > iface->msg_expiry) { 00331 /* found an expired message */ 00332 unref_msg(msg, type); 00333 ast_log(LOG_NOTICE, "Purged expired message from %s SMDI %s message queue. " 00334 "Message was %ld milliseconds too old.\n", 00335 iface->name, (type == SMDI_MD) ? "MD" : "MWI", 00336 elapsed - iface->msg_expiry); 00337 00338 lock_msg_q(iface, type); 00339 msg = unlink_from_msg_q(iface, type); 00340 unlock_msg_q(iface, type); 00341 } else { 00342 /* good message, put it back and return */ 00343 switch (type) { 00344 case SMDI_MD: 00345 ast_smdi_md_message_push(iface, msg); 00346 break; 00347 case SMDI_MWI: 00348 ast_smdi_mwi_message_push(iface, msg); 00349 break; 00350 } 00351 unref_msg(msg, type); 00352 break; 00353 } 00354 } 00355 }
| static int reload | ( | void | ) | [static] |
Definition at line 1391 of file res_smdi.c.
References ast_log(), LOG_WARNING, and smdi_load().
01392 { 01393 int res; 01394 01395 res = smdi_load(1); 01396 01397 if (res < 0) { 01398 return res; 01399 } else if (res == 1) { 01400 ast_log(LOG_WARNING, "No SMDI interfaces were specified to listen on, not starting SDMI listener.\n"); 01401 return 0; 01402 } else 01403 return 0; 01404 }
| static int smdi_load | ( | int | reload | ) | [static] |
Definition at line 861 of file res_smdi.c.
References alloc_smdi_interface(), append_mailbox_mapping(), ast_config_destroy(), ast_config_load, ast_copy_string(), AST_LIST_EMPTY, ast_log(), AST_MODULE_LOAD_FAILURE, ast_module_ref(), ast_pthread_create_background, AST_PTHREADT_NULL, ast_smdi_interface_destroy(), ast_true(), ast_variable_browse(), ast_verb, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_CONTAINER_PRUNE_MARKED, ASTOBJ_CONTAINER_RDLOCK, ASTOBJ_CONTAINER_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_POLLING_INTERVAL, destroy_all_mailbox_mappings(), errno, ast_smdi_interface::fd, ast_smdi_interface::file, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, ast_smdi_interface::mode, ast_smdi_interface::msdstrip, ast_smdi_interface::msg_expiry, mwi_monitor, mwi_monitor_handler(), ast_smdi_interface::name, ast_variable::name, ast_variable::next, smdi_ifaces, SMDI_MSG_EXPIRY_TIME, smdi_read(), ast_smdi_interface::thread, and ast_variable::value.
Referenced by load_module(), and reload().
00862 { 00863 struct ast_config *conf; 00864 struct ast_variable *v; 00865 struct ast_smdi_interface *iface = NULL; 00866 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 00867 int res = 0; 00868 00869 /* Config options */ 00870 speed_t baud_rate = B9600; /* 9600 baud rate */ 00871 tcflag_t paritybit = PARENB; /* even parity checking */ 00872 tcflag_t charsize = CS7; /* seven bit characters */ 00873 int stopbits = 0; /* One stop bit */ 00874 00875 int msdstrip = 0; /* strip zero digits */ 00876 long msg_expiry = SMDI_MSG_EXPIRY_TIME; 00877 00878 if (!(conf = ast_config_load(config_file, config_flags)) || conf == CONFIG_STATUS_FILEINVALID) { 00879 if (reload) 00880 ast_log(LOG_NOTICE, "Unable to reload config %s: SMDI untouched\n", config_file); 00881 else 00882 ast_log(LOG_NOTICE, "Unable to load config %s: SMDI disabled\n", config_file); 00883 return 1; 00884 } else if (conf == CONFIG_STATUS_FILEUNCHANGED) 00885 return 0; 00886 00887 /* Mark all interfaces that we are listening on. We will unmark them 00888 * as we find them in the config file, this way we know any interfaces 00889 * still marked after we have finished parsing the config file should 00890 * be stopped. 00891 */ 00892 if (reload) 00893 ASTOBJ_CONTAINER_MARKALL(&smdi_ifaces); 00894 00895 for (v = ast_variable_browse(conf, "interfaces"); v; v = v->next) { 00896 if (!strcasecmp(v->name, "baudrate")) { 00897 if (!strcasecmp(v->value, "9600")) 00898 baud_rate = B9600; 00899 else if (!strcasecmp(v->value, "4800")) 00900 baud_rate = B4800; 00901 else if (!strcasecmp(v->value, "2400")) 00902 baud_rate = B2400; 00903 else if (!strcasecmp(v->value, "1200")) 00904 baud_rate = B1200; 00905 else { 00906 ast_log(LOG_NOTICE, "Invalid baud rate '%s' specified in %s (line %d), using default\n", v->value, config_file, v->lineno); 00907 baud_rate = B9600; 00908 } 00909 } else if (!strcasecmp(v->name, "msdstrip")) { 00910 if (!sscanf(v->value, "%30d", &msdstrip)) { 00911 ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno); 00912 msdstrip = 0; 00913 } else if (0 > msdstrip || msdstrip > 9) { 00914 ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno); 00915 msdstrip = 0; 00916 } 00917 } else if (!strcasecmp(v->name, "msgexpirytime")) { 00918 if (!sscanf(v->value, "%30ld", &msg_expiry)) { 00919 ast_log(LOG_NOTICE, "Invalid msgexpirytime value in %s (line %d), using default\n", config_file, v->lineno); 00920 msg_expiry = SMDI_MSG_EXPIRY_TIME; 00921 } 00922 } else if (!strcasecmp(v->name, "paritybit")) { 00923 if (!strcasecmp(v->value, "even")) 00924 paritybit = PARENB; 00925 else if (!strcasecmp(v->value, "odd")) 00926 paritybit = PARENB | PARODD; 00927 else if (!strcasecmp(v->value, "none")) 00928 paritybit = ~PARENB; 00929 else { 00930 ast_log(LOG_NOTICE, "Invalid parity bit setting in %s (line %d), using default\n", config_file, v->lineno); 00931 paritybit = PARENB; 00932 } 00933 } else if (!strcasecmp(v->name, "charsize")) { 00934 if (!strcasecmp(v->value, "7")) 00935 charsize = CS7; 00936 else if (!strcasecmp(v->value, "8")) 00937 charsize = CS8; 00938 else { 00939 ast_log(LOG_NOTICE, "Invalid character size setting in %s (line %d), using default\n", config_file, v->lineno); 00940 charsize = CS7; 00941 } 00942 } else if (!strcasecmp(v->name, "twostopbits")) { 00943 stopbits = ast_true(v->name); 00944 } else if (!strcasecmp(v->name, "smdiport")) { 00945 if (reload) { 00946 /* we are reloading, check if we are already 00947 * monitoring this interface, if we are we do 00948 * not want to start it again. This also has 00949 * the side effect of not updating different 00950 * setting for the serial port, but it should 00951 * be trivial to rewrite this section so that 00952 * options on the port are changed without 00953 * restarting the interface. Or the interface 00954 * could be restarted with out emptying the 00955 * queue. */ 00956 if ((iface = ASTOBJ_CONTAINER_FIND(&smdi_ifaces, v->value))) { 00957 ast_log(LOG_NOTICE, "SMDI interface %s already running, not restarting\n", iface->name); 00958 ASTOBJ_UNMARK(iface); 00959 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00960 continue; 00961 } 00962 } 00963 00964 if (!(iface = alloc_smdi_interface())) 00965 continue; 00966 00967 ast_copy_string(iface->name, v->value, sizeof(iface->name)); 00968 00969 iface->thread = AST_PTHREADT_NULL; 00970 00971 if (!(iface->file = fopen(iface->name, "r"))) { 00972 ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s)\n", iface->name, strerror(errno)); 00973 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00974 continue; 00975 } 00976 00977 iface->fd = fileno(iface->file); 00978 00979 /* Set the proper attributes for our serial port. */ 00980 00981 /* get the current attributes from the port */ 00982 if (tcgetattr(iface->fd, &iface->mode)) { 00983 ast_log(LOG_ERROR, "Error getting atributes of %s (%s)\n", iface->name, strerror(errno)); 00984 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00985 continue; 00986 } 00987 00988 /* set the desired speed */ 00989 if (cfsetispeed(&iface->mode, baud_rate) || cfsetospeed(&iface->mode, baud_rate)) { 00990 ast_log(LOG_ERROR, "Error setting baud rate on %s (%s)\n", iface->name, strerror(errno)); 00991 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00992 continue; 00993 } 00994 00995 /* set the stop bits */ 00996 if (stopbits) 00997 iface->mode.c_cflag = iface->mode.c_cflag | CSTOPB; /* set two stop bits */ 00998 else 00999 iface->mode.c_cflag = iface->mode.c_cflag & ~CSTOPB; /* set one stop bit */ 01000 01001 /* set the parity */ 01002 iface->mode.c_cflag = (iface->mode.c_cflag & ~PARENB & ~PARODD) | paritybit; 01003 01004 /* set the character size */ 01005 iface->mode.c_cflag = (iface->mode.c_cflag & ~CSIZE) | charsize; 01006 01007 /* commit the desired attributes */ 01008 if (tcsetattr(iface->fd, TCSAFLUSH, &iface->mode)) { 01009 ast_log(LOG_ERROR, "Error setting attributes on %s (%s)\n", iface->name, strerror(errno)); 01010 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01011 continue; 01012 } 01013 01014 /* set the msdstrip */ 01015 iface->msdstrip = msdstrip; 01016 01017 /* set the message expiry time */ 01018 iface->msg_expiry = msg_expiry; 01019 01020 /* start the listener thread */ 01021 ast_verb(3, "Starting SMDI monitor thread for %s\n", iface->name); 01022 if (ast_pthread_create_background(&iface->thread, NULL, smdi_read, iface)) { 01023 ast_log(LOG_ERROR, "Error starting SMDI monitor thread for %s\n", iface->name); 01024 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01025 continue; 01026 } 01027 01028 ASTOBJ_CONTAINER_LINK(&smdi_ifaces, iface); 01029 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01030 ast_module_ref(ast_module_info->self); 01031 } else { 01032 ast_log(LOG_NOTICE, "Ignoring unknown option %s in %s\n", v->name, config_file); 01033 } 01034 } 01035 01036 destroy_all_mailbox_mappings(); 01037 mwi_monitor.polling_interval = DEFAULT_POLLING_INTERVAL; 01038 01039 iface = NULL; 01040 01041 for (v = ast_variable_browse(conf, "mailboxes"); v; v = v->next) { 01042 if (!strcasecmp(v->name, "smdiport")) { 01043 if (iface) 01044 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01045 01046 if (!(iface = ASTOBJ_CONTAINER_FIND(&smdi_ifaces, v->value))) { 01047 ast_log(LOG_NOTICE, "SMDI interface %s not found\n", v->value); 01048 continue; 01049 } 01050 } else if (!strcasecmp(v->name, "pollinginterval")) { 01051 if (sscanf(v->value, "%30u", &mwi_monitor.polling_interval) != 1) { 01052 ast_log(LOG_ERROR, "Invalid value for pollinginterval: %s\n", v->value); 01053 mwi_monitor.polling_interval = DEFAULT_POLLING_INTERVAL; 01054 } 01055 } else { 01056 if (!iface) { 01057 ast_log(LOG_ERROR, "Mailbox mapping ignored, no valid SMDI interface specified in mailboxes section\n"); 01058 continue; 01059 } 01060 append_mailbox_mapping(v, iface); 01061 } 01062 } 01063 01064 if (iface) 01065 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01066 01067 ast_config_destroy(conf); 01068 01069 if (!AST_LIST_EMPTY(&mwi_monitor.mailbox_mappings) && mwi_monitor.thread == AST_PTHREADT_NULL 01070 && ast_pthread_create_background(&mwi_monitor.thread, NULL, mwi_monitor_handler, NULL)) { 01071 ast_log(LOG_ERROR, "Failed to start MWI monitoring thread. This module will not operate.\n"); 01072 return AST_MODULE_LOAD_FAILURE; 01073 } 01074 01075 /* Prune any interfaces we should no longer monitor. */ 01076 if (reload) 01077 ASTOBJ_CONTAINER_PRUNE_MARKED(&smdi_ifaces, ast_smdi_interface_destroy); 01078 01079 ASTOBJ_CONTAINER_RDLOCK(&smdi_ifaces); 01080 /* TODO: this is bad, we need an ASTOBJ method for this! */ 01081 if (!smdi_ifaces.head) 01082 res = 1; 01083 ASTOBJ_CONTAINER_UNLOCK(&smdi_ifaces); 01084 01085 return res; 01086 }
| 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 443 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, msg, 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().
00445 { 00446 struct timeval start; 00447 long diff = 0; 00448 void *msg; 00449 ast_cond_t *cond = NULL; 00450 ast_mutex_t *lock = NULL; 00451 00452 switch (type) { 00453 case SMDI_MWI: 00454 cond = &iface->mwi_q_cond; 00455 lock = &iface->mwi_q_lock; 00456 break; 00457 case SMDI_MD: 00458 cond = &iface->md_q_cond; 00459 lock = &iface->md_q_lock; 00460 break; 00461 } 00462 00463 start = ast_tvnow(); 00464 00465 while (diff < timeout) { 00466 struct timespec ts = { 0, }; 00467 struct timeval wait; 00468 00469 lock_msg_q(iface, type); 00470 00471 if ((msg = smdi_msg_find(iface, type, search_key, options))) { 00472 unlock_msg_q(iface, type); 00473 return msg; 00474 } 00475 00476 wait = ast_tvadd(start, ast_tv(0, timeout)); 00477 ts.tv_sec = wait.tv_sec; 00478 ts.tv_nsec = wait.tv_usec * 1000; 00479 00480 /* If there were no messages in the queue, then go to sleep until one 00481 * arrives. */ 00482 00483 ast_cond_timedwait(cond, lock, &ts); 00484 00485 if ((msg = smdi_msg_find(iface, type, search_key, options))) { 00486 unlock_msg_q(iface, type); 00487 return msg; 00488 } 00489 00490 unlock_msg_q(iface, type); 00491 00492 /* check timeout */ 00493 diff = ast_tvdiff_ms(ast_tvnow(), start); 00494 } 00495 00496 return NULL; 00497 }
| static void smdi_msg_datastore_destroy | ( | void * | data | ) | [static] |
Definition at line 1094 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().
01095 { 01096 struct smdi_msg_datastore *smd = data; 01097 01098 if (smd->iface) 01099 ASTOBJ_UNREF(smd->iface, ast_smdi_interface_destroy); 01100 01101 if (smd->md_msg) 01102 ASTOBJ_UNREF(smd->md_msg, ast_smdi_md_message_destroy); 01103 01104 free(smd); 01105 }
| 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 375 of file res_smdi.c.
References ast_strlen_zero(), ast_test_flag, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_REF, ast_smdi_interface::md_q, msg, OPT_SEARCH_TERMINAL, purge_old_messages(), and SMDI_MD.
Referenced by smdi_message_wait().
00377 { 00378 void *msg = NULL; 00379 00380 purge_old_messages(iface, type); 00381 00382 switch (type) { 00383 case SMDI_MD: 00384 if (ast_strlen_zero(search_key)) { 00385 struct ast_smdi_md_message *md_msg = NULL; 00386 00387 /* No search key provided (the code from chan_dahdi does this). 00388 * Just pop the top message off of the queue. */ 00389 00390 ASTOBJ_CONTAINER_TRAVERSE(&iface->md_q, !md_msg, do { 00391 md_msg = ASTOBJ_REF(iterator); 00392 } while (0); ); 00393 00394 msg = md_msg; 00395 } else if (ast_test_flag(&options, OPT_SEARCH_TERMINAL)) { 00396 struct ast_smdi_md_message *md_msg = NULL; 00397 00398 /* Searching by the message desk terminal */ 00399 00400 ASTOBJ_CONTAINER_TRAVERSE(&iface->md_q, !md_msg, do { 00401 if (!strcasecmp(iterator->mesg_desk_term, search_key)) 00402 md_msg = ASTOBJ_REF(iterator); 00403 } while (0); ); 00404 00405 msg = md_msg; 00406 } else if (ast_test_flag(&options, OPT_SEARCH_NUMBER)) { 00407 struct ast_smdi_md_message *md_msg = NULL; 00408 00409 /* Searching by the message desk number */ 00410 00411 ASTOBJ_CONTAINER_TRAVERSE(&iface->md_q, !md_msg, do { 00412 if (!strcasecmp(iterator->mesg_desk_num, search_key)) 00413 md_msg = ASTOBJ_REF(iterator); 00414 } while (0); ); 00415 00416 msg = md_msg; 00417 } else { 00418 /* Searching by the forwarding station */ 00419 msg = ASTOBJ_CONTAINER_FIND(&iface->md_q, search_key); 00420 } 00421 break; 00422 case SMDI_MWI: 00423 if (ast_strlen_zero(search_key)) { 00424 struct ast_smdi_mwi_message *mwi_msg = NULL; 00425 00426 /* No search key provided (the code from chan_dahdi does this). 00427 * Just pop the top message off of the queue. */ 00428 00429 ASTOBJ_CONTAINER_TRAVERSE(&iface->mwi_q, !mwi_msg, do { 00430 mwi_msg = ASTOBJ_REF(iterator); 00431 } while (0); ); 00432 00433 msg = mwi_msg; 00434 } else { 00435 msg = ASTOBJ_CONTAINER_FIND(&iface->mwi_q, search_key); 00436 } 00437 break; 00438 } 00439 00440 return msg; 00441 }
| static void* smdi_msg_pop | ( | struct ast_smdi_interface * | iface, | |
| enum smdi_message_type | type | |||
| ) | [static] |
Definition at line 357 of file res_smdi.c.
References lock_msg_q(), msg, purge_old_messages(), unlink_from_msg_q(), and unlock_msg_q().
Referenced by ast_smdi_md_message_pop(), and ast_smdi_mwi_message_pop().
00358 { 00359 void *msg; 00360 00361 purge_old_messages(iface, type); 00362 00363 lock_msg_q(iface, type); 00364 msg = unlink_from_msg_q(iface, type); 00365 unlock_msg_q(iface, type); 00366 00367 return msg; 00368 }
| static int smdi_msg_read | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 1221 of file res_smdi.c.
References 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_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(), and ast_smdi_md_message::type.
01222 { 01223 struct ast_module_user *u; 01224 int res = -1; 01225 AST_DECLARE_APP_ARGS(args, 01226 AST_APP_ARG(id); 01227 AST_APP_ARG(component); 01228 ); 01229 char *parse; 01230 struct ast_datastore *datastore = NULL; 01231 struct smdi_msg_datastore *smd = NULL; 01232 01233 u = ast_module_user_add(chan); 01234 01235 if (!chan) { 01236 ast_log(LOG_ERROR, "SMDI_MSG can not be called without a channel\n"); 01237 goto return_error; 01238 } 01239 01240 if (ast_strlen_zero(data)) { 01241 ast_log(LOG_WARNING, "SMDI_MSG requires an argument\n"); 01242 goto return_error; 01243 } 01244 01245 parse = ast_strdupa(data); 01246 AST_STANDARD_APP_ARGS(args, parse); 01247 01248 if (ast_strlen_zero(args.id)) { 01249 ast_log(LOG_WARNING, "ID must be supplied to SMDI_MSG\n"); 01250 goto return_error; 01251 } 01252 01253 if (ast_strlen_zero(args.component)) { 01254 ast_log(LOG_WARNING, "ID must be supplied to SMDI_MSG\n"); 01255 goto return_error; 01256 } 01257 01258 ast_channel_lock(chan); 01259 datastore = ast_channel_datastore_find(chan, &smdi_msg_datastore_info, args.id); 01260 ast_channel_unlock(chan); 01261 01262 if (!datastore) { 01263 ast_log(LOG_WARNING, "No SMDI message found for message ID '%s'\n", args.id); 01264 goto return_error; 01265 } 01266 01267 smd = datastore->data; 01268 01269 if (!strcasecmp(args.component, "number")) { 01270 ast_copy_string(buf, smd->md_msg->mesg_desk_num, len); 01271 } else if (!strcasecmp(args.component, "terminal")) { 01272 ast_copy_string(buf, smd->md_msg->mesg_desk_term, len); 01273 } else if (!strcasecmp(args.component, "station")) { 01274 ast_copy_string(buf, smd->md_msg->fwd_st, len); 01275 } else if (!strcasecmp(args.component, "callerid")) { 01276 ast_copy_string(buf, smd->md_msg->calling_st, len); 01277 } else if (!strcasecmp(args.component, "type")) { 01278 snprintf(buf, len, "%c", smd->md_msg->type); 01279 } else { 01280 ast_log(LOG_ERROR, "'%s' is not a valid message component for SMDI_MSG\n", 01281 args.component); 01282 goto return_error; 01283 } 01284 01285 res = 0; 01286 01287 return_error: 01288 ast_module_user_remove(u); 01289 01290 return res; 01291 }
| static int smdi_msg_retrieve_read | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 1122 of file res_smdi.c.
References 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_strlen_zero(), ASTOBJ_REF, ASTOBJ_UNREF, ast_datastore::data, smdi_msg_datastore::id, smdi_msg_datastore::iface, LOG_ERROR, LOG_WARNING, smdi_msg_datastore::md_msg, parse(), SMDI_MD, smdi_message_wait(), smdi_msg_datastore_destroy(), smdi_msg_ret_options, and SMDI_RETRIEVE_TIMEOUT_DEFAULT.
01123 { 01124 struct ast_module_user *u; 01125 AST_DECLARE_APP_ARGS(args, 01126 AST_APP_ARG(port); 01127 AST_APP_ARG(search_key); 01128 AST_APP_ARG(timeout); 01129 AST_APP_ARG(options); 01130 ); 01131 struct ast_flags options = { 0 }; 01132 unsigned int timeout = SMDI_RETRIEVE_TIMEOUT_DEFAULT; 01133 int res = -1; 01134 char *parse = NULL; 01135 struct smdi_msg_datastore *smd = NULL; 01136 struct ast_datastore *datastore = NULL; 01137 struct ast_smdi_interface *iface = NULL; 01138 struct ast_smdi_md_message *md_msg = NULL; 01139 01140 u = ast_module_user_add(chan); 01141 01142 if (ast_strlen_zero(data)) { 01143 ast_log(LOG_ERROR, "SMDI_MSG_RETRIEVE requires an argument\n"); 01144 goto return_error; 01145 } 01146 01147 if (!chan) { 01148 ast_log(LOG_ERROR, "SMDI_MSG_RETRIEVE must be used with a channel\n"); 01149 goto return_error; 01150 } 01151 01152 ast_autoservice_start(chan); 01153 01154 parse = ast_strdupa(data); 01155 AST_STANDARD_APP_ARGS(args, parse); 01156 01157 if (ast_strlen_zero(args.port) || ast_strlen_zero(args.search_key)) { 01158 ast_log(LOG_ERROR, "Invalid arguments provided to SMDI_MSG_RETRIEVE\n"); 01159 goto return_error; 01160 } 01161 01162 if (!(iface = ast_smdi_interface_find(args.port))) { 01163 ast_log(LOG_ERROR, "SMDI port '%s' not found\n", args.port); 01164 goto return_error; 01165 } 01166 01167 if (!ast_strlen_zero(args.options)) { 01168 ast_app_parse_options(smdi_msg_ret_options, &options, NULL, args.options); 01169 } 01170 01171 if (!ast_strlen_zero(args.timeout)) { 01172 if (sscanf(args.timeout, "%30u", &timeout) != 1) { 01173 ast_log(LOG_ERROR, "'%s' is not a valid timeout\n", args.timeout); 01174 timeout = SMDI_RETRIEVE_TIMEOUT_DEFAULT; 01175 } 01176 } 01177 01178 if (!(md_msg = smdi_message_wait(iface, timeout, SMDI_MD, args.search_key, options))) { 01179 ast_log(LOG_WARNING, "No SMDI message retrieved for search key '%s' after " 01180 "waiting %u ms.\n", args.search_key, timeout); 01181 goto return_error; 01182 } 01183 01184 if (!(smd = ast_calloc(1, sizeof(*smd)))) 01185 goto return_error; 01186 01187 smd->iface = ASTOBJ_REF(iface); 01188 smd->md_msg = ASTOBJ_REF(md_msg); 01189 smd->id = ast_atomic_fetchadd_int((int *) &smdi_msg_id, 1); 01190 snprintf(buf, len, "%u", smd->id); 01191 01192 if (!(datastore = ast_datastore_alloc(&smdi_msg_datastore_info, buf))) 01193 goto return_error; 01194 01195 datastore->data = smd; 01196 01197 ast_channel_lock(chan); 01198 ast_channel_datastore_add(chan, datastore); 01199 ast_channel_unlock(chan); 01200 01201 res = 0; 01202 01203 return_error: 01204 if (iface) 01205 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 01206 01207 if (md_msg) 01208 ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy); 01209 01210 if (smd && !datastore) 01211 smdi_msg_datastore_destroy(smd); 01212 01213 if (parse) 01214 ast_autoservice_stop(chan); 01215 01216 ast_module_user_remove(u); 01217 01218 return res; 01219 }
| static void* smdi_read | ( | void * | iface_p | ) | [static] |
Definition at line 542 of file res_smdi.c.
References ast_calloc, ast_copy_string(), ast_log(), ast_smdi_interface_destroy(), ast_smdi_md_message_destroy(), ast_smdi_md_message_push(), ast_smdi_mwi_message_destroy(), ast_smdi_mwi_message_push(), ast_tvnow(), ASTOBJ_INIT, ASTOBJ_UNREF, ast_smdi_md_message::calling_st, ast_smdi_mwi_message::cause, ast_smdi_interface::file, ast_smdi_mwi_message::fwd_st, ast_smdi_md_message::fwd_st, LOG_DEBUG, LOG_ERROR, ast_smdi_md_message::mesg_desk_num, ast_smdi_md_message::mesg_desk_term, ast_smdi_interface::msdstrip, ast_smdi_mwi_message::name, ast_smdi_interface::name, ast_smdi_md_message::name, ast_smdi_mwi_message::timestamp, ast_smdi_md_message::timestamp, and ast_smdi_md_message::type.
Referenced by smdi_load().
00543 { 00544 struct ast_smdi_interface *iface = iface_p; 00545 struct ast_smdi_md_message *md_msg; 00546 struct ast_smdi_mwi_message *mwi_msg; 00547 char c = '\0'; 00548 char *cp = NULL; 00549 int i; 00550 int start = 0; 00551 00552 /* read an smdi message */ 00553 while ((c = fgetc(iface->file))) { 00554 00555 /* check if this is the start of a message */ 00556 if (!start) { 00557 if (c == 'M') { 00558 ast_log(LOG_DEBUG, "Read an 'M' to start an SMDI message\n"); 00559 start = 1; 00560 } 00561 continue; 00562 } 00563 00564 if (c == 'D') { /* MD message */ 00565 start = 0; 00566 00567 ast_log(LOG_DEBUG, "Read a 'D' ... it's an MD message.\n"); 00568 00569 if (!(md_msg = ast_calloc(1, sizeof(*md_msg)))) { 00570 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00571 return NULL; 00572 } 00573 00574 ASTOBJ_INIT(md_msg); 00575 00576 /* read the message desk number */ 00577 for (i = 0; i < sizeof(md_msg->mesg_desk_num) - 1; i++) { 00578 md_msg->mesg_desk_num[i] = fgetc(iface->file); 00579 ast_log(LOG_DEBUG, "Read a '%c'\n", md_msg->mesg_desk_num[i]); 00580 } 00581 00582 md_msg->mesg_desk_num[sizeof(md_msg->mesg_desk_num) - 1] = '\0'; 00583 00584 ast_log(LOG_DEBUG, "The message desk number is '%s'\n", md_msg->mesg_desk_num); 00585 00586 /* read the message desk terminal number */ 00587 for (i = 0; i < sizeof(md_msg->mesg_desk_term) - 1; i++) { 00588 md_msg->mesg_desk_term[i] = fgetc(iface->file); 00589 ast_log(LOG_DEBUG, "Read a '%c'\n", md_msg->mesg_desk_term[i]); 00590 } 00591 00592 md_msg->mesg_desk_term[sizeof(md_msg->mesg_desk_term) - 1] = '\0'; 00593 00594 ast_log(LOG_DEBUG, "The message desk terminal is '%s'\n", md_msg->mesg_desk_term); 00595 00596 /* read the message type */ 00597 md_msg->type = fgetc(iface->file); 00598 00599 ast_log(LOG_DEBUG, "Message type is '%c'\n", md_msg->type); 00600 00601 /* read the forwarding station number (may be blank) */ 00602 cp = &md_msg->fwd_st[0]; 00603 for (i = 0; i < sizeof(md_msg->fwd_st) - 1; i++) { 00604 if ((c = fgetc(iface->file)) == ' ') { 00605 *cp = '\0'; 00606 ast_log(LOG_DEBUG, "Read a space, done looking for the forwarding station\n"); 00607 break; 00608 } 00609 00610 /* store c in md_msg->fwd_st */ 00611 if (i >= iface->msdstrip) { 00612 ast_log(LOG_DEBUG, "Read a '%c' and stored it in the forwarding station buffer\n", c); 00613 *cp++ = c; 00614 } else { 00615 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); 00616 } 00617 } 00618 00619 /* make sure the value is null terminated, even if this truncates it */ 00620 md_msg->fwd_st[sizeof(md_msg->fwd_st) - 1] = '\0'; 00621 cp = NULL; 00622 00623 ast_log(LOG_DEBUG, "The forwarding station is '%s'\n", md_msg->fwd_st); 00624 00625 /* Put the fwd_st in the name field so that we can use ASTOBJ_FIND to look 00626 * up a message on this field */ 00627 ast_copy_string(md_msg->name, md_msg->fwd_st, sizeof(md_msg->name)); 00628 00629 /* read the calling station number (may be blank) */ 00630 cp = &md_msg->calling_st[0]; 00631 for (i = 0; i < sizeof(md_msg->calling_st) - 1; i++) { 00632 if (!isdigit((c = fgetc(iface->file)))) { 00633 *cp = '\0'; 00634 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); 00635 if (c == ' ') { 00636 /* Don't break on a space. We may read the space before the calling station 00637 * here if the forwarding station buffer filled up. */ 00638 i--; /* We're still on the same character */ 00639 continue; 00640 } 00641 break; 00642 } 00643 00644 /* store c in md_msg->calling_st */ 00645 if (i >= iface->msdstrip) { 00646 ast_log(LOG_DEBUG, "Read a '%c' and stored it in the calling station buffer\n", c); 00647 *cp++ = c; 00648 } else { 00649 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); 00650 } 00651 } 00652 00653 /* make sure the value is null terminated, even if this truncates it */ 00654 md_msg->calling_st[sizeof(md_msg->calling_st) - 1] = '\0'; 00655 cp = NULL; 00656 00657 ast_log(LOG_DEBUG, "The calling station is '%s'\n", md_msg->calling_st); 00658 00659 /* add the message to the message queue */ 00660 md_msg->timestamp = ast_tvnow(); 00661 ast_smdi_md_message_push(iface, md_msg); 00662 ast_log(LOG_DEBUG, "Received SMDI MD message on %s\n", iface->name); 00663 00664 ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy); 00665 00666 } else if (c == 'W') { /* MWI message */ 00667 start = 0; 00668 00669 ast_log(LOG_DEBUG, "Read a 'W', it's an MWI message. (No more debug coming for MWI messages)\n"); 00670 00671 if (!(mwi_msg = ast_calloc(1, sizeof(*mwi_msg)))) { 00672 ASTOBJ_UNREF(iface,ast_smdi_interface_destroy); 00673 return NULL; 00674 } 00675 00676 ASTOBJ_INIT(mwi_msg); 00677 00678 /* discard the 'I' (from 'MWI') */ 00679 fgetc(iface->file); 00680 00681 /* read the forwarding station number (may be blank) */ 00682 cp = &mwi_msg->fwd_st[0]; 00683 for (i = 0; i < sizeof(mwi_msg->fwd_st) - 1; i++) { 00684 if ((c = fgetc(iface->file)) == ' ') { 00685 *cp = '\0'; 00686 break; 00687 } 00688 00689 /* store c in md_msg->fwd_st */ 00690 if (i >= iface->msdstrip) 00691 *cp++ = c; 00692 } 00693 00694 /* make sure the station number is null terminated, even if this will truncate it */ 00695 mwi_msg->fwd_st[sizeof(mwi_msg->fwd_st) - 1] = '\0'; 00696 cp = NULL; 00697 00698 /* Put the fwd_st in the name field so that we can use ASTOBJ_FIND to look 00699 * up a message on this field */ 00700 ast_copy_string(mwi_msg->name, mwi_msg->fwd_st, sizeof(mwi_msg->name)); 00701 00702 /* read the mwi failure cause */ 00703 for (i = 0; i < sizeof(mwi_msg->cause) - 1; i++) 00704 mwi_msg->cause[i] = fgetc(iface->file); 00705 00706 mwi_msg->cause[sizeof(mwi_msg->cause) - 1] = '\0'; 00707 00708 /* add the message to the message queue */ 00709 mwi_msg->timestamp = ast_tvnow(); 00710 ast_smdi_mwi_message_push(iface, mwi_msg); 00711 ast_log(LOG_DEBUG, "Received SMDI MWI message on %s\n", iface->name); 00712 00713 ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy); 00714 } else { 00715 ast_log(LOG_ERROR, "Unknown SMDI message type received on %s (M%c).\n", iface->name, c); 00716 start = 0; 00717 } 00718 } 00719 00720 ast_log(LOG_ERROR, "Error reading from SMDI interface %s, stopping listener thread\n", iface->name); 00721 ASTOBJ_UNREF(iface,ast_smdi_interface_destroy); 00722 return NULL; 00723 }
| static int smdi_toggle_mwi | ( | struct ast_smdi_interface * | iface, | |
| const char * | mailbox, | |||
| int | on | |||
| ) | [static] |
Definition at line 193 of file res_smdi.c.
References ast_debug, ast_log(), ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, errno, LOG_ERROR, ast_smdi_interface::msdstrip, and ast_smdi_interface::name.
Referenced by ast_smdi_mwi_set(), and ast_smdi_mwi_unset().
00194 { 00195 FILE *file; 00196 int i; 00197 00198 if (!(file = fopen(iface->name, "w"))) { 00199 ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s) for writing\n", iface->name, strerror(errno)); 00200 return 1; 00201 } 00202 00203 ASTOBJ_WRLOCK(iface); 00204 00205 fprintf(file, "%s:MWI ", on ? "OP" : "RMV"); 00206 00207 for (i = 0; i < iface->msdstrip; i++) 00208 fprintf(file, "0"); 00209 00210 fprintf(file, "%s!\x04", mailbox); 00211 00212 fclose(file); 00213 00214 ASTOBJ_UNLOCK(iface); 00215 ast_debug(1, "Sent MWI set message for %s on %s\n", mailbox, iface->name); 00216 00217 return 0; 00218 }
| static void* unlink_from_msg_q | ( | struct ast_smdi_interface * | iface, | |
| enum smdi_message_type | type | |||
| ) | [inline, static] |
Definition at line 275 of file res_smdi.c.
References ASTOBJ_CONTAINER_UNLINK_START, ast_smdi_interface::md_q, ast_smdi_interface::mwi_q, SMDI_MD, and SMDI_MWI.
Referenced by purge_old_messages(), and smdi_msg_pop().
00276 { 00277 switch (type) { 00278 case SMDI_MWI: 00279 return ASTOBJ_CONTAINER_UNLINK_START(&iface->mwi_q); 00280 case SMDI_MD: 00281 return ASTOBJ_CONTAINER_UNLINK_START(&iface->md_q); 00282 } 00283 return NULL; 00284 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 1368 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, and smdi_ifaces.
01369 { 01370 /* this destructor stops any running smdi_read threads */ 01371 ASTOBJ_CONTAINER_DESTROYALL(&smdi_ifaces, ast_smdi_interface_destroy); 01372 ASTOBJ_CONTAINER_DESTROY(&smdi_ifaces); 01373 01374 destroy_all_mailbox_mappings(); 01375 01376 ast_mutex_lock(&mwi_monitor.lock); 01377 mwi_monitor.stop = 1; 01378 ast_cond_signal(&mwi_monitor.cond); 01379 ast_mutex_unlock(&mwi_monitor.lock); 01380 01381 if (mwi_monitor.thread != AST_PTHREADT_NULL) { 01382 pthread_join(mwi_monitor.thread, NULL); 01383 } 01384 01385 ast_custom_function_unregister(&smdi_msg_retrieve_function); 01386 ast_custom_function_unregister(&smdi_msg_function); 01387 01388 return 0; 01389 }
| static int unlock_msg_q | ( | struct ast_smdi_interface * | iface, | |
| enum smdi_message_type | type | |||
| ) | [inline, static] |
Definition at line 263 of file res_smdi.c.
References ast_mutex_unlock(), 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().
00264 { 00265 switch (type) { 00266 case SMDI_MWI: 00267 return ast_mutex_unlock(&iface->mwi_q_lock); 00268 case SMDI_MD: 00269 return ast_mutex_unlock(&iface->md_q_lock); 00270 } 00271 00272 return -1; 00273 }
| static void unref_msg | ( | void * | msg, | |
| enum smdi_message_type | type | |||
| ) | [inline, static] |
Definition at line 301 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().
00302 { 00303 struct ast_smdi_md_message *md_msg = msg; 00304 struct ast_smdi_mwi_message *mwi_msg = msg; 00305 00306 switch (type) { 00307 case SMDI_MWI: 00308 ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy); 00309 break; 00310 case SMDI_MD: 00311 ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy); 00312 break; 00313 } 00314 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 1410 of file res_smdi.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1410 of file res_smdi.c.
Definition at line 119 of file res_smdi.c.
const char config_file[] = "smdi.conf" [static] |
Definition at line 60 of file res_smdi.c.
| struct mailbox_mapping* first |
Definition at line 121 of file res_smdi.c.
| struct mailbox_mapping* last |
Definition at line 121 of file res_smdi.c.
| struct timeval last_poll |
The time that the last poll began
Definition at line 127 of file res_smdi.c.
Definition at line 118 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 append_mailbox_mapping(), destroy_all_mailbox_mappings(), load_module(), mwi_monitor_handler(), smdi_load(), and unload_module().
| unsigned int polling_interval |
Polling Interval for checking mailbox status
Definition at line 123 of file res_smdi.c.
SMDI interface container.
Referenced by ast_smdi_interface_find(), load_module(), smdi_load(), and unload_module().
struct ast_datastore_info smdi_msg_datastore_info [static] |
{
.type = "SMDIMSG",
.destroy = smdi_msg_datastore_destroy,
}
Definition at line 1107 of file res_smdi.c.
struct ast_custom_function smdi_msg_function [static] |
Definition at line 1317 of file res_smdi.c.
int smdi_msg_id [static] |
Definition at line 1112 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] |
Definition at line 1120 of file res_smdi.c.
Referenced by smdi_msg_retrieve_read().
struct ast_custom_function smdi_msg_retrieve_function [static] |
Definition at line 1293 of file res_smdi.c.
| unsigned int stop |
Set to 1 to tell the polling thread to stop
Definition at line 125 of file res_smdi.c.
| pthread_t thread |
The thread ID
Definition at line 117 of file res_smdi.c.
1.6.2