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

Reply via email to