[asterisk-commits] file: branch file/bridging r90968 - in /team/file/bridging: ./ apps/ channels...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Dec 4 14:40:11 CST 2007


Author: file
Date: Tue Dec  4 14:40:11 2007
New Revision: 90968

URL: http://svn.digium.com/view/asterisk?view=rev&rev=90968
Log:
Merged revisions 90873,90877-90880,90899,90927-90930,90949 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/trunk

................
r90873 | mmichelson | 2007-12-04 13:08:36 -0400 (Tue, 04 Dec 2007) | 30 lines

Merged revisions 90735 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r90735 | mmichelson | 2007-12-03 17:12:17 -0600 (Mon, 03 Dec 2007) | 22 lines

A big one...

This is the merge of the forward-loop branch. The main change here is that call-forwards can no longer loop.
This is accomplished by creating a datastore on the calling channel which has a linked list of all devices
dialed. If a forward happens, then the local channel which is created inherits the datastore. If, through this
progression of forwards and datastore inheritance, a device is attempted to be dialed a second time, it will simply
be skipped and a warning message will be printed to the CLI. After the dialing has been completed, the datastore
is detached from the channel and destroyed.

This change also introduces some side effects to the code which I shall enumerate here:

1. Datastore inheritance has been backported from trunk into 1.4
2. A large chunk of code has been removed from app_dial. This chunk is the section of code
   which handles the call forward case after the channel has been requested but before it has
   been called. This was removed because call-forwarding still works fine without it, it makes the
   code less error-prone should it need changing, and it made this set of changes much less painful
   to just have the forwarding handled in one place in each module.
3. Two new files, global_datastores.h and .c have been added. These are necessary since the datastore
   which is attached to the channel may be created and attached in either app_dial or app_queue, so they
   need a common place to find the datastore info. This approach was taken in case similar datastores are
   needed in the future, there will be a common place to add them.

........

................
r90877 | qwell | 2007-12-04 13:35:40 -0400 (Tue, 04 Dec 2007) | 1 line

Fix build in trunk.  This was fixed in 1.4, but blocked in trunk since this hadn't been merged yet.
................
r90878 | russell | 2007-12-04 13:36:59 -0400 (Tue, 04 Dec 2007) | 2 lines

Fix a silly little typo :)

................
r90879 | qwell | 2007-12-04 13:38:51 -0400 (Tue, 04 Dec 2007) | 13 lines

Merged revisions 90876 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

