[Asterisk-code-review] res agi: Prevent run agi from eating frames it shouldn't (asterisk[certified/13.8])

Anonymous Coward asteriskteam at digium.com
Mon Apr 25 12:53:25 CDT 2016


Anonymous Coward #1000019 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
  Anonymous Coward #1000019: Verified
  Joshua Colp: Looks good to me, but someone else must approve



diff --git a/res/res_agi.c b/res/res_agi.c
index ff33580..e3839dd 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/2690
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.8
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-code-review mailing list