]> Sergey Matveev's repositories - public-inbox.git/commitdiff
t/nntpd-tls: slow client connection test
authorEric Wong <e@80x24.org>
Mon, 24 Jun 2019 02:52:43 +0000 (02:52 +0000)
committerEric Wong <e@80x24.org>
Mon, 24 Jun 2019 05:26:27 +0000 (05:26 +0000)
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

index 00b03b66835e152a7b3e7fb3eb3fcac56c326b66..e8fb63b46fc80a204f774d1718b6158249687eba 100644 (file)
@@ -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');