(closes issue #11454)
........
r90876 | qwell | 2007-12-04 11:28:08 -0600 (Tue, 04 Dec 2007) | 4 lines

If we fail to create a channel after allocating a timing fd, we need to make sure to close it.

Issue 11454, patch by eliel.

........

................
r90880 | kpfleming | 2007-12-04 13:40:29 -0400 (Tue, 04 Dec 2007) | 2 lines

fix build of this module when libpri and/or libss7 are or are not present

................
r90899 | mmichelson | 2007-12-04 13:51:59 -0400 (Tue, 04 Dec 2007) | 3 lines

Wrong locking style got merged from 1.4 to trunk. My mistake.


................
r90927 | qwell | 2007-12-04 14:09:28 -0400 (Tue, 04 Dec 2007) | 1 line

Fix build, that some people aren't seeing for some reason.
................
r90928 | mmichelson | 2007-12-04 14:14:08 -0400 (Tue, 04 Dec 2007) | 3 lines

Suppress a compiler warning due to discarding a "const" qualifier


................
r90929 | qwell | 2007-12-04 14:15:17 -0400 (Tue, 04 Dec 2007) | 4 lines

Add Makefile alias target 'pdf' which does the same thing as asterisk.pdf.

Issue 11452, reported by blitzrage.

................
r90930 | mmichelson | 2007-12-04 14:29:35 -0400 (Tue, 04 Dec 2007) | 6 lines

Kevin suggested doing the reverse of my last commit, since imap_retrieve_file
does not modify the contents of the "mailbox" string. In other words, I'm changing
the imap_retrieve_file function to take a const char* as the third argument so that I
don't need to cast const char*'s as char*'s to suppress compiler warnings.


................
r90949 | russell | 2007-12-04 15:08:30 -0400 (Tue, 04 Dec 2007) | 15 lines

Add support for monitoring MWI on FXO lines.

This introduces two new options for zapata.conf: mwimonitor and mwimonitornotify.
The mwimonitor option enables MWI monitoring.  When the MWI state on a line changes,
then the script specified by mwimonitornotify will be executed for custom handling
of the state change, similar to the externnotify option of voicemail.conf.

Also, when the MWI state on an FXO line changes, an internal Asterisk event is
generated to indicate the new state of the associated mailbox.  That may, any
module that cares about MWI information will get notified and can handle it
just as if app_voicemail had sent this notification.

(BE-253, original patch from markster, with some minor modifications by me to
 add comments, documentation, and internal event support)

................

Added:
    team/file/bridging/include/asterisk/global_datastores.h
      - copied unchanged from r90949, trunk/include/asterisk/global_datastores.h
    team/file/bridging/main/global_datastores.c
      - copied unchanged from r90949, trunk/main/global_datastores.c
Modified:
    team/file/bridging/   (props changed)
    team/file/bridging/CHANGES
    team/file/bridging/Makefile
    team/file/bridging/apps/app_dial.c
    team/file/bridging/apps/app_queue.c
    team/file/bridging/apps/app_voicemail.c
    team/file/bridging/channels/chan_local.c
    team/file/bridging/channels/chan_zap.c
    team/file/bridging/configs/zapata.conf.sample
    team/file/bridging/include/asterisk/callerid.h
    team/file/bridging/include/asterisk/channel.h
    team/file/bridging/main/Makefile
    team/file/bridging/main/callerid.c
    team/file/bridging/main/channel.c

Propchange: team/file/bridging/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/file/bridging/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Dec  4 14:40:11 2007
@@ -1,1 +1,1 @@
-/trunk:1-90856
+/trunk:1-90967

Modified: team/file/bridging/CHANGES
URL: http://svn.digium.com/view/asterisk/team/file/bridging/CHANGES?view=diff&rev=90968&r1=90967&r2=90968
==============================================================================
--- team/file/bridging/CHANGES (original)
+++ team/file/bridging/CHANGES Tue Dec  4 14:40:11 2007
@@ -277,7 +277,12 @@
   * CID matching information is now shown when doing 'dialplan show'.
   * Added zap show version CLI command to chan_zap.
   * Added setvar support to zapata.conf channel entries.
-
+  * Added two new options: mwimonitor and mwimonitornotify.  These options allow
+     you to enable MWI monitoring on FXO lines.  When the MWI state changes,
+     the script specified in the mwimonitornotify option is executed.  An internal
+	 event indicating the new state of the mailbox is also generated, so that
+	 the normal MWI facilities in Asterisk work as usual.
+ 
 H.323 Changes
 -------------
   * H323 remote hold notification support added (by NOTIFY message

Modified: team/file/bridging/Makefile
URL: http://svn.digium.com/view/asterisk/team/file/bridging/Makefile?view=diff&rev=90968&r1=90967&r2=90968
==============================================================================
--- team/file/bridging/Makefile (original)
+++ team/file/bridging/Makefile Tue Dec  4 14:40:11 2007
@@ -774,7 +774,8 @@
 	@echo "Generating input for menuselect ..."
 	@build_tools/prep_moduledeps > $@
 
+pdf: asterisk.pdf
 asterisk.pdf:
 	$(MAKE) -C doc/tex asterisk.pdf
 
-.PHONY: menuselect main sounds clean dist-clean distclean all prereqs cleantest uninstall _uninstall uninstall-all dont-optimize $(SUBDIRS_INSTALL) $(SUBDIRS_DIST_CLEAN) $(SUBDIRS_CLEAN) $(SUBDIRS_UNINSTALL) $(SUBDIRS) $(MOD_SUBDIRS_EMBED_LDSCRIPT) $(MOD_SUBDIRS_EMBED_LDFLAGS) $(MOD_SUBDIRS_EMBED_LIBS) menuselect.makeopts
+.PHONY: menuselect main sounds clean dist-clean distclean all prereqs cleantest uninstall _uninstall uninstall-all pdf dont-optimize $(SUBDIRS_INSTALL) $(SUBDIRS_DIST_CLEAN) $(SUBDIRS_CLEAN) $(SUBDIRS_UNINSTALL) $(SUBDIRS) $(MOD_SUBDIRS_EMBED_LDSCRIPT) $(MOD_SUBDIRS_EMBED_LDFLAGS) $(MOD_SUBDIRS_EMBED_LIBS) menuselect.makeopts

Modified: team/file/bridging/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/apps/app_dial.c?view=diff&rev=90968&r1=90967&r2=90968
==============================================================================
--- team/file/bridging/apps/app_dial.c (original)
+++ team/file/bridging/apps/app_dial.c Tue Dec  4 14:40:11 2007
@@ -54,6 +54,7 @@
 #include "asterisk/manager.h"
 #include "asterisk/privacy.h"
 #include "asterisk/stringfields.h"
+#include "asterisk/global_datastores.h"
 
 static char *app = "Dial";
 
@@ -326,7 +327,6 @@
 	struct chanlist *next;
 	struct ast_channel *chan;
 	uint64_t flags;
-	int forwards;
 };
 
 
@@ -346,8 +346,6 @@
 		ast_free(oo);
 	}
 }
-
-#define AST_MAX_FORWARDS   8
 
 #define AST_MAX_WATCHERS 256
 
@@ -480,28 +478,22 @@
 		tech = "Local";
 	}
 	/* Before processing channel, go ahead and check for forwarding */
