diff options
author | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-01-19 00:28:49 +0000 |
---|---|---|
committer | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-01-19 00:28:49 +0000 |
commit | fb0c85edeb22827b7f7a242fb5266c1944b40c9e (patch) | |
tree | 1fa70043dacf63a29de615f9f6c82ad0f824f011 /res/res_agi.c | |
parent | 4c5831b3e5f9c280dafe6ec76c4f067d8ebcc713 (diff) |
Create iterative method for querying SRV results, and use that for finding AGI servers.
(closes issue #14775)
Reported by: _brent_
Patches:
20091215__issue14775.diff.txt uploaded by tilghman (license 14)
hagi-5.patch uploaded by brent (license 388)
Tested by: _brent_
Reviewboard: https://reviewboard.asterisk.org/r/378/
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@241188 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'res/res_agi.c')
-rw-r--r-- | res/res_agi.c | 106 |
1 files changed, 88 insertions, 18 deletions
diff --git a/res/res_agi.c b/res/res_agi.c index da4ebe8af..b055a23e6 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -60,6 +60,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/features.h" #include "asterisk/term.h" #include "asterisk/xmldoc.h" +#include "asterisk/srv.h" #define AST_API_MODULE #include "asterisk/agi.h" @@ -897,6 +898,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #define MAX_CMD_LEN 80 #define AGI_NANDFS_RETRY 3 #define AGI_BUF_LEN 2048 +#define SRV_PREFIX "_agi._tcp." static char *app = "AGI"; @@ -1339,32 +1341,28 @@ quit: /* launch_netscript: The fastagi handler. FastAGI defaults to port 4573 */ -static enum agi_result 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 s, flags, res, port = AGI_PORT; struct pollfd pfds[1]; - char *host, *c, *script = ""; + char *host, *c, *script; struct sockaddr_in addr_in; struct hostent *hp; struct ast_hostent ahp; - /* agiusl is "agi://host.domain[:port][/script/name]" */ + /* agiurl is "agi://host.domain[:port][/script/name]" */ host = ast_strdupa(agiurl + 6); /* Remove agi:// */ /* Strip off any script name */ - if ((c = strchr(host, '/'))) { - *c = '\0'; - c++; - script = c; + if ((script = strchr(host, '/'))) { + *script++ = '\0'; + } else { + script = ""; } + if ((c = strchr(host, ':'))) { - *c = '\0'; - c++; + *c++ = '\0'; port = atoi(c); } - if (efd) { - ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n"); - return -1; - } if (!(hp = ast_gethostbyname(host, &ahp))) { ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host); return -1; @@ -1423,20 +1421,92 @@ static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds, in ast_debug(4, "Wow, connected!\n"); fds[0] = s; fds[1] = s; - *opid = -1; return AGI_RESULT_SUCCESS_FAST; } +/*! + * \internal + * \brief The HA fastagi handler. + * \param agiurl The request URL as passed to Agi() in the dial plan + * \param argv The parameters after the URL passed to Agi() in the dial plan + * \param fds Input/output file descriptors + * + * Uses SRV lookups to try to connect to a list of FastAGI servers. The hostname in + * the URI is prefixed with _agi._tcp. prior to the DNS resolution. For + * example, if you specify the URI \a hagi://agi.example.com/foo.agi the DNS + * query would be for \a _agi._tcp.agi.example.com and you'll need to make sure + * this resolves. + * + * This function parses the URI, resolves the SRV service name, forms new URIs + * with the results of the DNS lookup, and then calls launch_netscript on the + * new URIs until one succeeds. + * + * \return the result of the AGI operation. + */ +static enum agi_result launch_ha_netscript(char *agiurl, char *argv[], int *fds) +{ + char *host, *script; + enum agi_result result = AGI_RESULT_FAILURE; + struct srv_context *context = NULL; + int srv_ret; + char service[256]; + char resolved_uri[1024]; + const char *srvhost; + unsigned short srvport; + + /* format of agiurl is "hagi://host.domain[:port][/script/name]" */ + if (!(host = ast_strdupa(agiurl + 7))) { /* Remove hagi:// */ + ast_log(LOG_WARNING, "An error occurred parsing the AGI URI: %s", agiurl); + return AGI_RESULT_FAILURE; + } + + /* Strip off any script name */ + if ((script = strchr(host, '/'))) { + *script++ = '\0'; + } else { + script = ""; + } + + if (strchr(host, ':')) { + ast_log(LOG_WARNING, "Specifying a port number disables SRV lookups: %s\n", agiurl); + return launch_netscript(agiurl + 1, argv, fds); /* +1 to strip off leading h from hagi:// */ + } + + snprintf(service, sizeof(service), "%s%s", SRV_PREFIX, host); + + while (!(srv_ret = ast_srv_lookup(&context, service, &srvhost, &srvport))) { + snprintf(resolved_uri, sizeof(resolved_uri), "agi://%s:%d/%s", srvhost, srvport, script); + result = launch_netscript(resolved_uri, argv, fds); + if (result == AGI_RESULT_FAILURE || result == AGI_RESULT_NOTFOUND) { + ast_log(LOG_WARNING, "AGI request failed for host '%s' (%s:%d)\n", host, srvhost, srvport); + } else { + break; + } + } + if (srv_ret < 0) { + ast_log(LOG_WARNING, "SRV lookup failed for %s\n", agiurl); + } else { + ast_srv_cleanup(&context); + } + + return result; +} + static enum agi_result launch_script(struct ast_channel *chan, char *script, char *argv[], int *fds, int *efd, int *opid) { char tmp[256]; int pid, toast[2], fromast[2], audio[2], res; struct stat st; - if (!strncasecmp(script, "agi://", 6)) - return launch_netscript(script, argv, fds, efd, opid); - if (!strncasecmp(script, "agi:async", sizeof("agi:async")-1)) + if (!strncasecmp(script, "agi://", 6)) { + return (efd == NULL) ? launch_netscript(script, argv, fds) : AGI_RESULT_FAILURE; + } + if (!strncasecmp(script, "hagi://", 7)) { + return (efd == NULL) ? launch_ha_netscript(script, argv, fds) : AGI_RESULT_FAILURE; + } + if (!strncasecmp(script, "agi:async", sizeof("agi:async") - 1)) { return launch_asyncagi(chan, argv, efd); + } if (script[0] != '/') { snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_AGI_DIR, script); @@ -3590,7 +3660,7 @@ static int agi_exec_full(struct ast_channel *chan, const char *data, int enhance { enum agi_result res; char *buf; - int fds[2], efd = -1, pid; + int fds[2], efd = -1, pid = -1; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(arg)[MAX_ARGS]; ); |