[asterisk-commits] mmichelson: branch group/manager2 r118559 - in /team/group/manager2: ./ apps/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue May 27 14:34:12 CDT 2008


Author: mmichelson
Date: Tue May 27 14:34:11 2008
New Revision: 118559

URL: http://svn.digium.com/view/asterisk?view=rev&rev=118559
Log:
Resolve conflict and reset automerge.


Added:
    team/group/manager2/configs/pbx_realtime.conf
      - copied unchanged from r118556, trunk/configs/pbx_realtime.conf
    team/group/manager2/doc/api-1.6.0-changes.odt
      - copied unchanged from r118556, trunk/doc/api-1.6.0-changes.odt
    team/group/manager2/doc/cli.txt
      - copied unchanged from r118556, trunk/doc/cli.txt
Modified:
    team/group/manager2/   (props changed)
    team/group/manager2/CHANGES
    team/group/manager2/UPGRADE.txt
    team/group/manager2/apps/app_alarmreceiver.c
    team/group/manager2/apps/app_chanisavail.c
    team/group/manager2/apps/app_chanspy.c
    team/group/manager2/apps/app_dial.c
    team/group/manager2/apps/app_disa.c
    team/group/manager2/apps/app_externalivr.c
    team/group/manager2/apps/app_festival.c
    team/group/manager2/apps/app_followme.c
    team/group/manager2/apps/app_ices.c
    team/group/manager2/apps/app_jack.c
    team/group/manager2/apps/app_meetme.c
    team/group/manager2/apps/app_milliwatt.c
    team/group/manager2/apps/app_mp3.c
    team/group/manager2/apps/app_nbscat.c
    team/group/manager2/apps/app_queue.c
    team/group/manager2/apps/app_rpt.c
    team/group/manager2/apps/app_sms.c
    team/group/manager2/apps/app_speech_utils.c
    team/group/manager2/apps/app_test.c
    team/group/manager2/apps/app_voicemail.c
    team/group/manager2/apps/app_zapbarge.c
    team/group/manager2/apps/app_zapscan.c
    team/group/manager2/build_tools/make_buildopts_h
    team/group/manager2/cdr/cdr_csv.c
    team/group/manager2/channels/Makefile
    team/group/manager2/channels/chan_alsa.c
    team/group/manager2/channels/chan_console.c
    team/group/manager2/channels/chan_gtalk.c
    team/group/manager2/channels/chan_h323.c
    team/group/manager2/channels/chan_iax2.c
    team/group/manager2/channels/chan_jingle.c
    team/group/manager2/channels/chan_local.c
    team/group/manager2/channels/chan_mgcp.c
    team/group/manager2/channels/chan_misdn.c
    team/group/manager2/channels/chan_nbs.c
    team/group/manager2/channels/chan_oss.c
    team/group/manager2/channels/chan_phone.c
    team/group/manager2/channels/chan_sip.c
    team/group/manager2/channels/chan_skinny.c
    team/group/manager2/channels/chan_unistim.c
    team/group/manager2/channels/chan_usbradio.c
    team/group/manager2/channels/chan_vpb.cc
    team/group/manager2/channels/chan_zap.c
    team/group/manager2/channels/console_gui.c
    team/group/manager2/channels/console_video.c
    team/group/manager2/channels/h323/ast_h323.cxx
    team/group/manager2/channels/iax2-parser.c
    team/group/manager2/channels/iax2-parser.h
    team/group/manager2/channels/xpmr/sinetabx.h
    team/group/manager2/channels/xpmr/xpmr.c
    team/group/manager2/channels/xpmr/xpmr.h
    team/group/manager2/channels/xpmr/xpmr_coef.h
    team/group/manager2/codecs/codec_a_mu.c
    team/group/manager2/codecs/codec_adpcm.c
    team/group/manager2/codecs/codec_alaw.c
    team/group/manager2/codecs/codec_g722.c
    team/group/manager2/codecs/codec_g726.c
    team/group/manager2/codecs/codec_gsm.c
    team/group/manager2/codecs/codec_lpc10.c
    team/group/manager2/codecs/codec_resample.c
    team/group/manager2/codecs/codec_speex.c
    team/group/manager2/codecs/codec_ulaw.c
    team/group/manager2/codecs/codec_zap.c
    team/group/manager2/configs/jabber.conf.sample
    team/group/manager2/configs/oss.conf.sample
    team/group/manager2/configs/queues.conf.sample
    team/group/manager2/configs/zapata.conf.sample
    team/group/manager2/doc/externalivr.txt
    team/group/manager2/doc/manager_1_1.txt
    team/group/manager2/formats/format_g723.c
    team/group/manager2/formats/format_g726.c
    team/group/manager2/formats/format_g729.c
    team/group/manager2/formats/format_gsm.c
    team/group/manager2/formats/format_h263.c
    team/group/manager2/formats/format_h264.c
    team/group/manager2/formats/format_ilbc.c
    team/group/manager2/formats/format_jpeg.c
    team/group/manager2/formats/format_ogg_vorbis.c
    team/group/manager2/formats/format_pcm.c
    team/group/manager2/formats/format_sln.c
    team/group/manager2/formats/format_sln16.c
    team/group/manager2/formats/format_vox.c
    team/group/manager2/formats/format_wav.c
    team/group/manager2/formats/format_wav_gsm.c
    team/group/manager2/funcs/func_speex.c
    team/group/manager2/include/asterisk/channel.h
    team/group/manager2/include/asterisk/compat.h
    team/group/manager2/include/asterisk/frame.h
    team/group/manager2/include/asterisk/lock.h
    team/group/manager2/include/asterisk/logger.h
    team/group/manager2/include/asterisk/manager.h
    team/group/manager2/include/asterisk/strings.h
    team/group/manager2/include/asterisk/utils.h
    team/group/manager2/main/abstract_jb.c
    team/group/manager2/main/app.c
    team/group/manager2/main/asterisk.c
    team/group/manager2/main/audiohook.c
    team/group/manager2/main/channel.c
    team/group/manager2/main/cli.c
    team/group/manager2/main/config.c
    team/group/manager2/main/dsp.c
    team/group/manager2/main/features.c
    team/group/manager2/main/file.c
    team/group/manager2/main/frame.c
    team/group/manager2/main/http.c
    team/group/manager2/main/indications.c
    team/group/manager2/main/logger.c
    team/group/manager2/main/manager.c
    team/group/manager2/main/pbx.c
    team/group/manager2/main/rtp.c
    team/group/manager2/main/slinfactory.c
    team/group/manager2/main/translate.c
    team/group/manager2/main/udptl.c
    team/group/manager2/main/utils.c
    team/group/manager2/pbx/pbx_gtkconsole.c
    team/group/manager2/pbx/pbx_realtime.c
    team/group/manager2/res/res_adsi.c
    team/group/manager2/res/res_agi.c
    team/group/manager2/res/res_config_ldap.c
    team/group/manager2/res/res_jabber.c
    team/group/manager2/res/res_musiconhold.c
    team/group/manager2/res/res_odbc.c
    team/group/manager2/res/res_smdi.c
    team/group/manager2/utils/ael_main.c
    team/group/manager2/utils/astcanary.c
    team/group/manager2/utils/check_expr.c
    team/group/manager2/utils/conf2ael.c
    team/group/manager2/utils/hashtest.c
    team/group/manager2/utils/hashtest2.c
    team/group/manager2/utils/refcounter.c

