summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2008-08-07 19:36:46 +0000
committerMark Michelson <mmichelson@digium.com>2008-08-07 19:36:46 +0000
commited4e6bf52bfa76563ce23f5fd20c2246496a31e1 (patch)
tree6c69ca57b377af3aa999459aef4d7b3eb76def63 /main
parentb92df4dc1eb939677de0db95d6ea6bf49ca59098 (diff)
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 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@136631 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r--main/channel.c56
1 files changed, 33 insertions, 23 deletions
diff --git a/main/channel.c b/main/channel.c
index 431dd223e..2ab138279 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -1649,6 +1649,7 @@ int ast_hangup(struct ast_channel *chan)
return res;
}
+#define ANSWER_WAIT_MS 500
int __ast_answer(struct ast_channel *chan, unsigned int delay)
{
int res = 0;
@@ -1670,31 +1671,40 @@ int __ast_answer(struct ast_channel *chan, unsigned int delay)
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);
- }
- ast_setstate(chan, AST_STATE_UP);
- } else {
- if (chan->tech->answer) {
- res = chan->tech->answer(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);
- 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, unsigned int delay)
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)