[svn-commits] mmichelson: trunk r136631 - /trunk/main/channel.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Aug 7 14:36:47 CDT 2008


Author: mmichelson
Date: Thu Aug  7 14:36:46 2008
New Revision: 136631

URL: http://svn.digium.com/view/asterisk?view=rev&rev=136631
Log:
Scrap the 500 ms delay when Asterisk auto-answers a channel.
Instead, poll the channel until receiving a voice frame. The
cap on this poll is 500 ms.

The optional delay is still allowable in the Answer() application,
but the delay has been moved back to its original position, after
the call to the channel's answer callback. The poll for the voice
frame will not happen if a delay is specified when calling Answer().

(closes issue #12708)
Reported by: kactus


Modified:
    trunk/main/channel.c

Modified: trunk/main/channel.c
URL: http://svn.digium.com/view/asterisk/trunk/main/channel.c?view=diff&rev=136631&r1=136630&r2=136631
==============================================================================
--- trunk/main/channel.c (original)
+++ trunk/main/channel.c Thu Aug  7 14:36:46 2008
@@ -1649,6 +1649,7 @@
 	return res;
 }
 
+#define ANSWER_WAIT_MS 500
 int __ast_answer(struct ast_channel *chan, unsigned int delay)
 {
 	int res = 0;
@@ -1670,31 +1671,40 @@
 	switch (chan->_state) {
 	case AST_STATE_RINGING:
 	case AST_STATE_RING:
-		if (delay) {
-			int needanswer = (chan->tech->answer != NULL);
-
-			ast_cdr_answer(chan->cdr);
-			ast_channel_unlock(chan);
+		if (chan->tech->answer)
+			res = chan->tech->answer(chan);
+		ast_setstate(chan, AST_STATE_UP);
+		ast_cdr_answer(chan->cdr);
+		if (delay)
 			ast_safe_sleep(chan, delay);
-			/* don't tell the channel it has been answered until *after* the delay,
-			   so that the media path will be in place and usable when it wants to
-			   send media
-			*/
-			if (needanswer) {
-				ast_channel_lock(chan);
-				res = chan->tech->answer(chan);
-				ast_channel_unlock(chan);
+		else {
+			struct ast_frame *f;
+			while (1) {
+				/* 500 ms was the original delay here, so now
+				 * we cap our waiting at 500 ms
+				 */
+				res = ast_waitfor(chan, ANSWER_WAIT_MS);
+				if (res < 0) {
+					ast_log(LOG_WARNING, "Error condition occurred when polling channel %s for a voice frame: %s\n", chan->name, strerror(errno));
+					break;
+				}
+				if (res == 0) {
+					ast_debug(2, "Didn't receive a voice frame from %s within %d ms of answering. Continuing anyway\n", chan->name, ANSWER_WAIT_MS);
+					break;
+				}
+				f = ast_read(chan);
+				if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
+					res = -1;
+					ast_debug(2, "Hangup of channel %s detected in answer routine\n", chan->name);
+					break;
+				}
+				if (f->frametype == AST_FRAME_VOICE) {
+					res = 0;
+					break;
+				}
 			}
-			ast_setstate(chan, AST_STATE_UP);	
-		} else {
-			if (chan->tech->answer) {
-				res = chan->tech->answer(chan);
-			}
-			ast_setstate(chan, AST_STATE_UP);
-			ast_cdr_answer(chan->cdr);
-			ast_channel_unlock(chan);
-		}
-		return res;
+		}
+		break;
 	case AST_STATE_UP:
 		break;
 	default:
@@ -1708,7 +1718,7 @@
 
 int ast_answer(struct ast_channel *chan)
 {
-	return __ast_answer(chan, 500);
+	return __ast_answer(chan, 0);
 }
 
 void ast_deactivate_generator(struct ast_channel *chan)




More information about the svn-commits mailing list