[asterisk-commits] russell: trunk r90949 - in /trunk: ./ channels/ configs/ include/asterisk/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Dec 4 13:08:30 CST 2007


Author: russell
Date: Tue Dec  4 13:08:30 2007
New Revision: 90949

URL: http://svn.digium.com/view/asterisk?view=rev&rev=90949
Log:
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)

Modified:
    trunk/CHANGES
    trunk/channels/chan_zap.c
    trunk/configs/zapata.conf.sample
    trunk/include/asterisk/callerid.h
    trunk/main/callerid.c

Modified: trunk/CHANGES
URL: http://svn.digium.com/view/asterisk/trunk/CHANGES?view=diff&rev=90949&r1=90948&r2=90949
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Tue Dec  4 13:08:30 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: trunk/channels/chan_zap.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_zap.c?view=diff&rev=90949&r1=90948&r2=90949
==============================================================================
--- trunk/channels/chan_zap.c (original)
+++ trunk/channels/chan_zap.c Tue Dec  4 13:08:30 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)
@@ -7328,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++;
 				}
@@ -7417,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));
 					}
@@ -7457,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);
@@ -7973,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;
@@ -11339,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");
@@ -12512,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);
@@ -13074,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: trunk/configs/zapata.conf.sample
URL: http://svn.digium.com/view/asterisk/trunk/configs/zapata.conf.sample?view=diff&rev=90949&r1=90948&r2=90949
==============================================================================
--- trunk/configs/zapata.conf.sample (original)
+++ trunk/configs/zapata.conf.sample Tue Dec  4 13:08:30 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: trunk/include/asterisk/callerid.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/callerid.h?view=diff&rev=90949&r1=90948&r2=90949
==============================================================================
--- trunk/include/asterisk/callerid.h (original)
+++ trunk/include/asterisk/callerid.h Tue Dec  4 13:08:30 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: trunk/main/callerid.c
URL: http://svn.digium.com/view/asterisk/trunk/main/callerid.c?view=diff&rev=90949&r1=90948&r2=90949
==============================================================================
--- trunk/main/callerid.c (original)
+++ trunk/main/callerid.c Tue Dec  4 13:08:30 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;




More information about the asterisk-commits mailing list