netty: move internal channel builder code to a special accessor

This commit is contained in:
Carl Mastrangelo 2016-12-13 11:17:00 -08:00 committed by GitHub
parent 178b5260c2
commit 677f05d7fb
3 changed files with 106 additions and 33 deletions

View File

@ -0,0 +1,71 @@
/*
* Copyright 2016, Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package io.grpc.netty;
import io.grpc.Internal;
import io.grpc.internal.ClientTransportFactory;
import io.grpc.internal.ConnectionClientTransport;
import io.grpc.netty.NettyChannelBuilder.NettyTransportFactory;
import java.net.SocketAddress;
/**
* Internal {@link NettyChannelBuilder} accessor. This is intended for usage internal to the gRPC
* team. If you *really* think you need to use this, contact the gRPC team first.
*/
@Internal
public final class InternalNettyChannelBuilder {
/**
* Checks authority upon channel construction. The purpose of this interface is to raise the
* visibility of {@link NettyChannelBuilder.OverrideAuthorityChecker}.
*/
public interface OverrideAuthorityChecker extends NettyChannelBuilder.OverrideAuthorityChecker {}
public static void overrideAuthorityChecker(
NettyChannelBuilder channelBuilder, OverrideAuthorityChecker authorityChecker) {
channelBuilder.overrideAuthorityChecker(authorityChecker);
}
/**
* Creates a custom client transport that allows overriding the protocol negotiator.
*/
public static ConnectionClientTransport newClientTransport(
ClientTransportFactory transportFactory, SocketAddress serverAddress, String authority,
String userAgent, ProtocolNegotiator negotiator) {
// Casting to avoid making {@link NettyTransportFactory} public.
return ((NettyTransportFactory) transportFactory)
.newClientTransport(serverAddress, authority, userAgent, negotiator);
}
private InternalNettyChannelBuilder() {}
}

View File

