mirror of https://github.com/grpc/grpc-java.git
netty: Initialize ProtocolNegotiators eagerly
This simplifies the construction paradigm and leads to the eventual removal of TransportCreationParamsFilterFactory. The eventual end goal is to be able to shut down ProtocolNegotiators as is necessary for ALTS. The only reason the initialization was delayed was for 'authority', so we now plumb the authority through GrpcHttp2ConnectionHandler.
This commit is contained in:
parent
c8975e987b
commit
7efbc36c72
|
|
@ -144,7 +144,7 @@ public final class GoogleDefaultChannelBuilder
|
||||||
"%s must be a InetSocketAddress",
|
"%s must be a InetSocketAddress",
|
||||||
serverAddress);
|
serverAddress);
|
||||||
final GoogleDefaultProtocolNegotiator negotiator =
|
final GoogleDefaultProtocolNegotiator negotiator =
|
||||||
new GoogleDefaultProtocolNegotiator(altsHandshakerFactory, sslContext, authority);
|
new GoogleDefaultProtocolNegotiator(altsHandshakerFactory, sslContext);
|
||||||
return new TransportCreationParamsFilter() {
|
return new TransportCreationParamsFilter() {
|
||||||
@Override
|
@Override
|
||||||
public SocketAddress getTargetServerAddress() {
|
public SocketAddress getTargetServerAddress() {
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,9 @@ public final class GoogleDefaultProtocolNegotiator implements ProtocolNegotiator
|
||||||
private final ProtocolNegotiator altsProtocolNegotiator;
|
private final ProtocolNegotiator altsProtocolNegotiator;
|
||||||
private final ProtocolNegotiator tlsProtocolNegotiator;
|
private final ProtocolNegotiator tlsProtocolNegotiator;
|
||||||
|
|
||||||
public GoogleDefaultProtocolNegotiator(
|
public GoogleDefaultProtocolNegotiator(TsiHandshakerFactory altsFactory, SslContext sslContext) {
|
||||||
TsiHandshakerFactory altsFactory, SslContext sslContext, String authority) {
|
|
||||||
altsProtocolNegotiator = AltsProtocolNegotiator.create(altsFactory);
|
altsProtocolNegotiator = AltsProtocolNegotiator.create(altsFactory);
|
||||||
tlsProtocolNegotiator = ProtocolNegotiators.tls(sslContext, authority);
|
tlsProtocolNegotiator = ProtocolNegotiators.tls(sslContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
|
|
||||||
|
|
@ -84,4 +84,13 @@ public abstract class GrpcHttp2ConnectionHandler extends Http2ConnectionHandler
|
||||||
public Attributes getEagAttributes() {
|
public Attributes getEagAttributes() {
|
||||||
return Attributes.EMPTY;
|
return Attributes.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the authority of the server. Only available on the client-side.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException if on server-side
|
||||||
|
*/
|
||||||
|
public String getAuthority() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -331,8 +331,25 @@ public final class NettyChannelBuilder
|
||||||
@CheckReturnValue
|
@CheckReturnValue
|
||||||
@Internal
|
@Internal
|
||||||
protected ClientTransportFactory buildTransportFactory() {
|
protected ClientTransportFactory buildTransportFactory() {
|
||||||
return new NettyTransportFactory(dynamicParamsFactory, channelType, channelOptions,
|
TransportCreationParamsFilterFactory transportCreationParamsFilterFactory =
|
||||||
negotiationType, sslContext, eventLoopGroup, flowControlWindow, maxInboundMessageSize(),
|
dynamicParamsFactory;
|
||||||
|
if (transportCreationParamsFilterFactory == null) {
|
||||||
|
SslContext localSslContext = sslContext;
|
||||||
|
if (negotiationType == NegotiationType.TLS && localSslContext == null) {
|
||||||
|
try {
|
||||||
|
localSslContext = GrpcSslContexts.forClient().build();
|
||||||
|
} catch (SSLException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ProtocolNegotiator negotiator =
|
||||||
|
createProtocolNegotiatorByType(negotiationType, localSslContext);
|
||||||
|
transportCreationParamsFilterFactory =
|
||||||
|
new DefaultNettyTransportCreationParamsFilterFactory(negotiator);
|
||||||
|
}
|
||||||
|
return new NettyTransportFactory(
|
||||||
|
transportCreationParamsFilterFactory, channelType, channelOptions,
|
||||||
|
eventLoopGroup, flowControlWindow, maxInboundMessageSize(),
|
||||||
maxHeaderListSize, keepAliveTimeNanos, keepAliveTimeoutNanos, keepAliveWithoutCalls,
|
maxHeaderListSize, keepAliveTimeNanos, keepAliveTimeoutNanos, keepAliveWithoutCalls,
|
||||||
transportTracerFactory.create());
|
transportTracerFactory.create());
|
||||||
}
|
}
|
||||||
|
|
@ -362,23 +379,7 @@ public final class NettyChannelBuilder
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@CheckReturnValue
|
@CheckReturnValue
|
||||||
static ProtocolNegotiator createProtocolNegotiator(
|
static ProtocolNegotiator createProtocolNegotiatorByType(
|
||||||
String authority,
|
|
||||||
NegotiationType negotiationType,
|
|
||||||
SslContext sslContext,
|
|
||||||
ProxyParameters proxy) {
|
|
||||||
ProtocolNegotiator negotiator =
|
|
||||||
createProtocolNegotiatorByType(authority, negotiationType, sslContext);
|
|
||||||
if (proxy != null) {
|
|
||||||
negotiator = ProtocolNegotiators.httpProxy(
|
|
||||||
proxy.proxyAddress, proxy.username, proxy.password, negotiator);
|
|
||||||
}
|
|
||||||
return negotiator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@CheckReturnValue
|
|
||||||
private static ProtocolNegotiator createProtocolNegotiatorByType(
|
|
||||||
String authority,
|
|
||||||
NegotiationType negotiationType,
|
NegotiationType negotiationType,
|
||||||
SslContext sslContext) {
|
SslContext sslContext) {
|
||||||
switch (negotiationType) {
|
switch (negotiationType) {
|
||||||
|
|
@ -387,7 +388,7 @@ public final class NettyChannelBuilder
|
||||||
case PLAINTEXT_UPGRADE:
|
case PLAINTEXT_UPGRADE:
|
||||||
return ProtocolNegotiators.plaintextUpgrade();
|
return ProtocolNegotiators.plaintextUpgrade();
|
||||||
case TLS:
|
case TLS:
|
||||||
return ProtocolNegotiators.tls(sslContext, authority);
|
return ProtocolNegotiators.tls(sslContext);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Unsupported negotiationType: " + negotiationType);
|
throw new IllegalArgumentException("Unsupported negotiationType: " + negotiationType);
|
||||||
}
|
}
|
||||||
|
|
@ -461,7 +462,6 @@ public final class NettyChannelBuilder
|
||||||
private final TransportCreationParamsFilterFactory transportCreationParamsFilterFactory;
|
private final TransportCreationParamsFilterFactory transportCreationParamsFilterFactory;
|
||||||
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 EventLoopGroup group;
|
private final EventLoopGroup group;
|
||||||
private final boolean usingSharedGroup;
|
private final boolean usingSharedGroup;
|
||||||
private final int flowControlWindow;
|
private final int flowControlWindow;
|
||||||
|
|
@ -476,27 +476,20 @@ public final class NettyChannelBuilder
|
||||||
|
|
||||||
NettyTransportFactory(TransportCreationParamsFilterFactory transportCreationParamsFilterFactory,
|
NettyTransportFactory(TransportCreationParamsFilterFactory transportCreationParamsFilterFactory,
|
||||||
Class<? extends Channel> channelType, Map<ChannelOption<?>, ?> channelOptions,
|
Class<? extends Channel> channelType, Map<ChannelOption<?>, ?> channelOptions,
|
||||||
NegotiationType negotiationType, SslContext sslContext, EventLoopGroup group,
|
EventLoopGroup group, int flowControlWindow, int maxMessageSize, int maxHeaderListSize,
|
||||||
int flowControlWindow, int maxMessageSize, int maxHeaderListSize,
|
|
||||||
long keepAliveTimeNanos, long keepAliveTimeoutNanos, boolean keepAliveWithoutCalls,
|
long keepAliveTimeNanos, long keepAliveTimeoutNanos, boolean keepAliveWithoutCalls,
|
||||||
TransportTracer transportTracer) {
|
TransportTracer transportTracer) {
|
||||||
this.channelType = channelType;
|
|
||||||
this.negotiationType = negotiationType;
|
|
||||||
this.channelOptions = new HashMap<ChannelOption<?>, Object>(channelOptions);
|
|
||||||
this.transportTracer = transportTracer;
|
|
||||||
|
|
||||||
if (transportCreationParamsFilterFactory == null) {
|
|
||||||
transportCreationParamsFilterFactory =
|
|
||||||
new DefaultNettyTransportCreationParamsFilterFactory(sslContext);
|
|
||||||
}
|
|
||||||
this.transportCreationParamsFilterFactory = transportCreationParamsFilterFactory;
|
this.transportCreationParamsFilterFactory = transportCreationParamsFilterFactory;
|
||||||
|
this.channelType = channelType;
|
||||||
|
this.channelOptions = new HashMap<ChannelOption<?>, Object>(channelOptions);
|
||||||
this.flowControlWindow = flowControlWindow;
|
this.flowControlWindow = flowControlWindow;
|
||||||
this.maxMessageSize = maxMessageSize;
|
this.maxMessageSize = maxMessageSize;
|
||||||
this.maxHeaderListSize = maxHeaderListSize;
|
this.maxHeaderListSize = maxHeaderListSize;
|
||||||
this.keepAliveTimeNanos = new AtomicBackoff("keepalive time nanos", keepAliveTimeNanos);
|
this.keepAliveTimeNanos = new AtomicBackoff("keepalive time nanos", keepAliveTimeNanos);
|
||||||
this.keepAliveTimeoutNanos = keepAliveTimeoutNanos;
|
this.keepAliveTimeoutNanos = keepAliveTimeoutNanos;
|
||||||
this.keepAliveWithoutCalls = keepAliveWithoutCalls;
|
this.keepAliveWithoutCalls = keepAliveWithoutCalls;
|
||||||
|
this.transportTracer = transportTracer;
|
||||||
|
|
||||||
usingSharedGroup = group == null;
|
usingSharedGroup = group == null;
|
||||||
if (usingSharedGroup) {
|
if (usingSharedGroup) {
|
||||||
// The group was unspecified, using the shared group.
|
// The group was unspecified, using the shared group.
|
||||||
|
|
@ -550,71 +543,69 @@ public final class NettyChannelBuilder
|
||||||
SharedResourceHolder.release(Utils.DEFAULT_WORKER_EVENT_LOOP_GROUP, group);
|
SharedResourceHolder.release(Utils.DEFAULT_WORKER_EVENT_LOOP_GROUP, group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final class DefaultNettyTransportCreationParamsFilterFactory
|
private static final class DefaultNettyTransportCreationParamsFilterFactory
|
||||||
implements TransportCreationParamsFilterFactory {
|
implements TransportCreationParamsFilterFactory {
|
||||||
private final SslContext sslContext;
|
final ProtocolNegotiator negotiator;
|
||||||
|
|
||||||
private DefaultNettyTransportCreationParamsFilterFactory(SslContext sslContext) {
|
DefaultNettyTransportCreationParamsFilterFactory(ProtocolNegotiator negotiator) {
|
||||||
if (negotiationType == NegotiationType.TLS && sslContext == null) {
|
this.negotiator = negotiator;
|
||||||
try {
|
}
|
||||||
sslContext = GrpcSslContexts.forClient().build();
|
|
||||||
} catch (SSLException ex) {
|
@Override
|
||||||
throw new RuntimeException(ex);
|
public TransportCreationParamsFilter create(
|
||||||
}
|
SocketAddress targetServerAddress,
|
||||||
}
|
String authority,
|
||||||
this.sslContext = sslContext;
|
String userAgent,
|
||||||
|
ProxyParameters proxyParams) {
|
||||||
|
ProtocolNegotiator localNegotiator = negotiator;
|
||||||
|
if (proxyParams != null) {
|
||||||
|
localNegotiator = ProtocolNegotiators.httpProxy(
|
||||||
|
proxyParams.proxyAddress, proxyParams.username, proxyParams.password, negotiator);
|
||||||
}
|
}
|
||||||
|
return new DynamicNettyTransportParams(
|
||||||
|
targetServerAddress, authority, userAgent, localNegotiator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@CheckReturnValue
|
||||||
public TransportCreationParamsFilter create(
|
private static final class DynamicNettyTransportParams implements TransportCreationParamsFilter {
|
||||||
SocketAddress targetServerAddress,
|
|
||||||
String authority,
|
|
||||||
String userAgent,
|
|
||||||
ProxyParameters proxyParams) {
|
|
||||||
return new DynamicNettyTransportParams(
|
|
||||||
targetServerAddress, authority, userAgent, proxyParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
@CheckReturnValue
|
private final SocketAddress targetServerAddress;
|
||||||
private final class DynamicNettyTransportParams implements TransportCreationParamsFilter {
|
private final String authority;
|
||||||
|
@Nullable private final String userAgent;
|
||||||
|
private final ProtocolNegotiator protocolNegotiator;
|
||||||
|
|
||||||
private final SocketAddress targetServerAddress;
|
private DynamicNettyTransportParams(
|
||||||
private final String authority;
|
SocketAddress targetServerAddress,
|
||||||
@Nullable private final String userAgent;
|
String authority,
|
||||||
private ProxyParameters proxyParams;
|
String userAgent,
|
||||||
|
ProtocolNegotiator protocolNegotiator) {
|
||||||
|
this.targetServerAddress = targetServerAddress;
|
||||||
|
this.authority = authority;
|
||||||
|
this.userAgent = userAgent;
|
||||||
|
this.protocolNegotiator = protocolNegotiator;
|
||||||
|
}
|
||||||
|
|
||||||
private DynamicNettyTransportParams(
|
@Override
|
||||||
SocketAddress targetServerAddress,
|
public SocketAddress getTargetServerAddress() {
|
||||||
String authority,
|
return targetServerAddress;
|
||||||
String userAgent,
|
}
|
||||||
ProxyParameters proxyParams) {
|
|
||||||
this.targetServerAddress = targetServerAddress;
|
|
||||||
this.authority = authority;
|
|
||||||
this.userAgent = userAgent;
|
|
||||||
this.proxyParams = proxyParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SocketAddress getTargetServerAddress() {
|
public String getAuthority() {
|
||||||
return targetServerAddress;
|
return authority;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAuthority() {
|
public String getUserAgent() {
|
||||||
return authority;
|
return userAgent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUserAgent() {
|
public ProtocolNegotiator getProtocolNegotiator() {
|
||||||
return userAgent;
|
return protocolNegotiator;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ProtocolNegotiator getProtocolNegotiator() {
|
|
||||||
return createProtocolNegotiator(authority, negotiationType, sslContext, proxyParams);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ class NettyClientHandler extends AbstractNettyHandler {
|
||||||
private final Supplier<Stopwatch> stopwatchFactory;
|
private final Supplier<Stopwatch> stopwatchFactory;
|
||||||
private final TransportTracer transportTracer;
|
private final TransportTracer transportTracer;
|
||||||
private final Attributes eagAttributes;
|
private final Attributes eagAttributes;
|
||||||
|
private final String authority;
|
||||||
private WriteQueue clientWriteQueue;
|
private WriteQueue clientWriteQueue;
|
||||||
private Http2Ping ping;
|
private Http2Ping ping;
|
||||||
private Attributes attributes = Attributes.EMPTY;
|
private Attributes attributes = Attributes.EMPTY;
|
||||||
|
|
@ -116,7 +117,8 @@ class NettyClientHandler extends AbstractNettyHandler {
|
||||||
Supplier<Stopwatch> stopwatchFactory,
|
Supplier<Stopwatch> stopwatchFactory,
|
||||||
Runnable tooManyPingsRunnable,
|
Runnable tooManyPingsRunnable,
|
||||||
TransportTracer transportTracer,
|
TransportTracer transportTracer,
|
||||||
Attributes eagAttributes) {
|
Attributes eagAttributes,
|
||||||
|
String authority) {
|
||||||
Preconditions.checkArgument(maxHeaderListSize > 0, "maxHeaderListSize must be positive");
|
Preconditions.checkArgument(maxHeaderListSize > 0, "maxHeaderListSize must be positive");
|
||||||
Http2HeadersDecoder headersDecoder = new GrpcHttp2ClientHeadersDecoder(maxHeaderListSize);
|
Http2HeadersDecoder headersDecoder = new GrpcHttp2ClientHeadersDecoder(maxHeaderListSize);
|
||||||
Http2FrameReader frameReader = new DefaultHttp2FrameReader(headersDecoder);
|
Http2FrameReader frameReader = new DefaultHttp2FrameReader(headersDecoder);
|
||||||
|
|
@ -139,7 +141,8 @@ class NettyClientHandler extends AbstractNettyHandler {
|
||||||
stopwatchFactory,
|
stopwatchFactory,
|
||||||
tooManyPingsRunnable,
|
tooManyPingsRunnable,
|
||||||
transportTracer,
|
transportTracer,
|
||||||
eagAttributes);
|
eagAttributes,
|
||||||
|
authority);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
|
@ -154,7 +157,8 @@ class NettyClientHandler extends AbstractNettyHandler {
|
||||||
Supplier<Stopwatch> stopwatchFactory,
|
Supplier<Stopwatch> stopwatchFactory,
|
||||||
Runnable tooManyPingsRunnable,
|
Runnable tooManyPingsRunnable,
|
||||||
TransportTracer transportTracer,
|
TransportTracer transportTracer,
|
||||||
Attributes eagAttributes) {
|
Attributes eagAttributes,
|
||||||
|
String authority) {
|
||||||
Preconditions.checkNotNull(connection, "connection");
|
Preconditions.checkNotNull(connection, "connection");
|
||||||
Preconditions.checkNotNull(frameReader, "frameReader");
|
Preconditions.checkNotNull(frameReader, "frameReader");
|
||||||
Preconditions.checkNotNull(lifecycleManager, "lifecycleManager");
|
Preconditions.checkNotNull(lifecycleManager, "lifecycleManager");
|
||||||
|
|
@ -163,6 +167,7 @@ class NettyClientHandler extends AbstractNettyHandler {
|
||||||
Preconditions.checkNotNull(stopwatchFactory, "stopwatchFactory");
|
Preconditions.checkNotNull(stopwatchFactory, "stopwatchFactory");
|
||||||
Preconditions.checkNotNull(tooManyPingsRunnable, "tooManyPingsRunnable");
|
Preconditions.checkNotNull(tooManyPingsRunnable, "tooManyPingsRunnable");
|
||||||
Preconditions.checkNotNull(eagAttributes, "eagAttributes");
|
Preconditions.checkNotNull(eagAttributes, "eagAttributes");
|
||||||
|
Preconditions.checkNotNull(authority, "authority");
|
||||||
|
|
||||||
Http2FrameLogger frameLogger = new Http2FrameLogger(LogLevel.DEBUG, NettyClientHandler.class);
|
Http2FrameLogger frameLogger = new Http2FrameLogger(LogLevel.DEBUG, NettyClientHandler.class);
|
||||||
frameReader = new Http2InboundFrameLogger(frameReader, frameLogger);
|
frameReader = new Http2InboundFrameLogger(frameReader, frameLogger);
|
||||||
|
|
@ -205,7 +210,8 @@ class NettyClientHandler extends AbstractNettyHandler {
|
||||||
stopwatchFactory,
|
stopwatchFactory,
|
||||||
tooManyPingsRunnable,
|
tooManyPingsRunnable,
|
||||||
transportTracer,
|
transportTracer,
|
||||||
eagAttributes);
|
eagAttributes,
|
||||||
|
authority);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NettyClientHandler(
|
private NettyClientHandler(
|
||||||
|
|
@ -217,13 +223,15 @@ class NettyClientHandler extends AbstractNettyHandler {
|
||||||
Supplier<Stopwatch> stopwatchFactory,
|
Supplier<Stopwatch> stopwatchFactory,
|
||||||
final Runnable tooManyPingsRunnable,
|
final Runnable tooManyPingsRunnable,
|
||||||
TransportTracer transportTracer,
|
TransportTracer transportTracer,
|
||||||
Attributes eagAttributes) {
|
Attributes eagAttributes,
|
||||||
|
String authority) {
|
||||||
super(/* channelUnused= */ null, decoder, encoder, settings);
|
super(/* channelUnused= */ null, decoder, encoder, settings);
|
||||||
this.lifecycleManager = lifecycleManager;
|
this.lifecycleManager = lifecycleManager;
|
||||||
this.keepAliveManager = keepAliveManager;
|
this.keepAliveManager = keepAliveManager;
|
||||||
this.stopwatchFactory = stopwatchFactory;
|
this.stopwatchFactory = stopwatchFactory;
|
||||||
this.transportTracer = Preconditions.checkNotNull(transportTracer);
|
this.transportTracer = Preconditions.checkNotNull(transportTracer);
|
||||||
this.eagAttributes = eagAttributes;
|
this.eagAttributes = eagAttributes;
|
||||||
|
this.authority = authority;
|
||||||
|
|
||||||
// Set the frame listener on the decoder.
|
// Set the frame listener on the decoder.
|
||||||
decoder().frameListener(new FrameListener());
|
decoder().frameListener(new FrameListener());
|
||||||
|
|
@ -429,6 +437,11 @@ class NettyClientHandler extends AbstractNettyHandler {
|
||||||
return eagAttributes;
|
return eagAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthority() {
|
||||||
|
return authority;
|
||||||
|
}
|
||||||
|
|
||||||
InternalChannelz.Security getSecurityInfo() {
|
InternalChannelz.Security getSecurityInfo() {
|
||||||
return securityInfo;
|
return securityInfo;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ class NettyClientTransport implements ConnectionClientTransport {
|
||||||
private final Class<? extends Channel> channelType;
|
private final Class<? extends Channel> channelType;
|
||||||
private final EventLoopGroup group;
|
private final EventLoopGroup group;
|
||||||
private final ProtocolNegotiator negotiator;
|
private final ProtocolNegotiator negotiator;
|
||||||
|
private final String authorityString;
|
||||||
private final AsciiString authority;
|
private final AsciiString authority;
|
||||||
private final AsciiString userAgent;
|
private final AsciiString userAgent;
|
||||||
private final int flowControlWindow;
|
private final int flowControlWindow;
|
||||||
|
|
@ -109,6 +110,7 @@ class NettyClientTransport implements ConnectionClientTransport {
|
||||||
this.keepAliveTimeNanos = keepAliveTimeNanos;
|
this.keepAliveTimeNanos = keepAliveTimeNanos;
|
||||||
this.keepAliveTimeoutNanos = keepAliveTimeoutNanos;
|
this.keepAliveTimeoutNanos = keepAliveTimeoutNanos;
|
||||||
this.keepAliveWithoutCalls = keepAliveWithoutCalls;
|
this.keepAliveWithoutCalls = keepAliveWithoutCalls;
|
||||||
|
this.authorityString = authority;
|
||||||
this.authority = new AsciiString(authority);
|
this.authority = new AsciiString(authority);
|
||||||
this.userAgent = new AsciiString(GrpcUtil.getGrpcUserAgent("netty", userAgent));
|
this.userAgent = new AsciiString(GrpcUtil.getGrpcUserAgent("netty", userAgent));
|
||||||
this.tooManyPingsRunnable =
|
this.tooManyPingsRunnable =
|
||||||
|
|
@ -195,7 +197,8 @@ class NettyClientTransport implements ConnectionClientTransport {
|
||||||
GrpcUtil.STOPWATCH_SUPPLIER,
|
GrpcUtil.STOPWATCH_SUPPLIER,
|
||||||
tooManyPingsRunnable,
|
tooManyPingsRunnable,
|
||||||
transportTracer,
|
transportTracer,
|
||||||
eagAttributes);
|
eagAttributes,
|
||||||
|
authorityString);
|
||||||
NettyHandlerSettings.setAutoWindow(handler);
|
NettyHandlerSettings.setAutoWindow(handler);
|
||||||
|
|
||||||
negotiationHandler = negotiator.newHandler(handler);
|
negotiationHandler = negotiator.newHandler(handler);
|
||||||
|
|
|
||||||
|
|
@ -259,57 +259,49 @@ public final class ProtocolNegotiators {
|
||||||
* be negotiated, the {@code handler} is added and writes to the {@link io.netty.channel.Channel}
|
* 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.
|
* may happen immediately, even before the TLS Handshake is complete.
|
||||||
*/
|
*/
|
||||||
public static ProtocolNegotiator tls(SslContext sslContext, String authority) {
|
public static ProtocolNegotiator tls(SslContext sslContext) {
|
||||||
Preconditions.checkNotNull(sslContext, "sslContext");
|
return new TlsNegotiator(sslContext);
|
||||||
URI uri = GrpcUtil.authorityToUri(Preconditions.checkNotNull(authority, "authority"));
|
|
||||||
String host;
|
|
||||||
int port;
|
|
||||||
if (uri.getHost() != null) {
|
|
||||||
host = uri.getHost();
|
|
||||||
port = uri.getPort();
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Implementation note: We pick -1 as the port here rather than deriving it from the original
|
|
||||||
* socket address. The SSL engine doens't use this port number when contacting the remote
|
|
||||||
* server, but rather it is used for other things like SSL Session caching. When an invalid
|
|
||||||
* authority is provided (like "bad_cert"), picking the original port and passing it in would
|
|
||||||
* mean that the port might used under the assumption that it was correct. By using -1 here,
|
|
||||||
* it forces the SSL implementation to treat it as invalid.
|
|
||||||
*/
|
|
||||||
host = authority;
|
|
||||||
port = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TlsNegotiator(sslContext, host, port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
static final class TlsNegotiator implements ProtocolNegotiator {
|
static final class TlsNegotiator implements ProtocolNegotiator {
|
||||||
private final SslContext sslContext;
|
private final SslContext sslContext;
|
||||||
private final String host;
|
|
||||||
private final int port;
|
|
||||||
|
|
||||||
TlsNegotiator(SslContext sslContext, String host, int port) {
|
TlsNegotiator(SslContext sslContext) {
|
||||||
this.sslContext = checkNotNull(sslContext, "sslContext");
|
this.sslContext = checkNotNull(sslContext, "sslContext");
|
||||||
this.host = checkNotNull(host, "host");
|
|
||||||
this.port = port;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
String getHost() {
|
HostPort parseAuthority(String authority) {
|
||||||
return host;
|
URI uri = GrpcUtil.authorityToUri(Preconditions.checkNotNull(authority, "authority"));
|
||||||
}
|
String host;
|
||||||
|
int port;
|
||||||
@VisibleForTesting
|
if (uri.getHost() != null) {
|
||||||
int getPort() {
|
host = uri.getHost();
|
||||||
return port;
|
port = uri.getPort();
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Implementation note: We pick -1 as the port here rather than deriving it from the
|
||||||
|
* original socket address. The SSL engine doens't use this port number when contacting the
|
||||||
|
* remote server, but rather it is used for other things like SSL Session caching. When an
|
||||||
|
* invalid authority is provided (like "bad_cert"), picking the original port and passing it
|
||||||
|
* in would mean that the port might used under the assumption that it was correct. By
|
||||||
|
* using -1 here, it forces the SSL implementation to treat it as invalid.
|
||||||
|
*/
|
||||||
|
host = authority;
|
||||||
|
port = -1;
|
||||||
|
}
|
||||||
|
return new HostPort(host, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Handler newHandler(GrpcHttp2ConnectionHandler handler) {
|
public Handler newHandler(GrpcHttp2ConnectionHandler handler) {
|
||||||
|
final HostPort hostPort = parseAuthority(handler.getAuthority());
|
||||||
|
|
||||||
ChannelHandler sslBootstrap = new ChannelHandlerAdapter() {
|
ChannelHandler sslBootstrap = new ChannelHandlerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
|
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
|
||||||
SSLEngine sslEngine = sslContext.newEngine(ctx.alloc(), host, port);
|
SSLEngine sslEngine = sslContext.newEngine(ctx.alloc(), hostPort.host, hostPort.port);
|
||||||
SSLParameters sslParams = sslEngine.getSSLParameters();
|
SSLParameters sslParams = sslEngine.getSSLParameters();
|
||||||
sslParams.setEndpointIdentificationAlgorithm("HTTPS");
|
sslParams.setEndpointIdentificationAlgorithm("HTTPS");
|
||||||
sslEngine.setSSLParameters(sslParams);
|
sslEngine.setSSLParameters(sslParams);
|
||||||
|
|
@ -320,6 +312,18 @@ public final class ProtocolNegotiators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A tuple of (host, port). */
|
||||||
|
@VisibleForTesting
|
||||||
|
static final class HostPort {
|
||||||
|
final String host;
|
||||||
|
final int port;
|
||||||
|
|
||||||
|
public HostPort(String host, int port) {
|
||||||
|
this.host = host;
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link ProtocolNegotiator} used for upgrading to HTTP/2 from HTTP/1.x.
|
* Returns a {@link ProtocolNegotiator} used for upgrading to HTTP/2 from HTTP/1.x.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -139,65 +139,57 @@ public class NettyChannelBuilderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createProtocolNegotiator_plaintext() {
|
public void createProtocolNegotiatorByType_plaintext() {
|
||||||
ProtocolNegotiator negotiator = NettyChannelBuilder.createProtocolNegotiator(
|
ProtocolNegotiator negotiator = NettyChannelBuilder.createProtocolNegotiatorByType(
|
||||||
"authority",
|
|
||||||
NegotiationType.PLAINTEXT,
|
NegotiationType.PLAINTEXT,
|
||||||
noSslContext,
|
noSslContext);
|
||||||
noProxy);
|
|
||||||
// just check that the classes are the same, and that negotiator is not null.
|
// just check that the classes are the same, and that negotiator is not null.
|
||||||
assertTrue(negotiator instanceof ProtocolNegotiators.PlaintextNegotiator);
|
assertTrue(negotiator instanceof ProtocolNegotiators.PlaintextNegotiator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createProtocolNegotiator_plaintextUpgrade() {
|
public void createProtocolNegotiatorByType_plaintextUpgrade() {
|
||||||
ProtocolNegotiator negotiator = NettyChannelBuilder.createProtocolNegotiator(
|
ProtocolNegotiator negotiator = NettyChannelBuilder.createProtocolNegotiatorByType(
|
||||||
"authority",
|
|
||||||
NegotiationType.PLAINTEXT_UPGRADE,
|
NegotiationType.PLAINTEXT_UPGRADE,
|
||||||
noSslContext,
|
noSslContext);
|
||||||
noProxy);
|
|
||||||
// just check that the classes are the same, and that negotiator is not null.
|
// just check that the classes are the same, and that negotiator is not null.
|
||||||
assertTrue(negotiator instanceof ProtocolNegotiators.PlaintextUpgradeNegotiator);
|
assertTrue(negotiator instanceof ProtocolNegotiators.PlaintextUpgradeNegotiator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createProtocolNegotiator_tlsWithNoContext() {
|
public void createProtocolNegotiatorByType_tlsWithNoContext() {
|
||||||
thrown.expect(NullPointerException.class);
|
thrown.expect(NullPointerException.class);
|
||||||
NettyChannelBuilder.createProtocolNegotiator(
|
NettyChannelBuilder.createProtocolNegotiatorByType(
|
||||||
"authority:1234",
|
|
||||||
NegotiationType.TLS,
|
NegotiationType.TLS,
|
||||||
noSslContext,
|
noSslContext);
|
||||||
noProxy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createProtocolNegotiator_tlsWithClientContext() throws SSLException {
|
public void createProtocolNegotiatorByType_tlsWithClientContext() throws SSLException {
|
||||||
ProtocolNegotiator negotiator = NettyChannelBuilder.createProtocolNegotiator(
|
ProtocolNegotiator negotiator = NettyChannelBuilder.createProtocolNegotiatorByType(
|
||||||
"authority:1234",
|
|
||||||
NegotiationType.TLS,
|
NegotiationType.TLS,
|
||||||
GrpcSslContexts.forClient().build(),
|
GrpcSslContexts.forClient().build());
|
||||||
noProxy);
|
|
||||||
|
|
||||||
assertTrue(negotiator instanceof ProtocolNegotiators.TlsNegotiator);
|
assertTrue(negotiator instanceof ProtocolNegotiators.TlsNegotiator);
|
||||||
ProtocolNegotiators.TlsNegotiator n = (TlsNegotiator) negotiator;
|
ProtocolNegotiators.TlsNegotiator n = (TlsNegotiator) negotiator;
|
||||||
|
ProtocolNegotiators.HostPort hostPort = n.parseAuthority("authority:1234");
|
||||||
|
|
||||||
assertEquals("authority", n.getHost());
|
assertEquals("authority", hostPort.host);
|
||||||
assertEquals(1234, n.getPort());
|
assertEquals(1234, hostPort.port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createProtocolNegotiator_tlsWithAuthorityFallback() throws SSLException {
|
public void createProtocolNegotiatorByType_tlsWithAuthorityFallback() throws SSLException {
|
||||||
ProtocolNegotiator negotiator = NettyChannelBuilder.createProtocolNegotiator(
|
ProtocolNegotiator negotiator = NettyChannelBuilder.createProtocolNegotiatorByType(
|
||||||
"bad_authority",
|
|
||||||
NegotiationType.TLS,
|
NegotiationType.TLS,
|
||||||
GrpcSslContexts.forClient().build(),
|
GrpcSslContexts.forClient().build());
|
||||||
noProxy);
|
|
||||||
|
|
||||||
assertTrue(negotiator instanceof ProtocolNegotiators.TlsNegotiator);
|
assertTrue(negotiator instanceof ProtocolNegotiators.TlsNegotiator);
|
||||||
ProtocolNegotiators.TlsNegotiator n = (TlsNegotiator) negotiator;
|
ProtocolNegotiators.TlsNegotiator n = (TlsNegotiator) negotiator;
|
||||||
|
ProtocolNegotiators.HostPort hostPort = n.parseAuthority("bad_authority");
|
||||||
|
|
||||||
assertEquals("bad_authority", n.getHost());
|
assertEquals("bad_authority", hostPort.host);
|
||||||
assertEquals(-1, n.getPort());
|
assertEquals(-1, hostPort.port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -722,7 +722,8 @@ public class NettyClientHandlerTest extends NettyHandlerTestBase<NettyClientHand
|
||||||
stopwatchSupplier,
|
stopwatchSupplier,
|
||||||
tooManyPingsRunnable,
|
tooManyPingsRunnable,
|
||||||
transportTracer,
|
transportTracer,
|
||||||
Attributes.EMPTY);
|
Attributes.EMPTY,
|
||||||
|
"someauthority");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,7 @@ public class NettyClientTransportTest {
|
||||||
.ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE)
|
.ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE)
|
||||||
.keyManager(clientCert, clientKey)
|
.keyManager(clientCert, clientKey)
|
||||||
.build();
|
.build();
|
||||||
ProtocolNegotiator negotiator = ProtocolNegotiators.tls(clientContext, authority);
|
ProtocolNegotiator negotiator = ProtocolNegotiators.tls(clientContext);
|
||||||
final NettyClientTransport transport = newTransport(negotiator);
|
final NettyClientTransport transport = newTransport(negotiator);
|
||||||
callMeMaybe(transport.start(clientTransportListener));
|
callMeMaybe(transport.start(clientTransportListener));
|
||||||
|
|
||||||
|
|
@ -573,7 +573,7 @@ public class NettyClientTransportTest {
|
||||||
File caCert = TestUtils.loadCert("ca.pem");
|
File caCert = TestUtils.loadCert("ca.pem");
|
||||||
SslContext clientContext = GrpcSslContexts.forClient().trustManager(caCert)
|
SslContext clientContext = GrpcSslContexts.forClient().trustManager(caCert)
|
||||||
.ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE).build();
|
.ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE).build();
|
||||||
return ProtocolNegotiators.tls(clientContext, authority);
|
return ProtocolNegotiators.tls(clientContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NettyClientTransport newTransport(ProtocolNegotiator negotiator) {
|
private NettyClientTransport newTransport(ProtocolNegotiator negotiator) {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
|
|
||||||
import io.grpc.internal.testing.TestUtils;
|
import io.grpc.internal.testing.TestUtils;
|
||||||
|
import io.grpc.netty.ProtocolNegotiators.HostPort;
|
||||||
import io.grpc.netty.ProtocolNegotiators.ServerTlsHandler;
|
import io.grpc.netty.ProtocolNegotiators.ServerTlsHandler;
|
||||||
import io.grpc.netty.ProtocolNegotiators.TlsNegotiator;
|
import io.grpc.netty.ProtocolNegotiators.TlsNegotiator;
|
||||||
import io.netty.bootstrap.Bootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
|
|
@ -253,36 +254,39 @@ public class ProtocolNegotiatorsTest {
|
||||||
public void tls_failsOnNullSslContext() {
|
public void tls_failsOnNullSslContext() {
|
||||||
thrown.expect(NullPointerException.class);
|
thrown.expect(NullPointerException.class);
|
||||||
|
|
||||||
Object unused = ProtocolNegotiators.tls(null, "authority");
|
Object unused = ProtocolNegotiators.tls(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void tls_hostAndPort() throws SSLException {
|
public void tls_hostAndPort() throws SSLException {
|
||||||
SslContext ctx = GrpcSslContexts.forClient().build();
|
SslContext ctx = GrpcSslContexts.forClient().build();
|
||||||
TlsNegotiator negotiator = (TlsNegotiator) ProtocolNegotiators.tls(ctx, "authority:1234");
|
TlsNegotiator negotiator = (TlsNegotiator) ProtocolNegotiators.tls(ctx);
|
||||||
|
HostPort hostPort = negotiator.parseAuthority("authority:1234");
|
||||||
|
|
||||||
assertEquals("authority", negotiator.getHost());
|
assertEquals("authority", hostPort.host);
|
||||||
assertEquals(1234, negotiator.getPort());
|
assertEquals(1234, hostPort.port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void tls_host() throws SSLException {
|
public void tls_host() throws SSLException {
|
||||||
SslContext ctx = GrpcSslContexts.forClient().build();
|
SslContext ctx = GrpcSslContexts.forClient().build();
|
||||||
TlsNegotiator negotiator = (TlsNegotiator) ProtocolNegotiators.tls(ctx, "[::1]");
|
TlsNegotiator negotiator = (TlsNegotiator) ProtocolNegotiators.tls(ctx);
|
||||||
|
HostPort hostPort = negotiator.parseAuthority("[::1]");
|
||||||
|
|
||||||
assertEquals("[::1]", negotiator.getHost());
|
assertEquals("[::1]", hostPort.host);
|
||||||
assertEquals(-1, negotiator.getPort());
|
assertEquals(-1, hostPort.port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void tls_invalidHost() throws SSLException {
|
public void tls_invalidHost() throws SSLException {
|
||||||
SslContext ctx = GrpcSslContexts.forClient().build();
|
SslContext ctx = GrpcSslContexts.forClient().build();
|
||||||
TlsNegotiator negotiator = (TlsNegotiator) ProtocolNegotiators.tls(ctx, "bad_host:1234");
|
TlsNegotiator negotiator = (TlsNegotiator) ProtocolNegotiators.tls(ctx);
|
||||||
|
HostPort hostPort = negotiator.parseAuthority("bad_host:1234");
|
||||||
|
|
||||||
// Even though it looks like a port, we treat it as part of the authority, since the host is
|
// Even though it looks like a port, we treat it as part of the authority, since the host is
|
||||||
// invalid.
|
// invalid.
|
||||||
assertEquals("bad_host:1234", negotiator.getHost());
|
assertEquals("bad_host:1234", hostPort.host);
|
||||||
assertEquals(-1, negotiator.getPort());
|
assertEquals(-1, hostPort.port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue