[asterisk-commits] murf: branch murf/macrogosub r42035 - in /team/murf/macrogosub: ./ apps/ chan...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Tue Sep 5 10:26:37 MST 2006


Author: murf
Date: Tue Sep  5 12:26:37 2006
New Revision: 42035

URL: http://svn.digium.com/view/asterisk?rev=42035&view=rev
Log:
Merged revisions 41828-41829,41831,41849-41850,41864-41865,41879,41881,41883,41900-41901,41915-41916,41930,41944,41958-41960,41974,41990,42015,42021 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/trunk

................
r41828 | bweschke | 2006-09-03 08:26:44 -0600 (Sun, 03 Sep 2006) | 3 lines

 Block 30546 from coming into /trunk. Some old cleanup.


................
r41829 | bweschke | 2006-09-03 08:28:25 -0600 (Sun, 03 Sep 2006) | 11 lines

Merged revisions 41827 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.2

........
r41827 | bweschke | 2006-09-03 10:16:08 -0400 (Sun, 03 Sep 2006) | 3 lines

 Setting a retry of 0 is generally not a good idea and shouldn't be allowed. (#7574 - reported by regin)


........

................
r41831 | bweschke | 2006-09-03 08:54:02 -0600 (Sun, 03 Sep 2006) | 3 lines

 r41830 isn't going to merge cleanly into /trunk so it is blocked.


................
r41849 | russell | 2006-09-03 09:04:26 -0600 (Sun, 03 Sep 2006) | 2 lines

remove leading space in Packet manager event header

................
r41850 | bweschke | 2006-09-03 09:21:12 -0600 (Sun, 03 Sep 2006) | 3 lines

 We don't spy on Zap/psuedo channels. Not at all. Never. (#7871 - sxpert reporting)


................
r41864 | russell | 2006-09-03 10:41:02 -0600 (Sun, 03 Sep 2006) | 6 lines

Don't use ast_frdup() in the AST_LIST_INSERT_TAIL macro directly.  That was a
very stupid thing to do.  It ends up duplicating the frame twice, linking in
one of them and setting the tail pointer to the other one.  Sorry ...

Thanks to file for pointing out the breakage!!!  file rocks.

................
r41865 | file | 2006-09-03 10:44:49 -0600 (Sun, 03 Sep 2006) | 2 lines

Tweak the if statement a bit

................
r41879 | bweschke | 2006-09-03 11:12:30 -0600 (Sun, 03 Sep 2006) | 3 lines

 Don't keep trying the same member in certain strategies when members of the queue are unavailable (#7278 - diLLec reported and patched)


................
r41881 | bweschke | 2006-09-03 11:15:07 -0600 (Sun, 03 Sep 2006) | 3 lines

 Blocking 41880 from coming into /trunk since I already patched it in /trunk first. Ooops!


................
r41883 | bweschke | 2006-09-03 11:40:08 -0600 (Sun, 03 Sep 2006) | 11 lines

Merged revisions 41882 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.2

