Hi
For those interested.
I've ported the following solution:
http://bugs.digium.com/view.php?id=4236
for asterisk 1.2.10
it works well.
To activate MWI over IAX2 add the following line in sip.conf or
zaptel.conf etc...
mailbox=IAX2/{iax2_context}/[EMAIL PROTECTED]
For some weird reason though, on my panasonic while I can hear the
message waiting tone, the little enveloppe icon doesn't appear on the
phone
The patch against 1.2.10 is attached to this email.
I have also ported this solution:
http://bugs.digium.com/view.php?id=4371
to asterisk 1.2.10 if anyone is interested.. It's more powerful but
much more complicated to configure ...
Jean-Yves
On 7/31/06, Jean-Yves Avenard <[EMAIL PROTECTED]> wrote:
Hi
On 7/27/06, Luki <[EMAIL PROTECTED]> wrote:
> There is this old patch that does remote MWI over IAX (among other
> things). I used it on earlier versions and it worked quite nicely.
> This was before 1.2 so it may no longer work at all. At the very least
> it will likely required some updating. Doable, just depends how much
> time you want to put into it :).
I think I got it working with Asterisk 1.2.10. I can see the mailbox
information being sent between the two servers.
However, my SPA3000 is still not getting the MWI properly. I believe
that the problem is with the configuration file. I'm not sure I fully
understand the information provided: in the bug report there are
several conflicting setup and I'm not sure which one is good.
Setup being:
SPA3000 ->(SIP) Asterisk1 --->(IAX2) Asterisk2
and I want SPA3000 to check if there's voicemail waiting on Asterisk2.
On Asterisk2:
in iax.conf I have:
[iax_peer_name_to_asterisk1]
type=friend
mailbox=500
host=dynamic
...
in voicemail.conf
voicemail_server=iax_peer_name_to_asterisk1
[default]
[EMAIL PROTECTED] => password,email etc..
On Asterisk1:
iax.conf:
[iax_peername_to_asterisk2]
type=friend
username=iax_peer_name_to_asterisk1
secret=..
host=asterisk2_hostname
sip.conf:
[spa3000]
mailbox=500:[EMAIL PROTECTED]
Am I correct?
I haven't digged too much in the source code, I'm starting to have a
good understanding but any help would be appreciated.
JY
diff -r -u asterisk-1.2.10/app.c asterisk-wmi.patch/app.c
--- asterisk-1.2.10/app.c 2006-07-13 01:46:56.000000000 +1000
+++ asterisk-wmi.patch/app.c 2006-08-01 03:02:08.000000000 +1000
@@ -232,6 +232,8 @@
static int (*ast_has_voicemail_func)(const char *mailbox, const char *folder) = NULL;
static int (*ast_messagecount_func)(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL;
+static int (*ast_iax_has_voicemail_func)(const char *mailbox, const char *folder) = NULL;
+static int (*ast_iax_messagecount_func)(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL;
void ast_install_vm_functions(int (*has_voicemail_func)(const char *mailbox, const char *folder),
int (*messagecount_func)(const char *mailbox, int *newmsgs, int *oldmsgs))
@@ -246,35 +248,135 @@
ast_messagecount_func = NULL;
}
+void ast_install_iax_vm_functions(int (*iax_has_voicemail_func)(const char *mailbox, const char *folder),
+ int (*iax_messagecount_func)(const char *mailbox, int *newmsgs, int *oldmsgs))
+{
+ ast_iax_has_voicemail_func = iax_has_voicemail_func;
+ ast_iax_messagecount_func = iax_messagecount_func;
+}
+
+void ast_uninstall_iax_vm_functions(void)
+{
+ ast_iax_has_voicemail_func = NULL;
+ ast_iax_messagecount_func = NULL;
+}
+
int ast_app_has_voicemail(const char *mailbox, const char *folder)
{
- static int warned = 0;
- if (ast_has_voicemail_func)
- return ast_has_voicemail_func(mailbox, folder);
-
- if ((option_verbose > 2) && !warned) {
- ast_verbose(VERBOSE_PREFIX_3 "Message check requested for mailbox %s/folder %s but voicemail not loaded.\n", mailbox, folder ? folder : "INBOX");
- warned++;
+ static int loc_warned = 0;
+ static int iax_warned = 0;
+ char *workspace, *mbp, *comma;
+ int ret = 0;
+
+ if (!mailbox)
+ return 0;
+
+ workspace = mbp = strdup(mailbox);
+ if (!workspace)
+ return 0;
+
+ while (*mbp) {
+ if ((comma = strchr(mbp, ',')))
+ *comma++ = '\0';
+
+ if (strncasecmp("iax2/", mbp, 5) == 0) {
+ if (!ast_iax_has_voicemail_func) {
+ if (!iax_warned && (option_verbose > 2)) {
+ ast_verbose(VERBOSE_PREFIX_3 "Message check requested for %s/folder %s but IAX voicemail checks not loaded.\n", mailbox, folder ? folder : "INBOX");
+ iax_warned++;
+ }
+ ret = 0;
+ } else
+ ret = ast_iax_has_voicemail_func(mbp + 5, folder);
+ } else { /* local voicemail system check */
+ if (!ast_has_voicemail_func) {
+ if (!loc_warned && (option_verbose > 2)) {
+ ast_verbose(VERBOSE_PREFIX_3 "Message check requested for mailbox %s/folder %s but voicemail checks not loaded.\n", mailbox, folder ? folder : "INBOX");
+ loc_warned++;
+ }
+ ret = 0;
+ } else
+ ret = ast_has_voicemail_func(mbp, folder);
+ }
+
+ if (ret)
+ break;
+
+ if (comma)
+ mbp = comma;
+ else
+ break;
}
- return 0;
-}
+ free(workspace);
+ return ret;
+}
int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
{
- static int warned = 0;
- if (newmsgs)
+ static int loc_warned = 0;
+ static int iax_warned = 0;
+ char *workspace, *mbp, *comma;
+ int tmpnew = 0, tmpold = 0, ret = 0;
+ int *ptmpnew = NULL, *ptmpold = NULL;
+
+ if (newmsgs) {
*newmsgs = 0;
- if (oldmsgs)
+ ptmpnew = &tmpnew;
+ }
+
+ if (oldmsgs) {
*oldmsgs = 0;
- if (ast_messagecount_func)
- return ast_messagecount_func(mailbox, newmsgs, oldmsgs);
+ ptmpold = &tmpold;
+ }
+
+ if (!mailbox)
+ return 0;
+
+ workspace = mbp = strdup(mailbox);
+ if (!workspace)
+ return 0;
- if (!warned && (option_verbose > 2)) {
- warned++;
- ast_verbose(VERBOSE_PREFIX_3 "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox);
+ while (*mbp) {
+ if ((comma = strchr(mbp, ',')))
+ *comma++ = '\0';
+
+ if (strncasecmp("iax2/", mbp, 5) == 0) {
+ if (!ast_iax_has_voicemail_func) {
+ if (!iax_warned && (option_verbose > 2)) {
+ ast_verbose(VERBOSE_PREFIX_3 "Message count requested for mailbox %s but IAX voicemail checks not loaded.\n", mailbox);
+ iax_warned++;
+ }
+ ret = tmpnew = tmpold = 0;
+ } else
+ ret = ast_iax_messagecount_func(mbp + 5, ptmpnew, ptmpold);
+ } else { /* local voicemail system check */
+ if (!ast_has_voicemail_func) {
+ if (!loc_warned && (option_verbose > 2)) {
+ ast_verbose(VERBOSE_PREFIX_3 "Message count requested for mailbox %s but voicemail checks not loaded.\n", mailbox);
+ loc_warned++;
+ }
+ ret = tmpnew = tmpold = 0;
+ } else
+ ret = ast_messagecount_func(mbp, ptmpnew, ptmpold);
+ }
+
+ /* XXX messagecount function always returns zero right now */
+ if (ret == 0) {
+ if (newmsgs)
+ *newmsgs += tmpnew;
+
+ if (oldmsgs)
+ *oldmsgs += tmpold;
+ }
+
+ if (comma)
+ mbp = comma;
+ else
+ break;
}
+ free(workspace);
return 0;
}
diff -r -u asterisk-1.2.10/apps/app_voicemail.c asterisk-wmi.patch/apps/app_voicemail.c
--- asterisk-1.2.10/apps/app_voicemail.c 2006-07-14 07:22:11.000000000 +1000
+++ asterisk-wmi.patch/apps/app_voicemail.c 2006-08-01 03:35:16.000000000 +1000
@@ -75,8 +75,8 @@
#endif
#define COMMAND_TIMEOUT 5000
-#define VOICEMAIL_DIR_MODE 0700
-#define VOICEMAIL_FILE_MODE 0600
+#define VOICEMAIL_DIR_MODE 0770
+#define VOICEMAIL_FILE_MODE 0660
#define VOICEMAIL_CONFIG "voicemail.conf"
#define ASTERISK_USERNAME "asterisk"
@@ -2187,26 +2187,12 @@
struct dirent *de;
char fn[256];
char tmp[256]="";
- char *mb, *cur;
char *context;
- int ret;
if (!folder)
folder = "INBOX";
/* If no mailbox, return immediately */
if (ast_strlen_zero(mailbox))
return 0;
- if (strchr(mailbox, ',')) {
- ast_copy_string(tmp, mailbox, sizeof(tmp));
- mb = tmp;
- ret = 0;
- while((cur = strsep(&mb, ","))) {
- if (!ast_strlen_zero(cur)) {
- if (has_voicemail(cur, folder))
- return 1;
- }
- }
- return 0;
- }
ast_copy_string(tmp, mailbox, sizeof(tmp));
context = strchr(tmp, '@');
if (context) {
@@ -2235,9 +2221,7 @@
struct dirent *de;
char fn[256];
char tmp[256]="";
- char *mb, *cur;
char *context;
- int ret;
if (newmsgs)
*newmsgs = 0;
if (oldmsgs)
@@ -2245,25 +2229,6 @@
/* If no mailbox, return immediately */
if (ast_strlen_zero(mailbox))
return 0;
- if (strchr(mailbox, ',')) {
- int tmpnew, tmpold;
- ast_copy_string(tmp, mailbox, sizeof(tmp));
- mb = tmp;
- ret = 0;
- while((cur = strsep(&mb, ", "))) {
- if (!ast_strlen_zero(cur)) {
- if (messagecount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
- return -1;
- else {
- if (newmsgs)
- *newmsgs += tmpnew;
- if (oldmsgs)
- *oldmsgs += tmpold;
- }
- }
- }
- return 0;
- }
ast_copy_string(tmp, mailbox, sizeof(tmp));
context = strchr(tmp, '@');
if (context) {
diff -r -u asterisk-1.2.10/channels/chan_iax2.c asterisk-wmi.patch/channels/chan_iax2.c
--- asterisk-1.2.10/channels/chan_iax2.c 2006-07-13 01:23:59.000000000 +1000
+++ asterisk-wmi.patch/channels/chan_iax2.c 2006-08-01 03:13:51.000000000 +1000
@@ -561,6 +561,11 @@
/*! IAX_ flags */
unsigned int flags;
+ /* Remote message waiting information */
+ int remotemwi; /* if this is a remote mwi request */
+ int rmwicomm; /* part of a pipe to wake up waiting mwi query task */
+ int rmwicount; /* message count for remote MWI */
+
/*! Transferring status */
enum iax_transfer_state transferring;
/*! Transfer identifier */
@@ -6330,6 +6335,178 @@
iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo;
}
+static int iax2_req_remotemwi(const char *mailbox, int *newmsgs, int *oldmsgs)
+{
+ int callno;
+ int iowp[2];
+ int timeout = 500; /* Wait 500ms for reply */
+ struct pollfd pfd;
+ int ret;
+ struct iax_ie_data ied;
+ struct sockaddr_in sin;
+ struct create_addr_info cai;
+
+ char wksp[256], *s;
+ char *username = NULL;
+ char *password = NULL;
+ char *host = NULL;
+ char *portno = NULL;
+ char *extenctx = NULL;
+
+ ast_log(LOG_DEBUG, "Performing IAX2 remote MWI for '%s'\n", mailbox);
+
+ if (newmsgs)
+ *newmsgs = 0;
+
+ if (oldmsgs)
+ *oldmsgs = 0;
+
+ /*
+ * Parse out the mailbox spec, of the form:
+ *
+ * --------- IAX spec ------------- ---- Mailbox ----
+ * [username[:[EMAIL PROTECTED]:port]/[EMAIL PROTECTED]
+ *
+ * Where host can also be an IAX peer name from iax.conf
+ */
+ memset(wksp, 0, 256);
+ strncpy(wksp, mailbox, sizeof(wksp)-1);
+
+ s = strchr(wksp, '/');
+ if (s) {
+ *s++ = '\0';
+ extenctx = s;
+ } else
+ return -1;
+
+ s = strchr(wksp, '@');
+ if (s) {
+ *s++ = '\0';
+ host = s;
+
+ username = wksp;
+
+ password = strchr(username, ':');
+ if (password)
+ *password++ = '\0';
+ } else
+ host = wksp;
+
+ portno = strchr(host, ':');
+ if (portno)
+ *portno++ = '\0';
+
+ /*
+ * Find peer by peername or hostname (host can be either,
+ * depending on whether it appears as a peer in iax.conf)
+ */
+
+ memset(&cai, 0, sizeof(cai));
+ if (create_addr(host, &sin, &cai))
+ return -1;
+
+ if (portno)
+ sin.sin_port = htons(atoi(portno));
+
+ callno = find_callno(0, 0, &sin, NEW_ALLOW, 1, cai.sockfd);
+ if (!callno) {
+ ast_log(LOG_WARNING, "Unable to generate call for remotemwi to '%s'\n", host);
+ return -1;
+ }
+
+ ast_mutex_lock(&iaxsl[callno]);
+ memset(&ied, 0, sizeof(ied));
+
+ iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
+ if (username) {
+ iax_ie_append_str(&ied, IAX_IE_USERNAME, username);
+ if (password)
+ strncpy(iaxs[callno]->secret, password, sizeof(iaxs[callno]->secret)-1);
+ } else if (cai.found) {
+ iax_ie_append_str(&ied, IAX_IE_USERNAME, cai.username);
+ strncpy(iaxs[callno]->secret, cai.secret, sizeof(iaxs[callno]->secret)-1);
+ }
+
+ send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, ied.buf, ied.pos, -1);
+
+ if (iaxs[callno]) {
+ if (pipe(iowp)) {
+ ast_log(LOG_WARNING, "Unable to create pipe for remote MWI I/O wait\n");
+ ast_mutex_unlock(&iaxsl[callno]);
+ return -1;
+ }
+
+ ast_log(LOG_DEBUG, "IAX2 remote MWI callno %d valid\n", callno);
+ iaxs[callno]->remotemwi = 1;
+ iaxs[callno]->rmwicomm = iowp[1];
+
+ memset(&ied, 0, sizeof(ied));
+ iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, extenctx);
+ send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_MWI, 0, ied.buf, ied.pos, -1);
+ ast_mutex_unlock(&iaxsl[callno]);
+ } else {
+ ast_log(LOG_DEBUG, "IAX2 remote MWI callno %d no longer valid\n", callno);
+ ast_mutex_unlock(&iaxsl[callno]);
+ return -1;
+ }
+
+ pfd.fd = iowp[0];
+ pfd.events = POLLIN | POLLPRI;
+ pfd.revents = 0;
+
+ ret = -1;
+ while (ret < 0) {
+ ret = poll(&pfd, 1, timeout);
+ if (ret < 0 || errno != EINTR)
+ break;
+ }
+
+ close(iowp[1]);
+ close(iowp[0]);
+
+ if (ret == 0) {
+ ast_log(LOG_WARNING, "Timeout on pipe waiting for reponse to remote MWI to '%s'\n", host);
+ return -1;
+ } else if (ret < 0) {
+ ast_log(LOG_WARNING, "Error %d on pipe waiting for reponse to remote MWI to '%s'\n", errno, host);
+ return -1;
+ }
+
+ if (iaxs[callno]) {
+ ast_mutex_lock(&iaxsl[callno]);
+ ast_log(LOG_DEBUG, "Success IAX2 remote MWI to '%s' for '%s' = %d/%d\n", host, extenctx,
+ iaxs[callno]->rmwicount >> 8, iaxs[callno]->rmwicount & 0xff);
+ if (oldmsgs)
+ *oldmsgs = iaxs[callno]->rmwicount >> 8;
+ if (newmsgs)
+ *newmsgs = iaxs[callno]->rmwicount & 0xff;
+ iaxs[callno]->remotemwi = 0;
+ iaxs[callno]->rmwicomm = 0;
+ iax2_destroy_nolock(callno);
+ ast_mutex_unlock(&iaxsl[callno]);
+ }
+
+ return 0;
+}
+
+static int iax_has_voicemail(const char *mailbox, const char *folder)
+{
+ int newmsgs, ret;
+
+ /* XXX folder is ignored right now (always INBOX)... */
+ ret = iax2_req_remotemwi(mailbox, &newmsgs, NULL);
+
+ if (ret || newmsgs == 0)
+ return 0;
+ else
+ return 1;
+}
+
+static int iax_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
+{
+ return iax2_req_remotemwi(mailbox, newmsgs, oldmsgs);
+}
+
static int socket_read(int *id, int fd, short events, void *cbdata)
{
struct sockaddr_in sin;
@@ -7589,6 +7766,43 @@
else
send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1);
break;
+ case IAX_COMMAND_MWI:
+ if (ies.called_number) {
+ /*
+ * means this is a request from another
+ * PBX for local mwi information
+ */
+ int new, old, msgcount;
+ struct iax_ie_data ied;
+
+ ast_log(LOG_DEBUG, "IAX2 MWI frame received, called number %s\n", ies.called_number);
+
+ memset(&ied, 0, sizeof(ied));
+ (void)ast_app_messagecount(ies.called_number, &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 (iaxs[fr->callno])
+ send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_MWI, 0, ied.buf, ied.pos, -1);
+ } else {
+ ast_log(LOG_DEBUG, "IAX2 MWI frame received - response\n");
+ /*
+ * means this should be a reply from a previously
+ * requested MWI query on this PBX
+ */
+ if (iaxs[fr->callno] && iaxs[fr->callno]->remotemwi) {
+ const char *anything = "x";
+
+ iaxs[fr->callno]->rmwicount = ies.msgcount;
+ (void)write(iaxs[fr->callno]->rmwicomm, anything, sizeof *anything);
+ }
+ }
+ break;
default:
ast_log(LOG_DEBUG, "Unknown IAX command %d on %d/%d\n", f.subclass, fr->callno, iaxs[fr->callno]->peercallno);
memset(&ied0, 0, sizeof(ied0));
@@ -9622,6 +9836,7 @@
int unload_module()
{
+ ast_uninstall_iax_vm_functions();
ast_mutex_destroy(&iaxq.lock);
ast_mutex_destroy(&userl.lock);
ast_mutex_destroy(&peerl.lock);
@@ -9721,6 +9936,7 @@
ast_mutex_unlock(&peerl.lock);
reload_firmware();
iax_provision_reload();
+ ast_install_iax_vm_functions(iax_has_voicemail, iax_messagecount);
return res;
}
diff -r -u asterisk-1.2.10/include/asterisk/app.h asterisk-wmi.patch/include/asterisk/app.h
--- asterisk-1.2.10/include/asterisk/app.h 2006-05-06 06:44:53.000000000 +1000
+++ asterisk-wmi.patch/include/asterisk/app.h 2006-08-01 03:08:49.000000000 +1000
@@ -107,6 +107,11 @@
void ast_uninstall_vm_functions(void);
+void ast_install_iax_vm_functions(int (*iax_has_voicemail_func)(const char *mailbox, const char *folder),
+ int (*iax_messagecount_func)(const char *mailbox, int *newmsgs, int *oldmsgs));
+
+void ast_uninstall_iax_vm_functions(void);
+
/*! Determine if a given mailbox has any voicemail */
int ast_app_has_voicemail(const char *mailbox, const char *folder);
_______________________________________________
--Bandwidth and Colocation provided by Easynews.com --
asterisk-users mailing list
To UNSUBSCRIBE or update options visit:
http://lists.digium.com/mailman/listinfo/asterisk-users