-	o->forwards++;
-	if (o->forwards < AST_MAX_FORWARDS) {
-		ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
-		/* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
-		if (ast_test_flag64(peerflags, OPT_IGNORE_FORWARDING)) {
-			ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
-			c = o->chan = NULL;
-			cause = AST_CAUSE_BUSY;
-		} else {
-			/* Setup parameters */
-			c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
-			if (c) {
-				if (single)
-					ast_channel_make_compatible(o->chan, in);
-				ast_channel_inherit_variables(in, o->chan);
-			} else
-				ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
-		}
+	ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
+	/* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
+	if (ast_test_flag64(peerflags, OPT_IGNORE_FORWARDING)) {
+		ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
+		c = o->chan = NULL;
+		cause = AST_CAUSE_BUSY;
 	} else {
-		ast_verb(3, "Too many forwards from %s\n", c->name);
-		cause = AST_CAUSE_CONGESTION;
-		c = o->chan = NULL;
+		/* Setup parameters */
+		c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
+		if (c) {
+			if (single)
+				ast_channel_make_compatible(o->chan, in);
+			ast_channel_inherit_variables(in, o->chan);
+			ast_channel_datastore_inherit(in, o->chan);
+		} else
+			ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
 	}
 	if (!c) {
 		ast_clear_flag64(o, DIAL_STILLGOING);	
@@ -1252,6 +1244,8 @@
 	);
 	struct ast_flags64 opts = { 0, };
 	char *opt_args[OPT_ARG_ARRAY_SIZE];
+	struct ast_datastore *datastore = NULL;
+	int fulldial = 0, num_dialed = 0;
 
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
@@ -1333,7 +1327,13 @@
 		struct ast_channel *tc;	/* channel for this destination */
 		/* Get a technology/[device:]number pair */
 		char *number = cur;
+		char *interface = ast_strdupa(number);
 		char *tech = strsep(&number, "/");
+		/* find if we already dialed this interface */
+		int dialed = 0;
+		struct ast_dialed_interface *di;
+		AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
+		num_dialed++;
 		if (!number) {
 			ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n");
 			goto out;
@@ -1353,6 +1353,50 @@
 		}
 		ast_copy_string(numsubst, number, sizeof(numsubst));
 		/* Request the peer */
+		if (!(datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL))) {
+			if(!(datastore = ast_channel_datastore_alloc(&dialed_interface_info, NULL))) {
+				ast_log(LOG_WARNING, "Unable to create channel datastore for dialed interfaces. Aborting!\n"); 
+				free(tmp);
+				goto out;
+			}
+			else {
+				datastore->inheritance = DATASTORE_INHERIT_FOREVER;
+				if((dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
+					datastore->data = dialed_interfaces;
+					AST_LIST_HEAD_INIT(dialed_interfaces);
+					ast_channel_datastore_add(chan, datastore);
+				} else {
+					free(tmp);
+					goto out;
+				}
+			}
+		} else 
+			dialed_interfaces = datastore->data;
+		AST_LIST_LOCK(dialed_interfaces);
+		AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
+			/* XXX case sensitive??? */
+			if(!strcasecmp(di->interface, interface)) {
+				dialed = 1;
+				break;
+			}
+		}
+		if(!dialed && strcasecmp(tech, "Local")) {
+			if(!(di = ast_calloc(1, sizeof(*di) + strlen(interface)))) {
+				AST_LIST_UNLOCK(dialed_interfaces);
+				free(tmp);
+				goto out;
+			}
+			strcpy(di->interface, interface);
+			AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
+		} else {
+			AST_LIST_UNLOCK(dialed_interfaces);
+			ast_log(LOG_WARNING, "Skipping dialing interface '%s' again since it has already been dialed\n", di->interface);
+			fulldial++;
+			free(tmp);
+			continue;
+		}
+		AST_LIST_UNLOCK(dialed_interfaces);
+
 		tc = ast_request(tech, chan->nativeformats, numsubst, &cause);
 		if (!tc) {
 			/* If we can't, just go on to the next call */
@@ -1365,50 +1409,6 @@
 			continue;
 		}
 		pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst);
-		if (!ast_strlen_zero(tc->call_forward)) {
-			char tmpchan[256];
-			char *stuff;
-			char *tech;
-			ast_copy_string(tmpchan, tc->call_forward, sizeof(tmpchan));
-			if ((stuff = strchr(tmpchan, '/'))) {
-				*stuff++ = '\0';
-				tech = tmpchan;
-			} else {
-				snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tc->call_forward, tc->context);
-				stuff = tmpchan;
-				tech = "Local";
-			}
-			tmp->forwards++;
-			if (tmp->forwards < AST_MAX_FORWARDS) {
-				ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n",
-					chan->name, tech, stuff, tc->name);
-				ast_hangup(tc);
-				/* If we have been told to ignore forwards, just set this channel to null
-				 * and continue processing extensions normally */
-				if (ast_test_flag64(&opts, OPT_IGNORE_FORWARDING)) {
-					tc = NULL;
-					cause = AST_CAUSE_BUSY;
-					ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n",
-							chan->name, tech, stuff);
-				} else {
-					tc = ast_request(tech, chan->nativeformats, stuff, &cause);
-				}
-				if (!tc)
-					ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
-				else
-					ast_channel_inherit_variables(chan, tc);
-			} else {
-				ast_verb(3, "Too many forwards from %s\n", tc->name);
-				ast_hangup(tc);
-				tc = NULL;
-				cause = AST_CAUSE_CONGESTION;
-			}
-			if (!tc) {
-				handle_cause(cause, &num);
-				ast_free(tmp);
-				continue;
-			}
-		}
 
 		/* Setup outgoing SDP to match incoming one */
 		ast_rtp_make_compatible(tc, chan, !outgoing && !rest);