........
r41882 | bweschke | 2006-09-03 13:38:22 -0400 (Sun, 03 Sep 2006) | 3 lines

 Make sure the forwarded channel inherits variables appropriately when we receive a call forward in the queue. (#7867 - raarts reported and patched)


........

................
r41900 | bweschke | 2006-09-03 13:07:58 -0600 (Sun, 03 Sep 2006) | 3 lines

 Some changes/fixes for func_curl. curl_global_init is only supposed to be called once, and if it returns non-zero, we need to give up on further executions with that instance. Additionally, let's set absolute timeout values for the CURL connections to try and prevent possible Zap (and possibly other channel tech) channel lockouts.


................
r41901 | bweschke | 2006-09-03 13:32:51 -0600 (Sun, 03 Sep 2006) | 3 lines

 This was added to app_dial a while back, and now it's in app_queue as well. Provide an option to prevent members of the queue from forwarding calls from the queue to somewhere else. 


................
r41915 | bweschke | 2006-09-03 14:23:41 -0600 (Sun, 03 Sep 2006) | 5 lines

 Changes/fixes to the app_waitforsilence app to make it behave more the way the author originally intended for it 
 to function along with an option to keep backward compatible with "old-style" functionality in 1.2. 
 (#6595 - davetroy reported and patched w/some very minor mods/corrections)


................
r41916 | bweschke | 2006-09-03 14:44:14 -0600 (Sun, 03 Sep 2006) | 3 lines

 Fix enum indexing problem with m() in WaitExten. Reported by Pavel J, in asterisk-dev.


................
r41930 | bweschke | 2006-09-03 15:26:04 -0600 (Sun, 03 Sep 2006) | 3 lines

 Provide a little more protection to make sure that a MOH class is specified when using the 'm' option with WaitExten, and prevent a segfault in the process.


................
r41944 | russell | 2006-09-03 16:56:01 -0600 (Sun, 03 Sep 2006) | 9 lines

when calling this function to append to a dynamic string and the buffer was not
large enough and had to be reallocated, cut off the partially appended data.
Otherwise, the function will get called over and over again appending to the
end every time and never thinking it has enough room.

Thanks to jmls for access to his machine for debugging!

(issue #7691)

................
r41958 | russell | 2006-09-03 17:14:54 -0600 (Sun, 03 Sep 2006) | 4 lines

Add the ability to specify that a frame should not be considered for caching
for uses in cases where you *know* that it will do no good.  This patch was
inspired by file for use in some work of his on mixmonitor/chanspy.

................
r41959 | file | 2006-09-03 17:30:37 -0600 (Sun, 03 Sep 2006) | 2 lines

Make the difference clear about what the responsibilities of the core and a spy are when it comes to spying on a channel. The core is responsible for adding a spy to a channel, feeding frames into the spy, removing the spy from the channel, and notifying the spy that is has been detached. The spy is responsible for reading frames in, and cleaning itself up. Each side will not try to do the other's job.

................
r41960 | file | 2006-09-03 17:45:03 -0600 (Sun, 03 Sep 2006) | 2 lines

Use tabs instead of spaces (I <3 tabs -- this is for you Qwell)

................
r41974 | file | 2006-09-03 21:18:12 -0600 (Sun, 03 Sep 2006) | 2 lines

Remove old unused functions

................
r41990 | oej | 2006-09-04 09:57:26 -0600 (Mon, 04 Sep 2006) | 2 lines

Make sure we handle CANCEL/ACK properly (imported with mods from 1.2)

................
r42015 | qwell | 2006-09-05 10:38:22 -0600 (Tue, 05 Sep 2006) | 12 lines

Merged revisions 42014 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.2

........
r42014 | qwell | 2006-09-05 09:27:46 -0700 (Tue, 05 Sep 2006) | 4 lines

Small typo in zapata.conf.sample

Reported by ppyy in 7881

........

................
r42021 | file | 2006-09-05 11:01:02 -0600 (Tue, 05 Sep 2006) | 2 lines

Minor tweak - we need to lock the channel when we are removing the spy from it.

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

Modified:
    team/murf/macrogosub/   (props changed)
    team/murf/macrogosub/UPGRADE.txt
    team/murf/macrogosub/apps/app_chanspy.c
    team/murf/macrogosub/apps/app_mixmonitor.c
    team/murf/macrogosub/apps/app_queue.c
    team/murf/macrogosub/apps/app_waitforsilence.c
    team/murf/macrogosub/channels/chan_sip.c
    team/murf/macrogosub/configs/zapata.conf.sample
    team/murf/macrogosub/funcs/func_curl.c
    team/murf/macrogosub/include/asterisk/chanspy.h
    team/murf/macrogosub/include/asterisk/frame.h
    team/murf/macrogosub/main/channel.c
    team/murf/macrogosub/main/frame.c
    team/murf/macrogosub/main/pbx.c
    team/murf/macrogosub/main/utils.c
    team/murf/macrogosub/res/res_jabber.c

Propchange: team/murf/macrogosub/
------------------------------------------------------------------------------
    automerge = yes

Propchange: team/murf/macrogosub/
------------------------------------------------------------------------------
Binary property 'branch-1.2-blocked' - no diff available.

Propchange: team/murf/macrogosub/
------------------------------------------------------------------------------
Binary property 'branch-1.2-merged' - no diff available.

Propchange: team/murf/macrogosub/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Sep  5 12:26:37 2006
@@ -1,1 +1,1 @@
-/trunk:1-41820
+/trunk:1-42033

Modified: team/murf/macrogosub/UPGRADE.txt
URL: http://svn.digium.com/view/asterisk/team/murf/macrogosub/UPGRADE.txt?rev=42035&r1=42034&r2=42035&view=diff
==============================================================================
--- team/murf/macrogosub/UPGRADE.txt (original)
+++ team/murf/macrogosub/UPGRADE.txt Tue Sep  5 12:26:37 2006
@@ -216,6 +216,12 @@
   previously used only by EXTENDED_ODBC_STORAGE. This means that you will need to update
   your table format using the schema provided in doc/odbcstorage.txt
 
+* app_waitforsilence: Fixes have been made to this application which changes the 
+  default behavior with how quickly it returns. You can maintain "old-style" behavior
+  with the addition/use of a third "timeout" parameter.
+  Please consult the application documentation and make changes to your dialplan 
+  if appropriate.
+
 Manager:
 
 * After executing the 'status' manager action, the "Status" manager events

Modified: team/murf/macrogosub/apps/app_chanspy.c
URL: http://svn.digium.com/view/asterisk/team/murf/macrogosub/apps/app_chanspy.c?rev=42035&r1=42034&r2=42035&view=diff
==============================================================================
--- team/murf/macrogosub/apps/app_chanspy.c (original)
+++ team/murf/macrogosub/apps/app_chanspy.c Tue Sep  5 12:26:37 2006
@@ -211,21 +211,6 @@
 	return res;
 }
 
-static void stop_spying(struct ast_channel_spy *spy) 
-{
-	/* If our status has changed to DONE, then the channel we're spying on is gone....
-	   DON'T TOUCH IT!!!  RUN AWAY!!! */
-	if (spy->status == CHANSPY_DONE)
-		return;
-
-	if (!spy->chan)
-		return;
-
-	ast_channel_lock(spy->chan);
-	ast_channel_spy_remove(spy->chan, spy);
-	ast_channel_unlock(spy->chan);
-};
-
 /* Map 'volume' levels from -4 through +4 into
    decibel (dB) settings for channel drivers
 */
@@ -327,10 +312,11 @@
 	*/
 	while ((res = ast_waitfor(chan, -1) > -1) &&
 	       csth.spy.status == CHANSPY_RUNNING &&
-	       !ast_check_hangup(chan) &&
 	       csth.spy.chan) {
-		if (!(f = ast_read(chan)))
+		if (!(f = ast_read(chan)) || ast_check_hangup(chan)) {
+			running = -1;
 			break;
+		}
 
 		if (ast_test_flag(flags, OPTION_WHISPER) &&
 		    (f->frametype == AST_FRAME_VOICE)) {
@@ -381,13 +367,18 @@
 	else
 		ast_deactivate_generator(chan);
 
-	stop_spying(&csth.spy);
+	/* If a channel still exists on our spy structure then we need to remove ourselves */
+	if (csth.spy.chan) {
+		csth.spy.status = CHANSPY_DONE;
+		ast_channel_lock(csth.spy.chan);
+		ast_channel_spy_remove(csth.spy.chan, &csth.spy);
+		ast_channel_unlock(csth.spy.chan);
+	}
+	ast_channel_spy_free(&csth.spy);
 	
 	if (option_verbose >= 2)
 		ast_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name);
 	
-	ast_mutex_destroy(&csth.spy.lock);
-
 	return running;
 }
 
@@ -396,6 +387,7 @@
 {
 	struct ast_channel *this;
 
+	redo:
 	if (spec)
 		this = ast_walk_channel_by_name_prefix_locked(last, spec, strlen(spec));
 	else if (exten)
@@ -403,8 +395,11 @@
 	else
 		this = ast_channel_walk_locked(last);
 
-	if (this)
+	if (this) {
 		ast_channel_unlock(this);
+		if (!strncmp(this->name, "Zap/pseudo", 10))
+			goto redo;
+	}
 
 	return this;
 }
@@ -528,6 +523,8 @@
 				peer = NULL;
 			}
 		}
