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