clean up SMDI support commit:

copyright header format and dates
code formatting and guidelines conformance
use of timeval wrapper functions
use of memory allocation wrappers
propery unref created interface objects during config load
document new variable set by chan_zap in doc/channelvariables.txt
remove useless 'extern' on function prototypes and definitions


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@9451 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.4
Kevin P. Fleming 20 years ago
parent 4f803dfda0
commit 7b2988821a

@ -1,7 +1,7 @@
/* /*
* Asterisk -- An open source telephony toolkit. * Asterisk -- An open source telephony toolkit.
* *
* Copyright (C) 1999 - 2005, Digium, Inc. * Copyright (C) 1999 - 2006, Digium, Inc.
* *
* Mark Spencer <markster@digium.com> * Mark Spencer <markster@digium.com>
* *
@ -2335,14 +2335,12 @@ static void run_externnotify(char *context, char *extension)
#ifdef WITH_SMDI #ifdef WITH_SMDI
if (!strcasecmp(externnotify, "smdi")) { if (!strcasecmp(externnotify, "smdi")) {
if (ast_app_has_voicemail(ext_context, NULL)) if (ast_app_has_voicemail(ext_context, NULL))
ast_smdi_mwi_set(smdi_iface, extension); ast_smdi_mwi_set(smdi_iface, extension);
else else
ast_smdi_mwi_unset(smdi_iface, extension); ast_smdi_mwi_unset(smdi_iface, extension);
mwi_msg = ast_smdi_mwi_message_wait(smdi_iface, SMDI_MWI_WAIT_TIMEOUT); if ((mwi_msg = ast_smdi_mwi_message_wait(smdi_iface, SMDI_MWI_WAIT_TIMEOUT))) {
if (mwi_msg) {
ast_log(LOG_ERROR, "Error executing SMDI MWI change for %s on %s\n", extension, smdi_iface->name); ast_log(LOG_ERROR, "Error executing SMDI MWI change for %s on %s\n", extension, smdi_iface->name);
if (!strncmp(mwi_msg->cause, "INV", 3)) if (!strncmp(mwi_msg->cause, "INV", 3))
ast_log(LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st); ast_log(LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
@ -5987,9 +5985,8 @@ static int load_config(void)
ast_copy_string(externnotify, notifystr, sizeof(externnotify)); ast_copy_string(externnotify, notifystr, sizeof(externnotify));
ast_log(LOG_DEBUG, "found externnotify: %s\n", externnotify); ast_log(LOG_DEBUG, "found externnotify: %s\n", externnotify);
#ifdef WITH_SMDI #ifdef WITH_SMDI
if(!strcasecmp(externnotify, "smdi")) { if (!strcasecmp(externnotify, "smdi")) {
ast_log(LOG_DEBUG, "Using SMDI for external voicemail notification\n"); ast_log(LOG_DEBUG, "Using SMDI for external voicemail notification\n");
if ((smdistr = ast_variable_retrieve(cfg, "general", "smdiport"))) { if ((smdistr = ast_variable_retrieve(cfg, "general", "smdiport"))) {
smdi_iface = ast_smdi_interface_find(smdistr); smdi_iface = ast_smdi_interface_find(smdistr);
} else { } else {
@ -5997,7 +5994,7 @@ static int load_config(void)
smdi_iface = ast_smdi_interface_find("/dev/ttyS0"); smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
} }
if(!smdi_iface) { if (!smdi_iface) {
ast_log(LOG_ERROR, "No valid SMDI interface specfied, disabling external voicemail notification\n"); ast_log(LOG_ERROR, "No valid SMDI interface specfied, disabling external voicemail notification\n");
externnotify[0] = '\0'; externnotify[0] = '\0';
} else { } else {

@ -1,7 +1,7 @@
/* /*
* Asterisk -- An open source telephony toolkit. * Asterisk -- An open source telephony toolkit.
* *
* Copyright (C) 1999 - 2005, Digium, Inc. * Copyright (C) 1999 - 2006, Digium, Inc.
* *
* Mark Spencer <markster@digium.com> * Mark Spencer <markster@digium.com>
* *
@ -5948,10 +5948,10 @@ lax);
#endif #endif
#ifdef WITH_SMDI #ifdef WITH_SMDI
/* check for SMDI messages */ /* check for SMDI messages */
if(p->use_smdi && p->smdi_iface) { if (p->use_smdi && p->smdi_iface) {
smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
if(smdi_msg != NULL) { if (smdi_msg != NULL) {
ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
if (smdi_msg->type == 'B') if (smdi_msg->type == 'B')

@ -696,6 +696,8 @@ ${CALLEDTON} * Type of number for incoming PRI extension
${CALLINGSUBADDR} * Called PRI Subaddress ${CALLINGSUBADDR} * Called PRI Subaddress
${FAXEXTEN} * The extension called before being redirected to "fax" ${FAXEXTEN} * The extension called before being redirected to "fax"
${PRIREDIRECTREASON} * Reason for redirect, if a call was directed ${PRIREDIRECTREASON} * Reason for redirect, if a call was directed
${SMDI_VM_TYPE} * When an call is received with an SMDI message, the 'type'
of message 'b' or 'u'
The SIP channel uses the following variables: The SIP channel uses the following variables:
--------------------------------------------------------- ---------------------------------------------------------

@ -1,14 +1,19 @@
/* /*
* Asterisk -- A telephony toolkit for Linux. * Asterisk -- A telephony toolkit for Linux.
* *
* SMDI support for Asterisk. * Copyright (C) 2005-2006, Digium, Inc.
*
* Copyright (C) 2005, Digium, Inc.
* *
* Matthew A. Nicholson <mnicholson@digium.com> * Matthew A. Nicholson <mnicholson@digium.com>
* *
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of * This program is free software, distributed under the terms of
* the GNU General Public License. * the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/ */
/*! /*!
@ -21,14 +26,15 @@
/* C is simply a ego booster for those who want to do objects the hard way. */ /* C is simply a ego booster for those who want to do objects the hard way. */
#ifndef AST_SMDI_H #ifndef ASTERISK_SMDI_H
#define AST_SMDI_H #define ASTERISK_SMDI_H
#include <termios.h>
#include <time.h>
#include "asterisk/config.h" #include "asterisk/config.h"
#include "asterisk/module.h" #include "asterisk/module.h"
#include "asterisk/astobj.h" #include "asterisk/astobj.h"
#include <termios.h>
#include <time.h>
#define SMDI_MESG_DESK_NUM_LEN 3 #define SMDI_MESG_DESK_NUM_LEN 3
#define SMDI_MESG_DESK_TERM_LEN 4 #define SMDI_MESG_DESK_TERM_LEN 4
@ -98,23 +104,24 @@ struct ast_smdi_interface {
/* MD message queue functions */ /* MD message queue functions */
extern struct ast_smdi_md_message *ast_smdi_md_message_pop(struct ast_smdi_interface *iface); struct ast_smdi_md_message *ast_smdi_md_message_pop(struct ast_smdi_interface *iface);
extern struct ast_smdi_md_message *ast_smdi_md_message_wait(struct ast_smdi_interface *iface, int timeout); struct ast_smdi_md_message *ast_smdi_md_message_wait(struct ast_smdi_interface *iface, int timeout);
extern void ast_smdi_md_message_putback(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 *msg);
/* MWI message queue functions */ /* MWI message queue functions */
extern struct ast_smdi_mwi_message *ast_smdi_mwi_message_pop(struct ast_smdi_interface *iface); struct ast_smdi_mwi_message *ast_smdi_mwi_message_pop(struct ast_smdi_interface *iface);
extern struct ast_smdi_mwi_message *ast_smdi_mwi_message_wait(struct ast_smdi_interface *iface, int timeout); struct ast_smdi_mwi_message *ast_smdi_mwi_message_wait(struct ast_smdi_interface *iface, int timeout);
extern void ast_smdi_mwi_message_putback(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 *msg);
extern struct ast_smdi_interface *ast_smdi_interface_find(const char *iface_name); struct ast_smdi_interface *ast_smdi_interface_find(const char *iface_name);
/* MWI functions */ /* MWI functions */
extern int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox); int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox);
extern int ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox); int ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox);
void ast_smdi_md_message_destroy(struct ast_smdi_md_message *msg);
void ast_smdi_mwi_message_destroy(struct ast_smdi_mwi_message *msg);
extern void ast_smdi_md_message_destroy(struct ast_smdi_md_message *msg); void ast_smdi_interface_destroy(struct ast_smdi_interface *iface);
extern void ast_smdi_mwi_message_destroy(struct ast_smdi_mwi_message *msg);
extern void ast_smdi_interface_destroy(struct ast_smdi_interface *iface); #endif /* !ASTERISK_SMDI_H */
#endif

@ -3,7 +3,7 @@
* *
* SMDI support for Asterisk. * SMDI support for Asterisk.
* *
* Copyright (C) 2005, Digium, Inc. * Copyright (C) 2005-2006, Digium, Inc.
* *
* Matthew A. Nicholson <mnicholson@digium.com> * Matthew A. Nicholson <mnicholson@digium.com>
* *
@ -84,7 +84,7 @@ static void ast_smdi_mwi_message_push(struct ast_smdi_interface *iface, struct a
* \param iface the interface to use. * \param iface the interface to use.
* \param mailbox the mailbox to use. * \param mailbox the mailbox to use.
*/ */
extern int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox) int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
{ {
FILE *file; FILE *file;
int i; int i;
@ -115,7 +115,7 @@ extern int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbo
* \param iface the interface to use. * \param iface the interface to use.
* \param mailbox the mailbox to use. * \param mailbox the mailbox to use.
*/ */
extern int ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox) int ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox)
{ {
FILE *file; FILE *file;
int i; int i;
@ -150,7 +150,7 @@ extern int ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mail
* should be used if a message was popped but is not going to be processed for * 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. * some reason, and the message needs to be returned to the queue.
*/ */
extern void ast_smdi_md_message_putback(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)
{ {
ASTOBJ_CONTAINER_LINK_START(&iface->md_q, md_msg); ASTOBJ_CONTAINER_LINK_START(&iface->md_q, md_msg);
} }
@ -164,7 +164,7 @@ extern void ast_smdi_md_message_putback(struct ast_smdi_interface *iface, struct
* should be used if a message was popped but is not going to be processed for * 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. * some reason, and the message needs to be returned to the queue.
*/ */
extern void ast_smdi_mwi_message_putback(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)
{ {
ASTOBJ_CONTAINER_LINK_START(&iface->mwi_q, mwi_msg); ASTOBJ_CONTAINER_LINK_START(&iface->mwi_q, mwi_msg);
} }
@ -179,28 +179,26 @@ extern void ast_smdi_mwi_message_putback(struct ast_smdi_interface *iface, struc
* *
* \return the next SMDI message, or NULL if there were no pending messages. * \return the next SMDI message, or NULL if there were no pending messages.
*/ */
extern struct ast_smdi_md_message *ast_smdi_md_message_pop(struct ast_smdi_interface *iface) struct ast_smdi_md_message *ast_smdi_md_message_pop(struct ast_smdi_interface *iface)
{ {
struct ast_smdi_md_message *md_msg = ASTOBJ_CONTAINER_UNLINK_START(&iface->md_q); struct ast_smdi_md_message *md_msg = ASTOBJ_CONTAINER_UNLINK_START(&iface->md_q);
struct timeval now; struct timeval now;
long elapsed = 0; long elapsed = 0;
/* purge old messages */ /* purge old messages */
gettimeofday(&now, NULL); now = ast_tvnow();
while(md_msg) while (md_msg) {
{ elapsed = ast_tvdiff_ms(now, md_msg->timestamp);
/* calculate the elapsed time since this message was recieved ( in milliseconds) */
elapsed = (now.tv_sec - md_msg->timestamp.tv_sec) * 1000; if (elapsed > iface->msg_expiry) {
elapsed += (now.tv_usec - md_msg->timestamp.tv_usec) / 1000; /* found an expired message */
ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy);
if(elapsed > iface->msg_expiry) ast_log(LOG_NOTICE, "Purged expired message from %s SMDI MD message queue. Message was %ld milliseconds too old.",
{ /* found an expired message */ iface->name, elapsed - iface->msg_expiry);
ASTOBJ_UNREF(md_msg,ast_smdi_md_message_destroy);
ast_log(LOG_NOTICE, "Purged expired message from %s SMDI MD message queue. Message was %ld milliseconds too old.", iface->name, elapsed - iface->msg_expiry);
md_msg = ASTOBJ_CONTAINER_UNLINK_START(&iface->md_q); md_msg = ASTOBJ_CONTAINER_UNLINK_START(&iface->md_q);
} }
else /* good message, return it */ else {
{ /* good message, return it */
break; break;
} }
} }
@ -222,21 +220,20 @@ extern struct ast_smdi_md_message *ast_smdi_md_message_pop(struct ast_smdi_inter
*/ */
extern struct ast_smdi_md_message *ast_smdi_md_message_wait(struct ast_smdi_interface *iface, int timeout) extern struct ast_smdi_md_message *ast_smdi_md_message_wait(struct ast_smdi_interface *iface, int timeout)
{ {
struct timeval start, end; struct timeval start;
long diff = 0; long diff = 0;
struct ast_smdi_md_message *msg; struct ast_smdi_md_message *msg;
gettimeofday(&start, NULL); start = ast_tvnow();
while(diff < timeout) { while (diff < timeout) {
if((msg = ast_smdi_md_message_pop(iface))) if ((msg = ast_smdi_md_message_pop(iface)))
return msg; return msg;
/* check timeout */ /* check timeout */
gettimeofday(&end, NULL); diff = ast_tvdiff_ms(ast_tvnow(), start);
diff = (end.tv_sec - start.tv_sec) * 1000;
diff += (end.tv_usec - start.tv_usec) / 1000;
} }
return (ast_smdi_md_message_pop(iface)); return (ast_smdi_md_message_pop(iface));
} }
@ -257,27 +254,24 @@ extern struct ast_smdi_mwi_message *ast_smdi_mwi_message_pop(struct ast_smdi_int
long elapsed = 0; long elapsed = 0;
/* purge old messages */ /* purge old messages */
gettimeofday(&now, NULL); now = ast_tvnow();
while(mwi_msg) while (mwi_msg) {
{ elapsed = ast_tvdiff_ms(now, mwi_msg->timestamp);
/* calculate the elapsed time since this message was recieved ( in milliseconds) */
elapsed = (now.tv_sec - mwi_msg->timestamp.tv_sec) * 1000; if (elapsed > iface->msg_expiry) {
elapsed += (now.tv_usec - mwi_msg->timestamp.tv_usec) / 1000; /* found an expired message */
ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
if(elapsed > iface->msg_expiry) ast_log(LOG_NOTICE, "Purged expired message from %s SMDI MWI message queue. Message was %ld milliseconds too old.",
{ /* found an expired message */ iface->name, elapsed - iface->msg_expiry);
ASTOBJ_UNREF(mwi_msg,ast_smdi_mwi_message_destroy);
ast_log(LOG_NOTICE, "Purged expired message from %s SMDI MWI message queue. Message was %ld milliseconds too old.", iface->name, elapsed - iface->msg_expiry);
mwi_msg = ASTOBJ_CONTAINER_UNLINK_START(&iface->mwi_q); mwi_msg = ASTOBJ_CONTAINER_UNLINK_START(&iface->mwi_q);
} }
else /* good message, return it */ else {
{ /* good message, return it */
break; break;
} }
} }
return mwi_msg; return mwi_msg;
return (ASTOBJ_CONTAINER_UNLINK_START(&iface->mwi_q));
} }
/*! /*!
@ -294,21 +288,20 @@ extern struct ast_smdi_mwi_message *ast_smdi_mwi_message_pop(struct ast_smdi_int
*/ */
extern struct ast_smdi_mwi_message *ast_smdi_mwi_message_wait(struct ast_smdi_interface *iface, int timeout) extern struct ast_smdi_mwi_message *ast_smdi_mwi_message_wait(struct ast_smdi_interface *iface, int timeout)
{ {
struct timeval start, end; struct timeval start;
long diff = 0; long diff = 0;
struct ast_smdi_mwi_message *msg; struct ast_smdi_mwi_message *msg;
gettimeofday(&start, NULL); start = ast_tvnow();
while(diff < timeout) { while (diff < timeout) {
if((msg = ast_smdi_mwi_message_pop(iface))) if ((msg = ast_smdi_mwi_message_pop(iface)))
return msg; return msg;
/* check timeout */ /* check timeout */
gettimeofday(&end, NULL); diff = ast_tvdiff_ms(ast_tvnow(), start);
diff = (end.tv_sec - start.tv_sec) * 1000;
diff += (end.tv_usec - start.tv_usec) / 1000;
} }
return (ast_smdi_mwi_message_pop(iface)); return (ast_smdi_mwi_message_pop(iface));
} }
@ -322,7 +315,7 @@ extern struct ast_smdi_mwi_message *ast_smdi_mwi_message_wait(struct ast_smdi_in
*/ */
extern struct ast_smdi_interface *ast_smdi_interface_find(const char *iface_name) extern struct ast_smdi_interface *ast_smdi_interface_find(const char *iface_name)
{ {
return (ASTOBJ_CONTAINER_FIND(&smdi_ifaces,iface_name)); return (ASTOBJ_CONTAINER_FIND(&smdi_ifaces, iface_name));
} }
/*! \brief Read an SMDI message. /*! \brief Read an SMDI message.
@ -343,39 +336,34 @@ static void *smdi_read(void *iface_p)
int start = 0; int start = 0;
/* read an smdi message */ /* read an smdi message */
while((c = fgetc(iface->file))) { while ((c = fgetc(iface->file))) {
/* check if this is the start of a message */ /* check if this is the start of a message */
if(!start) if (!start) {
{ if (c == 'M')
if(c == 'M')
start = 1; start = 1;
} }
else /* Determine if this is a MD or MWI message */ else { /* Determine if this is a MD or MWI message */
{
if(c == 'D') { /* MD message */ if(c == 'D') { /* MD message */
start = 0; start = 0;
md_msg = malloc(sizeof(struct ast_smdi_md_message)); if (!(md_msg = ast_calloc(1, sizeof(*md_msg)))) {
if(!md_msg) {
ast_log(LOG_ERROR, "Error allocating memory for ast_smdi_md_message. Stopping listner thread.\n");
ASTOBJ_UNREF(iface,ast_smdi_interface_destroy); ASTOBJ_UNREF(iface,ast_smdi_interface_destroy);
return NULL; return NULL;
} }
memset(md_msg, 0, sizeof(struct ast_smdi_md_message));
ASTOBJ_INIT(md_msg); ASTOBJ_INIT(md_msg);
/* read the message desk number */ /* read the message desk number */
for(i = 0; i < SMDI_MESG_DESK_NUM_LEN; i++) { for(i = 0; i < SMDI_MESG_DESK_NUM_LEN; i++)
md_msg->mesg_desk_num[i] = fgetc(iface->file); md_msg->mesg_desk_num[i] = fgetc(iface->file);
}
md_msg->mesg_desk_num[SMDI_MESG_DESK_NUM_LEN] = '\0'; md_msg->mesg_desk_num[SMDI_MESG_DESK_NUM_LEN] = '\0';
/* read the message desk terminal number */ /* read the message desk terminal number */
for(i = 0; i < SMDI_MESG_DESK_TERM_LEN; i++) { for(i = 0; i < SMDI_MESG_DESK_TERM_LEN; i++)
md_msg->mesg_desk_term[i] = fgetc(iface->file); md_msg->mesg_desk_term[i] = fgetc(iface->file);
}
md_msg->mesg_desk_term[SMDI_MESG_DESK_TERM_LEN] = '\0'; md_msg->mesg_desk_term[SMDI_MESG_DESK_TERM_LEN] = '\0';
/* read the message type */ /* read the message type */
@ -383,42 +371,40 @@ static void *smdi_read(void *iface_p)
/* read the forwarding station number (may be blank) */ /* read the forwarding station number (may be blank) */
cp = &md_msg->fwd_st[0]; cp = &md_msg->fwd_st[0];
for(i = 0; i < SMDI_MAX_STATION_NUM_LEN + 1; i++) { for (i = 0; i < SMDI_MAX_STATION_NUM_LEN + 1; i++) {
if((c = fgetc(iface->file)) == ' ') { if((c = fgetc(iface->file)) == ' ') {
*cp = '\0'; *cp = '\0';
break; break;
} }
/* store c in md_msg->fwd_st */ /* store c in md_msg->fwd_st */
if( i >= iface->msdstrip) { if( i >= iface->msdstrip)
*cp = c; *cp++ = c;
cp++;
}
} }
/* make sure the value is null terminated, even if this truncates it */ /* make sure the value is null terminated, even if this truncates it */
md_msg->fwd_st[SMDI_MAX_STATION_NUM_LEN] = '\0'; md_msg->fwd_st[SMDI_MAX_STATION_NUM_LEN] = '\0';
cp = NULL; cp = NULL;
/* read the calling station number (may be blank) */ /* read the calling station number (may be blank) */
cp = &md_msg->calling_st[0]; cp = &md_msg->calling_st[0];
for(i = 0; i < SMDI_MAX_STATION_NUM_LEN + 1; i++) { for (i = 0; i < SMDI_MAX_STATION_NUM_LEN + 1; i++) {
if(!isdigit( (c = fgetc(iface->file)) )) { if (!isdigit((c = fgetc(iface->file)))) {
*cp = '\0'; *cp = '\0';
break; break;
} }
/* store c in md_msg->calling_st */ /* store c in md_msg->calling_st */
if( i >= iface->msdstrip) { if (i >= iface->msdstrip)
*cp = c; *cp++ = c;
cp++;
}
} }
/* make sure the value is null terminated, even if this truncates it */ /* make sure the value is null terminated, even if this truncates it */
md_msg->calling_st[SMDI_MAX_STATION_NUM_LEN] = '\0'; md_msg->calling_st[SMDI_MAX_STATION_NUM_LEN] = '\0';
cp = NULL; cp = NULL;
/* add the message to the message queue */ /* add the message to the message queue */
gettimeofday(&md_msg->timestamp, NULL); md_msg->timestamp = ast_tvnow();
ast_smdi_md_message_push(iface, md_msg); ast_smdi_md_message_push(iface, md_msg);
ast_log(LOG_DEBUG, "Recieved SMDI MD message on %s\n", iface->name); ast_log(LOG_DEBUG, "Recieved SMDI MD message on %s\n", iface->name);
@ -427,13 +413,10 @@ static void *smdi_read(void *iface_p)
} else if(c == 'W') { /* MWI message */ } else if(c == 'W') { /* MWI message */
start = 0; start = 0;
mwi_msg = malloc(sizeof(struct ast_smdi_mwi_message)); if (!(mwi_msg = ast_calloc(1, sizeof(*mwi_msg)))) {
if(!mwi_msg) {
ast_log(LOG_ERROR, "Error allocating memory for ast_smdi_mwi_message. Stopping listner thread.\n");
ASTOBJ_UNREF(iface,ast_smdi_interface_destroy); ASTOBJ_UNREF(iface,ast_smdi_interface_destroy);
return NULL; return NULL;
} }
memset(mwi_msg, 0, sizeof(struct ast_smdi_mwi_message));
ASTOBJ_INIT(mwi_msg); ASTOBJ_INIT(mwi_msg);
@ -442,30 +425,29 @@ static void *smdi_read(void *iface_p)
/* read the forwarding station number (may be blank) */ /* read the forwarding station number (may be blank) */
cp = &mwi_msg->fwd_st[0]; cp = &mwi_msg->fwd_st[0];
for(i = 0; i < SMDI_MAX_STATION_NUM_LEN + 1; i++) { for (i = 0; i < SMDI_MAX_STATION_NUM_LEN + 1; i++) {
if((c = fgetc(iface->file)) == ' ') { if ((c = fgetc(iface->file)) == ' ') {
*cp = '\0'; *cp = '\0';
break; break;
} }
/* store c in md_msg->fwd_st */ /* store c in md_msg->fwd_st */
if( i >= iface->msdstrip) { if (i >= iface->msdstrip)
*cp = c; *cp++ = c;
cp++;
}
} }
/* make sure the station number is null terminated, even if this will truncate it */ /* make sure the station number is null terminated, even if this will truncate it */
mwi_msg->fwd_st[SMDI_MAX_STATION_NUM_LEN] = '\0'; mwi_msg->fwd_st[SMDI_MAX_STATION_NUM_LEN] = '\0';
cp = NULL; cp = NULL;
/* read the mwi failure cause */ /* read the mwi failure cause */
for(i = 0; i < SMDI_MWI_FAIL_CAUSE_LEN; i++) { for (i = 0; i < SMDI_MWI_FAIL_CAUSE_LEN; i++)
mwi_msg->cause[i] = fgetc(iface->file); mwi_msg->cause[i] = fgetc(iface->file);
}
mwi_msg->cause[SMDI_MWI_FAIL_CAUSE_LEN] = '\0'; mwi_msg->cause[SMDI_MWI_FAIL_CAUSE_LEN] = '\0';
/* add the message to the message queue */ /* add the message to the message queue */
gettimeofday(&mwi_msg->timestamp, NULL); mwi_msg->timestamp = ast_tvnow();
ast_smdi_mwi_message_push(iface, mwi_msg); ast_smdi_mwi_message_push(iface, mwi_msg);
ast_log(LOG_DEBUG, "Recieved SMDI MWI message on %s\n", iface->name); ast_log(LOG_DEBUG, "Recieved SMDI MWI message on %s\n", iface->name);
@ -497,7 +479,7 @@ void ast_smdi_mwi_message_destroy(struct ast_smdi_mwi_message *msg)
/*! \brief ast_smdi_interface destructor. */ /*! \brief ast_smdi_interface destructor. */
void ast_smdi_interface_destroy(struct ast_smdi_interface *iface) void ast_smdi_interface_destroy(struct ast_smdi_interface *iface)
{ {
if(iface->thread != AST_PTHREADT_NULL && iface->thread != AST_PTHREADT_STOP) { if (iface->thread != AST_PTHREADT_NULL && iface->thread != AST_PTHREADT_STOP) {
pthread_cancel(iface->thread); pthread_cancel(iface->thread);
pthread_join(iface->thread, NULL); pthread_join(iface->thread, NULL);
} }
@ -547,7 +529,7 @@ static int smdi_load(int reload)
conf = ast_config_load(config_file); conf = ast_config_load(config_file);
if(!conf) { if (!conf) {
ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
return -1; return -1;
} }
@ -557,61 +539,60 @@ static int smdi_load(int reload)
* still marked after we have finished parsing the config file should * still marked after we have finished parsing the config file should
* be stopped. * be stopped.
*/ */
if(reload) if (reload)
ASTOBJ_CONTAINER_MARKALL(&smdi_ifaces); ASTOBJ_CONTAINER_MARKALL(&smdi_ifaces);
v = ast_variable_browse(conf, "interfaces"); for (v = ast_variable_browse(conf, "interfaces"); v; v = v->next) {
while(v) { if (!strcasecmp(v->name, "baudrate")) {
if(!strcasecmp(v->name, "baudrate")) { if (!strcasecmp(v->value, "9600"))
if(!strcasecmp(v->value, "9600")) {
baud_rate = B9600; baud_rate = B9600;
} else if(!strcasecmp(v->value, "4800")) { else if(!strcasecmp(v->value, "4800"))
baud_rate = B4800; baud_rate = B4800;
} else if(!strcasecmp(v->value, "2400")) { else if(!strcasecmp(v->value, "2400"))
baud_rate = B2400; baud_rate = B2400;
} else if(!strcasecmp(v->value, "1200")) { else if(!strcasecmp(v->value, "1200"))
baud_rate = B1200; baud_rate = B1200;
} else { else {
ast_log(LOG_NOTICE, "Invalid baud rate '%s' specified in %s (line %d), using default\n", v->value, config_file, v->lineno); ast_log(LOG_NOTICE, "Invalid baud rate '%s' specified in %s (line %d), using default\n", v->value, config_file, v->lineno);
baud_rate = B9600; baud_rate = B9600;
} }
} else if(!strcasecmp(v->name, "msdstrip")) { } else if (!strcasecmp(v->name, "msdstrip")) {
if(!sscanf(v->value, "%d", &msdstrip)) { if (!sscanf(v->value, "%d", &msdstrip)) {
ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno); ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno);
msdstrip = 0; msdstrip = 0;
} else if(0 > msdstrip || msdstrip > 9) { } else if (0 > msdstrip || msdstrip > 9) {
ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno); ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno);
msdstrip = 0; msdstrip = 0;
} }
} else if(!strcasecmp(v->name, "msgexpirytime")) { } else if (!strcasecmp(v->name, "msgexpirytime")) {
if(!sscanf(v->value, "%ld", &msg_expiry)) { if (!sscanf(v->value, "%ld", &msg_expiry)) {
ast_log(LOG_NOTICE, "Invalid msgexpirytime value in %s (line %d), using default\n", config_file, v->lineno); ast_log(LOG_NOTICE, "Invalid msgexpirytime value in %s (line %d), using default\n", config_file, v->lineno);
msg_expiry = SMDI_MSG_EXPIRY_TIME; msg_expiry = SMDI_MSG_EXPIRY_TIME;
} }
} else if(!strcasecmp(v->name, "paritybit")) { } else if (!strcasecmp(v->name, "paritybit")) {
if(!strcasecmp(v->value, "even")) { if (!strcasecmp(v->value, "even"))
paritybit = PARENB; paritybit = PARENB;
} else if(!strcasecmp(v->value, "odd")) { else if (!strcasecmp(v->value, "odd"))
paritybit = PARENB | PARODD; paritybit = PARENB | PARODD;
} else if(!strcasecmp(v->value, "none")) { else if (!strcasecmp(v->value, "none"))
paritybit = ~PARENB; paritybit = ~PARENB;
} else { else {
ast_log(LOG_NOTICE, "Invalid parity bit setting in %s (line %d), using default\n", config_file, v->lineno); ast_log(LOG_NOTICE, "Invalid parity bit setting in %s (line %d), using default\n", config_file, v->lineno);
paritybit = PARENB; paritybit = PARENB;
} }
} else if(!strcasecmp(v->name, "charsize")) { } else if (!strcasecmp(v->name, "charsize")) {
if(!strcasecmp(v->value, "7")) { if (!strcasecmp(v->value, "7"))
charsize = CS7; charsize = CS7;
} else if(!strcasecmp(v->value, "8")) { else if (!strcasecmp(v->value, "8"))
charsize = CS8; charsize = CS8;
} else { else {
ast_log(LOG_NOTICE, "Invalid character size setting in %s (line %d), using default\n", config_file, v->lineno); ast_log(LOG_NOTICE, "Invalid character size setting in %s (line %d), using default\n", config_file, v->lineno);
charsize = CS7; charsize = CS7;
} }
} else if(!strcasecmp(v->name, "twostopbits")) { } else if (!strcasecmp(v->name, "twostopbits")) {
stopbits = ast_true(v->name); stopbits = ast_true(v->name);
} else if(!strcasecmp(v->name, "smdiport")) { } else if (!strcasecmp(v->name, "smdiport")) {
if(reload) { if (reload) {
/* we are reloading, check if we are already /* we are reloading, check if we are already
* monitoring this interface, if we are we do * monitoring this interface, if we are we do
* not want to start it again. This also has * not want to start it again. This also has
@ -622,57 +603,48 @@ static int smdi_load(int reload)
* restarting the interface. Or the interface * restarting the interface. Or the interface
* could be restarted with out emptying the * could be restarted with out emptying the
* queue. */ * queue. */
iface = ASTOBJ_CONTAINER_FIND(&smdi_ifaces, v->value); if ((iface = ASTOBJ_CONTAINER_FIND(&smdi_ifaces, v->value))) {
if(iface) {
ast_log(LOG_NOTICE, "SMDI interface %s already running, not restarting\n", iface->name); ast_log(LOG_NOTICE, "SMDI interface %s already running, not restarting\n", iface->name);
ASTOBJ_UNMARK(iface); ASTOBJ_UNMARK(iface);
ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
v = v->next;
continue; continue;
} }
} }
iface = malloc(sizeof(struct ast_smdi_interface)); iface = ast_calloc(1, sizeof(*iface));
ASTOBJ_INIT(iface); ASTOBJ_INIT(iface);
ASTOBJ_CONTAINER_INIT(&iface->md_q); ASTOBJ_CONTAINER_INIT(&iface->md_q);
ASTOBJ_CONTAINER_INIT(&iface->mwi_q); ASTOBJ_CONTAINER_INIT(&iface->mwi_q);
iface->md_q.head = NULL;
iface->mwi_q.head = NULL;
iface->thread = AST_PTHREADT_NULL;
memset(&iface->mode, 0, sizeof(iface->mode));
ast_copy_string(iface->name, v->value, sizeof(iface->name)); ast_copy_string(iface->name, v->value, sizeof(iface->name));
iface->file = fopen(iface->name, "r"); if (!(iface->file = fopen(iface->name, "r"))) {
if(!(iface->file)) {
ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s)\n", iface->name, strerror(errno)); ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s)\n", iface->name, strerror(errno));
ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
v = v->next;
continue; continue;
} }
iface->fd = fileno(iface->file); iface->fd = fileno(iface->file);
/* Set the proper attributes for our serial port. */ /* Set the proper attributes for our serial port. */
/* get the current attributes from the port */ /* get the current attributes from the port */
if(tcgetattr(iface->fd, &iface->mode)) { if (tcgetattr(iface->fd, &iface->mode)) {
ast_log(LOG_ERROR, "Error getting atributes of %s (%s)\n", iface->name, strerror(errno)); ast_log(LOG_ERROR, "Error getting atributes of %s (%s)\n", iface->name, strerror(errno));
ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
v = v->next;
continue; continue;
} }
/* set the desired speed */ /* set the desired speed */
if(cfsetispeed(&iface->mode, baud_rate) || cfsetospeed(&iface->mode, baud_rate)) { if (cfsetispeed(&iface->mode, baud_rate) || cfsetospeed(&iface->mode, baud_rate)) {
ast_log(LOG_ERROR, "Error setting baud rate on %s (%s)\n", iface->name, strerror(errno)); ast_log(LOG_ERROR, "Error setting baud rate on %s (%s)\n", iface->name, strerror(errno));
ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
v = v->next;
continue; continue;
} }
/* set the stop bits */ /* set the stop bits */
if(stopbits) if (stopbits)
iface->mode.c_cflag = iface->mode.c_cflag | CSTOPB; /* set two stop bits */ iface->mode.c_cflag = iface->mode.c_cflag | CSTOPB; /* set two stop bits */
else else
iface->mode.c_cflag = iface->mode.c_cflag & ~CSTOPB; /* set one stop bit */ iface->mode.c_cflag = iface->mode.c_cflag & ~CSTOPB; /* set one stop bit */
@ -684,10 +656,9 @@ static int smdi_load(int reload)
iface->mode.c_cflag = (iface->mode.c_cflag & ~CSIZE) | charsize; iface->mode.c_cflag = (iface->mode.c_cflag & ~CSIZE) | charsize;
/* commit the desired attributes */ /* commit the desired attributes */
if(tcsetattr(iface->fd, TCSAFLUSH, &iface->mode)) { if (tcsetattr(iface->fd, TCSAFLUSH, &iface->mode)) {
ast_log(LOG_ERROR, "Error setting attributes on %s (%s)\n", iface->name, strerror(errno)); ast_log(LOG_ERROR, "Error setting attributes on %s (%s)\n", iface->name, strerror(errno));
ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
v = v->next;
continue; continue;
} }
@ -698,15 +669,16 @@ static int smdi_load(int reload)
iface->msg_expiry = msg_expiry; iface->msg_expiry = msg_expiry;
/* start the listner thread */ /* start the listner thread */
if(option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Starting SMDI monitor thread for %s\n", iface->name); ast_verbose(VERBOSE_PREFIX_3 "Starting SMDI monitor thread for %s\n", iface->name);
if(ast_pthread_create(&iface->thread, NULL, smdi_read, iface)) { if (ast_pthread_create(&iface->thread, NULL, smdi_read, iface)) {
ast_log(LOG_ERROR, "Error starting SMDI monitor thread for %s\n", iface->name); ast_log(LOG_ERROR, "Error starting SMDI monitor thread for %s\n", iface->name);
ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
v = v->next;
continue; continue;
} }
ASTOBJ_CONTAINER_LINK(&smdi_ifaces, iface); ASTOBJ_CONTAINER_LINK(&smdi_ifaces, iface);
ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
ast_mutex_lock(&localuser_lock); ast_mutex_lock(&localuser_lock);
localusecnt++; localusecnt++;
ast_mutex_unlock(&localuser_lock); ast_mutex_unlock(&localuser_lock);
@ -719,11 +691,12 @@ static int smdi_load(int reload)
ast_config_destroy(conf); ast_config_destroy(conf);
/* Prune any interfaces we should no longer monitor. */ /* Prune any interfaces we should no longer monitor. */
if(reload) if (reload)
ASTOBJ_CONTAINER_PRUNE_MARKED(&smdi_ifaces, ast_smdi_interface_destroy); ASTOBJ_CONTAINER_PRUNE_MARKED(&smdi_ifaces, ast_smdi_interface_destroy);
ASTOBJ_CONTAINER_RDLOCK(&smdi_ifaces); ASTOBJ_CONTAINER_RDLOCK(&smdi_ifaces);
if(!smdi_ifaces.head) /* TODO: this is bad, we need an ASTOBJ method for this! */
if (!smdi_ifaces.head)
res = 1; res = 1;
ASTOBJ_CONTAINER_UNLOCK(&smdi_ifaces); ASTOBJ_CONTAINER_UNLOCK(&smdi_ifaces);
@ -733,33 +706,32 @@ static int smdi_load(int reload)
char *description(void) char *description(void)
{ {
return (char *)tdesc; return (char *) tdesc;
} }
int load_module(void) int load_module(void)
{ {
int res; int res;
/* initilize our containers */ /* initialize our containers */
memset(&smdi_ifaces, 0, sizeof(smdi_ifaces));
ASTOBJ_CONTAINER_INIT(&smdi_ifaces); ASTOBJ_CONTAINER_INIT(&smdi_ifaces);
smdi_ifaces.head = NULL;
/* load the config and start the listener threads*/ /* load the config and start the listener threads*/
res = smdi_load(0); res = smdi_load(0);
if(res < 0) { if (res < 0) {
return res; return res;
} else if(res == 1) { } else if (res == 1) {
ast_log(LOG_WARNING, "No SMDI interfaces are available to listen on, not starting SDMI listener.\n"); ast_log(LOG_WARNING, "No SMDI interfaces are available to listen on, not starting SDMI listener.\n");
return 0; return 0;
} } else
return 0; return 0;
} }
int unload_module(void) int unload_module(void)
{ {
/* this destructor stops any running smdi_read threads */ /* this destructor stops any running smdi_read threads */
ASTOBJ_CONTAINER_DESTROYALL(&smdi_ifaces,ast_smdi_interface_destroy); ASTOBJ_CONTAINER_DESTROYALL(&smdi_ifaces, ast_smdi_interface_destroy);
ASTOBJ_CONTAINER_DESTROY(&smdi_ifaces); ASTOBJ_CONTAINER_DESTROY(&smdi_ifaces);
return 0; return 0;
@ -768,23 +740,24 @@ int unload_module(void)
int reload(void) int reload(void)
{ {
int res; int res;
res = smdi_load(1); res = smdi_load(1);
if(res < 0) { if (res < 0) {
return res; return res;
} else if(res == 1) { } else if (res == 1) {
ast_log(LOG_WARNING, "No SMDI interfaces were specified to listen on, not starting SDMI listener.\n"); ast_log(LOG_WARNING, "No SMDI interfaces were specified to listen on, not starting SDMI listener.\n");
return 0; return 0;
} } else
/* notify the listner thread? */
return 0; return 0;
} }
int usecount(void) int usecount(void)
{ {
int res; int res;
STANDARD_USECOUNT(res); STANDARD_USECOUNT(res);
return res; return res;
} }

Loading…
Cancel
Save