+		if (res == -1)
+			break;
 	}
 	
 	ast_clear_flag(chan, AST_FLAG_SPYING);

Modified: team/murf/macrogosub/apps/app_mixmonitor.c
URL: http://svn.digium.com/view/asterisk/team/murf/macrogosub/apps/app_mixmonitor.c?rev=42035&r1=42034&r2=42035&view=diff
==============================================================================
--- team/murf/macrogosub/apps/app_mixmonitor.c (original)
+++ team/murf/macrogosub/apps/app_mixmonitor.c Tue Sep  5 12:26:37 2006
@@ -122,23 +122,6 @@
 	AST_APP_OPTION_ARG('W', MUXFLAG_VOLUME, OPT_ARG_VOLUME),
 });
 
-static void stopmon(struct ast_channel_spy *spy) 
-{
-	struct ast_channel *chan = spy->chan;
-
-	/* If our status has changed to DONE, then the channel we're spying on is gone....
-	   DON'T TOUCH IT!!!  RUN AWAY!!! */
-	if (spy->status == CHANSPY_DONE)
-		return;
-  
-	if (!chan)
-		return;
-
-	ast_channel_lock(chan);
-	ast_channel_spy_remove(chan, spy);
-	ast_channel_unlock(chan);
-}
-
 static int startmon(struct ast_channel *chan, struct ast_channel_spy *spy) 
 {
 	struct ast_channel *peer;
@@ -176,9 +159,8 @@
 
 		ast_channel_spy_trigger_wait(&mixmonitor->spy);
 		
-		if (!mixmonitor->spy.chan || mixmonitor->spy.status != CHANSPY_RUNNING) {
+		if (!mixmonitor->spy.chan || mixmonitor->spy.status != CHANSPY_RUNNING)
 			break;
-		}
 		
 		while (1) {
 			if (!(f = ast_channel_spy_read_frame(&mixmonitor->spy, SAMPLES_PER_FRAME)))
@@ -194,15 +176,15 @@
 				next = AST_LIST_NEXT(f, frame_list);
 				if (write)
 					ast_writestream(mixmonitor->fs, f);
-				ast_frfree(f);
+				ast_frame_free(f, 0);
 			}
 		}
 	}
 
 	ast_mutex_unlock(&mixmonitor->spy.lock);
-	
-	stopmon(&mixmonitor->spy);
-
+
+	ast_channel_spy_free(&mixmonitor->spy);
+	
 	if (option_verbose > 1)
 		ast_verbose(VERBOSE_PREFIX_2 "End MixMonitor Recording %s\n", mixmonitor->name);
 
@@ -211,8 +193,6 @@
 			ast_verbose(VERBOSE_PREFIX_2 "Executing [%s]\n", mixmonitor->post_process);
 		ast_safe_system(mixmonitor->post_process);
 	}
-
-	ast_mutex_destroy(&mixmonitor->spy.lock);
 		
 	ast_closestream(mixmonitor->fs);
 

Modified: team/murf/macrogosub/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/murf/macrogosub/apps/app_queue.c?rev=42035&r1=42034&r2=42035&view=diff
==============================================================================
--- team/murf/macrogosub/apps/app_queue.c (original)
+++ team/murf/macrogosub/apps/app_queue.c Tue Sep  5 12:26:37 2006
@@ -139,6 +139,8 @@
 "      'H' -- allow caller to hang up by hitting *.\n"
 "      'n' -- no retries on the timeout; will exit this application and \n"
 "             go to the next step.\n"
+"      'i' -- ignore call forward requests from queue members and do nothing\n"
+"             when they are requested.\n"
 "      'r' -- ring instead of playing MOH\n"
 "      't' -- allow the called user transfer the calling user\n"
 "      'T' -- to allow the calling user to transfer the call.\n"
@@ -839,7 +841,7 @@
 		q->periodicannouncefrequency = atoi(val);
 	} else if (!strcasecmp(param, "retry")) {
 		q->retry = atoi(val);
-		if (q->retry < 0)
+		if (q->retry <= 0)
 			q->retry = DEFAULT_RETRY;
 	} else if (!strcasecmp(param, "wrapuptime")) {
 		q->wrapuptime = atoi(val);
@@ -1600,6 +1602,11 @@
 			ast_cdr_busy(qe->chan->cdr);
 		tmp->stillgoing = 0;
 		update_dial_status(qe->parent, tmp->member, status);
+
+		ast_mutex_lock(&qe->parent->lock);
+		qe->parent->rrpos++;
+		ast_mutex_unlock(&qe->parent->lock);
+
 		(*busies)++;
 		return 0;
 	} else if (status != tmp->oldstatus)
@@ -1826,7 +1833,7 @@
 
 #define AST_MAX_WATCHERS 256
 
