#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.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/logger.h"
#include "asterisk/options.h"
Go to the source code of this file.
Data Structures | |
struct | ast_smdi_interface_container |
SMDI interface container. More... | |
Defines | |
#define | SMDI_MSG_EXPIRY_TIME 30000 |
Functions | |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS,"Simplified Message Desk Interface (SMDI) Resource",.load=load_module,.unload=unload_module,.reload=reload,) | |
void | ast_smdi_interface_destroy (struct ast_smdi_interface *iface) |
ast_smdi_interface destructor. | |
struct ast_smdi_interface * | ast_smdi_interface_find (const char *iface_name) |
Find an SMDI interface with the specified name. | |
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 *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 *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. | |
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 int | load_module (void) |
static int | reload (void) |
static int | smdi_load (int reload) |
static void * | smdi_read (void *iface_p) |
Read an SMDI message. | |
static int | unload_module (void) |
Variables | |
static const char | config_file [] = "smdi.conf" |
struct module_symbols * | me |
struct ast_smdi_interface_container | smdi_ifaces |
SMDI interface container. |
Definition in file res_smdi.c.
#define SMDI_MSG_EXPIRY_TIME 30000 |
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_GLOBAL_SYMBOLS | , | |||
"Simplified Message Desk Interface (SMDI) Resource" | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload | |||
) |
void ast_smdi_interface_destroy | ( | struct ast_smdi_interface * | iface | ) |
ast_smdi_interface destructor.
Definition at line 486 of file res_smdi.c.
References ast_module_unref(), 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::mwi_q, and ast_smdi_interface::thread.
00487 { 00488 if (iface->thread != AST_PTHREADT_NULL && iface->thread != AST_PTHREADT_STOP) { 00489 pthread_cancel(iface->thread); 00490 pthread_join(iface->thread, NULL); 00491 } 00492 00493 iface->thread = AST_PTHREADT_STOP; 00494 00495 if(iface->file) 00496 fclose(iface->file); 00497 00498 ASTOBJ_CONTAINER_DESTROYALL(&iface->md_q, ast_smdi_md_message_destroy); 00499 ASTOBJ_CONTAINER_DESTROYALL(&iface->mwi_q, ast_smdi_mwi_message_destroy); 00500 ASTOBJ_CONTAINER_DESTROY(&iface->md_q); 00501 ASTOBJ_CONTAINER_DESTROY(&iface->mwi_q); 00502 free(iface); 00503 00504 ast_module_unref(ast_module_info->self); 00505 }
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 322 of file res_smdi.c.
References ASTOBJ_CONTAINER_FIND, and smdi_ifaces.
00323 { 00324 return (ASTOBJ_CONTAINER_FIND(&smdi_ifaces, iface_name)); 00325 }
void ast_smdi_md_message_destroy | ( | struct ast_smdi_md_message * | msg | ) |
ast_smdi_md_message destructor.
Definition at line 474 of file res_smdi.c.
References free.
00475 { 00476 free(msg); 00477 }
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. |
Definition at line 188 of file res_smdi.c.
References ast_log(), ast_smdi_md_message_destroy(), ASTOBJ_CONTAINER_UNLINK_START, ASTOBJ_UNREF, LOG_NOTICE, ast_smdi_interface::md_q, ast_smdi_interface::msg_expiry, and ast_smdi_md_message::timestamp.
00189 { 00190 struct ast_smdi_md_message *md_msg = ASTOBJ_CONTAINER_UNLINK_START(&iface->md_q); 00191 struct timeval now; 00192 long elapsed = 0; 00193 00194 /* purge old messages */ 00195 now = ast_tvnow(); 00196 while (md_msg) { 00197 elapsed = ast_tvdiff_ms(now, md_msg->timestamp); 00198 00199 if (elapsed > iface->msg_expiry) { 00200 /* found an expired message */ 00201 ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy); 00202 ast_log(LOG_NOTICE, "Purged expired message from %s SMDI MD message queue. Message was %ld milliseconds too old.\n", 00203 iface->name, elapsed - iface->msg_expiry); 00204 md_msg = ASTOBJ_CONTAINER_UNLINK_START(&iface->md_q); 00205 } 00206 else { 00207 /* good message, return it */ 00208 break; 00209 } 00210 } 00211 00212 return md_msg; 00213 }
static void ast_smdi_md_message_push | ( | struct ast_smdi_interface * | iface, | |
struct ast_smdi_md_message * | msg | |||
) | [static] |
Definition at line 72 of file res_smdi.c.
References ASTOBJ_CONTAINER_LINK_END, and ast_smdi_interface::md_q.
Referenced by smdi_read().
00073 { 00074 ASTOBJ_CONTAINER_LINK_END(&iface->md_q, md_msg); 00075 }
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.
iface | a pointer to the interface to use. | |
md_msg | a pointer to the message to use. |
Definition at line 159 of file res_smdi.c.
References ASTOBJ_CONTAINER_LINK_START, and ast_smdi_interface::md_q.
00160 { 00161 ASTOBJ_CONTAINER_LINK_START(&iface->md_q, md_msg); 00162 }
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. |
Definition at line 227 of file res_smdi.c.
References ast_smdi_md_message_pop().
00228 { 00229 struct timeval start; 00230 long diff = 0; 00231 struct ast_smdi_md_message *msg; 00232 00233 start = ast_tvnow(); 00234 while (diff < timeout) { 00235 00236 if ((msg = ast_smdi_md_message_pop(iface))) 00237 return msg; 00238 00239 /* check timeout */ 00240 diff = ast_tvdiff_ms(ast_tvnow(), start); 00241 } 00242 00243 return (ast_smdi_md_message_pop(iface)); 00244 }
void ast_smdi_mwi_message_destroy | ( | struct ast_smdi_mwi_message * | msg | ) |
ast_smdi_mwi_message destructor.
Definition at line 480 of file res_smdi.c.
References free.
00481 { 00482 free(msg); 00483 }
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. |
Definition at line 256 of file res_smdi.c.
References ast_log(), ast_smdi_mwi_message_destroy(), ASTOBJ_CONTAINER_UNLINK_START, ASTOBJ_UNREF, LOG_NOTICE, ast_smdi_interface::msg_expiry, ast_smdi_interface::mwi_q, and ast_smdi_mwi_message::timestamp.
00257 { 00258 struct ast_smdi_mwi_message *mwi_msg = ASTOBJ_CONTAINER_UNLINK_START(&iface->mwi_q); 00259 struct timeval now; 00260 long elapsed = 0; 00261 00262 /* purge old messages */ 00263 now = ast_tvnow(); 00264 while (mwi_msg) { 00265 elapsed = ast_tvdiff_ms(now, mwi_msg->timestamp); 00266 00267 if (elapsed > iface->msg_expiry) { 00268 /* found an expired message */ 00269 ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy); 00270 ast_log(LOG_NOTICE, "Purged expired message from %s SMDI MWI message queue. Message was %ld milliseconds too old.\n", 00271 iface->name, elapsed - iface->msg_expiry); 00272 mwi_msg = ASTOBJ_CONTAINER_UNLINK_START(&iface->mwi_q); 00273 } 00274 else { 00275 /* good message, return it */ 00276 break; 00277 } 00278 } 00279 00280 return mwi_msg; 00281 }
static void ast_smdi_mwi_message_push | ( | struct ast_smdi_interface * | iface, | |
struct ast_smdi_mwi_message * | msg | |||
) | [static] |
Definition at line 83 of file res_smdi.c.
References ASTOBJ_CONTAINER_LINK_END, and ast_smdi_interface::mwi_q.
Referenced by smdi_read().
00084 { 00085 ASTOBJ_CONTAINER_LINK_END(&iface->mwi_q, mwi_msg); 00086 }
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.
iface | a pointer to the interface to use. | |
mwi_msg | a pointer to the message to use. |
Definition at line 173 of file res_smdi.c.
References ASTOBJ_CONTAINER_LINK_START, and ast_smdi_interface::mwi_q.
00174 { 00175 ASTOBJ_CONTAINER_LINK_START(&iface->mwi_q, mwi_msg); 00176 }
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. |
Definition at line 295 of file res_smdi.c.
References ast_smdi_mwi_message_pop().
00296 { 00297 struct timeval start; 00298 long diff = 0; 00299 struct ast_smdi_mwi_message *msg; 00300 00301 start = ast_tvnow(); 00302 while (diff < timeout) { 00303 00304 if ((msg = ast_smdi_mwi_message_pop(iface))) 00305 return msg; 00306 00307 /* check timeout */ 00308 diff = ast_tvdiff_ms(ast_tvnow(), start); 00309 } 00310 00311 return (ast_smdi_mwi_message_pop(iface)); 00312 }
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 93 of file res_smdi.c.
References ast_log(), ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, file, LOG_DEBUG, LOG_ERROR, and ast_smdi_interface::msdstrip.
00094 { 00095 FILE *file; 00096 int i; 00097 00098 file = fopen(iface->name, "w"); 00099 if(!file) { 00100 ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s) for writing\n", iface->name, strerror(errno)); 00101 return 1; 00102 } 00103 00104 ASTOBJ_WRLOCK(iface); 00105 00106 fprintf(file, "OP:MWI "); 00107 00108 for(i = 0; i < iface->msdstrip; i++) 00109 fprintf(file, "0"); 00110 00111 fprintf(file, "%s!\x04", mailbox); 00112 fclose(file); 00113 00114 ASTOBJ_UNLOCK(iface); 00115 ast_log(LOG_DEBUG, "Sent MWI set message for %s on %s\n", mailbox, iface->name); 00116 return 0; 00117 }
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 124 of file res_smdi.c.
References ast_log(), ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, file, LOG_DEBUG, LOG_ERROR, and ast_smdi_interface::msdstrip.
00125 { 00126 FILE *file; 00127 int i; 00128 00129 file = fopen(iface->name, "w"); 00130 if(!file) { 00131 ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s) for writing\n", iface->name, strerror(errno)); 00132 return 1; 00133 } 00134 00135 ASTOBJ_WRLOCK(iface); 00136 00137 fprintf(file, "RMV:MWI "); 00138 00139 for(i = 0; i < iface->msdstrip; i++) 00140 fprintf(file, "0"); 00141 00142 fprintf(file, "%s!\x04", mailbox); 00143 fclose(file); 00144 00145 ASTOBJ_UNLOCK(iface); 00146 ast_log(LOG_DEBUG, "Sent MWI unset message for %s on %s\n", mailbox, iface->name); 00147 return 0; 00148 }
static int load_module | ( | void | ) | [static] |
Definition at line 709 of file res_smdi.c.
References ast_log(), AST_MODULE_LOAD_DECLINE, ASTOBJ_CONTAINER_INIT, LOG_WARNING, smdi_ifaces, and smdi_load().
00710 { 00711 int res; 00712 00713 /* initialize our containers */ 00714 memset(&smdi_ifaces, 0, sizeof(smdi_ifaces)); 00715 ASTOBJ_CONTAINER_INIT(&smdi_ifaces); 00716 00717 /* load the config and start the listener threads*/ 00718 res = smdi_load(0); 00719 if (res < 0) { 00720 return res; 00721 } else if (res == 1) { 00722 ast_log(LOG_WARNING, "No SMDI interfaces are available to listen on, not starting SDMI listener.\n"); 00723 return AST_MODULE_LOAD_DECLINE;; 00724 } else 00725 return 0; 00726 }
static int reload | ( | void | ) | [static] |
Definition at line 737 of file res_smdi.c.
References ast_log(), LOG_WARNING, and smdi_load().
00738 { 00739 int res; 00740 00741 res = smdi_load(1); 00742 00743 if (res < 0) { 00744 return res; 00745 } else if (res == 1) { 00746 ast_log(LOG_WARNING, "No SMDI interfaces were specified to listen on, not starting SDMI listener.\n"); 00747 return 0; 00748 } else 00749 return 0; 00750 }
static int smdi_load | ( | int | reload | ) | [static] |
Definition at line 517 of file res_smdi.c.
References ast_calloc, ast_config_destroy(), ast_config_load(), ast_log(), ast_module_ref(), ast_pthread_create_background, ast_smdi_interface_destroy(), ast_true(), ast_variable_browse(), ast_verbose(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_INIT, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_CONTAINER_PRUNE_MARKED, ASTOBJ_CONTAINER_RDLOCK, ASTOBJ_CONTAINER_UNLOCK, ASTOBJ_INIT, ASTOBJ_UNMARK, ASTOBJ_UNREF, ast_smdi_interface::fd, ast_smdi_interface::file, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, ast_smdi_interface::md_q, ast_smdi_interface::mode, ast_smdi_interface::msdstrip, ast_smdi_interface::msg_expiry, ast_smdi_interface::mwi_q, ast_variable::name, ast_variable::next, option_verbose, smdi_ifaces, SMDI_MSG_EXPIRY_TIME, smdi_read(), ast_smdi_interface::thread, ast_variable::value, and VERBOSE_PREFIX_3.
Referenced by load_module(), and reload().
00518 { 00519 struct ast_config *conf; 00520 struct ast_variable *v; 00521 struct ast_smdi_interface *iface = NULL; 00522 int res = 0; 00523 00524 /* Config options */ 00525 speed_t baud_rate = B9600; /* 9600 baud rate */ 00526 tcflag_t paritybit = PARENB; /* even parity checking */ 00527 tcflag_t charsize = CS7; /* seven bit characters */ 00528 int stopbits = 0; /* One stop bit */ 00529 00530 int msdstrip = 0; /* strip zero digits */ 00531 long msg_expiry = SMDI_MSG_EXPIRY_TIME; 00532 00533 conf = ast_config_load(config_file); 00534 00535 if (!conf) { 00536 if (reload) 00537 ast_log(LOG_NOTICE, "Unable to reload config %s: SMDI untouched\n", config_file); 00538 else 00539 ast_log(LOG_NOTICE, "Unable to load config %s: SMDI disabled\n", config_file); 00540 return 1; 00541 } 00542 00543 /* Mark all interfaces that we are listening on. We will unmark them 00544 * as we find them in the config file, this way we know any interfaces 00545 * still marked after we have finished parsing the config file should 00546 * be stopped. 00547 */ 00548 if (reload) 00549 ASTOBJ_CONTAINER_MARKALL(&smdi_ifaces); 00550 00551 for (v = ast_variable_browse(conf, "interfaces"); v; v = v->next) { 00552 if (!strcasecmp(v->name, "baudrate")) { 00553 if (!strcasecmp(v->value, "9600")) 00554 baud_rate = B9600; 00555 else if(!strcasecmp(v->value, "4800")) 00556 baud_rate = B4800; 00557 else if(!strcasecmp(v->value, "2400")) 00558 baud_rate = B2400; 00559 else if(!strcasecmp(v->value, "1200")) 00560 baud_rate = B1200; 00561 else { 00562 ast_log(LOG_NOTICE, "Invalid baud rate '%s' specified in %s (line %d), using default\n", v->value, config_file, v->lineno); 00563 baud_rate = B9600; 00564 } 00565 } else if (!strcasecmp(v->name, "msdstrip")) { 00566 if (!sscanf(v->value, "%d", &msdstrip)) { 00567 ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno); 00568 msdstrip = 0; 00569 } else if (0 > msdstrip || msdstrip > 9) { 00570 ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno); 00571 msdstrip = 0; 00572 } 00573 } else if (!strcasecmp(v->name, "msgexpirytime")) { 00574 if (!sscanf(v->value, "%ld", &msg_expiry)) { 00575 ast_log(LOG_NOTICE, "Invalid msgexpirytime value in %s (line %d), using default\n", config_file, v->lineno); 00576 msg_expiry = SMDI_MSG_EXPIRY_TIME; 00577 } 00578 } else if (!strcasecmp(v->name, "paritybit")) { 00579 if (!strcasecmp(v->value, "even")) 00580 paritybit = PARENB; 00581 else if (!strcasecmp(v->value, "odd")) 00582 paritybit = PARENB | PARODD; 00583 else if (!strcasecmp(v->value, "none")) 00584 paritybit = ~PARENB; 00585 else { 00586 ast_log(LOG_NOTICE, "Invalid parity bit setting in %s (line %d), using default\n", config_file, v->lineno); 00587 paritybit = PARENB; 00588 } 00589 } else if (!strcasecmp(v->name, "charsize")) { 00590 if (!strcasecmp(v->value, "7")) 00591 charsize = CS7; 00592 else if (!strcasecmp(v->value, "8")) 00593 charsize = CS8; 00594 else { 00595 ast_log(LOG_NOTICE, "Invalid character size setting in %s (line %d), using default\n", config_file, v->lineno); 00596 charsize = CS7; 00597 } 00598 } else if (!strcasecmp(v->name, "twostopbits")) { 00599 stopbits = ast_true(v->name); 00600 } else if (!strcasecmp(v->name, "smdiport")) { 00601 if (reload) { 00602 /* we are reloading, check if we are already 00603 * monitoring this interface, if we are we do 00604 * not want to start it again. This also has 00605 * the side effect of not updating different 00606 * setting for the serial port, but it should 00607 * be trivial to rewrite this section so that 00608 * options on the port are changed without 00609 * restarting the interface. Or the interface 00610 * could be restarted with out emptying the 00611 * queue. */ 00612 if ((iface = ASTOBJ_CONTAINER_FIND(&smdi_ifaces, v->value))) { 00613 ast_log(LOG_NOTICE, "SMDI interface %s already running, not restarting\n", iface->name); 00614 ASTOBJ_UNMARK(iface); 00615 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00616 continue; 00617 } 00618 } 00619 00620 if (!(iface = ast_calloc(1, sizeof(*iface)))) 00621 continue; 00622 00623 ASTOBJ_INIT(iface); 00624 ASTOBJ_CONTAINER_INIT(&iface->md_q); 00625 ASTOBJ_CONTAINER_INIT(&iface->mwi_q); 00626 00627 ast_copy_string(iface->name, v->value, sizeof(iface->name)); 00628 00629 if (!(iface->file = fopen(iface->name, "r"))) { 00630 ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s)\n", iface->name, strerror(errno)); 00631 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00632 continue; 00633 } 00634 00635 iface->fd = fileno(iface->file); 00636 00637 /* Set the proper attributes for our serial port. */ 00638 00639 /* get the current attributes from the port */ 00640 if (tcgetattr(iface->fd, &iface->mode)) { 00641 ast_log(LOG_ERROR, "Error getting atributes of %s (%s)\n", iface->name, strerror(errno)); 00642 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00643 continue; 00644 } 00645 00646 /* set the desired speed */ 00647 if (cfsetispeed(&iface->mode, baud_rate) || cfsetospeed(&iface->mode, baud_rate)) { 00648 ast_log(LOG_ERROR, "Error setting baud rate on %s (%s)\n", iface->name, strerror(errno)); 00649 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00650 continue; 00651 } 00652 00653 /* set the stop bits */ 00654 if (stopbits) 00655 iface->mode.c_cflag = iface->mode.c_cflag | CSTOPB; /* set two stop bits */ 00656 else 00657 iface->mode.c_cflag = iface->mode.c_cflag & ~CSTOPB; /* set one stop bit */ 00658 00659 /* set the parity */ 00660 iface->mode.c_cflag = (iface->mode.c_cflag & ~PARENB & ~PARODD) | paritybit; 00661 00662 /* set the character size */ 00663 iface->mode.c_cflag = (iface->mode.c_cflag & ~CSIZE) | charsize; 00664 00665 /* commit the desired attributes */ 00666 if (tcsetattr(iface->fd, TCSAFLUSH, &iface->mode)) { 00667 ast_log(LOG_ERROR, "Error setting attributes on %s (%s)\n", iface->name, strerror(errno)); 00668 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00669 continue; 00670 } 00671 00672 /* set the msdstrip */ 00673 iface->msdstrip = msdstrip; 00674 00675 /* set the message expiry time */ 00676 iface->msg_expiry = msg_expiry; 00677 00678 /* start the listner thread */ 00679 if (option_verbose > 2) 00680 ast_verbose(VERBOSE_PREFIX_3 "Starting SMDI monitor thread for %s\n", iface->name); 00681 if (ast_pthread_create_background(&iface->thread, NULL, smdi_read, iface)) { 00682 ast_log(LOG_ERROR, "Error starting SMDI monitor thread for %s\n", iface->name); 00683 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00684 continue; 00685 } 00686 00687 ASTOBJ_CONTAINER_LINK(&smdi_ifaces, iface); 00688 ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); 00689 ast_module_ref(ast_module_info->self); 00690 } else { 00691 ast_log(LOG_NOTICE, "Ignoring unknown option %s in %s\n", v->name, config_file); 00692 } 00693 } 00694 ast_config_destroy(conf); 00695 00696 /* Prune any interfaces we should no longer monitor. */ 00697 if (reload) 00698 ASTOBJ_CONTAINER_PRUNE_MARKED(&smdi_ifaces, ast_smdi_interface_destroy); 00699 00700 ASTOBJ_CONTAINER_RDLOCK(&smdi_ifaces); 00701 /* TODO: this is bad, we need an ASTOBJ method for this! */ 00702 if (!smdi_ifaces.head) 00703 res = 1; 00704 ASTOBJ_CONTAINER_UNLOCK(&smdi_ifaces); 00705 00706 return res; 00707 }
static void * smdi_read | ( | void * | iface_p | ) | [static] |
Read an SMDI message.
iface_p | the SMDI interface to read from. |
Definition at line 334 of file res_smdi.c.
References ast_calloc, 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(), 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, SMDI_MAX_STATION_NUM_LEN, SMDI_MESG_DESK_NUM_LEN, SMDI_MESG_DESK_TERM_LEN, SMDI_MWI_FAIL_CAUSE_LEN, ast_smdi_mwi_message::timestamp, ast_smdi_md_message::timestamp, and ast_smdi_md_message::type.
Referenced by smdi_load().
00335 { 00336 struct ast_smdi_interface *iface = iface_p; 00337 struct ast_smdi_md_message *md_msg; 00338 struct ast_smdi_mwi_message *mwi_msg; 00339 char c = '\0'; 00340 char *cp = NULL; 00341 int i; 00342 int start = 0; 00343 00344 /* read an smdi message */ 00345 while ((c = fgetc(iface->file))) { 00346 00347 /* check if this is the start of a message */ 00348 if (!start) { 00349 if (c == 'M') 00350 start = 1; 00351 } 00352 else { /* Determine if this is a MD or MWI message */ 00353 if(c == 'D') { /* MD message */ 00354 start = 0; 00355 00356 if (!(md_msg = ast_calloc(1, sizeof(*md_msg)))) { 00357 ASTOBJ_UNREF(iface,ast_smdi_interface_destroy); 00358 return NULL; 00359 } 00360 00361 ASTOBJ_INIT(md_msg); 00362 00363 /* read the message desk number */ 00364 for(i = 0; i < SMDI_MESG_DESK_NUM_LEN; i++) 00365 md_msg->mesg_desk_num[i] = fgetc(iface->file); 00366 00367 md_msg->mesg_desk_num[SMDI_MESG_DESK_NUM_LEN] = '\0'; 00368 00369 /* read the message desk terminal number */ 00370 for(i = 0; i < SMDI_MESG_DESK_TERM_LEN; i++) 00371 md_msg->mesg_desk_term[i] = fgetc(iface->file); 00372 00373 md_msg->mesg_desk_term[SMDI_MESG_DESK_TERM_LEN] = '\0'; 00374 00375 /* read the message type */ 00376 md_msg->type = fgetc(iface->file); 00377 00378 /* read the forwarding station number (may be blank) */ 00379 cp = &md_msg->fwd_st[0]; 00380 for (i = 0; i < SMDI_MAX_STATION_NUM_LEN + 1; i++) { 00381 if((c = fgetc(iface->file)) == ' ') { 00382 *cp = '\0'; 00383 break; 00384 } 00385 00386 /* store c in md_msg->fwd_st */ 00387 if( i >= iface->msdstrip) 00388 *cp++ = c; 00389 } 00390 00391 /* make sure the value is null terminated, even if this truncates it */ 00392 md_msg->fwd_st[SMDI_MAX_STATION_NUM_LEN] = '\0'; 00393 cp = NULL; 00394 00395 /* read the calling station number (may be blank) */ 00396 cp = &md_msg->calling_st[0]; 00397 for (i = 0; i < SMDI_MAX_STATION_NUM_LEN + 1; i++) { 00398 if (!isdigit((c = fgetc(iface->file)))) { 00399 *cp = '\0'; 00400 break; 00401 } 00402 00403 /* store c in md_msg->calling_st */ 00404 if (i >= iface->msdstrip) 00405 *cp++ = c; 00406 } 00407 00408 /* make sure the value is null terminated, even if this truncates it */ 00409 md_msg->calling_st[SMDI_MAX_STATION_NUM_LEN] = '\0'; 00410 cp = NULL; 00411 00412 /* add the message to the message queue */ 00413 md_msg->timestamp = ast_tvnow(); 00414 ast_smdi_md_message_push(iface, md_msg); 00415 ast_log(LOG_DEBUG, "Recieved SMDI MD message on %s\n", iface->name); 00416 00417 ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy); 00418 00419 } else if(c == 'W') { /* MWI message */ 00420 start = 0; 00421 00422 if (!(mwi_msg = ast_calloc(1, sizeof(*mwi_msg)))) { 00423 ASTOBJ_UNREF(iface,ast_smdi_interface_destroy); 00424 return NULL; 00425 } 00426 00427 ASTOBJ_INIT(mwi_msg); 00428 00429 /* discard the 'I' (from 'MWI') */ 00430 fgetc(iface->file); 00431 00432 /* read the forwarding station number (may be blank) */ 00433 cp = &mwi_msg->fwd_st[0]; 00434 for (i = 0; i < SMDI_MAX_STATION_NUM_LEN + 1; i++) { 00435 if ((c = fgetc(iface->file)) == ' ') { 00436 *cp = '\0'; 00437 break; 00438 } 00439 00440 /* store c in md_msg->fwd_st */ 00441 if (i >= iface->msdstrip) 00442 *cp++ = c; 00443 } 00444 00445 /* make sure the station number is null terminated, even if this will truncate it */ 00446 mwi_msg->fwd_st[SMDI_MAX_STATION_NUM_LEN] = '\0'; 00447 cp = NULL; 00448 00449 /* read the mwi failure cause */ 00450 for (i = 0; i < SMDI_MWI_FAIL_CAUSE_LEN; i++) 00451 mwi_msg->cause[i] = fgetc(iface->file); 00452 00453 mwi_msg->cause[SMDI_MWI_FAIL_CAUSE_LEN] = '\0'; 00454 00455 /* add the message to the message queue */ 00456 mwi_msg->timestamp = ast_tvnow(); 00457 ast_smdi_mwi_message_push(iface, mwi_msg); 00458 ast_log(LOG_DEBUG, "Recieved SMDI MWI message on %s\n", iface->name); 00459 00460 ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy); 00461 } else { 00462 ast_log(LOG_ERROR, "Unknown SMDI message type recieved on %s (M%c).\n", iface->name, c); 00463 start = 0; 00464 } 00465 } 00466 } 00467 00468 ast_log(LOG_ERROR, "Error reading from SMDI interface %s, stopping listener thread\n", iface->name); 00469 ASTOBJ_UNREF(iface,ast_smdi_interface_destroy); 00470 return NULL; 00471 }
static int unload_module | ( | void | ) | [static] |
Definition at line 728 of file res_smdi.c.
References ast_smdi_interface_destroy(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, and smdi_ifaces.
00729 { 00730 /* this destructor stops any running smdi_read threads */ 00731 ASTOBJ_CONTAINER_DESTROYALL(&smdi_ifaces, ast_smdi_interface_destroy); 00732 ASTOBJ_CONTAINER_DESTROY(&smdi_ifaces); 00733 00734 return 0; 00735 }
const char config_file[] = "smdi.conf" [static] |
Definition at line 51 of file res_smdi.c.
struct module_symbols* me |
Definition at line 59 of file res_smdi.c.
SMDI interface container.
Referenced by ast_smdi_interface_find(), load_module(), smdi_load(), and unload_module().