Ensure we flush out all pending data on SslException. Related to [#3900]

Motivation:

We need to ensure we flush out all pending data when an SslException accours so the remote peer receives all alerts.

Modifications:

Ensure we call ctx.flush() when needed.

Result:

Correctly receive alerts in all cases on the remote peer.
This commit is contained in:
Norman Maurer 2016-01-18 13:00:25 +01:00
parent 7494e84208
commit ae4e9ddc2d

View File

@ -503,9 +503,14 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
if (!handshakePromise.isDone()) { if (!handshakePromise.isDone()) {
flushedBeforeHandshake = true; flushedBeforeHandshake = true;
} }
try {
wrap(ctx, false); wrap(ctx, false);
} finally {
// We may have written some parts of data before an exception was thrown so ensure we always flush.
// See https://github.com/netty/netty/issues/3900#issuecomment-172481830
ctx.flush(); ctx.flush();
} }
}
private void wrap(ChannelHandlerContext ctx, boolean inUnwrap) throws SSLException { private void wrap(ChannelHandlerContext ctx, boolean inUnwrap) throws SSLException {
ByteBuf out = null; ByteBuf out = null;
@ -642,6 +647,10 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
} }
} catch (SSLException e) { } catch (SSLException e) {
setHandshakeFailure(ctx, e); setHandshakeFailure(ctx, e);
// We may have written some parts of data before an exception was thrown so ensure we always flush.
// See https://github.com/netty/netty/issues/3900#issuecomment-172481830
flushIfNeeded(ctx);
throw e; throw e;
} finally { } finally {
if (out != null) { if (out != null) {
@ -925,10 +934,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
// Discard bytes of the cumulation buffer if needed. // Discard bytes of the cumulation buffer if needed.
discardSomeReadBytes(); discardSomeReadBytes();
if (needsFlush) { flushIfNeeded(ctx);
needsFlush = false;
ctx.flush();
}
// If handshake is not finished yet, we need more data. // If handshake is not finished yet, we need more data.
if (!ctx.channel().config().isAutoRead() && (!firedChannelRead || !handshakePromise.isDone())) { if (!ctx.channel().config().isAutoRead() && (!firedChannelRead || !handshakePromise.isDone())) {
@ -941,6 +947,13 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
ctx.fireChannelReadComplete(); ctx.fireChannelReadComplete();
} }
private void flushIfNeeded(ChannelHandlerContext ctx) {
if (needsFlush) {
needsFlush = false;
ctx.flush();
}
}
/** /**
* Calls {@link SSLEngine#unwrap(ByteBuffer, ByteBuffer)} with an empty buffer to handle handshakes, etc. * Calls {@link SSLEngine#unwrap(ByteBuffer, ByteBuffer)} with an empty buffer to handle handshakes, etc.
*/ */
@ -1349,9 +1362,12 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
try { try {
engine.beginHandshake(); engine.beginHandshake();
wrapNonAppData(ctx, false); wrapNonAppData(ctx, false);
ctx.flush();
} catch (Exception e) { } catch (Exception e) {
notifyHandshakeFailure(e); notifyHandshakeFailure(e);
} finally {
// We have may haven written some parts of data before an exception was thrown so ensure we always flush.
// See https://github.com/netty/netty/issues/3900#issuecomment-172481830
ctx.flush();
} }
// Set timeout if necessary. // Set timeout if necessary.