Propchange: team/group/manager2/
------------------------------------------------------------------------------
    automerge = buns

Propchange: team/group/manager2/
------------------------------------------------------------------------------
Binary property 'branch-1.4-blocked' - no diff available.

Propchange: team/group/manager2/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/group/manager2/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue May 27 14:34:11 2008
@@ -1,1 +1,1 @@
-/trunk:1-116629
+/trunk:1-118557

Modified: team/group/manager2/CHANGES
URL: http://svn.digium.com/view/asterisk/team/group/manager2/CHANGES?view=diff&rev=118559&r1=118558&r2=118559
==============================================================================
--- team/group/manager2/CHANGES (original)
+++ team/group/manager2/CHANGES Tue May 27 14:34:11 2008
@@ -14,11 +14,19 @@
    based on other parameters.  The default is still to search based on the
    forwarding station ID.  However, there are new options that allow you to search
    based on the message desk terminal ID, or the message desk number.
+ * TIMEOUT() has been modified to be accurate down to the millisecond.
+ * ENUM*() functions now include the following new options:
+     - 'u' returns the full URI and does not strip off the URI-scheme.
+	 - 's' triggers ISN specific rewriting
+	 - 'i' looks for branches into an Infrastructure ENUM tree
+	 - 'd' for a direct DNS lookup without any flipping of digits.
+ * TXCIDNAME() has a new zone-suffix parameter (which defaults to 'e164.arpa')
 
 Zaptel channel driver (chan_zap) Changes
 ----------------------------------------
  * Channels can now be configured using named sections in zapata.conf, just
    like other channel drivers, including the use of templates.
+ * The default for pridialplan has changed from 'national' to 'unknown'.
 
 PBX Changes
 -----------
@@ -64,6 +72,11 @@
    words, if using the 'd' option, it is not possible to enter a number to append to
    the first argument to Chanspy(). Pressing 4 will change to spy mode, pressing 5 will
    change to whisper mode, and pressing 6 will change to barge mode.
+ * ExternalIVR now takes several options that affect the way it performs, as
+   well as having several new commands.  Please see doc/externalivr.txt for the
+   complete documentation.
+ * ChanIsAvail has a new option, 'a', which will return all available channels instead
+   of just the first one if you give the function more then one channel to check.
 
 SIP Changes
 -----------
@@ -105,20 +118,16 @@
   * Addresses managed by DNS manager now can check to see if there is a DNS
     SRV record for a given domain and will use that hostname/port if present.
 
-Dialplan function changes
--------------------------
- * TIMEOUT() has been modified to be accurate down to the millisecond.
- * ENUM*() functions now include the following new options:
-     - 'u' returns the full URI and does not strip off the URI-scheme.
-	 - 's' triggers ISN specific rewriting
-	 - 'i' looks for branches into an Infrastructure ENUM tree
-	 - 'd' for a direct DNS lookup without any flipping of digits.
- * TXCIDNAME() has a new zone-suffix parameter (which defaults to 'e164.arpa')
-
 AMI - The manager (TCP/TLS/HTTP)
 --------------------------------
   * The Status command now takes an optional list of variables to display
     along with channel status.
+
+ODBC Changes
+------------
+  * res_odbc no longer has a limit of 1023 total possible unshared connections,
+    as some people were running into this limit.  This limit has been increased
+    to 4.2 billion.
 
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 1.4.X to Asterisk 1.6.0  -------------
@@ -735,3 +744,9 @@
      turned on, via the CHANNEL(trace) dialplan function.  Could be useful for
      dialplan debugging.
   * iLBC source code no longer included (see UPGRADE.txt for details)
+  * If compiled with DETECT_DEADLOCKS enabled and if you have glibc, then if 
+     deadlock is detected, a backtrace of the stack which led to the lock calls
+	 will be output to the CLI.
+  * If compiled with DEBUG_THREADS enabled and if you have glibc, then issuing
+     the "core show locks" CLI command will give lock information output as well
+	 as a backtrace of the stack which led to the lock calls.

