Net-FCP
view release on metacpan or search on metacpan
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"
}
if (defined $data) {
$attr .= sprintf "DataLength=%x\012", length $data;
$data = "Data\012$data";
} else {
$data = "EndMessage\012";
}
socket my $fh, PF_INET, SOCK_STREAM, 0
or Carp::croak "unable to create new tcp socket: $!";
binmode $fh, ":raw";
fcntl $fh, F_SETFL, O_NONBLOCK;
connect $fh, (sockaddr_in $self->{fcp}{port}, inet_aton $self->{fcp}{host});
# and Carp::croak "FCP::txn: unable to connect to $self->{fcp}{host}:$self->{fcp}{port}: $!\n";
$self->{sbuf} =
"\x00\x00\x00\x02"
. (Net::FCP::touc $self->{type})
. "\012$attr$data";
#shutdown $fh, 1; # freenet buggy?, well, it's java...
$self->{fh} = $fh;
$self->{w} = AnyEvent->io (fh => $fh, poll => 'w', cb => sub { $self->fh_ready_w });
$self;
}
=item $txn = $txn->cb ($coderef)
Sets a callback to be called when the request is finished. The coderef
will be called with the txn as it's sole argument, so it has to call
C<result> itself.
Returns the txn object, useful for chaining.
Example:
$fcp->txn_client_get ("freenet:CHK....")
->userdata ("ehrm")
->cb(sub {
my $data = shift->result;
});
=cut
sub cb($$) {
my ($self, $cb) = @_;
$self->{cb} = $cb;
$self;
}
=item $txn = $txn->userdata ([$userdata])
Set user-specific data. This is useful in progress callbacks. The data can be accessed
using C<< $txn->{userdata} >>.
Returns the txn object, useful for chaining.
=cut
sub userdata($$) {
my ($self, $data) = @_;
$self->{userdata} = $data;
$self;
}
=item $txn->cancel (%attr)
Cancels the operation with a C<cancel> exception and the given attributes
(consider at least giving the attribute C<reason>).
UNTESTED.
=cut
sub cancel {
my ($self, %attr) = @_;
$self->throw (Net::FCP::Exception->new (cancel => { %attr }));
$self->set_result;
$self->eof;
}
sub fh_ready_w {
my ($self) = @_;
my $len = syswrite $self->{fh}, $self->{sbuf};
if ($len > 0) {
substr $self->{sbuf}, 0, $len, "";
unless (length $self->{sbuf}) {
fcntl $self->{fh}, F_SETFL, 0;
$self->{w} = AnyEvent->io (fh => $self->{fh}, poll => 'r', cb => sub { $self->fh_ready_r });
}
} elsif (defined $len) {
$self->throw (Net::FCP::Exception->new (network_error => { reason => "unexpected end of file while writing" }));
} else {
$self->throw (Net::FCP::Exception->new (network_error => { reason => "$!" }));
}
}
sub fh_ready_r {
my ($self) = @_;
if (sysread $self->{fh}, $self->{buf}, 16384 + 1024, length $self->{buf}) {
for (;;) {
if ($self->{datalen}) {
( run in 0.828 second using v1.01-cache-2.11-cpan-524268b4103 )