@@ -1498,6 +1498,10 @@
 
 	if (!outgoing) {
 		strcpy(pa.status, "CHANUNAVAIL");
+		if(fulldial == num_dialed) {
+			res = -1;
+			goto out;
+		}
 	} else {
 		/* Our status will at least be NOANSWER */
 		strcpy(pa.status, "NOANSWER");
@@ -1520,7 +1524,9 @@
 
 	time(&start_time);
 	peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result);
-	
+
+	ast_channel_datastore_remove(chan, datastore);
+	ast_channel_datastore_free(datastore);
 	if (!peer) {
 		if (result) {
 			res = result;

Modified: team/file/bridging/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/apps/app_queue.c?view=diff&rev=90968&r1=90967&r2=90968
==============================================================================
--- team/file/bridging/apps/app_queue.c (original)
+++ team/file/bridging/apps/app_queue.c Tue Dec  4 14:40:11 2007
@@ -87,6 +87,7 @@
 #include "asterisk/event.h"
 #include "asterisk/astobj2.h"
 #include "asterisk/strings.h"
+#include "asterisk/global_datastores.h"
 
 enum {
 	QUEUE_STRATEGY_RINGALL = 0,
@@ -2295,6 +2296,7 @@
 						numnochan++;
 					} else {
 						ast_channel_inherit_variables(in, o->chan);
+						ast_channel_datastore_inherit(in, o->chan);
 						if (o->chan->cid.cid_num)
 							ast_free(o->chan->cid.cid_num);
 						o->chan->cid.cid_num = ast_strdup(in->cid.cid_num);
@@ -2733,6 +2735,7 @@
 	int forwardsallowed = 1;
 	int callcompletedinsl;
 	struct ao2_iterator memi;
+	struct ast_datastore *datastore = ast_channel_datastore_find(qe->chan, &dialed_interface_info, NULL);
 
 	memset(&bridge_config, 0, sizeof(bridge_config));
 	tmpid[0] = 0;
@@ -2802,7 +2805,9 @@
 	memi = ao2_iterator_init(qe->parent->members, 0);
 	while ((cur = ao2_iterator_next(&memi))) {
 		struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
-
+		struct ast_dialed_interface *di;
+		int dialed = 0;
+		AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
 		if (!tmp) {
 			ao2_ref(cur, -1);
 			ao2_unlock(qe->parent);
@@ -2810,6 +2815,49 @@
 				ao2_unlock(queues);
 			goto out;
 		}
+		if (!datastore) {
+			if(!(datastore = ast_channel_datastore_alloc(&dialed_interface_info, NULL))) {
+				ao2_ref(cur, -1);
+				ao2_unlock(qe->parent);
+				if(use_weight)
+					ao2_unlock(queues);
+				free(tmp);
+				goto out;
+			}
+			datastore->inheritance = DATASTORE_INHERIT_FOREVER;
+			dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces));
+			datastore->data = dialed_interfaces;
+			AST_LIST_HEAD_INIT(dialed_interfaces);
+			ast_channel_datastore_add(qe->chan, datastore);
+		} else
+			dialed_interfaces = datastore->data;
+		AST_LIST_LOCK(dialed_interfaces);
+		AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
+			/* XXX case sensitive ?? */
+			if(!strcasecmp(cur->interface, di->interface)) {
+				dialed = 1;
+				break;
+			}
+		}
+		if (!dialed && strncasecmp(cur->interface, "Local/", 6)) {
+			if(!(di = ast_calloc(1, sizeof(*di) + strlen(cur->interface)))) {
+				ao2_ref(cur, -1);
+				AST_LIST_UNLOCK(dialed_interfaces);
+				ao2_unlock(qe->parent);
+				if(use_weight)
+					ao2_unlock(queues);
+				free(tmp);
+				goto out;
+			}
+			strcpy(di->interface, cur->interface);
+			AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
+		} else {
+			AST_LIST_UNLOCK(dialed_interfaces);
+			ast_log(LOG_DEBUG, "Skipping dialing interface '%s' since it has already been dialed\n", di->interface);
+			free(tmp);
+			continue;
+		}
+		AST_LIST_UNLOCK(dialed_interfaces);
 		tmp->stillgoing = -1;
 		tmp->member = cur;
 		tmp->oldstatus = cur->status;
@@ -2842,6 +2890,8 @@
 	if (use_weight)
 		ao2_unlock(queues);
 	lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
+	ast_channel_datastore_remove(qe->chan, datastore);
+	ast_channel_datastore_free(datastore);
 	ao2_lock(qe->parent);
 	if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
 		store_next_rr(qe, outgoing);

Modified: team/file/bridging/apps/app_voicemail.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/apps/app_voicemail.c?view=diff&rev=90968&r1=90967&r2=90968
==============================================================================
--- team/file/bridging/apps/app_voicemail.c (original)
+++ team/file/bridging/apps/app_voicemail.c Tue Dec  4 14:40:11 2007
@@ -148,7 +148,7 @@
 static void update_messages_by_imapuser(const char *user, unsigned long number);
 
 static int imap_remove_file (char *dir, int msgnum);
-static int imap_retrieve_file (char *dir, int msgnum, char *mailbox, char *context);
+static int imap_retrieve_file (char *dir, int msgnum, const char *mailbox, char *context);
 static int imap_delete_old_greeting (char *dir, struct vm_state *vms);
 struct vmstate {
 	struct vm_state *vms;

Modified: team/file/bridging/channels/chan_local.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/channels/chan_local.c?view=diff&rev=90968&r1=90967&r2=90968
==============================================================================
--- team/file/bridging/channels/chan_local.c (original)
+++ team/file/bridging/channels/chan_local.c Tue Dec  4 14:40:11 2007
@@ -473,6 +473,7 @@
 			AST_LIST_INSERT_TAIL(&p->chan->varshead, new, entries);
 		}
 	}
