Rework of Filter's handling of the socket with freeswitch, the previous implementation was a serious cheat. We now properly handle the Content-Length tag and go out of line based mode and into length mode.

Also updated the console to show replies to commands.


git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3168 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Paul Tinsley 2006-10-23 20:47:22 +00:00
parent 39df1481c2
commit 900ad177d6
4 changed files with 64 additions and 50 deletions

View File

@ -1,3 +1,14 @@
=========================
2006-10-23 00:15:32 v0_06
=========================
2006-10-23 00:15:32 (r6) by ptinsley
reworked the handling of Content-Length based replies to deal with replies
that don't have \n at the end of their data block
Updated the curses example (fsconsole.pl)
- Added command/reply output
========================= =========================
2006-10-14 00:08:00 v0_05 2006-10-14 00:08:00 v0_05
========================= =========================

View File

@ -224,8 +224,14 @@ sub handle_curses_input {
} else { } else {
#see if we got connected at some point #see if we got connected at some point
if(defined($sockets{'localhost'})) { if(defined($sockets{'localhost'})) {
#send the command my $cmd;
$sockets{'localhost'}->put($input); if ($input =~ /^log|^event/) {
$cmd = $input;
} else {
$cmd = "api $input";
}
#send the command
$sockets{'localhost'}->put($cmd);
} }
} }
} }
@ -264,12 +270,14 @@ sub handle_server_input {
if($input->{'Content-Type'} eq "auth/request") { if($input->{'Content-Type'} eq "auth/request") {
$heap->{'server'}->put("auth $server_secret"); $heap->{'server'}->put("auth $server_secret");
} elsif ($input->{'Content-Type'} eq "api/response") { } elsif ($input->{'Content-Type'} eq "api/response") {
new_message('destination_window' => 0, 'message' => 'Response: '); new_message('destination_window' => 0, 'message' => 'API Response: ');
new_message('destination_window' => 0, 'message' => $input->{'__DATA__'}); new_message('destination_window' => 0, 'message' => $input->{'__DATA__'});
} elsif ($input->{'Content-Type'} eq "log/data") { } elsif ($input->{'Content-Type'} eq "log/data") {
new_message('destination_window' => 1, 'message' => $input->{'__DATA__'}); new_message('destination_window' => 1, 'message' => $input->{'__DATA__'});
} elsif ($input->{'Content-Type'} eq "text/event-plain") { } elsif ($input->{'Content-Type'} eq "text/event-plain") {
new_message('destination_window' => 2, 'message' => Dumper $input); 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'});
} }
}; };

View File

