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