Author: ptinsley Date: Mon Oct 23 16:47:22 2006 New Revision: 3168 Modified: freeswitch/trunk/scripts/POE-Filter-FSSocket/CHANGES freeswitch/trunk/scripts/POE-Filter-FSSocket/examples/fsconsole.pl freeswitch/trunk/scripts/POE-Filter-FSSocket/lib/POE/Filter/FSSocket.pm freeswitch/trunk/scripts/socket/fsconsole.pl Log: 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. Modified: freeswitch/trunk/scripts/POE-Filter-FSSocket/CHANGES ============================================================================== --- freeswitch/trunk/scripts/POE-Filter-FSSocket/CHANGES (original) +++ freeswitch/trunk/scripts/POE-Filter-FSSocket/CHANGES Mon Oct 23 16:47:22 2006 @@ -1,4 +1,15 @@ ========================= +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 ========================= Modified: freeswitch/trunk/scripts/POE-Filter-FSSocket/examples/fsconsole.pl ============================================================================== --- freeswitch/trunk/scripts/POE-Filter-FSSocket/examples/fsconsole.pl (original) +++ freeswitch/trunk/scripts/POE-Filter-FSSocket/examples/fsconsole.pl Mon Oct 23 16:47:22 2006 @@ -224,8 +224,14 @@ } else { #see if we got connected at some point if(defined($sockets{'localhost'})) { - #send the command - $sockets{'localhost'}->put($input); + my $cmd; + if ($input =~ /^log|^event/) { + $cmd = $input; + } else { + $cmd = "api $input"; + } + #send the command + $sockets{'localhost'}->put($cmd); } } } @@ -264,12 +270,14 @@ 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' => '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'}); } }; Modified: freeswitch/trunk/scripts/POE-Filter-FSSocket/lib/POE/Filter/FSSocket.pm ============================================================================== --- freeswitch/trunk/scripts/POE-Filter-FSSocket/lib/POE/Filter/FSSocket.pm (original) +++ freeswitch/trunk/scripts/POE-Filter-FSSocket/lib/POE/Filter/FSSocket.pm Mon Oct 23 16:47:22 2006 @@ -11,9 +11,6 @@ use POE qw(Component::Client::TCP Filter::FSSocket); use Data::Dumper; - - my $auth_sent = 0; - my $password = "ClueCon"; POE::Component::Client::TCP->new( 'RemoteAddress' => '127.0.0.1', @@ -25,6 +22,9 @@ POE::Kernel->run(); exit; + my $auth_sent = 0; + my $password = "ClueCon"; + sub handle_server_input { my ($heap,$input) = @_[HEAP,ARG0]; @@ -44,10 +44,6 @@ } } -=head1 EXAMPLES - -See examples in the examples directory of the distribution. - =head1 DESCRIPTION POE::Filter::FSSocket parses output from FreeSWITCH into hashes. FreeSWITCH @@ -110,19 +106,18 @@ use vars qw($VERSION); use base qw(POE::Filter); -$VERSION = '0.05'; +$VERSION = '0.06'; -use POE::Filter::Line; use Data::Dumper; #self array -sub LINE_FILTER() {1} -sub PARSER_STATE() {2} -sub PARSER_STATENEXT() {3} -sub PARSED_RECORD() {4} -sub CURRENT_LENGTH() {5} -sub STRICT_PARSE() {6} -sub DEBUG_LEVEL() {7} +sub FRAMING_BUFFER() {0} +sub PARSER_STATE() {1} +sub PARSER_STATENEXT() {2} +sub PARSED_RECORD() {3} +sub CURRENT_LENGTH() {4} +sub STRICT_PARSE() {5} +sub DEBUG_LEVEL() {6} #states of the parser sub STATE_WAITING() {1} #looking for new input @@ -146,12 +141,8 @@ $strict = $args{'strict'}; } - #our filter is line based, don't reinvent the wheel - my $line_filter = POE::Filter::Line->new(); - my $self = bless [ - "", #not used by me but the baseclass clone wants it here - $line_filter, #LINE_FILTER + "", #framing buffer STATE_WAITING, #PARSER_STATE undef, #PARSER_STATE {}, #PARSED_RECORD @@ -166,22 +157,40 @@ sub get_one_start { 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 { my $self = shift; + my $line; + while(1) { - #grab a line from the filter - my $line = $self->[LINE_FILTER]->get_one(); + $line = ""; - #quit if we can't get any lines - return [] unless @$line; + #see if we are in line based or length based mode + 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)) { #see if we need to wipe out the parsed_record info if($self->[PARSER_STATE] == STATE_FLUSH) { @@ -271,22 +280,6 @@ } } } - } 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 get_pending { my $self = shift; - return $self->[LINE_FILTER]->get_pending(); + return $self->[FRAMING_BUFFER]; } sub get { Modified: freeswitch/trunk/scripts/socket/fsconsole.pl ============================================================================== --- freeswitch/trunk/scripts/socket/fsconsole.pl (original) +++ freeswitch/trunk/scripts/socket/fsconsole.pl Mon Oct 23 16:47:22 2006 @@ -270,12 +270,14 @@ 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' => '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'}); } };