@ -11,9 +11,6 @@ POE::Filter::FSSocket - a POE filter that parses FreeSWITCH events into hashes
use POE qw(Component::Client::TCP Filter::FSSocket); use POE qw(Component::Client::TCP Filter::FSSocket);
use Data::Dumper; use Data::Dumper;
my $auth_sent = 0;
my $password = "ClueCon";
POE::Component::Client::TCP->new( POE::Component::Client::TCP->new(
'RemoteAddress' => '127.0.0.1', 'RemoteAddress' => '127.0.0.1',
@ -25,6 +22,9 @@ POE::Filter::FSSocket - a POE filter that parses FreeSWITCH events into hashes
POE::Kernel->run(); POE::Kernel->run();
exit; exit;
my $auth_sent = 0;
my $password = "ClueCon";
sub handle_server_input { sub handle_server_input {
my ($heap,$input) = @_[HEAP,ARG0]; my ($heap,$input) = @_[HEAP,ARG0];
@ -44,10 +44,6 @@ POE::Filter::FSSocket - a POE filter that parses FreeSWITCH events into hashes
} }
} }
=head1 EXAMPLES
See examples in the examples directory of the distribution.
=head1 DESCRIPTION =head1 DESCRIPTION
POE::Filter::FSSocket parses output from FreeSWITCH into hashes. FreeSWITCH POE::Filter::FSSocket parses output from FreeSWITCH into hashes. FreeSWITCH
@ -110,19 +106,18 @@ use Carp qw(carp croak);
use vars qw($VERSION); use vars qw($VERSION);
use base qw(POE::Filter); use base qw(POE::Filter);
$VERSION = '0.05'; $VERSION = '0.06';
use POE::Filter::Line;
use Data::Dumper; use Data::Dumper;
#self array #self array
sub LINE_FILTER() {1} sub FRAMING_BUFFER() {0}
sub PARSER_STATE() {2} sub PARSER_STATE() {1}
sub PARSER_STATENEXT() {3} sub PARSER_STATENEXT() {2}
sub PARSED_RECORD() {4} sub PARSED_RECORD() {3}
sub CURRENT_LENGTH() {5} sub CURRENT_LENGTH() {4}
sub STRICT_PARSE() {6} sub STRICT_PARSE() {5}
sub DEBUG_LEVEL() {7} sub DEBUG_LEVEL() {6}
#states of the parser #states of the parser
sub STATE_WAITING() {1} #looking for new input sub STATE_WAITING() {1} #looking for new input
@ -146,12 +141,8 @@ sub new {
$strict = $args{'strict'}; $strict = $args{'strict'};
} }
#our filter is line based, don't reinvent the wheel
my $line_filter = POE::Filter::Line->new();
my $self = bless [ my $self = bless [
"", #not used by me but the baseclass clone wants it here "", #framing buffer
$line_filter, #LINE_FILTER
STATE_WAITING, #PARSER_STATE STATE_WAITING, #PARSER_STATE
undef, #PARSER_STATE undef, #PARSER_STATE
{}, #PARSED_RECORD {}, #PARSED_RECORD
@ -166,22 +157,40 @@ sub new {
sub get_one_start { sub get_one_start {
my ($self, $stream) = @_; my ($self, $stream) = @_;
$self->[LINE_FILTER]->get_one_start($stream);
#take all the chunks and put them in the buffer
$self->[FRAMING_BUFFER] .= join('', @{$stream});
} }
sub get_one { sub get_one {
my $self = shift; my $self = shift;
my $line;
while(1) { while(1) {
#grab a line from the filter $line = "";
my $line = $self->[LINE_FILTER]->get_one();
#quit if we can't get any lines #see if we are in line based or length based mode
return [] unless @$line; if($self->[PARSER_STATE] == STATE_TEXTRESPONSE) {
my $length = $self->[PARSED_RECORD]{'Content-Length'};
#get the actual line
$line = $line->[0];
if($self->[FRAMING_BUFFER] =~ s/^(.{$length})//s) {
$self->[PARSER_STATE] = STATE_FLUSH;
$self->[PARSED_RECORD]->{'__DATA__'} = $1;
return [ $self->[PARSED_RECORD] ];
} else {
#not engough in the buffer yet, come back later
return;
}
} else { #we are in normal line based mode
if($self->[FRAMING_BUFFER] =~ s/^(.*?)(\x0D\x0A?|\x0A\x0D?)//) {
$line = $1;
} else {
#not enough off of the socket yet, come back later
return [];
}
}
if(($self->[PARSER_STATE] == STATE_WAITING) || ($self->[PARSER_STATE] == STATE_FLUSH)) { if(($self->[PARSER_STATE] == STATE_WAITING) || ($self->[PARSER_STATE] == STATE_FLUSH)) {
#see if we need to wipe out the parsed_record info #see if we need to wipe out the parsed_record info
if($self->[PARSER_STATE] == STATE_FLUSH) { if($self->[PARSER_STATE] == STATE_FLUSH) {
@ -271,22 +280,6 @@ sub get_one {
} }
} }
} }
} elsif ($self->[PARSER_STATE] == STATE_TEXTRESPONSE) {
if($self->[CURRENT_LENGTH] == -1) {
$self->[CURRENT_LENGTH] = 0;
next;
}
$self->[CURRENT_LENGTH] += (length($line) + 1);
if(($self->[CURRENT_LENGTH] - 1) == $self->[PARSED_RECORD]{'Content-Length'}) {
$self->[PARSER_STATE] = STATE_FLUSH;
$self->[PARSED_RECORD]{'__DATA__'} .= $line;
return [$self->[PARSED_RECORD]];
} else {
$self->[PARSED_RECORD]{'__DATA__'} .= $line . "\n";
}
} }
} }
} }
@ -305,7 +298,7 @@ sub put {
sub get_pending { sub get_pending {
my $self = shift; my $self = shift;
return $self->[LINE_FILTER]->get_pending(); return $self->[FRAMING_BUFFER];
} }
sub get { sub get {

View File

@ -270,12 +270,14 @@ sub handle_server_input {
if($input->{'Content-Type'} eq "auth/request") { if($input->{'Content-Type'} eq "auth/request") {
$heap->{'server'}->put("auth $server_secret"); $heap->{'server'}->put("auth $server_secret");
} elsif ($input->{'Content-Type'} eq "api/response") { } elsif ($input->{'Content-Type'} eq "api/response") {
new_message('destination_window' => 0, 'message' => 'Response: '); new_message('destination_window' => 0, 'message' => 'API Response: ');
new_message('destination_window' => 0, 'message' => $input->{'__DATA__'}); new_message('destination_window' => 0, 'message' => $input->{'__DATA__'});
} elsif ($input->{'Content-Type'} eq "log/data") { } elsif ($input->{'Content-Type'} eq "log/data") {
new_message('destination_window' => 1, 'message' => $input->{'__DATA__'}); new_message('destination_window' => 1, 'message' => $input->{'__DATA__'});
} elsif ($input->{'Content-Type'} eq "text/event-plain") { } elsif ($input->{'Content-Type'} eq "text/event-plain") {
new_message('destination_window' => 2, 'message' => Dumper $input); 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'});
} }
}; };