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.
This commit is contained in:
Trustin Lee 2014-12-11 17:48:45 +09:00
parent b8abe2d92e
commit b653491a9f

View File

@ -204,7 +204,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 final LazyChannelPromise handshakePromise = new LazyChannelPromise();
@ -404,7 +405,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();
}
@ -427,7 +432,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();
@ -884,7 +889,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();
}
/**
@ -948,11 +959,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;
}
@ -1105,6 +1116,11 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
}
ctx.fireUserEventTriggered(SslHandshakeCompletionEvent.SUCCESS);
}
if (readDuringHandshake && !ctx.channel().config().isAutoRead()) {
readDuringHandshake = false;
ctx.read();
}
}
/**