123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- #!/usr/bin/perl
- use strict;
- use warnings;
- sub POE::Kernel::ASSERT_DEFAULT () { 1 };
- sub Term::Visual::DEBUG () { 1 }
- sub Term::Visual::DEBUG_FILE () { 'test.log' }
- use IO::Socket;
- use POE qw/Filter::FSSocket Component::Client::TCP/;
- use Data::Dumper;
- use Term::Visual;
- local *D;
- if (Term::Visual::DEBUG) {
- *D = *Term::Visual::ERRS;
- }
- #local *ERROR = *STDERR;
- $SIG{__DIE__} = sub {
- if (Term::Visual::DEBUG) {
- print Term::Visual::ERRS "Died: @_\n";
- }
- };
- ###############################################################################
- ## BEGIN Globals ##############################################################
- ###############################################################################
- our $server_address = "127.0.0.1";
- our $server_port = "8021";
- our $server_secret = "ClueCon";
- #this is where you can customize the color scheme
- our %Pallet = (
- 'warn_bullet' => 'bold yellow',
- 'err_bullet' => 'bold red',
- 'out_bullet' => 'bold green',
- 'access' => 'bright red on blue',
- 'current' => 'bright yellow on blue',
- );
- our $terminal;
- my %sockets;
- my %windows;
- my %unread_count;
- my %commands = (
- 'window' => 1,
- 'w' => 1,
- 'win' => 1,
- );
- ###############################################################################
- ## END Globals ##############################################################
- ###############################################################################
- #setup our session
- POE::Session->create(
- 'inline_states' => {
- '_start' => \&handle_start, #session start
- '_stop' => \&handle_stop, #session stop
- 'curses_input' => \&handle_curses_input, #input from the keyboard
- 'update_time' => \&handle_update_time, #update the status line clock
- 'quit' => \&handle_quit, #handler to do any cleanup
- 'server_input' => \&handle_server_input,
- '_default' => \&handle_default,
- },
- 'heap' => {
- 'terminal' => undef,
- 'freeswitch' => undef,
- },
- );
- #start the kernel a chugging along
- $poe_kernel->run;
- ###############################################################################
- ## BEGIN Handlers #############################################################
- ###############################################################################
- #handles any startup functions for our session
- sub handle_default {
- }
- sub handle_start {
- my ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP];
- #setup our terminal
- $heap->{'terminal'} = Term::Visual->new(
- 'Alias' => 'terminal', #poe alias for this
- 'History_Size' => 300, #number of things to keep in history
- 'Common_Input' => 1, #all windows share input and history
- 'Tab_Complete' => \&tab_complete,
- );
- $terminal = $heap->{'terminal'};
- #setup the color palette
- $terminal->set_palette(%Pallet);
- #create a base window
- my $window_id = $terminal->create_window(
- 'Window_Name' => 'console',
- 'Buffer_Size' => 3000,
- 'Title' => 'FreeSWITCH Console',
- 'Status' => {
- '0' => {
- 'format' => '%s',
- 'fields' => ['time'],
- },
- '1' => {
- 'format' => '%s',
- 'fields' => ['window_status'],
- },
- },
- );
- $windows{'console'} = $window_id;
- $window_id = $terminal->create_window(
- 'Window_Name' => 'log',
- 'Buffer_Size' => 3000,
- 'Title' => 'FreeSWITCH Logs',
- 'Status' => {
- '0' => {
- 'format' => '%s',
- 'fields' => ['time'],
- },
- '1' => {
- 'format' => '%s',
- 'fields' => ['window_status'],
- },
- },
- );
- $windows{'log'} = $window_id;
- $window_id = $terminal->create_window(
- 'Window_Name' => 'event',
- 'Buffer_Size' => 3000,
- 'Title' => 'FreeSWITCH Event',
- 'Status' => {
- '0' => {
- 'format' => '%s',
- 'fields' => ['time'],
- },
- '1' => {
- 'format' => '%s',
- 'fields' => ['window_status'],
- },
- },
- );
- $windows{'event'} = $window_id;
- #tell the terminal what to call when there is input from the keyboard
- $kernel->post('terminal' => 'send_me_input' => 'curses_input');
- $terminal->change_window(0);
- $kernel->delay_set('update_time' => 1);
- $terminal->set_status_field(0, 'time' => scalar(localtime));
- new_message('destination_window' => 0, 'message' => "
- Welcome to the FreeSWITCH POE Curses Console!
- The console is split into three windows:
- - 'console' for api response messages
- - 'log' for freeswitch log output (simply send the log level you want
- to start seeing events eg: 'log all')
- - 'event' for freeswitch event output (must subscribe in plain format
- eg: 'event plain all')
- To switch between windows type 'w <windowname' so 'w log' for example.
- Coming soon:
- - Tab completion
- - command history
- - window status in the bar (messages added since last view, etc...)
- Send any bug reports or comments to jackhammer\@gmail.com
- Thanks,
- Paul\n");
- $terminal->set_status_field($terminal->current_window, 'window_status' => format_window_status());
- #connect to freeswitch
- $heap->{'freeswitch'} = POE::Component::Client::TCP->new(
- 'RemoteAddress' => $server_address,
- 'RemotePort' => $server_port,
- 'ServerInput' => \&handle_server_input,
- 'Connected' => \&handle_fs_connected,
- 'ServerError' => \&handle_server_error,
- 'Disconnected' => \&handle_server_disconnect,
- 'Domain' => AF_INET,
- 'Filter' => POE::Filter::FSSocket->new(),
- );
- }
- #called when users enter commands in a window
- sub handle_curses_input {
- my ($kernel, $heap, $input, $context) = @_[KERNEL, HEAP, ARG0, ARG1];
- #get the id of the window that is responsible for the input
- my $window = $heap->{'terminal'}->current_window;
- open(ERROR, ">>error.log");
- if($input eq "quit") {
- $kernel->yield('quit');
- } elsif ($input =~ /^w\ (.*)$/) {
- #get the id of the requested window
- eval {
- my $window_id = $windows{$1};
- #see if it's real
- if(defined($window_id)) {
- $unread_count{$window_id} = 0;
- $terminal->change_window($window_id);
- $terminal->set_status_field($window_id, 'window_status' => &format_window_status());
- }
- };
- if($@) {
- print ERROR "put error: $@\n";
- }
- } else {
- #see if we got connected at some point
- if(defined($sockets{'localhost'})) {
- my $cmd;
- if ($input =~ /^log|^event/) {
- $cmd = $input;
- } else {
- $cmd = "api $input";
- }
- #send the command
- $sockets{'localhost'}->put($cmd);
- }
- }
- }
- sub handle_fs_connected {
- my ($kernel, $heap) = @_[KERNEL, HEAP];
- eval {
- $sockets{'localhost'} = $heap->{'server'};
- }
- }
- #this is responsible for doing any cleanup and returning the terminal to the previous
- #state before we mucked with it
- sub handle_quit {
- my ($kernel, $heap) = @_[KERNEL, HEAP];
- #tell curses to clean up it's crap
- $kernel->post('terminal' => 'shutdown');
- #there is probably a more elegant way, but this works for now
- exit;
- }
- #data from freeswitch
- sub handle_server_input {
- my ($kernel,$heap,$input) = @_[KERNEL,HEAP,ARG0];
- eval {
- #terminal HATES null
- if(defined($input->{'__DATA__'})) {
- $input->{'__DATA__'} =~ s/[\x00]//g;
- }
- #handle the login
- if($input->{'Content-Type'} eq "auth/request") {
- $heap->{'server'}->put("auth $server_secret");
- } elsif ($input->{'Content-Type'} eq "api/response") {
- new_message('destination_window' => 0, 'message' => 'API Response: ');
- new_message('destination_window' => 0, 'message' => $input->{'__DATA__'});
- } elsif ($input->{'Content-Type'} eq "log/data") {
- new_message('destination_window' => 1, 'message' => $input->{'__DATA__'});
- } elsif ($input->{'Content-Type'} eq "text/event-plain") {
- new_message('destination_window' => 2, 'message' => Dumper $input);
- } elsif ($input->{'Content-Type'} eq "command/reply") {
- new_message('destination_window' => 0, 'message' => 'Command Response: ' . $input->{'Reply-Text'});
- }
- };
- if($@) {
- open(ERROR, ">>error.log");
- print ERROR "died: $@\n";
- print ERROR Dumper $heap;
- close(ERROR);
- }
- }
- sub handle_server_error {
- }
- sub handle_server_disconnect {
- }
- sub tab_complete {
- my $left = shift;
- my @return;
- if(defined($commands{$left})) {
- return [$left . " "];
- #} elsif () {
- }
-
- }
- sub handle_update_time {
- my ($kernel, $heap) = @_[KERNEL, HEAP];
- $terminal->set_status_field($terminal->current_window, 'time' => scalar(localtime));
- $kernel->delay_set('update_time' => 1);
- }
- ###############################################################################
- ## END Handlers #############################################################
- ###############################################################################
- sub new_message {
- my %args = @_;
- my $message = $args{'message'};
- my $destination_window = $args{'destination_window'};
- my $status_field;
- #see if we are on the window being updated
- if($terminal->current_window != $destination_window) {
- #increment the unread count for the window
- #FIXME, should we count messages or lines?
- $unread_count{$destination_window}++;
- #update the status bar
- eval {
- $terminal->set_status_field($terminal->current_window, 'window_status' => &format_window_status());
- };
- if($@) {
- print $@;
- }
- }
- #deliver the message
- $terminal->print($destination_window, $message);
- }
- sub format_window_status {
- my $status_field;
- #put all the windows in the bar with their current unread count
- foreach my $window (sort {$windows{$a} <=> $windows{$b}} keys %windows) {
- #see if we are printing the current window
- if($terminal->current_window == $windows{$window}) {
- $status_field .= "[\0(current)$window\0(st_frames)";
- } else {
- $status_field .= "[$window";
- }
- if($unread_count{$windows{$window}}) {
- $status_field .= " (" . $unread_count{$windows{$window}} . ")";
- }
- $status_field .= "] ";
- }
- return $status_field;
- }
|