--- AnyEvent/lib/AnyEvent/Handle.pm 2008/10/02 06:42:39 1.95 +++ AnyEvent/lib/AnyEvent/Handle.pm 2009/01/21 06:01:29 1.111 @@ -16,7 +16,7 @@ =cut -our $VERSION = 4.3; +our $VERSION = 4.331; =head1 SYNOPSIS @@ -29,7 +29,7 @@ AnyEvent::Handle->new ( fh => \*STDIN, on_eof => sub { - $cv->broadcast; + $cv->send; }, ); @@ -61,14 +61,6 @@ 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 @@ -94,11 +86,11 @@ connection cleanly. 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 +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, +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. @@ -265,6 +257,11 @@ or C on it before you pass it to AnyEvent::Handle. +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. + See the C<< ->starttls >> method for when need to start TLS negotiation later. =item tls_ctx => $ssl_ctx @@ -336,7 +333,7 @@ if ($self->{on_error}) { $self->{on_error}($self, $fatal); - } else { + } elsif ($self->{fh}) { Carp::croak "AnyEvent::Handle uncaught error: $!"; } } @@ -384,10 +381,14 @@ =item $handle->autocork ($boolean) Enables or disables the current autocork behaviour (see C -constructor argument). +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 @@ -552,6 +553,7 @@ if ($self->{tls}) { $self->{_tls_wbuf} .= $_[0]; + &_dotls ($self); } else { $self->{wbuf} .= $_[0]; @@ -579,7 +581,7 @@ register_write_type netstring => sub { my ($self, $string) = @_; - sprintf "%d:%s,", (length $string), $string + (length $string) . ":$string," }; =item packstring => $format, $data @@ -1103,7 +1105,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). @@ -1143,7 +1146,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. @@ -1170,18 +1174,31 @@ my $json = $self->{json} ||= JSON->new->utf8; sub { - my $ref = $json->incr_parse ($self->{rbuf}); + eval { + my $ref = $json->incr_parse ($self->{rbuf}); + + if ($ref) { + $self->{rbuf} = $json->incr_text; + $json->incr_text = ""; + $cb->($self, $ref); + + 1 + } else { + $self->{rbuf} = ""; + () + } + + 1 + } or do { + # error case + $json->incr_skip; - if ($ref) { $self->{rbuf} = $json->incr_text; $json->incr_text = ""; - $cb->($self, $ref); - 1 - } else { - $self->{rbuf} = ""; - () - } + $self->_error (&Errno::EBADMSG); + }; + } }; @@ -1292,6 +1309,7 @@ if ($self->{tls}) { Net::SSLeay::BIO_write ($self->{_rbio}, $$rbuf); + &_dotls ($self); } else { $self->_drain_rbuf unless $self->{_in_drain}; @@ -1309,44 +1327,45 @@ } } +# poll the write BIO and send the data if applicable 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, ""; } } - while (defined ($buf = Net::SSLeay::read ($self->{tls}))) { - unless (length $buf) { + 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; &_freetls; } - $self->{rbuf} .= $buf; + $self->{rbuf} .= $tmp; $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); + $tmp = Net::SSLeay::get_error ($self->{tls}, -1); - if ($err!= Net::SSLeay::ERROR_WANT_READ ()) { - if ($err == Net::SSLeay::ERROR_SYSCALL ()) { + if ($tmp != Net::SSLeay::ERROR_WANT_READ ()) { + if ($tmp == Net::SSLeay::ERROR_SYSCALL ()) { return $self->_error ($!, 1); - } elsif ($err == Net::SSLeay::ERROR_SSL ()) { + } elsif ($tmp == Net::SSLeay::ERROR_SSL ()) { return $self->_error (&Errno::EIO, 1); } - # all others are fine for our purposes + # all other errors are fine for our purposes } - if (length ($buf = Net::SSLeay::BIO_read ($self->{_wbio}))) { - $self->{wbuf} .= $buf; + while (length ($tmp = Net::SSLeay::BIO_read ($self->{_wbio}))) { + $self->{wbuf} .= $tmp; $self->_drain_wbuf; } } @@ -1377,7 +1396,7 @@ require Net::SSLeay; - Carp::croak "it is an error to call starttls more than once on an Anyevent::Handle object" + Carp::croak "it is an error to call starttls more than once on an AnyEvent::Handle object" if $self->{tls}; if ($ssl eq "accept") { @@ -1476,6 +1495,31 @@ } } +=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. + +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 handle might still linger in the background and write out remaining +data, as specified by the C option, however. + +=cut + +sub destroy { + my ($self) = @_; + + $self->DESTROY; + %$self = (); +} + =item AnyEvent::Handle::TLS_CTX This function creates and returns the Net::SSLeay::CTX object used by @@ -1518,11 +1562,39 @@ =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}>: +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); @@ -1535,13 +1607,13 @@ 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 transfering data, +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 sent? +=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