mirror of https://github.com/grpc/grpc-java.git
core,okhttp,netty,alts,testing: Plumb proxy resolved addr to transports (#4137)
ProxyDetector is now responsible for resolving the proxy's `InetSocketAddress`, and `ProxyParameters` asserts that the address is resolved. The results are plumbed through using a `PairSocketAddress`, which is a special `SocketAddress`. If a proxy should be used but the proxy can not be resolved, we the `DnsNameResolver` will re-attempt the resolution later. Remove the unit test testing for unresolved proxy addresses, since it's no longer applicable.
This commit is contained in:
parent
2fc2270011
commit
402c1740fa
|
|
@ -396,7 +396,6 @@ public abstract class AbstractManagedChannelImplBuilder
|
||||||
SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR),
|
SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR),
|
||||||
GrpcUtil.STOPWATCH_SUPPLIER,
|
GrpcUtil.STOPWATCH_SUPPLIER,
|
||||||
getEffectiveInterceptors(),
|
getEffectiveInterceptors(),
|
||||||
GrpcUtil.getProxyDetector(),
|
|
||||||
CallTracer.getDefaultFactory());
|
CallTracer.getDefaultFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import io.grpc.EquivalentAddressGroup;
|
||||||
import io.grpc.NameResolver;
|
import io.grpc.NameResolver;
|
||||||
import io.grpc.Status;
|
import io.grpc.Status;
|
||||||
import io.grpc.internal.SharedResourceHolder.Resource;
|
import io.grpc.internal.SharedResourceHolder.Resource;
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
|
|
@ -71,13 +72,15 @@ final class DnsNameResolver extends NameResolver {
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static boolean enableJndi = Boolean.parseBoolean(JNDI_PROPERTY);
|
static boolean enableJndi = Boolean.parseBoolean(JNDI_PROPERTY);
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
final ProxyDetector proxyDetector;
|
||||||
|
|
||||||
private DelegateResolver delegateResolver = pickDelegateResolver();
|
private DelegateResolver delegateResolver = pickDelegateResolver();
|
||||||
|
|
||||||
private final String authority;
|
private final String authority;
|
||||||
private final String host;
|
private final String host;
|
||||||
private final int port;
|
private final int port;
|
||||||
private final Resource<ExecutorService> executorResource;
|
private final Resource<ExecutorService> executorResource;
|
||||||
private final ProxyDetector proxyDetector;
|
|
||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
private boolean shutdown;
|
private boolean shutdown;
|
||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
|
|
@ -145,9 +148,23 @@ final class DnsNameResolver extends NameResolver {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
InetSocketAddress destination = InetSocketAddress.createUnresolved(host, port);
|
InetSocketAddress destination = InetSocketAddress.createUnresolved(host, port);
|
||||||
ProxyParameters proxy = proxyDetector.proxyFor(destination);
|
ProxyParameters proxy;
|
||||||
|
try {
|
||||||
|
proxy = proxyDetector.proxyFor(destination);
|
||||||
|
} catch (IOException e) {
|
||||||
|
savedListener.onError(
|
||||||
|
Status.UNAVAILABLE.withDescription("Unable to resolve host " + host).withCause(e));
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (proxy != null) {
|
if (proxy != null) {
|
||||||
EquivalentAddressGroup server = new EquivalentAddressGroup(destination);
|
EquivalentAddressGroup server =
|
||||||
|
new EquivalentAddressGroup(
|
||||||
|
new PairSocketAddress(
|
||||||
|
destination,
|
||||||
|
Attributes
|
||||||
|
.newBuilder()
|
||||||
|
.set(ProxyDetector.PROXY_PARAMS_KEY, proxy)
|
||||||
|
.build()));
|
||||||
savedListener.onAddresses(Collections.singletonList(server), Attributes.EMPTY);
|
savedListener.onAddresses(Collections.singletonList(server), Attributes.EMPTY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ public final class DnsNameResolverProvider extends NameResolverProvider {
|
||||||
name,
|
name,
|
||||||
params,
|
params,
|
||||||
GrpcUtil.SHARED_CHANNEL_EXECUTOR,
|
GrpcUtil.SHARED_CHANNEL_EXECUTOR,
|
||||||
GrpcUtil.getProxyDetector());
|
GrpcUtil.getDefaultProxyDetector());
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ public final class GrpcUtil {
|
||||||
/**
|
/**
|
||||||
* Returns a proxy detector appropriate for the current environment.
|
* Returns a proxy detector appropriate for the current environment.
|
||||||
*/
|
*/
|
||||||
public static ProxyDetector getProxyDetector() {
|
public static ProxyDetector getDefaultProxyDetector() {
|
||||||
if (IS_RESTRICTED_APPENGINE) {
|
if (IS_RESTRICTED_APPENGINE) {
|
||||||
return NOOP_PROXY_DETECTOR;
|
return NOOP_PROXY_DETECTOR;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -150,8 +150,6 @@ final class InternalSubchannel implements Instrumented<ChannelStats> {
|
||||||
@GuardedBy("lock")
|
@GuardedBy("lock")
|
||||||
private ConnectivityStateInfo state = ConnectivityStateInfo.forNonError(IDLE);
|
private ConnectivityStateInfo state = ConnectivityStateInfo.forNonError(IDLE);
|
||||||
|
|
||||||
private final ProxyDetector proxyDetector;
|
|
||||||
|
|
||||||
@GuardedBy("lock")
|
@GuardedBy("lock")
|
||||||
private Status shutdownReason;
|
private Status shutdownReason;
|
||||||
|
|
||||||
|
|
@ -159,7 +157,7 @@ final class InternalSubchannel implements Instrumented<ChannelStats> {
|
||||||
BackoffPolicy.Provider backoffPolicyProvider,
|
BackoffPolicy.Provider backoffPolicyProvider,
|
||||||
ClientTransportFactory transportFactory, ScheduledExecutorService scheduledExecutor,
|
ClientTransportFactory transportFactory, ScheduledExecutorService scheduledExecutor,
|
||||||
Supplier<Stopwatch> stopwatchSupplier, ChannelExecutor channelExecutor, Callback callback,
|
Supplier<Stopwatch> stopwatchSupplier, ChannelExecutor channelExecutor, Callback callback,
|
||||||
ProxyDetector proxyDetector, Channelz channelz, CallTracer callsTracer) {
|
Channelz channelz, CallTracer callsTracer) {
|
||||||
this.addressGroup = Preconditions.checkNotNull(addressGroup, "addressGroup");
|
this.addressGroup = Preconditions.checkNotNull(addressGroup, "addressGroup");
|
||||||
this.authority = authority;
|
this.authority = authority;
|
||||||
this.userAgent = userAgent;
|
this.userAgent = userAgent;
|
||||||
|
|
@ -169,7 +167,6 @@ final class InternalSubchannel implements Instrumented<ChannelStats> {
|
||||||
this.connectingTimer = stopwatchSupplier.get();
|
this.connectingTimer = stopwatchSupplier.get();
|
||||||
this.channelExecutor = channelExecutor;
|
this.channelExecutor = channelExecutor;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.proxyDetector = proxyDetector;
|
|
||||||
this.channelz = channelz;
|
this.channelz = channelz;
|
||||||
this.callsTracer = callsTracer;
|
this.callsTracer = callsTracer;
|
||||||
}
|
}
|
||||||
|
|
@ -211,9 +208,14 @@ final class InternalSubchannel implements Instrumented<ChannelStats> {
|
||||||
connectingTimer.reset().start();
|
connectingTimer.reset().start();
|
||||||
}
|
}
|
||||||
List<SocketAddress> addrs = addressGroup.getAddresses();
|
List<SocketAddress> addrs = addressGroup.getAddresses();
|
||||||
final SocketAddress address = addrs.get(addressIndex);
|
SocketAddress address = addrs.get(addressIndex);
|
||||||
|
|
||||||
|
ProxyParameters proxy = null;
|
||||||
|
if (address instanceof PairSocketAddress) {
|
||||||
|
proxy = ((PairSocketAddress) address).getAttributes().get(ProxyDetector.PROXY_PARAMS_KEY);
|
||||||
|
address = ((PairSocketAddress) address).getAddress();
|
||||||
|
}
|
||||||
|
|
||||||
ProxyParameters proxy = proxyDetector.proxyFor(address);
|
|
||||||
ConnectionClientTransport transport =
|
ConnectionClientTransport transport =
|
||||||
new CallTracingTransport(
|
new CallTracingTransport(
|
||||||
transportFactory.newClientTransport(address, authority, userAgent, proxy),
|
transportFactory.newClientTransport(address, authority, userAgent, proxy),
|
||||||
|
|
|
||||||
|
|
@ -151,8 +151,6 @@ final class ManagedChannelImpl extends ManagedChannel implements Instrumented<Ch
|
||||||
// Only null after channel is terminated. Must be assigned from the channelExecutor.
|
// Only null after channel is terminated. Must be assigned from the channelExecutor.
|
||||||
private NameResolver nameResolver;
|
private NameResolver nameResolver;
|
||||||
|
|
||||||
private final ProxyDetector proxyDetector;
|
|
||||||
|
|
||||||
// Must be accessed from the channelExecutor.
|
// Must be accessed from the channelExecutor.
|
||||||
private boolean nameResolverStarted;
|
private boolean nameResolverStarted;
|
||||||
|
|
||||||
|
|
@ -548,7 +546,6 @@ final class ManagedChannelImpl extends ManagedChannel implements Instrumented<Ch
|
||||||
ObjectPool<? extends Executor> oobExecutorPool,
|
ObjectPool<? extends Executor> oobExecutorPool,
|
||||||
Supplier<Stopwatch> stopwatchSupplier,
|
Supplier<Stopwatch> stopwatchSupplier,
|
||||||
List<ClientInterceptor> interceptors,
|
List<ClientInterceptor> interceptors,
|
||||||
ProxyDetector proxyDetector,
|
|
||||||
CallTracer.Factory callTracerFactory) {
|
CallTracer.Factory callTracerFactory) {
|
||||||
this.target = checkNotNull(builder.target, "target");
|
this.target = checkNotNull(builder.target, "target");
|
||||||
this.nameResolverFactory = builder.getNameResolverFactory();
|
this.nameResolverFactory = builder.getNameResolverFactory();
|
||||||
|
|
@ -583,7 +580,6 @@ final class ManagedChannelImpl extends ManagedChannel implements Instrumented<Ch
|
||||||
this.decompressorRegistry = checkNotNull(builder.decompressorRegistry, "decompressorRegistry");
|
this.decompressorRegistry = checkNotNull(builder.decompressorRegistry, "decompressorRegistry");
|
||||||
this.compressorRegistry = checkNotNull(builder.compressorRegistry, "compressorRegistry");
|
this.compressorRegistry = checkNotNull(builder.compressorRegistry, "compressorRegistry");
|
||||||
this.userAgent = builder.userAgent;
|
this.userAgent = builder.userAgent;
|
||||||
this.proxyDetector = proxyDetector;
|
|
||||||
|
|
||||||
this.maxRetryAttempts = builder.maxRetryAttempts;
|
this.maxRetryAttempts = builder.maxRetryAttempts;
|
||||||
this.maxHedgedAttempts = builder.maxHedgedAttempts;
|
this.maxHedgedAttempts = builder.maxHedgedAttempts;
|
||||||
|
|
@ -1015,7 +1011,6 @@ final class ManagedChannelImpl extends ManagedChannel implements Instrumented<Ch
|
||||||
inUseStateAggregator.updateObjectInUse(is, false);
|
inUseStateAggregator.updateObjectInUse(is, false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
proxyDetector,
|
|
||||||
channelz,
|
channelz,
|
||||||
callTracerFactory.create());
|
callTracerFactory.create());
|
||||||
channelz.addSubchannel(internalSubchannel);
|
channelz.addSubchannel(internalSubchannel);
|
||||||
|
|
@ -1100,7 +1095,6 @@ final class ManagedChannelImpl extends ManagedChannel implements Instrumented<Ch
|
||||||
oobChannel.handleSubchannelStateChange(newState);
|
oobChannel.handleSubchannelStateChange(newState);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
proxyDetector,
|
|
||||||
channelz,
|
channelz,
|
||||||
callTracerFactory.create());
|
callTracerFactory.create());
|
||||||
channelz.addSubchannel(oobChannel);
|
channelz.addSubchannel(oobChannel);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018, gRPC Authors All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.grpc.internal;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import io.grpc.Attributes;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data structure to associate a {@link SocketAddress} with {@link Attributes}.
|
||||||
|
*/
|
||||||
|
final class PairSocketAddress extends SocketAddress {
|
||||||
|
private static final long serialVersionUID = -6854992294603212793L;
|
||||||
|
|
||||||
|
private final SocketAddress address;
|
||||||
|
private final Attributes attributes;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
PairSocketAddress(SocketAddress address, Attributes attributes) {
|
||||||
|
this.address = Preconditions.checkNotNull(address);
|
||||||
|
this.attributes = Preconditions.checkNotNull(attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Attributes getAttributes() {
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SocketAddress getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,18 +16,24 @@
|
||||||
|
|
||||||
package io.grpc.internal;
|
package io.grpc.internal;
|
||||||
|
|
||||||
|
import io.grpc.Attributes;
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility class to detect which proxy, if any, should be used for a given
|
* A utility class to detect which proxy, if any, should be used for a given
|
||||||
* {@link java.net.SocketAddress}.
|
* {@link java.net.SocketAddress}. This class performs network requests to resolve address names,
|
||||||
|
* and should only be used in places that are expected to do IO such as the
|
||||||
|
* {@link io.grpc.NameResolver}.
|
||||||
*/
|
*/
|
||||||
public interface ProxyDetector {
|
public interface ProxyDetector {
|
||||||
|
Attributes.Key<ProxyParameters> PROXY_PARAMS_KEY = Attributes.Key.of("proxy-params-key");
|
||||||
/**
|
/**
|
||||||
* Given a target address, returns which proxy address should be used. If no proxy should be
|
* Given a target address, returns which proxy address should be used. If no proxy should be
|
||||||
* used, then return value will be null.
|
* used, then return value will be null. The address of the {@link ProxyParameters} is always
|
||||||
|
* resolved. This throws if the proxy address cannot be resolved.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
ProxyParameters proxyFor(SocketAddress targetServerAddress);
|
ProxyParameters proxyFor(SocketAddress targetServerAddress) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.Authenticator;
|
import java.net.Authenticator;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
|
@ -108,7 +109,7 @@ class ProxyDetectorImpl implements ProxyDetector {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public ProxyParameters proxyFor(SocketAddress targetServerAddress) {
|
public ProxyParameters proxyFor(SocketAddress targetServerAddress) throws IOException {
|
||||||
if (override != null) {
|
if (override != null) {
|
||||||
return override;
|
return override;
|
||||||
}
|
}
|
||||||
|
|
@ -118,7 +119,7 @@ class ProxyDetectorImpl implements ProxyDetector {
|
||||||
return detectProxy((InetSocketAddress) targetServerAddress);
|
return detectProxy((InetSocketAddress) targetServerAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProxyParameters detectProxy(InetSocketAddress targetAddr) {
|
private ProxyParameters detectProxy(InetSocketAddress targetAddr) throws IOException {
|
||||||
URI uri;
|
URI uri;
|
||||||
String host;
|
String host;
|
||||||
try {
|
try {
|
||||||
|
|
@ -167,12 +168,21 @@ class ProxyDetectorImpl implements ProxyDetector {
|
||||||
promptString,
|
promptString,
|
||||||
null);
|
null);
|
||||||
|
|
||||||
|
final InetSocketAddress resolvedProxyAddr;
|
||||||
|
if (proxyAddr.isUnresolved()) {
|
||||||
|
InetAddress resolvedAddress = InetAddress.getByName(proxyAddr.getHostName());
|
||||||
|
resolvedProxyAddr = new InetSocketAddress(resolvedAddress, proxyAddr.getPort());
|
||||||
|
} else {
|
||||||
|
resolvedProxyAddr = proxyAddr;
|
||||||
|
}
|
||||||
|
|
||||||
if (auth == null) {
|
if (auth == null) {
|
||||||
return new ProxyParameters(proxyAddr, null, null);
|
return new ProxyParameters(resolvedProxyAddr, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(spencerfang): users of ProxyParameters should clear the password when done
|
// TODO(spencerfang): users of ProxyParameters should clear the password when done
|
||||||
return new ProxyParameters(proxyAddr, auth.getUserName(), new String(auth.getPassword()));
|
return new ProxyParameters(
|
||||||
|
resolvedProxyAddr, auth.getUserName(), new String(auth.getPassword()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,16 @@ public final class ProxyParameters {
|
||||||
@Nullable public final String username;
|
@Nullable public final String username;
|
||||||
@Nullable public final String password;
|
@Nullable public final String password;
|
||||||
|
|
||||||
ProxyParameters(
|
/** Creates an instance. */
|
||||||
|
public ProxyParameters(
|
||||||
InetSocketAddress proxyAddress,
|
InetSocketAddress proxyAddress,
|
||||||
@Nullable String username,
|
@Nullable String username,
|
||||||
@Nullable String password) {
|
@Nullable String password) {
|
||||||
this.proxyAddress = Preconditions.checkNotNull(proxyAddress);
|
Preconditions.checkNotNull(proxyAddress);
|
||||||
|
// The resolution must be done by the ProxyParameters producer, because consumers
|
||||||
|
// may not be allowed to do IO.
|
||||||
|
Preconditions.checkState(!proxyAddress.isUnresolved());
|
||||||
|
this.proxyAddress = proxyAddress;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package io.grpc.internal;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
|
|
@ -247,7 +248,7 @@ public class DnsNameResolverTest {
|
||||||
final int port = 81;
|
final int port = 81;
|
||||||
ProxyDetector alwaysDetectProxy = mock(ProxyDetector.class);
|
ProxyDetector alwaysDetectProxy = mock(ProxyDetector.class);
|
||||||
ProxyParameters proxyParameters = new ProxyParameters(
|
ProxyParameters proxyParameters = new ProxyParameters(
|
||||||
InetSocketAddress.createUnresolved("proxy.example.com", 1000),
|
new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 1000),
|
||||||
"username",
|
"username",
|
||||||
"password");
|
"password");
|
||||||
when(alwaysDetectProxy.proxyFor(any(SocketAddress.class)))
|
when(alwaysDetectProxy.proxyFor(any(SocketAddress.class)))
|
||||||
|
|
@ -263,8 +264,10 @@ public class DnsNameResolverTest {
|
||||||
assertThat(result).hasSize(1);
|
assertThat(result).hasSize(1);
|
||||||
EquivalentAddressGroup eag = result.get(0);
|
EquivalentAddressGroup eag = result.get(0);
|
||||||
assertThat(eag.getAddresses()).hasSize(1);
|
assertThat(eag.getAddresses()).hasSize(1);
|
||||||
SocketAddress socketAddress = eag.getAddresses().get(0);
|
|
||||||
assertTrue(((InetSocketAddress) socketAddress).isUnresolved());
|
PairSocketAddress socketAddress = (PairSocketAddress) eag.getAddresses().get(0);
|
||||||
|
assertSame(proxyParameters, socketAddress.getAttributes().get(ProxyDetector.PROXY_PARAMS_KEY));
|
||||||
|
assertTrue(((InetSocketAddress) socketAddress.getAddress()).isUnresolved());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testInvalidUri(URI uri) {
|
private void testInvalidUri(URI uri) {
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertSame;
|
import static org.junit.Assert.assertSame;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Matchers.eq;
|
|
||||||
import static org.mockito.Matchers.same;
|
import static org.mockito.Matchers.same;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
|
|
@ -37,19 +36,16 @@ import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import io.grpc.ConnectivityState;
|
|
||||||
import io.grpc.ConnectivityStateInfo;
|
import io.grpc.ConnectivityStateInfo;
|
||||||
import io.grpc.EquivalentAddressGroup;
|
import io.grpc.EquivalentAddressGroup;
|
||||||
import io.grpc.Status;
|
import io.grpc.Status;
|
||||||
import io.grpc.internal.InternalSubchannel.CallTracingTransport;
|
import io.grpc.internal.InternalSubchannel.CallTracingTransport;
|
||||||
import io.grpc.internal.TestUtils.MockClientTransportInfo;
|
import io.grpc.internal.TestUtils.MockClientTransportInfo;
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -865,32 +861,6 @@ public class InternalSubchannelTest {
|
||||||
assertEquals(3, runnableInvokes.get());
|
assertEquals(3, runnableInvokes.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void proxyTest() {
|
|
||||||
final SocketAddress addr1 = mock(SocketAddress.class);
|
|
||||||
final ProxyParameters proxy = new ProxyParameters(
|
|
||||||
InetSocketAddress.createUnresolved("proxy.example.com", 1000), "username", "password");
|
|
||||||
ProxyDetector proxyDetector = new ProxyDetector() {
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public ProxyParameters proxyFor(SocketAddress targetServerAddress) {
|
|
||||||
if (targetServerAddress == addr1) {
|
|
||||||
return proxy;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
createInternalSubChannelWithProxy(proxyDetector, addr1);
|
|
||||||
assertEquals(ConnectivityState.IDLE, internalSubchannel.getState());
|
|
||||||
assertNoCallbackInvoke();
|
|
||||||
assertNull(internalSubchannel.obtainActiveTransport());
|
|
||||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
|
||||||
assertEquals(ConnectivityState.CONNECTING, internalSubchannel.getState());
|
|
||||||
verify(mockTransportFactory).newClientTransport(
|
|
||||||
eq(addr1), eq(AUTHORITY), eq(USER_AGENT), eq(proxy));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resetConnectBackoff() throws Exception {
|
public void resetConnectBackoff() throws Exception {
|
||||||
SocketAddress addr = mock(SocketAddress.class);
|
SocketAddress addr = mock(SocketAddress.class);
|
||||||
|
|
@ -962,16 +932,11 @@ public class InternalSubchannelTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createInternalSubchannel(SocketAddress ... addrs) {
|
private void createInternalSubchannel(SocketAddress ... addrs) {
|
||||||
createInternalSubChannelWithProxy(GrpcUtil.NOOP_PROXY_DETECTOR, addrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createInternalSubChannelWithProxy(
|
|
||||||
ProxyDetector proxyDetector, SocketAddress ... addrs) {
|
|
||||||
addressGroup = new EquivalentAddressGroup(Arrays.asList(addrs));
|
addressGroup = new EquivalentAddressGroup(Arrays.asList(addrs));
|
||||||
internalSubchannel = new InternalSubchannel(addressGroup, AUTHORITY, USER_AGENT,
|
internalSubchannel = new InternalSubchannel(addressGroup, AUTHORITY, USER_AGENT,
|
||||||
mockBackoffPolicyProvider, mockTransportFactory, fakeClock.getScheduledExecutorService(),
|
mockBackoffPolicyProvider, mockTransportFactory, fakeClock.getScheduledExecutorService(),
|
||||||
fakeClock.getStopwatchSupplier(), channelExecutor, mockInternalSubchannelCallback,
|
fakeClock.getStopwatchSupplier(), channelExecutor, mockInternalSubchannelCallback,
|
||||||
proxyDetector, channelz, CallTracer.getDefaultFactory().create());
|
channelz, CallTracer.getDefaultFactory().create());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertNoCallbackInvoke() {
|
private void assertNoCallbackInvoke() {
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ public class ManagedChannelImplIdlenessTest {
|
||||||
builder, mockTransportFactory, new FakeBackoffPolicyProvider(),
|
builder, mockTransportFactory, new FakeBackoffPolicyProvider(),
|
||||||
oobExecutorPool, timer.getStopwatchSupplier(),
|
oobExecutorPool, timer.getStopwatchSupplier(),
|
||||||
Collections.<ClientInterceptor>emptyList(),
|
Collections.<ClientInterceptor>emptyList(),
|
||||||
GrpcUtil.NOOP_PROXY_DETECTOR, CallTracer.getDefaultFactory());
|
CallTracer.getDefaultFactory());
|
||||||
newTransports = TestUtils.captureTransports(mockTransportFactory);
|
newTransports = TestUtils.captureTransports(mockTransportFactory);
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,7 @@ public class ManagedChannelImplTest {
|
||||||
checkState(channel == null);
|
checkState(channel == null);
|
||||||
channel = new ManagedChannelImpl(
|
channel = new ManagedChannelImpl(
|
||||||
builder, mockTransportFactory, new FakeBackoffPolicyProvider(),
|
builder, mockTransportFactory, new FakeBackoffPolicyProvider(),
|
||||||
oobExecutorPool, timer.getStopwatchSupplier(), interceptors, GrpcUtil.NOOP_PROXY_DETECTOR,
|
oobExecutorPool, timer.getStopwatchSupplier(), interceptors,
|
||||||
channelStatsFactory);
|
channelStatsFactory);
|
||||||
|
|
||||||
if (requestConnection) {
|
if (requestConnection) {
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,10 @@ package io.grpc.internal;
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertFalse;
|
import static junit.framework.TestCase.assertFalse;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
@ -42,18 +44,18 @@ import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
@RunWith(JUnit4.class)
|
@RunWith(JUnit4.class)
|
||||||
public class ProxyDetectorImplTest {
|
public class ProxyDetectorImplTest {
|
||||||
private InetSocketAddress destination = InetSocketAddress.createUnresolved(
|
private static final String NO_USER = null;
|
||||||
"destination",
|
private static final String NO_PW = null;
|
||||||
5678
|
|
||||||
);
|
|
||||||
|
|
||||||
@Mock private ProxySelector proxySelector;
|
@Mock private ProxySelector proxySelector;
|
||||||
@Mock private ProxyDetectorImpl.AuthenticationProvider authenticator;
|
@Mock private ProxyDetectorImpl.AuthenticationProvider authenticator;
|
||||||
|
private InetSocketAddress destination = InetSocketAddress.createUnresolved("10.10.10.10", 5678);
|
||||||
private Supplier<ProxySelector> proxySelectorSupplier;
|
private Supplier<ProxySelector> proxySelectorSupplier;
|
||||||
private ProxyDetector proxyDetector;
|
private ProxyDetector proxyDetector;
|
||||||
|
private InetSocketAddress unresolvedProxy;
|
||||||
|
private ProxyParameters proxyParmeters;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() throws Exception {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
proxySelectorSupplier = new Supplier<ProxySelector>() {
|
proxySelectorSupplier = new Supplier<ProxySelector>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -62,11 +64,17 @@ public class ProxyDetectorImplTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
proxyDetector = new ProxyDetectorImpl(proxySelectorSupplier, authenticator, null);
|
proxyDetector = new ProxyDetectorImpl(proxySelectorSupplier, authenticator, null);
|
||||||
|
int proxyPort = 1234;
|
||||||
|
unresolvedProxy = InetSocketAddress.createUnresolved("10.0.0.1", proxyPort);
|
||||||
|
proxyParmeters = new ProxyParameters(
|
||||||
|
new InetSocketAddress(InetAddress.getByName(unresolvedProxy.getHostName()), proxyPort),
|
||||||
|
NO_USER,
|
||||||
|
NO_PW);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void override_hostPort() throws Exception {
|
public void override_hostPort() throws Exception {
|
||||||
final String overrideHost = "override";
|
final String overrideHost = "10.99.99.99";
|
||||||
final int overridePort = 1234;
|
final int overridePort = 1234;
|
||||||
final String overrideHostWithPort = overrideHost + ":" + overridePort;
|
final String overrideHostWithPort = overrideHost + ":" + overridePort;
|
||||||
ProxyDetectorImpl proxyDetector = new ProxyDetectorImpl(
|
ProxyDetectorImpl proxyDetector = new ProxyDetectorImpl(
|
||||||
|
|
@ -77,13 +85,15 @@ public class ProxyDetectorImplTest {
|
||||||
assertNotNull(detected);
|
assertNotNull(detected);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
new ProxyParameters(
|
new ProxyParameters(
|
||||||
InetSocketAddress.createUnresolved(overrideHost, overridePort), null, null),
|
new InetSocketAddress(InetAddress.getByName(overrideHost), overridePort),
|
||||||
|
NO_USER,
|
||||||
|
NO_PW),
|
||||||
detected);
|
detected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void override_hostOnly() throws Exception {
|
public void override_hostOnly() throws Exception {
|
||||||
final String overrideHostWithoutPort = "override";
|
final String overrideHostWithoutPort = "10.99.99.99";
|
||||||
final int defaultPort = 80;
|
final int defaultPort = 80;
|
||||||
ProxyDetectorImpl proxyDetector = new ProxyDetectorImpl(
|
ProxyDetectorImpl proxyDetector = new ProxyDetectorImpl(
|
||||||
proxySelectorSupplier,
|
proxySelectorSupplier,
|
||||||
|
|
@ -93,7 +103,10 @@ public class ProxyDetectorImplTest {
|
||||||
assertNotNull(detected);
|
assertNotNull(detected);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
new ProxyParameters(
|
new ProxyParameters(
|
||||||
InetSocketAddress.createUnresolved(overrideHostWithoutPort, defaultPort), null, null),
|
new InetSocketAddress(
|
||||||
|
InetAddress.getByName(overrideHostWithoutPort), defaultPort),
|
||||||
|
NO_USER,
|
||||||
|
NO_PW),
|
||||||
detected);
|
detected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,43 +118,50 @@ public class ProxyDetectorImplTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void detectProxyForUnresolved() throws Exception {
|
public void detectProxyForUnresolvedDestination() throws Exception {
|
||||||
final InetSocketAddress proxyAddress = InetSocketAddress.createUnresolved("proxy", 1234);
|
Proxy proxy = new Proxy(Proxy.Type.HTTP, unresolvedProxy);
|
||||||
Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyAddress);
|
|
||||||
when(proxySelector.select(any(URI.class))).thenReturn(ImmutableList.of(proxy));
|
when(proxySelector.select(any(URI.class))).thenReturn(ImmutableList.of(proxy));
|
||||||
|
|
||||||
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
||||||
assertNotNull(detected);
|
assertNotNull(detected);
|
||||||
assertEquals(new ProxyParameters(proxyAddress, null, null), detected);
|
assertEquals(proxyParmeters, detected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void detectProxyForResolved() throws Exception {
|
public void detectProxyForResolvedDestination() throws Exception {
|
||||||
InetSocketAddress resolved =
|
InetSocketAddress resolved = new InetSocketAddress(InetAddress.getByName("10.1.2.3"), 10);
|
||||||
new InetSocketAddress(InetAddress.getByAddress(new byte[]{10, 0, 0, 1}), 10);
|
|
||||||
assertFalse(resolved.isUnresolved());
|
assertFalse(resolved.isUnresolved());
|
||||||
destination = resolved;
|
destination = resolved;
|
||||||
|
|
||||||
final InetSocketAddress proxyAddress = InetSocketAddress.createUnresolved("proxy", 1234);
|
Proxy proxy = new Proxy(Proxy.Type.HTTP, unresolvedProxy);
|
||||||
Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyAddress);
|
|
||||||
when(proxySelector.select(any(URI.class))).thenReturn(ImmutableList.of(proxy));
|
when(proxySelector.select(any(URI.class))).thenReturn(ImmutableList.of(proxy));
|
||||||
|
|
||||||
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
||||||
assertNotNull(detected);
|
assertNotNull(detected);
|
||||||
assertEquals(new ProxyParameters(proxyAddress, null, null), detected);
|
assertEquals(proxyParmeters, detected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unresolvedProxyAddressBecomesResolved() throws Exception {
|
||||||
|
InetSocketAddress unresolvedProxy = InetSocketAddress.createUnresolved("10.0.0.100", 1234);
|
||||||
|
assertTrue(unresolvedProxy.isUnresolved());
|
||||||
|
Proxy proxy1 = new java.net.Proxy(java.net.Proxy.Type.HTTP, unresolvedProxy);
|
||||||
|
when(proxySelector.select(any(URI.class))).thenReturn(ImmutableList.of(proxy1));
|
||||||
|
ProxyParameters proxy = proxyDetector.proxyFor(destination);
|
||||||
|
assertFalse(proxy.proxyAddress.isUnresolved());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void pickFirstHttpProxy() throws Exception {
|
public void pickFirstHttpProxy() throws Exception {
|
||||||
final InetSocketAddress proxyAddress = InetSocketAddress.createUnresolved("proxy1", 1111);
|
InetSocketAddress otherProxy = InetSocketAddress.createUnresolved("10.0.0.2", 11111);
|
||||||
InetSocketAddress otherProxy = InetSocketAddress.createUnresolved("proxy2", 2222);
|
assertNotEquals(unresolvedProxy, otherProxy);
|
||||||
Proxy proxy1 = new java.net.Proxy(java.net.Proxy.Type.HTTP, proxyAddress);
|
Proxy proxy1 = new java.net.Proxy(java.net.Proxy.Type.HTTP, unresolvedProxy);
|
||||||
Proxy proxy2 = new java.net.Proxy(java.net.Proxy.Type.HTTP, otherProxy);
|
Proxy proxy2 = new java.net.Proxy(java.net.Proxy.Type.HTTP, otherProxy);
|
||||||
when(proxySelector.select(any(URI.class))).thenReturn(ImmutableList.of(proxy1, proxy2));
|
when(proxySelector.select(any(URI.class))).thenReturn(ImmutableList.of(proxy1, proxy2));
|
||||||
|
|
||||||
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
||||||
assertNotNull(detected);
|
assertNotNull(detected);
|
||||||
assertEquals(new ProxyParameters(proxyAddress, null, null), detected);
|
assertEquals(proxyParmeters, detected);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mainly for InProcessSocketAddress
|
// Mainly for InProcessSocketAddress
|
||||||
|
|
@ -152,10 +172,7 @@ public class ProxyDetectorImplTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void authRequired() throws Exception {
|
public void authRequired() throws Exception {
|
||||||
final String proxyHost = "proxyhost";
|
Proxy proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, unresolvedProxy);
|
||||||
final int proxyPort = 1234;
|
|
||||||
final InetSocketAddress proxyAddress = InetSocketAddress.createUnresolved(proxyHost, proxyPort);
|
|
||||||
Proxy proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, proxyAddress);
|
|
||||||
final String proxyUser = "testuser";
|
final String proxyUser = "testuser";
|
||||||
final String proxyPassword = "testpassword";
|
final String proxyPassword = "testpassword";
|
||||||
PasswordAuthentication auth = new PasswordAuthentication(
|
PasswordAuthentication auth = new PasswordAuthentication(
|
||||||
|
|
@ -171,7 +188,13 @@ public class ProxyDetectorImplTest {
|
||||||
when(proxySelector.select(any(URI.class))).thenReturn(ImmutableList.of(proxy));
|
when(proxySelector.select(any(URI.class))).thenReturn(ImmutableList.of(proxy));
|
||||||
|
|
||||||
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
||||||
assertNotNull(detected);
|
assertEquals(
|
||||||
assertEquals(new ProxyParameters(proxyAddress, proxyUser, proxyPassword), detected);
|
new ProxyParameters(
|
||||||
|
new InetSocketAddress(
|
||||||
|
InetAddress.getByName(unresolvedProxy.getHostName()),
|
||||||
|
unresolvedProxy.getPort()),
|
||||||
|
proxyUser,
|
||||||
|
proxyPassword),
|
||||||
|
detected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -483,9 +483,7 @@ public class OkHttpChannelBuilder extends
|
||||||
hostnameVerifier,
|
hostnameVerifier,
|
||||||
Utils.convertSpec(connectionSpec),
|
Utils.convertSpec(connectionSpec),
|
||||||
maxMessageSize,
|
maxMessageSize,
|
||||||
proxy == null ? null : proxy.proxyAddress,
|
proxy,
|
||||||
proxy == null ? null : proxy.username,
|
|
||||||
proxy == null ? null : proxy.password,
|
|
||||||
tooManyPingsRunnable,
|
tooManyPingsRunnable,
|
||||||
transportTracerFactory.create());
|
transportTracerFactory.create());
|
||||||
if (enableKeepAlive) {
|
if (enableKeepAlive) {
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ import io.grpc.internal.Http2Ping;
|
||||||
import io.grpc.internal.KeepAliveManager;
|
import io.grpc.internal.KeepAliveManager;
|
||||||
import io.grpc.internal.KeepAliveManager.ClientKeepAlivePinger;
|
import io.grpc.internal.KeepAliveManager.ClientKeepAlivePinger;
|
||||||
import io.grpc.internal.LogId;
|
import io.grpc.internal.LogId;
|
||||||
|
import io.grpc.internal.ProxyParameters;
|
||||||
import io.grpc.internal.SerializingExecutor;
|
import io.grpc.internal.SerializingExecutor;
|
||||||
import io.grpc.internal.SharedResourceHolder;
|
import io.grpc.internal.SharedResourceHolder;
|
||||||
import io.grpc.internal.StatsTraceContext;
|
import io.grpc.internal.StatsTraceContext;
|
||||||
|
|
@ -177,25 +178,23 @@ class OkHttpClientTransport implements ConnectionClientTransport {
|
||||||
private long keepAliveTimeNanos;
|
private long keepAliveTimeNanos;
|
||||||
private long keepAliveTimeoutNanos;
|
private long keepAliveTimeoutNanos;
|
||||||
private boolean keepAliveWithoutCalls;
|
private boolean keepAliveWithoutCalls;
|
||||||
@Nullable
|
|
||||||
private final InetSocketAddress proxyAddress;
|
|
||||||
@Nullable
|
|
||||||
private final String proxyUsername;
|
|
||||||
@Nullable
|
|
||||||
private final String proxyPassword;
|
|
||||||
private final Runnable tooManyPingsRunnable;
|
private final Runnable tooManyPingsRunnable;
|
||||||
@GuardedBy("lock")
|
@GuardedBy("lock")
|
||||||
private final TransportTracer transportTracer;
|
private final TransportTracer transportTracer;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
@Nullable
|
||||||
|
final ProxyParameters proxy;
|
||||||
|
|
||||||
// The following fields should only be used for test.
|
// The following fields should only be used for test.
|
||||||
Runnable connectingCallback;
|
Runnable connectingCallback;
|
||||||
SettableFuture<Void> connectedFuture;
|
SettableFuture<Void> connectedFuture;
|
||||||
|
|
||||||
|
|
||||||
OkHttpClientTransport(InetSocketAddress address, String authority, @Nullable String userAgent,
|
OkHttpClientTransport(InetSocketAddress address, String authority, @Nullable String userAgent,
|
||||||
Executor executor, @Nullable SSLSocketFactory sslSocketFactory,
|
Executor executor, @Nullable SSLSocketFactory sslSocketFactory,
|
||||||
@Nullable HostnameVerifier hostnameVerifier, ConnectionSpec connectionSpec,
|
@Nullable HostnameVerifier hostnameVerifier, ConnectionSpec connectionSpec,
|
||||||
int maxMessageSize, @Nullable InetSocketAddress proxyAddress, @Nullable String proxyUsername,
|
int maxMessageSize, @Nullable ProxyParameters proxy, Runnable tooManyPingsRunnable,
|
||||||
@Nullable String proxyPassword, Runnable tooManyPingsRunnable,
|
|
||||||
TransportTracer transportTracer) {
|
TransportTracer transportTracer) {
|
||||||
this.address = Preconditions.checkNotNull(address, "address");
|
this.address = Preconditions.checkNotNull(address, "address");
|
||||||
this.defaultAuthority = authority;
|
this.defaultAuthority = authority;
|
||||||
|
|
@ -210,9 +209,7 @@ class OkHttpClientTransport implements ConnectionClientTransport {
|
||||||
this.connectionSpec = Preconditions.checkNotNull(connectionSpec, "connectionSpec");
|
this.connectionSpec = Preconditions.checkNotNull(connectionSpec, "connectionSpec");
|
||||||
this.stopwatchFactory = GrpcUtil.STOPWATCH_SUPPLIER;
|
this.stopwatchFactory = GrpcUtil.STOPWATCH_SUPPLIER;
|
||||||
this.userAgent = GrpcUtil.getGrpcUserAgent("okhttp", userAgent);
|
this.userAgent = GrpcUtil.getGrpcUserAgent("okhttp", userAgent);
|
||||||
this.proxyAddress = proxyAddress;
|
this.proxy = proxy;
|
||||||
this.proxyUsername = proxyUsername;
|
|
||||||
this.proxyPassword = proxyPassword;
|
|
||||||
this.tooManyPingsRunnable =
|
this.tooManyPingsRunnable =
|
||||||
Preconditions.checkNotNull(tooManyPingsRunnable, "tooManyPingsRunnable");
|
Preconditions.checkNotNull(tooManyPingsRunnable, "tooManyPingsRunnable");
|
||||||
this.transportTracer = Preconditions.checkNotNull(transportTracer);
|
this.transportTracer = Preconditions.checkNotNull(transportTracer);
|
||||||
|
|
@ -250,9 +247,7 @@ class OkHttpClientTransport implements ConnectionClientTransport {
|
||||||
this.connectionSpec = null;
|
this.connectionSpec = null;
|
||||||
this.connectingCallback = connectingCallback;
|
this.connectingCallback = connectingCallback;
|
||||||
this.connectedFuture = Preconditions.checkNotNull(connectedFuture, "connectedFuture");
|
this.connectedFuture = Preconditions.checkNotNull(connectedFuture, "connectedFuture");
|
||||||
this.proxyAddress = null;
|
this.proxy = null;
|
||||||
this.proxyUsername = null;
|
|
||||||
this.proxyPassword = null;
|
|
||||||
this.tooManyPingsRunnable =
|
this.tooManyPingsRunnable =
|
||||||
Preconditions.checkNotNull(tooManyPingsRunnable, "tooManyPingsRunnable");
|
Preconditions.checkNotNull(tooManyPingsRunnable, "tooManyPingsRunnable");
|
||||||
this.transportTracer = Preconditions.checkNotNull(transportTracer, "transportTracer");
|
this.transportTracer = Preconditions.checkNotNull(transportTracer, "transportTracer");
|
||||||
|
|
@ -456,10 +451,11 @@ class OkHttpClientTransport implements ConnectionClientTransport {
|
||||||
BufferedSink sink;
|
BufferedSink sink;
|
||||||
Socket sock;
|
Socket sock;
|
||||||
try {
|
try {
|
||||||
if (proxyAddress == null) {
|
if (proxy == null) {
|
||||||
sock = new Socket(address.getAddress(), address.getPort());
|
sock = new Socket(address.getAddress(), address.getPort());
|
||||||
} else {
|
} else {
|
||||||
sock = createHttpProxySocket(address, proxyAddress, proxyUsername, proxyPassword);
|
sock = createHttpProxySocket(
|
||||||
|
address, proxy.proxyAddress, proxy.username, proxy.password);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sslSocketFactory != null) {
|
if (sslSocketFactory != null) {
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ import io.grpc.internal.ClientTransport;
|
||||||
import io.grpc.internal.GrpcUtil;
|
import io.grpc.internal.GrpcUtil;
|
||||||
import io.grpc.internal.Instrumented;
|
import io.grpc.internal.Instrumented;
|
||||||
import io.grpc.internal.ManagedClientTransport;
|
import io.grpc.internal.ManagedClientTransport;
|
||||||
|
import io.grpc.internal.ProxyParameters;
|
||||||
import io.grpc.internal.TransportTracer;
|
import io.grpc.internal.TransportTracer;
|
||||||
import io.grpc.okhttp.OkHttpClientTransport.ClientFrameHandler;
|
import io.grpc.okhttp.OkHttpClientTransport.ClientFrameHandler;
|
||||||
import io.grpc.okhttp.internal.ConnectionSpec;
|
import io.grpc.okhttp.internal.ConnectionSpec;
|
||||||
|
|
@ -124,6 +125,9 @@ public class OkHttpClientTransportTest {
|
||||||
// The gRPC header length, which includes 1 byte compression flag and 4 bytes message length.
|
// The gRPC header length, which includes 1 byte compression flag and 4 bytes message length.
|
||||||
private static final int HEADER_LENGTH = 5;
|
private static final int HEADER_LENGTH = 5;
|
||||||
private static final Status SHUTDOWN_REASON = Status.UNAVAILABLE.withDescription("for test");
|
private static final Status SHUTDOWN_REASON = Status.UNAVAILABLE.withDescription("for test");
|
||||||
|
private static final ProxyParameters NO_PROXY = null;
|
||||||
|
private static final String NO_USER = null;
|
||||||
|
private static final String NO_PW = null;
|
||||||
|
|
||||||
@Rule public final Timeout globalTimeout = Timeout.seconds(10);
|
@Rule public final Timeout globalTimeout = Timeout.seconds(10);
|
||||||
|
|
||||||
|
|
@ -137,9 +141,6 @@ public class OkHttpClientTransportTest {
|
||||||
|
|
||||||
private final SSLSocketFactory sslSocketFactory = null;
|
private final SSLSocketFactory sslSocketFactory = null;
|
||||||
private final HostnameVerifier hostnameVerifier = null;
|
private final HostnameVerifier hostnameVerifier = null;
|
||||||
private final InetSocketAddress proxyAddr = null;
|
|
||||||
private final String proxyUser = null;
|
|
||||||
private final String proxyPassword = null;
|
|
||||||
private final TransportTracer transportTracer = new TransportTracer();
|
private final TransportTracer transportTracer = new TransportTracer();
|
||||||
private OkHttpClientTransport clientTransport;
|
private OkHttpClientTransport clientTransport;
|
||||||
private MockFrameReader frameReader;
|
private MockFrameReader frameReader;
|
||||||
|
|
@ -225,9 +226,7 @@ public class OkHttpClientTransportTest {
|
||||||
hostnameVerifier,
|
hostnameVerifier,
|
||||||
Utils.convertSpec(OkHttpChannelBuilder.DEFAULT_CONNECTION_SPEC),
|
Utils.convertSpec(OkHttpChannelBuilder.DEFAULT_CONNECTION_SPEC),
|
||||||
DEFAULT_MAX_MESSAGE_SIZE,
|
DEFAULT_MAX_MESSAGE_SIZE,
|
||||||
proxyAddr,
|
NO_PROXY,
|
||||||
proxyUser,
|
|
||||||
proxyPassword,
|
|
||||||
tooManyPingsRunnable,
|
tooManyPingsRunnable,
|
||||||
transportTracer);
|
transportTracer);
|
||||||
String s = clientTransport.toString();
|
String s = clientTransport.toString();
|
||||||
|
|
@ -1450,9 +1449,7 @@ public class OkHttpClientTransportTest {
|
||||||
hostnameVerifier,
|
hostnameVerifier,
|
||||||
ConnectionSpec.CLEARTEXT,
|
ConnectionSpec.CLEARTEXT,
|
||||||
DEFAULT_MAX_MESSAGE_SIZE,
|
DEFAULT_MAX_MESSAGE_SIZE,
|
||||||
proxyAddr,
|
NO_PROXY,
|
||||||
proxyUser,
|
|
||||||
proxyPassword,
|
|
||||||
tooManyPingsRunnable,
|
tooManyPingsRunnable,
|
||||||
transportTracer);
|
transportTracer);
|
||||||
|
|
||||||
|
|
@ -1474,9 +1471,7 @@ public class OkHttpClientTransportTest {
|
||||||
hostnameVerifier,
|
hostnameVerifier,
|
||||||
ConnectionSpec.CLEARTEXT,
|
ConnectionSpec.CLEARTEXT,
|
||||||
DEFAULT_MAX_MESSAGE_SIZE,
|
DEFAULT_MAX_MESSAGE_SIZE,
|
||||||
proxyAddr,
|
NO_PROXY,
|
||||||
proxyUser,
|
|
||||||
proxyPassword,
|
|
||||||
tooManyPingsRunnable,
|
tooManyPingsRunnable,
|
||||||
new TransportTracer());
|
new TransportTracer());
|
||||||
|
|
||||||
|
|
@ -1506,9 +1501,8 @@ public class OkHttpClientTransportTest {
|
||||||
hostnameVerifier,
|
hostnameVerifier,
|
||||||
ConnectionSpec.CLEARTEXT,
|
ConnectionSpec.CLEARTEXT,
|
||||||
DEFAULT_MAX_MESSAGE_SIZE,
|
DEFAULT_MAX_MESSAGE_SIZE,
|
||||||
(InetSocketAddress) serverSocket.getLocalSocketAddress(),
|
new ProxyParameters(
|
||||||
proxyUser,
|
(InetSocketAddress) serverSocket.getLocalSocketAddress(), NO_USER, NO_PW),
|
||||||
proxyPassword,
|
|
||||||
tooManyPingsRunnable,
|
tooManyPingsRunnable,
|
||||||
transportTracer);
|
transportTracer);
|
||||||
clientTransport.start(transportListener);
|
clientTransport.start(transportListener);
|
||||||
|
|
@ -1557,9 +1551,8 @@ public class OkHttpClientTransportTest {
|
||||||
hostnameVerifier,
|
hostnameVerifier,
|
||||||
ConnectionSpec.CLEARTEXT,
|
ConnectionSpec.CLEARTEXT,
|
||||||
DEFAULT_MAX_MESSAGE_SIZE,
|
DEFAULT_MAX_MESSAGE_SIZE,
|
||||||
(InetSocketAddress) serverSocket.getLocalSocketAddress(),
|
new ProxyParameters(
|
||||||
proxyUser,
|
(InetSocketAddress) serverSocket.getLocalSocketAddress(), NO_USER, NO_PW),
|
||||||
proxyPassword,
|
|
||||||
tooManyPingsRunnable,
|
tooManyPingsRunnable,
|
||||||
transportTracer);
|
transportTracer);
|
||||||
clientTransport.start(transportListener);
|
clientTransport.start(transportListener);
|
||||||
|
|
@ -1607,9 +1600,8 @@ public class OkHttpClientTransportTest {
|
||||||
hostnameVerifier,
|
hostnameVerifier,
|
||||||
ConnectionSpec.CLEARTEXT,
|
ConnectionSpec.CLEARTEXT,
|
||||||
DEFAULT_MAX_MESSAGE_SIZE,
|
DEFAULT_MAX_MESSAGE_SIZE,
|
||||||
(InetSocketAddress) serverSocket.getLocalSocketAddress(),
|
new ProxyParameters(
|
||||||
proxyUser,
|
(InetSocketAddress) serverSocket.getLocalSocketAddress(), NO_USER, NO_PW),
|
||||||
proxyPassword,
|
|
||||||
tooManyPingsRunnable,
|
tooManyPingsRunnable,
|
||||||
transportTracer);
|
transportTracer);
|
||||||
clientTransport.start(transportListener);
|
clientTransport.start(transportListener);
|
||||||
|
|
@ -1628,34 +1620,6 @@ public class OkHttpClientTransportTest {
|
||||||
verify(transportListener, timeout(TIME_OUT_MS)).transportTerminated();
|
verify(transportListener, timeout(TIME_OUT_MS)).transportTerminated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void proxy_unresolvedProxyAddress() throws Exception {
|
|
||||||
clientTransport = new OkHttpClientTransport(
|
|
||||||
InetSocketAddress.createUnresolved("theservice", 80),
|
|
||||||
"authority",
|
|
||||||
"userAgent",
|
|
||||||
executor,
|
|
||||||
sslSocketFactory,
|
|
||||||
hostnameVerifier,
|
|
||||||
ConnectionSpec.CLEARTEXT,
|
|
||||||
DEFAULT_MAX_MESSAGE_SIZE,
|
|
||||||
InetSocketAddress.createUnresolved("unresolvedproxy", 80),
|
|
||||||
proxyUser,
|
|
||||||
proxyPassword,
|
|
||||||
tooManyPingsRunnable,
|
|
||||||
transportTracer);
|
|
||||||
clientTransport.start(transportListener);
|
|
||||||
|
|
||||||
ArgumentCaptor<Status> captor = ArgumentCaptor.forClass(Status.class);
|
|
||||||
verify(transportListener, timeout(TIME_OUT_MS)).transportShutdown(captor.capture());
|
|
||||||
Status error = captor.getValue();
|
|
||||||
assertTrue("Status didn't contain proxy: " + captor.getValue(),
|
|
||||||
error.getDescription().contains("proxy"));
|
|
||||||
assertEquals("Not UNAVAILABLE: " + captor.getValue(),
|
|
||||||
Status.UNAVAILABLE.getCode(), error.getCode());
|
|
||||||
verify(transportListener, timeout(TIME_OUT_MS)).transportTerminated();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void goAway_notUtf8() throws Exception {
|
public void goAway_notUtf8() throws Exception {
|
||||||
initTransport();
|
initTransport();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue