mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 12:16:00 +00:00
Merged revisions 313579 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.6.2 ................ r313579 | rmudgett | 2011-04-13 11:29:49 -0500 (Wed, 13 Apr 2011) | 48 lines Merged revisions 313545 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r313545 | rmudgett | 2011-04-13 11:21:24 -0500 (Wed, 13 Apr 2011) | 41 lines Asterisk does not hangup a channel after endpoint hangs up. If the call that the dialplan started an AGI script for is hungup while the AGI script is in the middle of a command then the AGI script is not notified of the hangup. There are many AGI Exec commands that this can happen with. The reported applications have been: Background, Wait, Read, and Dial. Also the AGI Get Data command. * Don't wait on the Asterisk channel after it has hung up. The channel is likely to never need servicing again. * Restored the AGI script's ability to return the AGI_RESULT_HANGUP value in run_agi(). It previously only could return AGI_RESULT_SUCCESS or AGI_RESULT_FAILURE after the DeadAGI and AGI applications were merged. (closes issue #17954) Reported by: mn3250 Patches: issue17954_v1.8.patch uploaded by rmudgett (license 664) issue17954_v1.6.2.patch uploaded by rmudgett (license 664) issue17954_v1.4.patch uploaded by rmudgett (license 664) Tested by: rmudgett JIRA SWP-2171 (closes issue #18492) Reported by: devmod Tested by: rmudgett JIRA SWP-2761 (closes issue #18935) Reported by: nvitaly Tested by: astmiv, rmudgett JIRA SWP-3216 (closes issue #17393) Reported by: siby Tested by: rmudgett JIRA SWP-2727 Review: https://reviewboard.asterisk.org/r/1165/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@313588 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -3679,23 +3679,27 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
|
||||
} else {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
#ifdef AST_DEVMODE
|
||||
/*
|
||||
* The ast_waitfor() code records which of the channel's file descriptors reported that
|
||||
* data is available. In theory, ast_read() should only be called after ast_waitfor()
|
||||
* reports that a channel has data available for reading. However, there still may be
|
||||
* some edge cases throughout the code where ast_read() is called improperly. This can
|
||||
* potentially cause problems, so if this is a developer build, make a lot of noise if
|
||||
* this happens so that it can be addressed.
|
||||
*/
|
||||
if (chan->fdno == -1) {
|
||||
ast_log(LOG_ERROR,
|
||||
"ast_read() on chan '%s' called with no recorded file descriptor.\n",
|
||||
chan->name);
|
||||
}
|
||||
/*
|
||||
* The ast_waitfor() code records which of the channel's file
|
||||
* descriptors reported that data is available. In theory,
|
||||
* ast_read() should only be called after ast_waitfor() reports
|
||||
* that a channel has data available for reading. However,
|
||||
* there still may be some edge cases throughout the code where
|
||||
* ast_read() is called improperly. This can potentially cause
|
||||
* problems, so if this is a developer build, make a lot of
|
||||
* noise if this happens so that it can be addressed.
|
||||
*
|
||||
* One of the potential problems is blocking on a dead channel.
|
||||
*/
|
||||
if (chan->fdno == -1) {
|
||||
ast_log(LOG_ERROR,
|
||||
"ast_read() on chan '%s' called with no recorded file descriptor.\n",
|
||||
chan->name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
prestate = chan->_state;
|
||||
|
||||
|
@@ -1178,7 +1178,7 @@ static int action_add_agi_cmd(struct mansession *s, const struct message *m)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead);
|
||||
static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead);
|
||||
static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[]);
|
||||
static enum agi_result launch_asyncagi(struct ast_channel *chan, char *argv[], int *efd)
|
||||
{
|
||||
@@ -2180,12 +2180,14 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const
|
||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
|
||||
return -1;
|
||||
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
sildet = ast_dsp_new();
|
||||
if (!sildet) {
|
||||
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
||||
return -1;
|
||||
ast_agi_send(agi->fd, chan, "200 result=-1\n");
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
|
||||
}
|
||||
@@ -3246,7 +3248,7 @@ normal:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
|
||||
static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
|
||||
{
|
||||
const char *argv[MAX_ARGS];
|
||||
int argc = MAX_ARGS, res;
|
||||
@@ -3297,9 +3299,10 @@ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int
|
||||
}
|
||||
break;
|
||||
case RESULT_FAILURE:
|
||||
/* They've already given the failure. We've been hung up on so handle this
|
||||
appropriately */
|
||||
return -1;
|
||||
/* The RESULT_FAILURE code is usually because the channel hungup. */
|
||||
return AGI_RESULT_FAILURE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if ((c = find_command(argv, 0))) {
|
||||
ast_agi_send(agi->fd, chan, "511 Command Not Permitted on a dead channel\n");
|
||||
@@ -3320,7 +3323,7 @@ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int
|
||||
"ResultCode: 510\r\n"
|
||||
"Result: Invalid or unknown command\r\n", chan->name, command_id, ami_cmd);
|
||||
}
|
||||
return 0;
|
||||
return AGI_RESULT_SUCCESS;
|
||||
}
|
||||
static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[])
|
||||
{
|
||||
@@ -3365,16 +3368,27 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
|
||||
}
|
||||
}
|
||||
ms = -1;
|
||||
c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
|
||||
if (dead) {
|
||||
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);
|
||||
} else {
|
||||
/*
|
||||
* Read the channel control queue until it is dry so we can
|
||||
* switch to dead mode.
|
||||
*/
|
||||
c = chan;
|
||||
}
|
||||
if (c) {
|
||||
retry = AGI_NANDFS_RETRY;
|
||||
/* Idle the channel until we get a command */
|
||||
f = ast_read(c);
|
||||
if (!f) {
|
||||
ast_debug(1, "%s hungup\n", chan->name);
|
||||
returnstatus = AGI_RESULT_HANGUP;
|
||||
needhup = 1;
|
||||
continue;
|
||||
if (!returnstatus) {
|
||||
returnstatus = AGI_RESULT_HANGUP;
|
||||
}
|
||||
} else {
|
||||
/* If it's voice, write it to the audio pipe */
|
||||
if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
|
||||
@@ -3387,6 +3401,7 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
|
||||
} else if (outfd > -1) {
|
||||
size_t len = sizeof(buf);
|
||||
size_t buflen = 0;
|
||||
enum agi_result cmd_status;
|
||||
|
||||
retry = AGI_NANDFS_RETRY;
|
||||
buf[0] = '\0';
|
||||
@@ -3409,9 +3424,6 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
|
||||
|
||||
if (!buf[0]) {
|
||||
/* Program terminated */
|
||||
if (returnstatus) {
|
||||
returnstatus = -1;
|
||||
}
|
||||
ast_verb(3, "<%s>AGI Script %s completed, returning %d\n", chan->name, request, returnstatus);
|
||||
if (pid > 0)
|
||||
waitpid(pid, status, 0);
|
||||
@@ -3431,11 +3443,16 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
|
||||
buf[strlen(buf) - 1] = 0;
|
||||
if (agidebug)
|
||||
ast_verbose("<%s>AGI Rx << %s\n", chan->name, buf);
|
||||
returnstatus |= agi_handle_command(chan, agi, buf, dead);
|
||||
/* If the handle_command returns -1, we need to stop */
|
||||
if (returnstatus < 0) {
|
||||
needhup = 1;
|
||||
continue;
|
||||
cmd_status = agi_handle_command(chan, agi, buf, dead);
|
||||
switch (cmd_status) {
|
||||
case AGI_RESULT_FAILURE:
|
||||
if (dead || !ast_check_hangup(chan)) {
|
||||
/* The failure was not because of a hangup. */
|
||||
returnstatus = AGI_RESULT_FAILURE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (--retry <= 0) {
|
||||
|
Reference in New Issue
Block a user