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

Comparing cvsroot/Net-FCP/FCP.pm (file contents):
Revision 1.22 by root, Wed Sep 17 05:05:33 2003 UTC vs.
Revision 1.41 by root, Thu May 1 15:30:15 2008 UTC

11 my $ni = $fcp->txn_node_info->result; 11 my $ni = $fcp->txn_node_info->result;
12 my $ni = $fcp->node_info; 12 my $ni = $fcp->node_info;
13 13
14=head1 DESCRIPTION 14=head1 DESCRIPTION
15 15
16This module implements the first version of the freenet client protocol,
17for use with freenet versions 0.5. For freenet protocol version 2.0
18support (as used by freenet 0.7), see the L<AnyEvent::FCP> module.
19
16See L<http://freenet.sourceforge.net/index.php?page=fcp> for a description 20See L<http://freenet.sourceforge.net/index.php?page=fcp> for a description
17of what the messages do. I am too lazy to document all this here. 21of what the messages do.
18 22
19=head1 WARNING 23The module uses L<AnyEvent> to find a suitable Event module.
20
21This module is alpha. While it probably won't destroy (much :) of your
22data, it currently falls short of what it should provide (intelligent uri
23following, splitfile downloads, healing...)
24 24
25=head2 IMPORT TAGS 25=head2 IMPORT TAGS
26 26
27Nothing much can be "imported" from this module right now. There are, 27Nothing much can be "imported" from this module right now.
28however, certain "import tags" that can be used to select the event model
29to be used.
30
31Event models are implemented as modules under the C<Net::FCP::Event::xyz>
32class, where C<xyz> is the event model to use. The default is C<Event> (or
33later C<Auto>).
34
35The import tag to use is named C<event=xyz>, e.g. C<event=Event>,
36C<event=Glib> etc.
37
38You should specify the event module to use only in the main program.
39
40If no event model has been specified, FCP tries to autodetect it on first
41use (e.g. first transaction), in this order: Coro, Event, Glib, Tk.
42 28
43=head2 FREENET BASICS 29=head2 FREENET BASICS
44 30
45Ok, this section will not explain any freenet basics to you, just some 31Ok, this section will not explain any freenet basics to you, just some
46problems I found that you might want to avoid: 32problems I found that you might want to avoid:
72 58
73package Net::FCP; 59package Net::FCP;
74 60
75use Carp; 61use Carp;
76 62
77$VERSION = 0.5; 63$VERSION = '1.2';
78 64
79no warnings; 65no warnings;
80 66
81our $EVENT = Net::FCP::Event::Auto::; 67use AnyEvent;
82 68
83sub import { 69use Net::FCP::Metadata;
84 shift; 70use Net::FCP::Util qw(tolc touc xeh);
85 71
86 for (@_) {
87 if (/^event=(\w+)$/) {
88 $EVENT = "Net::FCP::Event::$1";
89 eval "require $EVENT";
90 }
91 }
92 die $@ if $@;
93}
94
95sub touc($) {
96 local $_ = shift;
97 1 while s/((?:^|_)(?:svk|chk|uri)(?:_|$))/\U$1/;
98 s/(?:^|_)(.)/\U$1/g;
99 $_;
100}
101
102sub tolc($) {
103 local $_ = shift;
104 s/(?<=[a-z])(?=[A-Z])/_/g;
105 lc $_;
106}
107
108=item $meta = Net::FCP::parse_metadata $string
109
110Parse a metadata string and return it.
111
112The metadata will be a hashref with key C<version> (containing the
113mandatory version header entries) and key C<raw> containing the original
114metadata string.
115
116All other headers are represented by arrayrefs (they can be repeated).
117
118Since this description is confusing, here is a rather verbose example of a
119parsed manifest:
120
121 (
122 raw => "Version...",
123 version => { revision => 1 },
124 document => [
125 {
126 info => { format" => "image/jpeg" },
127 name => "background.jpg",
128 redirect => { target => "freenet:CHK\@ZcagI,ra726bSw" },
129 },
130 {
131 info => { format" => "text/html" },
132 name => ".next",
133 redirect => { target => "freenet:SSK\@ilUPAgM/TFEE/3" },
134 },
135 {
136 info => { format" => "text/html" },
137 redirect => { target => "freenet:CHK\@8M8Po8ucwI,8xA" },
138 }
139 ]
140 )
141
142=cut
143
144sub parse_metadata {
145 my $data = shift;
146 my $meta = { raw => $data };
147
148 if ($data =~ /^Version\015?\012/gc) {
149 my $hdr = $meta->{version} = {};
150
151 for (;;) {
152 while ($data =~ /\G([^=\015\012]+)=([^\015\012]*)\015?\012/gc) {
153 my ($k, $v) = ($1, $2);
154 my @p = split /\./, tolc $k, 3;
155
156 $hdr->{$p[0]} = $v if @p == 1; # lamest code I ever wrote
157 $hdr->{$p[0]}{$p[1]} = $v if @p == 2;
158 $hdr->{$p[0]}{$p[1]}{$p[2]} = $v if @p == 3;
159 die "FATAL: 4+ dot metadata" if @p >= 4;
160 }
161
162 if ($data =~ /\GEndPart\015?\012/gc) {
163 # nop
164 } elsif ($data =~ /\GEnd(\015?\012|$)/gc) {
165 last;
166 } elsif ($data =~ /\G([A-Za-z0-9.\-]+)\015?\012/gcs) {
167 push @{$meta->{tolc $1}}, $hdr = {};
168 } elsif ($data =~ /\G(.*)/gcs) {
169 print STDERR "metadata format error ($1), please report this string: <<$data>>";
170 die "metadata format error";
171 }
172 }
173 }
174
175 #$meta->{tail} = substr $data, pos $data;
176
177 $meta;
178}
179
180=item $fcp = new Net::FCP [host => $host][, port => $port] 72=item $fcp = new Net::FCP [host => $host][, port => $port][, progress => \&cb]
181 73
182Create a new virtual FCP connection to the given host and port (default 74Create a new virtual FCP connection to the given host and port (default
183127.0.0.1:8481, or the environment variables C<FREDHOST> and C<FREDPORT>). 75127.0.0.1:8481, or the environment variables C<FREDHOST> and C<FREDPORT>).
184 76
185Connections are virtual because no persistent physical connection is 77Connections are virtual because no persistent physical connection is
186established. 78established.
187 79
188=begin comment 80You can install a progress callback that is being called with the Net::FCP
81object, a txn object, the type of the transaction and the attributes. Use
82it like this:
189 83
190However, the existance of the node is checked by executing a 84 sub progress_cb {
191C<ClientHello> transaction. 85 my ($self, $txn, $type, $attr) = @_;
192 86
193=end 87 warn "progress<$txn,$type," . (join ":", %$attr) . ">\n";
88 }
194 89
195=cut 90=cut
196 91
197sub new { 92sub new {
198 my $class = shift; 93 my $class = shift;
199 my $self = bless { @_ }, $class; 94 my $self = bless { @_ }, $class;
200 95
201 $self->{host} ||= $ENV{FREDHOST} || "127.0.0.1"; 96 $self->{host} ||= $ENV{FREDHOST} || "127.0.0.1";
202 $self->{port} ||= $ENV{FREDPORT} || 8481; 97 $self->{port} ||= $ENV{FREDPORT} || 8481;
203 98
204 #$self->{nodehello} = $self->client_hello
205 # or croak "unable to get nodehello from node\n";
206
207 $self; 99 $self;
208} 100}
209 101
210sub progress { 102sub progress {
211 my ($self, $txn, $type, $attr) = @_; 103 my ($self, $txn, $type, $attr) = @_;
212 #warn "progress<$txn,$type," . (join ":", %$attr) . ">\n";
213}
214 104
105 $self->{progress}->($self, $txn, $type, $attr)
106 if $self->{progress};
107}
108
215=item $txn = $fcp->txn(type => attr => val,...) 109=item $txn = $fcp->txn (type => attr => val,...)
216 110
217The low-level interface to transactions. Don't use it. 111The low-level interface to transactions. Don't use it unless you have
218 112"special needs". Instead, use predefiend transactions like this:
219Here are some examples of using transactions:
220 113
221The blocking case, no (visible) transactions involved: 114The blocking case, no (visible) transactions involved:
222 115
223 my $nodehello = $fcp->client_hello; 116 my $nodehello = $fcp->client_hello;
224 117
243sub txn { 136sub txn {
244 my ($self, $type, %attr) = @_; 137 my ($self, $type, %attr) = @_;
245 138
246 $type = touc $type; 139 $type = touc $type;
247 140
248 my $txn = "Net::FCP::Txn::$type"->new(fcp => $self, type => tolc $type, attr => \%attr); 141 my $txn = "Net::FCP::Txn::$type"->new (fcp => $self, type => tolc $type, attr => \%attr);
249 142
250 $txn; 143 $txn;
251} 144}
252 145
253{ # transactions 146{ # transactions
318 211
319=item $txn = $fcp->txn_generate_chk ($metadata, $data[, $cipher]) 212=item $txn = $fcp->txn_generate_chk ($metadata, $data[, $cipher])
320 213
321=item $uri = $fcp->generate_chk ($metadata, $data[, $cipher]) 214=item $uri = $fcp->generate_chk ($metadata, $data[, $cipher])
322 215
323Calculcates a CHK, given the metadata and data. C<$cipher> is either 216Calculates a CHK, given the metadata and data. C<$cipher> is either
324C<Rijndael> or C<Twofish>, with the latter being the default. 217C<Rijndael> or C<Twofish>, with the latter being the default.
325 218
326=cut 219=cut
327 220
328$txn->(generate_chk => sub { 221$txn->(generate_chk => sub {
329 my ($self, $metadata, $data, $cipher) = @_; 222 my ($self, $metadata, $data, $cipher) = @_;
330 223
224 $metadata = Net::FCP::Metadata::build_metadata $metadata;
225
331 $self->txn (generate_chk => 226 $self->txn (generate_chk =>
332 data => "$metadata$data", 227 data => "$metadata$data",
333 metadata_length => length $metadata, 228 metadata_length => xeh length $metadata,
334 cipher => $cipher || "Twofish"); 229 cipher => $cipher || "Twofish");
335}); 230});
336 231
337=item $txn = $fcp->txn_generate_svk_pair 232=item $txn = $fcp->txn_generate_svk_pair
338 233
339=item ($public, $private) = @{ $fcp->generate_svk_pair } 234=item ($public, $private, $crypto) = @{ $fcp->generate_svk_pair }
340 235
341Creates a new SVK pair. Returns an arrayref. 236Creates a new SVK pair. Returns an arrayref with the public key, the
237private key and a crypto key, which is just additional entropy.
342 238
343 [ 239 [
344 "hKs0-WDQA4pVZyMPKNFsK1zapWY", 240 "acLx4dux9fvvABH15Gk6~d3I-yw",
345 "ZnmvMITaTXBMFGl4~jrjuyWxOWg" 241 "cPoDkDMXDGSMM32plaPZDhJDxSs",
242 "BH7LXCov0w51-y9i~BoB3g",
346 ] 243 ]
244
245A private key (for inserting) can be constructed like this:
246
247 SSK@<private_key>,<crypto_key>/<name>
248
249It can be used to insert data. The corresponding public key looks like this:
250
251 SSK@<public_key>PAgM,<crypto_key>/<name>
252
253Watch out for the C<PAgM>-part!
347 254
348=cut 255=cut
349 256
350$txn->(generate_svk_pair => sub { 257$txn->(generate_svk_pair => sub {
351 my ($self) = @_; 258 my ($self) = @_;
352 259
353 $self->txn ("generate_svk_pair"); 260 $self->txn ("generate_svk_pair");
354}); 261});
355 262
356=item $txn = $fcp->txn_insert_private_key ($private) 263=item $txn = $fcp->txn_invert_private_key ($private)
357 264
358=item $public = $fcp->insert_private_key ($private) 265=item $public = $fcp->invert_private_key ($private)
359 266
360Inserts a private key. $private can be either an insert URI (must start 267Inverts a private key (returns the public key). C<$private> can be either
361with C<freenet:SSK@>) or a raw private key (i.e. the private value you get 268an insert URI (must start with C<freenet:SSK@>) or a raw private key (i.e.
362back from C<generate_svk_pair>). 269the private value you get back from C<generate_svk_pair>).
363 270
364Returns the public key. 271Returns the public key.
365 272
366UNTESTED.
367
368=cut 273=cut
369 274
370$txn->(insert_private_key => sub { 275$txn->(invert_private_key => sub {
371 my ($self, $privkey) = @_; 276 my ($self, $privkey) = @_;
372 277
373 $self->txn (invert_private_key => private => $privkey); 278 $self->txn (invert_private_key => private => $privkey);
374}); 279});
375 280
378=item $length = $fcp->get_size ($uri) 283=item $length = $fcp->get_size ($uri)
379 284
380Finds and returns the size (rounded up to the nearest power of two) of the 285Finds and returns the size (rounded up to the nearest power of two) of the
381given document. 286given document.
382 287
383UNTESTED.
384
385=cut 288=cut
386 289
387$txn->(get_size => sub { 290$txn->(get_size => sub {
388 my ($self, $uri) = @_; 291 my ($self, $uri) = @_;
389 292
392 295
393=item $txn = $fcp->txn_client_get ($uri [, $htl = 15 [, $removelocal = 0]]) 296=item $txn = $fcp->txn_client_get ($uri [, $htl = 15 [, $removelocal = 0]])
394 297
395=item ($metadata, $data) = @{ $fcp->client_get ($uri, $htl, $removelocal) 298=item ($metadata, $data) = @{ $fcp->client_get ($uri, $htl, $removelocal)
396 299
397Fetches a (small, as it should fit into memory) file from 300Fetches a (small, as it should fit into memory) key content block from
398freenet. C<$meta> is the metadata (as returned by C<parse_metadata> or 301freenet. C<$meta> is a C<Net::FCP::Metadata> object or C<undef>).
399C<undef>).
400 302
401Due to the overhead, a better method to download big files should be used. 303The C<$uri> should begin with C<freenet:>, but the scheme is currently
304added, if missing.
402 305
403 my ($meta, $data) = @{ 306 my ($meta, $data) = @{
404 $fcp->client_get ( 307 $fcp->client_get (
405 "freenet:CHK@hdXaxkwZ9rA8-SidT0AN-bniQlgPAwI,XdCDmBuGsd-ulqbLnZ8v~w" 308 "freenet:CHK@hdXaxkwZ9rA8-SidT0AN-bniQlgPAwI,XdCDmBuGsd-ulqbLnZ8v~w"
406 ) 309 )
409=cut 312=cut
410 313
411$txn->(client_get => sub { 314$txn->(client_get => sub {
412 my ($self, $uri, $htl, $removelocal) = @_; 315 my ($self, $uri, $htl, $removelocal) = @_;
413 316
317 $uri =~ s/^freenet://; $uri = "freenet:$uri";
318
414 $self->txn (client_get => URI => $uri, hops_to_live => (defined $htl ? $htl :15), 319 $self->txn (client_get => URI => $uri, hops_to_live => xeh (defined $htl ? $htl : 15),
415 remove_local_key => $removelocal ? "true" : "false"); 320 remove_local_key => $removelocal ? "true" : "false");
416}); 321});
417 322
418=item $txn = $fcp->txn_client_put ($uri, $metadata, $data, $htl, $removelocal) 323=item $txn = $fcp->txn_client_put ($uri, $metadata, $data, $htl, $removelocal)
419 324
420=item my $uri = $fcp->client_put ($uri, $metadata, $data, $htl, $removelocal); 325=item my $uri = $fcp->client_put ($uri, $metadata, $data, $htl, $removelocal);
421 326
422Insert a new key. If the client is inserting a CHK, the URI may be 327Insert a new key. If the client is inserting a CHK, the URI may be
423abbreviated as just CHK@. In this case, the node will calculate the 328abbreviated as just CHK@. In this case, the node will calculate the
424CHK. 329CHK. If the key is a private SSK key, the node will calculcate the public
330key and the resulting public URI.
425 331
426C<$meta> can be a reference or a string (ONLY THE STRING CASE IS IMPLEMENTED!). 332C<$meta> can be a hash reference (same format as returned by
333C<Net::FCP::parse_metadata>) or a string.
427 334
428THIS INTERFACE IS UNTESTED AND SUBJECT TO CHANGE. 335The result is an arrayref with the keys C<uri>, C<public_key> and C<private_key>.
429 336
430=cut 337=cut
431 338
432$txn->(client_put => sub { 339$txn->(client_put => sub {
433 my ($self, $uri, $meta, $data, $htl, $removelocal) = @_; 340 my ($self, $uri, $metadata, $data, $htl, $removelocal) = @_;
434 341
435 $self->txn (client_put => URI => $uri, hops_to_live => (defined $htl ? $htl :15), 342 $metadata = Net::FCP::Metadata::build_metadata $metadata;
343 $uri =~ s/^freenet://; $uri = "freenet:$uri";
344
345 $self->txn (client_put => URI => $uri,
346 hops_to_live => xeh (defined $htl ? $htl : 15),
436 remove_local_key => $removelocal ? "true" : "false", 347 remove_local_key => $removelocal ? "true" : "false",
437 data => "$meta$data", metadata_length => length $meta); 348 data => "$metadata$data", metadata_length => xeh length $metadata);
438}); 349});
439 350
440} # transactions 351} # transactions
441 352
442=item MISSING: (ClientPut), InsretKey
443
444=back 353=back
445 354
446=head2 THE Net::FCP::Txn CLASS 355=head2 THE Net::FCP::Txn CLASS
447 356
448All requests (or transactions) are executed in a asynchroneous way (LIE: 357All requests (or transactions) are executed in a asynchronous way. For
449uploads are blocking). For each request, a C<Net::FCP::Txn> object is 358each request, a C<Net::FCP::Txn> object is created (worse: a tcp
450created (worse: a tcp connection is created, too). 359connection is created, too).
451 360
452For each request there is actually a different subclass (and it's possible 361For each request there is actually a different subclass (and it's possible
453to subclass these, although of course not documented). 362to subclass these, although of course not documented).
454 363
455The most interesting method is C<result>. 364The most interesting method is C<result>.
471 380
472sub new { 381sub new {
473 my $class = shift; 382 my $class = shift;
474 my $self = bless { @_ }, $class; 383 my $self = bless { @_ }, $class;
475 384
476 $self->{signal} = $EVENT->new_signal; 385 $self->{signal} = AnyEvent->condvar;
477 386
478 $self->{fcp}{txn}{$self} = $self; 387 $self->{fcp}{txn}{$self} = $self;
479 388
480 my $attr = ""; 389 my $attr = "";
481 my $data = delete $self->{attr}{data}; 390 my $data = delete $self->{attr}{data};
493 402
494 socket my $fh, PF_INET, SOCK_STREAM, 0 403 socket my $fh, PF_INET, SOCK_STREAM, 0
495 or Carp::croak "unable to create new tcp socket: $!"; 404 or Carp::croak "unable to create new tcp socket: $!";
496 binmode $fh, ":raw"; 405 binmode $fh, ":raw";
497 fcntl $fh, F_SETFL, O_NONBLOCK; 406 fcntl $fh, F_SETFL, O_NONBLOCK;
498 connect $fh, (sockaddr_in $self->{fcp}{port}, inet_aton $self->{fcp}{host}) 407 connect $fh, (sockaddr_in $self->{fcp}{port}, inet_aton $self->{fcp}{host});
499 and !$!{EWOULDBLOCK}
500 and !$!{EINPROGRESS}
501 and Carp::croak "FCP::txn: unable to connect to $self->{fcp}{host}:$self->{fcp}{port}: $!\n"; 408# and Carp::croak "FCP::txn: unable to connect to $self->{fcp}{host}:$self->{fcp}{port}: $!\n";
502 409
503 $self->{sbuf} = 410 $self->{sbuf} =
504 "\x00\x00\x00\x02" 411 "\x00\x00\x00\x02"
505 . (Net::FCP::touc $self->{type}) 412 . (Net::FCP::touc $self->{type})
506 . "\012$attr$data"; 413 . "\012$attr$data";
507 414
508 #shutdown $fh, 1; # freenet buggy?, well, it's java... 415 #shutdown $fh, 1; # freenet buggy?, well, it's java...
509 416
510 $self->{fh} = $fh; 417 $self->{fh} = $fh;
511 418
512 $self->{w} = $EVENT->new_from_fh ($fh)->cb(sub { $self->fh_ready_w })->poll(0, 1, 1); 419 $self->{w} = AnyEvent->io (fh => $fh, poll => 'w', cb => sub { $self->fh_ready_w });
513 420
514 $self; 421 $self;
515} 422}
516 423
517=item $txn = $txn->cb ($coderef) 424=item $txn = $txn->cb ($coderef)
553 $self; 460 $self;
554} 461}
555 462
556=item $txn->cancel (%attr) 463=item $txn->cancel (%attr)
557 464
558Cancels the operation with a C<cancel> exception anf the given attributes 465Cancels the operation with a C<cancel> exception and the given attributes
559(consider at least giving the attribute C<reason>). 466(consider at least giving the attribute C<reason>).
560 467
561UNTESTED. 468UNTESTED.
562 469
563=cut 470=cut
576 483
577 if ($len > 0) { 484 if ($len > 0) {
578 substr $self->{sbuf}, 0, $len, ""; 485 substr $self->{sbuf}, 0, $len, "";
579 unless (length $self->{sbuf}) { 486 unless (length $self->{sbuf}) {
580 fcntl $self->{fh}, F_SETFL, 0; 487 fcntl $self->{fh}, F_SETFL, 0;
581 $self->{w}->cb(sub { $self->fh_ready_r })->poll (1, 0, 1); 488 $self->{w} = AnyEvent->io (fh => $self->{fh}, poll => 'r', cb => sub { $self->fh_ready_r });
582 } 489 }
583 } elsif (defined $len) { 490 } elsif (defined $len) {
584 $self->throw (Net::FCP::Exception->new (network_error => { reason => "unexpected end of file while writing" })); 491 $self->throw (Net::FCP::Exception->new (network_error => { reason => "unexpected end of file while writing" }));
585 } else { 492 } else {
586 $self->throw (Net::FCP::Exception->new (network_error => { reason => "$!" })); 493 $self->throw (Net::FCP::Exception->new (network_error => { reason => "$!" }));
588} 495}
589 496
590sub fh_ready_r { 497sub fh_ready_r {
591 my ($self) = @_; 498 my ($self) = @_;
592 499
593 if (sysread $self->{fh}, $self->{buf}, 65536, length $self->{buf}) { 500 if (sysread $self->{fh}, $self->{buf}, 16384 + 1024, length $self->{buf}) {
594 for (;;) { 501 for (;;) {
595 if ($self->{datalen}) { 502 if ($self->{datalen}) {
596 #warn "expecting new datachunk $self->{datalen}, got ".(length $self->{buf})."\n";#d# 503 #warn "expecting new datachunk $self->{datalen}, got ".(length $self->{buf})."\n";#d#
597 if (length $self->{buf} >= $self->{datalen}) { 504 if (length $self->{buf} >= $self->{datalen}) {
598 $self->rcv_data (substr $self->{buf}, 0, delete $self->{datalen}, ""); 505 $self->rcv_data (substr $self->{buf}, 0, delete $self->{datalen}, "");
651 my ($self, $result) = @_; 558 my ($self, $result) = @_;
652 559
653 unless (exists $self->{result}) { 560 unless (exists $self->{result}) {
654 $self->{result} = $result; 561 $self->{result} = $result;
655 $self->{cb}->($self) if exists $self->{cb}; 562 $self->{cb}->($self) if exists $self->{cb};
656 $self->{signal}->send; 563 $self->{signal}->broadcast;
657 } 564 }
658} 565}
659 566
660sub eof { 567sub eof {
661 my ($self) = @_; 568 my ($self) = @_;
672 } 579 }
673} 580}
674 581
675sub progress { 582sub progress {
676 my ($self, $type, $attr) = @_; 583 my ($self, $type, $attr) = @_;
584
677 $self->{fcp}->progress ($self, $type, $attr); 585 $self->{fcp}->progress ($self, $type, $attr);
678} 586}
679 587
680=item $result = $txn->result 588=item $result = $txn->result
681 589
682Waits until a result is available and then returns it. 590Waits until a result is available and then returns it.
683 591
684This waiting is (depending on your event model) not very efficient, as it 592This waiting is (depending on your event model) not very efficient, as it
685is done outside the "mainloop". 593is done outside the "mainloop". The biggest problem, however, is that it's
594blocking one thread of execution. Try to use the callback mechanism, if
595possible, and call result from within the callback (or after is has been
596run), as then no waiting is necessary.
686 597
687=cut 598=cut
688 599
689sub result { 600sub result {
690 my ($self) = @_; 601 my ($self) = @_;
730 641
731use base Net::FCP::Txn; 642use base Net::FCP::Txn;
732 643
733sub rcv_success { 644sub rcv_success {
734 my ($self, $attr) = @_; 645 my ($self, $attr) = @_;
735 $self->set_result ([$attr->{PublicKey}, $attr->{PrivateKey}]); 646 $self->set_result ([$attr->{public_key}, $attr->{private_key}, $attr->{crypto_key}]);
736} 647}
737 648
738package Net::FCP::Txn::InsertPrivateKey; 649package Net::FCP::Txn::InvertPrivateKey;
739 650
740use base Net::FCP::Txn; 651use base Net::FCP::Txn;
741 652
742sub rcv_success { 653sub rcv_success {
743 my ($self, $attr) = @_; 654 my ($self, $attr) = @_;
744 $self->set_result ($attr->{PublicKey}); 655 $self->set_result ($attr->{public_key});
745} 656}
746 657
747package Net::FCP::Txn::GetSize; 658package Net::FCP::Txn::GetSize;
748 659
749use base Net::FCP::Txn; 660use base Net::FCP::Txn;
750 661
751sub rcv_success { 662sub rcv_success {
752 my ($self, $attr) = @_; 663 my ($self, $attr) = @_;
753 $self->set_result ($attr->{Length}); 664 $self->set_result (hex $attr->{length});
754} 665}
755 666
756package Net::FCP::Txn::GetPut; 667package Net::FCP::Txn::GetPut;
757 668
758# base class for get and put 669# base class for get and put
759 670
760use base Net::FCP::Txn; 671use base Net::FCP::Txn;
761 672
762*rcv_uri_error = \&Net::FCP::Txn::rcv_throw_exception; 673*rcv_uri_error = \&Net::FCP::Txn::rcv_throw_exception;
763*rcv_route_not_found = \&Net::FCP::Txn::rcv_throw_exception; 674*rcv_route_not_found = \&Net::FCP::Txn::rcv_throw_exception;
764 675
765sub rcv_restarted { 676sub rcv_restarted {
766 my ($self, $attr, $type) = @_; 677 my ($self, $attr, $type) = @_;
767 678
768 delete $self->{datalength}; 679 delete $self->{datalength};
785 696
786 $self->progress ("data", { chunk => length $chunk, received => length $self->{data}, total => $self->{datalength} }); 697 $self->progress ("data", { chunk => length $chunk, received => length $self->{data}, total => $self->{datalength} });
787 698
788 if ($self->{datalength} == length $self->{data}) { 699 if ($self->{datalength} == length $self->{data}) {
789 my $data = delete $self->{data}; 700 my $data = delete $self->{data};
790 my $meta = Net::FCP::parse_metadata substr $data, 0, $self->{metalength}, ""; 701 my $meta = new Net::FCP::Metadata (substr $data, 0, $self->{metalength}, "");
791 702
792 $self->set_result ([$meta, $data]); 703 $self->set_result ([$meta, $data]);
793 $self->eof; 704 $self->eof;
794 } 705 }
795} 706}
806package Net::FCP::Txn::ClientPut; 717package Net::FCP::Txn::ClientPut;
807 718
808use base Net::FCP::Txn::GetPut; 719use base Net::FCP::Txn::GetPut;
809 720
810*rcv_size_error = \&Net::FCP::Txn::rcv_throw_exception; 721*rcv_size_error = \&Net::FCP::Txn::rcv_throw_exception;
811*rcv_key_collision = \&Net::FCP::Txn::rcv_throw_exception;
812 722
813sub rcv_pending { 723sub rcv_pending {
814 my ($self, $attr, $type) = @_; 724 my ($self, $attr, $type) = @_;
815 $self->progress ($type, $attr); 725 $self->progress ($type, $attr);
816} 726}
817 727
818sub rcv_success { 728sub rcv_success {
819 my ($self, $attr, $type) = @_; 729 my ($self, $attr, $type) = @_;
820 $self->set_result ($attr); 730 $self->set_result ($attr);
731}
732
733sub rcv_key_collision {
734 my ($self, $attr, $type) = @_;
735 $self->set_result ({ key_collision => 1, %$attr });
821} 736}
822 737
823=back 738=back
824 739
825=head2 The Net::FCP::Exception CLASS 740=head2 The Net::FCP::Exception CLASS
893 808
894=head1 BUGS 809=head1 BUGS
895 810
896=head1 AUTHOR 811=head1 AUTHOR
897 812
898 Marc Lehmann <pcg@goof.com> 813 Marc Lehmann <schmorp@schmorp.de>
899 http://www.goof.com/pcg/marc/ 814 http://home.schmorp.de/
900 815
901=cut 816=cut
902 817
903package Net::FCP::Event::Auto; 8181
904 819
905my @models = (
906 [Coro => Coro::Event:: ],
907 [Event => Event::],
908 [Glib => Glib:: ],
909 [Tk => Tk::],
910);
911
912sub AUTOLOAD {
913 $AUTOLOAD =~ s/.*://;
914
915 for (@models) {
916 my ($model, $package) = @$_;
917 if (defined ${"$package\::VERSION"}) {
918 $EVENT = "Net::FCP::Event::$model";
919 eval "require $EVENT"; die if $@;
920 goto &{"$EVENT\::$AUTOLOAD"};
921 }
922 }
923
924 for (@models) {
925 my ($model, $package) = @$_;
926 $EVENT = "Net::FCP::Event::$model";
927 if (eval "require $EVENT") {
928 goto &{"$EVENT\::$AUTOLOAD"};
929 }
930 }
931
932 die "No event module selected for Net::FCP and autodetect failed. Install any of these: Coro, Event, Glib or Tk.";
933}
934
9351;
936

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines