Ensure SslHandler.sslCloseFuture() is notified in all cases.

Motivation:

The SslHandler.sslCloseFuture() may not be notified when the Channel is closed before a closify_notify is received.

Modifications:

Ensure we try to fail the sslCloseFuture() when the Channel is closed.

Result:

Correctly notify the ssl close future.
This commit is contained in:
Norman Maurer 2017-01-11 14:31:53 +01:00
parent 91951a51ad
commit d37702aa69
2 changed files with 20 additions and 4 deletions

View File

@ -277,7 +277,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
private PendingWriteQueue pendingUnencryptedWrites;
private Promise<Channel> handshakePromise = new LazyChannelPromise();
private final LazyChannelPromise sslCloseFuture = new LazyChannelPromise();
private final LazyChannelPromise sslClosePromise = new LazyChannelPromise();
/**
* Set by wrap*() methods when something is produced.
@ -456,7 +456,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
* @see SSLEngine
*/
public Future<Channel> sslCloseFuture() {
return sslCloseFuture;
return sslClosePromise;
}
@Override
@ -770,6 +770,9 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
// Make sure to release SSLEngine,
// and notify the handshake future if the connection has been closed during handshake.
setHandshakeFailure(ctx, CHANNEL_CLOSED, !outboundClosed);
// Ensure we always notify the sslClosePromise as well
sslClosePromise.tryFailure(CHANNEL_CLOSED);
super.channelInactive(ctx);
}
@ -804,7 +807,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
*
*/
private boolean ignoreException(Throwable t) {
if (!(t instanceof SSLException) && t instanceof IOException && sslCloseFuture.isDone()) {
if (!(t instanceof SSLException) && t instanceof IOException && sslClosePromise.isDone()) {
String message = String.valueOf(t.getMessage()).toLowerCase();
// first try to match connection reset / broke peer based on the regex. This is the fastest way
@ -1129,7 +1132,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
}
if (notifyClosure) {
sslCloseFuture.trySuccess(ctx.channel());
sslClosePromise.trySuccess(ctx.channel());
}
} finally {
if (decodeOut != null) {

View File

@ -62,6 +62,7 @@ import io.netty.util.ReferenceCounted;
import java.io.File;
import java.net.InetSocketAddress;
import java.nio.channels.ClosedChannelException;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
@ -371,4 +372,16 @@ public class SslHandlerTest {
ReferenceCountUtil.release(sslClientCtx);
}
}
@Test
public void testCloseFutureNotified() throws Exception {
SslHandler handler = new SslHandler(SSLContext.getDefault().createSSLEngine());
EmbeddedChannel ch = new EmbeddedChannel(handler);
// Closing the Channel will also produce a close_notify so it is expected to return true.
assertTrue(ch.finishAndReleaseAll());
assertTrue(handler.handshakeFuture().cause() instanceof ClosedChannelException);
assertTrue(handler.sslCloseFuture().cause() instanceof ClosedChannelException);
}
}