Package: asterisk
Version: 1:1.2.7.1.dfsg-1.sarge.1642
Severity: wishlist
Tags: patch

Please consider applying the attached patch to the next packaged
release: I have backported it to the stable branch from the just accepted
mainstream one.
You can read the details here:
http://bugs.digium.com/view.php?id=7121

The patch resolves a grave shortcoming of the fastagi extension because
in the stable release it can't recover from a situation where the agi
server is down or unreachable.
This is a very bad problem for people that works on asterisk and needs
to extend it via fastagi.

Thanks,
Alex

-- System Information:
Debian Release: 3.1
  APT prefers testing
  APT policy: (90, 'testing')
Architecture: i386 (i686)
Kernel: Linux 2.6.15-1-k7-smp
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)

Versions of packages asterisk depends on:
ii  adduser      3.63                        Add and remove users and groups
ii  asterisk-cla 1:1.2.7.1.dfsg-1.sarge.1642 Open Source Private Branch Exchang

-- no debconf information
Index: res/res_agi.c
===================================================================
--- res/res_agi.c       (revision 30544)
+++ res/res_agi.c       (working copy)
@@ -88,11 +88,15 @@
 "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;
 
@@ -108,6 +112,12 @@
 
 #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;
@@ -129,7 +139,7 @@
 
 /* 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;
@@ -187,7 +197,7 @@
        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;
@@ -196,7 +206,7 @@
                if (errno != EINTR) {
                        ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", 
agiurl, strerror(errno));
                        close(s);
-                       return -1;
+                       return AGI_RESULT_FAILURE;
                }
        }
 
@@ -204,7 +214,7 @@
                if (errno != EINTR) {
                        ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", 
agiurl, strerror(errno));
                        close(s);
-                       return -1;
+                       return AGI_RESULT_FAILURE;
                }
        }
 
@@ -217,10 +227,10 @@
        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;
@@ -240,13 +250,13 @@
        }
        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)) {
@@ -255,7 +265,7 @@
                        close(fromast[1]);
                        close(toast[0]);
                        close(toast[1]);
-                       return -1;
+                       return AGI_RESULT_FAILURE;
                }
                res = fcntl(audio[1], F_GETFL);
                if (res > -1) 
@@ -268,13 +278,13 @@
                        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) {
                /* Redirect stdin and out, provide enhanced audio channel if 
desired */
@@ -316,13 +326,11 @@
        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;
                
 }
 
@@ -1848,12 +1856,12 @@
        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;
@@ -1866,7 +1874,7 @@
                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));
@@ -1879,7 +1887,7 @@
                        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 */
@@ -1914,7 +1922,7 @@
                } else {
                        if (--retry <= 0) {
                                ast_log(LOG_WARNING, "No channel, no fd?\n");
-                               returnstatus = -1;
+                               returnstatus = AGI_RESULT_FAILURE;
                                break;
                        }
                }
@@ -2009,7 +2017,7 @@
 
 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]="";
@@ -2043,7 +2051,7 @@
        }
 #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;
@@ -2053,7 +2061,20 @@
                        close(efd);
        }
        LOCAL_USER_REMOVE(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)

Reply via email to