-static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect)
+static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
 {
 	char *queue = qe->parent->name;
 	struct callattempt *o;
@@ -1887,8 +1894,12 @@
 					peer = o;
 				}
 			} else if (o->chan && (o->chan == winner)) {
-				ast_copy_string(on, o->member->interface, sizeof(on));
-				if (!ast_strlen_zero(o->chan->call_forward)) {
+				if (!ast_strlen_zero(o->chan->call_forward) && !forwardsallowed) {
+					ast_copy_string(on, o->member->interface, sizeof(on));
+					if (option_verbose > 2)
+						ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s' prevented.\n", in->name, o->chan->call_forward);
+                                        winner = o->chan = NULL;
+				} else if (!ast_strlen_zero(o->chan->call_forward)) {
 					char tmpchan[256];
 					char *stuff;
 					char *tech;
@@ -1914,6 +1925,7 @@
 						o->stillgoing = 0;
 						numnochan++;
 					} else {
+						ast_channel_inherit_variables(in, o->chan);
 						if (o->chan->cid.cid_num)
 							free(o->chan->cid.cid_num);
 						o->chan->cid.cid_num = ast_strdup(in->cid.cid_num);
@@ -2280,6 +2292,7 @@
 	struct ast_app *mixmonapp = NULL;
 	char *p;
 	char vars[2048];
+	int forwardsallowed = 1;
 
 	memset(&bridge_config, 0, sizeof(bridge_config));
 	time(&now);
@@ -2311,6 +2324,9 @@
 			if ((now - qe->start >= qe->parent->timeout))
 				*go_on = 1;
 			break;
+		case 'i':
+			forwardsallowed = 0;
+			break;
 		}
 
 	/* Hold the lock while we setup the outgoing calls */
@@ -2364,7 +2380,7 @@
 	ast_mutex_unlock(&qe->parent->lock);
 	if (use_weight)
 		AST_LIST_UNLOCK(&queues);
-	lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT));
+	lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
 	ast_mutex_lock(&qe->parent->lock);
 	if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
 		store_next(qe, outgoing);

Modified: team/murf/macrogosub/apps/app_waitforsilence.c
URL: http://svn.digium.com/view/asterisk/team/murf/macrogosub/apps/app_waitforsilence.c?rev=42035&r1=42034&r2=42035&view=diff
==============================================================================
--- team/murf/macrogosub/apps/app_waitforsilence.c (original)
+++ team/murf/macrogosub/apps/app_waitforsilence.c Tue Sep  5 12:26:37 2006
@@ -4,7 +4,7 @@
  * Copyright (C) 1999 - 2005, Digium, Inc.
  *
  * WaitForSilence Application by David C. Troy <dave at popvox.com>
- * Version 1.00 2004-01-29
+ * Version 1.11 2006-06-29
  *
  * Mark Spencer <markster at digium.com>
  *
@@ -25,6 +25,7 @@
  *   - Waits for up to 'x' milliseconds of silence, 'y' times \n
  *   - WaitForSilence(500,2) will wait for 1/2 second of silence, twice \n
  *   - WaitForSilence(1000,1) will wait for 1 second of silence, once \n
+ *   - WaitForSilence(300,3,10) will wait for 300ms of silence, 3 times, and return after 10sec \n
  *
  * \author David C. Troy <dave at popvox.com>
  *
@@ -50,34 +51,43 @@
 
 static char *app = "WaitForSilence";
 static char *synopsis = "Waits for a specified amount of silence";
-static char *descrip = 
-"  WaitForSilence(x[|y]) Wait for Silence: Waits for up to 'x' \n"
-"milliseconds of silence, 'y' times or 1 if omitted\n"
-"Set the channel variable WAITSTATUS with to one of these values:"
-"SILENCE - if silence of x ms was detected"
-"TIMEOUT - if silence of x ms was not detected."
-"Examples:\n"
+static char *descrip =
+"  WaitForSilence(silencerequired[|iterations][|timeout]) \n"
+"Wait for Silence: Waits for up to 'silencerequired' \n"
+"milliseconds of silence, 'iterations' times or once if omitted.\n"
+"An optional timeout specified the number of seconds to return\n"
+"after, even if we do not receive the specified amount of silence.\n"
+"Use 'timeout' with caution, as it may defeat the purpose of this\n"
+"application, which is to wait indefinitely until silence is detected\n"
+"on the line.  This is particularly useful for reverse-911-type\n"
+"call broadcast applications where you need to wait for an answering\n"
+"machine to complete its spiel before playing a message.\n"
+"The timeout parameter is specified only to avoid an infinite loop in\n"
+"cases where silence is never achieved.  Typically you will want to\n"
+"include two or more calls to WaitForSilence when dealing with an answering\n"
+"machine; first waiting for the spiel to finish, then waiting for the beep, etc.\n\n"
+  "Examples:\n"
 "  - WaitForSilence(500|2) will wait for 1/2 second of silence, twice\n"
