noxxi / p5-io-socket-ssl

IO::Socket::SSL Perl Module
36 stars 60 forks source link

Reliable read, better handling of SSL *_WANT_* situations #77

Closed rainerjung closed 5 years ago

rainerjung commented 6 years ago

I noticed, that getline() often returns undefined, although data is available.

The reason is, that readline() andles EINTR and EWOULDBLOCK, but must also handle ERROR_WANT_READ and ERROR_WANT_WRITE. A good example as a starting point is Net::SSLeay::ssl_read_all():

sub ssl_read_all {
    my ($ssl,$how_much) = @_;
    $how_much = 2000000000 unless $how_much;
    my ($got, $rv, $errs);
    my $reply = '';

    while ($how_much > 0) {
        ($got, $rv) = Net::SSLeay::read($ssl,
                ($how_much > 32768) ? 32768 : $how_much
        );
        if (! defined $got) {
            my $err = Net::SSLeay::get_error($ssl, $rv);
            if ($err != Net::SSLeay::ERROR_WANT_READ() and
                $err != Net::SSLeay::ERROR_WANT_WRITE()) {
                $errs = print_errs('SSL_read');
                last;
            }
            next;
        }
        $how_much -= blength($got);
        debug_read(\$reply, \$got) if $trace>1;
        last if $got eq '';  # EOF
        $reply .= $got;
    }

    return wantarray ? ($reply, $errs) : $reply;
}

Maybe Net::SSLeay::ssl_read_until() can be used which internally calls ssl_read_all. And for getline() something like Net::SSLeay::ssl_read_CRLF()?

I only looked at Net::SSLeay current dev version, not sure what of that is available in latest stable.

noxxi commented 6 years ago

I noticed, that getline() often returns undefined, although data is available.

That's new to me and I don't have any example to trigger this behavior either (and you don't provide any). ERROR_WANT_READ and ERROR_WANT_WRITE should only happen if the socket is set to non-blocking. getline should not be expected to work correctly with a non-blocking socket because to work correctly (i.e. return only full lines) it might need to read more data than are currently available, i.e. need a blocking socket.