aboutsummaryrefslogtreecommitdiffstats
path: root/res/res_agi.c
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2006-05-25 16:44:22 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2006-05-25 16:44:22 +0000
commitd4f2c0ca2a3398536d487b66bd0f1d3bbb148d3f (patch)
tree92e702b86b97ee856983f1897f4d0530a7e45a02 /res/res_agi.c
parent1812f9ed10516cc130b1ec04c5bba7379d1cf8b1 (diff)
- add support for setting an AGISTATUS variable that indicates successful
execution, failure, or if the channel requested hangup. - only return -1 from the application if the application requested hangup. If there was just a failure in execution of the AGI, just set the status variable appropriately and move on in the dialplan. (issue #7121, original patch by Alessandro Polverini, updated patch by srt, committed patch is heavily modified to allow still returning -1 on hangup) git-svn-id: http://svn.digium.com/svn/asterisk/trunk@30272 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'res/res_agi.c')
-rw-r--r--res/res_agi.c75
1 files changed, 48 insertions, 27 deletions
diff --git a/res/res_agi.c b/res/res_agi.c
index 9d082ef6d..481edc5bc 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -86,11 +86,15 @@ static char *descrip =
"written in any language to control a telephony channel, play audio,\n"
"read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
"and stdout.\n"
-"Returns -1 on hangup (except for DeadAGI) or if application requested\n"
-" hangup, or 0 on non-hangup exit. \n"
-"Using 'EAGI' provides enhanced AGI, with incoming audio available out of band\n"
+" This channel will stop dialplan execution on hangup inside of this\n"
+"application, except when using DeadAGI. Otherwise, dialplan execution\n"
+"will continue normally.\n"
+" Using 'EAGI' provides enhanced AGI, with incoming audio available out of band\n"
"on file descriptor 3\n\n"
-"Use the CLI command 'show agi' to list available agi commands\n";
+" Use the CLI command 'show agi' to list available agi commands\n"
+" This application sets the following channel variable upon completion:\n"
+" AGISTATUS The status of the attempt to the run the AGI script\n"
+" text string, one of SUCCESS | FAILED | HANGUP\n";
static int agidebug = 0;
@@ -103,6 +107,12 @@ struct module_symbols *me;
#define AGI_PORT 4573
+enum agi_result {
+ AGI_RESULT_SUCCESS,
+ AGI_RESULT_FAILURE,
+ AGI_RESULT_HANGUP
+};
+
static void agi_debug_cli(int fd, char *fmt, ...)
{
char *stuff;
@@ -124,7 +134,7 @@ static void agi_debug_cli(int fd, char *fmt, ...)
/* launch_netscript: The fastagi handler.
FastAGI defaults to port 4573 */
-static int launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int *opid)
+static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int *opid)
{
int s;
int flags;
@@ -181,7 +191,7 @@ static int launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) && (errno != EINPROGRESS)) {
ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno));
close(s);
- return -1;
+ return AGI_RESULT_FAILURE;
}
pfds[0].fd = s;
@@ -190,7 +200,7 @@ static int launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int
if (errno != EINTR) {
ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
close(s);
- return -1;
+ return AGI_RESULT_FAILURE;
}
}
/* XXX in theory should check for partial writes... */
@@ -198,7 +208,7 @@ static int launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int
if (errno != EINTR) {
ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
close(s);
- return -1;
+ return AGI_RESULT_FAILURE;
}
}
@@ -211,10 +221,10 @@ static int launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int
fds[0] = s;
fds[1] = s;
*opid = -1;
- return 0;
+ return AGI_RESULT_SUCCESS;
}
-static int 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)
{
char tmp[256];
int pid;
@@ -234,13 +244,13 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
}
if (pipe(toast)) {
ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
- return -1;
+ return AGI_RESULT_FAILURE;
}
if (pipe(fromast)) {
ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
close(toast[0]);
close(toast[1]);
- return -1;
+ return AGI_RESULT_FAILURE;
}
if (efd) {
if (pipe(audio)) {
@@ -249,7 +259,7 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
close(fromast[1]);
close(toast[0]);
close(toast[1]);
- return -1;
+ return AGI_RESULT_FAILURE;
}
res = fcntl(audio[1], F_GETFL);
if (res > -1)
@@ -262,13 +272,13 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
close(toast[1]);
close(audio[0]);
close(audio[1]);
- return -1;
+ return AGI_RESULT_FAILURE;
}
}
pid = fork();
if (pid < 0) {
ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
- return -1;
+ return AGI_RESULT_FAILURE;
}
if (!pid) {
/* Pass paths to AGI via environmental variables */
@@ -324,13 +334,11 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
close(toast[1]);
close(fromast[0]);
- if (efd) {
- /* [PHM 12/18/03] */
+ if (efd)
close(audio[0]);
- }
*opid = pid;
- return 0;
+ return AGI_RESULT_SUCCESS;
}
@@ -1773,12 +1781,12 @@ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf)
return 0;
}
#define RETRY 3
-static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int dead)
+static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int dead)
{
struct ast_channel *c;
int outfd;
int ms;
- int returnstatus = 0;
+ enum agi_result returnstatus = AGI_RESULT_SUCCESS;
struct ast_frame *f;
char buf[2048];
FILE *readf;
@@ -1791,7 +1799,7 @@ static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, i
if (pid > -1)
kill(pid, SIGHUP);
close(agi->ctrl);
- return -1;
+ return AGI_RESULT_FAILURE;
}
setlinebuf(readf);
setup_env(chan, request, agi->fd, (agi->audio > -1));
@@ -1804,7 +1812,7 @@ static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, i
f = ast_read(c);
if (!f) {
ast_log(LOG_DEBUG, "%s hungup\n", chan->name);
- returnstatus = -1;
+ returnstatus = AGI_RESULT_HANGUP;
break;
} else {
/* If it's voice, write it to the audio pipe */
@@ -1839,7 +1847,7 @@ static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, i
} else {
if (--retry <= 0) {
ast_log(LOG_WARNING, "No channel, no fd?\n");
- returnstatus = -1;
+ returnstatus = AGI_RESULT_FAILURE;
break;
}
}
@@ -1933,7 +1941,7 @@ static int handle_dumpagihtml(int fd, int argc, char *argv[])
static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int dead)
{
- int res=0;
+ enum agi_result res;
struct localuser *u;
char *argv[MAX_ARGS];
char buf[2048]="";
@@ -1967,7 +1975,7 @@ 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) {
+ if (res == AGI_RESULT_SUCCESS) {
agi.fd = fds[1];
agi.ctrl = fds[0];
agi.audio = efd;
@@ -1977,7 +1985,20 @@ static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int
close(efd);
}
ast_localuser_remove(me, u);
- return res;
+
+ switch (res) {
+ case AGI_RESULT_SUCCESS:
+ pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS");
+ break;
+ case AGI_RESULT_FAILURE:
+ pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE");
+ break;
+ case AGI_RESULT_HANGUP:
+ pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP");
+ return -1;
+ }
+
+ return 0;
}
static int agi_exec(struct ast_channel *chan, void *data)