]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
app_amd: Fixed timeout issue
authorMichael Cargile <mikec@vicidial.com>
Tue, 5 Nov 2019 18:16:48 +0000 (13:16 -0500)
committerMichael Cargile <mikec@vicidial.com>
Tue, 19 Nov 2019 15:07:19 +0000 (10:07 -0500)
ASTERISK_28143 attempted to fix an issue where calls with no audio would never
timeout. It did so by adding AST_FRAME_NULL as a frame type to process in its
calculations. Unfortunately these frames seem to show up at irregular time
intervals. This resulted in app_amd returning prematurely most of the time.

* Removed AST_FRAME_NULL from the calculations
* Added a check to see how much time has actually passed since app_amd began

ASTERISK-28608

Change-Id: I642a21b02d389b17e40ccd5357754b034c3daa42

apps/app_amd.c

index 1a0af3fa2d8b227e40f490b9cd288619de7d366f..39d0b79a941ebf62930858ca6d7b4d1d428e1de6 100644 (file)
@@ -162,8 +162,10 @@ static int dfltMaxWaitTimeForFrame  = 50;
 static void isAnsweringMachine(struct ast_channel *chan, const char *data)
 {
        int res = 0;
+       int audioFrameCount = 0;
        struct ast_frame *f = NULL;
        struct ast_dsp *silenceDetector = NULL;
+       struct timeval amd_tvstart;
        int dspsilence = 0, framelength = 0;
        RAII_VAR(struct ast_format *, readFormat, NULL, ao2_cleanup);
        int inInitialSilence = 1;
@@ -275,6 +277,9 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
        /* Set silence threshold to specified value */
        ast_dsp_set_threshold(silenceDetector, silenceThreshold);
 
+       /* Set our start time so we can tie the loop to real world time and not RTP updates */
+       amd_tvstart = ast_tvnow();
+
        /* Now we go into a loop waiting for frames from the channel */
        while ((res = ast_waitfor(chan, 2 * maxWaitTimeForFrame)) > -1) {
                int ms = 0;
@@ -293,7 +298,24 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
                        break;
                }
 
-               if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_NULL || f->frametype == AST_FRAME_CNG) {
+               /* Check to make sure we haven't gone over our real-world timeout in case frames get stalled for whatever reason */
+               if ( (ast_tvdiff_ms(ast_tvnow(), amd_tvstart)) > totalAnalysisTime ) {
+                       ast_frfree(f);
+                       strcpy(amdStatus , "NOTSURE");
+                       if ( audioFrameCount == 0 ) {
+                               ast_verb(3, "AMD: Channel [%s]. No audio data received in [%d] seconds.\n", ast_channel_name(chan), totalAnalysisTime);
+                               sprintf(amdCause , "NOAUDIODATA-%d", iTotalTime);
+                               break;
+                       }
+                       ast_verb(3, "AMD: Channel [%s]. Timeout...\n", ast_channel_name(chan));
+                       sprintf(amdCause , "TOOLONG-%d", iTotalTime);
+                       break;
+               }
+
+               if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_CNG) {
+                       /* keep track of the number of audio frames we get */
+                       audioFrameCount++;
+
                        /* Figure out how long the frame is in milliseconds */
                        if (f->frametype == AST_FRAME_VOICE) {
                                framelength = (ast_codec_samples_count(f) / DEFAULT_SAMPLES_PER_MS);