Modified: team/group/manager2/UPGRADE.txt
URL: http://svn.digium.com/view/asterisk/team/group/manager2/UPGRADE.txt?view=diff&rev=118559&r1=118558&r2=118559
==============================================================================
--- team/group/manager2/UPGRADE.txt (original)
+++ team/group/manager2/UPGRADE.txt Tue May 27 14:34:11 2008
@@ -58,6 +58,12 @@
 
 * The silencethreshold used for various applications is now settable via a
   centralized config option in dsp.conf.
+
+* The logical value of spaces immediately preceding a standalone 0 previously
+  evaluated to true.  It now evaluates to false.  This has confused a good
+  many people in the past (typically because they failed to realize the space
+  had any significance).  Since this violates the Principle of Least Surprise,
+  it has been changed.
 
 Voicemail:
 

Modified: team/group/manager2/apps/app_alarmreceiver.c
URL: http://svn.digium.com/view/asterisk/team/group/manager2/apps/app_alarmreceiver.c?view=diff&rev=118559&r1=118558&r2=118559
==============================================================================
--- team/group/manager2/apps/app_alarmreceiver.c (original)
+++ team/group/manager2/apps/app_alarmreceiver.c Tue May 27 14:34:11 2008
@@ -185,7 +185,7 @@
 			wf.subclass = AST_FORMAT_ULAW;
 			wf.offset = AST_FRIENDLY_OFFSET;
 			wf.mallocd = 0;
-			wf.data = tone_block.buf;
+			wf.data.ptr = tone_block.buf;
 			wf.datalen = f->datalen;
 			wf.samples = wf.datalen;
 			
@@ -252,8 +252,8 @@
 
 		/* If they hung up, leave */
 		if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
-			if (f->seqno) {
-				chan->hangupcause = f->seqno;
+			if (f->data.uint32) {
+				chan->hangupcause = f->data.uint32;
 			}
 			ast_frfree(f);
 			res = -1;

Modified: team/group/manager2/apps/app_chanisavail.c
URL: http://svn.digium.com/view/asterisk/team/group/manager2/apps/app_chanisavail.c?view=diff&rev=118559&r1=118558&r2=118559
==============================================================================
--- team/group/manager2/apps/app_chanisavail.c (original)
+++ team/group/manager2/apps/app_chanisavail.c Tue May 27 14:34:11 2008
@@ -50,6 +50,7 @@
 "This application will check to see if any of the specified channels are\n"
 "available.\n"
 "  Options:\n"
+"    a - Check for all available channels, not only the first one.\n"
 "    s - Consider the channel unavailable if the channel is in use at all.\n"
 "    t - Simply checks if specified channels exist in the channel list\n"
 "        (implies option s).\n"
@@ -61,9 +62,12 @@
 
 static int chanavail_exec(struct ast_channel *chan, void *data)
 {
-	int res=-1, inuse=-1, option_state=0, string_compare=0;
+	int inuse=-1, option_state=0, string_compare=0, option_all_avail=0;
 	int status;
 	char *info, tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur;
+	struct ast_str *tmp_availchan = ast_str_alloca(2048);
+	struct ast_str *tmp_availorig = ast_str_alloca(2048);
+	struct ast_str *tmp_availstat = ast_str_alloca(2048);
 	struct ast_channel *tempchan;
 	AST_DECLARE_APP_ARGS(args,
 		AST_APP_ARG(reqchans);
@@ -80,10 +84,15 @@
 	AST_STANDARD_APP_ARGS(args, info);
 
 	if (args.options) {
-		if (strchr(args.options, 's'))
+		if (strchr(args.options, 'a')) {
+			option_all_avail = 1;
+		}
+		if (strchr(args.options, 's')) {
 			option_state = 1;
-		if (strchr(args.options, 't'))
+		}
+		if (strchr(args.options, 't')) {
 			string_compare = 1;
+		}
 	}
 	peers = args.reqchans;
 	if (peers) {
@@ -119,27 +128,32 @@
 				status = inuse = ast_device_state(trychan);
 			}
 			if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) {
-					pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name);
-					/* Store the originally used channel too */
+					ast_str_append(&tmp_availchan, 0, "%s%s", tmp_availchan->used ? "&" : "", tempchan->name);
+					
 					snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
-					pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp);
+					ast_str_append(&tmp_availorig, 0, "%s%s", tmp_availorig->used ? "&" : "", tmp);
+
 					snprintf(tmp, sizeof(tmp), "%d", status);
-					pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp);
+					ast_str_append(&tmp_availstat, 0, "%s%s", tmp_availstat->used ? "&" : "", tmp);
+
 					ast_hangup(tempchan);
 					tempchan = NULL;
-					res = 1;
-					break;
+
+					if (!option_all_avail) {
+						break;
+					}
 			} else {
 				snprintf(tmp, sizeof(tmp), "%d", status);
-				pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp);
+				ast_str_append(&tmp_availstat, 0, "%s%s", tmp_availstat->used ? "&" : "", tmp);
 			}
 			cur = rest;
 		} while (cur);
 	}
-	if (res < 1) {
-		pbx_builtin_setvar_helper(chan, "AVAILCHAN", "");
-		pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", "");
-	}
+
+	pbx_builtin_setvar_helper(chan, "AVAILCHAN", tmp_availchan->str);
+	/* Store the originally used channel too */
+	pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp_availorig->str);
+	pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp_availstat->str);
 
 	return 0;
 }

Modified: team/group/manager2/apps/app_chanspy.c
URL: http://svn.digium.com/view/asterisk/team/group/manager2/apps/app_chanspy.c?view=diff&rev=118559&r1=118558&r2=118559
==============================================================================
--- team/group/manager2/apps/app_chanspy.c (original)
+++ team/group/manager2/apps/app_chanspy.c Tue May 27 14:34:11 2008
@@ -217,6 +217,7 @@
 	AST_APP_OPTION('d', OPTION_DTMF_SWITCH_MODES),
 });
 
