From d5a24d4f6c5110fcd2c3185e3752c4537ad84b7c Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Thu, 11 Dec 2014 17:48:45 +0900 Subject: [PATCH] Make SslHandler work when autoRead is turned off Related: #2958 Motivation: SslHandler currently does not issue a read() request when it is handshaking. It makes a connection with autoRead off stall, because a user's read() request can be used to read the handshake response which is invisible to the user. Modifications: - SslHandler now issues a read() request when: - the current handshake is in progress and channelReadComplete() is invoked - the current handshake is complete and a user issued a read() request during handshake - Rename flushedBeforeHandshakeDone to flushedBeforeHandshake for consistency with the new variable 'readDuringHandshake' Result: SslHandler should work regardless whether autoRead is on or off. --- .../java/io/netty/handler/ssl/SslHandler.java | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java index d175f93330..ec580a4ae3 100644 --- a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java +++ b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java @@ -206,7 +206,8 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH private final boolean startTls; private boolean sentFirstMessage; - private boolean flushedBeforeHandshakeDone; + private boolean flushedBeforeHandshake; + private boolean readDuringHandshake; private PendingWriteQueue pendingUnencryptedWrites; private Promise handshakePromise = new LazyChannelPromise(); @@ -408,7 +409,11 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH } @Override - public void read(ChannelHandlerContext ctx) { + public void read(ChannelHandlerContext ctx) throws Exception { + if (!handshakePromise.isDone()) { + readDuringHandshake = true; + } + ctx.read(); } @@ -431,7 +436,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH pendingUnencryptedWrites.add(Unpooled.EMPTY_BUFFER, ctx.voidPromise()); } if (!handshakePromise.isDone()) { - flushedBeforeHandshakeDone = true; + flushedBeforeHandshake = true; } wrap(ctx, false); ctx.flush(); @@ -888,7 +893,13 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH needsFlush = false; ctx.flush(); } - super.channelReadComplete(ctx); + + // If handshake is not finished yet, we need more data. + if (!handshakePromise.isDone() && !ctx.channel().config().isAutoRead()) { + ctx.read(); + } + + ctx.fireChannelReadComplete(); } /** @@ -952,11 +963,11 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH wrapLater = true; continue; } - if (flushedBeforeHandshakeDone) { + if (flushedBeforeHandshake) { // We need to call wrap(...) in case there was a flush done before the handshake completed. // // See https://github.com/netty/netty/pull/2437 - flushedBeforeHandshakeDone = false; + flushedBeforeHandshake = false; wrapLater = true; } @@ -1109,6 +1120,11 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH logger.debug(ctx.channel() + " HANDSHAKEN: " + engine.getSession().getCipherSuite()); } ctx.fireUserEventTriggered(SslHandshakeCompletionEvent.SUCCESS); + + if (readDuringHandshake && !ctx.channel().config().isAutoRead()) { + readDuringHandshake = false; + ctx.read(); + } } /**