From 809e3df9dddf7afc11164fa3234c69bb302e19ed Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Fri, 18 Apr 2014 17:59:48 +0900 Subject: [PATCH] Work around an Android SSLEngine issue Motivation: Some Android SSLEngine implementations skip FINISHED handshake status and go straightly into NOT_HANDSHAKING. This behavior blocks SslHandler from notifying its handshakeFuture, because we do the notification when SSLEngine enters the FINISHED state. Modification: When the current handshake state is NOT_HANDSHAKING and the handshakeFuture is not fulfilled yet, treat NOT_HANDSHAKING as FINISHED. Result: Better Android compatibility - fixes #1823 --- .../java/io/netty/handler/ssl/SslHandler.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) 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 2b88e14cf4..342e60baff 100644 --- a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java +++ b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java @@ -438,6 +438,8 @@ public class SslHandler extends ByteToMessageDecoder { setHandshakeSuccess(); // deliberate fall-through case NOT_HANDSHAKING: + setHandshakeSuccessIfStillHandshaking(); + // deliberate fall-through case NEED_WRAP: finishWrap(ctx, out, promise, inUnwrap); promise = null; @@ -509,6 +511,7 @@ public class SslHandler extends ByteToMessageDecoder { case NEED_WRAP: break; case NOT_HANDSHAKING: + setHandshakeSuccessIfStillHandshaking(); // Workaround for TLS False Start problem reported at: // https://github.com/netty/netty/issues/1108#issuecomment-14266970 if (!inUnwrap) { @@ -863,6 +866,10 @@ public class SslHandler extends ByteToMessageDecoder { wrapLater = true; continue; case NOT_HANDSHAKING: + if (setHandshakeSuccessIfStillHandshaking()) { + wrapLater = true; + continue; + } break; default: throw new IllegalStateException("Unknown handshake status: " + handshakeStatus); @@ -925,6 +932,21 @@ public class SslHandler extends ByteToMessageDecoder { } } + /** + * Works around some Android {@link SSLEngine} implementations that skip {@link HandshakeStatus#FINISHED} and + * go straight into {@link HandshakeStatus#NOT_HANDSHAKING} when handshake is finished. + * + * @return {@code true} if and only if the workaround has been applied and thus {@link #handshakeFuture} has been + * marked as success by this method + */ + private boolean setHandshakeSuccessIfStillHandshaking() { + if (!handshakePromise.isDone()) { + setHandshakeSuccess(); + return true; + } + return false; + } + /** * Notify all the handshake futures about the successfully handshake */