+int next_unique_id_to_use = 0;
 
 struct chanspy_translation_helper {
 	/* spy data */
@@ -263,7 +264,7 @@
 	}
 
 	if (csth->fd)
-		write(csth->fd, f->data, f->datalen);
+		write(csth->fd, f->data.ptr, f->datalen);
 
 	ast_frfree(f);
 
@@ -293,6 +294,7 @@
 
 struct chanspy_ds {
 	struct ast_channel *chan;
+	char unique_id[20];
 	ast_mutex_t lock;
 };
 
@@ -545,7 +547,7 @@
 		chan = chanspy_ds->chan;
 
 		ast_channel_lock(chan);
-		if ((datastore = ast_channel_datastore_find(chan, &chanspy_ds_info, NULL))) {
+		if ((datastore = ast_channel_datastore_find(chan, &chanspy_ds_info, chanspy_ds->unique_id))) {
 			ast_channel_datastore_remove(chan, datastore);
 			/* chanspy_ds->chan is NULL after this call */
 			chanspy_ds_destroy(datastore->data);
@@ -566,7 +568,7 @@
 
 	ast_mutex_lock(&chanspy_ds->lock);
 
-	if (!(datastore = ast_channel_datastore_alloc(&chanspy_ds_info, NULL))) {
+	if (!(datastore = ast_channel_datastore_alloc(&chanspy_ds_info, chanspy_ds->unique_id))) {
 		ast_mutex_unlock(&chanspy_ds->lock);
 		chanspy_ds = chanspy_ds_free(chanspy_ds);
 		ast_channel_unlock(chan);
@@ -639,6 +641,8 @@
 	}
 
 	ast_mutex_init(&chanspy_ds.lock);
+
+	snprintf(chanspy_ds.unique_id, sizeof(chanspy_ds.unique_id), "%d", ast_atomic_fetchadd_int(&next_unique_id_to_use, +1));
 
 	if (chan->_state != AST_STATE_UP)
 		ast_answer(chan);

Modified: team/group/manager2/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/team/group/manager2/apps/app_dial.c?view=diff&rev=118559&r1=118558&r2=118559
==============================================================================
--- team/group/manager2/apps/app_dial.c (original)
+++ team/group/manager2/apps/app_dial.c Tue May 27 14:34:11 2008
@@ -765,7 +765,7 @@
 						}
 						break;
 					case AST_FRAME_HTML:
-						if (!ast_test_flag64(outgoing, DIAL_NOFORWARDHTML) && ast_channel_sendhtml(in, f->subclass, f->data, f->datalen) == -1) {
+						if (!ast_test_flag64(outgoing, DIAL_NOFORWARDHTML) && ast_channel_sendhtml(in, f->subclass, f->data.ptr, f->datalen) == -1) {
 							ast_log(LOG_WARNING, "Unable to send URL\n");
 						}
 						break;
@@ -789,8 +789,9 @@
 				strcpy(pa->status, "CANCEL");
 				ast_cdr_noanswer(in->cdr);
 				if (f) {
-					if (f->seqno)
-						in->hangupcause = f->seqno;
+					if (f->data.uint32) {
+						in->hangupcause = f->data.uint32;
+					}
 					ast_frfree(f);
 				}
 				return NULL;
@@ -824,7 +825,7 @@
 
 			/* Forward HTML stuff */
 			if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag64(outgoing, DIAL_NOFORWARDHTML))
-				if (ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen) == -1)
+				if (ast_channel_sendhtml(outgoing->chan, f->subclass, f->data.ptr, f->datalen) == -1)
 					ast_log(LOG_WARNING, "Unable to send URL\n");
 
 			if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END)))  {
@@ -837,7 +838,7 @@
 				(f->subclass == AST_CONTROL_VIDUPDATE) ||
 				 (f->subclass == AST_CONTROL_SRCUPDATE))) {
 				ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
-				ast_indicate_data(outgoing->chan, f->subclass, f->data, f->datalen);
+				ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);
 			}
 			ast_frfree(f);
 		}

Modified: team/group/manager2/apps/app_disa.c
URL: http://svn.digium.com/view/asterisk/team/group/manager2/apps/app_disa.c?view=diff&rev=118559&r1=118558&r2=118559
==============================================================================
--- team/group/manager2/apps/app_disa.c (original)
+++ team/group/manager2/apps/app_disa.c Tue May 27 14:34:11 2008
@@ -195,8 +195,8 @@
 		}
 
 		if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
-			if (f->seqno)
-				chan->hangupcause = f->seqno;
+			if (f->data.uint32)
+				chan->hangupcause = f->data.uint32;
 			ast_frfree(f);
 			ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
 			return -1;

Modified: team/group/manager2/apps/app_externalivr.c
URL: http://svn.digium.com/view/asterisk/team/group/manager2/apps/app_externalivr.c?view=diff&rev=118559&r1=118558&r2=118559
==============================================================================
--- team/group/manager2/apps/app_externalivr.c (original)
+++ team/group/manager2/apps/app_externalivr.c Tue May 27 14:34:11 2008
@@ -50,19 +50,37 @@
 static const char *app = "ExternalIVR";
 
 static const char *synopsis = "Interfaces with an external IVR application";
-
 static const char *descrip =
-"  ExternalIVR(command|ivr://ivrhost[,arg[,arg...]]): Either forks a process\n"
+"  ExternalIVR(command|ivr://ivrhosti([,arg[,arg...]])[,options]): Either forks a process\n"
 "to run given command or makes a socket to connect to given host and starts\n"
 "a generator on the channel. The generator's play list is controlled by the\n"
 "external application, which can add and clear entries via simple commands\n"
 "issued over its stdout. The external application will receive all DTMF events\n"
 "received on the channel, and notification if the channel is hung up. The\n"
 "application will not be forcibly terminated when the channel is hung up.\n"
