From 9b6b0fcaf68d28d87aaa8f2d2dccb52dc23228e4 Mon Sep 17 00:00:00 2001 From: russell Date: Tue, 18 Sep 2007 22:42:27 +0000 Subject: 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 --- include/asterisk/agi.h | 1 + res/res_agi.c | 29 +++++++++++++++++++++++++---- 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: -- cgit v1.2.3