diff --git a/common/src/main/java/io/netty/util/internal/Hidden.java b/common/src/main/java/io/netty/util/internal/Hidden.java index 86348a04d5..e9ec19e757 100644 --- a/common/src/main/java/io/netty/util/internal/Hidden.java +++ b/common/src/main/java/io/netty/util/internal/Hidden.java @@ -62,6 +62,16 @@ class Hidden { "confirmShutdown" ); + builder.allowBlockingCallsInside( + "io.netty.handler.ssl.SslHandler", + "handshake" + ); + + builder.allowBlockingCallsInside( + "io.netty.handler.ssl.SslHandler", + "runAllDelegatedTasks" + ); + builder.nonBlockingThreadPredicate(p -> thread -> p.test(thread) || thread instanceof FastThreadLocalThread); } diff --git a/handler/src/test/java/io/netty/handler/ssl/SslHandlerTest.java b/handler/src/test/java/io/netty/handler/ssl/SslHandlerTest.java index b3a67c915d..2006732246 100644 --- a/handler/src/test/java/io/netty/handler/ssl/SslHandlerTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/SslHandlerTest.java @@ -911,7 +911,7 @@ public class SslHandlerTest { } } - private void testHandshakeWithExecutor(Executor executor) throws Exception { + private static void testHandshakeWithExecutor(Executor executor) throws Exception { final SslContext sslClientCtx = SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE) .sslProvider(SslProvider.JDK).build(); @@ -968,7 +968,7 @@ public class SslHandlerTest { testHandshakeTimeoutBecauseExecutorNotExecute(false); } - private void testHandshakeTimeoutBecauseExecutorNotExecute(final boolean client) throws Exception { + private static void testHandshakeTimeoutBecauseExecutorNotExecute(final boolean client) throws Exception { final SslContext sslClientCtx = SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE) .sslProvider(SslProvider.JDK).build(); diff --git a/transport-blockhound-tests/pom.xml b/transport-blockhound-tests/pom.xml index f2709cd4c7..ba0ee7f94f 100644 --- a/transport-blockhound-tests/pom.xml +++ b/transport-blockhound-tests/pom.xml @@ -46,6 +46,8 @@ 1.8 1.8 + + --add-exports java.base/sun.security.x509=ALL-UNNAMED true @@ -55,7 +57,17 @@ netty-transport ${project.version} + + ${project.groupId} + netty-handler + ${project.version} + + + org.bouncycastle + bcpkix-jdk15on + true + io.projectreactor.tools blockhound diff --git a/transport-blockhound-tests/src/test/java/io/netty/util/internal/NettyBlockHoundIntegrationTest.java b/transport-blockhound-tests/src/test/java/io/netty/util/internal/NettyBlockHoundIntegrationTest.java index 4482a67f50..8c7720582f 100644 --- a/transport-blockhound-tests/src/test/java/io/netty/util/internal/NettyBlockHoundIntegrationTest.java +++ b/transport-blockhound-tests/src/test/java/io/netty/util/internal/NettyBlockHoundIntegrationTest.java @@ -15,15 +15,41 @@ */ package io.netty.util.internal; +import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.UnpooledByteBufAllocator; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.SslHandshakeCompletionEvent; +import io.netty.handler.ssl.SslProvider; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; +import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.util.ReferenceCountUtil; import io.netty.util.concurrent.GlobalEventExecutor; +import io.netty.util.concurrent.ImmediateEventExecutor; +import io.netty.util.concurrent.ImmediateExecutor; import io.netty.util.internal.Hidden.NettyBlockHoundIntegration; import org.junit.BeforeClass; import org.junit.Test; import reactor.blockhound.BlockHound; import reactor.blockhound.integration.BlockHoundIntegration; +import java.net.InetSocketAddress; import java.util.ServiceLoader; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; @@ -66,4 +92,89 @@ public class NettyBlockHoundIntegrationTest { assertTrue("Blocking call was reported", throwable.getMessage().contains("Blocking call")); } } + + // Tests copied from io.netty.handler.ssl.SslHandlerTest + @Test + public void testHandshakeWithExecutorThatExecuteDirectory() throws Exception { + testHandshakeWithExecutor(Runnable::run); + } + + @Test + public void testHandshakeWithImmediateExecutor() throws Exception { + testHandshakeWithExecutor(ImmediateExecutor.INSTANCE); + } + + @Test + public void testHandshakeWithImmediateEventExecutor() throws Exception { + testHandshakeWithExecutor(ImmediateEventExecutor.INSTANCE); + } + + @Test + public void testHandshakeWithExecutor() throws Exception { + ExecutorService executorService = Executors.newCachedThreadPool(); + try { + testHandshakeWithExecutor(executorService); + } finally { + executorService.shutdown(); + } + } + + private static void testHandshakeWithExecutor(Executor executor) throws Exception { + final SslContext sslClientCtx = SslContextBuilder.forClient() + .trustManager(InsecureTrustManagerFactory.INSTANCE) + .sslProvider(SslProvider.JDK).build(); + + final SelfSignedCertificate cert = new SelfSignedCertificate(); + final SslContext sslServerCtx = SslContextBuilder.forServer(cert.key(), cert.cert()) + .sslProvider(SslProvider.JDK).build(); + + EventLoopGroup group = new NioEventLoopGroup(); + Channel sc = null; + Channel cc = null; + final SslHandler clientSslHandler = sslClientCtx.newHandler(UnpooledByteBufAllocator.DEFAULT, executor); + final SslHandler serverSslHandler = sslServerCtx.newHandler(UnpooledByteBufAllocator.DEFAULT, executor); + + try { + sc = new ServerBootstrap() + .group(group) + .channel(NioServerSocketChannel.class) + .childHandler(serverSslHandler) + .bind(new InetSocketAddress(0)).syncUninterruptibly().channel(); + + ChannelFuture future = new Bootstrap() + .group(group) + .channel(NioSocketChannel.class) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(Channel ch) { + ch.pipeline() + .addLast(clientSslHandler) + .addLast(new ChannelInboundHandlerAdapter() { + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { + if (evt instanceof SslHandshakeCompletionEvent && + ((SslHandshakeCompletionEvent) evt).cause() != null) { + ((SslHandshakeCompletionEvent) evt).cause().printStackTrace(); + } + ctx.fireUserEventTriggered(evt); + } + }); + } + }).connect(sc.localAddress()); + cc = future.syncUninterruptibly().channel(); + + assertTrue(clientSslHandler.handshakeFuture().await().isSuccess()); + assertTrue(serverSslHandler.handshakeFuture().await().isSuccess()); + } finally { + if (cc != null) { + cc.close().syncUninterruptibly(); + } + if (sc != null) { + sc.close().syncUninterruptibly(); + } + group.shutdownGracefully(); + ReferenceCountUtil.release(sslClientCtx); + } + } }