-"  - WaitForSilence(1000) will wait for 1 second of silence, once\n";
-
-
-static int do_waiting(struct ast_channel *chan, int maxsilence) {
-
+"  - WaitForSilence(1000) will wait for 1 second of silence, once\n"
+"  - WaitForSilence(300|3|10) will wait for 300ms silence, 3 times,\n"
+"     and returns after 10 sec, even if silence is not detected\n\n"
+"Sets the channel variable WAITSTATUS with to one of these values:\n"
+"SILENCE - if exited with silence detected\n"
+"TIMEOUT - if exited without silence detected after timeout\n";
+
+static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstart, int timeout) {
 	struct ast_frame *f;
-	int totalsilence = 0;
 	int dspsilence = 0;
-	int gotsilence = 0; 
 	static int silencethreshold = 128;
 	int rfmt = 0;
 	int res = 0;
 	struct ast_dsp *sildet;	 /* silence detector dsp */
-	time_t start, now;
-	time(&start);
+ 	time_t now;
 
 	rfmt = chan->readformat; /* Set to linear mode */
 	res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
 	if (res < 0) {
-		ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
+		ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n");
 		return -1;
 	}
 
@@ -91,88 +101,90 @@
 	/* Await silence... */
 	f = NULL;
 	for(;;) {
-		res = ast_waitfor(chan, 2000);
-		if (!res) {
-			ast_log(LOG_WARNING, "One waitfor failed, trying another\n");
-			/* Try one more time in case of masq */
-			res = ast_waitfor(chan, 2000);
-			if (!res) {
-				ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
-				res = -1;
-			}
-		}
-
-		if (res < 0) {
+		/* Start with no silence received */
+		dspsilence = 0;
+
+		res = ast_waitfor(chan, silencereqd);
+
+		/* Must have gotten a hangup; let's exit */
+		if (res <= 0) {
 			f = NULL;
 			break;
 		}
-		f = ast_read(chan);
-		if (!f)
+		
+		/* We waited and got no frame; sounds like digital silence or a muted digital channel */
+		if (!res) {
+			dspsilence = silencereqd;
+		} else {
+			/* Looks like we did get a frame, so let's check it out */
+			f = ast_read(chan);
+			if (!f)
+				break;
+			if (f && f->frametype == AST_FRAME_VOICE) {
+				ast_dsp_silence(sildet, f, &dspsilence);
+				ast_frfree(f);
+			}
+		}
+
+		if (option_verbose > 6)
+			ast_verbose(VERBOSE_PREFIX_3 "Got %dms silence< %dms required\n", dspsilence, silencereqd);
+
+		if (dspsilence >= silencereqd) {
+			if (option_verbose > 2)
+				ast_verbose(VERBOSE_PREFIX_3 "Exiting with %dms silence >= %dms required\n", dspsilence, silencereqd);
+			/* Ended happily with silence */
+			res = 1;
+			pbx_builtin_setvar_helper(chan, "WAITSTATUS", "SILENCE");
+			ast_log(LOG_DEBUG, "WAITSTATUS was set to SILENCE\n");
 			break;
-		if (f->frametype == AST_FRAME_VOICE) {
-			dspsilence = 0;
-			ast_dsp_silence(sildet, f, &dspsilence);
-			if (dspsilence) {
-				totalsilence = dspsilence;
-				time(&start);
-			} else {
-				totalsilence = 0;
-			}
-
-			if (totalsilence >= maxsilence) {
-				if (option_verbose > 2)
-					ast_verbose(VERBOSE_PREFIX_3 "Exiting with %dms silence > %dms required\n", totalsilence, maxsilence);
-				/* Ended happily with silence */
-				gotsilence = 1;
-				pbx_builtin_setvar_helper(chan, "WAITSTATUS", "SILENCE");
-				ast_log(LOG_DEBUG, "WAITSTATUS was set to SILENCE\n");
-				ast_frfree(f);
-				break;
-			} else if ( difftime(time(&now),start) >= maxsilence/1000 ) {
-				pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT");
-				ast_log(LOG_DEBUG, "WAITSTATUS was set to TIMEOUT\n");
-				ast_frfree(f);
-				break;
-			}
-		}
-		ast_frfree(f);
-	}
+		}
+
+		if ( timeout && (difftime(time(&now),waitstart) >= timeout) ) {
+			pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT");
+			ast_log(LOG_DEBUG, "WAITSTATUS was set to TIMEOUT\n");
+			res = 0;
+			break;
+		}
+	}
+
+
 	if (rfmt && ast_set_read_format(chan, rfmt)) {
 		ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
 	}
 	ast_dsp_free(sildet);
-	return gotsilence;
+	return res;
 }
 
 static int waitforsilence_exec(struct ast_channel *chan, void *data)
 {
 	int res = 1;
-	struct ast_module_user *u;
-	int maxsilence = 1000;
+	int silencereqd = 1000;
+	int timeout = 0;
 	int iterations = 1, i;
-
-	u = ast_module_user_add(chan);
-	
+	time_t waitstart;
+
 	res = ast_answer(chan); /* Answer the channel */
 
-	if (!data || ((sscanf(data, "%d|%d", &maxsilence, &iterations) != 2) &&
-		(sscanf(data, "%d", &maxsilence) != 1))) {
-		ast_log(LOG_WARNING, "Using default value of 1000ms, 1 iteration\n");
+	if (!data || ( (sscanf(data, "%d|%d|%d", &silencereqd, &iterations, &timeout) != 3) &&
+		(sscanf(data, "%d|%d", &silencereqd, &iterations) != 2) &&
+		(sscanf(data, "%d", &silencereqd) != 1) ) ) {
+		ast_log(LOG_WARNING, "Using default value of 1000ms, 1 iteration, no timeout\n");
 	}
 
 	if (option_verbose > 2)
-		ast_verbose(VERBOSE_PREFIX_3 "Waiting %d time(s) for %d ms silence\n", iterations, maxsilence);
-	
+		ast_verbose(VERBOSE_PREFIX_3 "Waiting %d time(s) for %d ms silence with %d timeout\n", iterations, silencereqd, timeout);
+
+	time(&waitstart);
 	res = 1;
 	for (i=0; (i<iterations) && (res == 1); i++) {
-		res = do_waiting(chan, maxsilence);
-	}
-	ast_module_user_remove(u);
+		res = do_waiting(chan, silencereqd, waitstart, timeout);
+	}
 	if (res > 0)
 		res = 0;
 	return res;
 }
 
