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

Comparing Net-FCP/FCP.pm (file contents):
Revision 1.23 by root, Wed Sep 17 08:57:32 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# the opposite of hex
109sub xeh($) {
110 sprintf "%x", $_[0];
111}
112
113=item $meta = Net::FCP::parse_metadata $string
114
115Parse a metadata string and return it.
116
117The metadata will be a hashref with key C<version> (containing the
118mandatory version header entries) and key C<raw> containing the original
119metadata string.
120
121All other headers are represented by arrayrefs (they can be repeated).
122
123Since this description is confusing, here is a rather verbose example of a
124parsed manifest:
125
126 (
127 raw => "Version...",
128 version => { revision => 1 },
129 document => [
130 {
131 info => { format" => "image/jpeg" },
132 name => "background.jpg",
133 redirect => { target => "freenet:CHK\@ZcagI,ra726bSw" },
134 },
135 {
136 info => { format" => "text/html" },
137 name => ".next",
138 redirect => { target => "freenet:SSK\@ilUPAgM/TFEE/3" },
139 },
140 {
141 info => { format" => "text/html" },
142 redirect => { target => "freenet:CHK\@8M8Po8ucwI,8xA" },
143 }
144 ]
145 )
146
147=cut
148
149sub parse_metadata {
150 my $data = shift;
151 my $meta = { raw => $data };
152
153 if ($data =~ /^Version\015?\012/gc) {
154 my $hdr = $meta->{version} = {};
155
156 for (;;) {
157 while ($data =~ /\G([^=\015\012]+)=([^\015\012]*)\015?\012/gc) {
158 my ($k, $v) = ($1, $2);
159 my @p = split /\./, tolc $k, 3;
160
161 $hdr->{$p[0]} = $v if @p == 1; # lamest code I ever wrote
162 $hdr->{$p[0]}{$p[1]} = $v if @p == 2;
163 $hdr->{$p[0]}{$p[1]}{$p[2]} = $v if @p == 3;
164 die "FATAL: 4+ dot metadata" if @p >= 4;
165 }
166
167 if ($data =~ /\GEndPart\015?\012/gc) {
168 # nop
169 } elsif ($data =~ /\GEnd(\015?\012|$)/gc) {
170 last;
171 } elsif ($data =~ /\G([A-Za-z0-9.\-]+)\015?\012/gcs) {
172 push @{$meta->{tolc $1}}, $hdr = {};
173 } elsif ($data =~ /\G(.*)/gcs) {
174 print STDERR "metadata format error ($1), please report this string: <<$data>>";
175 die "metadata format error";
176 }
177 }
178 }
179
180 #$meta->{tail} = substr $data, pos $data;
181
182 $meta;
183}
184
185=item $fcp = new Net::FCP [host => $host][, port => $port] 72=item $fcp = new Net::FCP [host => $host][, port => $port][, progress => \&cb]
186 73
187Create 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
188127.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>).
189 76
190Connections are virtual because no persistent physical connection is 77Connections are virtual because no persistent physical connection is
191established. 78established.
192 79
193=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:
194 83
195However, the existance of the node is checked by executing a 84 sub progress_cb {
196C<ClientHello> transaction. 85 my ($self, $txn, $type, $attr) = @_;
197 86
198=end 87 warn "progress<$txn,$type," . (join ":", %$attr) . ">\n";
88 }
199 89
200=cut 90=cut
201 91
202sub new { 92sub new {
203 my $class = shift; 93 my $class = shift;
204 my $self = bless { @_ }, $class; 94 my $self = bless { @_ }, $class;
205 95
206 $self->{host} ||= $ENV{FREDHOST} || "127.0.0.1"; 96 $self->{host} ||= $ENV{FREDHOST} || "127.0.0.1";
207 $self->{port} ||= $ENV{FREDPORT} || 8481; 97 $self->{port} ||= $ENV{FREDPORT} || 8481;
208 98
209 #$self->{nodehello} = $self->client_hello
210 # or croak "unable to get nodehello from node\n";
211
212 $self; 99 $self;
213} 100}
214 101
215sub progress { 102sub progress {
216 my ($self, $txn, $type, $attr) = @_; 103 my ($self, $txn, $type, $attr) = @_;
217 #warn "progress<$txn,$type," . (join ":", %$attr) . ">\n";
218}
219 104
105 $self->{progress}->($self, $txn, $type, $attr)
106 if $self->{progress};
107}
108
220=item $txn = $fcp->txn(type => attr => val,...) 109=item $txn = $fcp->txn (type => attr => val,...)
221 110
222The low-level interface to transactions. Don't use it. 111The low-level interface to transactions. Don't use it unless you have
223 112"special needs". Instead, use predefiend transactions like this:
224Here are some examples of using transactions:
225 113
226The blocking case, no (visible) transactions involved: 114The blocking case, no (visible) transactions involved:
227 115
228 my $nodehello = $fcp->client_hello; 116 my $nodehello = $fcp->client_hello;
229 117
248sub txn { 136sub txn {
249 my ($self, $type, %attr) = @_; 137 my ($self, $type, %attr) = @_;
250 138
251 $type = touc $type; 139 $type = touc $type;
252 140
253 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);
254 142
255 $txn; 143 $txn;
256} 144}
257 145
258{ # transactions 146{ # transactions
323 211
324=item $txn = $fcp->txn_generate_chk ($metadata, $data[, $cipher]) 212=item $txn = $fcp->txn_generate_chk ($metadata, $data[, $cipher])
325 213
326=item $uri = $fcp->generate_chk ($metadata, $data[, $cipher]) 214=item $uri = $fcp->generate_chk ($metadata, $data[, $cipher])
327 215
328Calculcates a CHK, given the metadata and data. C<$cipher> is either 216Calculates a CHK, given the metadata and data. C<$cipher> is either
329C<Rijndael> or C<Twofish>, with the latter being the default. 217C<Rijndael> or C<Twofish>, with the latter being the default.
330 218
331=cut 219=cut
332 220
333$txn->(generate_chk => sub { 221$txn->(generate_chk => sub {
334 my ($self, $metadata, $data, $cipher) = @_; 222 my ($self, $metadata, $data, $cipher) = @_;
335 223
224 $metadata = Net::FCP::Metadata::build_metadata $metadata;
225
336 $self->txn (generate_chk => 226 $self->txn (generate_chk =>
337 data => "$metadata$data", 227 data => "$metadata$data",
338 metadata_length => xeh length $metadata, 228 metadata_length => xeh length $metadata,
339 cipher => $cipher || "Twofish"); 229 cipher => $cipher || "Twofish");
340}); 230});
341 231
342=item $txn = $fcp->txn_generate_svk_pair 232=item $txn = $fcp->txn_generate_svk_pair
343 233
344=item ($public, $private) = @{ $fcp->generate_svk_pair } 234=item ($public, $private, $crypto) = @{ $fcp->generate_svk_pair }
345 235
346Creates 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.
347 238
348 [ 239 [
349 "hKs0-WDQA4pVZyMPKNFsK1zapWY", 240 "acLx4dux9fvvABH15Gk6~d3I-yw",
350 "ZnmvMITaTXBMFGl4~jrjuyWxOWg" 241 "cPoDkDMXDGSMM32plaPZDhJDxSs",
242 "BH7LXCov0w51-y9i~BoB3g",
351 ] 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!
352 254
353=cut 255=cut
354 256
355$txn->(generate_svk_pair => sub { 257$txn->(generate_svk_pair => sub {
356 my ($self) = @_; 258 my ($self) = @_;
357 259
358 $self->txn ("generate_svk_pair"); 260 $self->txn ("generate_svk_pair");
359}); 261});
360 262
361=item $txn = $fcp->txn_insert_private_key ($private) 263=item $txn = $fcp->txn_invert_private_key ($private)
362 264
363=item $public = $fcp->insert_private_key ($private) 265=item $public = $fcp->invert_private_key ($private)
364 266
365Inserts 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
366with 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.
367back from C<generate_svk_pair>). 269the private value you get back from C<generate_svk_pair>).
368 270
369Returns the public key. 271Returns the public key.
370 272
371UNTESTED.
372
373=cut 273=cut
374 274
375$txn->(insert_private_key => sub { 275$txn->(invert_private_key => sub {
376 my ($self, $privkey) = @_; 276 my ($self, $privkey) = @_;
377 277
378 $self->txn (invert_private_key => private => $privkey); 278 $self->txn (invert_private_key => private => $privkey);
379}); 279});
380 280
383=item $length = $fcp->get_size ($uri) 283=item $length = $fcp->get_size ($uri)
384 284
385Finds 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
386given document. 286given document.
387 287
388UNTESTED.
389
390=cut 288=cut
391 289
392$txn->(get_size => sub { 290$txn->(get_size => sub {
393 my ($self, $uri) = @_; 291 my ($self, $uri) = @_;
394 292
397 295
398=item $txn = $fcp->txn_client_get ($uri [, $htl = 15 [, $removelocal = 0]]) 296=item $txn = $fcp->txn_client_get ($uri [, $htl = 15 [, $removelocal = 0]])
399 297
400=item ($metadata, $data) = @{ $fcp->client_get ($uri, $htl, $removelocal) 298=item ($metadata, $data) = @{ $fcp->client_get ($uri, $htl, $removelocal)
401 299
402Fetches a (small, as it should fit into memory) file from 300Fetches a (small, as it should fit into memory) key content block from
403freenet. 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>).
404C<undef>).
405 302
406Due 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.
407 305
408 my ($meta, $data) = @{ 306 my ($meta, $data) = @{
409 $fcp->client_get ( 307 $fcp->client_get (
410 "freenet:CHK@hdXaxkwZ9rA8-SidT0AN-bniQlgPAwI,XdCDmBuGsd-ulqbLnZ8v~w" 308 "freenet:CHK@hdXaxkwZ9rA8-SidT0AN-bniQlgPAwI,XdCDmBuGsd-ulqbLnZ8v~w"
411 ) 309 )
414=cut 312=cut
415 313
416$txn->(client_get => sub { 314$txn->(client_get => sub {
417 my ($self, $uri, $htl, $removelocal) = @_; 315 my ($self, $uri, $htl, $removelocal) = @_;
418 316
317 $uri =~ s/^freenet://; $uri = "freenet:$uri";
318
419 $self->txn (client_get => URI => $uri, hops_to_live => xeh (defined $htl ? $htl : 15), 319 $self->txn (client_get => URI => $uri, hops_to_live => xeh (defined $htl ? $htl : 15),
420 remove_local_key => $removelocal ? "true" : "false"); 320 remove_local_key => $removelocal ? "true" : "false");
421}); 321});
422 322
423=item $txn = $fcp->txn_client_put ($uri, $metadata, $data, $htl, $removelocal) 323=item $txn = $fcp->txn_client_put ($uri, $metadata, $data, $htl, $removelocal)
424 324
425=item my $uri = $fcp->client_put ($uri, $metadata, $data, $htl, $removelocal); 325=item my $uri = $fcp->client_put ($uri, $metadata, $data, $htl, $removelocal);
426 326
427Insert 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
428abbreviated as just CHK@. In this case, the node will calculate the 328abbreviated as just CHK@. In this case, the node will calculate the
429CHK. 329CHK. If the key is a private SSK key, the node will calculcate the public
330key and the resulting public URI.
430 331
431C<$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.
432 334
433THIS INTERFACE IS UNTESTED AND SUBJECT TO CHANGE. 335The result is an arrayref with the keys C<uri>, C<public_key> and C<private_key>.
434 336
435=cut 337=cut
436 338
437$txn->(client_put => sub { 339$txn->(client_put => sub {
438 my ($self, $uri, $meta, $data, $htl, $removelocal) = @_; 340 my ($self, $uri, $metadata, $data, $htl, $removelocal) = @_;
439 341
440 $self->txn (client_put => URI => $uri, xeh (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),
441 remove_local_key => $removelocal ? "true" : "false", 347 remove_local_key => $removelocal ? "true" : "false",
442 data => "$meta$data", metadata_length => xeh length $meta); 348 data => "$metadata$data", metadata_length => xeh length $metadata);
443}); 349});
444 350
445} # transactions 351} # transactions
446
447=item MISSING: (ClientPut), InsertKey
448 352
449=back 353=back
450 354
451=head2 THE Net::FCP::Txn CLASS 355=head2 THE Net::FCP::Txn CLASS
452 356
476 380
477sub new { 381sub new {
478 my $class = shift; 382 my $class = shift;
479 my $self = bless { @_ }, $class; 383 my $self = bless { @_ }, $class;
480 384
481 $self->{signal} = $EVENT->new_signal; 385 $self->{signal} = AnyEvent->condvar;
482 386
483 $self->{fcp}{txn}{$self} = $self; 387 $self->{fcp}{txn}{$self} = $self;
484 388
485 my $attr = ""; 389 my $attr = "";
486 my $data = delete $self->{attr}{data}; 390 my $data = delete $self->{attr}{data};
498 402
499 socket my $fh, PF_INET, SOCK_STREAM, 0 403 socket my $fh, PF_INET, SOCK_STREAM, 0
500 or Carp::croak "unable to create new tcp socket: $!"; 404 or Carp::croak "unable to create new tcp socket: $!";
501 binmode $fh, ":raw"; 405 binmode $fh, ":raw";
502 fcntl $fh, F_SETFL, O_NONBLOCK; 406 fcntl $fh, F_SETFL, O_NONBLOCK;
503 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});
504 and !$!{EWOULDBLOCK}
505 and !$!{EINPROGRESS}
506 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";
507 409
508 $self->{sbuf} = 410 $self->{sbuf} =
509 "\x00\x00\x00\x02" 411 "\x00\x00\x00\x02"
510 . (Net::FCP::touc $self->{type}) 412 . (Net::FCP::touc $self->{type})
511 . "\012$attr$data"; 413 . "\012$attr$data";
512 414
513 #shutdown $fh, 1; # freenet buggy?, well, it's java... 415 #shutdown $fh, 1; # freenet buggy?, well, it's java...
514 416
515 $self->{fh} = $fh; 417 $self->{fh} = $fh;
516 418
517 $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 });
518 420
519 $self; 421 $self;
520} 422}
521 423
522=item $txn = $txn->cb ($coderef) 424=item $txn = $txn->cb ($coderef)
558 $self; 460 $self;
559} 461}
560 462
561=item $txn->cancel (%attr) 463=item $txn->cancel (%attr)
562 464
563Cancels the operation with a C<cancel> exception anf the given attributes 465Cancels the operation with a C<cancel> exception and the given attributes
564(consider at least giving the attribute C<reason>). 466(consider at least giving the attribute C<reason>).
565 467
566UNTESTED. 468UNTESTED.
567 469
568=cut 470=cut
581 483
582 if ($len > 0) { 484 if ($len > 0) {
583 substr $self->{sbuf}, 0, $len, ""; 485 substr $self->{sbuf}, 0, $len, "";
584 unless (length $self->{sbuf}) { 486 unless (length $self->{sbuf}) {
585 fcntl $self->{fh}, F_SETFL, 0; 487 fcntl $self->{fh}, F_SETFL, 0;
586 $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 });
587 } 489 }
588 } elsif (defined $len) { 490 } elsif (defined $len) {
589 $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" }));
590 } else { 492 } else {
591 $self->throw (Net::FCP::Exception->new (network_error => { reason => "$!" })); 493 $self->throw (Net::FCP::Exception->new (network_error => { reason => "$!" }));
593} 495}
594 496
595sub fh_ready_r { 497sub fh_ready_r {
596 my ($self) = @_; 498 my ($self) = @_;
597 499
598 if (sysread $self->{fh}, $self->{buf}, 65536, length $self->{buf}) { 500 if (sysread $self->{fh}, $self->{buf}, 16384 + 1024, length $self->{buf}) {
599 for (;;) { 501 for (;;) {
600 if ($self->{datalen}) { 502 if ($self->{datalen}) {
601 #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#
602 if (length $self->{buf} >= $self->{datalen}) { 504 if (length $self->{buf} >= $self->{datalen}) {
603 $self->rcv_data (substr $self->{buf}, 0, delete $self->{datalen}, ""); 505 $self->rcv_data (substr $self->{buf}, 0, delete $self->{datalen}, "");
656 my ($self, $result) = @_; 558 my ($self, $result) = @_;
657 559
658 unless (exists $self->{result}) { 560 unless (exists $self->{result}) {
659 $self->{result} = $result; 561 $self->{result} = $result;
660 $self->{cb}->($self) if exists $self->{cb}; 562 $self->{cb}->($self) if exists $self->{cb};
661 $self->{signal}->send; 563 $self->{signal}->broadcast;
662 } 564 }
663} 565}
664 566
665sub eof { 567sub eof {
666 my ($self) = @_; 568 my ($self) = @_;
677 } 579 }
678} 580}
679 581
680sub progress { 582sub progress {
681 my ($self, $type, $attr) = @_; 583 my ($self, $type, $attr) = @_;
584
682 $self->{fcp}->progress ($self, $type, $attr); 585 $self->{fcp}->progress ($self, $type, $attr);
683} 586}
684 587
685=item $result = $txn->result 588=item $result = $txn->result
686 589
738 641
739use base Net::FCP::Txn; 642use base Net::FCP::Txn;
740 643
741sub rcv_success { 644sub rcv_success {
742 my ($self, $attr) = @_; 645 my ($self, $attr) = @_;
743 $self->set_result ([$attr->{PublicKey}, $attr->{PrivateKey}]); 646 $self->set_result ([$attr->{public_key}, $attr->{private_key}, $attr->{crypto_key}]);
744} 647}
745 648
746package Net::FCP::Txn::InsertPrivateKey; 649package Net::FCP::Txn::InvertPrivateKey;
747 650
748use base Net::FCP::Txn; 651use base Net::FCP::Txn;
749 652
750sub rcv_success { 653sub rcv_success {
751 my ($self, $attr) = @_; 654 my ($self, $attr) = @_;
752 $self->set_result ($attr->{PublicKey}); 655 $self->set_result ($attr->{public_key});
753} 656}
754 657
755package Net::FCP::Txn::GetSize; 658package Net::FCP::Txn::GetSize;
756 659
757use base Net::FCP::Txn; 660use base Net::FCP::Txn;
758 661
759sub rcv_success { 662sub rcv_success {
760 my ($self, $attr) = @_; 663 my ($self, $attr) = @_;
761 $self->set_result (hex $attr->{Length}); 664 $self->set_result (hex $attr->{length});
762} 665}
763 666
764package Net::FCP::Txn::GetPut; 667package Net::FCP::Txn::GetPut;
765 668
766# base class for get and put 669# base class for get and put
767 670
768use base Net::FCP::Txn; 671use base Net::FCP::Txn;
769 672
770*rcv_uri_error = \&Net::FCP::Txn::rcv_throw_exception; 673*rcv_uri_error = \&Net::FCP::Txn::rcv_throw_exception;
771*rcv_route_not_found = \&Net::FCP::Txn::rcv_throw_exception; 674*rcv_route_not_found = \&Net::FCP::Txn::rcv_throw_exception;
772 675
773sub rcv_restarted { 676sub rcv_restarted {
774 my ($self, $attr, $type) = @_; 677 my ($self, $attr, $type) = @_;
775 678
776 delete $self->{datalength}; 679 delete $self->{datalength};
793 696
794 $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} });
795 698
796 if ($self->{datalength} == length $self->{data}) { 699 if ($self->{datalength} == length $self->{data}) {
797 my $data = delete $self->{data}; 700 my $data = delete $self->{data};
798 my $meta = Net::FCP::parse_metadata substr $data, 0, $self->{metalength}, ""; 701 my $meta = new Net::FCP::Metadata (substr $data, 0, $self->{metalength}, "");
799 702
800 $self->set_result ([$meta, $data]); 703 $self->set_result ([$meta, $data]);
801 $self->eof; 704 $self->eof;
802 } 705 }
803} 706}
814package Net::FCP::Txn::ClientPut; 717package Net::FCP::Txn::ClientPut;
815 718
816use base Net::FCP::Txn::GetPut; 719use base Net::FCP::Txn::GetPut;
817 720
818*rcv_size_error = \&Net::FCP::Txn::rcv_throw_exception; 721*rcv_size_error = \&Net::FCP::Txn::rcv_throw_exception;
819*rcv_key_collision = \&Net::FCP::Txn::rcv_throw_exception;
820 722
821sub rcv_pending { 723sub rcv_pending {
822 my ($self, $attr, $type) = @_; 724 my ($self, $attr, $type) = @_;
823 $self->progress ($type, $attr); 725 $self->progress ($type, $attr);
824} 726}
825 727
826sub rcv_success { 728sub rcv_success {
827 my ($self, $attr, $type) = @_; 729 my ($self, $attr, $type) = @_;
828 $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 });
829} 736}
830 737
831=back 738=back
832 739
833=head2 The Net::FCP::Exception CLASS 740=head2 The Net::FCP::Exception CLASS
901 808
902=head1 BUGS 809=head1 BUGS
903 810
904=head1 AUTHOR 811=head1 AUTHOR
905 812
906 Marc Lehmann <pcg@goof.com> 813 Marc Lehmann <schmorp@schmorp.de>
907 http://www.goof.com/pcg/marc/ 814 http://home.schmorp.de/
908 815
909=cut 816=cut
910 817
911package Net::FCP::Event::Auto; 8181
912 819
913my @models = (
914 [Coro => Coro::Event:: ],
915 [Event => Event::],
916 [Glib => Glib:: ],
917 [Tk => Tk::],
918);
919
920sub AUTOLOAD {
921 $AUTOLOAD =~ s/.*://;
922
923 for (@models) {
924 my ($model, $package) = @$_;
925 if (defined ${"$package\::VERSION"}) {
926 $EVENT = "Net::FCP::Event::$model";
927 eval "require $EVENT"; die if $@;
928 goto &{"$EVENT\::$AUTOLOAD"};
929 }
930 }
931
932 for (@models) {
933 my ($model, $package) = @$_;
934 $EVENT = "Net::FCP::Event::$model";
935 if (eval "require $EVENT") {
936 goto &{"$EVENT\::$AUTOLOAD"};
937 }
938 }
939
940 die "No event module selected for Net::FCP and autodetect failed. Install any of these: Coro, Event, Glib or Tk.";
941}
942
9431;
944

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines