aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-09-18 22:42:27 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-09-18 22:42:27 +0000
commit9b6b0fcaf68d28d87aaa8f2d2dccb52dc23228e4 (patch)
tree98951d3dbae55b1079e6f83f049775483596ce55
parent1e7a1dd3b1ca67fe3270f78f58354e6a85b7da7a (diff)
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: http://svn.digium.com/svn/asterisk/branches/1.4@82929 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--include/asterisk/agi.h1
-rw-r--r--res/res_agi.c29
2 files changed, 26 insertions, 4 deletions
diff --git a/include/asterisk/agi.h b/include/asterisk/agi.h
index 5a0edc83f..5797176fe 100644
--- a/include/asterisk/agi.h
+++ b/include/asterisk/agi.h
@@ -31,6 +31,7 @@ typedef struct agi_state {
int fd; /* FD for general output */
int audio; /* FD for audio output */
int ctrl; /* FD for input control */
+ unsigned int fast:1; /* flag for fast agi or not */
} AGI;
typedef struct agi_command {
diff --git a/res/res_agi.c b/res/res_agi.c
index 288b0bc7c..376089eff 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -113,6 +113,7 @@ static int agidebug = 0;
enum agi_result {
AGI_RESULT_SUCCESS,
+ AGI_RESULT_SUCCESS_FAST,
AGI_RESULT_FAILURE,
AGI_RESULT_HANGUP
};
@@ -232,7 +233,7 @@ static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds, in
fds[0] = s;
fds[1] = s;
*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)
@@ -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;
struct ast_frame *f;
char buf[AGI_BUF_LEN];
+ char *res = NULL;
FILE *readf;
/* 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) */
@@ -1867,10 +1869,27 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
ast_frfree(f);
}
} else if (outfd > -1) {
+ size_t len = sizeof(buf);
+ size_t buflen = 0;
+
retry = AGI_NANDFS_RETRY;
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 */
if (returnstatus)
returnstatus = -1;
@@ -2027,14 +2046,15 @@ static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int
}
#endif
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;
agi.fd = fds[1];
agi.ctrl = fds[0];
agi.audio = efd;
+ agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0;
res = run_agi(chan, argv[0], &agi, pid, &status, dead);
/* 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;
if (fds[1] != fds[0])
close(fds[1]);
@@ -2046,6 +2066,7 @@ static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int
switch (res) {
case AGI_RESULT_SUCCESS:
+ case AGI_RESULT_SUCCESS_FAST:
pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS");
break;
case AGI_RESULT_FAILURE: