diff options
author | Richard Mudgett <rmudgett@digium.com> | 2017-01-31 16:38:49 -0600 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2017-02-01 13:33:12 -0600 |
commit | a199f94908601be10c0b43e3b3b7d67c41c5025f (patch) | |
tree | f6117dcf5685b726d257c008228e815cfe3488eb /res | |
parent | 6bed318a660c5258925c84f5d3f7012f3183c2de (diff) |
res_agi: Prevent an AGI from eating frames it should not. (Re-do)
A dialplan intercept routine is equivalent to an interrupt routine. As
such, the routine must be done quickly and you do not have access to the
media stream. These restrictions are necessary because the media stream
is the responsibility of some other code and interfering with or delaying
that processing is bad. A possible future dialplan processing
architecture change may allow the interception routine to run in a
different thread from the main thread handling the media and remove the
execution time restriction.
* Made res_agi.c:run_agi() running an AGI in an interception routine run
in DeadAGI mode. No touchy channel frames.
ASTERISK-25951
ASTERISK-26343
ASTERISK-26716
Change-Id: I638f147ca7a7f2590d7194a8ef4090eb191e4e43
Diffstat (limited to 'res')
-rw-r--r-- | res/res_agi.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/res/res_agi.c b/res/res_agi.c index 969c62dd0..cd0d621eb 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -4075,7 +4075,7 @@ static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, ch break; } } else if (c) { - ami_res = "Command Not Permitted on a dead channel"; + ami_res = "Command Not Permitted on a dead channel or intercept routine"; resultcode = 511; ast_agi_send(agi->fd, chan, "%d %s\n", resultcode, ami_res); @@ -4111,6 +4111,8 @@ 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; + /*! Running in an interception routine is like DeadAGI mode. No touchy the channel frames. */ + int in_intercept = ast_channel_get_intercept_mode(); ast_channel_lock(chan); sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP"); @@ -4145,7 +4147,7 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi } } ms = -1; - if (dead) { + if (dead || in_intercept) { c = ast_waitfor_nandfds(&chan, 0, &agi->ctrl, 1, NULL, &outfd, &ms); } else if (!ast_check_hangup(chan)) { c = ast_waitfor_nandfds(&chan, 1, &agi->ctrl, 1, NULL, &outfd, &ms); @@ -4223,10 +4225,10 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi if (agidebug) ast_verbose("<%s>AGI Rx << %s\n", ast_channel_name(chan), buf); - cmd_status = agi_handle_command(chan, agi, buf, dead); + cmd_status = agi_handle_command(chan, agi, buf, dead || in_intercept); switch (cmd_status) { case AGI_RESULT_FAILURE: - if (dead || !ast_check_hangup(chan)) { + if (dead || in_intercept || !ast_check_hangup(chan)) { /* The failure was not because of a hangup. */ returnstatus = AGI_RESULT_FAILURE; } |