[asterisk-commits] russell: trunk r62292 - in /trunk: ./ apps/
channels/ configs/ include/ inclu...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Sat Apr 28 14:01:44 MST 2007
Author: russell
Date: Sat Apr 28 16:01:44 2007
New Revision: 62292
URL: http://svn.digium.com/view/asterisk?view=rev&rev=62292
Log:
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.
Added:
trunk/include/asterisk/event.h
- copied unchanged from r62291, team/russell/events/include/asterisk/event.h
trunk/include/asterisk/event_defs.h
- copied unchanged from r62291, team/russell/events/include/asterisk/event_defs.h
trunk/main/event.c
- copied unchanged from r62291, team/russell/events/main/event.c
trunk/res/res_eventtest.c
- copied unchanged from r62291, team/russell/events/res/res_eventtest.c
Modified:
trunk/CHANGES
trunk/UPGRADE.txt
trunk/apps/app_voicemail.c
trunk/channels/chan_iax2.c
trunk/channels/chan_mgcp.c
trunk/channels/chan_sip.c
trunk/channels/chan_zap.c
trunk/configs/sip.conf.sample
trunk/configs/voicemail.conf.sample
trunk/include/asterisk.h
trunk/main/Makefile
trunk/main/asterisk.c
trunk/main/dial.c
Modified: trunk/CHANGES
URL: http://svn.digium.com/view/asterisk/trunk/CHANGES?view=diff&rev=62292&r1=62291&r2=62292
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Sat Apr 28 16:01:44 2007
@@ -53,6 +53,10 @@
registration data, as before.
* The SIPPEER function have new options for port address, call and pickup groups
* Added support for T.140 realtime text in SIP/RTP
+ * The "checkmwi" option has been removed from sip.conf, as it is no longer
+ required due to the restructuring of how MWI is handled. See the descriptions
+ in this file of the "pollmailboxes" and "pollfreq" options to voicemail.conf
+ for more information.
IAX2 changes
------------
@@ -79,6 +83,18 @@
prompts within the Voicemail application by changing them in voicemail.conf
* Added the ability for the "voicemail show users" CLI command to show users
configured by the dynamic realtime configuration method.
+ * MWI (Message Waiting Indication) handling has been significantly
+ restructured internally to Asterisk. It is now totally event based
+ instead of polling based. The voicemail application will notify other
+ modules that have subscribed to MWI events when something in the mailbox
+ changes.
+ This also means that if any other entity outside of Asterisk is changing
+ the contents of mailboxes, then the voicemail application still needs to
+ poll for changes. Examples of situations that would require this option
+ are web interfaces to voicemail or an email client in the case of using
+ IMAP storage. So, two new options have been added to voicemail.conf
+ to account for this: "pollmailboxes" and "pollfreq". See the sample
+ configuration file for details.
Queue changes
-------------
Modified: trunk/UPGRADE.txt
URL: http://svn.digium.com/view/asterisk/trunk/UPGRADE.txt?view=diff&rev=62292&r1=62291&r2=62292
==============================================================================
--- trunk/UPGRADE.txt (original)
+++ trunk/UPGRADE.txt Sat Apr 28 16:01:44 2007
@@ -24,13 +24,24 @@
style' layout introduced in Asterisk 1.4 (and used by the automatic
sound file installer in the Makefile).
-Applications:
+Voicemail:
* The voicemail configuration values 'maxmessage' and 'minmessage' have
been changed to 'maxsecs' and 'minsecs' to clarify their purpose and
to make them more distinguishable from 'maxmsgs', which sets folder
size. The old variables will continue to work in this version, albeit
with a deprecation warning.
+* If you use any interface for modifying voicemail aside from the built in
+ dialplan applications, then the option "pollmailboxes" *must* be set in
+ voicemail.conf for message waiting indication (MWI) to work properly. This
+ is because Voicemail notification is now event based instead of polling
+ based. The channel drivers are no longer responsible for constantly manually
+ checking mailboxes for changes so that they can send MWI information to users.
+ Examples of situations that would require this option are web interfaces to
+ voicemail or an email client in the case of using IMAP storage.
+
+Applications:
+
* ChanIsAvail() now has a 't' option, which allows the specified device
to be queried for state without consulting the channel drivers. This
performs mostly a 'ChanExists' sort of function.
Modified: trunk/apps/app_voicemail.c
URL: http://svn.digium.com/view/asterisk/trunk/apps/app_voicemail.c?view=diff&rev=62292&r1=62291&r2=62292
==============================================================================
--- trunk/apps/app_voicemail.c (original)
+++ trunk/apps/app_voicemail.c Sat Apr 28 16:01:44 2007
@@ -104,6 +104,7 @@
#include "asterisk/utils.h"
#include "asterisk/stringfields.h"
#include "asterisk/smdi.h"
+#include "asterisk/event.h"
#ifdef ODBC_STORAGE
#include "asterisk/res_odbc.h"
@@ -313,7 +314,8 @@
unsigned char iobuf[BASEMAXINLINE];
};
-/*! Structure for linked list of users */
+/*! Structure for linked list of users
+ * Use ast_vm_user_destroy() to free one of these structures. */
struct ast_vm_user {
char context[AST_MAX_CONTEXT]; /*!< Voicemail context */
char mailbox[AST_MAX_EXTENSION]; /*!< Mailbox id, unique within vm context */
@@ -527,6 +529,42 @@
static int maxgreet;
static int skipms;
static int maxlogins;
+
+/*! Poll mailboxes for changes since there is something external to
+ * app_voicemail that may change them. */
+static unsigned int poll_mailboxes;
+
+/*! Polling frequency */
+static unsigned int poll_freq;
+/*! By default, poll every 30 seconds */
+#define DEFAULT_POLL_FREQ 30
+
+AST_MUTEX_DEFINE_STATIC(poll_lock);
+static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER;
+static pthread_t poll_thread = AST_PTHREADT_NULL;
+static unsigned char poll_thread_run;
+
+/*! Subscription to ... MWI event subscriptions */
+static struct ast_event_sub *mwi_sub_sub;
+/*! Subscription to ... MWI event un-subscriptions */
+static struct ast_event_sub *mwi_unsub_sub;
+
+/*!
+ * \brief An MWI subscription
+ *
+ * This is so we can keep track of which mailboxes are subscribed to.
+ * This way, we know which mailboxes to poll when the pollmailboxes
+ * option is being used.
+ */
+struct mwi_sub {
+ AST_RWLIST_ENTRY(mwi_sub) entry;
+ int old_new;
+ int old_old;
+ uint32_t uniqueid;
+ char mailbox[1];
+};
+
+static AST_RWLIST_HEAD_STATIC(mwi_subs, mwi_sub);
/* custom password sounds */
static char vm_password[80] = "vm-password";
@@ -2258,8 +2296,10 @@
static void free_user(struct ast_vm_user *vmu)
{
- if (ast_test_flag(vmu, VM_ALLOCED))
- free(vmu);
+ if (!ast_test_flag(vmu, VM_ALLOCED))
+ return;
+
+ free(vmu);
}
static void free_zone(struct vm_zone *z)
@@ -4002,6 +4042,35 @@
return cmd;
}
+static void queue_mwi_event(const char *mbox, int new, int old)
+{
+ struct ast_event *event;
+ char *mailbox;
+
+ /* Strip off @default */
+ mailbox = ast_strdupa(mbox);
+ if (strstr(mailbox, "@default"))
+ mailbox = strsep(&mailbox, "@");
+
+ if (ast_event_check_subscriber(AST_EVENT_MWI,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
+ AST_EVENT_IE_END) == AST_EVENT_SUB_NONE) {
+ return;
+ }
+
+ if (!(event = ast_event_new(AST_EVENT_MWI,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
+ AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, new,
+ AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
+ AST_EVENT_IE_END))) {
+ return;
+ }
+
+ ast_event_queue_and_cache(event,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
+ AST_EVENT_IE_END);
+}
+
static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname)
{
char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
@@ -4049,6 +4118,8 @@
/* Leave voicemail for someone */
if (ast_app_has_voicemail(ext_context, NULL))
ast_app_inboxcount(ext_context, &newmsgs, &oldmsgs);
+
+ queue_mwi_event(ext_context, newmsgs, oldmsgs);
manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s@%s\r\nWaiting: %d\r\nNew: %d\r\nOld: %d\r\n", vmu->mailbox, vmu->context, ast_app_has_voicemail(ext_context, NULL), newmsgs, oldmsgs);
run_externnotify(vmu->context, vmu->mailbox);
@@ -6833,9 +6904,12 @@
if (vmu)
close_mailbox(&vms, vmu);
if (valid) {
+ int new = 0, old = 0;
snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
run_externnotify(vmu->context, vmu->mailbox);
+ ast_app_inboxcount(ext_context, &new, &old);
+ queue_mwi_event(ext_context, new, old);
}
#ifdef IMAP_STORAGE
/* expunge message - use UID Expunge if supported on IMAP server*/
@@ -6939,20 +7013,25 @@
static struct ast_vm_user *find_or_create(char *context, char *mbox)
{
struct ast_vm_user *vmu;
+
AST_LIST_TRAVERSE(&users, vmu, list) {
if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mbox, vmu->mailbox))
break;
if (context && (!strcasecmp(context, vmu->context)) && (!strcasecmp(mbox, vmu->mailbox)))
break;
}
+
+ if (vmu)
+ return vmu;
- if (!vmu) {
- if ((vmu = ast_calloc(1, sizeof(*vmu)))) {
- ast_copy_string(vmu->context, context, sizeof(vmu->context));
- ast_copy_string(vmu->mailbox, mbox, sizeof(vmu->mailbox));
- AST_LIST_INSERT_TAIL(&users, vmu, list);
- }
- }
+ if (!(vmu = ast_calloc(1, sizeof(*vmu))))
+ return NULL;
+
+ ast_copy_string(vmu->context, context, sizeof(vmu->context));
+ ast_copy_string(vmu->mailbox, mbox, sizeof(vmu->mailbox));
+
+ AST_LIST_INSERT_TAIL(&users, vmu, list);
+
return vmu;
}
@@ -6963,24 +7042,36 @@
char *stringp;
char *s;
struct ast_vm_user *vmu;
+ char *mailbox_full;
+ int new = 0, old = 0;
tmp = ast_strdupa(data);
- if ((vmu = find_or_create(context, mbox))) {
- populate_defaults(vmu);
-
- stringp = tmp;
- if ((s = strsep(&stringp, ",")))
- ast_copy_string(vmu->password, s, sizeof(vmu->password));
- if (stringp && (s = strsep(&stringp, ",")))
- ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
- if (stringp && (s = strsep(&stringp, ",")))
- ast_copy_string(vmu->email, s, sizeof(vmu->email));
- if (stringp && (s = strsep(&stringp, ",")))
- ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
- if (stringp && (s = strsep(&stringp, ",")))
- apply_options(vmu, s);
- }
+ if (!(vmu = find_or_create(context, mbox)))
+ return -1;
+
+ populate_defaults(vmu);
+
+ stringp = tmp;
+ if ((s = strsep(&stringp, ",")))
+ ast_copy_string(vmu->password, s, sizeof(vmu->password));
+ if (stringp && (s = strsep(&stringp, ",")))
+ ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
+ if (stringp && (s = strsep(&stringp, ",")))
+ ast_copy_string(vmu->email, s, sizeof(vmu->email));
+ if (stringp && (s = strsep(&stringp, ",")))
+ ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
+ if (stringp && (s = strsep(&stringp, ",")))
+ apply_options(vmu, s);
+
+ mailbox_full = alloca(strlen(mbox) + strlen(context) + 1);
+ strcpy(mailbox_full, mbox);
+ strcat(mailbox_full, "@");
+ strcat(mailbox_full, context);
+
+ inboxcount(mailbox_full, &new, &old);
+ queue_mwi_event(mailbox_full, new, old);
+
return 0;
}
@@ -7256,6 +7347,160 @@
handle_voicemail_show_zones, "List zone message formats",
voicemail_show_zones_help, NULL, NULL },
};
+
+static void poll_subscribed_mailboxes(void)
+{
+ struct mwi_sub *mwi_sub;
+
+ AST_RWLIST_RDLOCK(&mwi_subs);
+ AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
+ int new = 0, old = 0;
+
+ if (ast_strlen_zero(mwi_sub->mailbox))
+ continue;
+
+ inboxcount(mwi_sub->mailbox, &new, &old);
+
+ if (new != mwi_sub->old_new || old != mwi_sub->old_old) {
+ mwi_sub->old_new = new;
+ mwi_sub->old_old = old;
+ queue_mwi_event(mwi_sub->mailbox, new, old);
+ }
+ }
+ AST_RWLIST_UNLOCK(&mwi_subs);
+}
+
+static void *mb_poll_thread(void *data)
+{
+ while (poll_thread_run) {
+ struct timespec ts = { 0, };
+ struct timeval tv;
+
+ tv = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+
+ ast_mutex_lock(&poll_lock);
+ ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
+ ast_mutex_unlock(&poll_lock);
+
+ if (!poll_thread_run)
+ break;
+
+ poll_subscribed_mailboxes();
+ }
+
+ return NULL;
+}
+
+static void mwi_sub_destroy(struct mwi_sub *mwi_sub)
+{
+ free(mwi_sub);
+}
+
+static void mwi_unsub_event_cb(const struct ast_event *event, void *userdata)
+{
+ uint32_t uniqueid;
+ struct mwi_sub *mwi_sub;
+
+ if (ast_event_get_type(event) != AST_EVENT_UNSUB)
+ return;
+
+ if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
+ return;
+
+ uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
+
+ AST_RWLIST_WRLOCK(&mwi_subs);
+ AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
+ if (mwi_sub->uniqueid == uniqueid) {
+ AST_LIST_REMOVE_CURRENT(&mwi_subs, entry);
+ break;
+ }
+ }
+ AST_RWLIST_TRAVERSE_SAFE_END
+ AST_RWLIST_UNLOCK(&mwi_subs);
+
+ if (mwi_sub)
+ mwi_sub_destroy(mwi_sub);
+}
+
+static void mwi_sub_event_cb(const struct ast_event *event, void *userdata)
+{
+ const char *mailbox;
+ uint32_t uniqueid;
+ unsigned int len;
+ struct mwi_sub *mwi_sub;
+
+ if (ast_event_get_type(event) != AST_EVENT_SUB)
+ return;
+
+ if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
+ return;
+
+ mailbox = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
+ uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
+
+ len = sizeof(*mwi_sub);
+ if (!ast_strlen_zero(mailbox))
+ len += strlen(mailbox);
+
+ if (!(mwi_sub = ast_calloc(1, len)))
+ return;
+
+ mwi_sub->uniqueid = uniqueid;
+ if (!ast_strlen_zero(mailbox))
+ strcpy(mwi_sub->mailbox, mailbox);
+
+ AST_RWLIST_WRLOCK(&mwi_subs);
+ AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
+ AST_RWLIST_UNLOCK(&mwi_subs);
+}
+
+static void start_poll_thread(void)
+{
+ pthread_attr_t attr;
+
+ mwi_sub_sub = ast_event_subscribe(AST_EVENT_SUB, mwi_sub_event_cb, NULL,
+ AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI,
+ AST_EVENT_IE_END);
+
+ mwi_unsub_sub = ast_event_subscribe(AST_EVENT_UNSUB, mwi_unsub_event_cb, NULL,
+ AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI,
+ AST_EVENT_IE_END);
+
+ if (mwi_sub_sub)
+ ast_event_report_subs(mwi_sub_sub);
+
+ poll_thread_run = 1;
+
+ pthread_attr_init(&attr);
+ ast_pthread_create(&poll_thread, &attr, mb_poll_thread, NULL);
+ pthread_attr_destroy(&attr);
+}
+
+static void stop_poll_thread(void)
+{
+ poll_thread_run = 0;
+
+ if (mwi_sub_sub) {
+ ast_event_unsubscribe(mwi_sub_sub);
+ mwi_sub_sub = NULL;
+ }
+
+ if (mwi_unsub_sub) {
+ ast_event_unsubscribe(mwi_unsub_sub);
+ mwi_unsub_sub = NULL;
+ }
+
+ ast_mutex_lock(&poll_lock);
+ ast_cond_signal(&poll_cond);
+ ast_mutex_unlock(&poll_lock);
+
+ pthread_join(poll_thread, NULL);
+
+ poll_thread = AST_PTHREADT_NULL;
+}
static int load_config(void)
{
@@ -7641,6 +7886,19 @@
if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory")))
val = "no";
ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD);
+
+ poll_freq = DEFAULT_POLL_FREQ;
+ if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
+ if (sscanf(val, "%u", &poll_freq) != 1) {
+ poll_freq = DEFAULT_POLL_FREQ;
+ ast_log(LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
+ }
+ }
+
+ poll_mailboxes = 0;
+ if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
+ poll_mailboxes = ast_true(val);
+
if ((ucfg = ast_config_load("users.conf"))) {
for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
@@ -7800,6 +8058,12 @@
}
AST_LIST_UNLOCK(&users);
ast_config_destroy(cfg);
+
+ if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
+ start_poll_thread();
+ if (!poll_mailboxes && poll_thread != AST_PTHREADT_NULL)
+ stop_poll_thread();;
+
return 0;
} else {
AST_LIST_UNLOCK(&users);
@@ -7810,13 +8074,13 @@
static int reload(void)
{
- return(load_config());
+ return load_config();
}
static int unload_module(void)
{
int res;
-
+
res = ast_unregister_application(app);
res |= ast_unregister_application(app2);
res |= ast_unregister_application(app3);
@@ -7827,28 +8091,31 @@
ast_module_user_hangup_all();
+ if (poll_thread != AST_PTHREADT_NULL)
+ stop_poll_thread();
+
return res;
}
static int load_module(void)
{
int res;
+
+ /* compute the location of the voicemail spool directory */
+ snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
+
+ if ((res = load_config()))
+ return res;
+
res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
res |= ast_register_application(app2, vm_execmain, synopsis_vmain, descrip_vmain);
res |= ast_register_application(app3, vm_box_exists, synopsis_vm_box_exists, descrip_vm_box_exists);
res |= ast_register_application(app4, vmauthenticate, synopsis_vmauthenticate, descrip_vmauthenticate);
res |= ast_custom_function_register(&mailbox_exists_acf);
if (res)
- return(res);
-
- if ((res=load_config())) {
- return(res);
- }
+ return res;
ast_cli_register_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry));
-
- /* compute the location of the voicemail spool directory */
- snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
ast_install_vm_functions(has_voicemail, inboxcount, messagecount);
Modified: trunk/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_iax2.c?view=diff&rev=62292&r1=62291&r2=62292
==============================================================================
--- trunk/channels/chan_iax2.c (original)
+++ trunk/channels/chan_iax2.c Sat Apr 28 16:01:44 2007
@@ -91,6 +91,7 @@
#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 @@
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;
};
@@ -882,6 +885,13 @@
.func_channel_read = acf_channel_read,
.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)
{
@@ -5546,9 +5556,38 @@
return 0;
}
+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, ®->addr.sin_addr, ®->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(®istrations);
+ AST_LIST_INSERT_HEAD(®istrations, reg, entry);
+ AST_LIST_UNLOCK(®istrations);
+
+ return 0;
+}
+
static int iax2_register(char *value, int lineno)
{
- struct iax2_registry *reg;
char copy[256];
char *username, *hostname, *secret;
char *porta;
@@ -5556,18 +5595,21 @@
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,25 +5617,10 @@
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, ®->addr.sin_addr, ®->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(®istrations);
- AST_LIST_INSERT_HEAD(®istrations, reg, entry);
- AST_LIST_UNLOCK(®istrations);
-
- return 0;
-}
+
+ return iax2_append_register(hostname, username, secret, porta);
+}
+
static void register_peer_exten(struct iax2_peer *peer, int onoff)
{
@@ -5790,13 +5817,27 @@
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 @@
{
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 @@
/* 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;
}
@@ -9064,6 +9113,9 @@
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);
Modified: trunk/channels/chan_mgcp.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_mgcp.c?view=diff&rev=62292&r1=62291&r2=62292
==============================================================================
--- trunk/channels/chan_mgcp.c (original)
+++ trunk/channels/chan_mgcp.c Sat Apr 28 16:01:44 2007
@@ -76,6 +76,7 @@
#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 @@
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 @@
.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 @@
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 @@
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);
Modified: trunk/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_sip.c?view=diff&rev=62292&r1=62291&r2=62292
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Sat Apr 28 16:01:44 2007
@@ -142,6 +142,7 @@
#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 @@
#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_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 @@
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 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 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 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);
@@ -2599,6 +2597,11 @@
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);
@@ -8733,6 +8736,16 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
}
/*! \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;
-
- /* Check for messages */
- ast_app_inboxcount(peer->mailbox, &newmsgs, &oldmsgs);
+ int newmsgs = 0, oldmsgs = 0;
+ struct ast_event *cache_event = NULL;
+
+ if (ast_test_flag((&peer->flags[1]), SIP_PAGE2_SUBSCRIBEMWIONLY) && !peer->mwipvt)
+ return 0;
+
+ 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);
- 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) {
- return 0;
- }
-
-
- peer->lastmsgssent = ((newmsgs > 0x7fff ? 0x7fff0000 : (newmsgs << 16)) | (oldmsgs > 0xffff ? 0xffff : oldmsgs));
-
if (peer->mwipvt) {
/* Base message on subscription */
p = peer->mwipvt;
@@ -15724,29 +15751,13 @@
/* 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;
-}
-
/*! \brief helper function for the monitoring thread */
static void check_rtp_timeout(struct sip_pvt *dialog, time_t t)
@@ -15823,11 +15834,7 @@
{
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 @@
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 @@
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 @@
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 */
@@ -16713,7 +16690,6 @@
struct ast_flags peerflags[2] = {{(0)}};
struct ast_flags mask[2] = {{(0)}};
char callback[256] = "";
-
if (!realtime)
/* Note we do NOT use find_peer here, to avoid realtime recursion */
@@ -16953,7 +16929,22 @@
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 @@
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 @@
[... 231 lines stripped ...]
More information about the asterisk-commits
mailing list