75cef85405bb217cf7c6a49982b9bc1c5a62ed82
[asterisk/asterisk.git] / contrib / scripts / managerproxy.pl
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2 <!-- saved from url=(0027)http://homey/simpleproxy.pl -->
3 <HTML><HEAD>
4 <META http-equiv=Content-Type content="text/html; charset=utf-8">
5 <META content="MSHTML 6.00.2900.2180" name=GENERATOR></HEAD>
6 <BODY><PRE>#!/usr/bin/perl -w 
7 #
8 #  Simple Asterisk Manager Proxy, Version 1.01
9 #  2004-09-26
10 #  Copyright (c) 2004 David C. Troy &lt;dave@popvox.com&gt;
11 #
12 #  This code is based on Flash Operator Panel 'op_server.pl'
13 #  by Nicol᳠Gudi񯬠Copyright (C) 2004.
14 #
15 #  David C. Troy &lt;dave@popvox.com&gt;
16 #  Nicol᳠Gudi񯠼nicolas@house.com.ar&gt;
17 #
18 #  This program is free software, distributed under the terms of
19 #  the GNU General Public License.
20 #
21 #############################
22
23 #############################
24 # Perl Prerequisites
25 #############################
26 use strict;
27 use IO::Socket;
28 use IO::Select;
29 use POSIX qw(setsid);
30
31 #############################
32 # User Configurable Options
33 #############################
34 my $manager_host = '127.0.0.1';
35 my $listen_port = 1234;
36 my $manager_port = 5038;
37 my $manager_user = 'your_username';
38 my $manager_secret = 'your_secret';
39
40 #############################
41 # Declarations
42 #############################
43 my %proxy_clients;
44 my $O;
45 my $p;
46 my @S;
47 my %blocks;
48 my $debug = 0;
49
50 $SIG{PIPE} = 'IGNORE';
51 $SIG{INT}  = 'close_all';
52 $SIG{USR1} = 'list_clients';
53
54 if (defined($ARGV[0]))
55 {
56     if ($ARGV[0] eq "-d")
57     {
58         defined(my $pid = fork) or die "Can't Fork: $!";
59         exit if $pid;
60         setsid or die "Can't start a new session: $!";
61         open MYPIDFILE, "&gt;/var/run/op_panel.pid";
62         print MYPIDFILE $$;
63         close MYPIDFILE;
64     }
65 } else {
66    $debug = 1;
67 }
68
69
70 # Connect to manager
71 $p =
72   new IO::Socket::INET-&gt;new(
73                             PeerAddr =&gt; $manager_host,
74                             PeerPort =&gt; $manager_port,
75                             Proto    =&gt; "tcp",
76                             Type     =&gt; SOCK_STREAM
77                            )
78   or die "\nCould not connect to Asterisk Manager Port\n";
79
80 $p-&gt;autoflush(1);
81
82 # Login to Manager
83 send_command_to_manager( "Action: Login\r\nUsername: $manager_user\r\nSecret: $manager_secret\r\n\r\n" );
84
85 # Start up listener for new connections
86 my $m =
87   new IO::Socket::INET(Listen =&gt; 1, LocalPort =&gt; $listen_port, ReuseAddr =&gt; 1)
88   or die "\nCan't listen to port $listen_port\n";
89 $O = new IO::Select();
90 $O-&gt;add($m);
91 $O-&gt;add($p);
92 $/ = "\0";
93
94 sub manager_reconnect()
95 {
96     my $attempt        = 1;
97     my $total_attempts = 60;
98
99     do
100     {
101         log_debug("** Attempt reconnection to manager port # $attempt", 16);
102         $p =
103           new IO::Socket::INET-&gt;new(
104                                     PeerAddr =&gt; $manager_host,
105                                     PeerPort =&gt; $manager_port,
106                                     Proto    =&gt; "tcp",
107                                     Type     =&gt; SOCK_STREAM
108                                    );
109         $attempt++;
110         if ($attempt &gt; $total_attempts)
111         {
112             die("!! Could not reconnect to Asterisk Manager port");
113         }
114         sleep(10);    # wait 10 seconds before trying to reconnect
115     } until $p;
116     $O-&gt;add($p);
117     send_command_to_manager(
118         "Action: Login\r\nUsername: $manager_user\r\nSecret: $manager_secret\r\n\r\n"
119     );
120 }
121
122 # Loop, continuously processing new connections, input from those connections, and input from Manager conn
123 while (1)
124 {
125     while (@S = $O-&gt;can_read)
126     {
127         foreach (@S)
128         {
129             if ($_ == $m)
130             {
131                 log_debug("** New client connection", 16);
132                 my $C = $m-&gt;accept;
133                 $proxy_clients{$C} = \$C;                
134                 print "New Connection: $C\n" if $debug;
135                 $O-&gt;add($C);
136             } else {
137                 # It's not a new client connection
138                 my $i;
139                 my $R = sysread($_, $i, 2);    # 2048; interleave every two bytes?
140                 if (defined($R) &amp;&amp; $R == 0)
141                 {
142                     # Confirm it's really dead by trying to write to it?
143                     my $T = syswrite($_, ' ', 2);    # 2048
144                     if (!defined($T))
145                     {
146                         # connection went away...
147                         $O-&gt;remove($_);
148                         $_-&gt;close;
149
150                         # If we lost the socket for the Asterisk Mgr, then reconnect
151                         if ($_ == $p)
152                         {
153                             log_debug(
154                                      "** Asterisk Manager connection lost!!!!!",
155                                      16);
156                             manager_reconnect();
157                         } else {
158                             # Remove handle from proxy_clients hash
159                             print "Closed Connection: $_\n" if $debug;
160                             delete $proxy_clients{$_};
161                         }
162                     }
163                 }
164                 else  # Socket is active and we are ready to read something from it
165                 {
166                     $blocks{$_} .= $i;
167                     next if ($blocks{$_} !~ /\r\n\r\n$/);
168                     # do a 'next' unless we have completed a block; we are not ready to continue
169
170                     # Process the completed block
171                     # If block is from asterisk, send to clients
172                     if ($_ == $p) {
173                        # block is from asterisk, send to clients
174                        print "asterisk: $_\n$blocks{$_}" if $debug;
175                        my $cnt = 0;
176                        foreach my $client (values %proxy_clients) {
177                           print "writing to $$client...\n" if $debug;
178                           syswrite($$client, $blocks{$_});
179                           $cnt++;
180                        }
181                        print "sent block to $cnt clients\n" if $debug;
182                     } else {
183                        # Blocks are from clients, send to asterisk
184                        syswrite($p, $blocks{$_});
185                        print "client: $_\n$blocks{$_}\n" if $debug;
186                     }
187                     delete $blocks{$_};
188
189                 } # end if read succeeded
190             } # end if new client connection
191         }    # end foreach @S -&gt; can read
192     }    # while can read
193 }    # endless loop
194
195 sub close_all
196 {
197     log_debug("Exiting...", 0);
198
199     foreach my $hd ($O-&gt;handles)
200     {
201         $O-&gt;remove($hd);
202         close($hd);
203     }
204
205     exit(0);
206 }
207
208 sub send_command_to_manager
209 {
210     my $comando = shift;
211     if (defined $p)
212     {
213         my @lineas = split("\r\n", $comando);
214         foreach my $linea (@lineas)
215         {
216             syswrite($p, "$linea\r\n");
217             log_debug("-&gt; $linea", 2);
218         }
219         log_debug(" ", 2);
220         syswrite($p, "\r\n");
221     }
222 }
223
224 sub log_debug
225 {
226     my $texto = shift;
227     $texto =~ s/\0//g;
228     print "$texto\n" if $debug;
229 }
230
231 sub list_clients()
232 {
233    my $cnt = 0;
234    foreach my $client (values %proxy_clients) {
235       print "client: $$client\n";
236       $cnt++;
237    }
238    print "$cnt clients.\n\n";
239 }
240
241
242 </PRE></BODY></HTML>