@ -41,7 +41,6 @@ import com.google.common.base.Preconditions;
import io.grpc.Attributes; import io.grpc.Attributes;
import io.grpc.ExperimentalApi; import io.grpc.ExperimentalApi;
import io.grpc.Internal;
import io.grpc.NameResolver; import io.grpc.NameResolver;
import io.grpc.internal.AbstractManagedChannelImplBuilder; import io.grpc.internal.AbstractManagedChannelImplBuilder;
import io.grpc.internal.ClientTransportFactory; import io.grpc.internal.ClientTransportFactory;
@ -67,7 +66,8 @@ import javax.net.ssl.SSLException;
* A builder to help simplify construction of channels using the Netty transport. * A builder to help simplify construction of channels using the Netty transport.
*/ */
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1784") @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1784")
public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<NettyChannelBuilder> { public final class NettyChannelBuilder
extends AbstractManagedChannelImplBuilder<NettyChannelBuilder> {
public static final int DEFAULT_FLOW_CONTROL_WINDOW = 1048576; // 1MiB public static final int DEFAULT_FLOW_CONTROL_WINDOW = 1048576; // 1MiB
private final Map<ChannelOption<?>, Object> channelOptions = private final Map<ChannelOption<?>, Object> channelOptions =
@ -75,6 +75,7 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
private NegotiationType negotiationType = NegotiationType.TLS; private NegotiationType negotiationType = NegotiationType.TLS;
private ProtocolNegotiator protocolNegotiator; private ProtocolNegotiator protocolNegotiator;
private OverrideAuthorityChecker authorityChecker;
private Class<? extends Channel> channelType = NioSocketChannel.class; private Class<? extends Channel> channelType = NioSocketChannel.class;
@Nullable @Nullable
@ -135,7 +136,7 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
/** /**
* Specifies the channel type to use, by default we use {@link NioSocketChannel}. * Specifies the channel type to use, by default we use {@link NioSocketChannel}.
*/ */
public final NettyChannelBuilder channelType(Class<? extends Channel> channelType) { public NettyChannelBuilder channelType(Class<? extends Channel> channelType) {
this.channelType = Preconditions.checkNotNull(channelType, "channelType"); this.channelType = Preconditions.checkNotNull(channelType, "channelType");
return this; return this;
} }
@ -144,7 +145,7 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
* Specifies a channel option. As the underlying channel as well as network implementation may * Specifies a channel option. As the underlying channel as well as network implementation may
* ignore this value applications should consider it a hint. * ignore this value applications should consider it a hint.
*/ */
public final <T> NettyChannelBuilder withOption(ChannelOption<T> option, T value) { public <T> NettyChannelBuilder withOption(ChannelOption<T> option, T value) {
channelOptions.put(option, value); channelOptions.put(option, value);
return this; return this;
} }
@ -154,24 +155,11 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
* *
* <p>Default: <code>TLS</code> * <p>Default: <code>TLS</code>
*/ */
public final NettyChannelBuilder negotiationType(NegotiationType type) { public NettyChannelBuilder negotiationType(NegotiationType type) {
negotiationType = type; negotiationType = type;
return this; return this;
} }
/**
* Sets the {@link ProtocolNegotiator} to be used. If non-{@code null}, overrides the value
* specified in {@link #negotiationType(NegotiationType)} or {@link #usePlaintext(boolean)}.
*
* <p>Default: {@code null}.
*/
@Internal
public final NettyChannelBuilder protocolNegotiator(
@Nullable ProtocolNegotiator protocolNegotiator) {
this.protocolNegotiator = protocolNegotiator;
return this;
}
/** /**
* Provides an EventGroupLoop to be used by the netty transport. * Provides an EventGroupLoop to be used by the netty transport.
* *
@ -181,7 +169,7 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
* <p>The channel won't take ownership of the given EventLoopGroup. It's caller's responsibility * <p>The channel won't take ownership of the given EventLoopGroup. It's caller's responsibility
* to shut it down when it's desired. * to shut it down when it's desired.
*/ */
public final NettyChannelBuilder eventLoopGroup(@Nullable EventLoopGroup eventLoopGroup) { public NettyChannelBuilder eventLoopGroup(@Nullable EventLoopGroup eventLoopGroup) {
this.eventLoopGroup = eventLoopGroup; this.eventLoopGroup = eventLoopGroup;
return this; return this;
} }
@ -190,7 +178,7 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
* SSL/TLS context to use instead of the system default. It must have been configured with {@link * SSL/TLS context to use instead of the system default. It must have been configured with {@link
* GrpcSslContexts}, but options could have been overridden. * GrpcSslContexts}, but options could have been overridden.
*/ */
public final NettyChannelBuilder sslContext(SslContext sslContext) { public NettyChannelBuilder sslContext(SslContext sslContext) {
if (sslContext != null) { if (sslContext != null) {
checkArgument(sslContext.isClient(), checkArgument(sslContext.isClient(),
"Server SSL context can not be used for client channel"); "Server SSL context can not be used for client channel");
@ -204,7 +192,7 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
* Sets the flow control window in bytes. If not called, the default value * Sets the flow control window in bytes. If not called, the default value
* is {@link #DEFAULT_FLOW_CONTROL_WINDOW}). * is {@link #DEFAULT_FLOW_CONTROL_WINDOW}).
*/ */
public final NettyChannelBuilder flowControlWindow(int flowControlWindow) { public NettyChannelBuilder flowControlWindow(int flowControlWindow) {
checkArgument(flowControlWindow > 0, "flowControlWindow must be positive"); checkArgument(flowControlWindow > 0, "flowControlWindow must be positive");
this.flowControlWindow = flowControlWindow; this.flowControlWindow = flowControlWindow;
return this; return this;
@ -216,7 +204,7 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
* @deprecated Use {@link #maxInboundMessageSize} instead * @deprecated Use {@link #maxInboundMessageSize} instead
*/ */
@Deprecated @Deprecated
public final NettyChannelBuilder maxMessageSize(int maxMessageSize) { public NettyChannelBuilder maxMessageSize(int maxMessageSize) {
maxInboundMessageSize(maxMessageSize); maxInboundMessageSize(maxMessageSize);
return this; return this;
} }
@ -225,7 +213,7 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
* Sets the maximum size of header list allowed to be received on the channel. If not called, * Sets the maximum size of header list allowed to be received on the channel. If not called,
* defaults to {@link GrpcUtil#DEFAULT_MAX_HEADER_LIST_SIZE}. * defaults to {@link GrpcUtil#DEFAULT_MAX_HEADER_LIST_SIZE}.
*/ */
public final NettyChannelBuilder maxHeaderListSize(int maxHeaderListSize) { public NettyChannelBuilder maxHeaderListSize(int maxHeaderListSize) {
checkArgument(maxHeaderListSize > 0, "maxHeaderListSize must be > 0"); checkArgument(maxHeaderListSize > 0, "maxHeaderListSize must be > 0");
this.maxHeaderListSize = maxHeaderListSize; this.maxHeaderListSize = maxHeaderListSize;
return this; return this;
@ -236,7 +224,7 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
* {@code PLAINTEXT_UPGRADE}. * {@code PLAINTEXT_UPGRADE}.
*/ */
@Override @Override
public final NettyChannelBuilder usePlaintext(boolean skipNegotiation) { public NettyChannelBuilder usePlaintext(boolean skipNegotiation) {
if (skipNegotiation) { if (skipNegotiation) {
negotiationType(NegotiationType.PLAINTEXT); negotiationType(NegotiationType.PLAINTEXT);
} else { } else {
@ -297,6 +285,10 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
.set(NameResolver.Factory.PARAMS_DEFAULT_PORT, defaultPort).build(); .set(NameResolver.Factory.PARAMS_DEFAULT_PORT, defaultPort).build();
} }
void overrideAuthorityChecker(@Nullable OverrideAuthorityChecker authorityChecker) {
this.authorityChecker = authorityChecker;
}
@VisibleForTesting @VisibleForTesting
static ProtocolNegotiator createProtocolNegotiator( static ProtocolNegotiator createProtocolNegotiator(
String authority, String authority,
@ -321,11 +313,22 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
} }
} }
interface OverrideAuthorityChecker {
String checkAuthority(String authority);
}
@Override
protected String checkAuthority(String authority) {
if (authorityChecker != null) {
return authorityChecker.checkAuthority(authority);
}
return super.checkAuthority(authority);
}
/** /**
* Creates Netty transports. Exposed for internal use, as it should be private. * Creates Netty transports. Exposed for internal use, as it should be private.
*/ */
@Internal static class NettyTransportFactory implements ClientTransportFactory {
protected static final class NettyTransportFactory implements ClientTransportFactory {
private final Class<? extends Channel> channelType; private final Class<? extends Channel> channelType;
private final Map<ChannelOption<?>, ?> channelOptions; private final Map<ChannelOption<?>, ?> channelOptions;
private final NegotiationType negotiationType; private final NegotiationType negotiationType;
@ -379,8 +382,7 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
return newClientTransport(serverAddress, authority, userAgent, negotiator); return newClientTransport(serverAddress, authority, userAgent, negotiator);
} }
@Internal // This is strictly for internal use. Depend on this at your own peril. ConnectionClientTransport newClientTransport(
public ConnectionClientTransport newClientTransport(
SocketAddress serverAddress, String authority, String userAgent, SocketAddress serverAddress, String authority, String userAgent,
ProtocolNegotiator negotiator) { ProtocolNegotiator negotiator) {
if (closed) { if (closed) {

View File

@ -33,10 +33,10 @@ package io.grpc.netty;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import io.grpc.internal.ClientTransportFactory; import io.grpc.internal.ClientTransportFactory;
import io.grpc.netty.InternalNettyChannelBuilder.OverrideAuthorityChecker;
import io.grpc.netty.ProtocolNegotiators.TlsNegotiator; import io.grpc.netty.ProtocolNegotiators.TlsNegotiator;
import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContext;
@ -59,13 +59,13 @@ public class NettyChannelBuilderTest {
@Test @Test
public void overrideAllowsInvalidAuthority() { public void overrideAllowsInvalidAuthority() {
NettyChannelBuilder builder = new NettyChannelBuilder(new SocketAddress(){}) { NettyChannelBuilder builder = new NettyChannelBuilder(new SocketAddress(){});
InternalNettyChannelBuilder.overrideAuthorityChecker(builder, new OverrideAuthorityChecker() {
@Override @Override
protected String checkAuthority(String authority) { public String checkAuthority(String authority) {
return authority; return authority;
} }
}; });
ClientTransportFactory factory = builder.overrideAuthority("[invalidauthority") ClientTransportFactory factory = builder.overrideAuthority("[invalidauthority")
.negotiationType(NegotiationType.PLAINTEXT) .negotiationType(NegotiationType.PLAINTEXT)
.buildTransportFactory(); .buildTransportFactory();