managerproxy.pl 7.0 KB

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