From 8d8323b1427b1abe60b4b8777dccb3a2232315e8 Mon Sep 17 00:00:00 2001 From: Mark Michelson Date: Thu, 3 Nov 2016 16:42:40 -0500 Subject: [PATCH] AGI: Only defer frames when in an interception routine. AGI recently was modified to defer important frames. This was because when AGI was used in a connected line interception routine, the resulting connected line frame would end up getting discarded by the AGI. However, this caused bad behavior in other cases. Specifically, during a transfer, if someone attempted to manually set the Caller ID on a channel in an AGI, the deferred connected line frame would end up overwriting what had been manually set in the AGI. Since the initial issue was specific to interception routines, this change removes the manual frame deferral from AGI and instead uses the new frame deferral API in interception routines. ASTERISK-26343 #close Reported by Morton Tryfoss Change-Id: Iab7d39436d0ee99bfe32ad55ef91e9bd88db4208 --- main/channel.c | 24 ++++++++++++++++++++++++ res/res_agi.c | 38 +------------------------------------- 2 files changed, 25 insertions(+), 37 deletions(-) diff --git a/main/channel.c b/main/channel.c index f00f222c98..9ac8a640f0 100644 --- a/main/channel.c +++ b/main/channel.c @@ -10261,9 +10261,15 @@ int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struc ast_party_connected_line_copy(ast_channel_connected(macro_chan), connected); } + ast_channel_start_defer_frames(macro_chan); ast_channel_unlock(macro_chan); retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args); + + ast_channel_lock(macro_chan); + ast_channel_stop_defer_frames(macro_chan); + ast_channel_unlock(macro_chan); + if (!retval) { struct ast_party_connected_line saved_connected; @@ -10311,9 +10317,15 @@ int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct a ast_party_redirecting_copy(ast_channel_redirecting(macro_chan), redirecting); } + ast_channel_start_defer_frames(macro_chan); ast_channel_unlock(macro_chan); retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args); + + ast_channel_lock(macro_chan); + ast_channel_stop_defer_frames(macro_chan); + ast_channel_unlock(macro_chan); + if (!retval) { struct ast_party_redirecting saved_redirecting; @@ -10354,9 +10366,15 @@ int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct ast_party_connected_line_copy(ast_channel_connected(sub_chan), connected); } + ast_channel_start_defer_frames(sub_chan); ast_channel_unlock(sub_chan); retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args, 0); + + ast_channel_lock(sub_chan); + ast_channel_stop_defer_frames(sub_chan); + ast_channel_unlock(sub_chan); + if (!retval) { struct ast_party_connected_line saved_connected; @@ -10397,9 +10415,15 @@ int ast_channel_redirecting_sub(struct ast_channel *autoservice_chan, struct ast ast_party_redirecting_copy(ast_channel_redirecting(sub_chan), redirecting); } + ast_channel_start_defer_frames(sub_chan); ast_channel_unlock(sub_chan); retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args, 0); + + ast_channel_lock(sub_chan); + ast_channel_stop_defer_frames(sub_chan); + ast_channel_unlock(sub_chan); + if (!retval) { struct ast_party_redirecting saved_redirecting; diff --git a/res/res_agi.c b/res/res_agi.c index e0eb8e2ecb..cb23a07afc 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -4093,23 +4093,6 @@ static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, ch 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; @@ -4128,9 +4111,6 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi 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"); @@ -4192,20 +4172,8 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi /* 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); @@ -4253,8 +4221,6 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi 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); @@ -4277,8 +4243,6 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi } } - queue_deferred_frames(&deferred_frames, chan); - if (agi->speech) { ast_speech_destroy(agi->speech); } -- 2.47.2