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