--- AnyEvent/lib/AnyEvent/Handle.pm 2008/06/06 11:01:17 1.64 +++ AnyEvent/lib/AnyEvent/Handle.pm 2009/07/04 23:58:52 1.137 @@ -1,7 +1,7 @@ package AnyEvent::Handle; no warnings; -use strict; +use strict qw(subs vars); use AnyEvent (); use AnyEvent::Util qw(WSAEWOULDBLOCK); @@ -16,7 +16,7 @@ =cut -our $VERSION = 4.15; +our $VERSION = 4.452; =head1 SYNOPSIS @@ -29,7 +29,7 @@ AnyEvent::Handle->new ( fh => \*STDIN, on_eof => sub { - $cv->broadcast; + $cv->send; }, ); @@ -51,6 +51,9 @@ filehandles. For utility functions for doing non-blocking connects and accepts on sockets see L. +The L tutorial contains some well-documented +AnyEvent::Handle examples. + In the following, when the documentation refers to of "bytes" then this means characters. As sysread and syswrite are used for all I/O, their treatment of characters applies to this module as well. @@ -62,9 +65,9 @@ =over 4 -=item B +=item $handle = B AnyEvent::TLS fh => $filehandle, key => value... -The constructor supports these arguments (all as key => value pairs). +The constructor supports these arguments (all as C<< key => value >> pairs). =over 4 @@ -72,33 +75,53 @@ The filehandle this L object will operate on. -NOTE: The filehandle will be set to non-blocking (using -AnyEvent::Util::fh_nonblocking). +NOTE: The filehandle will be set to non-blocking mode (using +C) by the constructor and needs to stay in +that mode. =item on_eof => $cb->($handle) -Set the callback to be called when an end-of-file condition is detcted, +Set the callback to be called when an end-of-file condition is detected, i.e. in the case of a socket, when the other side has closed the connection cleanly. -While not mandatory, it is highly recommended to set an eof callback, +For sockets, this just means that the other side has stopped sending data, +you can still try to write data, and, in fact, one can return from the EOF +callback and continue writing data, as only the read part has been shut +down. + +While not mandatory, it is I recommended to set an EOF callback, otherwise you might end up with a closed socket while you are still waiting for data. -=item on_error => $cb->($handle, $fatal) +If an EOF condition has been detected but no C callback has been +set, then a fatal error will be raised with C<$!> set to <0>. + +=item on_error => $cb->($handle, $fatal, $message) This is the error callback, which is called when, well, some error occured, such as not being able to resolve the hostname, failure to connect or a read error. Some errors are fatal (which is indicated by C<$fatal> being true). On -fatal errors the handle object will be shut down and will not be -usable. Non-fatal errors can be retried by simply returning, but it is -recommended to simply ignore this parameter and instead abondon the handle -object when this callback is invoked. +fatal errors the handle object will be shut down and will not be usable +(but you are free to look at the current C<< ->rbuf >>). Examples of fatal +errors are an EOF condition with active (but unsatisifable) read watchers +(C) or I/O errors. + +AnyEvent::Handle tries to find an appropriate error code for you to check +against, but in some cases (TLS errors), this does not work well. It is +recommended to always output the C<$message> argument in human-readable +error messages (it's usually the same as C<"$!">). + +Non-fatal errors can be retried by simply returning, but it is recommended +to simply ignore this parameter and instead abondon the handle object +when this callback is invoked. Examples of non-fatal errors are timeouts +C) or badly-formatted data (C). On callback entrance, the value of C<$!> contains the operating system -error (or C, C, C or C). +error code (or C, C, C, C or +C). While not mandatory, it is I recommended to set this callback, as you will not be notified of errors otherwise. The default simply calls @@ -112,7 +135,9 @@ read buffer). To access (and remove data from) the read buffer, use the C<< ->rbuf >> -method or access the C<$handle->{rbuf}> member directly. +method or access the C<$handle->{rbuf}> member directly. Note that you +must not enlarge or modify the read buffer, you can only remove data at +the beginning from it. When an EOF condition is detected then AnyEvent::Handle will first try to feed all the remaining data to the queued callbacks and C before @@ -126,17 +151,24 @@ To append to the write buffer, use the C<< ->push_write >> method. +This callback is useful when you don't want to put all of your write data +into the queue at once, for example, when you want to write the contents +of some file to the socket you might not want to read the whole file into +memory and push it into the queue, but instead only read more data from +the file when the write queue becomes empty. + =item timeout => $fractional_seconds If non-zero, then this enables an "inactivity" timeout: whenever this many seconds pass without a successful read or write on the underlying file handle, the C callback will be invoked (and if that one is -missing, an C error will be raised). +missing, a non-fatal C error will be raised). Note that timeout processing is also active when you currently do not have any outstanding read or write requests: If you plan to keep the connection idle then you should disable the timout temporarily or ignore the timeout -in the C callback. +in the C callback, in which case AnyEvent::Handle will simply +restart the timeout. Zero (the default) disables this timeout. @@ -150,7 +182,7 @@ If defined, then a fatal error will be raised (with C<$!> set to C) when the read buffer ever (strictly) exceeds this size. This is useful to -avoid denial-of-service attacks. +avoid some forms of denial-of-service attacks. For example, a server accepting connections from untrusted sources should be configured to accept only so-and-so much data that it cannot act on @@ -158,10 +190,37 @@ amount of data without a callback ever being called as long as the line isn't finished). +=item autocork => + +When disabled (the default), then C will try to immediately +write the data to the handle, if possible. This avoids having to register +a write watcher and wait for the next event loop iteration, but can +be inefficient if you write multiple small chunks (on the wire, this +disadvantage is usually avoided by your kernel's nagle algorithm, see +C, but this option can save costly syscalls). + +When enabled, then writes will always be queued till the next event loop +iteration. This is efficient when you do many small writes per iteration, +but less efficient when you do a single write only per iteration (or when +the write buffer often is full). It also increases write latency. + +=item no_delay => + +When doing small writes on sockets, your operating system kernel might +wait a bit for more data before actually sending it out. This is called +the Nagle algorithm, and usually it is beneficial. + +In some situations you want as low a delay as possible, which can be +accomplishd by setting this option to a true value. + +The default is your opertaing system's default behaviour (most likely +enabled), this option explicitly enables or disables it, if possible. + =item read_size => -The default read block size (the amount of bytes this module will try to read -during each (loop iteration). Default: C<8192>. +The default read block size (the amount of bytes this module will +try to read during each loop iteration, which affects memory +requirements). Default: C<8192>. =item low_water_mark => @@ -169,113 +228,143 @@ buffer: If the write reaches this size or gets even samller it is considered empty. +Sometimes it can be beneficial (for performance reasons) to add data to +the write buffer before it is fully drained, but this is a rare case, as +the operating system kernel usually buffers data as well, so the default +is good in almost all cases. + =item linger => If non-zero (default: C<3600>), then the destructor of the -AnyEvent::Handle object will check wether there is still outstanding write -data and will install a watcher that will write out this data. No errors -will be reported (this mostly matches how the operating system treats -outstanding data at socket close time). +AnyEvent::Handle object will check whether there is still outstanding +write data and will install a watcher that will write this data to the +socket. No errors will be reported (this mostly matches how the operating +system treats outstanding data at socket close time). + +This will not work for partial TLS data that could not be encoded +yet. This data will be lost. Calling the C method in time might +help. + +=item peername => $string + +A string used to identify the remote site - usually the DNS hostname +(I IDN!) used to create the connection, rarely the IP address. -This will not work for partial TLS data that could not yet been -encoded. This data will be lost. +Apart from being useful in error messages, this string is also used in TLS +common name verification (see C in L). =item tls => "accept" | "connect" | Net::SSLeay::SSL object -When this parameter is given, it enables TLS (SSL) mode, that means it -will start making tls handshake and will transparently encrypt/decrypt -data. +When this parameter is given, it enables TLS (SSL) mode, that means +AnyEvent will start a TLS handshake as soon as the conenction has been +established and will transparently encrypt/decrypt data afterwards. -TLS mode requires Net::SSLeay to be installed (it will be loaded -automatically when you try to create a TLS handle). +All TLS protocol errors will be signalled as C, with an +appropriate error message. -For the TLS server side, use C, and for the TLS client side of a -connection, use C mode. +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. + +Unlike TCP, TLS has a server and client side: for the TLS server side, use +C, and for the TLS client side of a connection, use C +mode. You can also provide your own TLS connection object, but you have to make sure that you call either C or C on it before you pass it to -AnyEvent::Handle. +AnyEvent::Handle. Also, this module will take ownership of this connection +object. -See the C method if you need to start TLs negotiation later. +At some future point, AnyEvent::Handle might switch to another TLS +implementation, then the option to use your own session object will go +away. -=item tls_ctx => $ssl_ctx +B 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 given Net::SSLeay::CTX object to create the new TLS connection +See the C<< ->starttls >> method for when need to start TLS negotiation later. + +=item tls_ctx => $anyevent_tls + +Use the given C object to create the new TLS connection (unless a connection object was specified directly). If this parameter is missing, then AnyEvent::Handle will use C. +Instead of an object, you can also specify a hash reference with C<< key +=> value >> pairs. Those will be passed to L to create a +new TLS context object. + =item json => JSON or JSON::XS object This is the json coder object used by the C read and write types. If you don't supply it, then AnyEvent::Handle will create and use a -suitable one, which will write and expect UTF-8 encoded JSON texts. +suitable one (on demand), which will write and expect UTF-8 encoded JSON +texts. Note that you are responsible to depend on the JSON module if you want to use this functionality, as AnyEvent does not have a dependency itself. -=item filter_r => $cb - -=item filter_w => $cb - -These exist, but are undocumented at this time. - =back =cut sub new { my $class = shift; - my $self = bless { @_ }, $class; $self->{fh} or Carp::croak "mandatory argument fh is missing"; AnyEvent::Util::fh_nonblocking $self->{fh}, 1; - if ($self->{tls}) { - require Net::SSLeay; - $self->starttls (delete $self->{tls}, delete $self->{tls_ctx}); - } - $self->{_activity} = AnyEvent->now; $self->_timeout; - $self->on_drain (delete $self->{on_drain}) if $self->{on_drain}; + $self->no_delay (delete $self->{no_delay}) if exists $self->{no_delay}; + + $self->starttls (delete $self->{tls}, delete $self->{tls_ctx}) + if $self->{tls}; - $self + $self->on_drain (delete $self->{on_drain}) if exists $self->{on_drain}; + + $self->start_read + if $self->{on_read}; + + $self->{fh} && $self } sub _shutdown { my ($self) = @_; - delete $self->{_tw}; - delete $self->{_rw}; - delete $self->{_ww}; - delete $self->{fh}; + delete @$self{qw(_tw _rw _ww fh wbuf on_read _queue)}; + $self->{_eof} = 1; # tell starttls et. al to stop trying - $self->stoptls; + &_freetls; } sub _error { - my ($self, $errno, $fatal) = @_; + my ($self, $errno, $fatal, $message) = @_; $self->_shutdown if $fatal; $! = $errno; + $message ||= "$!"; if ($self->{on_error}) { - $self->{on_error}($self, $fatal); - } else { - Carp::croak "AnyEvent::Handle uncaught error: $!"; + $self->{on_error}($self, $fatal, $message); + } elsif ($self->{fh}) { + Carp::croak "AnyEvent::Handle uncaught error: $message"; } } =item $fh = $handle->fh -This method returns the file handle of the L object. +This method returns the file handle used to create the L object. =cut @@ -303,9 +392,9 @@ =item $handle->on_timeout ($cb) -Replace the current C callback, or disables the callback -(but not the timeout) if C<$cb> = C. See C constructor -argument. +Replace the current C callback, or disables the callback (but +not the timeout) if C<$cb> = C. See the C constructor +argument and method. =cut @@ -313,6 +402,33 @@ $_[0]{on_timeout} = $_[1]; } +=item $handle->autocork ($boolean) + +Enables or disables the current autocork behaviour (see C +constructor argument). Changes will only take effect on the next write. + +=cut + +sub autocork { + $_[0]{autocork} = $_[1]; +} + +=item $handle->no_delay ($boolean) + +Enables or disables the C setting (see constructor argument of +the same name for details). + +=cut + +sub no_delay { + $_[0]{no_delay} = $_[1]; + + eval { + local $SIG{__DIE__}; + setsockopt $_[0]{fh}, &Socket::IPPROTO_TCP, &Socket::TCP_NODELAY, int $_[1]; + }; +} + ############################################################################# =item $handle->timeout ($seconds) @@ -398,7 +514,7 @@ $self->{on_drain} = $cb; $cb->($self) - if $cb && $self->{low_water_mark} >= length $self->{wbuf}; + if $cb && $self->{low_water_mark} >= (length $self->{wbuf}) + (length $self->{_tls_wbuf}); } =item $handle->push_write ($data) @@ -425,7 +541,7 @@ $self->{_activity} = AnyEvent->now; $self->{on_drain}($self) - if $self->{low_water_mark} >= length $self->{wbuf} + if $self->{low_water_mark} >= (length $self->{wbuf}) + (length $self->{_tls_wbuf}) && $self->{on_drain}; delete $self->{_ww} unless length $self->{wbuf}; @@ -435,7 +551,7 @@ }; # try to write data immediately - $cb->(); + $cb->() unless $self->{autocork}; # if still data left in wbuf, we need to poll $self->{_ww} = AnyEvent->io (fh => $self->{fh}, poll => "w", cb => $cb) @@ -459,8 +575,10 @@ ->($self, @_); } - if ($self->{filter_w}) { - $self->{filter_w}($self, \$_[0]); + if ($self->{tls}) { + $self->{_tls_wbuf} .= $_[0]; + + &_dotls ($self); } else { $self->{wbuf} .= $_[0]; $self->_drain_wbuf; @@ -487,7 +605,7 @@ register_write_type netstring => sub { my ($self, $string) = @_; - sprintf "%d:%s,", (length $string), $string + (length $string) . ":$string," }; =item packstring => $format, $data @@ -502,7 +620,7 @@ register_write_type packstring => sub { my ($self, $format, $string) = @_; - pack "$format/a", $string + pack "$format/a*", $string }; =item json => $array_or_hashref @@ -558,11 +676,32 @@ require Storable; - pack "w/a", Storable::nfreeze ($ref) + pack "w/a*", Storable::nfreeze ($ref) }; =back +=item $handle->push_shutdown + +Sometimes you know you want to close the socket after writing your data +before it was actually written. One way to do that is to replace your +C handler by a callback that shuts down the socket. This method +is a shorthand for just that, and replaces the C callback with: + + sub { shutdown $_[0]{fh}, 1 } # for push_shutdown + +This simply shuts down the write side and signals an EOF condition to the +the peer. + +You can rely on the normal read queue and C handling +afterwards. This is the cleanest way to close a connection. + +=cut + +sub push_shutdown { + $_[0]->{on_drain} = sub { shutdown $_[0]{fh}, 1 }; +} + =item AnyEvent::Handle::register_write_type type => $coderef->($handle, @args) This function (not method) lets you add your own types to C. @@ -592,8 +731,9 @@ In the simple case, you just install an C callback and whenever new data arrives, it will be called. You can then remove some data (if -enough is there) from the read buffer (C<< $handle->rbuf >>) if you want -or not. +enough is there) from the read buffer (C<< $handle->rbuf >>). Or you cna +leave the data there if you want to accumulate more (e.g. when only a +partial message has been received so far). In the more complex case, you want to queue multiple callbacks. In this case, AnyEvent::Handle will call the first queued callback each time new @@ -621,13 +761,17 @@ }); }); -Example 2: Implement a client for a protocol that replies either with -"OK" and another line or "ERROR" for one request, and 64 bytes for the -second request. Due tot he availability of a full queue, we can just -pipeline sending both requests and manipulate the queue as necessary in -the callbacks: +Example 2: Implement a client for a protocol that replies either with "OK" +and another line or "ERROR" for the first request that is sent, and 64 +bytes for the second request. Due to the availability of a queue, we can +just pipeline sending both requests and manipulate the queue as necessary +in the callbacks. + +When the first callback is called and sees an "OK" response, it will +C another line-read. This line-read will be queued I the +64-byte chunk callback. - # request one + # request one, returns either "OK + extra line" or "ERROR" $handle->push_write ("request 1\015\012"); # we expect "ERROR" or "OK" as response, so push a line read @@ -644,7 +788,7 @@ } }); - # request two + # request two, simply returns 64 octets $handle->push_write ("request 2\015\012"); # simply read 64 bytes, always @@ -666,11 +810,13 @@ defined $self->{rbuf_max} && $self->{rbuf_max} < length $self->{rbuf} ) { - return $self->_error (&Errno::ENOSPC, 1); + $self->_error (&Errno::ENOSPC, 1), return; } while () { - no strict 'refs'; + # we need to use a separate tls read buffer, as we must not receive data while + # we are draining the buffer, and this can only happen with TLS. + $self->{rbuf} .= delete $self->{_tls_rbuf} if exists $self->{_tls_rbuf}; my $len = length $self->{rbuf}; @@ -678,7 +824,7 @@ unless ($cb->($self)) { if ($self->{_eof}) { # no progress can be made (not enough data and no data forthcoming) - $self->_error (&Errno::EPIPE, 1), last; + $self->_error (&Errno::EPIPE, 1), return; } unshift @{ $self->{_queue} }, $cb; @@ -696,20 +842,25 @@ ) { # no further data will arrive # so no progress can be made - $self->_error (&Errno::EPIPE, 1), last + $self->_error (&Errno::EPIPE, 1), return if $self->{_eof}; last; # more data might arrive } } else { # read side becomes idle - delete $self->{_rw}; + delete $self->{_rw} unless $self->{tls}; last; } } - $self->{on_eof}($self) - if $self->{_eof} && $self->{on_eof}; + if ($self->{_eof}) { + if ($self->{on_eof}) { + $self->{on_eof}($self) + } else { + $self->_error (0, 1); + } + } # may need to restart read watcher unless ($self->{_rw}) { @@ -737,8 +888,11 @@ Returns the read buffer (as a modifiable lvalue). -You can access the read buffer directly as the C<< ->{rbuf} >> member, if -you want. +You can access the read buffer directly as the C<< ->{rbuf} >> +member, if you want. However, the only operation allowed on the +read buffer (apart from looking at it) is removing data from its +beginning. Otherwise modifying or appending to it is not allowed and will +lead to hard-to-track-down bugs. NOTE: The read buffer should only be used or modified if the C, C or C methods are used. The other read methods @@ -845,15 +999,6 @@ } }; -# compatibility with older API -sub push_read_chunk { - $_[0]->push_read (chunk => $_[1], $_[2]); -} - -sub unshift_read_chunk { - $_[0]->unshift_read (chunk => $_[1], $_[2]); -} - =item line => [$eol, ]$cb->($handle, $line, $eol) The callback will be called only once a full line (including the end of @@ -878,29 +1023,27 @@ register_read_type line => sub { my ($self, $cb, $eol) = @_; - $eol = qr|(\015?\012)| if @_ < 3; - $eol = quotemeta $eol unless ref $eol; - $eol = qr|^(.*?)($eol)|s; + if (@_ < 3) { + # this is more than twice as fast as the generic code below + sub { + $_[0]{rbuf} =~ s/^([^\015\012]*)(\015?\012)// or return; - sub { - $_[0]{rbuf} =~ s/$eol// or return; + $cb->($_[0], $1, $2); + 1 + } + } else { + $eol = quotemeta $eol unless ref $eol; + $eol = qr|^(.*?)($eol)|s; - $cb->($_[0], $1, $2); - 1 + sub { + $_[0]{rbuf} =~ s/$eol// or return; + + $cb->($_[0], $1, $2); + 1 + } } }; -# compatibility with older API -sub push_read_line { - my $self = shift; - $self->push_read (line => @_); -} - -sub unshift_read_line { - my $self = shift; - $self->unshift_read (line => @_); -} - =item regex => $accept[, $reject[, $skip], $cb->($handle, $data) Makes a regex match against the regex object C<$accept> and returns @@ -1014,7 +1157,8 @@ integer only (only one of C is allowed, plus an optional C, C<< < >> or C<< > >> modifier). -DNS over TCP uses a prefix of C, EPP uses a prefix of C. +For example, DNS over TCP uses a prefix of C (2 octet network order), +EPP uses a prefix of C (4 octtes). Example: read a block of data prefixed by its length in BER-encoded format (very efficient). @@ -1030,14 +1174,23 @@ sub { # when we can use 5.10 we can use ".", but for 5.8 we use the re-pack method - defined (my $len = eval { unpack $format, $_[0]->{rbuf} }) + defined (my $len = eval { unpack $format, $_[0]{rbuf} }) or return; - # remove prefix - substr $_[0]->{rbuf}, 0, (length pack $format, $len), ""; + $format = length pack $format, $len; - # read rest - $_[0]->unshift_read (chunk => $len, $cb); + # bypass unshift if we already have the remaining chunk + if ($format + $len <= length $_[0]{rbuf}) { + my $data = substr $_[0]{rbuf}, $format, $len; + substr $_[0]{rbuf}, 0, $format + $len, ""; + $cb->($_[0], $data); + } else { + # remove prefix + substr $_[0]{rbuf}, 0, $format, ""; + + # read remaining chunk + $_[0]->unshift_read (chunk => $len, $cb); + } 1 } @@ -1045,7 +1198,8 @@ =item json => $cb->($handle, $hash_or_arrayref) -Reads a JSON object or array, decodes it and passes it to the callback. +Reads a JSON object or array, decodes it and passes it to the +callback. When a parse error occurs, an C error will be raised. If a C object was passed to the constructor, then that will be used for the final decode, otherwise it will create a JSON coder expecting UTF-8. @@ -1064,15 +1218,15 @@ register_read_type json => sub { my ($self, $cb) = @_; - require JSON; + my $json = $self->{json} ||= + eval { require JSON::XS; JSON::XS->new->utf8 } + || do { require JSON; JSON->new->utf8 }; my $data; my $rbuf = \$self->{rbuf}; - my $json = $self->{json} ||= JSON->new->utf8; - sub { - my $ref = $json->incr_parse ($self->{rbuf}); + my $ref = eval { $json->incr_parse ($self->{rbuf}) }; if ($ref) { $self->{rbuf} = $json->incr_text; @@ -1080,8 +1234,19 @@ $cb->($self, $ref); 1 + } elsif ($@) { + # error case + $json->incr_skip; + + $self->{rbuf} = $json->incr_text; + $json->incr_text = ""; + + $self->_error (&Errno::EBADMSG); + + () } else { $self->{rbuf} = ""; + () } } @@ -1104,20 +1269,31 @@ sub { # when we can use 5.10 we can use ".", but for 5.8 we use the re-pack method - defined (my $len = eval { unpack "w", $_[0]->{rbuf} }) + defined (my $len = eval { unpack "w", $_[0]{rbuf} }) or return; - # remove prefix - substr $_[0]->{rbuf}, 0, (length pack "w", $len), ""; + my $format = length pack "w", $len; - # read rest - $_[0]->unshift_read (chunk => $len, sub { - if (my $ref = eval { Storable::thaw ($_[1]) }) { - $cb->($_[0], $ref); - } else { - $self->_error (&Errno::EBADMSG); - } - }); + # bypass unshift if we already have the remaining chunk + if ($format + $len <= length $_[0]{rbuf}) { + my $data = substr $_[0]{rbuf}, $format, $len; + substr $_[0]{rbuf}, 0, $format + $len, ""; + $cb->($_[0], Storable::thaw ($data)); + } else { + # remove prefix + substr $_[0]{rbuf}, 0, $format, ""; + + # read remaining chunk + $_[0]->unshift_read (chunk => $len, sub { + if (my $ref = eval { Storable::thaw ($_[1]) }) { + $cb->($_[0], $ref); + } else { + $self->_error (&Errno::EBADMSG); + } + }); + } + + 1 } }; @@ -1157,12 +1333,15 @@ will automatically C for you when neither C is set nor there are any read requests in the queue. +These methods will have no effect when in TLS mode (as TLS doesn't support +half-duplex connections). + =cut sub stop_read { my ($self) = @_; - delete $self->{_rw}; + delete $self->{_rw} unless $self->{tls}; } sub start_read { @@ -1172,15 +1351,19 @@ Scalar::Util::weaken $self; $self->{_rw} = AnyEvent->io (fh => $self->{fh}, poll => "r", cb => sub { - my $rbuf = $self->{filter_r} ? \my $buf : \$self->{rbuf}; + my $rbuf = \($self->{tls} ? my $buf : $self->{rbuf}); my $len = sysread $self->{fh}, $$rbuf, $self->{read_size} || 8192, length $$rbuf; if ($len > 0) { $self->{_activity} = AnyEvent->now; - $self->{filter_r} - ? $self->{filter_r}($self, $rbuf) - : $self->{_in_drain} || $self->_drain_rbuf; + if ($self->{tls}) { + Net::SSLeay::BIO_write ($self->{_rbio}, $$rbuf); + + &_dotls ($self); + } else { + $self->_drain_rbuf unless $self->{_in_drain}; + } } elsif (defined $len) { delete $self->{_rw}; @@ -1194,44 +1377,68 @@ } } +our $ERROR_SYSCALL; +our $ERROR_WANT_READ; +our $ERROR_ZERO_RETURN; + +sub _tls_error { + my ($self, $err) = @_; + + return $self->_error ($!, 1) + if $err == Net::SSLeay::ERROR_SYSCALL (); + + my $err =Net::SSLeay::ERR_error_string (Net::SSLeay::ERR_get_error ()); + + # reduce error string to look less scary + $err =~ s/^error:[0-9a-fA-F]{8}:[^:]+:([^:]+):/\L$1: /; + + $self->_error (&Errno::EPROTO, 1, $err); +} + +# poll the write BIO and send the data if applicable +# also decode read data if possible +# this is basiclaly our TLS state machine +# more efficient implementations are possible with openssl, +# but not with the buggy and incomplete Net::SSLeay. sub _dotls { my ($self) = @_; - my $buf; + my $tmp; if (length $self->{_tls_wbuf}) { - while ((my $len = Net::SSLeay::write ($self->{tls}, $self->{_tls_wbuf})) > 0) { - substr $self->{_tls_wbuf}, 0, $len, ""; + while (($tmp = Net::SSLeay::write ($self->{tls}, $self->{_tls_wbuf})) > 0) { + substr $self->{_tls_wbuf}, 0, $tmp, ""; } - } - if (length ($buf = Net::SSLeay::BIO_read ($self->{_wbio}))) { - $self->{wbuf} .= $buf; - $self->_drain_wbuf; + $tmp = Net::SSLeay::get_error ($self->{tls}, $tmp); + return $self->_tls_error ($tmp) + if $tmp != $ERROR_WANT_READ + && ($tmp != $ERROR_SYSCALL || $!) + && $tmp != $ERROR_ZERO_RETURN; } - while (defined ($buf = Net::SSLeay::read ($self->{tls}))) { - if (length $buf) { - $self->{rbuf} .= $buf; - $self->_drain_rbuf unless $self->{_in_drain}; - } else { + while (defined ($tmp = Net::SSLeay::read ($self->{tls}))) { + unless (length $tmp) { # let's treat SSL-eof as we treat normal EOF + delete $self->{_rw}; $self->{_eof} = 1; - $self->_shutdown; - return; + &_freetls; } - } - my $err = Net::SSLeay::get_error ($self->{tls}, -1); + $self->{_tls_rbuf} .= $tmp; + $self->_drain_rbuf unless $self->{_in_drain}; + $self->{tls} or return; # tls session might have gone away in callback + } - if ($err!= Net::SSLeay::ERROR_WANT_READ ()) { - if ($err == Net::SSLeay::ERROR_SYSCALL ()) { - return $self->_error ($!, 1); - } elsif ($err == Net::SSLeay::ERROR_SSL ()) { - return $self->_error (&Errno::EIO, 1); - } + $tmp = Net::SSLeay::get_error ($self->{tls}, -1); + return $self->_tls_error ($tmp) + if $tmp != $ERROR_WANT_READ + && ($tmp != $ERROR_SYSCALL || $!) + && $tmp != $ERROR_ZERO_RETURN; - # all others are fine for our purposes + while (length ($tmp = Net::SSLeay::BIO_read ($self->{_wbio}))) { + $self->{wbuf} .= $tmp; + $self->_drain_wbuf; } } @@ -1244,77 +1451,116 @@ The first argument is the same as the C constructor argument (either C<"connect">, C<"accept"> or an existing Net::SSLeay object). -The second argument is the optional C object that is -used when AnyEvent::Handle has to create its own TLS connection object. +The second argument is the optional C object that is used +when AnyEvent::Handle has to create its own TLS connection object, or +a hash reference with C<< key => value >> pairs that will be used to +construct a new context. + +The TLS connection object will end up in C<< $handle->{tls} >>, the TLS +context in C<< $handle->{tls_ctx} >> after this call and can be used or +changed to your liking. Note that the handshake might have already started +when this function returns. -The TLS connection object will end up in C<< $handle->{tls} >> after this -call and can be used or changed to your liking. Note that the handshake -might have already started when this function returns. +If it an error to start a TLS handshake more than once per +AnyEvent::Handle object (this is due to bugs in OpenSSL). =cut +our %TLS_CACHE; #TODO not yet documented, should we? + sub starttls { my ($self, $ssl, $ctx) = @_; - $self->stoptls; + require Net::SSLeay; - if ($ssl eq "accept") { - $ssl = Net::SSLeay::new ($ctx || TLS_CTX ()); - Net::SSLeay::set_accept_state ($ssl); - } elsif ($ssl eq "connect") { - $ssl = Net::SSLeay::new ($ctx || TLS_CTX ()); - Net::SSLeay::set_connect_state ($ssl); - } + Carp::croak "it is an error to call starttls more than once on an AnyEvent::Handle object" + if $self->{tls}; + + $ERROR_SYSCALL = Net::SSLeay::ERROR_SYSCALL (); + $ERROR_WANT_READ = Net::SSLeay::ERROR_WANT_READ (); + $ERROR_ZERO_RETURN = Net::SSLeay::ERROR_ZERO_RETURN (); + + $ctx ||= $self->{tls_ctx}; + + if ("HASH" eq ref $ctx) { + require AnyEvent::TLS; - $self->{tls} = $ssl; + local $Carp::CarpLevel = 1; # skip ourselves when creating a new context + + if ($ctx->{cache}) { + my $key = $ctx+0; + $ctx = $TLS_CACHE{$key} ||= new AnyEvent::TLS %$ctx; + } else { + $ctx = new AnyEvent::TLS %$ctx; + } + } + + $self->{tls_ctx} = $ctx || TLS_CTX (); + $self->{tls} = $ssl = $self->{tls_ctx}->_get_session ($ssl, $self, $self->{peername}); # basically, this is deep magic (because SSL_read should have the same issues) # but the openssl maintainers basically said: "trust us, it just works". # (unfortunately, we have to hardcode constants because the abysmally misdesigned # and mismaintained ssleay-module doesn't even offer them). # http://www.mail-archive.com/openssl-dev@openssl.org/msg22420.html - Net::SSLeay::CTX_set_mode ($self->{tls}, - (eval { local $SIG{__DIE__}; Net::SSLeay::MODE_ENABLE_PARTIAL_WRITE () } || 1) - | (eval { local $SIG{__DIE__}; Net::SSLeay::MODE_ACCEPT_MOVING_WRITE_BUFFER () } || 2)); + # + # in short: this is a mess. + # + # note that we do not try to keep the length constant between writes as we are required to do. + # we assume that most (but not all) of this insanity only applies to non-blocking cases, + # and we drive openssl fully in blocking mode here. Or maybe we don't - openssl seems to + # have identity issues in that area. +# Net::SSLeay::CTX_set_mode ($ssl, +# (eval { local $SIG{__DIE__}; Net::SSLeay::MODE_ENABLE_PARTIAL_WRITE () } || 1) +# | (eval { local $SIG{__DIE__}; Net::SSLeay::MODE_ACCEPT_MOVING_WRITE_BUFFER () } || 2)); + Net::SSLeay::CTX_set_mode ($ssl, 1|2); $self->{_rbio} = Net::SSLeay::BIO_new (Net::SSLeay::BIO_s_mem ()); $self->{_wbio} = Net::SSLeay::BIO_new (Net::SSLeay::BIO_s_mem ()); Net::SSLeay::set_bio ($ssl, $self->{_rbio}, $self->{_wbio}); - $self->{filter_w} = sub { - $_[0]{_tls_wbuf} .= ${$_[1]}; - &_dotls; - }; - $self->{filter_r} = sub { - Net::SSLeay::BIO_write ($_[0]{_rbio}, ${$_[1]}); - &_dotls; - }; + &_dotls; # need to trigger the initial handshake + $self->start_read; # make sure we actually do read } =item $handle->stoptls -Destroys the SSL connection, if any. Partial read or write data will be -lost. +Shuts down the SSL connection - this makes a proper EOF handshake by +sending a close notify to the other side, but since OpenSSL doesn't +support non-blocking shut downs, it is not possible to re-use the stream +afterwards. =cut sub stoptls { my ($self) = @_; - Net::SSLeay::free (delete $self->{tls}) if $self->{tls}; + if ($self->{tls}) { + Net::SSLeay::shutdown ($self->{tls}); + + &_dotls; - delete $self->{_rbio}; - delete $self->{_wbio}; - delete $self->{_tls_wbuf}; - delete $self->{filter_r}; - delete $self->{filter_w}; + # we don't give a shit. no, we do, but we can't. no... + # we, we... have to use openssl :/ + &_freetls; + } +} + +sub _freetls { + my ($self) = @_; + + return unless $self->{tls}; + + $self->{tls_ctx}->_put_session (delete $self->{tls}); + + delete @$self{qw(_rbio _wbio _tls_wbuf)}; } sub DESTROY { - my $self = shift; + my ($self) = @_; - $self->stoptls; + &_freetls; my $linger = exists $self->{linger} ? $self->{linger} : 3600; @@ -1339,43 +1585,124 @@ } } -=item AnyEvent::Handle::TLS_CTX +=item $handle->destroy + +Shuts down the handle object as much as possible - this call ensures that +no further callbacks will be invoked and resources will be freed as much +as possible. You must not call any methods on the object afterwards. -This function creates and returns the Net::SSLeay::CTX object used by -default for TLS mode. +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 work in a read or write +callback, so when you want to destroy the AnyEvent::Handle object from +within such an callback. You I call C<< ->destroy >> explicitly in +that case. -The context is created like this: +The handle might still linger in the background and write out remaining +data, as specified by the C option, however. - Net::SSLeay::load_error_strings; - Net::SSLeay::SSLeay_add_ssl_algorithms; - Net::SSLeay::randomize; +=cut + +sub destroy { + my ($self) = @_; - my $CTX = Net::SSLeay::CTX_new; + $self->DESTROY; + %$self = (); +} + +=item AnyEvent::Handle::TLS_CTX - Net::SSLeay::CTX_set_options $CTX, Net::SSLeay::OP_ALL +This function creates and returns the AnyEvent::TLS object used by default +for TLS mode. + +The context is created by calling L without any arguments. =cut our $TLS_CTX; sub TLS_CTX() { - $TLS_CTX || do { - require Net::SSLeay; + $TLS_CTX ||= do { + require AnyEvent::TLS; - Net::SSLeay::load_error_strings (); - Net::SSLeay::SSLeay_add_ssl_algorithms (); - Net::SSLeay::randomize (); + new AnyEvent::TLS + } +} - $TLS_CTX = Net::SSLeay::CTX_new (); +=back - Net::SSLeay::CTX_set_options ($TLS_CTX, Net::SSLeay::OP_ALL ()); - $TLS_CTX - } -} +=head1 NONFREQUENTLY ASKED QUESTIONS + +=over 4 + +=item I C the AnyEvent::Handle reference inside my callback and +still get further invocations! + +That's because AnyEvent::Handle keeps a reference to itself when handling +read or write callbacks. + +It is only safe to "forget" the reference inside EOF or error callbacks, +from within all other callbacks, you need to explicitly call the C<< +->destroy >> method. + +=item I get different callback invocations in TLS mode/Why can't I pause +reading? + +Unlike, say, TCP, TLS connections do not consist of two independent +communication channels, one for each direction. Or put differently. The +read and write directions are not independent of each other: you cannot +write data unless you are also prepared to read, and vice versa. + +This can mean than, in TLS mode, you might get C or C +callback invocations when you are not expecting any read data - the reason +is that AnyEvent::Handle always reads in TLS mode. + +During the connection, you have to make sure that you always have a +non-empty read-queue, or an C watcher. At the end of the +connection (or when you no longer want to use it) you can call the +C method. + +=item How do I read data until the other side closes the connection? + +If you just want to read your data into a perl scalar, the easiest way +to achieve this is by setting an C callback that does nothing, +clearing the C callback and in the C callback, the data +will be in C<$_[0]{rbuf}>: + + $handle->on_read (sub { }); + $handle->on_eof (undef); + $handle->on_error (sub { + my $data = delete $_[0]{rbuf}; + undef $handle; + }); + +The reason to use C is that TCP connections, due to latencies +and packets loss, might get closed quite violently with an error, when in +fact, all data has been received. + +It is usually better to use acknowledgements when transferring data, +to make sure the other side hasn't just died and you got the data +intact. This is also one reason why so many internet protocols have an +explicit QUIT command. + +=item I don't want to destroy the handle too early - how do I wait until +all data has been written? + +After writing your last bits of data, set the C callback +and destroy the handle in there - with the default setting of +C this will be called precisely when all data has been +written to the socket: + + $handle->push_write (...); + $handle->on_drain (sub { + warn "all data submitted to the kernel\n"; + undef $handle; + }); =back + =head1 SUBCLASSING AnyEvent::Handle In many cases, you might want to subclass AnyEvent::Handle. @@ -1388,7 +1715,7 @@ =item * all constructor arguments become object members. At least initially, when you pass a C-argument to the constructor it -will end up in C<< $handle->{tls} >>. Those members might be changes or +will end up in C<< $handle->{tls} >>. Those members might be changed or mutated later on (for example C will hold the TLS connection object). =item * other object member names are prefixed with an C<_>.