AnyEvent
view release on metacpan or search on metacpan
lib/AnyEvent/Handle.pm view on Meta::CPAN
AnyEvent will start a TLS handshake as soon as the connection has been
established and will transparently encrypt/decrypt data afterwards.
All TLS protocol errors will be signalled as C<EPROTO>, with an
appropriate error message.
TLS mode requires Net::SSLeay to be installed (it will be loaded
automatically when you try to create a TLS handle): this module doesn't
have a dependency on that module, so if your module requires it, you have
to add the dependency yourself. If Net::SSLeay cannot be loaded or is too
old, you get an C<EPROTO> error.
Unlike TCP, TLS has a server and client side: for the TLS server side, use
C<accept>, and for the TLS client side of a connection, use C<connect>
mode.
You can also provide your own TLS connection object, but you have
to make sure that you call either C<Net::SSLeay::set_connect_state>
or C<Net::SSLeay::set_accept_state> on it before you pass it to
AnyEvent::Handle. Also, this module will take ownership of this connection
object.
At some future point, AnyEvent::Handle might switch to another TLS
implementation, then the option to use your own session object will go
away.
B<IMPORTANT:> since Net::SSLeay "objects" are really only integers,
passing in the wrong integer will lead to certain crash. This most often
happens when one uses a stylish C<< tls => 1 >> and is surprised about the
segmentation fault.
Use the C<< ->starttls >> method if you need to start TLS negotiation later.
=item tls_ctx => $anyevent_tls
Use the given C<AnyEvent::TLS> object to create the new TLS connection
(unless a connection object was specified directly). If this
parameter is missing (or C<undef>), then AnyEvent::Handle will use
C<AnyEvent::Handle::TLS_CTX>.
Instead of an object, you can also specify a hash reference with C<< key
=> value >> pairs. Those will be passed to L<AnyEvent::TLS> to create a
new TLS context object.
=item on_starttls => $cb->($handle, $success[, $error_message])
This callback will be invoked when the TLS/SSL handshake has finished. If
C<$success> is true, then the TLS handshake succeeded, otherwise it failed
(C<on_stoptls> will not be called in this case).
The session in C<< $handle->{tls} >> can still be examined in this
callback, even when the handshake was not successful.
TLS handshake failures will not cause C<on_error> to be invoked when this
callback is in effect, instead, the error message will be passed to C<on_starttls>.
Without this callback, handshake failures lead to C<on_error> being
called as usual.
Note that you cannot just call C<starttls> again in this callback. If you
need to do that, start an zero-second timer instead whose callback can
then call C<< ->starttls >> again.
=item on_stoptls => $cb->($handle)
When a SSLv3/TLS shutdown/close notify/EOF is detected and this callback is
set, then it will be invoked after freeing the TLS session. If it is not,
then a TLS shutdown condition will be treated like a normal EOF condition
on the handle.
The session in C<< $handle->{tls} >> can still be examined in this
callback.
This callback will only be called on TLS shutdowns, not when the
underlying handle signals EOF.
=item json => L<JSON>, L<JSON::PP> or L<JSON::XS> object
This is the json coder object used by the C<json> read and write types.
If you don't supply it, then AnyEvent::Handle will create and use a
suitable one (on demand), which will write and expect UTF-8 encoded
JSON texts (either using L<JSON::XS> or L<JSON>). The written texts are
guaranteed not to contain any newline character.
For security reasons, this encoder will likely I<not> handle numbers and
strings, only arrays and objects/hashes. The reason is that originally
JSON was self-delimited, but Dougles Crockford thought it was a splendid
idea to redefine JSON incompatibly, so this is no longer true.
For protocols that used back-to-back JSON texts, this might lead to
run-ins, where two or more JSON texts will be interpreted as one JSON
text.
For this reason, if the default encoder uses L<JSON::XS>, it will default
to not allowing anything but arrays and objects/hashes, at least for the
forseeable future (it will change at some point). This might or might not
be true for the L<JSON> module, so this might cause a security issue.
If you depend on either behaviour, you should create your own json object
and pass it in explicitly.
=item cbor => L<CBOR::XS> object
This is the cbor coder object used by the C<cbor> read and write types.
If you don't supply it, then AnyEvent::Handle will create and use a
suitable one (on demand), which will write CBOR without using extensions,
if possible.
Note that you are responsible to depend on the L<CBOR::XS> module if you
want to use this functionality, as AnyEvent does not have a dependency on
it itself.
=back
=cut
sub new {
my $class = shift;
my $self = bless { @_ }, $class;
lib/AnyEvent/Handle.pm view on Meta::CPAN
=cut
for my $dir ("", "r", "w") {
my $timeout = "${dir}timeout";
my $tw = "_${dir}tw";
my $on_timeout = "on_${dir}timeout";
my $activity = "_${dir}activity";
my $cb;
*$on_timeout = sub {
$_[0]{$on_timeout} = $_[1];
};
*$timeout = sub {
my ($self, $new_value) = @_;
$new_value >= 0
or Carp::croak "AnyEvent::Handle->$timeout called with negative timeout ($new_value), caught";
$self->{$timeout} = $new_value;
delete $self->{$tw}; &$cb;
};
*{"${dir}timeout_reset"} = sub {
$_[0]{$activity} = AE::now;
};
# main workhorse:
# reset the timeout watcher, as neccessary
# also check for time-outs
$cb = sub {
my ($self) = @_;
if ($self->{$timeout} && $self->{fh}) {
my $NOW = AE::now;
# when would the timeout trigger?
my $after = $self->{$activity} + $self->{$timeout} - $NOW;
# now or in the past already?
if ($after <= 0) {
$self->{$activity} = $NOW;
if ($self->{$on_timeout}) {
$self->{$on_timeout}($self);
} else {
$self->_error (Errno::ETIMEDOUT);
}
# callback could have changed timeout value, optimise
return unless $self->{$timeout};
# calculate new after
$after = $self->{$timeout};
}
Scalar::Util::weaken $self;
return unless $self; # ->error could have destroyed $self
$self->{$tw} ||= AE::timer $after, 0, sub {
delete $self->{$tw};
$cb->($self);
};
} else {
delete $self->{$tw};
}
}
}
#############################################################################
=back
=head2 WRITE QUEUE
AnyEvent::Handle manages two queues per handle, one for writing and one
for reading.
The write queue is very simple: you can add data to its end, and
AnyEvent::Handle will automatically try to get rid of it for you.
When data could be written and the write buffer is shorter then the low
water mark, the C<on_drain> callback will be invoked once.
=over 4
=item $handle->on_drain ($cb)
Sets the C<on_drain> callback or clears it (see the description of
C<on_drain> in the constructor).
This method may invoke callbacks (and therefore the handle might be
destroyed after it returns).
=cut
sub on_drain {
my ($self, $cb) = @_;
$self->{on_drain} = $cb;
$cb->($self)
if $cb && $self->{low_water_mark} >= (length $self->{wbuf}) + (length $self->{_tls_wbuf});
}
=item $handle->push_write ($data)
Queues the given scalar to be written. You can push as much data as
you want (only limited by the available memory and C<wbuf_max>), as
C<AnyEvent::Handle> buffers it independently of the kernel.
This method may invoke callbacks (and therefore the handle might be
destroyed after it returns).
=cut
sub _drain_wbuf {
my ($self) = @_;
if (!$self->{_ww} && length $self->{wbuf}) {
lib/AnyEvent/Handle.pm view on Meta::CPAN
sub stoptls {
my ($self) = @_;
if ($self->{tls} && $self->{fh}) {
Net::SSLeay::shutdown ($self->{tls});
&_dotls;
# # we don't give a shit. no, we do, but we can't. no...#d#
# # we, we... have to use openssl :/#d#
# &_freetls;#d#
}
}
sub _freetls {
my ($self) = @_;
return unless $self->{tls};
$self->{tls_ctx}->_put_session (delete $self->{tls})
if $self->{tls} > 0;
delete @$self{qw(_rbio _wbio _tls_wbuf _on_starttls)};
}
=item $handle->resettls
This rarely-used method simply resets and TLS state on the handle, usually
causing data loss.
One case where it may be useful is when you want to skip over the data in
the stream but you are not interested in interpreting it, so data loss is
no concern.
=cut
*resettls = \&_freetls;
sub DESTROY {
my ($self) = @_;
&_freetls;
my $linger = exists $self->{linger} ? $self->{linger} : 3600;
if ($linger && length $self->{wbuf} && $self->{fh}) {
my $fh = delete $self->{fh};
my $wbuf = delete $self->{wbuf};
my @linger;
push @linger, AE::io $fh, 1, sub {
my $len = syswrite $fh, $wbuf, length $wbuf;
if ($len > 0) {
substr $wbuf, 0, $len, "";
} elsif (defined $len || ($! != EAGAIN && $! != EINTR && $! != EWOULDBLOCK && $! != WSAEWOULDBLOCK)) {
@linger = (); # end
}
};
push @linger, AE::timer $linger, 0, sub {
@linger = ();
};
}
}
=item $handle->destroy
Shuts down the handle object as much as possible - this call ensures that
no further callbacks will be invoked and as many resources as possible
will be freed. Any method you will call on the handle object after
destroying it in this way will be silently ignored (and it will return the
empty list).
Normally, you can just "forget" any references to an AnyEvent::Handle
object and it will simply shut down. This works in fatal error and EOF
callbacks, as well as code outside. It does I<NOT> work in a read or write
callback, so when you want to destroy the AnyEvent::Handle object from
within such an callback. You I<MUST> call C<< ->destroy >> explicitly in
that case.
Destroying the handle object in this way has the advantage that callbacks
will be removed as well, so if those are the only reference holders (as
is common), then one doesn't need to do anything special to break any
reference cycles.
The handle might still linger in the background and write out remaining
data, as specified by the C<linger> option, however.
=cut
sub destroy {
my ($self) = @_;
$self->DESTROY;
%$self = ();
bless $self, "AnyEvent::Handle::destroyed";
}
sub AnyEvent::Handle::destroyed::AUTOLOAD {
#nop
}
=item $handle->destroyed
Returns false as long as the handle hasn't been destroyed by a call to C<<
->destroy >>, true otherwise.
Can be useful to decide whether the handle is still valid after some
callback possibly destroyed the handle. For example, C<< ->push_write >>,
C<< ->starttls >> and other methods can call user callbacks, which in turn
can destroy the handle, so work can be avoided by checking sometimes:
$hdl->starttls ("accept");
return if $hdl->destroyed;
$hdl->push_write (...
Note that the call to C<push_write> will silently be ignored if the handle
has been destroyed, so often you can just ignore the possibility of the
handle being destroyed.
( run in 0.446 second using v1.01-cache-2.11-cpan-39bf76dae61 )