ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-FCP/FCP.pm
(Generate patch)

Comparing AnyEvent-FCP/FCP.pm (file contents):
Revision 1.19 by root, Tue Jun 7 18:53:23 2016 UTC vs.
Revision 1.28 by root, Thu Sep 9 00:49:06 2021 UTC

18=head1 DESCRIPTION 18=head1 DESCRIPTION
19 19
20This module implements the freenet client protocol version 2.0, as used by 20This module implements the freenet client protocol version 2.0, as used by
21freenet 0.7. See L<Net::FCP> for the earlier freenet 0.5 version. 21freenet 0.7. See L<Net::FCP> for the earlier freenet 0.5 version.
22 22
23See L<http://wiki.freenetproject.org/FreenetFCPSpec2Point0> for a 23See L<https://wiki.freenetproject.org/FCP> for a description of what the
24description of what the messages do. 24messages do.
25 25
26The module uses L<AnyEvent> to find a suitable event module. 26The module uses L<AnyEvent> to find a suitable event module.
27 27
28Only very little is implemented, ask if you need more, and look at the 28Only very little is implemented, ask if you need more, and look at the
29example program later in this section. 29example program later in this section.
61 61
62use common::sense; 62use common::sense;
63 63
64use Carp; 64use Carp;
65 65
66our $VERSION = 0.4; 66our $VERSION = 0.5;
67 67
68use Scalar::Util (); 68use Scalar::Util ();
69 69
70use AnyEvent; 70use AnyEvent;
71use AnyEvent::Handle; 71use AnyEvent::Handle;
86 1 while s/([^_])(SVK|CHK|URI|FCP|DS|MIME|DDA)/$1\_$2/; 86 1 while s/([^_])(SVK|CHK|URI|FCP|DS|MIME|DDA)/$1\_$2/;
87 s/(?<=[a-z])(?=[A-Z])/_/g; 87 s/(?<=[a-z])(?=[A-Z])/_/g;
88 lc 88 lc
89} 89}
90 90
91=item $fcp = new AnyEvent::FCP [host => $host][, port => $port][, name => $name] 91=item $fcp = new AnyEvent::FCP key => value...;
92 92
93Create a new FCP connection to the given host and port (default 93Create a new FCP connection to the given host and port (default
94127.0.0.1:9481, or the environment variables C<FREDHOST> and C<FREDPORT>). 94127.0.0.1:9481, or the environment variables C<FREDHOST> and C<FREDPORT>).
95 95
96If no C<name> was specified, then AnyEvent::FCP will generate a 96If no C<name> was specified, then AnyEvent::FCP will generate a
97(hopefully) unique client name for you. 97(hopefully) unique client name for you.
98
99The following keys can be specified (they are all optional):
100
101=over 4
102
103=item name => $string
104
105A unique name to identify this client. If none is specified, a randomly
106generated name will be used.
107
108=item host => $hostname
109
110The hostname or IP address of the freenet node. Default is C<$ENV{FREDHOST}>
111or C<127.0.0.1>.
112
113=item port => $portnumber
114
115The port number of the FCP port. Default is C<$ENV{FREDPORT}> or C<9481>.
116
117=item timeout => $seconds
118
119The timeout, in seconds, after which a connection error is assumed when
120there is no activity. Default is C<7200>, i.e. two hours.
121
122=item keepalive => $seconds
123
124The interval, in seconds, at which keepalive messages will be
125sent. Default is C<540>, i.e. nine minutes.
126
127These keepalive messages are useful both to detect that a connection is
128no longer working and to keep any (home) routers from expiring their
129masquerading entry.
130
131=item on_eof => $callback->($fcp)
132
133Invoked when the underlying L<AnyEvent::Handle> signals EOF, currently
134regardless of whether the EOF was expected or not.
135
136=item on_error => $callback->($fcp, $message)
137
138Invoked on any (fatal) errors, such as unexpected connection close. The
139callback receives the FCP object and a textual error message.
140
141=item on_failure => $callback->($fcp, $type, $args, $backtrace, $error)
142
143Invoked when an FCP request fails that didn't have a failure callback. See
144L<FCP REQUESTS> for details.
145
146=back
98 147
99=cut 148=cut
100 149
101sub new { 150sub new {
102 my $class = shift; 151 my $class = shift;
190 239
191 $self->{hdl} = new AnyEvent::Handle 240 $self->{hdl} = new AnyEvent::Handle
192 connect => [$self->{host} => $self->{port}], 241 connect => [$self->{host} => $self->{port}],
193 timeout => $self->{timeout}, 242 timeout => $self->{timeout},
194 on_read => $on_read, 243 on_read => $on_read,
195 on_eof => $self->{on_eof}, 244 on_eof => sub {
245 if ($self->{on_eof}) {
246 $self->{on_eof}($self);
247 } else {
248 $self->fatal ("EOF");
249 }
250 },
196 on_error => sub { 251 on_error => sub {
197 $self->fatal ($_[2]); 252 $self->fatal ($_[2]);
198 }, 253 },
199 ; 254 ;
200 255
210} 265}
211 266
212sub fatal { 267sub fatal {
213 my ($self, $msg) = @_; 268 my ($self, $msg) = @_;
214 269
215 $self->{hdl}->shutdown; 270 $self->{hdl}->push_shutdown if $self->{hdl};
216 delete $self->{kw}; 271 delete $self->{kw};
217 272
218 if ($self->{on_error}) { 273 if ($self->{on_error}) {
219 $self->{on_error}->($msg); 274 $self->{on_error}->($self, $msg);
220 } else { 275 } else {
221 die $msg; 276 die "AnyEvent::FCP($self->{host}:$self->{port}): $msg";
222 } 277 }
223} 278}
224 279
225sub identifier { 280sub identifier {
226 $_[0]{prefix} . ++$_[0]{idseq} 281 $_[0]{prefix} . ++$_[0]{idseq}
236 $self->{id}{$id} = delete $kv{id_cb}; 291 $self->{id}{$id} = delete $kv{id_cb};
237 } 292 }
238 293
239 my $msg = (touc $type) . "\012" 294 my $msg = (touc $type) . "\012"
240 . join "", map +(touc $_) . "=$kv{$_}\012", keys %kv; 295 . join "", map +(touc $_) . "=$kv{$_}\012", keys %kv;
241
242 sub id {
243 my ($self) = @_;
244
245
246 }
247 296
248 if (defined $data) { 297 if (defined $data) {
249 $msg .= "DataLength=" . (length $data) . "\012" 298 $msg .= "DataLength=" . (length $data) . "\012"
250 . "Data\012$data"; 299 . "Data\012$data";
251 } else { 300 } else {
370 419
371Also comes in this underscore variant: 420Also comes in this underscore variant:
372 421
373 $fcp->get_plugin_info_ ($name, $detailed, $cb); 422 $fcp->get_plugin_info_ ($name, $detailed, $cb);
374 423
375You can thinbk of the underscore as a kind of continuation indicator - the 424You can think of the underscore as a kind of continuation indicator - the
376normal function waits and returns with the data, the C<_> indicates that 425normal function waits and returns with the data, the C<_> indicates that
377you pass the continuation yourself, and the continuation will be invoked 426you pass the continuation yourself, and the continuation will be invoked
378with the results. 427with the results.
379 428
380This callback/continuation argument (C<$cb>) can come in three forms itself: 429This callback/continuation argument (C<$cb>) can come in three forms itself:
382=over 4 431=over 4
383 432
384=item A code reference (or rather anything not matching some other alternative) 433=item A code reference (or rather anything not matching some other alternative)
385 434
386This code reference will be invoked with the result on success. On an 435This code reference will be invoked with the result on success. On an
436error, it will invoke the C<on_failure> callback of the FCP object, or,
387error, it will die (in the event loop) with a backtrace of the call site. 437if none was defined, will die (in the event loop) with a backtrace of the
438call site.
388 439
389This is a popular choice, but it makes handling errors hard - make sure 440This is a popular choice, but it makes handling errors hard - make sure
390you never generate protocol errors! 441you never generate protocol errors!
442
443In the failure case, if an C<on_failure> hook exists, it will be invoked
444with the FCP object, the request type (the name of the method, an arrayref
445containing the arguments from the original request invocation, a (textual)
446backtrace as generated by C<Carp::longmess>, and the error object from the
447server, in this order, e.g.:
448
449 on_failure => sub {
450 my ($fcp, $request_type, $orig_args, $backtrace, $error_object) = @_;
451
452 warn "FCP failure ($type @$args), $error_object->{code_description} ($error_object->{extra_description})$backtrace";
453 exit 1;
454 },
391 455
392=item A condvar (as returned by e.g. C<< AnyEvent->condvar >>) 456=item A condvar (as returned by e.g. C<< AnyEvent->condvar >>)
393 457
394When a condvar is passed, it is sent (C<< $cv->send ($results) >>) the 458When a condvar is passed, it is sent (C<< $cv->send ($results) >>) the
395results when the request has finished. Should an error occur, the error 459results when the request has finished. Should an error occur, the error
400=item An array with two callbacks C<[$success, $failure]> 464=item An array with two callbacks C<[$success, $failure]>
401 465
402The C<$success> callback will be invoked with the results, while the 466The C<$success> callback will be invoked with the results, while the
403C<$failure> callback will be invoked on any errors. 467C<$failure> callback will be invoked on any errors.
404 468
469The C<$failure> callback will be invoked with the error object from the
470server.
471
405=item C<undef> 472=item C<undef>
406 473
407This is the same thing as specifying C<sub { }> as callback, i.e. on 474This is the same thing as specifying C<sub { }> as callback, i.e. on
408success, the results are ignored, while on failure, you the module dies 475success, the results are ignored, while on failure, the C<on_failure> hook
409with a backtrace. 476is invoked or the module dies with a backtrace.
410 477
411This is good for quick scripts, or when you really aren't interested in 478This is good for quick scripts, or when you really aren't interested in
412the results. 479the results.
413 480
414=back 481=back
434 if (ARRAY:: eq ref $ok) { 501 if (ARRAY:: eq ref $ok) {
435 ($ok, $err) = @$ok; 502 ($ok, $err) = @$ok;
436 } elsif (UNIVERSAL::isa $ok, AnyEvent::CondVar::) { 503 } elsif (UNIVERSAL::isa $ok, AnyEvent::CondVar::) {
437 $err = sub { $ok->croak ($_[0]{extra_description}) }; 504 $err = sub { $ok->croak ($_[0]{extra_description}) };
438 } else { 505 } else {
439 my $bt = Carp::longmess ""; 506 my $bt = Carp::longmess "AnyEvent::FCP request $name";
507 Scalar::Util::weaken (my $self = $_[0]);
508 my $args = [@_]; shift @$args;
440 $err = sub { 509 $err = sub {
510 if ($self->{on_failure}) {
511 $self->{on_failure}($self, $name, $args, $bt, $_[0]);
512 } else {
441 die "$_[0]{code_description} ($_[0]{extra_description})$bt"; 513 die "$_[0]{code_description} ($_[0]{extra_description})$bt";
514 }
442 }; 515 };
443 } 516 }
444 517
445 $ok ||= $NOP_CB; 518 $ok ||= $NOP_CB;
446 519
658 }); 731 });
659}; 732};
660 733
661=item $status = $fcp->remove_request ($identifier[, $global]) 734=item $status = $fcp->remove_request ($identifier[, $global])
662 735
663Remove the request with the given isdentifier. Returns true if successful, 736Remove the request with the given identifier. Returns true if successful,
664false on error. 737false on error.
665 738
666=cut 739=cut
667 740
668_txn remove_request => sub { 741_txn remove_request => sub {
713 786
714C<$want_read> and C<$want_write> should be set to a true value when you 787C<$want_read> and C<$want_write> should be set to a true value when you
715want to read (get) files or write (put) files, respectively. 788want to read (get) files or write (put) files, respectively.
716 789
717On error, an exception is thrown. Otherwise, C<$can_read> and 790On error, an exception is thrown. Otherwise, C<$can_read> and
718C<$can_write> indicate whether you can reaqd or write to freenet via the 791C<$can_write> indicate whether you can read or write to freenet via the
719directory. 792directory.
720 793
721=cut 794=cut
722 795
723_txn test_dda => sub { 796_txn test_dda => sub {
844on every change, which will be called as C<< $cb->($fcp, $kv, $type) >>, where C<$type> 917on every change, which will be called as C<< $cb->($fcp, $kv, $type) >>, where C<$type>
845is the type of the original message triggering the change, 918is the type of the original message triggering the change,
846 919
847To fill this cache with the global queue and keep it updated, 920To fill this cache with the global queue and keep it updated,
848call C<watch_global> to subscribe to updates, followed by 921call C<watch_global> to subscribe to updates, followed by
849C<list_persistent_requests_sync>. 922C<list_persistent_requests>.
850 923
851 $fcp->watch_global_sync_; # do not wait 924 $fcp->watch_global_; # do not wait
852 $fcp->list_persistent_requests; # wait 925 $fcp->list_persistent_requests; # wait
853 926
854To get a better idea of what is stored in the cache, here is an example of 927To get a better idea of what is stored in the cache, here is an example of
855what might be stored in C<< $fcp->{req}{"Frost-gpl.txt"} >>: 928what might be stored in C<< $fcp->{req}{"Frost-gpl.txt"} >>:
856 929
965 if 0.1 > rand; 1038 if 0.1 > rand;
966 } 1039 }
967 } 1040 }
968 1041
969 # see if the dummy plugin is loaded, to ensure all previous requests have finished. 1042 # see if the dummy plugin is loaded, to ensure all previous requests have finished.
970 $fcp->get_plugin_info_sync ("dummy"); 1043 $fcp->get_plugin_info ("dummy");
971 1044
972=head1 SEE ALSO 1045=head1 SEE ALSO
973 1046
974L<http://wiki.freenetproject.org/FreenetFCPSpec2Point0>, L<Net::FCP>. 1047L<http://wiki.freenetproject.org/FreenetFCPSpec2Point0>, L<Net::FCP>.
975 1048

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines