[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