]> Sergey Matveev's repositories - public-inbox.git/commitdiff
nntp: call SSL_shutdown in normal cases
authorEric Wong <e@80x24.org>
Mon, 24 Jun 2019 02:52:42 +0000 (02:52 +0000)
committerEric Wong <e@80x24.org>
Mon, 24 Jun 2019 05:26:27 +0000 (05:26 +0000)
This is in accordance with TLS standards and will be needed
to support session caching/reuse in the future.  However, we
don't issue shutdown(2) since we know not to inadvertantly
share our sockets with other processes.

lib/PublicInbox/DS.pm
lib/PublicInbox/NNTP.pm
t/nntpd-tls.t

index 2c886b4e4ff64674b6d367be0b528c5322417cdf..2aa9e3d294beae7615b999d88085bc5b2f7e0cd3 100644 (file)
@@ -621,6 +621,30 @@ sub accept_tls_step ($) {
     drop($self, 'BUG? EAGAIN but '.PublicInbox::TLS::err());
 }
 
+sub shutdn_tls_step ($) {
+    my ($self) = @_;
+    my $sock = $self->{sock} or return;
+    return $self->close if $sock->stop_SSL(SSL_fast_shutdown => 1);
+    return $self->close if $! != EAGAIN;
+    if (my $ev = PublicInbox::TLS::epollbit()) {
+        unshift @{$self->{wbuf} ||= []}, \&shutdn_tls_step;
+        return watch($self, $ev | EPOLLONESHOT);
+    }
+    drop($self, 'BUG? EAGAIN but '.PublicInbox::TLS::err());
+}
+
+# don't bother with shutdown($sock, 2), we don't fork+exec w/o CLOEXEC
+# or fork w/o exec, so no inadvertant socket sharing
+sub shutdn ($) {
+    my ($self) = @_;
+    my $sock = $self->{sock} or return;
+    if (ref($sock) eq 'IO::Socket::SSL') {
+        shutdn_tls_step($self);
+    } else {
+       $self->close;
+    }
+}
+
 package PublicInbox::DS::Timer;
 # [$abs_float_firetime, $coderef];
 sub cancel {
index 8840adbb8a807aa2fb0a2741675a0d137b232320..53de2bca2495c7b49b4369dbc1a94ebae7fa41fc 100644 (file)
@@ -74,11 +74,17 @@ sub expire_old () {
        my $exp = $EXPTIME;
        my $old = $now - $exp;
        my $nr = 0;
+       my $closed = 0;
        my %new;
        while (my ($fd, $v) = each %$EXPMAP) {
                my ($idle_time, $nntp) = @$v;
                if ($idle_time < $old) {
-                       $nntp->close; # idempotent
+                       if ($nntp->shutdn) {
+                               $closed++;
+                       } else {
+                               ++$nr;
+                               $new{$fd} = $v;
+                       }
                } else {
                        ++$nr;
                        $new{$fd} = $v;
@@ -91,7 +97,7 @@ sub expire_old () {
                $expt = undef;
                # noop to kick outselves out of the loop ASAP so descriptors
                # really get closed
-               PublicInbox::EvCleanup::asap(sub {});
+               PublicInbox::EvCleanup::asap(sub {}) if $closed;
        }
 }
 
@@ -410,7 +416,7 @@ sub cmd_post ($) {
 sub cmd_quit ($) {
        my ($self) = @_;
        res($self, '205 closing connection - goodbye!');
-       $self->close;
+       $self->shutdn;
        undef;
 }
 
index 4727ee5bb6f68e5e88e0e8f1cf180effad842f45..00b03b66835e152a7b3e7fb3eb3fcac56c326b66 100644 (file)
@@ -118,6 +118,8 @@ for my $args (
        my $c = Net::NNTP->new($nntps_addr, %o);
        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};