-"See doc/externalivr.txt for a protocol specification.\n";
+"See doc/externalivr.txt for a protocol specification.\n"
+"The 'n' option tells ExternalIVR() not to answer the channel. \n"
+"The 'i' option tells ExternalIVR() not to send a hangup and exit when the\n"
+"  channel receives a hangup, instead it sends an 'I' informative message\n"
+"  meaning that the external application MUST hang up the call with an H command\n"
+"The 'd' option tells ExternalIVR() to run on a channel that has been hung up\n"
+"  and will not look for hangups.  The external application must exit with\n"
+"  an 'E' command.\n";
 
 /* XXX the parser in gcc 2.95 gets confused if you don't put a space between 'name' and the comma */
 #define ast_chan_log(level, channel, format, ...) ast_log(level, "%s: " format, channel->name , ## __VA_ARGS__)
+
+enum {
+	noanswer = (1 << 0),
+	ignore_hangup = (1 << 1),
+	run_dead = (1 << 2),
+} options_flags;
+
+AST_APP_OPTIONS(app_opts, {
+	AST_APP_OPTION('n', noanswer),
+	AST_APP_OPTION('i', ignore_hangup),
+	AST_APP_OPTION('d', run_dead),
+});
 
 struct playlist_entry {
 	AST_LIST_ENTRY(playlist_entry) list;
@@ -76,6 +94,7 @@
 	int abort_current_sound;
 	int playing_silence;
 	int option_autoclear;
+	int gen_active;
 };
 
 
@@ -88,24 +107,22 @@
 
 static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u, 
 	int eivr_events_fd, int eivr_commands_fd, int eivr_errors_fd, 
-	const char *args);
+	const struct ast_str *args, const struct ast_flags flags);
 
 int eivr_connect_socket(struct ast_channel *chan, const char *host, int port);
 
 static void send_eivr_event(FILE *handle, const char event, const char *data,
 	const struct ast_channel *chan)
 {
-	char tmp[256];
-
-	if (!data) {
-		snprintf(tmp, sizeof(tmp), "%c,%10d", event, (int)time(NULL));
-	} else {
-		snprintf(tmp, sizeof(tmp), "%c,%10d,%s", event, (int)time(NULL), data);
-	}
-
-	fprintf(handle, "%s\n", tmp);
-	if (option_debug)
-		ast_chan_log(LOG_DEBUG, chan, "sent '%s'\n", tmp);
+	struct ast_str *tmp = ast_str_create(12);
+
+	ast_str_append(&tmp, 0, "%c,%10d", event, (int)time(NULL));
+	if (data) {
+		ast_str_append(&tmp, 0, "%s", data);
+	}
+
+	fprintf(handle, "%s\n", tmp->str);
+	ast_debug(1, "sent '%s'\n", tmp->str);
 }
 
 static void *gen_alloc(struct ast_channel *chan, void *params)
