Scrap the 500 ms delay when Asterisk auto-answers a channel.
authorMark Michelson <mmichelson@digium.com>
Thu, 7 Aug 2008 19:36:46 +0000 (19:36 +0000)
committerMark Michelson <mmichelson@digium.com>
Thu, 7 Aug 2008 19:36:46 +0000 (19:36 +0000)
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

main/channel.c

index 431dd22..2ab1382 100644 (file)
@@ -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)