Fix a NoSuchElementException and out-of-order event problem caused by SslHandler

The fix prevents from reentering channelRead incorrectly. It also
prevents from getting the inbound requests out of order.
This commit is contained in:
Jeff Pinner 2013-07-11 17:45:28 -07:00 committed by Trustin Lee
parent d8479a04df
commit c77ab7d092

View File

@ -311,7 +311,6 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
/**
* See {@link #close()}
*/
public ChannelFuture close(final ChannelPromise future) {
final ChannelHandlerContext ctx = this.ctx;
@ -473,9 +472,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
out = ctx.alloc().buffer();
continue;
case NEED_UNWRAP:
if (internalBuffer().isReadable()) {
unwrapLater = true;
}
break;
case NEED_TASK:
runDelegatedTasks();
@ -486,9 +483,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
case NOT_HANDSHAKING:
// Workaround for TLS False Start problem reported at:
// https://github.com/netty/netty/issues/1108#issuecomment-14266970
if (internalBuffer().isReadable()) {
unwrapLater = true;
}
break;
default:
throw new IllegalStateException("Unknown handshake status: " + result.getHandshakeStatus());
@ -499,10 +494,6 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
}
}
}
if (unwrapLater) {
unwrapLater(ctx);
}
} catch (SSLException e) {
setHandshakeFailure(e);
throw e;
@ -521,22 +512,13 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
out.release();
}
}
}
private void unwrapLater(ChannelHandlerContext ctx) throws SSLException {
RecyclableArrayList out = RecyclableArrayList.newInstance();
try {
decode(ctx, internalBuffer(), out);
for (int i = 0; i < out.size(); i++) {
ctx.fireChannelRead(out.get(i));
}
} finally {
out.recycle();
if (unwrapLater) {
unwrap(ctx);
}
}
private void flushNonAppData0(ChannelHandlerContext ctx) throws SSLException {
boolean unwrapLater = false;
private void flushNonAppData0(ChannelHandlerContext ctx, boolean inUnwrap) throws SSLException {
ByteBuf out = null;
try {
for (;;) {
@ -551,29 +533,25 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
}
switch (result.getHandshakeStatus()) {
case NEED_WRAP:
continue;
case NEED_UNWRAP:
if (internalBuffer().isReadable()) {
unwrapLater = true;
}
case FINISHED:
setHandshakeSuccess();
break;
case NEED_TASK:
runDelegatedTasks();
continue;
case FINISHED:
setHandshakeSuccess();
// try to flush now just in case as there may be pending write tasks
flush0(ctx);
return;
break;
case NEED_UNWRAP:
if (!inUnwrap) {
unwrap(ctx);
}
break;
case NEED_WRAP:
break;
case NOT_HANDSHAKING:
// Workaround for TLS False Start problem reported at:
// https://github.com/netty/netty/issues/1108#issuecomment-14266970
if (internalBuffer().isReadable()) {
unwrapLater = true;
if (!inUnwrap) {
unwrap(ctx);
}
// try to flush now just in case as there may be pending write tasks
flush0(ctx);
break;
default:
throw new IllegalStateException("Unknown handshake status: " + result.getHandshakeStatus());
@ -583,10 +561,6 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
break;
}
}
if (unwrapLater) {
unwrapLater(ctx);
}
} catch (SSLException e) {
setHandshakeFailure(e);
throw e;
@ -848,6 +822,18 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
unwrap(ctx, buffer, out);
}
private void unwrap(ChannelHandlerContext ctx) throws SSLException {
RecyclableArrayList out = RecyclableArrayList.newInstance();
try {
unwrap(ctx, Unpooled.EMPTY_BUFFER.nioBuffer(), out);
for (int i = 0; i < out.size(); i++) {
ctx.fireChannelRead(out.get(i));
}
} finally {
out.recycle();
}
}
private void unwrap(ChannelHandlerContext ctx, ByteBuffer packet, List<Object> out) throws SSLException {
boolean wrapLater = false;
int bytesProduced = 0;
@ -872,7 +858,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
case NEED_UNWRAP:
break;
case NEED_WRAP:
wrapLater = true;
flushNonAppData0(ctx, true);
break;
case NEED_TASK:
runDelegatedTasks();
@ -894,7 +880,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
}
if (wrapLater) {
flushNonAppData0(ctx);
flush0(ctx);
}
} catch (SSLException e) {
setHandshakeFailure(e);
@ -1044,7 +1030,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
});
try {
engine.beginHandshake();
flushNonAppData0(ctx);
flushNonAppData0(ctx, false);
} catch (Exception e) {
notifyHandshakeFailure(e);
}