+	ast_channel_datastore_inherit(p->owner, p->chan);
 
 	/* Start switch on sub channel */
 	if (!(res = ast_pbx_start(p->chan)))

Modified: team/file/bridging/channels/chan_zap.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/channels/chan_zap.c?view=diff&rev=90968&r1=90967&r2=90968
==============================================================================
--- team/file/bridging/channels/chan_zap.c (original)
+++ team/file/bridging/channels/chan_zap.c Tue Dec  4 14:40:11 2007
@@ -224,6 +224,9 @@
 
 static char defaultcic[64] = "";
 static char defaultozz[64] = "";
+
+/*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
+static char mwimonitornotify[PATH_MAX] = "";
 
 static char progzone[10] = "";
 
@@ -552,6 +555,7 @@
 	unsigned int usedistinctiveringdetection:1;
 	unsigned int zaptrcallerid:1;			/*!< should we use the callerid from incoming call on zap transfer or not */
 	unsigned int transfertobusy:1;			/*!< allow flash-transfers to busy channels */
+	unsigned int mwimonitor:1;
 	/* Channel state or unavilability flags */
 	unsigned int inservice:1;
 	unsigned int locallyblocked:1;
@@ -608,6 +612,7 @@
 	int callwaitingrepeat;				/*!< How many samples to wait before repeating call waiting */
 	int cidcwexpire;				/*!< When to expire our muting for CID/CW */
 	unsigned char *cidspill;
+	struct callerid_state *mwi_state;
 	int cidpos;
 	int cidlen;
 	int ringt;
@@ -1842,6 +1847,56 @@
 	}
 	ast_debug(1, "Disabled conferencing\n");
 	return 0;
+}
+
+/*!
+ * \brief Send MWI state change
+ *
+ * \arg mailbox_full This is the mailbox associated with the FXO line that the
+ *      MWI state has changed on.
+ * \arg thereornot This argument should simply be set to 1 or 0, to indicate
+ *      whether there are messages waiting or not.
+ *
+ *  \return nothing
+ *
+ * This function does two things:
+ *
+ * 1) It generates an internal Asterisk event notifying any other module that
+ *    cares about MWI that the state of a mailbox has changed.
+ *
+ * 2) It runs the script specified by the mwimonitornotify option to allow
+ *    some custom handling of the state change.
+ */
+static void notify_message(char *mailbox_full, int thereornot)
+{
+	char s[sizeof(mwimonitornotify) + 80];
+	struct ast_event *event;
+	char *mailbox, *context;
+
+	/* Strip off @default */
+	context = mailbox = ast_strdupa(mailbox_full);
+	strsep(&context, "@");
+	if (ast_strlen_zero(context))
+		context = "default";
+
+	if (!(event = ast_event_new(AST_EVENT_MWI,
+			AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
+			AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
+			AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
+			AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
+			AST_EVENT_IE_END))) {
+		return;
+	}
+
+	ast_event_queue_and_cache(event,
+		AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
+		AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
+		AST_EVENT_IE_END);
+
+	if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
+		snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
+		ast_safe_system(s);
+	}
 }
 
 static int restore_conference(struct zt_pvt *p)
@@ -5800,7 +5855,10 @@
 	tmp->cid.cid_pres = i->callingpres;
 	tmp->cid.cid_ton = i->cid_ton;
 	tmp->cid.cid_ani2 = i->cid_ani2;
