summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
authorRussell Bryant <russell@russellbryant.com>2007-04-28 21:01:44 +0000
committerRussell Bryant <russell@russellbryant.com>2007-04-28 21:01:44 +0000
commitb6b1bf321330796329e206a427e04c84299b41ba (patch)
treea1a974c0e0c22e01ba079b2655a8d9eb28668653 /channels
parent503b75f885337ec09afafffca178c012e1b6318a (diff)
Merge changes from team/russell/events
This set of changes introduces a new generic event API for use within Asterisk. I am still working on a way for events to be shared between servers, but this part is ready and can already be used inside of Asterisk. This set of changes introduces the first use of the API, as well. I have restructured the way that MWI (message waiting indication) is handled. It is now event based instead of polling based. For example, if there are a bunch of SIP phones subscribed to mailboxes, then chan_sip will not have to constantly poll the mailboxes for changes. app_voicemail will generate events when changes occur. See UPGRADE.txt and CHANGES for some more information on the effects of these changes from the user perspective. For developer information, see the text in include/asterisk/event.h. As always, additional feedback is welcome on the asterisk-dev mailing list. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@62292 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_iax2.c106
-rw-r--r--channels/chan_mgcp.c38
-rw-r--r--channels/chan_sip.c153
-rw-r--r--channels/chan_zap.c36
4 files changed, 218 insertions, 115 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index b6953bcff..6b943ea58 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -91,6 +91,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/netsock.h"
#include "asterisk/stringfields.h"
#include "asterisk/linkedlists.h"
+#include "asterisk/event.h"
#include "iax2.h"
#include "iax2-parser.h"
@@ -367,7 +368,9 @@ struct iax2_peer {
int pokefreqnotok; /*!< How often to check when the host has been determined to be down */
int historicms; /*!< How long recent average responses took */
int smoothing; /*!< Sample over how many units to determine historic ms */
-
+
+ struct ast_event_sub *mwi_event_sub;
+
struct ast_ha *ha;
AST_LIST_ENTRY(iax2_peer) entry;
};
@@ -883,6 +886,13 @@ static const struct ast_channel_tech iax2_tech = {
.func_channel_write = acf_channel_write,
};
+static void mwi_event_cb(const struct ast_event *event, void *userdata)
+{
+ /* The MWI subscriptions exist just so the core knows we care about those
+ * mailboxes. However, we just grab the events out of the cache when it
+ * is time to send MWI, since it is only sent with a REGACK. */
+}
+
static void insert_idle_thread(struct iax2_thread *thread)
{
if (thread->type == IAX_THREAD_TYPE_DYNAMIC) {
@@ -5546,9 +5556,38 @@ static int iax2_ack_registry(struct iax_ies *ies, struct sockaddr_in *sin, int c
return 0;
}
-static int iax2_register(char *value, int lineno)
+static int iax2_append_register(const char *hostname, const char *username,
+ const char *secret, const char *porta)
{
struct iax2_registry *reg;
+
+ if (!(reg = ast_calloc(1, sizeof(*reg))))
+ return -1;
+
+ if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
+ free(reg);
+ return -1;
+ }
+
+ ast_copy_string(reg->username, username, sizeof(reg->username));
+
+ if (secret)
+ ast_copy_string(reg->secret, secret, sizeof(reg->secret));
+
+ reg->expire = -1;
+ reg->refresh = IAX_DEFAULT_REG_EXPIRE;
+ reg->addr.sin_family = AF_INET;
+ reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
+
+ AST_LIST_LOCK(&registrations);
+ AST_LIST_INSERT_HEAD(&registrations, reg, entry);
+ AST_LIST_UNLOCK(&registrations);
+
+ return 0;
+}
+
+static int iax2_register(char *value, int lineno)
+{
char copy[256];
char *username, *hostname, *secret;
char *porta;
@@ -5556,18 +5595,21 @@ static int iax2_register(char *value, int lineno)
if (!value)
return -1;
+
ast_copy_string(copy, value, sizeof(copy));
- stringp=copy;
+ stringp = copy;
username = strsep(&stringp, "@");
hostname = strsep(&stringp, "@");
+
if (!hostname) {
ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno);
return -1;
}
- stringp=username;
+
+ stringp = username;
username = strsep(&stringp, ":");
secret = strsep(&stringp, ":");
- stringp=hostname;
+ stringp = hostname;
hostname = strsep(&stringp, ":");
porta = strsep(&stringp, ":");
@@ -5575,26 +5617,11 @@ static int iax2_register(char *value, int lineno)
ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
return -1;
}
- if (!(reg = ast_calloc(1, sizeof(*reg))))
- return -1;
- if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
- free(reg);
- return -1;
- }
- ast_copy_string(reg->username, username, sizeof(reg->username));
- if (secret)
- ast_copy_string(reg->secret, secret, sizeof(reg->secret));
- reg->expire = -1;
- reg->refresh = IAX_DEFAULT_REG_EXPIRE;
- reg->addr.sin_family = AF_INET;
- reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
- AST_LIST_LOCK(&registrations);
- AST_LIST_INSERT_HEAD(&registrations, reg, entry);
- AST_LIST_UNLOCK(&registrations);
-
- return 0;
+
+ return iax2_append_register(hostname, username, secret, porta);
}
+
static void register_peer_exten(struct iax2_peer *peer, int onoff)
{
char multi[256];
@@ -5790,13 +5817,27 @@ static int update_registry(const char *name, struct sockaddr_in *sin, int callno
iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry);
iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr);
if (!ast_strlen_zero(p->mailbox)) {
+ struct ast_event *event;
int new, old;
- ast_app_inboxcount(p->mailbox, &new, &old);
+
+ event = ast_event_get_cached(AST_EVENT_MWI,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, p->mailbox,
+ AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+ AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+ AST_EVENT_IE_END);
+ if (event) {
+ new = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
+ old = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS);
+ ast_event_destroy(event);
+ } else /* Fall back on checking the mailbox directly */
+ ast_app_inboxcount(p->mailbox, &new, &old);
+
if (new > 255)
new = 255;
if (old > 255)
old = 255;
msgcount = (old << 8) | new;
+
iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount);
}
if (ast_test_flag(p, IAX_HASCALLERID)) {
@@ -8533,9 +8574,9 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
{
struct iax2_peer *peer = NULL;
struct ast_ha *oldha = NULL;
- int maskfound=0;
- int found=0;
- int firstpass=1;
+ int maskfound = 0;
+ int found = 0;
+ int firstpass = 1;
AST_LIST_LOCK(&peers);
if (!temponly) {
@@ -8762,8 +8803,16 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
/* Make sure these are IPv4 addresses */
peer->addr.sin_family = AF_INET;
}
+
if (oldha)
ast_free_ha(oldha);
+
+ if (!ast_strlen_zero(peer->mailbox)) {
+ peer->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, peer->mailbox,
+ AST_EVENT_IE_END);
+ }
+
return peer;
}
@@ -9065,6 +9114,9 @@ static void destroy_peer(struct iax2_peer *peer)
if (peer->dnsmgr)
ast_dnsmgr_release(peer->dnsmgr);
+ if (peer->mwi_event_sub)
+ ast_event_unsubscribe(peer->mwi_event_sub);
+
ast_string_field_free_pools(peer);
free(peer);
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index 27ca2688c..b39e1fbdd 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -76,6 +76,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
+#include "asterisk/event.h"
#ifndef IPTOS_MINCOST
#define IPTOS_MINCOST 0x02
@@ -320,9 +321,10 @@ struct mgcp_endpoint {
char cid_name[AST_MAX_EXTENSION]; /*!< Caller*ID name */
char lastcallerid[AST_MAX_EXTENSION]; /*!< Last Caller*ID */
char call_forward[AST_MAX_EXTENSION]; /*!< Last Caller*ID */
- char mailbox[AST_MAX_EXTENSION];
char musicclass[MAX_MUSICCLASS];
char curtone[80]; /*!< Current tone */
+ char mailbox[AST_MAX_EXTENSION];
+ struct ast_event_sub *mwi_event_sub;
ast_group_t callgroup;
ast_group_t pickupgroup;
int callwaiting;
@@ -450,9 +452,31 @@ static const struct ast_channel_tech mgcp_tech = {
.bridge = ast_rtp_bridge,
};
+static void mwi_event_cb(const struct ast_event *event, void *userdata)
+{
+ /* This module does not handle MWI in an event-based manner. However, it
+ * subscribes to MWI for each mailbox that is configured so that the core
+ * knows that we care about it. Then, chan_mgcp will get the MWI from the
+ * event cache instead of checking the mailbox directly. */
+}
+
static int has_voicemail(struct mgcp_endpoint *p)
{
- return ast_app_has_voicemail(p->mailbox, NULL);
+ int new_msgs;
+ struct ast_event *event;
+
+ event = ast_event_get_cached(AST_EVENT_MWI,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, p->mailbox,
+ AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+ AST_EVENT_IE_END);
+
+ if (event) {
+ new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
+ ast_event_destroy(event);
+ } else
+ new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
+
+ return new_msgs;
}
static int unalloc_sub(struct mgcp_subchannel *sub)
@@ -3740,6 +3764,12 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
ast_copy_string(e->language, language, sizeof(e->language));
ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
+ if (!ast_strlen_zero(e->mailbox)) {
+ e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, e->mailbox,
+ AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+ AST_EVENT_IE_END);
+ }
snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
e->msgstate = -1;
e->amaflags = amaflags;
@@ -4014,6 +4044,10 @@ static void destroy_endpoint(struct mgcp_endpoint *e)
ast_mutex_destroy(&s->cx_queue_lock);
free(s);
}
+
+ if (e->mwi_event_sub)
+ ast_event_unsubscribe(e->mwi_event_sub);
+
ast_mutex_destroy(&e->lock);
ast_mutex_destroy(&e->rqnt_queue_lock);
ast_mutex_destroy(&e->cmd_queue_lock);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index c756549b6..4c6243aaa 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -142,6 +142,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/threadstorage.h"
#include "asterisk/translate.h"
#include "asterisk/version.h"
+#include "asterisk/event.h"
#ifndef FALSE
#define FALSE 0
@@ -503,7 +504,6 @@ static const struct cfsip_options {
#define DEFAULT_VMEXTEN "asterisk"
#define DEFAULT_CALLERID "asterisk"
#define DEFAULT_NOTIFYMIME "application/simple-message-summary"
-#define DEFAULT_MWITIME 10
#define DEFAULT_ALLOWGUEST TRUE
#define DEFAULT_SRVLOOKUP FALSE /*!< Recommended setting is ON */
#define DEFAULT_COMPACTHEADERS FALSE
@@ -560,7 +560,6 @@ static int global_regattempts_max; /*!< Registration attempts before giving up *
static int global_allowguest; /*!< allow unauthenticated users/peers to connect? */
static int global_allowsubscribe; /*!< Flag for disabling ALL subscriptions, this is FALSE only if all peers are FALSE
the global setting is in globals_flags[1] */
-static int global_mwitime; /*!< Time between MWI checks for peers */
static unsigned int global_tos_sip; /*!< IP type of service for SIP packets */
static unsigned int global_tos_audio; /*!< IP type of service for audio RTP packets */
static unsigned int global_tos_video; /*!< IP type of service for video RTP packets */
@@ -1134,7 +1133,6 @@ struct sip_peer {
char useragent[256]; /*!< User agent in SIP request (saved from registration) */
struct ast_codec_pref prefs; /*!< codec prefs */
int lastmsgssent;
- time_t lastmsgcheck; /*!< Last time we checked for MWI */
unsigned int sipoptions; /*!< Supported SIP options */
struct ast_flags flags[2]; /*!< SIP_ flags */
int expire; /*!< When to expire this peer registration */
@@ -1160,6 +1158,7 @@ struct sip_peer {
struct ast_variable *chanvars; /*!< Variables to set for channel created by user */
struct sip_pvt *mwipvt; /*!< Subscription for MWI */
int autoframing;
+ struct ast_event_sub *mwi_event_sub; /*!< The MWI event subscription */
};
@@ -1291,8 +1290,7 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittyp
static void copy_request(struct sip_request *dst, const struct sip_request *src);
static void receive_message(struct sip_pvt *p, struct sip_request *req);
static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req);
-static int sip_send_mwi_to_peer(struct sip_peer *peer);
-static int does_peer_need_mwi(struct sip_peer *peer);
+static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *event, int cache_only);
/*--- Dialog management */
static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
@@ -1363,20 +1361,20 @@ static int reload_config(enum channelreloadreason reason);
static int expire_register(void *data);
static void *do_monitor(void *data);
static int restart_monitor(void);
-static int sip_send_mwi_to_peer(struct sip_peer *peer);
static void sip_destroy(struct sip_pvt *p);
static int sip_addrcmp(char *name, struct sockaddr_in *sin); /* Support for peer matching */
static int sip_refer_allocate(struct sip_pvt *p);
static void ast_quiet_chan(struct ast_channel *chan);
static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target);
-/*--- Device monitoring and Device/extension state handling */
+/*--- Device monitoring and Device/extension state/event handling */
static int cb_extensionstate(char *context, char* exten, int state, void *data);
static int sip_devicestate(void *data);
static int sip_poke_noanswer(void *data);
static int sip_poke_peer(struct sip_peer *peer);
static void sip_poke_all_peers(void);
static void sip_peer_hold(struct sip_pvt *p, int hold);
+static void mwi_event_cb(const struct ast_event *, void *);
/*--- Applications, functions, CLI and manager command helpers */
static const char *sip_nat_mode(const struct sip_pvt *p);
@@ -2600,6 +2598,11 @@ static void sip_destroy_peer(struct sip_peer *peer)
if (peer->mwipvt) /* We have an active subscription, delete it */
sip_destroy(peer->mwipvt);
+ if (peer->mwi_event_sub) {
+ ast_event_unsubscribe(peer->mwi_event_sub);
+ peer->mwi_event_sub = NULL;
+ }
+
if (peer->chanvars) {
ast_variables_destroy(peer->chanvars);
peer->chanvars = NULL;
@@ -8733,6 +8736,16 @@ static void sip_peer_hold(struct sip_pvt *p, int hold)
return;
}
+/*! \brief Receive MWI events that we have subscribed to */
+static void mwi_event_cb(const struct ast_event *event, void *userdata)
+{
+ struct sip_peer *peer = userdata;
+
+ ASTOBJ_RDLOCK(peer);
+ sip_send_mwi_to_peer(peer, event, 0);
+ ASTOBJ_UNLOCK(peer);
+}
+
/*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem
\note If you add an "hint" priority to the extension in the dial plan,
you will get notifications on device state changes */
@@ -8860,7 +8873,7 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
if (!(res = check_auth(p, req, peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri, XMIT_UNRELIABLE, ast_test_flag(req, SIP_PKT_IGNORE)))) {
sip_cancel_destroy(p);
- /* We have a succesful registration attemp with proper authentication,
+ /* We have a successful registration attempt with proper authentication,
now, update the peer */
switch (parse_register_contact(p, peer, req)) {
case PARSE_REGISTER_FAILED:
@@ -11016,7 +11029,6 @@ static int sip_show_settings(int fd, int argc, char *argv[])
ast_cli(fd, " Call limit peers only: %s\n", global_limitonpeers ? "Yes" : "No");
ast_cli(fd, " Direct RTP setup: %s\n", global_directrtpsetup ? "Yes" : "No");
ast_cli(fd, " User Agent: %s\n", global_useragent);
- ast_cli(fd, " MWI checking interval: %d secs\n", global_mwitime);
ast_cli(fd, " Reg. context: %s\n", S_OR(global_regcontext, "(not set)"));
ast_cli(fd, " Caller ID: %s\n", default_callerid);
ast_cli(fd, " From: Domain: %s\n", default_fromdomain);
@@ -15227,6 +15239,11 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
}
p->subscribed = MWI_NOTIFICATION;
+ if (ast_test_flag(&authpeer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY)) {
+ authpeer->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, authpeer,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, authpeer->mailbox,
+ AST_EVENT_IE_END);
+ }
if (authpeer->mwipvt && authpeer->mwipvt != p) /* Destroy old PVT if this is a new one */
/* We only allow one subscription per peer */
sip_destroy(authpeer->mwipvt);
@@ -15273,7 +15290,7 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
transmit_response(p, "200 OK", req);
if (p->relatedpeer) { /* Send first notification */
ASTOBJ_WRLOCK(p->relatedpeer);
- sip_send_mwi_to_peer(p->relatedpeer);
+ sip_send_mwi_to_peer(p->relatedpeer, NULL, 0);
ASTOBJ_UNLOCK(p->relatedpeer);
}
} else {
@@ -15685,25 +15702,35 @@ static int sipsock_read(int *id, int fd, short events, void *ignore)
}
/*! \brief Send message waiting indication to alert peer that they've got voicemail */
-static int sip_send_mwi_to_peer(struct sip_peer *peer)
+static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *event, int cache_only)
{
/* Called with peerl lock, but releases it */
struct sip_pvt *p;
- int newmsgs, oldmsgs;
+ int newmsgs = 0, oldmsgs = 0;
+ struct ast_event *cache_event = NULL;
- /* Check for messages */
- ast_app_inboxcount(peer->mailbox, &newmsgs, &oldmsgs);
-
- peer->lastmsgcheck = time(NULL);
-
- /* Return now if it's the same thing we told them last time */
- if (((newmsgs > 0x7fff ? 0x7fff0000 : (newmsgs << 16)) | (oldmsgs > 0xffff ? 0xffff : oldmsgs)) == peer->lastmsgssent) {
+ if (ast_test_flag((&peer->flags[1]), SIP_PAGE2_SUBSCRIBEMWIONLY) && !peer->mwipvt)
return 0;
- }
-
-
- peer->lastmsgssent = ((newmsgs > 0x7fff ? 0x7fff0000 : (newmsgs << 16)) | (oldmsgs > 0xffff ? 0xffff : oldmsgs));
+ if (!event) {
+ /* Check the event cache for the mailbox info */
+ event = cache_event = ast_event_get_cached(AST_EVENT_MWI,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, peer->mailbox,
+ AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+ AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+ AST_EVENT_IE_END);
+ }
+
+ if (event) {
+ newmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
+ oldmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS);
+ if (cache_event)
+ ast_event_destroy(cache_event);
+ } else if (cache_only) {
+ return 0;
+ } else /* Fall back to manually checking the mailbox */
+ ast_app_inboxcount(peer->mailbox, &newmsgs, &oldmsgs);
+
if (peer->mwipvt) {
/* Base message on subscription */
p = peer->mwipvt;
@@ -15724,30 +15751,14 @@ static int sip_send_mwi_to_peer(struct sip_peer *peer)
/* Destroy this session after 32 secs */
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
}
+
/* Send MWI */
ast_set_flag(&p->flags[0], SIP_OUTGOING);
transmit_notify_with_mwi(p, newmsgs, oldmsgs, peer->vmexten);
- return 0;
-}
-
-/*! \brief Check whether peer needs a new MWI notification check */
-static int does_peer_need_mwi(struct sip_peer *peer)
-{
- time_t t = time(NULL);
-
- if (ast_test_flag(&peer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY) &&
- !peer->mwipvt) { /* We don't have a subscription */
- peer->lastmsgcheck = t; /* Reset timer */
- return FALSE;
- }
- if (!ast_strlen_zero(peer->mailbox) && (t - peer->lastmsgcheck) > global_mwitime)
- return TRUE;
-
- return FALSE;
+ return 0;
}
-
/*! \brief helper function for the monitoring thread */
static void check_rtp_timeout(struct sip_pvt *dialog, time_t t)
{
@@ -15823,11 +15834,7 @@ static void *do_monitor(void *data)
{
int res;
struct sip_pvt *dialog;
- struct sip_peer *peer = NULL;
time_t t;
- int fastrestart = FALSE;
- int lastpeernum = -1;
- int curpeernum;
int reloading;
/* Add an I/O event to our SIP UDP socket */
@@ -15859,7 +15866,7 @@ restartsearch:
of time since the last time we did it (when MWI is being sent, we can
get back to this point every millisecond or less)
*/
- for (dialog = dialoglist; !fastrestart && dialog; dialog = dialog->next) {
+ for (dialog = dialoglist; dialog; dialog = dialog->next) {
sip_pvt_lock(dialog);
/* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */
check_rtp_timeout(dialog, t);
@@ -15881,10 +15888,6 @@ restartsearch:
res = ast_sched_wait(sched);
if ((res < 0) || (res > 1000))
res = 1000;
-
- /* If we might need to send more mailbox notifications, don't wait long at all.*/
- if (fastrestart)
- res = 1;
res = ast_io_wait(io, res);
if (option_debug && res > 20)
ast_log(LOG_DEBUG, "chan_sip: ast_io_wait ran %d all at once\n", res);
@@ -15894,37 +15897,11 @@ restartsearch:
if (option_debug && res >= 20)
ast_log(LOG_DEBUG, "chan_sip: ast_sched_runq ran %d all at once\n", res);
}
-
- /* Send MWI notifications to peers - static and cached realtime peers */
- t = time(NULL);
- fastrestart = FALSE;
- curpeernum = 0;
- peer = NULL;
- /* Find next peer that needs mwi */
- ASTOBJ_CONTAINER_TRAVERSE(&peerl, !peer, do {
- if ((curpeernum > lastpeernum) && does_peer_need_mwi(iterator)) {
- fastrestart = TRUE;
- lastpeernum = curpeernum;
- peer = ASTOBJ_REF(iterator);
- };
- curpeernum++;
- } while (0)
- );
- /* Send MWI to the peer */
- if (peer) {
- ASTOBJ_WRLOCK(peer);
- sip_send_mwi_to_peer(peer);
- ASTOBJ_UNLOCK(peer);
- unref_peer(peer);
- } else {
- /* Reset where we come from */
- lastpeernum = -1;
- }
ast_mutex_unlock(&monlock);
}
+
/* Never reached */
return NULL;
-
}
/*! \brief Start the channel monitor thread */
@@ -16714,7 +16691,6 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
struct ast_flags mask[2] = {{(0)}};
char callback[256] = "";
-
if (!realtime)
/* Note we do NOT use find_peer here, to avoid realtime recursion */
/* We also use a case-sensitive comparison (unlike find_peer) so
@@ -16953,7 +16929,22 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
global_allowsubscribe = TRUE; /* No global ban any more */
if (!found && ast_test_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC) && !ast_test_flag(&peer->flags[0], SIP_REALTIME))
reg_source_db(peer);
+
+ /* If they didn't request that MWI is sent *only* on subscribe, go ahead and
+ * subscribe to it now. */
+ if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY) &&
+ !ast_strlen_zero(peer->mailbox)) {
+ peer->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, peer,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, peer->mailbox,
+ AST_EVENT_IE_END);
+ /* Send MWI from the event cache only. This is so we can send initial
+ * MWI if app_voicemail got loaded before chan_sip. If it is the other
+ * way, then we will get events when app_voicemail gets loaded. */
+ sip_send_mwi_to_peer(peer, NULL, 1);
+ }
+
ASTOBJ_UNMARK(peer);
+
ast_free_ha(oldha);
if (!ast_strlen_zero(callback)) { /* build string from peer info */
char *reg_string;
@@ -17047,7 +17038,6 @@ static int reload_config(enum channelreloadreason reason)
global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT;
global_regattempts_max = 0;
pedanticsipchecking = DEFAULT_PEDANTIC;
- global_mwitime = DEFAULT_MWITIME;
autocreatepeer = DEFAULT_AUTOCREATEPEER;
global_autoframing = 0;
global_allowguest = DEFAULT_ALLOWGUEST;
@@ -17135,11 +17125,6 @@ static int reload_config(enum channelreloadreason reason)
ast_set2_flag(&global_flags[0], ast_true(v->value), SIP_USEREQPHONE);
} else if (!strcasecmp(v->name, "relaxdtmf")) {
global_relaxdtmf = ast_true(v->value);
- } else if (!strcasecmp(v->name, "checkmwi")) {
- if ((sscanf(v->value, "%d", &global_mwitime) != 1) || (global_mwitime < 0)) {
- ast_log(LOG_WARNING, "'%s' is not a valid MWI time setting at line %d. Using default (10).\n", v->value, v->lineno);
- global_mwitime = DEFAULT_MWITIME;
- }
} else if (!strcasecmp(v->name, "vmexten")) {
ast_copy_string(default_vmexten, v->value, sizeof(default_vmexten));
} else if (!strcasecmp(v->name, "rtptimeout")) {
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index 93b01d405..3703b40f9 100644
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -106,6 +106,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/abstract_jb.h"
#include "asterisk/smdi.h"
#include "asterisk/astobj.h"
+#include "asterisk/event.h"
+
#define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
/*! Global jitterbuffer configuration - by default, jb is disabled */
@@ -261,6 +263,14 @@ static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_chann
static int zt_sendtext(struct ast_channel *c, const char *text);
+static void mwi_event_cb(const struct ast_event *event, void *userdata)
+{
+ /* This module does not handle MWI in an event-based manner. However, it
+ * subscribes to MWI for each mailbox that is configured so that the core
+ * knows that we care about it. Then, chan_zap will get the MWI from the
+ * event cache instead of checking the mailbox directly. */
+}
+
/*! \brief Avoid the silly zt_getevent which ignores a bunch of events */
static inline int zt_get_event(int fd)
{
@@ -601,6 +611,7 @@ static struct zt_pvt {
struct tdd_state *tdd; /*!< TDD flag */
char call_forward[AST_MAX_EXTENSION];
char mailbox[AST_MAX_EXTENSION];
+ struct ast_event_sub *mwi_event_sub;
char dialdest[256];
int onhooktime;
int msgstate;
@@ -1831,8 +1842,21 @@ static int send_cwcidspill(struct zt_pvt *p)
static int has_voicemail(struct zt_pvt *p)
{
+ int new_msgs;
+ struct ast_event *event;
- return ast_app_has_voicemail(p->mailbox, NULL);
+ event = ast_event_get_cached(AST_EVENT_MWI,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, p->mailbox,
+ AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+ AST_EVENT_IE_END);
+
+ if (event) {
+ new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
+ ast_event_destroy(event);
+ } else
+ new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
+
+ return new_msgs;
}
static int send_callerid(struct zt_pvt *p)
@@ -2390,6 +2414,8 @@ static void destroy_zt_pvt(struct zt_pvt **pvt)
p->next->prev = p->prev;
if (p->use_smdi)
ASTOBJ_UNREF(p->smdi_iface, ast_smdi_interface_destroy);
+ if (p->mwi_event_sub)
+ ast_event_unsubscribe(p->mwi_event_sub);
ast_mutex_destroy(&p->lock);
free(p);
*pvt = NULL;
@@ -7191,7 +7217,7 @@ static void *do_monitor(void *data)
if (last) {
if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
(last->sig & __ZT_SIG_FXO)) {
- res = ast_app_has_voicemail(last->mailbox, NULL);
+ res = has_voicemail(last);
if (last->msgstate != res) {
int x;
if (option_debug)
@@ -7872,6 +7898,12 @@ static struct zt_pvt *mkintf(int channel, struct zt_chan_conf conf, struct zt_pr
tmp->cid_ton = 0;
ast_copy_string(tmp->cid_name, conf.chan.cid_name, sizeof(tmp->cid_name));
ast_copy_string(tmp->mailbox, conf.chan.mailbox, sizeof(tmp->mailbox));
+ if (!ast_strlen_zero(tmp->mailbox)) {
+ tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, tmp->mailbox,
+ AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+ AST_EVENT_IE_END);
+ }
tmp->msgstate = -1;
tmp->group = conf.chan.group;
tmp->callgroup = conf.chan.callgroup;