mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-03 11:11:05 +00:00
Merge "res_agi: Prevent an AGI from eating frames it should not. (Re-do)"
This commit is contained in:
@@ -4717,4 +4717,21 @@ enum ast_channel_error {
|
|||||||
*/
|
*/
|
||||||
enum ast_channel_error ast_channel_errno(void);
|
enum ast_channel_error ast_channel_errno(void);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Am I currently running an intercept dialplan routine.
|
||||||
|
* \since 13.14.0
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* \retval 0 Not in an intercept routine.
|
||||||
|
* \retval 1 In an intercept routine.
|
||||||
|
*/
|
||||||
|
int ast_channel_get_intercept_mode(void);
|
||||||
|
|
||||||
#endif /* _ASTERISK_CHANNEL_H */
|
#endif /* _ASTERISK_CHANNEL_H */
|
||||||
|
@@ -10300,6 +10300,36 @@ void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct
|
|||||||
ast_queue_control_data(chan, AST_CONTROL_REDIRECTING, data, datalen);
|
ast_queue_control_data(chan, AST_CONTROL_REDIRECTING, data, datalen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Storage to determine if the current thread is running an intercept dialplan routine.
|
||||||
|
*/
|
||||||
|
AST_THREADSTORAGE_RAW(in_intercept_routine);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Set the current intercept dialplan routine status mode.
|
||||||
|
* \since 13.14.0
|
||||||
|
*
|
||||||
|
* \param in_intercept_mode New intercept mode. (Non-zero if in intercept mode)
|
||||||
|
*
|
||||||
|
* \return Nothing
|
||||||
|
*/
|
||||||
|
static void channel_set_intercept_mode(int in_intercept_mode)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = ast_threadstorage_set_ptr(&in_intercept_routine,
|
||||||
|
in_intercept_mode ? (void *) 1 : (void *) 0);
|
||||||
|
if (status) {
|
||||||
|
ast_log(LOG_ERROR, "Failed to set dialplan intercept mode\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ast_channel_get_intercept_mode(void)
|
||||||
|
{
|
||||||
|
return ast_threadstorage_get_ptr(&in_intercept_routine) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int is_caller, int is_frame)
|
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int is_caller, int is_frame)
|
||||||
{
|
{
|
||||||
static int deprecation_warning = 0;
|
static int deprecation_warning = 0;
|
||||||
@@ -10335,7 +10365,9 @@ int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struc
|
|||||||
}
|
}
|
||||||
ast_channel_unlock(macro_chan);
|
ast_channel_unlock(macro_chan);
|
||||||
|
|
||||||
|
channel_set_intercept_mode(1);
|
||||||
retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args);
|
retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args);
|
||||||
|
channel_set_intercept_mode(0);
|
||||||
if (!retval) {
|
if (!retval) {
|
||||||
struct ast_party_connected_line saved_connected;
|
struct ast_party_connected_line saved_connected;
|
||||||
|
|
||||||
@@ -10385,7 +10417,9 @@ int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct a
|
|||||||
}
|
}
|
||||||
ast_channel_unlock(macro_chan);
|
ast_channel_unlock(macro_chan);
|
||||||
|
|
||||||
|
channel_set_intercept_mode(1);
|
||||||
retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args);
|
retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args);
|
||||||
|
channel_set_intercept_mode(0);
|
||||||
if (!retval) {
|
if (!retval) {
|
||||||
struct ast_party_redirecting saved_redirecting;
|
struct ast_party_redirecting saved_redirecting;
|
||||||
|
|
||||||
@@ -10428,7 +10462,9 @@ int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct
|
|||||||
}
|
}
|
||||||
ast_channel_unlock(sub_chan);
|
ast_channel_unlock(sub_chan);
|
||||||
|
|
||||||
|
channel_set_intercept_mode(1);
|
||||||
retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args, 0);
|
retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args, 0);
|
||||||
|
channel_set_intercept_mode(0);
|
||||||
if (!retval) {
|
if (!retval) {
|
||||||
struct ast_party_connected_line saved_connected;
|
struct ast_party_connected_line saved_connected;
|
||||||
|
|
||||||
@@ -10471,7 +10507,9 @@ int ast_channel_redirecting_sub(struct ast_channel *autoservice_chan, struct ast
|
|||||||
}
|
}
|
||||||
ast_channel_unlock(sub_chan);
|
ast_channel_unlock(sub_chan);
|
||||||
|
|
||||||
|
channel_set_intercept_mode(1);
|
||||||
retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args, 0);
|
retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args, 0);
|
||||||
|
channel_set_intercept_mode(0);
|
||||||
if (!retval) {
|
if (!retval) {
|
||||||
struct ast_party_redirecting saved_redirecting;
|
struct ast_party_redirecting saved_redirecting;
|
||||||
|
|
||||||
|
@@ -4073,7 +4073,7 @@ static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, ch
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (c) {
|
} 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;
|
resultcode = 511;
|
||||||
|
|
||||||
ast_agi_send(agi->fd, chan, "%d %s\n", resultcode, ami_res);
|
ast_agi_send(agi->fd, chan, "%d %s\n", resultcode, ami_res);
|
||||||
@@ -4109,6 +4109,8 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
|
|||||||
const char *sighup_str;
|
const char *sighup_str;
|
||||||
const char *exit_on_hangup_str;
|
const char *exit_on_hangup_str;
|
||||||
int exit_on_hangup;
|
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);
|
ast_channel_lock(chan);
|
||||||
sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP");
|
sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP");
|
||||||
@@ -4143,7 +4145,7 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ms = -1;
|
ms = -1;
|
||||||
if (dead) {
|
if (dead || in_intercept) {
|
||||||
c = ast_waitfor_nandfds(&chan, 0, &agi->ctrl, 1, NULL, &outfd, &ms);
|
c = ast_waitfor_nandfds(&chan, 0, &agi->ctrl, 1, NULL, &outfd, &ms);
|
||||||
} else if (!ast_check_hangup(chan)) {
|
} else if (!ast_check_hangup(chan)) {
|
||||||
c = ast_waitfor_nandfds(&chan, 1, &agi->ctrl, 1, NULL, &outfd, &ms);
|
c = ast_waitfor_nandfds(&chan, 1, &agi->ctrl, 1, NULL, &outfd, &ms);
|
||||||
@@ -4221,10 +4223,10 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
|
|||||||
|
|
||||||
if (agidebug)
|
if (agidebug)
|
||||||
ast_verbose("<%s>AGI Rx << %s\n", ast_channel_name(chan), buf);
|
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) {
|
switch (cmd_status) {
|
||||||
case AGI_RESULT_FAILURE:
|
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. */
|
/* The failure was not because of a hangup. */
|
||||||
returnstatus = AGI_RESULT_FAILURE;
|
returnstatus = AGI_RESULT_FAILURE;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user