-#if defined(HAVE_PRI) || defined(HAVE_SS7)
+/* TODO: enable this code for HAVE_SS7 when PRI_TRANS_CAP_DIGITAL gets renamed
+   and doesn't come from libpri.h any longer
+*/
+#if defined(HAVE_PRI)
 	tmp->transfercapability = transfercapability;
 	pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
 	if (transfercapability & PRI_TRANS_CAP_DIGITAL)
@@ -7325,7 +7383,14 @@
 					pfds[count].events = POLLPRI;
 					pfds[count].revents = 0;
 					/* Message waiting or r2 channels also get watched for reading */
-					if (i->cidspill)
+					if (i->mwimonitor && (i->sig & __ZT_SIG_FXS) && !i->mwi_state) {
+						if (!i->mwi_state) {
+							i->mwi_state = callerid_new(i->cid_signalling);
+							bump_gains(i);
+							zt_setlinear(i->subs[SUB_REAL].zfd, 0);
+						}
+					}
+					if (i->cidspill || i->mwi_state)
 						pfds[count].events |= POLLIN;
 					count++;
 				}
@@ -7414,29 +7479,57 @@
 						i = i->next;
 						continue;
 					}
-					if (!i->cidspill) {
+					if (!i->cidspill && !i->mwi_state) {
 						ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].zfd);
 						i = i->next;
 						continue;
 					}
 					res = read(i->subs[SUB_REAL].zfd, buf, sizeof(buf));
 					if (res > 0) {
-						/* We read some number of bytes.  Write an equal amount of data */
-						if (res > i->cidlen - i->cidpos) 
-							res = i->cidlen - i->cidpos;
-						res2 = write(i->subs[SUB_REAL].zfd, i->cidspill + i->cidpos, res);
-						if (res2 > 0) {
-							i->cidpos += res2;
-							if (i->cidpos >= i->cidlen) {
-								ast_free(i->cidspill);
-								i->cidspill = 0;
-								i->cidpos = 0;
-								i->cidlen = 0;
-							}
-						} else {
-							ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
-							i->msgstate = -1;
-						}
+ 						if (i->mwi_state) {
+ 							if (i->cid_signalling == CID_SIG_V23_JP) {
+ 								res = callerid_feed_jp(i->mwi_state, (unsigned char *)buf, res, AST_LAW(i));
+ 							} else {
+ 								res = callerid_feed(i->mwi_state, (unsigned char *)buf, res, AST_LAW(i));
+ 							}
+ 							if (res < 0) {
+ 								ast_log(LOG_WARNING, "MWI CallerID feed failed: %s!\n", strerror(errno));
+ 								callerid_free(i->mwi_state);
+ 								i->mwi_state = NULL;
+ 							} else if (res) {
+ 								char *name, *number;
+ 								int flags;
+ 								callerid_get(i->mwi_state, &number, &name, &flags);
+ 								if (flags & CID_MSGWAITING) {
+ 									ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n",i->channel);
+ 									notify_message(i->mailbox, 1);
+ 								} else if (flags & CID_NOMSGWAITING) {
+ 									ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n",i->channel);
+ 									notify_message(i->mailbox, 0);
+ 								} else 
+ 									ast_log(LOG_NOTICE, "MWI: Channel %d status unknown\n", i->channel);
+ 								callerid_free(i->mwi_state);
+ 								i->mwi_state = NULL;
+ 							}
+ 						} else if (i->cidspill) {
+ 							/* We read some number of bytes.  Write an equal amount of data */
+ 							if (res > i->cidlen - i->cidpos) 
+ 								res = i->cidlen - i->cidpos;
+ 							res2 = write(i->subs[SUB_REAL].zfd, i->cidspill + i->cidpos, res);
+ 							if (res2 > 0) {
+ 								i->cidpos += res2;
+ 								if (i->cidpos >= i->cidlen) {
+ 									free(i->cidspill);
+ 									i->cidspill = 0;
+ 									i->cidpos = 0;
+ 									i->cidlen = 0;
+ 								}
+ 							} else {
+ 								ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
+ 								i->msgstate = -1;
+ 							}
+  						}
+
 					} else {
 						ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
 					}
@@ -7454,6 +7547,12 @@
 							ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].zfd);
 						i = i->next;
 						continue;
+					}
+					if (i->mwi_state) {
+						callerid_free(i->mwi_state);
+						i->mwi_state = NULL;
+						zt_setlinear(i->subs[SUB_REAL].zfd, i->subs[SUB_REAL].linear);
+						restore_gains(i);
 					}
 					res = zt_get_event(i->subs[SUB_REAL].zfd);
 					ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
@@ -7970,6 +8069,7 @@
 #endif
 		tmp->immediate = conf.chan.immediate;
 		tmp->transfertobusy = conf.chan.transfertobusy;
+		tmp->mwimonitor = conf.chan.mwimonitor;
 		tmp->sig = conf.chan.sig;
 		tmp->outsigmod = conf.chan.outsigmod;
 		tmp->radio = conf.chan.radio;
@@ -8560,8 +8660,14 @@
 	return tmp;
 }
 
