[asterisk-commits] res agi: Prevent run agi from eating frames it shouldn't (asterisk[certified/13.1])

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Apr 25 12:29:02 CDT 2016


Joshua Colp has submitted this change and it was merged.

Change subject: res_agi:  Prevent run_agi from eating frames it shouldn't
......................................................................


res_agi:  Prevent run_agi from eating frames it shouldn't

The run_agi function is eating control frames when it shouldn't be. This is
causing issues when an AGI is run from CONNECTED_LINE_SEND_SUB in a blond
transfer.

Alice calls Bob. Bob attended transfers to Charlie but hangs up before Charlie
answers.

Alice gets the COLP UPDATE indicating Charlie but Charlie never gets an UPDATE
and is left thinking he's connected to Bob.

In this case, when CONNECTED_LINE_SEND_SUB runs on Alice's channel and it calls
an AGI, the extra eaten frames prevent CONNECTED_LINE_SEND_SUB from running on
Charlie's channel.

The fix was to accumulate deferrable frames in the "forever" loop instead of
dropping them, and re-queue them just before running the actual agi command
or exiting.

ASTERISK-25951 #close

Change-Id: I0f4bbfd72fc1126c2aaba41da3233a33d0433645
---
M res/res_agi.c
1 file changed, 39 insertions(+), 1 deletion(-)

Approvals:
  Mark Michelson: Looks good to me, approved
  Richard Mudgett: Looks good to me, but someone else must approve
  Joshua Colp: Looks good to me, but someone else must approve; Verified



diff --git a/res/res_agi.c b/res/res_agi.c
index 921eeff..f9a7003 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -3736,6 +3736,24 @@
 
 	return AGI_RESULT_SUCCESS;
 }
+
+AST_LIST_HEAD_NOLOCK(deferred_frames, ast_frame);
+
+static void queue_deferred_frames(struct deferred_frames *deferred_frames,
+	struct ast_channel *chan)
+{
+	struct ast_frame *f;
+
+	if (!AST_LIST_EMPTY(deferred_frames)) {
+		ast_channel_lock(chan);
+		while ((f = AST_LIST_REMOVE_HEAD(deferred_frames, frame_list))) {
+			ast_queue_frame_head(chan, f);
+			ast_frfree(f);
+		}
+		ast_channel_unlock(chan);
+	}
+}
+
 static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[])
 {
 	struct ast_channel *c;
@@ -3754,6 +3772,9 @@
 	const char *sighup_str;
 	const char *exit_on_hangup_str;
 	int exit_on_hangup;
+	struct deferred_frames deferred_frames;
+
+	AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
 
 	ast_channel_lock(chan);
 	sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP");
@@ -3815,8 +3836,20 @@
 					/* Write, ignoring errors */
 					if (write(agi->audio, f->data.ptr, f->datalen) < 0) {
 					}
+					ast_frfree(f);
+				} else if (ast_is_deferrable_frame(f)) {
+					struct ast_frame *dup_f;
+
+					if ((dup_f = ast_frisolate(f))) {
+						AST_LIST_INSERT_HEAD(&deferred_frames, dup_f, frame_list);
+					}
+
+					if (dup_f != f) {
+						ast_frfree(f);
+					}
+				} else {
+					ast_frfree(f);
 				}
-				ast_frfree(f);
 			}
 		} else if (outfd > -1) {
 			size_t len = sizeof(buf);
@@ -3864,6 +3897,8 @@
 				buf[buflen - 1] = '\0';
 			}
 
+			queue_deferred_frames(&deferred_frames, chan);
+
 			if (agidebug)
 				ast_verbose("<%s>AGI Rx << %s\n", ast_channel_name(chan), buf);
 			cmd_status = agi_handle_command(chan, agi, buf, dead);
@@ -3885,6 +3920,9 @@
 			}
 		}
 	}
+
+	queue_deferred_frames(&deferred_frames, chan);
+
 	if (agi->speech) {
 		ast_speech_destroy(agi->speech);
 	}

-- 
To view, visit https://gerrit.asterisk.org/2689
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I0f4bbfd72fc1126c2aaba41da3233a33d0433645
Gerrit-PatchSet: 3
Gerrit-Project: asterisk
Gerrit-Branch: certified/13.1
Gerrit-Owner: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Anonymous Coward #1000019
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Mark Michelson <mmichelson at digium.com>
Gerrit-Reviewer: Richard Mudgett <rmudgett at digium.com>



More information about the asterisk-commits mailing list