+
 static int unload_module(void)
 {
 	int res;
@@ -190,3 +202,4 @@
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Wait For Silence");
+

Modified: team/murf/macrogosub/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/murf/macrogosub/channels/chan_sip.c?rev=42035&r1=42034&r2=42035&view=diff
==============================================================================
--- team/murf/macrogosub/channels/chan_sip.c (original)
+++ team/murf/macrogosub/channels/chan_sip.c Tue Sep  5 12:26:37 2006
@@ -3153,7 +3153,7 @@
 {
 	struct sip_pvt *p = ast->tech_pvt;
 	int needcancel = FALSE;
-	struct ast_flags locflags = {0};
+	int needdestroy = 0;
 	struct ast_channel *oldowner = ast;
 
 	if (!p) {
@@ -3166,7 +3166,7 @@
 			ast_log(LOG_DEBUG, "SIP Transfer: Not hanging up right now... Rescheduling hangup for %s.\n", p->callid);
 		if (p->autokillid > -1)
 			sip_cancel_destroy(p);
-		sip_scheddestroy(p, 32000);
+		sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
 		ast_clear_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER);	/* Really hang up next time */
 		ast_clear_flag(&p->flags[0], SIP_NEEDDESTROY);
 		p->owner->tech_pvt = NULL;
@@ -3202,7 +3202,6 @@
 	}
 
 	/* Disconnect */
-	p = ast->tech_pvt;
 	if (p->vad)
 		ast_dsp_free(p->vad);
 
@@ -3212,7 +3211,16 @@
 	ast_atomic_fetchadd_int(&usecnt, -1);
 	ast_update_use_count();
 
-	ast_set_flag(&locflags, SIP_NEEDDESTROY);	
+	/* Do not destroy this pvt until we have timeout or
+	   get an answer to the BYE or INVITE/CANCEL 
+	   If we get no answer during retransmit period, drop the call anyway.
+	   (Sorry, mother-in-law, you can't deny a hangup by sending
+	   603 declined to BYE...)
+	*/
+	if (ast_test_flag(&p->flags[0], SIP_ALREADYGONE))
+		needdestroy = 1;	/* Set destroy flag at end of this function */
+	else
+		sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
 
 	/* Start the process if it's not already started */
 	if (!ast_test_flag(&p->flags[0], SIP_ALREADYGONE) && !ast_strlen_zero(p->initreq.data)) {
@@ -3224,13 +3232,13 @@
 				/* if we can't send right now, mark it pending */
 				if (!ast_test_flag(&p->flags[0], SIP_CAN_BYE)) {
 					ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
+					/* Do we need a timer here if we don't hear from them at all? */
 				} else {
 					/* Send a new request: CANCEL */
 					transmit_request_with_auth(p, SIP_CANCEL, p->ocseq, XMIT_RELIABLE, FALSE);
 					/* Actually don't destroy us yet, wait for the 487 on our original 
 					   INVITE, but do set an autodestruct just in case we never get it. */
-					ast_clear_flag(&locflags, SIP_NEEDDESTROY);
-
+					needdestroy = 0;
 					sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
 				}
 				if ( p->initid != -1 ) {
@@ -3275,7 +3283,8 @@
 			}
 		}
 	}
-	ast_copy_flags(&p->flags[0], &locflags, SIP_NEEDDESTROY);	
+	if (needdestroy)
+		ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
 	ast_mutex_unlock(&p->lock);
 	return 0;
 }
@@ -11721,7 +11730,7 @@
 				}
 			} else if (sipmethod == SIP_REGISTER) 
 				res = handle_response_register(p, resp, rest, req, ignore, seqno);
-			else if (sipmethod == SIP_BYE)
+			else if (sipmethod == SIP_BYE)		/* Ok, we're ready to go */
 				ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 
 			break;
 		case 202:   /* Transfer accepted */
@@ -11939,6 +11948,7 @@
 				handle_response_invite(p, resp, rest, req, seqno);
 			} else if (sipmethod == SIP_CANCEL) {
 				ast_log(LOG_DEBUG, "Got 200 OK on CANCEL\n");
+
 				/* Wait for 487, then destroy */
 			} else if (sipmethod == SIP_NOTIFY) {
 				/* They got the notify, this is the end */
@@ -11954,6 +11964,9 @@
 			else if (sipmethod == SIP_MESSAGE)
 				/* We successfully transmitted a message */
 				/* XXX Why destroy this pvt after message transfer? Bad */
+				ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
+			else if (sipmethod == SIP_BYE) 
+				/* Ok, we're ready to go */
 				ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
 			break;
 		case 202:   /* Transfer accepted */
@@ -13650,10 +13663,15 @@
 			if (p->owner)
 				ast_queue_hangup(p->owner);
 		}
-	} else if (p->owner)
+	} else if (p->owner) {
 		ast_queue_hangup(p->owner);
-	else
+		if (option_debug > 2)
+			ast_log(LOG_DEBUG, "Received bye, issuing owner hangup\n.");
+	} else {
 		ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
+		if (option_debug > 2)
+			ast_log(LOG_DEBUG, "Received bye, no owner, selfdestruct soon.\n.");
+	}
 	transmit_response(p, "200 OK", req);
 
 	return 1;

Modified: team/murf/macrogosub/configs/zapata.conf.sample
URL: http://svn.digium.com/view/asterisk/team/murf/macrogosub/configs/zapata.conf.sample?rev=42035&r1=42034&r2=42035&view=diff
==============================================================================
--- team/murf/macrogosub/configs/zapata.conf.sample (original)
+++ team/murf/macrogosub/configs/zapata.conf.sample Tue Sep  5 12:26:37 2006
@@ -16,7 +16,7 @@
 ; Trunk groups are used for NFAS or GR-303 connections.
 ;
 ; Group: Defines a trunk group.  
-;        group => <trunkgroup>,<dchannel>[,<backup1>...]
+;        trunkgroup => <trunkgroup>,<dchannel>[,<backup1>...]
 ;
 ;        trunkgroup  is the numerical trunk group to create
 ;        dchannel    is the zap channel which will have the 

Modified: team/murf/macrogosub/funcs/func_curl.c
URL: http://svn.digium.com/view/asterisk/team/murf/macrogosub/funcs/func_curl.c?rev=42035&r1=42034&r2=42035&view=diff
==============================================================================
--- team/murf/macrogosub/funcs/func_curl.c (original)
+++ team/murf/macrogosub/funcs/func_curl.c Tue Sep  5 12:26:37 2006
@@ -57,6 +57,7 @@
 	size_t size;
 };
 
