[asterisk-commits] russell: branch russell/issue_12658 r163036 - in /team/russell/issue_12658: i...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Dec 11 09:34:56 CST 2008


Author: russell
Date: Thu Dec 11 09:34:56 2008
New Revision: 163036

URL: http://svn.digium.com/view/asterisk?view=rev&rev=163036
Log:
Change up DTMF handling in ast_read() to fix some more issues realted to issue #12658.

The fact that DTMF frames came from two different queues caused problems that could
lead to swapped received digit order.  So, simplify things a bit by only using the
frame readq to make sure the order stays intact.

Modified:
    team/russell/issue_12658/include/asterisk/channel.h
    team/russell/issue_12658/main/channel.c

Modified: team/russell/issue_12658/include/asterisk/channel.h
URL: http://svn.digium.com/view/asterisk/team/russell/issue_12658/include/asterisk/channel.h?view=diff&rev=163036&r1=163035&r2=163036
==============================================================================
--- team/russell/issue_12658/include/asterisk/channel.h (original)
+++ team/russell/issue_12658/include/asterisk/channel.h Thu Dec 11 09:34:56 2008
@@ -398,7 +398,7 @@
 	enum ast_channel_state _state;			/*!< State of line -- Don't write directly, use ast_setstate */
 	int rings;					/*!< Number of rings so far */
 	struct ast_callerid cid;			/*!< Caller ID, name, presentation etc */
-	char dtmfq[AST_MAX_EXTENSION];			/*!< Any/all queued DTMF characters */
+	char unused_old_dtmfq[AST_MAX_EXTENSION];	/*!< The DTMFQ is deprecated.  All frames should go to the readq. */
 	struct ast_frame dtmff;				/*!< DTMF frame */
 
 	char context[AST_MAX_CONTEXT];			/*!< Dialplan: Current extension context */

Modified: team/russell/issue_12658/main/channel.c
URL: http://svn.digium.com/view/asterisk/team/russell/issue_12658/main/channel.c?view=diff&rev=163036&r1=163035&r2=163036
==============================================================================
--- team/russell/issue_12658/main/channel.c (original)
+++ team/russell/issue_12658/main/channel.c Thu Dec 11 09:34:56 2008
@@ -1987,6 +1987,20 @@
 	}
 }
 
+static inline void queue_dtmf_readq(struct ast_channel *chan, struct ast_frame *f)
+{
+	struct ast_frame *fr = &chan->dtmff;
+
+	/* Put this frame back on the head of the readq to ensure that received
+	 * digits stay in the same order. */
+
+	fr->frametype = AST_FRAME_DTMF_END;
+	fr->subclass = f->subclass;
+	fr->len = f->len;
+
+	ast_queue_frame_head(chan, fr);
+}
+
 static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
 {
 	struct ast_frame *f = NULL;	/* the return value */
@@ -2020,28 +2034,6 @@
 	}
 	prestate = chan->_state;
 
-	if (!ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_EMULATE_DTMF | AST_FLAG_IN_DTMF) && 
-	    !ast_strlen_zero(chan->dtmfq) && 
-		(ast_tvzero(chan->dtmf_tv) || ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) > AST_MIN_DTMF_GAP) ) {
-		/* We have DTMF that has been deferred.  Return it now */
-		chan->dtmff.subclass = chan->dtmfq[0];
-		/* Drop first digit from the buffer */
-		memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1);
-		f = &chan->dtmff;
-		if (ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY)) {
-			ast_log(LOG_DTMF, "DTMF end emulation of '%c' queued on %s\n", f->subclass, chan->name);
-			chan->dtmff.frametype = AST_FRAME_DTMF_END;
-		} else {
-			ast_log(LOG_DTMF, "DTMF begin emulation of '%c' with duration %d queued on %s\n", f->subclass, AST_DEFAULT_EMULATE_DTMF_DURATION, chan->name);
-			chan->dtmff.frametype = AST_FRAME_DTMF_BEGIN;
-			ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
-			chan->emulate_dtmf_digit = f->subclass;
-			chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION;
-		}
-		chan->dtmf_tv = ast_tvnow();
-		goto done;
-	}
-	
 	/* Read and ignore anything on the alertpipe, but read only
 	   one sizeof(blah) per frame that we send from it */
 	if (chan->alertpipe[0] > -1) {
@@ -2114,7 +2106,37 @@
 
 	/* Check for pending read queue */
 	if (!AST_LIST_EMPTY(&chan->readq)) {
-		f = AST_LIST_REMOVE_HEAD(&chan->readq, frame_list);
+		AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->readq, f, frame_list) {
+			/* We have to be picky about which frame we pull off of the readq because
+			 * there are cases where we want to leave DTMF frames on the queue until
+			 * some later time. */
+
+			if (f->frametype != AST_FRAME_DTMF_BEGIN && f->frametype != AST_FRAME_DTMF_END) {
+				/* It's not a DTMF frame, so we know we're good. */
+				AST_LIST_REMOVE_CURRENT(&chan->readq, frame_list);
+				break;
+			}
+
+			/* It's a DTMF frame.  Let's see if now is the time. */
+
+			if (ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_EMULATE_DTMF)) {
+				/* We're in the middle of emulating a digit, or DTMF has been
+				 * explicitly deferred.  Skip this digit, then. */
+				continue;
+			}
+			
+			/* It was a DTMF FRAME, but now is an acceptable time to process it. */
+
+			AST_LIST_REMOVE_CURRENT(&chan->readq, frame_list);
+			break;
+		}
+		AST_LIST_TRAVERSE_SAFE_END
+		
+		if (!f) {
+			/* There were no acceptable frames on the readq. */
+			f = &ast_null_frame;
+		}
+
 		/* Interpret hangup and return NULL */
 		/* XXX why not the same for frames from the channel ? */
 		if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
@@ -2175,22 +2197,14 @@
 			 * However, only let emulation be forced if the other end cares about BEGIN frames */
 			if ( ast_test_flag(chan, AST_FLAG_DEFER_DTMF) ||
 				(ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY)) ) {
-				if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2) {
-					ast_log(LOG_DTMF, "DTMF end '%c' put into dtmf queue on %s\n", f->subclass, chan->name);
-					chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
-				} else
-					ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
+				queue_dtmf_readq(chan, f);
 				ast_frfree(f);
 				f = &ast_null_frame;
 			} else if (!ast_test_flag(chan, AST_FLAG_IN_DTMF | AST_FLAG_END_DTMF_ONLY)) {
 				if (!ast_tvzero(chan->dtmf_tv) && 
 				    ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) {
 					/* If it hasn't been long enough, defer this digit */
-					if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2) {
-						ast_log(LOG_DTMF, "DTMF end '%c' put into dtmf queue on %s\n", f->subclass, chan->name);
-						chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
-					} else
-						ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
+					queue_dtmf_readq(chan, f);
 					ast_frfree(f);
 					f = &ast_null_frame;
 				} else {




More information about the asterisk-commits mailing list