Merged revisions 104119 via svnmerge from

https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r104119 | russell | 2008-02-25 18:25:29 -0600 (Mon, 25 Feb 2008) | 33 lines

Merge changes from team/russell/smdi-1.4

This commit brings in a significant set of changes to the SMDI support in Asterisk.
There were a number of bugs in the current implementation, most notably being that
it was very likely on busy systems to pop off the wrong message from the SMDI message
queue.  So, this set of changes fixes the issues discovered as well as introducing
some new ways to use the SMDI support which are required to avoid the bugs with
grabbing the wrong message off of the queue.

This code introduces a new interface to SMDI, with two dialplan functions.  First,
you get an SMDI message in the dialplan using SMDI_MSG_RETRIEVE() and then you access
details in the message using the SMDI_MSG() function.  A side benefit of this is that
it now supports more than just chan_zap.

For example, with this implementation, you can have some FXO lines being terminated 
on a SIP gateway, but the SMDI link in Asterisk.

Another issue with the current implementation is that it is quite common that the
station ID that comes in on the SMDI link is not necessarily the same as the Asterisk
voicemail box.  There are now additional directives in the smdi.conf configuration
file which let you map SMDI station IDs to Asterisk voicemail boxes.

Yet another issue with the current SMDI support was related to MWI reporting over
the SMDI link.  The current code could only report a MWI change when the change
was made by someone calling into voicemail.  If the change was made by some other
entity (such as with IMAP storage, or with a web interface of some kind), then the
MWI change would never be sent.  The SMDI module can now poll for MWI changes if
configured to do so.

This work was inspired by and primarily done for the University of Pennsylvania.