+
 static void *myrealloc(void *ptr, size_t size)
 {
 	/* There might be a realloc() out there that doesn't like reallocing
@@ -85,13 +86,16 @@
 {
 	CURL *curl;
 
-	curl_global_init(CURL_GLOBAL_ALL);
 	curl = curl_easy_init();
 
 	if (!curl) {
 		return -1;
 	}
 
+	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+	curl_easy_setopt(curl, CURLOPT_TIMEOUT, 180);
+	curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
+	curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1);
 	curl_easy_setopt(curl, CURLOPT_URL, url);
 	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
 	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)chunk);
@@ -126,7 +130,7 @@
 	u = ast_module_user_add(chan);
 
 	AST_STANDARD_APP_ARGS(args, info);	
-	
+
 	if (!curl_internal(&chunk, args.url, args.postdata)) {
 		if (chunk.memory) {
 			chunk.memory[chunk.size] = '\0';
@@ -162,6 +166,8 @@
 	res = ast_custom_function_unregister(&acf_curl);
 
 	ast_module_user_hangup_all();
+
+	curl_global_cleanup();
 	
 	return res;
 }
@@ -170,6 +176,11 @@
 {
 	int res;
 
+	if (curl_global_init(CURL_GLOBAL_ALL)) {
+		ast_log(LOG_ERROR, "Unable to initialize the CURL library. Cannot load func_curl\n");
+		return AST_MODULE_LOAD_DECLINE;
+	}	
+
 	res = ast_custom_function_register(&acf_curl);
 
 	return res;

Modified: team/murf/macrogosub/include/asterisk/chanspy.h
URL: http://svn.digium.com/view/asterisk/team/murf/macrogosub/include/asterisk/chanspy.h?rev=42035&r1=42034&r2=42035&view=diff
==============================================================================
--- team/murf/macrogosub/include/asterisk/chanspy.h (original)
+++ team/murf/macrogosub/include/asterisk/chanspy.h Tue Sep  5 12:26:37 2006
@@ -95,6 +95,15 @@
 void ast_channel_spy_remove(struct ast_channel *chan, struct ast_channel_spy *spy);
 
 /*!
+  \brief Free a spy.
+  \param spy The spy to free
+  \return nothing
+
+  Note: This function MUST NOT be called with the spy locked.
+*/
+void ast_channel_spy_free(struct ast_channel_spy *spy);
+
+/*!
   \brief Find all spies of a particular type on a channel and stop them.
   \param chan The channel to operate on
   \param type A character string identifying the type of spies to be stopped

Modified: team/murf/macrogosub/include/asterisk/frame.h
URL: http://svn.digium.com/view/asterisk/team/murf/macrogosub/include/asterisk/frame.h?rev=42035&r1=42034&r2=42035&view=diff
==============================================================================
--- team/murf/macrogosub/include/asterisk/frame.h (original)
+++ team/murf/macrogosub/include/asterisk/frame.h Tue Sep  5 12:26:37 2006
@@ -31,6 +31,8 @@
 
 #include <sys/types.h>
 #include <sys/time.h>
+
+#include "asterisk/compiler.h"
 #include "asterisk/endian.h"
 #include "asterisk/linkedlists.h"
 
@@ -354,12 +356,18 @@
 struct ast_frame *ast_fralloc(char *source, int len);
 #endif
 
-/*!  \brief Frees a frame 
+/*!  
+ * \brief Frees a frame 
+ * 
  * \param fr Frame to free
- * Free a frame, and the memory it used if applicable
- * \return no return.
- */
-void ast_frfree(struct ast_frame *fr);
+ * \param cache Whether to consider this frame for frame caching
+ */
+void ast_frame_free(struct ast_frame *fr, int cache);
+
+static void force_inline ast_frfree(struct ast_frame *fr)
+{
+	ast_frame_free(fr, 1);
+}
 
 /*! \brief Makes a frame independent of any static storage
  * \param fr frame to act upon
@@ -377,28 +385,6 @@
  * \return Returns a frame on success, NULL on error
  */
 struct ast_frame *ast_frdup(const struct ast_frame *fr);
-
-/*! \brief Reads a frame from an fd
- * Read a frame from a stream or packet fd, as written by fd_write
- * \param fd an opened fd to read from
- * \return returns a frame on success, NULL on error
- */
-struct ast_frame *ast_fr_fdread(int fd);
-
-/*! Writes a frame to an fd
- * Write a frame to an fd
- * \param fd Which fd to write to
- * \param frame frame to write to the fd
- * \return Returns 0 on success, -1 on failure
- */
-int ast_fr_fdwrite(int fd, struct ast_frame *frame);
-
-/*! \brief Sends a hangup to an fd 
- * Send a hangup (NULL equivalent) on an fd
- * \param fd fd to write to
- * \return Returns 0 on success, -1 on failure
- */
-int ast_fr_fdhangup(int fd);
 
 void ast_swapcopy_samples(void *dst, const void *src, int samples);
 

Modified: team/murf/macrogosub/main/channel.c
URL: http://svn.digium.com/view/asterisk/team/murf/macrogosub/main/channel.c?rev=42035&r1=42034&r2=42035&view=diff
==============================================================================
--- team/murf/macrogosub/main/channel.c (original)
+++ team/murf/macrogosub/main/channel.c Tue Sep  5 12:26:37 2006
@@ -1203,22 +1203,61 @@
 	return 0;
 }
 