@@ -245,7 +262,7 @@
 		variable = strsep(&inbuf, ",");
 		if (variable == NULL) {
 			int outstrlen = strlen(outbuf);
-			if(outstrlen && outbuf[outstrlen - 1] == ',') {
+			if (outstrlen && outbuf[outstrlen - 1] == ',') {
 				outbuf[outstrlen - 1] = 0;
 			}
 			break;
@@ -260,7 +277,7 @@
 		ast_channel_unlock(chan);
 		ast_copy_string(outbuf, newstring->str, outbuflen);
 	}
-};
+}
 
 static void ast_eivr_setvariable(struct ast_channel *chan, char *data)
 {
@@ -273,21 +290,22 @@
 
 	for (j = 1, inbuf = data; ; j++, inbuf = NULL) {
 		variable = strsep(&inbuf, ",");
-		ast_chan_log(LOG_DEBUG, chan, "Setting up a variable: %s\n", variable);
-		if(variable) {
+		ast_debug(1, "Setting up a variable: %s\n", variable);
+		if (variable) {
 			/* variable contains "varname=value" */
 			ast_copy_string(buf, variable, sizeof(buf));
 			value = strchr(buf, '=');
-			if(!value) 
-				value="";
-			else
+			if (!value) {
+				value = "";
+			} else {
 				*value++ = '\0';
+			}
 			pbx_builtin_setvar_helper(chan, buf, value);
-		}
-		else
+		} else {
 			break;
-	}
-};
+		}
+	}
+}
 
 static struct playlist_entry *make_entry(const char *filename)
 {
@@ -303,14 +321,14 @@
 
 static int app_exec(struct ast_channel *chan, void *data)
 {
+	struct ast_flags flags;
+	char *opts[0];
 	struct playlist_entry *entry;
-	int child_stdin[2] = { 0,0 };
-	int child_stdout[2] = { 0,0 };
-	int child_stderr[2] = { 0,0 };
+	int child_stdin[2] = { 0, 0 };
+	int child_stdout[2] = { 0, 0 };
+	int child_stderr[2] = { 0, 0 };
 	int res = -1;
-	int gen_active = 0;
 	int pid;
-	char *buf, *pipe_delim_argbuf, *pdargbuf_ptr;
 
 	char hostname[1024];
 	char *port_str = NULL;
@@ -320,29 +338,87 @@
 	struct ivr_localuser foo = {
 		.playlist = AST_LIST_HEAD_INIT_VALUE,
 		.finishlist = AST_LIST_HEAD_INIT_VALUE,
+		.gen_active = 0,
 	};
 	struct ivr_localuser *u = &foo;
-	AST_DECLARE_APP_ARGS(args,
+
+	char *buf;
+	int j;
+	char *s, **app_args, *e; 
+	struct ast_str *pipe_delim_args = ast_str_create(100);
+
+	AST_DECLARE_APP_ARGS(eivr_args,
 		AST_APP_ARG(cmd)[32];
 	);
+	AST_DECLARE_APP_ARGS(application_args,
+		AST_APP_ARG(cmd)[32];
+	);
 
 	u->abort_current_sound = 0;
 	u->chan = chan;
 
+	buf = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(eivr_args, buf);
+
+	if ((s = strchr(eivr_args.cmd[0], '('))) {
+		s[0] = ',';
+		if (( e = strrchr(s, ')')) ) {
+			*e = '\0';
+		} else {
+			ast_log(LOG_ERROR, "Parse error, no closing paren?\n");
+		}
+		AST_STANDARD_APP_ARGS(application_args, eivr_args.cmd[0]);
+		app_args = application_args.argv;
+
+		/* Put the application + the arguments in a | delimited list */
+		ast_str_reset(pipe_delim_args);
+		for (j = 0; application_args.cmd[j] != NULL; j++) {
+			ast_str_append(&pipe_delim_args, 0, "%s%s", j == 0 ? "" : "|", application_args.cmd[j]);
+		}
+
+		/* Parse the ExternalIVR() arguments */
+		if (option_debug)
+			ast_debug(1, "Parsing options from: [%s]\n", eivr_args.cmd[1]);
+		ast_app_parse_options(app_opts, &flags, opts, eivr_args.cmd[1]);
+		if (option_debug) {
+			if (ast_test_flag(&flags, noanswer))
+				ast_debug(1, "noanswer is set\n");
+			if (ast_test_flag(&flags, ignore_hangup))
+				ast_debug(1, "ignore_hangup is set\n");
+			if (ast_test_flag(&flags, run_dead))
+				ast_debug(1, "run_dead is set\n");
+		}
+
+	} else {
+		app_args = eivr_args.argv;
+		for (j = 0; eivr_args.cmd[j] != NULL; j++) {
+			ast_str_append(&pipe_delim_args, 0, "%s%s", j == 0 ? "" : "|", eivr_args.cmd[j]);
+		}
+	}
+	
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "ExternalIVR requires a command to execute\n");
 		return -1;
 	}
 
-	buf = ast_strdupa(data);
-	AST_STANDARD_APP_ARGS(args, buf);
-
-	/* copy args and replace commas with pipes */
-	pipe_delim_argbuf = ast_strdupa(data);
-	while((pdargbuf_ptr = strchr(pipe_delim_argbuf, ',')) != NULL)
-		pdargbuf_ptr[0] = '|';
-
-	if(!strncmp(args.cmd[0], "ivr://", 6)) {
+	if (!(ast_test_flag(&flags, noanswer))) {
+		ast_chan_log(LOG_WARNING, chan, "Answering channel and starting generator\n");
+		if (chan->_state != AST_STATE_UP) {
+			if (ast_test_flag(&flags, run_dead)) {
+				ast_chan_log(LOG_WARNING, chan, "Running ExternalIVR with 'd'ead flag on non-hungup channel isn't supported\n");
+				goto exit;
+			}
+			ast_answer(chan);
+		}
+		if (ast_activate_generator(chan, &gen, u) < 0) {
+			ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n");
+			goto exit;
+		} else {
+			u->gen_active = 1;
+		}
+	}
+
+	if (!strncmp(app_args[0], "ivr://", 6)) {
 		struct server_args ivr_desc = {
 			.accept_fd = -1,
 			.name = "IVR",
@@ -350,25 +426,16 @@
 		struct ast_hostent hp;
 
 		/*communicate through socket to server*/
-		if (chan->_state != AST_STATE_UP) {
-			ast_answer(chan);
-		}
-		if (ast_activate_generator(chan, &gen, u) < 0) {
-			ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n");
-			goto exit;
-		} else {
-			gen_active = 1;
-		}
-
-		ast_chan_log(LOG_DEBUG, chan, "Parsing hostname:port for socket connect from \"%s\"\n", args.cmd[0]);           
-		strncpy(hostname, args.cmd[0] + 6, sizeof(hostname));
-		if((port_str = strchr(hostname, ':')) != NULL) {
+		ast_debug(1, "Parsing hostname:port for socket connect from \"%s\"\n", app_args[0]);
+		ast_copy_string(hostname, app_args[0] + 6, sizeof(hostname));
+		if ((port_str = strchr(hostname, ':')) != NULL) {
 			port_str[0] = 0;
 			port_str += 1;
 			port = atoi(port_str);
 		}
-		if(!port)
-			port = 2949;  /*default port, if one is not provided*/
+		if (!port) {
+			port = 2949;  /* default port, if one is not provided */
+		}
 
 		ast_gethostbyname(hostname, &hp);
 		ivr_desc.sin.sin_family = AF_INET;
@@ -378,8 +445,9 @@
 
 		if (!ser) {
 			goto exit;
-		} 
-		res = eivr_comm(chan, u, ser->fd, ser->fd, 0, pipe_delim_argbuf);
+		}
+		res = eivr_comm(chan, u, ser->fd, ser->fd, -1, pipe_delim_args, flags);
+
 	} else {
 	
 		if (pipe(child_stdin)) {
@@ -393,15 +461,6 @@
 		if (pipe(child_stderr)) {
 			ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child errors: %s\n", strerror(errno));
 			goto exit;
-		}
-		if (chan->_state != AST_STATE_UP) {
-			ast_answer(chan);
-		}
-		if (ast_activate_generator(chan, &gen, u) < 0) {
-			ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n");
-			goto exit;
-		} else {
-			gen_active = 1;
 		}
 	
 		pid = ast_safe_fork(0);
@@ -419,24 +478,23 @@
 			dup2(child_stdout[1], STDOUT_FILENO);
 			dup2(child_stderr[1], STDERR_FILENO);
 			ast_close_fds_above_n(STDERR_FILENO);
-			execv(args.cmd[0], args.cmd);
-			fprintf(stderr, "Failed to execute '%s': %s\n", args.cmd[0], strerror(errno));
+			execv(app_args[0], app_args);
+			fprintf(stderr, "Failed to execute '%s': %s\n", app_args[0], strerror(errno));
 			_exit(1);
 		} else {
 			/* parent process */
-	
 			close(child_stdin[0]);
 			child_stdin[0] = 0;
 			close(child_stdout[1]);
 			child_stdout[1] = 0;
 			close(child_stderr[1]);
 			child_stderr[1] = 0;
-			res = eivr_comm(chan, u, child_stdin[1], child_stdout[0], child_stderr[0], pipe_delim_argbuf);
+			res = eivr_comm(chan, u, child_stdin[1], child_stdout[0], child_stderr[0], pipe_delim_args, flags);
 		}
 	}
 
 	exit:
-	if (gen_active)
+	if (u->gen_active)
 		ast_deactivate_generator(chan);
 
 	if (child_stdin[0])
@@ -456,12 +514,10 @@
 
 	if (child_stderr[1])
 		close(child_stderr[1]);
-
 	if (ser) {
 		fclose(ser->f);
 		ast_tcptls_session_instance_destroy(ser);
 	}
-
 	while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list)))
 		ast_free(entry);
 
