forked from Mirrors/freeswitch
370 lines
9.5 KiB
Perl
370 lines
9.5 KiB
Perl
#!/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;
|
|
}
|