From a8120bb025f0f9392008a1add3472dae738427b0 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Thu, 19 Sep 2024 09:15:03 -0700 Subject: [PATCH 1/6] S2AHandshakerServiceChannel doesn't use custom event loop. --- .../netty/InternalProtocolNegotiators.java | 32 +++++++++++++ .../channel/S2AHandshakerServiceChannel.java | 42 +++++------------ .../S2AProtocolNegotiatorFactory.java | 5 +- .../S2AHandshakerServiceChannelTest.java | 46 +++++++------------ 4 files changed, 64 insertions(+), 61 deletions(-) diff --git a/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java b/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java index 0d309828c6d..9d195c85086 100644 --- a/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java +++ b/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java @@ -17,12 +17,14 @@ package io.grpc.netty; import io.grpc.ChannelLogger; +import io.grpc.internal.ObjectPool; import io.grpc.netty.ProtocolNegotiators.ClientTlsHandler; import io.grpc.netty.ProtocolNegotiators.GrpcNegotiationHandler; import io.grpc.netty.ProtocolNegotiators.WaitUntilActiveHandler; import io.netty.channel.ChannelHandler; import io.netty.handler.ssl.SslContext; import io.netty.util.AsciiString; +import java.util.concurrent.Executor; /** * Internal accessor for {@link ProtocolNegotiators}. @@ -31,6 +33,36 @@ public final class InternalProtocolNegotiators { private InternalProtocolNegotiators() {} + /** + * Returns a {@link ProtocolNegotiator} that ensures the pipeline is set up so that TLS will + * be negotiated, the {@code handler} is added and writes to the {@link io.netty.channel.Channel} + * may happen immediately, even before the TLS Handshake is complete. + * @param executorPool a dedicated {@link Executor} pool for time-consuming TLS tasks + */ + public static InternalProtocolNegotiator.ProtocolNegotiator tls(SslContext sslContext, + ObjectPool executorPool) { + final io.grpc.netty.ProtocolNegotiator negotiator = ProtocolNegotiators.tls(sslContext); + final class TlsNegotiator implements InternalProtocolNegotiator.ProtocolNegotiator { + + @Override + public AsciiString scheme() { + return negotiator.scheme(); + } + + @Override + public ChannelHandler newHandler(GrpcHttp2ConnectionHandler grpcHandler) { + return negotiator.newHandler(grpcHandler); + } + + @Override + public void close() { + negotiator.close(); + } + } + + return new TlsNegotiator(); + } + /** * Returns a {@link ProtocolNegotiator} that ensures the pipeline is set up so that TLS will * be negotiated, the {@code handler} is added and writes to the {@link io.netty.channel.Channel} diff --git a/s2a/src/main/java/io/grpc/s2a/channel/S2AHandshakerServiceChannel.java b/s2a/src/main/java/io/grpc/s2a/channel/S2AHandshakerServiceChannel.java index 75ec7347bb5..6a09f21bd68 100644 --- a/s2a/src/main/java/io/grpc/s2a/channel/S2AHandshakerServiceChannel.java +++ b/s2a/src/main/java/io/grpc/s2a/channel/S2AHandshakerServiceChannel.java @@ -29,10 +29,6 @@ import io.grpc.MethodDescriptor; import io.grpc.internal.SharedResourceHolder.Resource; import io.grpc.netty.NettyChannelBuilder; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.util.concurrent.DefaultThreadFactory; import java.time.Duration; import java.util.Optional; import java.util.concurrent.ConcurrentMap; @@ -61,7 +57,6 @@ public final class S2AHandshakerServiceChannel { private static final ConcurrentMap> SHARED_RESOURCE_CHANNELS = Maps.newConcurrentMap(); - private static final Duration DELEGATE_TERMINATION_TIMEOUT = Duration.ofSeconds(2); private static final Duration CHANNEL_SHUTDOWN_TIMEOUT = Duration.ofSeconds(10); /** @@ -95,41 +90,35 @@ public ChannelResource(String targetAddress, Optional channe } /** - * Creates a {@code EventLoopHoldingChannel} instance to the service running at {@code + * Creates a {@code HandshakerServiceChannel} instance to the service running at {@code * targetAddress}. This channel uses a dedicated thread pool for its {@code EventLoopGroup} * instance to avoid blocking. */ @Override public Channel create() { - EventLoopGroup eventLoopGroup = - new NioEventLoopGroup(1, new DefaultThreadFactory("S2A channel pool", true)); ManagedChannel channel = null; if (channelCredentials.isPresent()) { // Create a secure channel. channel = NettyChannelBuilder.forTarget(targetAddress, channelCredentials.get()) - .channelType(NioSocketChannel.class) .directExecutor() - .eventLoopGroup(eventLoopGroup) .build(); } else { // Create a plaintext channel. channel = NettyChannelBuilder.forTarget(targetAddress) - .channelType(NioSocketChannel.class) .directExecutor() - .eventLoopGroup(eventLoopGroup) .usePlaintext() .build(); } - return EventLoopHoldingChannel.create(channel, eventLoopGroup); + return HandshakerServiceChannel.create(channel); } - /** Destroys a {@code EventLoopHoldingChannel} instance. */ + /** Destroys a {@code HandshakerServiceChannel} instance. */ @Override public void close(Channel instanceChannel) { checkNotNull(instanceChannel); - EventLoopHoldingChannel channel = (EventLoopHoldingChannel) instanceChannel; + HandshakerServiceChannel channel = (HandshakerServiceChannel) instanceChannel; channel.close(); } @@ -140,23 +129,19 @@ public String toString() { } /** - * Manages a channel using a {@link ManagedChannel} instance that belong to the {@code - * EventLoopGroup} thread pool. + * Manages a channel using a {@link ManagedChannel} instance. */ @VisibleForTesting - static class EventLoopHoldingChannel extends Channel { + static class HandshakerServiceChannel extends Channel { private final ManagedChannel delegate; - private final EventLoopGroup eventLoopGroup; - static EventLoopHoldingChannel create(ManagedChannel delegate, EventLoopGroup eventLoopGroup) { + static HandshakerServiceChannel create(ManagedChannel delegate) { checkNotNull(delegate); - checkNotNull(eventLoopGroup); - return new EventLoopHoldingChannel(delegate, eventLoopGroup); + return new HandshakerServiceChannel(delegate); } - private EventLoopHoldingChannel(ManagedChannel delegate, EventLoopGroup eventLoopGroup) { + private HandshakerServiceChannel(ManagedChannel delegate) { this.delegate = delegate; - this.eventLoopGroup = eventLoopGroup; } /** @@ -178,16 +163,11 @@ public ClientCall newCall( @SuppressWarnings("FutureReturnValueIgnored") public void close() { delegate.shutdownNow(); - boolean isDelegateTerminated; try { - isDelegateTerminated = - delegate.awaitTermination(DELEGATE_TERMINATION_TIMEOUT.getSeconds(), SECONDS); + delegate.awaitTermination(CHANNEL_SHUTDOWN_TIMEOUT.getSeconds(), SECONDS); } catch (InterruptedException e) { - isDelegateTerminated = false; + Thread.currentThread().interrupt(); } - long quietPeriodSeconds = isDelegateTerminated ? 0 : 1; - eventLoopGroup.shutdownGracefully( - quietPeriodSeconds, CHANNEL_SHUTDOWN_TIMEOUT.getSeconds(), SECONDS); } } diff --git a/s2a/src/main/java/io/grpc/s2a/handshaker/S2AProtocolNegotiatorFactory.java b/s2a/src/main/java/io/grpc/s2a/handshaker/S2AProtocolNegotiatorFactory.java index 25d1e325ea8..d330efeb3ad 100644 --- a/s2a/src/main/java/io/grpc/s2a/handshaker/S2AProtocolNegotiatorFactory.java +++ b/s2a/src/main/java/io/grpc/s2a/handshaker/S2AProtocolNegotiatorFactory.java @@ -29,6 +29,7 @@ import com.google.common.util.concurrent.MoreExecutors; import com.google.errorprone.annotations.ThreadSafe; import io.grpc.Channel; +import io.grpc.internal.FixedObjectPool; import io.grpc.internal.ObjectPool; import io.grpc.netty.GrpcHttp2ConnectionHandler; import io.grpc.netty.InternalProtocolNegotiator; @@ -227,7 +228,9 @@ protected void handlerAdded0(ChannelHandlerContext ctx) { @Override public void onSuccess(SslContext sslContext) { ChannelHandler handler = - InternalProtocolNegotiators.tls(sslContext).newHandler(grpcHandler); + InternalProtocolNegotiators.tls( + sslContext, new FixedObjectPool<>(Executors.newFixedThreadPool(1))) + .newHandler(grpcHandler); // Remove the bufferReads handler and delegate the rest of the handshake to the TLS // handler. diff --git a/s2a/src/test/java/io/grpc/s2a/channel/S2AHandshakerServiceChannelTest.java b/s2a/src/test/java/io/grpc/s2a/channel/S2AHandshakerServiceChannelTest.java index 57288be1b6f..dc5909442bf 100644 --- a/s2a/src/test/java/io/grpc/s2a/channel/S2AHandshakerServiceChannelTest.java +++ b/s2a/src/test/java/io/grpc/s2a/channel/S2AHandshakerServiceChannelTest.java @@ -18,11 +18,7 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat; -import static java.util.concurrent.TimeUnit.SECONDS; import static org.junit.Assert.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import io.grpc.CallOptions; import io.grpc.Channel; @@ -39,15 +35,13 @@ import io.grpc.benchmarks.Utils; import io.grpc.internal.SharedResourceHolder.Resource; import io.grpc.netty.NettyServerBuilder; -import io.grpc.s2a.channel.S2AHandshakerServiceChannel.EventLoopHoldingChannel; +import io.grpc.s2a.channel.S2AHandshakerServiceChannel.HandshakerServiceChannel; import io.grpc.stub.StreamObserver; import io.grpc.testing.GrpcCleanupRule; import io.grpc.testing.protobuf.SimpleRequest; import io.grpc.testing.protobuf.SimpleResponse; import io.grpc.testing.protobuf.SimpleServiceGrpc; -import io.netty.channel.EventLoopGroup; import java.io.File; -import java.time.Duration; import java.util.Optional; import java.util.concurrent.TimeUnit; import org.junit.Before; @@ -60,8 +54,6 @@ @RunWith(JUnit4.class) public final class S2AHandshakerServiceChannelTest { @ClassRule public static final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); - private static final Duration CHANNEL_SHUTDOWN_TIMEOUT = Duration.ofSeconds(10); - private final EventLoopGroup mockEventLoopGroup = mock(EventLoopGroup.class); private Server mtlsServer; private Server plaintextServer; @@ -191,7 +183,7 @@ public void close_mtlsSuccess() throws Exception { } /** - * Verifies that an {@code EventLoopHoldingChannel}'s {@code newCall} method can be used to + * Verifies that an {@code HandshakerServiceChannel}'s {@code newCall} method can be used to * perform a simple RPC. */ @Test @@ -201,7 +193,7 @@ public void newCall_performSimpleRpcSuccess() { "localhost:" + plaintextServer.getPort(), /* s2aChannelCredentials= */ Optional.empty()); Channel channel = resource.create(); - assertThat(channel).isInstanceOf(EventLoopHoldingChannel.class); + assertThat(channel).isInstanceOf(HandshakerServiceChannel.class); assertThat( SimpleServiceGrpc.newBlockingStub(channel).unaryRpc(SimpleRequest.getDefaultInstance())) .isEqualToDefaultInstance(); @@ -214,53 +206,49 @@ public void newCall_mtlsPerformSimpleRpcSuccess() throws Exception { S2AHandshakerServiceChannel.getChannelResource( "localhost:" + mtlsServer.getPort(), getTlsChannelCredentials()); Channel channel = resource.create(); - assertThat(channel).isInstanceOf(EventLoopHoldingChannel.class); + assertThat(channel).isInstanceOf(HandshakerServiceChannel.class); assertThat( SimpleServiceGrpc.newBlockingStub(channel).unaryRpc(SimpleRequest.getDefaultInstance())) .isEqualToDefaultInstance(); } - /** Creates a {@code EventLoopHoldingChannel} instance and verifies its authority. */ + /** Creates a {@code HandshakerServiceChannel} instance and verifies its authority. */ @Test public void authority_success() throws Exception { ManagedChannel channel = new FakeManagedChannel(true); - EventLoopHoldingChannel eventLoopHoldingChannel = - EventLoopHoldingChannel.create(channel, mockEventLoopGroup); + HandshakerServiceChannel eventLoopHoldingChannel = + HandshakerServiceChannel.create(channel); assertThat(eventLoopHoldingChannel.authority()).isEqualTo("FakeManagedChannel"); } /** - * Creates and closes a {@code EventLoopHoldingChannel} when its {@code ManagedChannel} terminates - * successfully. + * Creates and closes a {@code HandshakerServiceChannel} when its {@code ManagedChannel} + * terminates successfully. */ @Test public void close_withDelegateTerminatedSuccess() throws Exception { ManagedChannel channel = new FakeManagedChannel(true); - EventLoopHoldingChannel eventLoopHoldingChannel = - EventLoopHoldingChannel.create(channel, mockEventLoopGroup); + HandshakerServiceChannel eventLoopHoldingChannel = + HandshakerServiceChannel.create(channel); eventLoopHoldingChannel.close(); assertThat(channel.isShutdown()).isTrue(); - verify(mockEventLoopGroup, times(1)) - .shutdownGracefully(0, CHANNEL_SHUTDOWN_TIMEOUT.getSeconds(), SECONDS); } /** - * Creates and closes a {@code EventLoopHoldingChannel} when its {@code ManagedChannel} does not + * Creates and closes a {@code HandshakerServiceChannel} when its {@code ManagedChannel} does not * terminate successfully. */ @Test public void close_withDelegateTerminatedFailure() throws Exception { ManagedChannel channel = new FakeManagedChannel(false); - EventLoopHoldingChannel eventLoopHoldingChannel = - EventLoopHoldingChannel.create(channel, mockEventLoopGroup); + HandshakerServiceChannel eventLoopHoldingChannel = + HandshakerServiceChannel.create(channel); eventLoopHoldingChannel.close(); assertThat(channel.isShutdown()).isTrue(); - verify(mockEventLoopGroup, times(1)) - .shutdownGracefully(1, CHANNEL_SHUTDOWN_TIMEOUT.getSeconds(), SECONDS); } /** - * Creates and closes a {@code EventLoopHoldingChannel}, creates a new channel from the same + * Creates and closes a {@code HandshakerServiceChannel}, creates a new channel from the same * resource, and verifies that this second channel is useable. */ @Test @@ -273,7 +261,7 @@ public void create_succeedsAfterCloseIsCalledOnce() throws Exception { resource.close(channelOne); Channel channelTwo = resource.create(); - assertThat(channelTwo).isInstanceOf(EventLoopHoldingChannel.class); + assertThat(channelTwo).isInstanceOf(HandshakerServiceChannel.class); assertThat( SimpleServiceGrpc.newBlockingStub(channelTwo) .unaryRpc(SimpleRequest.getDefaultInstance())) @@ -291,7 +279,7 @@ public void create_mtlsSucceedsAfterCloseIsCalledOnce() throws Exception { resource.close(channelOne); Channel channelTwo = resource.create(); - assertThat(channelTwo).isInstanceOf(EventLoopHoldingChannel.class); + assertThat(channelTwo).isInstanceOf(HandshakerServiceChannel.class); assertThat( SimpleServiceGrpc.newBlockingStub(channelTwo) .unaryRpc(SimpleRequest.getDefaultInstance())) From efcd06b71c422fceb1132bcdd7f81e551ecba0e2 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Thu, 19 Sep 2024 09:28:11 -0700 Subject: [PATCH 2/6] clean up comment. --- .../java/io/grpc/s2a/channel/S2AHandshakerServiceChannel.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/s2a/src/main/java/io/grpc/s2a/channel/S2AHandshakerServiceChannel.java b/s2a/src/main/java/io/grpc/s2a/channel/S2AHandshakerServiceChannel.java index 6a09f21bd68..4a258f224fe 100644 --- a/s2a/src/main/java/io/grpc/s2a/channel/S2AHandshakerServiceChannel.java +++ b/s2a/src/main/java/io/grpc/s2a/channel/S2AHandshakerServiceChannel.java @@ -91,8 +91,7 @@ public ChannelResource(String targetAddress, Optional channe /** * Creates a {@code HandshakerServiceChannel} instance to the service running at {@code - * targetAddress}. This channel uses a dedicated thread pool for its {@code EventLoopGroup} - * instance to avoid blocking. + * targetAddress}. */ @Override public Channel create() { From 8be7eecefbcb20a298a18522424e5dc384197891 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Thu, 19 Sep 2024 12:49:43 -0700 Subject: [PATCH 3/6] use executorPool. --- .../main/java/io/grpc/netty/InternalProtocolNegotiators.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java b/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java index 9d195c85086..4fb430ce942 100644 --- a/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java +++ b/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java @@ -41,7 +41,7 @@ private InternalProtocolNegotiators() {} */ public static InternalProtocolNegotiator.ProtocolNegotiator tls(SslContext sslContext, ObjectPool executorPool) { - final io.grpc.netty.ProtocolNegotiator negotiator = ProtocolNegotiators.tls(sslContext); + final io.grpc.netty.ProtocolNegotiator negotiator = ProtocolNegotiators.tls(sslContext, executorPool); final class TlsNegotiator implements InternalProtocolNegotiator.ProtocolNegotiator { @Override From 653ac1e8e415eda8df7c941b1e91296c3ff2eb9b Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Thu, 19 Sep 2024 18:18:55 -0700 Subject: [PATCH 4/6] log when channel not shutdown. --- .../io/grpc/s2a/channel/S2AHandshakerServiceChannel.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/s2a/src/main/java/io/grpc/s2a/channel/S2AHandshakerServiceChannel.java b/s2a/src/main/java/io/grpc/s2a/channel/S2AHandshakerServiceChannel.java index 4a258f224fe..90956907bfe 100644 --- a/s2a/src/main/java/io/grpc/s2a/channel/S2AHandshakerServiceChannel.java +++ b/s2a/src/main/java/io/grpc/s2a/channel/S2AHandshakerServiceChannel.java @@ -32,6 +32,8 @@ import java.time.Duration; import java.util.Optional; import java.util.concurrent.ConcurrentMap; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.annotation.concurrent.ThreadSafe; /** @@ -132,6 +134,8 @@ public String toString() { */ @VisibleForTesting static class HandshakerServiceChannel extends Channel { + private static final Logger logger = + Logger.getLogger(S2AHandshakerServiceChannel.class.getName()); private final ManagedChannel delegate; static HandshakerServiceChannel create(ManagedChannel delegate) { @@ -166,6 +170,7 @@ public void close() { delegate.awaitTermination(CHANNEL_SHUTDOWN_TIMEOUT.getSeconds(), SECONDS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); + logger.log(Level.WARNING, "Channel to S2A was not shutdown."); } } } From 168d62f520f74d6f1e919a5e779d99de6becc502 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Thu, 19 Sep 2024 18:30:57 -0700 Subject: [PATCH 5/6] use a cached threadpool. --- .../java/io/grpc/netty/InternalProtocolNegotiators.java | 3 ++- .../grpc/s2a/handshaker/S2AProtocolNegotiatorFactory.java | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java b/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java index 4fb430ce942..412576b3c10 100644 --- a/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java +++ b/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java @@ -41,7 +41,8 @@ private InternalProtocolNegotiators() {} */ public static InternalProtocolNegotiator.ProtocolNegotiator tls(SslContext sslContext, ObjectPool executorPool) { - final io.grpc.netty.ProtocolNegotiator negotiator = ProtocolNegotiators.tls(sslContext, executorPool); + final io.grpc.netty.ProtocolNegotiator negotiator = ProtocolNegotiators.tls(sslContext, + executorPool); final class TlsNegotiator implements InternalProtocolNegotiator.ProtocolNegotiator { @Override diff --git a/s2a/src/main/java/io/grpc/s2a/handshaker/S2AProtocolNegotiatorFactory.java b/s2a/src/main/java/io/grpc/s2a/handshaker/S2AProtocolNegotiatorFactory.java index d330efeb3ad..14bdc05238d 100644 --- a/s2a/src/main/java/io/grpc/s2a/handshaker/S2AProtocolNegotiatorFactory.java +++ b/s2a/src/main/java/io/grpc/s2a/handshaker/S2AProtocolNegotiatorFactory.java @@ -29,8 +29,9 @@ import com.google.common.util.concurrent.MoreExecutors; import com.google.errorprone.annotations.ThreadSafe; import io.grpc.Channel; -import io.grpc.internal.FixedObjectPool; +import io.grpc.internal.GrpcUtil; import io.grpc.internal.ObjectPool; +import io.grpc.internal.SharedResourcePool; import io.grpc.netty.GrpcHttp2ConnectionHandler; import io.grpc.netty.InternalProtocolNegotiator; import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator; @@ -229,7 +230,8 @@ protected void handlerAdded0(ChannelHandlerContext ctx) { public void onSuccess(SslContext sslContext) { ChannelHandler handler = InternalProtocolNegotiators.tls( - sslContext, new FixedObjectPool<>(Executors.newFixedThreadPool(1))) + sslContext, + SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR)) .newHandler(grpcHandler); // Remove the bufferReads handler and delegate the rest of the handshake to the TLS From 5aa9794d48c60b3a87f69f530f99c1f3b84f328a Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Fri, 20 Sep 2024 08:40:47 -0700 Subject: [PATCH 6/6] update non-executor version. --- .../netty/InternalProtocolNegotiators.java | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java b/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java index 412576b3c10..b9c6a77982a 100644 --- a/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java +++ b/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java @@ -70,26 +70,7 @@ public void close() { * may happen immediately, even before the TLS Handshake is complete. */ public static InternalProtocolNegotiator.ProtocolNegotiator tls(SslContext sslContext) { - final io.grpc.netty.ProtocolNegotiator negotiator = ProtocolNegotiators.tls(sslContext); - final class TlsNegotiator implements InternalProtocolNegotiator.ProtocolNegotiator { - - @Override - public AsciiString scheme() { - return negotiator.scheme(); - } - - @Override - public ChannelHandler newHandler(GrpcHttp2ConnectionHandler grpcHandler) { - return negotiator.newHandler(grpcHandler); - } - - @Override - public void close() { - negotiator.close(); - } - } - - return new TlsNegotiator(); + return tls(sslContext, null); } /**