(also related to issue #9260)

........


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@104120 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.6.0
Russell Bryant 17 years ago
parent 7f97d296be
commit 3a8756c9b4

@ -2976,8 +2976,8 @@ static void run_externnotify(char *context, char *extension)
else
ast_smdi_mwi_unset(smdi_iface, extension);
if ((mwi_msg = ast_smdi_mwi_message_wait(smdi_iface, SMDI_MWI_WAIT_TIMEOUT))) {
ast_log(LOG_ERROR, "Error executing SMDI MWI change for %s on %s\n", extension, smdi_iface->name);
if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
ast_log(LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
if (!strncmp(mwi_msg->cause, "INV", 3))
ast_log(LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
else if (!strncmp(mwi_msg->cause, "BLK", 3))
@ -2985,7 +2985,7 @@ static void run_externnotify(char *context, char *extension)
ast_log(LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
} else {
ast_debug(1, "Successfully executed SMDI MWI change for %s on %s\n", extension, smdi_iface->name);
ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
}
}
@ -8411,8 +8411,6 @@ static int load_config(int reload)
}
if (!smdi_iface) {
ast_log(LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
} else {
ast_debug(1, "Using SMDI port %s\n", smdi_iface->name);
}
}

@ -2764,7 +2764,7 @@ static void destroy_zt_pvt(struct zt_pvt **pvt)
if (p->next)
p->next->prev = p->prev;
if (p->use_smdi)
ASTOBJ_UNREF(p->smdi_iface, ast_smdi_interface_destroy);
ast_smdi_interface_unref(p->smdi_iface);
if (p->mwi_event_sub)
ast_event_unsubscribe(p->mwi_event_sub);
if (p->vars)

@ -41,3 +41,35 @@
;msgexpirytime = 30000
;smdiport => /dev/ttyS0
[mailboxes]
; This section configures parameters related to MWI handling for the SMDI link.
; This option configures the polling interval used to check to see if the
; mailboxes have any new messages. This option is specified in seconds.
; The default value is 10 seconds.
;
;pollinginterval=10
; Every other entry in this section of the configuration file is interpreted as
; a mapping between the mailbox ID on the SMDI link, and the local Asterisk
; mailbox name. In many cases, they are the same thing, but they still must be
; listed here so that this module knows which mailboxes it needs to pay
; attention to.
;
; Syntax:
; <SMDI mailbox ID>=<Asterisk Mailbox Name>[@Asterisk Voicemail Context]
;
; If no Asterisk voicemail context is specified, "default" will be assumed.
;
; Before specifying mailboxes, you must specify an SMDI interface. All mailbox
; definitions that follow will correspond to that SMDI interface. If you specify
; another interface, then all definitions following that will correspond to the
; new interface.
;
;smdiport=/dev/ttyS0
;2565551234=1234@vmcontext1
;2565555678=5678@vmcontext2
;smdiport=/dev/ttyS1
;2565559999=9999

@ -1,9 +1,10 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Copyright (C) 2005-2006, Digium, Inc.
* Copyright (C) 2005-2008, Digium, Inc.
*
* Matthew A. Nicholson <mnicholson@digium.com>
* Russell Bryant <russell@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@ -20,6 +21,7 @@
* \file
* \brief SMDI support for Asterisk.
* \author Matthew A. Nicholson <mnicholson@digium.com>
* \author Russell Bryant <russell@digium.com>
*/
@ -73,16 +75,6 @@ struct ast_smdi_md_message {
struct timeval timestamp; /* a timestamp for the message */
};
/*! \brief SMDI message desk message queue. */
struct ast_smdi_md_queue {
ASTOBJ_CONTAINER_COMPONENTS(struct ast_smdi_md_message);
};
/*! \brief SMDI message waiting indicator message queue. */
struct ast_smdi_mwi_queue {
ASTOBJ_CONTAINER_COMPONENTS(struct ast_smdi_mwi_message);
};
/*!
* \brief SMDI interface structure.
*
@ -90,38 +82,114 @@ struct ast_smdi_mwi_queue {
* should be monitored for SMDI activity. The structure contains a message
* queue of messages that have been received on the interface.
*/
struct ast_smdi_interface {
ASTOBJ_COMPONENTS_FULL(struct ast_smdi_interface, SMDI_MAX_FILENAME_LEN, 1);
struct ast_smdi_md_queue md_q;
struct ast_smdi_mwi_queue mwi_q;
FILE *file;
int fd;
pthread_t thread;
struct termios mode;
int msdstrip;
long msg_expiry;
};
struct ast_smdi_interface;
void ast_smdi_interface_unref(struct ast_smdi_interface *iface);
/* MD message queue functions */
/*!
* \brief Get the next SMDI message from the queue.
* \param iface a pointer to the interface to use.
*
* This function pulls the first unexpired message from the SMDI message queue
* on the specified interface. It will purge all expired SMDI messages before
* returning.
*
* \return the next SMDI message, or NULL if there were no pending messages.
*/
struct ast_smdi_md_message *ast_smdi_md_message_pop(struct ast_smdi_interface *iface);
/*!
* \brief Get the next SMDI message from the queue.
* \param iface a pointer to the interface to use.
* \param timeout the time to wait before returning in milliseconds.
*
* This function pulls a message from the SMDI message queue on the specified
* interface. If no message is available this function will wait the specified
* amount of time before returning.
*
* \return the next SMDI message, or NULL if there were no pending messages and
* the timeout has expired.
*/
struct ast_smdi_md_message *ast_smdi_md_message_wait(struct ast_smdi_interface *iface, int timeout);
/*!
* \brief Put an SMDI message back in the front of the queue.
* \param iface a pointer to the interface to use.
* \param md_msg a pointer to the message to use.
*
* This function puts a message back in the front of the specified queue. It
* should be used if a message was popped but is not going to be processed for
* some reason, and the message needs to be returned to the queue.
*/
void ast_smdi_md_message_putback(struct ast_smdi_interface *iface, struct ast_smdi_md_message *msg);
/* MWI message queue functions */
/*!
* \brief Get the next SMDI message from the queue.
* \param iface a pointer to the interface to use.
*
* This function pulls the first unexpired message from the SMDI message queue
* on the specified interface. It will purge all expired SMDI messages before
* returning.
*
* \return the next SMDI message, or NULL if there were no pending messages.
*/
struct ast_smdi_mwi_message *ast_smdi_mwi_message_pop(struct ast_smdi_interface *iface);
/*!
* \brief Get the next SMDI message from the queue.
* \param iface a pointer to the interface to use.
* \param timeout the time to wait before returning in milliseconds.
*
* This function pulls a message from the SMDI message queue on the specified
* interface. If no message is available this function will wait the specified
* amount of time before returning.
*
* \return the next SMDI message, or NULL if there were no pending messages and
* the timeout has expired.
*/
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_station(struct ast_smdi_interface *iface,
int timeout, const char *station);
/*!
* \brief Put an SMDI message back in the front of the queue.
* \param iface a pointer to the interface to use.
* \param mwi_msg a pointer to the message to use.
*
* This function puts a message back in the front of the specified queue. It
* should be used if a message was popped but is not going to be processed for
* some reason, and the message needs to be returned to the queue.
*/
void ast_smdi_mwi_message_putback(struct ast_smdi_interface *iface, struct ast_smdi_mwi_message *msg);
/*!
* \brief Find an SMDI interface with the specified name.
* \param iface_name the name/port of the interface to search for.
*
* \return a pointer to the interface located or NULL if none was found. This
* actually returns an ASTOBJ reference and should be released using
* #ASTOBJ_UNREF(iface, ast_smdi_interface_destroy).
*/
struct ast_smdi_interface *ast_smdi_interface_find(const char *iface_name);
/* MWI functions */
/*!
* \brief Set the MWI indicator for a mailbox.
* \param iface the interface to use.
* \param mailbox the mailbox to use.
*/
int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox);
/*!
* \brief Unset the MWI indicator for a mailbox.
* \param iface the interface to use.
* \param mailbox the mailbox to use.
*/
int ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox);
/*! \brief ast_smdi_md_message destructor. */
void ast_smdi_md_message_destroy(struct ast_smdi_md_message *msg);
void ast_smdi_mwi_message_destroy(struct ast_smdi_mwi_message *msg);
void ast_smdi_interface_destroy(struct ast_smdi_interface *iface);
/*! \brief ast_smdi_mwi_message destructor. */
void ast_smdi_mwi_message_destroy(struct ast_smdi_mwi_message *msg);
#endif /* !ASTERISK_SMDI_H */

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save