Net-FCP
view release on metacpan or search on metacpan
datastore_used => "1f72bb000",
estimated_load => 52,
free_memory => "5cc0148",
is_transient => "false",
java_name => "Java HotSpot(_T_M) Server VM",
java_vendor => "http://www.blackdown.org/",
java_version => "Blackdown-1.4.1-01",
least_recent_timestamp => "f41538b878",
max_file_size => "5f5e100",
most_recent_timestamp => "f77e2cc520"
node_address => "1.2.3.4",
node_port => 369,
operating_system => "Linux",
operating_system_version => "2.4.20",
routing_time => "a5",
}
=cut
$txn->(client_info => sub {
my ($self) = @_;
$self->txn ("client_info");
});
=item $txn = $fcp->txn_generate_chk ($metadata, $data[, $cipher])
=item $uri = $fcp->generate_chk ($metadata, $data[, $cipher])
Calculates a CHK, given the metadata and data. C<$cipher> is either
C<Rijndael> or C<Twofish>, with the latter being the default.
=cut
$txn->(generate_chk => sub {
my ($self, $metadata, $data, $cipher) = @_;
$metadata = Net::FCP::Metadata::build_metadata $metadata;
$self->txn (generate_chk =>
data => "$metadata$data",
metadata_length => xeh length $metadata,
cipher => $cipher || "Twofish");
});
=item $txn = $fcp->txn_generate_svk_pair
=item ($public, $private, $crypto) = @{ $fcp->generate_svk_pair }
Creates a new SVK pair. Returns an arrayref with the public key, the
private key and a crypto key, which is just additional entropy.
[
"acLx4dux9fvvABH15Gk6~d3I-yw",
"cPoDkDMXDGSMM32plaPZDhJDxSs",
"BH7LXCov0w51-y9i~BoB3g",
]
A private key (for inserting) can be constructed like this:
SSK@<private_key>,<crypto_key>/<name>
It can be used to insert data. The corresponding public key looks like this:
SSK@<public_key>PAgM,<crypto_key>/<name>
Watch out for the C<PAgM>-part!
=cut
$txn->(generate_svk_pair => sub {
my ($self) = @_;
$self->txn ("generate_svk_pair");
});
=item $txn = $fcp->txn_invert_private_key ($private)
=item $public = $fcp->invert_private_key ($private)
Inverts a private key (returns the public key). C<$private> can be either
an insert URI (must start with C<freenet:SSK@>) or a raw private key (i.e.
the private value you get back from C<generate_svk_pair>).
Returns the public key.
=cut
$txn->(invert_private_key => sub {
my ($self, $privkey) = @_;
$self->txn (invert_private_key => private => $privkey);
});
=item $txn = $fcp->txn_get_size ($uri)
=item $length = $fcp->get_size ($uri)
Finds and returns the size (rounded up to the nearest power of two) of the
given document.
=cut
$txn->(get_size => sub {
my ($self, $uri) = @_;
$self->txn (get_size => URI => $uri);
});
=item $txn = $fcp->txn_client_get ($uri [, $htl = 15 [, $removelocal = 0]])
=item ($metadata, $data) = @{ $fcp->client_get ($uri, $htl, $removelocal)
Fetches a (small, as it should fit into memory) key content block from
freenet. C<$meta> is a C<Net::FCP::Metadata> object or C<undef>).
The C<$uri> should begin with C<freenet:>, but the scheme is currently
added, if missing.
my ($meta, $data) = @{
$fcp->client_get (
"freenet:CHK@hdXaxkwZ9rA8-SidT0AN-bniQlgPAwI,XdCDmBuGsd-ulqbLnZ8v~w"
)
};
=cut
$txn->(client_get => sub {
my ($self, $uri, $htl, $removelocal) = @_;
$uri =~ s/^freenet://; $uri = "freenet:$uri";
$self->txn (client_get => URI => $uri, hops_to_live => xeh (defined $htl ? $htl : 15),
remove_local_key => $removelocal ? "true" : "false");
});
=item $txn = $fcp->txn_client_put ($uri, $metadata, $data, $htl, $removelocal)
=item my $uri = $fcp->client_put ($uri, $metadata, $data, $htl, $removelocal);
Insert a new key. If the client is inserting a CHK, the URI may be
abbreviated as just CHK@. In this case, the node will calculate the
CHK. If the key is a private SSK key, the node will calculcate the public
key and the resulting public URI.
C<$meta> can be a hash reference (same format as returned by
C<Net::FCP::parse_metadata>) or a string.
The result is an arrayref with the keys C<uri>, C<public_key> and C<private_key>.
=cut
$txn->(client_put => sub {
my ($self, $uri, $metadata, $data, $htl, $removelocal) = @_;
$metadata = Net::FCP::Metadata::build_metadata $metadata;
$uri =~ s/^freenet://; $uri = "freenet:$uri";
$self->txn (client_put => URI => $uri,
hops_to_live => xeh (defined $htl ? $htl : 15),
remove_local_key => $removelocal ? "true" : "false",
data => "$metadata$data", metadata_length => xeh length $metadata);
});
} # transactions
=back
=head2 THE Net::FCP::Txn CLASS
All requests (or transactions) are executed in a asynchronous way. For
each request, a C<Net::FCP::Txn> object is created (worse: a tcp
connection is created, too).
For each request there is actually a different subclass (and it's possible
to subclass these, although of course not documented).
The most interesting method is C<result>.
=over 4
=cut
package Net::FCP::Txn;
use Fcntl;
use Socket;
=item new arg => val,...
Creates a new C<Net::FCP::Txn> object. Not normally used.
=cut
sub new {
my $class = shift;
my $self = bless { @_ }, $class;
$self->{signal} = AnyEvent->condvar;
$self->{fcp}{txn}{$self} = $self;
my $attr = "";
my $data = delete $self->{attr}{data};
while (my ($k, $v) = each %{$self->{attr}}) {
$attr .= (Net::FCP::touc $k) . "=$v\012"
}
}
=item $result = $txn->result
Waits until a result is available and then returns it.
This waiting is (depending on your event model) not very efficient, as it
is done outside the "mainloop". The biggest problem, however, is that it's
blocking one thread of execution. Try to use the callback mechanism, if
possible, and call result from within the callback (or after is has been
run), as then no waiting is necessary.
=cut
sub result {
my ($self) = @_;
$self->{signal}->wait while !exists $self->{result};
die $self->{exception} if $self->{exception};
return $self->{result};
}
package Net::FCP::Txn::ClientHello;
use base Net::FCP::Txn;
sub rcv_node_hello {
my ($self, $attr) = @_;
$self->set_result ($attr);
}
package Net::FCP::Txn::ClientInfo;
use base Net::FCP::Txn;
sub rcv_node_info {
my ($self, $attr) = @_;
$self->set_result ($attr);
}
package Net::FCP::Txn::GenerateCHK;
use base Net::FCP::Txn;
sub rcv_success {
my ($self, $attr) = @_;
$self->set_result ($attr->{uri});
}
package Net::FCP::Txn::GenerateSVKPair;
use base Net::FCP::Txn;
sub rcv_success {
my ($self, $attr) = @_;
$self->set_result ([$attr->{public_key}, $attr->{private_key}, $attr->{crypto_key}]);
}
package Net::FCP::Txn::InvertPrivateKey;
use base Net::FCP::Txn;
sub rcv_success {
my ($self, $attr) = @_;
$self->set_result ($attr->{public_key});
}
package Net::FCP::Txn::GetSize;
use base Net::FCP::Txn;
sub rcv_success {
my ($self, $attr) = @_;
$self->set_result (hex $attr->{length});
}
package Net::FCP::Txn::GetPut;
# base class for get and put
use base Net::FCP::Txn;
*rcv_uri_error = \&Net::FCP::Txn::rcv_throw_exception;
*rcv_route_not_found = \&Net::FCP::Txn::rcv_throw_exception;
sub rcv_restarted {
my ($self, $attr, $type) = @_;
delete $self->{datalength};
delete $self->{metalength};
delete $self->{data};
$self->progress ($type, $attr);
}
package Net::FCP::Txn::ClientGet;
use base Net::FCP::Txn::GetPut;
*rcv_data_not_found = \&Net::FCP::Txn::rcv_throw_exception;
sub rcv_data {
my ($self, $chunk) = @_;
$self->{data} .= $chunk;
$self->progress ("data", { chunk => length $chunk, received => length $self->{data}, total => $self->{datalength} });
if ($self->{datalength} == length $self->{data}) {
my $data = delete $self->{data};
my $meta = new Net::FCP::Metadata (substr $data, 0, $self->{metalength}, "");
$self->set_result ([$meta, $data]);
$self->eof;
}
}
( run in 3.173 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )