mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 12:36:58 +00:00
Add a new patch to handle interrupting the fgets() call when using FastAGI.
This version of the patch maintains the original behavior of the code when not using FastAGI. (closes issue #10553) Reported by: juggie Patches: res_agi_fgets-4.patch uploaded by juggie (license 24) res_agi_fgets_1.4svn.patch uploaded by juggie (license 24) Slight mods by me Tested by: juggie, festr git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@82929 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -31,6 +31,7 @@ typedef struct agi_state {
|
|||||||
int fd; /* FD for general output */
|
int fd; /* FD for general output */
|
||||||
int audio; /* FD for audio output */
|
int audio; /* FD for audio output */
|
||||||
int ctrl; /* FD for input control */
|
int ctrl; /* FD for input control */
|
||||||
|
unsigned int fast:1; /* flag for fast agi or not */
|
||||||
} AGI;
|
} AGI;
|
||||||
|
|
||||||
typedef struct agi_command {
|
typedef struct agi_command {
|
||||||
|
@@ -113,6 +113,7 @@ static int agidebug = 0;
|
|||||||
|
|
||||||
enum agi_result {
|
enum agi_result {
|
||||||
AGI_RESULT_SUCCESS,
|
AGI_RESULT_SUCCESS,
|
||||||
|
AGI_RESULT_SUCCESS_FAST,
|
||||||
AGI_RESULT_FAILURE,
|
AGI_RESULT_FAILURE,
|
||||||
AGI_RESULT_HANGUP
|
AGI_RESULT_HANGUP
|
||||||
};
|
};
|
||||||
@@ -232,7 +233,7 @@ static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds, in
|
|||||||
fds[0] = s;
|
fds[0] = s;
|
||||||
fds[1] = s;
|
fds[1] = s;
|
||||||
*opid = -1;
|
*opid = -1;
|
||||||
return AGI_RESULT_SUCCESS;
|
return AGI_RESULT_SUCCESS_FAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum agi_result launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
|
static enum agi_result launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
|
||||||
@@ -1833,6 +1834,7 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
|
|||||||
enum agi_result returnstatus = AGI_RESULT_SUCCESS;
|
enum agi_result returnstatus = AGI_RESULT_SUCCESS;
|
||||||
struct ast_frame *f;
|
struct ast_frame *f;
|
||||||
char buf[AGI_BUF_LEN];
|
char buf[AGI_BUF_LEN];
|
||||||
|
char *res = NULL;
|
||||||
FILE *readf;
|
FILE *readf;
|
||||||
/* how many times we'll retry if ast_waitfor_nandfs will return without either
|
/* how many times we'll retry if ast_waitfor_nandfs will return without either
|
||||||
channel or file descriptor in case select is interrupted by a system call (EINTR) */
|
channel or file descriptor in case select is interrupted by a system call (EINTR) */
|
||||||
@@ -1867,10 +1869,27 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
|
|||||||
ast_frfree(f);
|
ast_frfree(f);
|
||||||
}
|
}
|
||||||
} else if (outfd > -1) {
|
} else if (outfd > -1) {
|
||||||
|
size_t len = sizeof(buf);
|
||||||
|
size_t buflen = 0;
|
||||||
|
|
||||||
retry = AGI_NANDFS_RETRY;
|
retry = AGI_NANDFS_RETRY;
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
|
|
||||||
if (!fgets(buf, sizeof(buf), readf)) {
|
while (buflen < (len - 1)) {
|
||||||
|
res = fgets(buf + buflen, len, readf);
|
||||||
|
if (feof(readf))
|
||||||
|
break;
|
||||||
|
if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN)))
|
||||||
|
break;
|
||||||
|
if (res != NULL && !agi->fast)
|
||||||
|
break;
|
||||||
|
buflen = strlen(buf);
|
||||||
|
len -= buflen;
|
||||||
|
if (agidebug)
|
||||||
|
ast_verbose( "AGI Rx << temp buffer %s - errno %s\n", buf, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buf[0]) {
|
||||||
/* Program terminated */
|
/* Program terminated */
|
||||||
if (returnstatus)
|
if (returnstatus)
|
||||||
returnstatus = -1;
|
returnstatus = -1;
|
||||||
@@ -2027,14 +2046,15 @@ static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
|
res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
|
||||||
if (res == AGI_RESULT_SUCCESS) {
|
if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) {
|
||||||
int status = 0;
|
int status = 0;
|
||||||
agi.fd = fds[1];
|
agi.fd = fds[1];
|
||||||
agi.ctrl = fds[0];
|
agi.ctrl = fds[0];
|
||||||
agi.audio = efd;
|
agi.audio = efd;
|
||||||
|
agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0;
|
||||||
res = run_agi(chan, argv[0], &agi, pid, &status, dead);
|
res = run_agi(chan, argv[0], &agi, pid, &status, dead);
|
||||||
/* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */
|
/* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */
|
||||||
if (res == AGI_RESULT_SUCCESS && status)
|
if ((res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) && status)
|
||||||
res = AGI_RESULT_FAILURE;
|
res = AGI_RESULT_FAILURE;
|
||||||
if (fds[1] != fds[0])
|
if (fds[1] != fds[0])
|
||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
@@ -2046,6 +2066,7 @@ static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int
|
|||||||
|
|
||||||
switch (res) {
|
switch (res) {
|
||||||
case AGI_RESULT_SUCCESS:
|
case AGI_RESULT_SUCCESS:
|
||||||
|
case AGI_RESULT_SUCCESS_FAST:
|
||||||
pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS");
|
pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS");
|
||||||
break;
|
break;
|
||||||
case AGI_RESULT_FAILURE:
|
case AGI_RESULT_FAILURE:
|
||||||
|
Reference in New Issue
Block a user