+#if defined(HAVE_PRI) || defined(HAVE_SS7)
+static int zt_setlaw(int zfd, int law)
+{
+	return ioctl(zfd, ZT_SETLAW, &law);
+}
+#endif
+
 #ifdef HAVE_SS7
-static int zt_setlaw(int zfd, int law);
 
 static int ss7_find_cic(struct zt_ss7 *linkset, int cic)
 {
@@ -9578,14 +9684,6 @@
 	}
 }
 
-static int zt_setlaw(int zfd, int law)
-{
-	int res;
-	res = ioctl(zfd, ZT_SETLAW, &law);
-	if (res)
-		return res;
-	return 0;
-}
 
 static void *pri_dchannel(void *vpri)
 {
@@ -11338,6 +11436,7 @@
 			ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
 			ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
 			ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
+			ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
 			if (tmp->vars) {
 				struct ast_variable *v;
 				ast_cli(a->fd, "Variables:\n");
@@ -11778,9 +11877,11 @@
 {
 	int x;
 	struct zt_pvt *p, *pl;
-
-#ifdef HAVE_PRI
+#if defined(HAVE_PRI) || defined(HAVE_SS7)
 	int i;
+#endif
+
+#if defined(HAVE_PRI)
 	for (i = 0; i < NUM_SPANS; i++) {
 		if (pris[i].master != AST_PTHREADT_NULL) 
 			pthread_cancel(pris[i].master);
@@ -11788,6 +11889,7 @@
 	ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
 	ast_unregister_application(zap_send_keypad_facility_app);
 #endif
+
 	ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
 	ast_manager_unregister( "ZapDialOffhook" );
 	ast_manager_unregister( "ZapHangup" );
@@ -11836,20 +11938,23 @@
 	iflist = NULL;
 	ifcount = 0;
 	ast_mutex_unlock(&iflock);
-#ifdef HAVE_PRI		
+
+#if defined(HAVE_PRI)
 	for (i = 0; i < NUM_SPANS; i++) {
 		if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
 			pthread_join(pris[i].master, NULL);
 		zt_close(pris[i].fds[i]);
 	}
-#endif
-#ifdef HAVE_SS7
+#endif /* HAVE_PRI */
+
+#if defined(HAVE_SS7)
 	for (i = 0; i < NUM_SPANS; i++) {
 		if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
 			pthread_join(linksets[i].master, NULL);
 		zt_close(linksets[i].fds[i]);
 	}
 #endif /* HAVE_SS7 */
+
 	return 0;
 }
 
@@ -12505,6 +12610,8 @@
 			confp->chan.immediate = ast_true(v->value);
 		} else if (!strcasecmp(v->name, "transfertobusy")) {
 			confp->chan.transfertobusy = ast_true(v->value);
+		} else if (!strcasecmp(v->name, "mwimonitor")) {
+			confp->chan.mwimonitor = ast_true(v->value) ? 1 : 0;
 		} else if (!strcasecmp(v->name, "cid_rxgain")) {
 			if (sscanf(v->value, "%f", &confp->chan.cid_rxgain) != 1) {
 				ast_log(LOG_WARNING, "Invalid cid_rxgain: %s\n", v->value);
@@ -13067,7 +13174,9 @@
 				ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
 			} else if (!strcasecmp(v->name, "defaultozz")) {
 				ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
-			} 
+			} else if (!strcasecmp(v->name, "mwimonitornotify")) {
+				ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
+			}
 		} else if (!skipchannels)
 			ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
 	}

Modified: team/file/bridging/configs/zapata.conf.sample
URL: http://svn.digium.com/view/asterisk/team/file/bridging/configs/zapata.conf.sample?view=diff&rev=90968&r1=90967&r2=90968
==============================================================================
--- team/file/bridging/configs/zapata.conf.sample (original)
+++ team/file/bridging/configs/zapata.conf.sample Tue Dec  4 14:40:11 2007
@@ -337,6 +337,19 @@
 ;
 ;hidecallerid=yes
 ;
+; The following option enables receiving MWI on FXO lines.  The default
+; value is no.  When this is enabled, and MWI notification indicates on or off,
+; the script specified by the mwimonitornotify option is executed.
+;
+;mwimonitor=no
+;
+; This option is used in conjunction with mwimonitor.  This will get executed
+; when incoming MWI state changes.  The script is passed 2 arguments.  The
+; first is the corresponding mailbox, and the second is 1 or 0, indicating if
+; there are messages waiting or not.
+;
+;mwimonitornotify=/usr/local/bin/zapnotify.sh
+;
 ; Whether or not to enable call waiting on internal extensions
 ; With this set to 'yes', busy extensions will hear the call-waiting
 ; tone, and can use hook-flash to switch between callers. The Dial()

Modified: team/file/bridging/include/asterisk/callerid.h
URL: http://svn.digium.com/view/asterisk/team/file/bridging/include/asterisk/callerid.h?view=diff&rev=90968&r1=90967&r2=90968
==============================================================================
--- team/file/bridging/include/asterisk/callerid.h (original)
+++ team/file/bridging/include/asterisk/callerid.h Tue Dec  4 14:40:11 2007
@@ -49,6 +49,8 @@
 #define CID_PRIVATE_NUMBER		(1 << 1)
 #define CID_UNKNOWN_NAME		(1 << 2)
 #define CID_UNKNOWN_NUMBER		(1 << 3)
