| 
									
										
										
										
											2017-12-22 09:23:22 -05:00
										 |  |  | #!/usr/bin/perl -w | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  | # | 
					
						
							|  |  |  | #  Simple Asterisk Manager Proxy, Version 1.01 | 
					
						
							|  |  |  | #  2004-09-26 | 
					
						
							| 
									
										
										
										
											2006-01-04 13:56:11 +00:00
										 |  |  | #  Copyright (c) 2004 David C. Troy <dave@popvox.com> | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  | # | 
					
						
							|  |  |  | #  This code is based on Flash Operator Panel 'op_server.pl' | 
					
						
							| 
									
										
										
										
											2017-12-21 10:51:02 -05:00
										 |  |  | #  by Nicolás Gudiño | 
					
						
							|  |  |  | #  Copyright (C) 2004. | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2006-01-04 13:56:11 +00:00
										 |  |  | #  David C. Troy <dave@popvox.com> | 
					
						
							| 
									
										
										
										
											2017-12-21 10:51:02 -05:00
										 |  |  | #  Nicolás Gudiño <nicolas@house.com.ar> | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  | # | 
					
						
							|  |  |  | #  This program is free software, distributed under the terms of | 
					
						
							|  |  |  | #  the GNU General Public License. | 
					
						
							|  |  |  | # | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  | #  Security consideration: This script will open your manager port | 
					
						
							|  |  |  | #  for unauthenticated logins. Be careful out there :-) | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  | ############################# | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ############################# | 
					
						
							|  |  |  | # Perl Prerequisites | 
					
						
							|  |  |  | ############################# | 
					
						
							|  |  |  | use strict; | 
					
						
							|  |  |  | use IO::Socket; | 
					
						
							|  |  |  | use IO::Select; | 
					
						
							|  |  |  | use POSIX qw(setsid); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ############################# | 
					
						
							|  |  |  | # User Configurable Options | 
					
						
							|  |  |  | ############################# | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  | # Configuration for logging in to your asterisk server | 
					
						
							|  |  |  | # Check you Asterisk config file "manager.conf" for details | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  | my $manager_host = '127.0.0.1'; | 
					
						
							|  |  |  | my $manager_port = 5038; | 
					
						
							|  |  |  | my $manager_user = 'your_username'; | 
					
						
							|  |  |  | my $manager_secret = 'your_secret'; | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  | # Port For this proxy | 
					
						
							|  |  |  | my $listen_port = 1234; | 
					
						
							|  |  |  | my $manager_pid = "/var/run/asterisk_managerproxy.pid"; | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ############################# | 
					
						
							|  |  |  | # 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: $!"; | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |         open MYPIDFILE, ">$manager_pid"; | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |         print MYPIDFILE $$; | 
					
						
							|  |  |  |         close MYPIDFILE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } else { | 
					
						
							|  |  |  |    $debug = 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Connect to manager | 
					
						
							|  |  |  | $p = | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |   new IO::Socket::INET->new( | 
					
						
							|  |  |  |                             PeerAddr => $manager_host, | 
					
						
							|  |  |  |                             PeerPort => $manager_port, | 
					
						
							|  |  |  |                             Proto    => "tcp", | 
					
						
							|  |  |  |                             Type     => SOCK_STREAM | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |                            ) | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |   or die "\nCould not connect to Asterisk Manager Port at $manager_host\n"; | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  | $p->autoflush(1); | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # 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 = | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |   new IO::Socket::INET(Listen => 1, LocalPort => $listen_port, ReuseAddr => 1) | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |   or die "\nCan't listen to port $listen_port\n"; | 
					
						
							|  |  |  | $O = new IO::Select(); | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  | $O->add($m); | 
					
						
							|  |  |  | $O->add($p); | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  | $/ = "\0"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sub manager_reconnect() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $attempt        = 1; | 
					
						
							|  |  |  |     my $total_attempts = 60; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     do | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         log_debug("** Attempt reconnection to manager port # $attempt", 16); | 
					
						
							|  |  |  |         $p = | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |           new IO::Socket::INET->new( | 
					
						
							|  |  |  |                                     PeerAddr => $manager_host, | 
					
						
							|  |  |  |                                     PeerPort => $manager_port, | 
					
						
							|  |  |  |                                     Proto    => "tcp", | 
					
						
							|  |  |  |                                     Type     => SOCK_STREAM | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |                                    ); | 
					
						
							|  |  |  |         $attempt++; | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |         if ($attempt > $total_attempts) | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             die("!! Could not reconnect to Asterisk Manager port"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         sleep(10);    # wait 10 seconds before trying to reconnect | 
					
						
							|  |  |  |     } until $p; | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |     $O->add($p); | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |     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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |     while (@S = $O->can_read) | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |         foreach (@S) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if ($_ == $m) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 log_debug("** New client connection", 16); | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |                 my $C = $m->accept; | 
					
						
							| 
									
										
										
										
											2017-12-22 09:23:22 -05:00
										 |  |  |                 $proxy_clients{$C} = \$C; | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |                 print "New Connection: $C\n" if $debug; | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |                 $O->add($C); | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 # It's not a new client connection | 
					
						
							|  |  |  |                 my $i; | 
					
						
							|  |  |  |                 my $R = sysread($_, $i, 2);    # 2048; interleave every two bytes? | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |                 if (defined($R) && $R == 0) | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |                 { | 
					
						
							|  |  |  |                     # Confirm it's really dead by trying to write to it? | 
					
						
							|  |  |  |                     my $T = syswrite($_, ' ', 2);    # 2048 | 
					
						
							|  |  |  |                     if (!defined($T)) | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         # connection went away... | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |                         $O->remove($_); | 
					
						
							|  |  |  |                         $_->close; | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                         # 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 | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |         }    # end foreach @S -> can read | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |     }    # while can read | 
					
						
							|  |  |  | }    # endless loop | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sub close_all | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     log_debug("Exiting...", 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |     foreach my $hd ($O->handles) | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |         $O->remove($hd); | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |         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"); | 
					
						
							| 
									
										
										
										
											2004-11-02 22:34:51 +00:00
										 |  |  |             log_debug("-> $linea", 2); | 
					
						
							| 
									
										
										
										
											2004-10-26 04:02:57 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |         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"; | 
					
						
							|  |  |  | } |