--- AnyEvent/lib/AnyEvent/Handle.pm 2008/08/21 20:52:39 1.87 +++ AnyEvent/lib/AnyEvent/Handle.pm 2008/10/01 15:50:33 1.94 @@ -16,7 +16,7 @@ =cut -our $VERSION = 4.232; +our $VERSION = 4.3; =head1 SYNOPSIS @@ -61,6 +61,14 @@ All callbacks will be invoked with the handle object as their first argument. +=head2 SIGPIPE is not handled by this module + +SIGPIPE is not handled by this module, so one of the practical +requirements of using it is to ignore SIGPIPE (C<$SIG{PIPE} = +'IGNORE'>). At least, this is highly recommend in a networked program: If +you use AnyEvent::Handle in a filter program (like sort), exiting on +SIGPIPE is probably the right thing to do. + =head1 METHODS =over 4 @@ -105,7 +113,7 @@ 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 -(but you are free to look at the current C< ->rbuf >). Examples of fatal +(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. @@ -154,12 +162,13 @@ 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. @@ -173,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 @@ -184,14 +193,16 @@ =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 (this disadvantage is -usually avoided by your kernel's nagle algorithm, see C). +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. +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 => @@ -199,16 +210,17 @@ 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 cna be -accomplishd by setting this option to true. +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, this option -explicitly enables or disables it, if possible. +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 => @@ -216,25 +228,33 @@ 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). - -This will not work for partial TLS data that could not yet been -encoded. This data will be lost. +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 tls => "accept" | "connect" | Net::SSLeay::SSL object When this parameter is given, it enables TLS (SSL) mode, that means -AnyEvent will start a TLS handshake and will transparently encrypt/decrypt -data. +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). +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 @@ -245,11 +265,11 @@ or C on it before you pass it to AnyEvent::Handle. -See the C method for when need to start TLS negotiation later. +See the C<< ->starttls >> method for when need to start TLS negotiation later. =item tls_ctx => $ssl_ctx -Use the given Net::SSLeay::CTX object to create the new TLS connection +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. @@ -264,13 +284,6 @@ 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. (They are used internally -by the TLS code). - =back =cut @@ -284,10 +297,8 @@ AnyEvent::Util::fh_nonblocking $self->{fh}, 1; - if ($self->{tls}) { - require Net::SSLeay; - $self->starttls (delete $self->{tls}, delete $self->{tls_ctx}); - } + $self->starttls (delete $self->{tls}, delete $self->{tls_ctx}) + if $self->{tls}; $self->{_activity} = AnyEvent->now; $self->_timeout; @@ -309,7 +320,7 @@ delete $self->{_ww}; delete $self->{fh}; - $self->stoptls; + &_freetls; delete $self->{on_read}; delete $self->{_queue}; @@ -332,7 +343,7 @@ =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 @@ -360,9 +371,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 @@ -478,7 +489,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) @@ -505,7 +516,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}; @@ -539,8 +550,9 @@ ->($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; @@ -786,7 +798,7 @@ } } else { # read side becomes idle - delete $self->{_rw}; + delete $self->{_rw} unless $self->{tls}; last; } } @@ -1254,12 +1266,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 { @@ -1269,15 +1284,18 @@ 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}; @@ -1302,21 +1320,17 @@ } } - if (length ($buf = Net::SSLeay::BIO_read ($self->{_wbio}))) { - $self->{wbuf} .= $buf; - $self->_drain_wbuf; - } - while (defined ($buf = Net::SSLeay::read ($self->{tls}))) { - if (length $buf) { - $self->{rbuf} .= $buf; - $self->_drain_rbuf unless $self->{_in_drain}; - } else { + unless (length $buf) { # let's treat SSL-eof as we treat normal EOF + delete $self->{_rw}; $self->{_eof} = 1; - $self->_shutdown; - return; + &_freetls; } + + $self->{rbuf} .= $buf; + $self->_drain_rbuf unless $self->{_in_drain}; + $self->{tls} or return; # tls session might have gone away in callback } my $err = Net::SSLeay::get_error ($self->{tls}, -1); @@ -1330,6 +1344,11 @@ # all others are fine for our purposes } + + if (length ($buf = Net::SSLeay::BIO_read ($self->{_wbio}))) { + $self->{wbuf} .= $buf; + $self->_drain_wbuf; + } } =item $handle->starttls ($tls[, $tls_ctx]) @@ -1348,13 +1367,19 @@ 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 sub starttls { my ($self, $ssl, $ctx) = @_; - $self->stoptls; + require Net::SSLeay; + Carp::croak "it is an error to call starttls more than once on an Anyevent::Handle object" + if $self->{tls}; + if ($ssl eq "accept") { $ssl = Net::SSLeay::new ($ctx || TLS_CTX ()); Net::SSLeay::set_accept_state ($ssl); @@ -1373,9 +1398,10 @@ # # in short: this is a mess. # - # note that we do not try to kepe the length constant between writes as we are required to do. + # 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. + # 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 ($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)); @@ -1385,39 +1411,47 @@ 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; + + # 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}; - delete $self->{_rbio}; - delete $self->{_wbio}; - delete $self->{_tls_wbuf}; - delete $self->{filter_r}; - delete $self->{filter_w}; + Net::SSLeay::free (delete $self->{tls}); + + delete @$self{qw(_rbio _wbio _tls_wbuf)}; } sub DESTROY { my $self = shift; - $self->stoptls; + &_freetls; my $linger = exists $self->{linger} ? $self->{linger} : 3600;