asterisk/contrib/scripts/managerproxy.pl

243 lines
7.1 KiB
Perl
Raw Normal View History

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0027)http://homey/simpleproxy.pl -->
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=utf-8">
<META content="MSHTML 6.00.2900.2180" name=GENERATOR></HEAD>
<BODY><PRE>#!/usr/bin/perl -w
#
# Simple Asterisk Manager Proxy, Version 1.01
# 2004-09-26
# Copyright (c) 2004 David C. Troy &lt;dave@popvox.com&gt;
#
# This code is based on Flash Operator Panel 'op_server.pl'
# by Nicol᳠Gudi񯬠Copyright (C) 2004.
#
# David C. Troy &lt;dave@popvox.com&gt;
# Nicol᳠Gudi񯠼nicolas@house.com.ar&gt;
#
# This program is free software, distributed under the terms of
# the GNU General Public License.
#
#############################
#############################
# Perl Prerequisites
#############################
use strict;
use IO::Socket;
use IO::Select;
use POSIX qw(setsid);
#############################
# User Configurable Options
#############################
my $manager_host = '127.0.0.1';
my $listen_port = 1234;
my $manager_port = 5038;
my $manager_user = 'your_username';
my $manager_secret = 'your_secret';
#############################
# Declarations
#############################
my %proxy_clients;
my $O;
my $p;
my @S;
my %blocks;
my $debug = 0;
$SIG{PIPE} = 'IGNORE';
$SIG{INT} = 'close_all';
$SIG{USR1} = 'list_clients';
if (defined($ARGV[0]))
{
if ($ARGV[0] eq "-d")
{
defined(my $pid = fork) or die "Can't Fork: $!";
exit if $pid;
setsid or die "Can't start a new session: $!";
open MYPIDFILE, "&gt;/var/run/op_panel.pid";
print MYPIDFILE $$;
close MYPIDFILE;
}
} else {
$debug = 1;
}
# Connect to manager
$p =
new IO::Socket::INET-&gt;new(
PeerAddr =&gt; $manager_host,
PeerPort =&gt; $manager_port,
Proto =&gt; "tcp",
Type =&gt; SOCK_STREAM
)
or die "\nCould not connect to Asterisk Manager Port\n";
$p-&gt;autoflush(1);
# Login to Manager
send_command_to_manager( "Action: Login\r\nUsername: $manager_user\r\nSecret: $manager_secret\r\n\r\n" );
# Start up listener for new connections
my $m =
new IO::Socket::INET(Listen =&gt; 1, LocalPort =&gt; $listen_port, ReuseAddr =&gt; 1)
or die "\nCan't listen to port $listen_port\n";
$O = new IO::Select();
$O-&gt;add($m);
$O-&gt;add($p);
$/ = "\0";
sub manager_reconnect()
{
my $attempt = 1;
my $total_attempts = 60;
do
{
log_debug("** Attempt reconnection to manager port # $attempt", 16);
$p =
new IO::Socket::INET-&gt;new(
PeerAddr =&gt; $manager_host,
PeerPort =&gt; $manager_port,
Proto =&gt; "tcp",
Type =&gt; SOCK_STREAM
);
$attempt++;
if ($attempt &gt; $total_attempts)
{
die("!! Could not reconnect to Asterisk Manager port");
}
sleep(10); # wait 10 seconds before trying to reconnect
} until $p;
$O-&gt;add($p);
send_command_to_manager(
"Action: Login\r\nUsername: $manager_user\r\nSecret: $manager_secret\r\n\r\n"
);
}
# Loop, continuously processing new connections, input from those connections, and input from Manager conn
while (1)
{
while (@S = $O-&gt;can_read)
{
foreach (@S)
{
if ($_ == $m)
{
log_debug("** New client connection", 16);
my $C = $m-&gt;accept;
$proxy_clients{$C} = \$C;
print "New Connection: $C\n" if $debug;
$O-&gt;add($C);
} else {
# It's not a new client connection
my $i;
my $R = sysread($_, $i, 2); # 2048; interleave every two bytes?
if (defined($R) &amp;&amp; $R == 0)
{
# Confirm it's really dead by trying to write to it?
my $T = syswrite($_, ' ', 2); # 2048
if (!defined($T))
{
# connection went away...
$O-&gt;remove($_);
$_-&gt;close;
# If we lost the socket for the Asterisk Mgr, then reconnect
if ($_ == $p)
{
log_debug(
"** Asterisk Manager connection lost!!!!!",
16);
manager_reconnect();
} else {
# Remove handle from proxy_clients hash
print "Closed Connection: $_\n" if $debug;
delete $proxy_clients{$_};
}
}
}
else # Socket is active and we are ready to read something from it
{
$blocks{$_} .= $i;
next if ($blocks{$_} !~ /\r\n\r\n$/);
# do a 'next' unless we have completed a block; we are not ready to continue
# Process the completed block
# If block is from asterisk, send to clients
if ($_ == $p) {
# block is from asterisk, send to clients
print "asterisk: $_\n$blocks{$_}" if $debug;
my $cnt = 0;
foreach my $client (values %proxy_clients) {
print "writing to $$client...\n" if $debug;
syswrite($$client, $blocks{$_});
$cnt++;
}
print "sent block to $cnt clients\n" if $debug;
} else {
# Blocks are from clients, send to asterisk
syswrite($p, $blocks{$_});
print "client: $_\n$blocks{$_}\n" if $debug;
}
delete $blocks{$_};
} # end if read succeeded
} # end if new client connection
} # end foreach @S -&gt; can read
} # while can read
} # endless loop
sub close_all
{
log_debug("Exiting...", 0);
foreach my $hd ($O-&gt;handles)
{
$O-&gt;remove($hd);
close($hd);
}
exit(0);
}
sub send_command_to_manager
{
my $comando = shift;
if (defined $p)
{
my @lineas = split("\r\n", $comando);
foreach my $linea (@lineas)
{
syswrite($p, "$linea\r\n");
log_debug("-&gt; $linea", 2);
}
log_debug(" ", 2);
syswrite($p, "\r\n");
}
}
sub log_debug
{
my $texto = shift;
$texto =~ s/\0//g;
print "$texto\n" if $debug;
}
sub list_clients()
{
my $cnt = 0;
foreach my $client (values %proxy_clients) {
print "client: $$client\n";
$cnt++;
}
print "$cnt clients.\n\n";
}
</PRE></BODY></HTML>