1 package Net::FTP::AutoReconnect;
11 Net::FTP::AutoReconnect - FTP client class with automatic reconnect on failure
15 C<Net::FTP::AutoReconnect> is a wrapper module around C<Net::FTP>.
16 For many commands, if anything goes wrong on the first try, it tries
17 to disconnect and reconnect to the server, restore the state to the
18 same as it was when the command was executed, then execute it again.
19 The state includes login credentials, authorize credentials, transfer
20 mode (ASCII or binary), current working directory, and any restart,
21 passive, or port commands sent.
25 The goal of this method is to hide some implementation details of FTP
26 server systems from the programmer. In particular, many FTP systems
27 will automatically disconnect a user after a relatively short idle
28 time or after a transfer is aborted. In this case,
29 C<Net::FTP::AutoReconnect> will simply reconnect, send the commands
30 necessary to return your session to its previous state, then resend
31 the command. If that fails, it will return the error.
33 It makes no effort to determine what sorts of errors are likely to
34 succeed when they're retried. Partly that's because it's hard to
35 know; if you're retreiving a file from an FTP site with several
36 mirrors and the file is not found, for example, maybe on the next try
37 you'll connect to a different server and find it. But mostly it's
38 from laziness; if you have some good ideas about how to determine when
39 to retry and when not to bother, by all means send patches.
41 This module contains an instance of C<Net::FTP>, which it passes most
42 method calls along to.
44 These methods also record their state: C<alloc>, C<ascii>,
45 C<authorize>, C<binary>, C<cdup>, C<cwd>, C<hash>,
46 C<login>,C<restart>, C<pasv>, C<port>. Directory changing commands
47 execute a C<pwd> afterwards and store their new working directory.
49 These methods are automatically retried: C<alloc>, C<appe>, C<append>,
50 C<ascii>, C<binary>, C<cdup>, C<cwd>, C<delete>, C<dir>, C<get>,
51 C<list>, C<ls>, C<mdtm>, C<mkdir>, C<nlst>, C<pasv>, C<port>, C<put>,
52 C<put_unique>, C<pwd>, C<rename>, C<retr>, C<rmdir>, C<size>, C<stou>,
55 These methods are tried just once: C<abort>, C<authorize>, C<hash>,
56 C<login>, C<pasv_xfer>, C<pasv_xfer_unique>, C<pasv_wait>, C<quit>,
57 C<restart>, C<site>, C<unique_name>. From C<Net::Cmd>: C<code>,
58 C<message>, C<ok>, C<status>. C<restart> doesn't actually send any
59 FTP commands (they're sent along with the command they apply to),
60 which is why it's not restarted.
62 Any other commands are unimplemented (or possibly misdocumented); if I
63 missed one you'd like, please send a patch.
69 All parameters are passed along verbatim to C<Net::FTP>, as well as
70 stored in case we have to reconnect.
80 $self->{newargs} = \@_;
88 Most of the methods are those of L<Net::FTP|Net::FTP>. One additional
93 Abandon the current FTP connection and create a new one, restoring all
103 warn "Reconnecting!\n"
106 $self->{ftp} = Net::FTP->new(@{$self->{newargs}})
107 or die "Couldn't create new FTP object\n";
111 $self->{ftp}->login(@{$self->{login}});
113 if ($self->{authorize})
115 $self->{ftp}->authorize(@{$self->{authorize}});
119 if ($self->{mode} eq 'ascii')
121 $self->{ftp}->ascii();
125 $self->{ftp}->binary();
130 $self->{ftp}->cwd($self->{cwd});
134 $self->{ftp}->hash(@{$self->{hash}});
136 if ($self->{restart})
138 $self->{ftp}->restart(@{$self->{restart}});
142 $self->{ftp}->restart(@{$self->{alloc}});
146 $self->{ftp}->pasv(@{$self->{pasv}});
150 $self->{ftp}->port(@{$self->{port}});
175 delete $self->{port};
176 delete $self->{pasv};
177 delete $self->{restart};
178 delete $self->{alloc};
188 $self->{login} = \@_;
189 $self->{ftp}->login(@_);
195 $self->{authorize} = \@_;
196 $self->{ftp}->authorize(@_);
202 $self->{ftp}->site(@_);
208 $self->{mode} = 'ascii';
209 $self->_auto_reconnect(sub { $self->{ftp}->ascii() });
215 $self->{mode} = 'binary';
216 $self->_auto_reconnect(sub { $self->{ftp}->binary() });
223 $self->_auto_reconnect(sub { $self->{ftp}->rename(@a) });
230 $self->_auto_reconnect(sub { $self->{ftp}->delete(@a) });
237 my $ret = $self->_auto_reconnect(sub { $self->{ftp}->cwd(@a) });
240 $self->{cwd} = $self->{ftp}->pwd()
241 or die "Couldn't get directory after cwd\n";
250 my $ret = $self->_auto_reconnect(sub { $self->{ftp}->cdup(@a) });
253 $self->{cwd} = $self->{ftp}->pwd()
254 or die "Couldn't get directory after cdup\n";
263 $self->_auto_reconnect(sub { $self->{ftp}->pwd(@a) });
270 $self->_auto_reconnect(sub { $self->{ftp}->rmdir(@a) });
277 $self->_auto_reconnect(sub { $self->{ftp}->mkdir(@a) });
284 my $ret = $self->_auto_reconnect(sub { $self->{ftp}->ls(@a) });
285 return $ret ? (wantarray ? @$ret : $ret) : undef;
292 my $ret = $self->_auto_reconnect(sub { $self->{ftp}->dir(@a) });
293 return $ret ? (wantarray ? @$ret : $ret) : undef;
300 $self->{restart} = \@a;
301 $self->{ftp}->restart(@_);
308 $self->_after_pcmd($self->_auto_reconnect(sub { $self->{ftp}->retr(@a) }));
315 $self->_auto_reconnect(sub { $self->{ftp}->get(@a) });
322 $self->_auto_reconnect(sub { $self->{ftp}->mdtm(@a) });
329 $self->_auto_reconnect(sub { $self->{ftp}->size(@a) });
335 $self->{ftp}->abort();
341 $self->{ftp}->quit();
349 $self->{ftp}->hash(@_);
356 $self->{alloc} = \@a;
357 $self->_auto_reconnect(sub { $self->{ftp}->alloc(@a) });
364 $self->_auto_reconnect(sub { $self->{ftp}->put(@a) });
371 $self->_auto_reconnect(sub { $self->{ftp}->put_unique(@a) });
378 $self->_auto_reconnect(sub { $self->{ftp}->append(@a) });
384 $self->{ftp}->unique_name(@_);
391 $self->_auto_reconnect(sub { $self->{ftp}->supported(@a) });
399 $self->_auto_reconnect(sub { $self->{ftp}->port(@a) });
407 $self->_auto_reconnect(sub { $self->{ftp}->pasv(@a) });
414 $self->_after_pcmd($self->_auto_reconnect(sub { $self->{ftp}->nlst(@a) }));
421 $self->_after_pcmd($self->_auto_reconnect(sub { $self->{ftp}->stou(@a) }));
428 $self->_after_pcmd($self->_auto_reconnect(sub { $self->{ftp}->appe(@a) }));
435 $self->_after_pcmd($self->_auto_reconnect(sub { $self->{ftp}->list(@a) }));
441 $self->{ftp}->pasv_xfer(@_);
447 $self->{ftp}->pasv_xfer_unique(@_);
453 $self->{ftp}->pasv_wait(@_);
459 $self->{ftp}->message(@_);
465 $self->{ftp}->code(@_);
471 $self->{ftp}->ok(@_);
477 $self->{ftp}->status(@_);
482 Scott Gifford <sgifford@suspectclass.com>
486 We should really be smarter about when to retry.
488 We shouldn't be hardwired to use C<Net::FTP>, but any FTP-compatible
489 class; that would allow all modules similar to this one to be chained
492 Much of this is only lightly tested; it's hard to find an FTP server
493 unreliable enough to test all aspects of it. It's mostly been tested
494 with a server that dicsonnects after an aborted transfer, and the
495 module seems to work OK.
503 Copyright (c) 2006 Scott Gifford. All rights reserved. This program
504 is free software; you can redistribute it and/or modify it under the
505 same terms as Perl itself.