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.2 by root, Sat Jul 25 06:28:49 2009 UTC vs.
Revision 1.3 by root, Tue Jul 28 02:20:51 2009 UTC

2 2
3AnyEvent::FCP - freenet client protocol 2.0 3AnyEvent::FCP - freenet client protocol 2.0
4 4
5=head1 SYNOPSIS 5=head1 SYNOPSIS
6 6
7 use AnyEvent::FCP; 7 use AnyEvent::FCP;
8 8
9 my $fcp = new AnyEvent::FCP; 9 my $fcp = new AnyEvent::FCP;
10 10
11 my $ni = $fcp->txn_node_info->result; 11# transactions return condvars
12 my $ni = $fcp->node_info; 12 my $lp_cv = $fcp->list_peers;
13 my $pr_cv = $fcp->list_persistent_requests;
14
15 my $peers = $lp_cv->recv;
16 my $reqs = $pr_cv->recv;
13 17
14=head1 DESCRIPTION 18=head1 DESCRIPTION
15 19
16This 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
17freenet 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.
18 22
19See L<http://wiki.freenetproject.org/FreenetFCPSpec2Point0> for a description 23See L<http://wiki.freenetproject.org/FreenetFCPSpec2Point0> for a
20of what the messages do. 24description of what the messages do.
21 25
22The module uses L<AnyEvent> to find a suitable event module. 26The module uses L<AnyEvent> to find a suitable event module.
23 27
28Only very little is implemented, ask if you need more, and look at the
29example program later in this section.
30
24=head2 IMPORT TAGS 31=head2 IMPORT TAGS
25 32
26Nothing much can be "imported" from this module right now. 33Nothing much can be "imported" from this module right now.
27 34
28=head2 FREENET BASICS 35=head2 THE AnyEvent::FCP CLASS
29
30Ok, this section will not explain any freenet basics to you, just some
31problems I found that you might want to avoid:
32 36
33=over 4 37=over 4
34 38
35=item freenet URIs are _NOT_ URIs
36
37Whenever a "uri" is required by the protocol, freenet expects a kind of
38URI prefixed with the "freenet:" scheme, e.g. "freenet:CHK...". However,
39these are not URIs, as freeent fails to parse them correctly, that is, you
40must unescape an escaped characters ("%2c" => ",") yourself. Maybe in the
41future this library will do it for you, so watch out for this incompatible
42change.
43
44=back
45
46=head2 THE AnyEvent::FCP CLASS
47
48=over 4
49
50=cut 39=cut
51 40
52package AnyEvent::FCP; 41package AnyEvent::FCP;
53 42
54use common::sense; 43use common::sense;
55 44
56use Carp; 45use Carp;
57 46
58our $VERSION = '0.1'; 47our $VERSION = '0.2';
59 48
60use Scalar::Util (); 49use Scalar::Util ();
61 50
62use AnyEvent; 51use AnyEvent;
63use AnyEvent::Handle; 52use AnyEvent::Handle;
80=item $fcp = new AnyEvent::FCP [host => $host][, port => $port][, progress => \&cb][, name => $name] 69=item $fcp = new AnyEvent::FCP [host => $host][, port => $port][, progress => \&cb][, name => $name]
81 70
82Create a new FCP connection to the given host and port (default 71Create a new FCP connection to the given host and port (default
83127.0.0.1:9481, or the environment variables C<FREDHOST> and C<FREDPORT>). 72127.0.0.1:9481, or the environment variables C<FREDHOST> and C<FREDPORT>).
84 73
85If no C<name> was specified, then AnyEvent::FCP will generate a (hopefully) 74If no C<name> was specified, then AnyEvent::FCP will generate a
86unique client name for you. 75(hopefully) unique client name for you.
76
77=cut
87 78
88#TODO 79#TODO
89#You can install a progress callback that is being called with the AnyEvent::FCP 80#You can install a progress callback that is being called with the AnyEvent::FCP
90#object, a txn object, the type of the transaction and the attributes. Use 81#object, a txn object, the type of the transaction and the attributes. Use
91#it like this: 82#it like this:
94# my ($self, $txn, $type, $attr) = @_; 85# my ($self, $txn, $type, $attr) = @_;
95# 86#
96# warn "progress<$txn,$type," . (join ":", %$attr) . ">\n"; 87# warn "progress<$txn,$type," . (join ":", %$attr) . ">\n";
97# } 88# }
98 89
99=cut
100
101sub new { 90sub new {
102 my $class = shift; 91 my $class = shift;
103 my $self = bless { @_ }, $class; 92 my $self = bless { @_ }, $class;
104 93
105 $self->{host} ||= $ENV{FREDHOST} || "127.0.0.1"; 94 $self->{host} ||= $ENV{FREDHOST} || "127.0.0.1";
132 ); 121 );
133 122
134 $self 123 $self
135} 124}
136 125
137sub progress { 126#sub progress {
138 my ($self, $txn, $type, $attr) = @_; 127# my ($self, $txn, $type, $attr) = @_;
139 128#
140 $self->{progress}->($self, $txn, $type, $attr) 129# $self->{progress}->($self, $txn, $type, $attr)
141 if $self->{progress}; 130# if $self->{progress};
142} 131#}
143 132
144sub send_msg { 133sub send_msg {
145 my ($self, $type, %kv) = @_; 134 my ($self, $type, %kv) = @_;
146 135
147 my $data = delete $kv{data}; 136 my $data = delete $kv{data};
253 &$sub; 242 &$sub;
254 $cv->recv 243 $cv->recv
255 }; 244 };
256} 245}
257 246
247=item $cv = $fcp->list_peers ([$with_metdata[, $with_volatile]])
248
249=item $peers = $fcp->list_peers_sync ([$with_metdata[, $with_volatile]])
250
251=cut
252
258_txn list_peers => sub { 253_txn list_peers => sub {
259 my ($self, $cv, $with_metadata, $with_volatile) = @_; 254 my ($self, $cv, $with_metadata, $with_volatile) = @_;
260 255
261 my @res; 256 my @res;
262 257
275 } 270 }
276 }, 271 },
277 ); 272 );
278}; 273};
279 274
275=item $cv = $fcp->list_peer_notes ($node_identifier)
276
277=item $notes = $fcp->list_peer_notes_sync ($node_identifier)
278
279=cut
280
280_txn list_peer_notes => sub { 281_txn list_peer_notes => sub {
281 my ($self, $cv, $node_identifier) = @_; 282 my ($self, $cv, $node_identifier) = @_;
282 283
283 $self->send_msg (list_peer_notes => 284 $self->send_msg (list_peer_notes =>
284 node_identifier => $node_identifier, 285 node_identifier => $node_identifier,
289 1 290 1
290 }, 291 },
291 ); 292 );
292}; 293};
293 294
295=item $cv = $fcp->watch_global ($enabled[, $verbosity_mask])
296
297=item $fcp->watch_global_sync ($enabled[, $verbosity_mask])
298
299=cut
300
294_txn watch_global => sub { 301_txn watch_global => sub {
295 my ($self, $cv, $enabled, $verbosity_mask) = @_; 302 my ($self, $cv, $enabled, $verbosity_mask) = @_;
296 303
297 $self->send_msg (watch_global => 304 $self->send_msg (watch_global =>
298 enabled => $enabled ? "true" : "false", 305 enabled => $enabled ? "true" : "false",
299 defined $verbosity_mask ? (verbosity_mask => $verbosity_mask+0) : (), 306 defined $verbosity_mask ? (verbosity_mask => $verbosity_mask+0) : (),
300 ); 307 );
301 308
302 $cv->(); 309 $cv->();
303}; 310};
311
312=item $cv = $fcp->list_persistent_requests
313
314=item $reqs = $fcp->list_persistent_requests_sync
315
316=cut
304 317
305_txn list_persistent_requests => sub { 318_txn list_persistent_requests => sub {
306 my ($self, $cv) = @_; 319 my ($self, $cv) = @_;
307 320
308 my %res; 321 my %res;
333 0 346 0
334 } 347 }
335 }; 348 };
336}; 349};
337 350
351=item $cv = $fcp->remove_request ($global, $identifier)
352
353=item $status = $fcp->remove_request_sync ($global, $identifier)
354
355=cut
356
338_txn remove_request => sub { 357_txn remove_request => sub {
339 my ($self, $cv, $global, $identifier) = @_; 358 my ($self, $cv, $global, $identifier) = @_;
340 359
341 $self->send_msg (remove_request => 360 $self->send_msg (remove_request =>
342 global => $global ? "true" : "false", 361 global => $global ? "true" : "false",
349 }, 368 },
350 ); 369 );
351 370
352 $cv->(); 371 $cv->();
353}; 372};
373
374=item $cv = $fcp->modify_persistent_request ($global, $identifier[, $client_token[, $priority_class]])
375
376=item $status = $fcp->modify_persistent_request_sync ($global, $identifier[, $client_token[, $priority_class]])
377
378=cut
354 379
355_txn modify_persistent_request => sub { 380_txn modify_persistent_request => sub {
356 my ($self, $cv, $global, $identifier, $client_token, $priority_class) = @_; 381 my ($self, $cv, $global, $identifier, $client_token, $priority_class) = @_;
357 382
358 $self->send_msg (modify_persistent_request => 383 $self->send_msg (modify_persistent_request =>
369 ); 394 );
370 395
371 $cv->(); 396 $cv->();
372}; 397};
373 398
399=item $cv = $fcp->get_plugin_info ($name, $detailed)
400
401=item $info = $fcp->get_plugin_info_sync ($name, $detailed)
402
403=cut
404
374_txn get_plugin_info => sub { 405_txn get_plugin_info => sub {
375 my ($self, $cv, $name, $detailed) = @_; 406 my ($self, $cv, $name, $detailed) = @_;
376 407
377 $self->send_msg (get_plugin_info => 408 $self->send_msg (get_plugin_info =>
378 plugin_name => $name, 409 plugin_name => $name,
388 $cv->(); 419 $cv->();
389}; 420};
390 421
391=back 422=back
392 423
424=head1 EXAMPLE PROGRAM
425
426 use AnyEvent::FCP;
427
428 my $fcp = new AnyEvent::FCP;
429
430 # let us look at the global request list
431 $fcp->watch_global (1, 0);
432
433 # list them, synchronously
434 my $req = $fcp->list_persistent_requests_sync;
435
436 # go through all requests
437 for my $req (values %$req) {
438 # skip jobs not directly-to-disk
439 next unless $req->{return_type} eq "disk";
440 # skip jobs not issued by FProxy
441 next unless $req->{identifier} =~ /^FProxy:/;
442
443 if ($req->{data_found}) {
444 # file has been successfully downloaded
445
446 ... move the file away
447 (left as exercise)
448
449 # remove the request
450
451 $fcp->remove_request (1, $req->{identifier});
452 } elsif ($req->{get_failed}) {
453 # request has failed
454 if ($req->{get_failed}{code} == 11) {
455 # too many path components, should restart
456 } else {
457 # other failure
458 }
459 } else {
460 # modify priorities randomly, to improve download rates
461 $fcp->modify_persistent_request (1, $req->{identifier}, undef, int 6 - 5 * (rand) ** 1.7)
462 if 0.1 > rand;
463 }
464 }
465
466 # see if the dummy plugin is loaded, to ensure all previous requests have finished.
467 $fcp->get_plugin_info_sync ("dummy");
468
393=head1 SEE ALSO 469=head1 SEE ALSO
394 470
395L<http://wiki.freenetproject.org/FreenetFCPSpec2Point0>, L<Net::FCP>. 471L<http://wiki.freenetproject.org/FreenetFCPSpec2Point0>, L<Net::FCP>.
396 472
397=head1 BUGS 473=head1 BUGS

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines