From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id BC1651F4B7 for ; Mon, 24 Jun 2019 02:58:07 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 42/57] t/nntpd-tls: slow client connection test Date: Mon, 24 Jun 2019 02:52:43 +0000 Message-Id: <20190624025258.25592-43-e@80x24.org> In-Reply-To: <20190624025258.25592-1-e@80x24.org> References: <20190624025258.25592-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: We need to ensure slowly negotiating TLS clients don't block the event loop. This is why I added the size check of {wbuf} before and after calling the CODE ref in DS::flush_write. --- t/nntpd-tls.t | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/t/nntpd-tls.t b/t/nntpd-tls.t index 00b03b66..e8fb63b4 100644 --- a/t/nntpd-tls.t +++ b/t/nntpd-tls.t @@ -5,7 +5,9 @@ use warnings; use Test::More; use File::Temp qw(tempdir); use Socket qw(SOCK_STREAM); -foreach my $mod (qw(DBD::SQLite IO::Socket::SSL Net::NNTP)) { +# IO::Poll and Net::NNTP are part of the standard library, but +# distros may split them off... +foreach my $mod (qw(DBD::SQLite IO::Socket::SSL Net::NNTP IO::Poll)) { eval "require $mod"; plan skip_all => "$mod missing for $0" if $@; } @@ -108,21 +110,32 @@ for my $args ( my %o = ( SSL_hostname => 'server.local', SSL_verifycn_name => 'server.local', - SSL => 1, SSL_verify_mode => SSL_VERIFY_PEER(), SSL_ca_file => 'certs/test-ca.pem', ); my $expect = { $group => [qw(1 1 n)] }; + # start negotiating a slow TLS connection + my $slow = IO::Socket::INET->new( + Proto => 'tcp', + PeerAddr => $nntps_addr, + Type => SOCK_STREAM, + Blocking => 0, + ); + $slow = IO::Socket::SSL->start_SSL($slow, SSL_startHandshake => 0, %o); + my $slow_done = $slow->connect_SSL; + diag('W: connect_SSL early OK, slow client test invalid') if $slow_done; + my @poll = (fileno($slow), PublicInbox::TLS::epollbit()); + # we should call connect_SSL much later... + # NNTPS - my $c = Net::NNTP->new($nntps_addr, %o); + my $c = Net::NNTP->new($nntps_addr, %o, SSL => 1); my $list = $c->list; is_deeply($list, $expect, 'NNTPS LIST works'); is($c->command('QUIT')->response(), Net::Cmd::CMD_OK(), 'QUIT works'); is(0, sysread($c, my $buf, 1), 'got EOF after QUIT'); # STARTTLS - delete $o{SSL}; $c = Net::NNTP->new($starttls_addr, %o); $list = $c->list; is_deeply($list, $expect, 'plain LIST works'); @@ -154,6 +167,21 @@ for my $args ( $c = Net::NNTP->new($nntps_addr, %o, SSL => 1); ok($c, 'NNTPS succeeds again with valid hostname'); + # slow TLS connection did not block the other fast clients while + # connecting, finish it off: + until ($slow_done) { + IO::Poll::_poll(-1, @poll); + $slow_done = $slow->connect_SSL and last; + @poll = (fileno($slow), PublicInbox::TLS::epollbit()); + } + $slow->blocking(1); + ok(sysread($slow, my $greet, 4096) > 0, 'slow got greeting'); + like($greet, qr/\A201 /, 'got expected greeting'); + is(syswrite($slow, "QUIT\r\n"), 6, 'slow wrote QUIT'); + ok(sysread($slow, my $end, 4096) > 0, 'got EOF'); + is(sysread($slow, my $eof, 4096), 0, 'got EOF'); + $slow = undef; + $c = undef; kill('TERM', $pid); is($pid, waitpid($pid, 0), 'nntpd exited successfully'); -- EW