@@ -470,7 +526,7 @@
 
 static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u, 
  				int eivr_events_fd, int eivr_commands_fd, int eivr_errors_fd, 
- 				const char *args)
+ 				const struct ast_str *args, const struct ast_flags flags)
 {
 	struct playlist_entry *entry;
 	struct ast_frame *f;
@@ -482,6 +538,7 @@
  	char *command;
  	int res = -1;
 	int test_available_fd = -1;
+	int hangup_info_sent = 0;
   
  	FILE *eivr_commands = NULL;
  	FILE *eivr_errors = NULL;
@@ -495,7 +552,7 @@
 		ast_chan_log(LOG_WARNING, chan, "Could not open stream to receive commands\n");
 		goto exit;
 	}
-	if(eivr_errors_fd) {  /* if opening a socket connection, error stream will not be used */
+	if (eivr_errors_fd > -1) {  /* if opening a socket connection, error stream will not be used */
  		if (!(eivr_errors = fdopen(eivr_errors_fd, "r"))) {
  			ast_chan_log(LOG_WARNING, chan, "Could not open stream to receive errors\n");
  			goto exit;
@@ -506,8 +563,9 @@
  
  	setvbuf(eivr_events, NULL, _IONBF, 0);
  	setvbuf(eivr_commands, NULL, _IONBF, 0);
- 	if(eivr_errors)
+ 	if (eivr_errors) {
 		setvbuf(eivr_errors, NULL, _IONBF, 0);
+	}
 
 	res = 0;
  
@@ -517,11 +575,17 @@
  			res = -1;
  			break;
  		}
- 		if (ast_check_hangup(chan)) {
- 			ast_chan_log(LOG_NOTICE, chan, "Got check_hangup\n");
- 			send_eivr_event(eivr_events, 'H', NULL, chan);
- 			res = -1;
- 			break;
+ 		if (!hangup_info_sent && !(ast_test_flag(&flags, run_dead)) && ast_check_hangup(chan)) {
+			if (ast_test_flag(&flags, ignore_hangup)) {
+				ast_chan_log(LOG_NOTICE, chan, "Got check_hangup, but ignore_hangup set so sending 'I' command\n");
+				send_eivr_event(eivr_events, 'I', "HANGUP", chan);
+				hangup_info_sent = 1;
+			} else {
+ 				ast_chan_log(LOG_NOTICE, chan, "Got check_hangup\n");
+ 				send_eivr_event(eivr_events, 'H', NULL, chan);
+ 				res = -1;
+	 			break;
+			}
  		}
  
  		ready_fd = 0;
@@ -529,9 +593,9 @@
  		errno = 0;
  		exception = 0;
  
- 		rchan = ast_waitfor_nandfds(&chan, 1, waitfds, 2, &exception, &ready_fd, &ms);
- 
- 		if (!AST_LIST_EMPTY(&u->finishlist)) {
+ 		rchan = ast_waitfor_nandfds(&chan, 1, waitfds, (eivr_errors_fd < 0) ? 1 : 2, &exception, &ready_fd, &ms);
+ 
+ 		if (chan->_state == AST_STATE_UP && !AST_LIST_EMPTY(&u->finishlist)) {
  			AST_LIST_LOCK(&u->finishlist);
  			while ((entry = AST_LIST_REMOVE_HEAD(&u->finishlist, list))) {
  				send_eivr_event(eivr_events, 'F', entry->filename, chan);
@@ -540,7 +604,7 @@
  			AST_LIST_UNLOCK(&u->finishlist);
  		}
  
- 		if (rchan) {
+ 		if (chan->_state == AST_STATE_UP && !(ast_check_hangup(chan)) && rchan) {
  			/* the channel has something */
  			f = ast_read(chan);
  			if (!f) {
@@ -566,8 +630,8 @@
  			} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
  				ast_chan_log(LOG_NOTICE, chan, "Got AST_CONTROL_HANGUP\n");
  				send_eivr_event(eivr_events, 'H', NULL, chan);
-				if (f->seqno) {
-					chan->hangupcause = f->seqno;
+				if (f->data.uint32) {
+					chan->hangupcause = f->data.uint32;
 				}
  				ast_frfree(f);
  				res = -1;
@@ -589,15 +653,37 @@
  			command = ast_strip(input);
   
  			if (option_debug)
- 				ast_chan_log(LOG_DEBUG, chan, "got command '%s'\n", input);
+ 				ast_debug(1, "got command '%s'\n", input);
   
  			if (strlen(input) < 4)
  				continue;
   
 			if (input[0] == 'P') {
- 				send_eivr_event(eivr_events, 'P', args, chan);
- 
+ 				send_eivr_event(eivr_events, 'P', args->str, chan);
+			} else if ( input[0] == 'T' ) {
+				ast_chan_log(LOG_WARNING, chan, "Answering channel if needed and starting generator\n");
+				if (chan->_state != AST_STATE_UP) {
+					if (ast_test_flag(&flags, run_dead)) {
+						ast_chan_log(LOG_WARNING, chan, "Running ExternalIVR with 'd'ead flag on non-hungup channel isn't supported\n");
+						send_eivr_event(eivr_events, 'Z', "ANSWER_FAILURE", chan);
+						continue;
+					}
+					ast_answer(chan);
+				}
+				if (!(u->gen_active)) {
+					if (ast_activate_generator(chan, &gen, u) < 0) {
+						ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n");
+						send_eivr_event(eivr_events, 'Z', "GENERATOR_FAILURE", chan);
+					} else {
+						u->gen_active = 1;
+					}
+				}
  			} else if (input[0] == 'S') {
+				if (chan->_state != AST_STATE_UP || ast_check_hangup(chan)) {
+					ast_chan_log(LOG_WARNING, chan, "Queue 'S'et called on unanswered channel\n");
+					send_eivr_event(eivr_events, 'Z', NULL, chan);
+					continue;
+				}
  				if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
  					ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
  					send_eivr_event(eivr_events, 'Z', NULL, chan);
@@ -617,6 +703,11 @@
  					AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
  				AST_LIST_UNLOCK(&u->playlist);
  			} else if (input[0] == 'A') {
+				if (chan->_state != AST_STATE_UP || ast_check_hangup(chan)) {
+					ast_chan_log(LOG_WARNING, chan, "Queue 'A'ppend called on unanswered channel\n");
+					send_eivr_event(eivr_events, 'Z', NULL, chan);
+					continue;
+				}
  				if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
  					ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
  					send_eivr_event(eivr_events, 'Z', NULL, chan);
@@ -657,6 +748,11 @@
  				res = -1;
  				break;
  			} else if (input[0] == 'O') {
+				if (chan->_state != AST_STATE_UP || ast_check_hangup(chan)) {
+					ast_chan_log(LOG_WARNING, chan, "Option called on unanswered channel\n");
+					send_eivr_event(eivr_events, 'Z', NULL, chan);
+					continue;
+				}
  				if (!strcasecmp(&input[2], "autoclear"))
  					u->option_autoclear = 1;
  				else if (!strcasecmp(&input[2], "noautoclear"))

Modified: team/group/manager2/apps/app_festival.c
URL: http://svn.digium.com/view/asterisk/team/group/manager2/apps/app_festival.c?view=diff&rev=118559&r1=118558&r2=118559
==============================================================================
--- team/group/manager2/apps/app_festival.c (original)
+++ team/group/manager2/apps/app_festival.c Tue May 27 14:34:11 2008
@@ -218,7 +218,7 @@
 					myf.f.samples = res / 2;
 					myf.f.offset = AST_FRIENDLY_OFFSET;
 					myf.f.src = __PRETTY_FUNCTION__;
-					myf.f.data = myf.frdata;
+					myf.f.data.ptr = myf.frdata;
 					if (ast_write(chan, &myf.f) < 0) {
 						res = -1;
 						ast_frfree(f);

Modified: team/group/manager2/apps/app_followme.c
URL: http://svn.digium.com/view/asterisk/team/group/manager2/apps/app_followme.c?view=diff&rev=118559&r1=118558&r2=118559
==============================================================================
--- team/group/manager2/apps/app_followme.c (original)
+++ team/group/manager2/apps/app_followme.c Tue May 27 14:34:11 2008
@@ -607,8 +607,8 @@
 					switch(f->subclass) {
 					case AST_CONTROL_HANGUP:
 						ast_verb(3, "%s received a hangup frame.\n", winner->name);
-						if (f->seqno) {
-							winner->hangupcause = f->seqno;
+						if (f->data.uint32) {
+							winner->hangupcause = f->data.uint32;
 						}
 						if (dg == 0) {
 							ast_verb(3, "The calling channel hungup. Need to drop everyone else.\n");

Modified: team/group/manager2/apps/app_ices.c
URL: http://svn.digium.com/view/asterisk/team/group/manager2/apps/app_ices.c?view=diff&rev=118559&r1=118558&r2=118559
==============================================================================
--- team/group/manager2/apps/app_ices.c (original)
+++ team/group/manager2/apps/app_ices.c Tue May 27 14:34:11 2008
@@ -157,7 +157,7 @@
 				break;
 			}
 			if (f->frametype == AST_FRAME_VOICE) {
-				res = write(fds[1], f->data, f->datalen);
+				res = write(fds[1], f->data.ptr, f->datalen);
 				if (res < 0) {
 					if (errno != EAGAIN) {
 						ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));

Modified: team/group/manager2/apps/app_jack.c
URL: http://svn.digium.com/view/asterisk/team/group/manager2/apps/app_jack.c?view=diff&rev=118559&r1=118558&r2=118559
==============================================================================
--- team/group/manager2/apps/app_jack.c (original)
+++ team/group/manager2/apps/app_jack.c Tue May 27 14:34:11 2008
@@ -484,7 +484,7 @@
 	float f_buf[f->samples * 8];
 	size_t f_buf_used = 0;
 	int i;
-	int16_t *s_buf = f->data;
+	int16_t *s_buf = f->data.ptr;
 	size_t res;
 
 	memset(f_buf, 0, sizeof(f_buf));
@@ -572,7 +572,7 @@
 		.frametype = AST_FRAME_VOICE,
 		.subclass = AST_FORMAT_SLINEAR,
 		.src = "JACK",
-		.data = buf,
+		.data.ptr = buf,

[... 36190 lines stripped ...]



More information about the asterisk-commits mailing list