Skip Menu |
 

This queue is for tickets about the POE-Component-Client-FTP CPAN distribution.

Report information
The Basics
Id: 34609
Status: new
Priority: 0/
Queue: POE-Component-Client-FTP

People
Owner: Nobody in particular
Requestors: jpalmer [...] linz.govt.nz
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: 0.18
Fixed in: (no value)



Subject: Event not emitted after list error
Download (untitled) / with headers
text/plain 1.5k
Hi, I've setup a POCO FTP client i.e my $ftp = POE::Component::Client::FTP->spawn( Alias => 'ftp_alias', RemoteAddr => $host, RemotePort => $port, Username => $user, Password => $password, Events => [qw( connected connect_error authenticated login_error quit quit_error type type_error cd cd_error ls_data ls_done ls_error get_data get_done get_error )], ); Everything seems to work ok to most ftp sites until I get a dir list error. My parent session is expecting either a ls_data ls_done ls_error to be called, but after the list error the ls_error is not emitted. Here's the last few lines of my debug log: 5 -> ls_data (from C:/Perl/site/lib/POE/Component/Client/FTP.pm at 986) 5 -> ls_data (from C:/Perl/site/lib/POE/Component/Client/FTP.pm at 986) 5 -> ls_data (from C:/Perl/site/lib/POE/Component/Client/FTP.pm at 986) 5 -> ls_data (from C:/Perl/site/lib/POE/Component/Client/FTP.pm at 986) 5 -> ls_data (from C:/Perl/site/lib/POE/Component/Client/FTP.pm at 986) 5 -> ls_data (from C:/Perl/site/lib/POE/Component/Client/FTP.pm at 986) 5 -> ls_data (from C:/Perl/site/lib/POE/Component/Client/FTP.pm at 986) -> default_complex::cmd_input at C:/Perl/site/lib/POE/Component/Client/FTP.pm line 968. <<< 227 Entering Passive Mode (69,44,86,87,213,212) -> default_complex::data_error at C:/Perl/site/lib/POE/Component/Client/FTP.pm line 968. error: complex_list: read at C:/Perl/site/lib/POE/Component/Client/FTP.pm line 913. Thanks, Jeremy
From: jpalmer [...] linz.govt.nz
Download (untitled) / with headers
text/plain 611b
Ok here is a patch that ensures that the order of command events is handled correctly. What was currently happening with certain FTP servers was the success transfer command event was being processed before the actual data connection had finished. In the current version of FTP 0.18 this caused the 'ready' state to be declared too early. This attached patch now ensures that the success transfer command event is queued if the data connection is not complete. The queued command event is then dispatched once the data connection has closed. This resolves the issue I was seeing in this bug. Cheers, Jeremy
Download FTP.patch
text/x-diff 4.1k
--- FTP.pm.org Wed Mar 19 01:21:07 2008 +++ FTP.pm Fri Apr 18 13:13:49 2008 @@ -294,8 +294,7 @@ delete $heap->{cmd_rw_wheel}; delete $heap->{cmd_sock_wheel}; - delete $heap->{data_rw_wheel}; - delete $heap->{data_sock_wheel}; + clean_up_complex_cmd(); $poe_kernel->alias_remove( $heap->{alias} ); return; @@ -309,8 +308,7 @@ my $coderef; - $input =~ s/^(\d\d\d)(.?)//o; - my ($code, $more) = ($1, $2); + my ($code, $major, $more) = parse_cmd_string($input); $input =~ s/^ // if defined $more && $more eq "-"; @@ -320,8 +318,6 @@ $heap->{ftp_message} =~ s/\s+$//; - my $major = substr($code, 0, 1); - if ($major == 1) { # 1yz Positive Preliminary reply @@ -470,8 +466,7 @@ elsif ($heap->{data_suicidal}) { warn "killing suicidal socket" . $heap->{data_rw_wheel}->get_driver_out_octets() if DEBUG; - delete $heap->{data_sock_wheel}; - delete $heap->{data_rw_wheel}; + clean_up_complex_cmd(); $heap->{data_suicidal} = 0; send_event("put_closed", @@ -489,8 +484,7 @@ send_event( "put_error", $error, $heap->{complex_stack}->{command}->[1] ); - delete $heap->{data_sock_wheel}; - delete $heap->{data_rw_wheel}; + clean_up_complex_cmd(); goto_state("ready"); return; } @@ -808,8 +802,6 @@ command($heap->{complex_stack}->{command}); } else { - send_event( $heap->{complex_stack}->{command}->[0] . "_done", - $heap->{complex_stack}->{command}->[1] ); goto_state("ready"); } return; @@ -826,9 +818,7 @@ $status, $line, $heap->{complex_stack}->{command}->[1] ); - delete $heap->{data_sock_wheel}; - delete $heap->{data_rw_wheel}; - + clean_up_complex_cmd(); goto_state("ready"); return; } @@ -891,8 +881,7 @@ send_event( $heap->{complex_stack}->{command}->[0] . "_error", $error, $heap->{complex_stack}->{command}->[1] ); - delete $heap->{data_sock_wheel}; - delete $heap->{data_rw_wheel}; + clean_up_complex_cmd(); goto_state("ready"); return; } @@ -911,9 +900,11 @@ sub handler_complex_list_error { my ($kernel, $heap, $input) = @_[KERNEL, HEAP, ARG0]; warn "error: complex_list: $input" if DEBUG; + send_event( $heap->{complex_stack}->{command}->[0] . "_done", + $heap->{complex_stack}->{command}->[1] ); - delete $heap->{data_sock_wheel}; - delete $heap->{data_rw_wheel}; + clean_up_complex_cmd(); + dequeue_complex_cmd(); return; } @@ -958,8 +949,15 @@ # if active session knows how to handle this event, dispatch it to them # if not, enqueue the event sub dispatch { - my ($kernel, $heap, $state) = @_[KERNEL, HEAP, STATE]; + my ($kernel, $heap, $state, $input) = @_[KERNEL, HEAP, STATE, ARG0]; + if ($state eq 'cmd_input' && defined $heap->{data_rw_wheel} ) { + my ($code, $major, $msg) = parse_cmd_string($input); + if ( $major == 2 ) { + enqueue_complex_cmd(@_); + return; + } + } my $coderef = ( $state_map->{ $heap->{state} }->{$state} || $state_map->{global}->{$state} || \&enqueue_event ); @@ -1058,6 +1056,38 @@ command("PORT " . join ",", @addr, @port); } return; +} + +sub parse_cmd_string { + my $string = shift; + $string =~ s/^(\d\d\d)(.?)//o; + my ($code, $more) = ($1, $2); + my $major = substr($code, 0, 1); + return ($code, $major, $more); +} + +sub clean_up_complex_cmd { + my $heap = $poe_kernel->get_active_session()->get_heap(); + delete $heap->{data_sock_wheel}; + delete $heap->{data_rw_wheel}; + $heap->{complex_stack} = {}; +} + +sub enqueue_complex_cmd { + my $heap = $poe_kernel->get_active_session()->get_heap(); + warn "enqueue_complex_cmd $_[STATE]" if DEBUG; + $heap->{pending_complex_cmd} = \@_; +} + +sub dequeue_complex_cmd { + my $heap = $poe_kernel->get_active_session()->get_heap(); + return unless $heap->{pending_complex_cmd}; + + my $state = $heap->{pending_complex_cmd}->[STATE]; + warn "dequeue_complex_cmd $state" if DEBUG; + my @event = @{ $heap->{pending_complex_cmd} }; + $heap->{pending_complex_cmd} = undef; + dispatch( @event ); } 1;
From: jpalmer [...] linz.govt.nz
Download (untitled) / with headers
text/plain 114b
Here's a new version of the patch the corrects a small uninitialized value in concatenation error. Cheers, Jeremy
--- FTP.pm.org Wed Mar 19 01:21:07 2008 +++ FTP.pm Fri Apr 18 14:16:45 2008 @@ -294,8 +294,7 @@ delete $heap->{cmd_rw_wheel}; delete $heap->{cmd_sock_wheel}; - delete $heap->{data_rw_wheel}; - delete $heap->{data_sock_wheel}; + clean_up_complex_cmd(); $poe_kernel->alias_remove( $heap->{alias} ); return; @@ -309,8 +308,7 @@ my $coderef; - $input =~ s/^(\d\d\d)(.?)//o; - my ($code, $more) = ($1, $2); + my ($code, $more) = parse_cmd_string($input); $input =~ s/^ // if defined $more && $more eq "-"; @@ -470,8 +468,7 @@ elsif ($heap->{data_suicidal}) { warn "killing suicidal socket" . $heap->{data_rw_wheel}->get_driver_out_octets() if DEBUG; - delete $heap->{data_sock_wheel}; - delete $heap->{data_rw_wheel}; + clean_up_complex_cmd(); $heap->{data_suicidal} = 0; send_event("put_closed", @@ -489,8 +486,7 @@ send_event( "put_error", $error, $heap->{complex_stack}->{command}->[1] ); - delete $heap->{data_sock_wheel}; - delete $heap->{data_rw_wheel}; + clean_up_complex_cmd(); goto_state("ready"); return; } @@ -808,8 +804,6 @@ command($heap->{complex_stack}->{command}); } else { - send_event( $heap->{complex_stack}->{command}->[0] . "_done", - $heap->{complex_stack}->{command}->[1] ); goto_state("ready"); } return; @@ -826,9 +820,7 @@ $status, $line, $heap->{complex_stack}->{command}->[1] ); - delete $heap->{data_sock_wheel}; - delete $heap->{data_rw_wheel}; - + clean_up_complex_cmd(); goto_state("ready"); return; } @@ -891,8 +883,7 @@ send_event( $heap->{complex_stack}->{command}->[0] . "_error", $error, $heap->{complex_stack}->{command}->[1] ); - delete $heap->{data_sock_wheel}; - delete $heap->{data_rw_wheel}; + clean_up_complex_cmd(); goto_state("ready"); return; } @@ -911,9 +902,11 @@ sub handler_complex_list_error { my ($kernel, $heap, $input) = @_[KERNEL, HEAP, ARG0]; warn "error: complex_list: $input" if DEBUG; + send_event( $heap->{complex_stack}->{command}->[0] . "_done", + $heap->{complex_stack}->{command}->[1] ); - delete $heap->{data_sock_wheel}; - delete $heap->{data_rw_wheel}; + clean_up_complex_cmd(); + dequeue_complex_cmd(); return; } @@ -958,8 +951,15 @@ # if active session knows how to handle this event, dispatch it to them # if not, enqueue the event sub dispatch { - my ($kernel, $heap, $state) = @_[KERNEL, HEAP, STATE]; + my ($kernel, $heap, $state, $input) = @_[KERNEL, HEAP, STATE, ARG0]; + if ($state eq 'cmd_input' && defined $heap->{data_rw_wheel} ) { + my ($code, $msg) = parse_cmd_string($input); + if ( substr($code, 0, 1) == 2 ) { + enqueue_complex_cmd(@_); + return; + } + } my $coderef = ( $state_map->{ $heap->{state} }->{$state} || $state_map->{global}->{$state} || \&enqueue_event ); @@ -1058,6 +1058,37 @@ command("PORT " . join ",", @addr, @port); } return; +} + +sub parse_cmd_string { + my $string = shift; + $string =~ s/^(\d\d\d)(.?)//o; + my ($code, $more) = ($1, $2); + return ($code, $more); +} + +sub clean_up_complex_cmd { + my $heap = $poe_kernel->get_active_session()->get_heap(); + delete $heap->{data_sock_wheel}; + delete $heap->{data_rw_wheel}; + $heap->{complex_stack} = {}; +} + +sub enqueue_complex_cmd { + my $heap = $poe_kernel->get_active_session()->get_heap(); + warn "enqueue_complex_cmd $_[STATE]" if DEBUG; + $heap->{pending_complex_cmd} = \@_; +} + +sub dequeue_complex_cmd { + my $heap = $poe_kernel->get_active_session()->get_heap(); + return unless $heap->{pending_complex_cmd}; + + my $state = $heap->{pending_complex_cmd}->[STATE]; + warn "dequeue_complex_cmd $state" if DEBUG; + my @event = @{ $heap->{pending_complex_cmd} }; + $heap->{pending_complex_cmd} = undef; + dispatch( @event ); } 1;


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.