+/* Clean up a channel's spy information */
+static void spy_cleanup(struct ast_channel *chan)
+{
+	if (!AST_LIST_EMPTY(&chan->spies->list))
+		return;
+	if (chan->spies->read_translator.path)
+		ast_translator_free_path(chan->spies->read_translator.path);
+	if (chan->spies->write_translator.path)
+		ast_translator_free_path(chan->spies->write_translator.path);
+	free(chan->spies);
+	chan->spies = NULL;
+	return;
+}
+
+/* Detach a spy from it's channel */
+static void spy_detach(struct ast_channel_spy *spy, struct ast_channel *chan)
+{
+	ast_mutex_lock(&spy->lock);
+
+	/* We only need to poke them if they aren't already done */
+	if (spy->status != CHANSPY_DONE) {
+		/* Indicate to the spy to stop */
+		spy->status = CHANSPY_STOP;
+		spy->chan = NULL;
+		/* Poke the spy if needed */
+		if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE)
+			ast_cond_signal(&spy->trigger);
+	}
+
+	/* Print it out while we still have a lock so the structure can't go away (if signalled above) */
+	ast_log(LOG_DEBUG, "Spy %s removed from channel %s\n", spy->type, chan->name);
+
+	ast_mutex_unlock(&spy->lock);
+
+	return;
+}
+
 void ast_channel_spy_stop_by_type(struct ast_channel *chan, const char *type)
 {
-	struct ast_channel_spy *spy;
+	struct ast_channel_spy *spy = NULL;
 	
 	if (!chan->spies)
 		return;
 
-	AST_LIST_TRAVERSE(&chan->spies->list, spy, list) {
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->spies->list, spy, list) {
 		ast_mutex_lock(&spy->lock);
 		if ((spy->type == type) && (spy->status == CHANSPY_RUNNING)) {
-			spy->status = CHANSPY_STOP;
-			if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE)
-				ast_cond_signal(&spy->trigger);
-		}
-		ast_mutex_unlock(&spy->lock);
-	}
+			ast_mutex_unlock(&spy->lock);
+			AST_LIST_REMOVE_CURRENT(&chan->spies->list, list);
+			spy_detach(spy, chan);
+		} else
+			ast_mutex_unlock(&spy->lock);
+	}
+	AST_LIST_TRAVERSE_SAFE_END
+	spy_cleanup(chan);
 }
 
 void ast_channel_spy_trigger_wait(struct ast_channel_spy *spy)
@@ -1235,62 +1274,54 @@
 
 void ast_channel_spy_remove(struct ast_channel *chan, struct ast_channel_spy *spy)
 {
-	struct ast_frame *f;
-
 	if (!chan->spies)
 		return;
 
 	AST_LIST_REMOVE(&chan->spies->list, spy, list);
-
-	ast_mutex_lock(&spy->lock);
-
-	spy->chan = NULL;
-
+	spy_detach(spy, chan);
+	spy_cleanup(chan);
+}
+
+void ast_channel_spy_free(struct ast_channel_spy *spy)
+{
+	struct ast_frame *f = NULL;
+
+	if (spy->status == CHANSPY_DONE)
+		return;
+
+	/* Switch status to done in case we get called twice */
+	spy->status = CHANSPY_DONE;
+
+	/* Drop any frames in the queue */
+	while ((f = AST_LIST_REMOVE_HEAD(&spy->write_queue.list, frame_list)))
+		ast_frfree(f);
 	while ((f = AST_LIST_REMOVE_HEAD(&spy->read_queue.list, frame_list)))
 		ast_frfree(f);
-	
-	while ((f = AST_LIST_REMOVE_HEAD(&spy->write_queue.list, frame_list)))
-		ast_frfree(f);
-
+
+	/* Destroy the condition if in use */
 	if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE)
 		ast_cond_destroy(&spy->trigger);
 
-	ast_mutex_unlock(&spy->lock);
-
-	ast_log(LOG_DEBUG, "Spy %s removed from channel %s\n",
-		spy->type, chan->name);
-
-	if (AST_LIST_EMPTY(&chan->spies->list)) {
-		if (chan->spies->read_translator.path)
-			ast_translator_free_path(chan->spies->read_translator.path);
-		if (chan->spies->write_translator.path)
-			ast_translator_free_path(chan->spies->write_translator.path);
-		free(chan->spies);
-		chan->spies = NULL;
-	}
+	/* Destroy our mutex since it is no longer in use */
+	ast_mutex_destroy(&spy->lock);
+
+	return;
 }
 
 static void detach_spies(struct ast_channel *chan)
 {
-	struct ast_channel_spy *spy;
+	struct ast_channel_spy *spy = NULL;
 
 	if (!chan->spies)
 		return;
 
-	/* Marking the spies as done is sufficient.  Chanspy or spy users will get the picture. */
-	AST_LIST_TRAVERSE(&chan->spies->list, spy, list) {
-		ast_mutex_lock(&spy->lock);
-		spy->chan = NULL;
-		if (spy->status == CHANSPY_RUNNING)
-			spy->status = CHANSPY_DONE;
-		if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE)
-			ast_cond_signal(&spy->trigger);
-		ast_mutex_unlock(&spy->lock);
-	}
-
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->spies->list, spy, list)
-		ast_channel_spy_remove(chan, spy);
-	AST_LIST_TRAVERSE_SAFE_END;
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->spies->list, spy, list) {
+		AST_LIST_REMOVE_CURRENT(&chan->spies->list, list);
+		spy_detach(spy, chan);
+	}
+	AST_LIST_TRAVERSE_SAFE_END
+
+	spy_cleanup(chan);
 }
 
 /*! \brief Softly hangup a channel, don't lock */
@@ -1334,6 +1365,7 @@
 
 	AST_LIST_TRAVERSE(&chan->spies->list, spy, list) {
 		struct ast_channel_spy_queue *queue;
+		struct ast_frame *duped_fr;
 
 		ast_mutex_lock(&spy->lock);
 
@@ -1364,17 +1396,17 @@
 					break;
 				}
 			}
-			AST_LIST_INSERT_TAIL(&queue->list, ast_frdup(translated_frame), frame_list);
-		} else {

[... 196 lines stripped ...]


More information about the asterisk-commits mailing list