+#define CID_MSGWAITING			(1 << 4)
+#define CID_NOMSGWAITING		(1 << 5)
 
 #define CID_SIG_BELL	1
 #define CID_SIG_V23	2

Modified: team/file/bridging/include/asterisk/channel.h
URL: http://svn.digium.com/view/asterisk/team/file/bridging/include/asterisk/channel.h?view=diff&rev=90968&r1=90967&r2=90968
==============================================================================
--- team/file/bridging/include/asterisk/channel.h (original)
+++ team/file/bridging/include/asterisk/channel.h Tue Dec  4 14:40:11 2007
@@ -651,6 +651,7 @@
  * \retval 0 success
  * \retval non-zero failure
  */
+
 int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore);
 
 /*! 

Modified: team/file/bridging/main/Makefile
URL: http://svn.digium.com/view/asterisk/team/file/bridging/main/Makefile?view=diff&rev=90968&r1=90967&r2=90968
==============================================================================
--- team/file/bridging/main/Makefile (original)
+++ team/file/bridging/main/Makefile Tue Dec  4 14:40:11 2007
@@ -27,7 +27,7 @@
 	netsock.o slinfactory.o ast_expr2.o ast_expr2f.o \
 	cryptostub.o sha1.o http.o fixedjitterbuf.o abstract_jb.o \
 	strcompat.o threadstorage.o dial.o event.o adsistub.o audiohook.o \
-	astobj2.o hashtab.o bridging.o
+	astobj2.o hashtab.o global_datastores.o bridging.o
 
 # we need to link in the objects statically, not as a library, because
 # otherwise modules will not have them available if none of the static

Modified: team/file/bridging/main/callerid.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/main/callerid.c?view=diff&rev=90968&r1=90967&r2=90968
==============================================================================
--- team/file/bridging/main/callerid.c (original)
+++ team/file/bridging/main/callerid.c Tue Dec  4 14:40:11 2007
@@ -555,7 +555,7 @@
 					cid->sawflag = 2;
 				break;
 			case 2: /* Get lead-in */
-				if ((b == 0x04) || (b == 0x80)) {
+				if ((b == 0x04) || (b == 0x80) || (b == 0x06) || (b == 0x82)) {
 					cid->type = b;
 					cid->sawflag = 3;
 					cid->cksum = b;
@@ -591,8 +591,10 @@
 		
 				cid->number[0] = '\0';
 				cid->name[0] = '\0';
+				/* Update flags */
+				cid->flags = 0;
 				/* If we get this far we're fine.  */
-				if (cid->type == 0x80) {
+				if ((cid->type == 0x80) || (cid->type == 0x82)) {
 					/* MDMF */
 					/* Go through each element and process */
 					for (x = 0; x < cid->pos;) {
@@ -626,6 +628,13 @@
 							memcpy(cid->name, cid->rawdata + x + 1, res);
 							cid->name[res] = '\0';
 							break;
+						case 11: /* Message Waiting */
+							res = cid->rawdata[x + 1];
+							if (res)
+								cid->flags |= CID_MSGWAITING;
+							else
+								cid->flags |= CID_NOMSGWAITING;
+							break;
 						case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting  */
 						case 19: /* UK: Network message system status (Number of messages waiting) */
 						case 22: /* Something French */
@@ -643,12 +652,17 @@
 						x += cid->rawdata[x];
 						x++;
 					}
+				} else if (cid->type == 0x6) {
+					/* VMWI SDMF */
+					if (cid->rawdata[2] == 0x42) {
+						cid->flags |= CID_MSGWAITING;
+					} else if (cid->rawdata[2] == 0x6f) {
+						cid->flags |= CID_NOMSGWAITING;
+					}
 				} else {
 					/* SDMF */
 					ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
 				}
-				/* Update flags */
-				cid->flags = 0;
 				if (!strcmp(cid->number, "P")) {
 					strcpy(cid->number, "");
 					cid->flags |= CID_PRIVATE_NUMBER;

Modified: team/file/bridging/main/channel.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/main/channel.c?view=diff&rev=90968&r1=90967&r2=90968
==============================================================================
--- team/file/bridging/main/channel.c (original)
+++ team/file/bridging/main/channel.c Tue Dec  4 14:40:11 2007
@@ -673,6 +673,10 @@
 	if (needqueue) {
 		if (pipe(tmp->alertpipe)) {
 			ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe!\n");
+#ifdef HAVE_ZAPTEL
+			if (tmp->timingfd > -1)
+				close(tmp->timingfd);
+#endif
 			sched_context_destroy(tmp->sched);
 			ast_string_field_free_memory(tmp);
 			ast_free(tmp);




More information about the asterisk-commits mailing list