mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 12:16:00 +00:00
Implement Fast AGI (agi://) over TCP socket (Astricon talk idea)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3820 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
94
agi/fastagi-test
Executable file
94
agi/fastagi-test
Executable file
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/perl
|
||||
use strict;
|
||||
use Socket;
|
||||
use Carp;
|
||||
use IO::Handle;
|
||||
|
||||
my $port = 4573;
|
||||
|
||||
$|=1;
|
||||
|
||||
# Setup some variables
|
||||
my %AGI; my $tests = 0; my $fail = 0; my $pass = 0;
|
||||
|
||||
sub checkresult {
|
||||
my ($res) = @_;
|
||||
my $retval;
|
||||
$tests++;
|
||||
chomp $res;
|
||||
if ($res =~ /^200/) {
|
||||
$res =~ /result=(-?\d+)/;
|
||||
if (!length($1)) {
|
||||
print STDERR "FAIL ($res)\n";
|
||||
$fail++;
|
||||
} else {
|
||||
print STDERR "PASS ($1)\n";
|
||||
$pass++;
|
||||
}
|
||||
} else {
|
||||
print STDERR "FAIL (unexpected result '$res')\n";
|
||||
$fail++;
|
||||
}
|
||||
}
|
||||
|
||||
socket(SERVER, PF_INET, SOCK_STREAM, 0);
|
||||
setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, pack("l", 1));
|
||||
bind(SERVER, sockaddr_in($port, INADDR_ANY)) || die("can't bind\n");
|
||||
listen(SERVER, SOMAXCONN);
|
||||
|
||||
for(;;) {
|
||||
my $raddr = accept(CLIENT, SERVER);
|
||||
my ($s, $p) = sockaddr_in($raddr);
|
||||
CLIENT->autoflush(1);
|
||||
while(<CLIENT>) {
|
||||
chomp;
|
||||
last unless length($_);
|
||||
if (/^agi_(\w+)\:\s+(.*)$/) {
|
||||
$AGI{$1} = $2;
|
||||
}
|
||||
}
|
||||
print STDERR "AGI Environment Dump from $s:$p --\n";
|
||||
foreach my $i (sort keys %AGI) {
|
||||
print STDERR " -- $i = $AGI{$i}\n";
|
||||
}
|
||||
|
||||
print STDERR "1. Testing 'sendfile'...";
|
||||
print CLIENT "STREAM FILE beep \"\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "2. Testing 'sendtext'...";
|
||||
print CLIENT "SEND TEXT \"hello world\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "3. Testing 'sendimage'...";
|
||||
print CLIENT "SEND IMAGE asterisk-image\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "4. Testing 'saynumber'...";
|
||||
print CLIENT "SAY NUMBER 192837465 \"\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "5. Testing 'waitdtmf'...";
|
||||
print CLIENT "WAIT FOR DIGIT 1000\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "6. Testing 'record'...";
|
||||
print CLIENT "RECORD FILE testagi gsm 1234 3000\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "6a. Testing 'record' playback...";
|
||||
print CLIENT "STREAM FILE testagi \"\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
close(CLIENT);
|
||||
print STDERR "================== Complete ======================\n";
|
||||
print STDERR "$tests tests completed, $pass passed, $fail failed\n";
|
||||
print STDERR "==================================================\n";
|
||||
}
|
||||
|
@@ -3,9 +3,9 @@
|
||||
*
|
||||
* Asterisk Gateway Interface
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999-2004, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/poll.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
@@ -79,6 +80,90 @@ LOCAL_USER_DECL;
|
||||
|
||||
#define TONE_BLOCK_SIZE 200
|
||||
|
||||
/* Max time to connect to an AGI remote host */
|
||||
#define MAX_AGI_CONNECT 2000
|
||||
|
||||
#define AGI_PORT 4573
|
||||
|
||||
static int launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int *opid)
|
||||
{
|
||||
int s;
|
||||
int flags;
|
||||
struct pollfd pfds[1];
|
||||
char *host;
|
||||
char *c; int port = AGI_PORT;
|
||||
char *script;
|
||||
struct sockaddr_in sin;
|
||||
struct hostent *hp;
|
||||
struct ast_hostent ahp;
|
||||
ast_log(LOG_DEBUG, "Blah\n");
|
||||
host = ast_strdupa(agiurl + 6);
|
||||
if (!host)
|
||||
return -1;
|
||||
/* Strip off any script name */
|
||||
if ((c = strchr(host, '/'))) {
|
||||
*c = '\0';
|
||||
c++;
|
||||
script = c;
|
||||
}
|
||||
if ((c = strchr(host, ':'))) {
|
||||
*c = '\0';
|
||||
c++;
|
||||
port = atoi(c + 1);
|
||||
}
|
||||
if (efd) {
|
||||
ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n");
|
||||
return -1;
|
||||
}
|
||||
hp = ast_gethostbyname(host, &ahp);
|
||||
if (!hp) {
|
||||
ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
|
||||
return -1;
|
||||
}
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
flags = fcntl(s, F_GETFL);
|
||||
if (flags < 0) {
|
||||
ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||
ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(port);
|
||||
memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
|
||||
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;
|
||||
}
|
||||
pfds[0].fd = s;
|
||||
pfds[0].events = POLLOUT;
|
||||
if (poll(pfds, 1, MAX_AGI_CONNECT) != 1) {
|
||||
ast_log(LOG_WARNING, "Connect to '%s' failed!\n", agiurl);
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
if (write(s, "agi_network: yes\n", strlen("agi_network: yes\n")) < 0) {
|
||||
ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
ast_log(LOG_DEBUG, "Wow, connected!\n");
|
||||
fds[0] = s;
|
||||
fds[1] = s;
|
||||
*opid = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
|
||||
{
|
||||
char tmp[256];
|
||||
@@ -88,6 +173,10 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
|
||||
int audio[2];
|
||||
int x;
|
||||
int res;
|
||||
|
||||
if (!strncasecmp(script, "agi://", 6))
|
||||
return launch_netscript(script, argv, fds, efd, opid);
|
||||
|
||||
if (script[0] != '/') {
|
||||
snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_AGI_DIR, script);
|
||||
script = tmp;
|
||||
@@ -1338,7 +1427,8 @@ static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, i
|
||||
|
||||
if (!(readf = fdopen(agi->ctrl, "r"))) {
|
||||
ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
|
||||
kill(pid, SIGHUP);
|
||||
if (pid > -1)
|
||||
kill(pid, SIGHUP);
|
||||
close(agi->ctrl);
|
||||
return -1;
|
||||
}
|
||||
|
Reference in New Issue
Block a user