Extract SocketAdress logic from NameResolver
Motivation: As discussed in #4529, NameResolver design shouldn't be resolving SocketAddresses (or String name + port) and return InetSocketAddresses. It should resolve String names and return InetAddresses. This SocketAddress to InetSocketAddresses resolution is actually a different concern, used by Bootstrap. Modifications: Extract SocketAddress to InetSocketAddresses resolution concern to a new class hierarchy named AddressResolver. These AddressResolvers delegate to NameResolvers. Result: Better separation of concerns. Note that new AddressResolvers generate a bit more allocations because of the intermediate Promise and List<InetAddress>.
This commit is contained in:
parent
89ff831a67
commit
6393506b97
@ -36,7 +36,7 @@ import io.netty.handler.codec.LineBasedFrameDecoder;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
import io.netty.resolver.NoopNameResolverGroup;
|
||||
import io.netty.resolver.NoopAddressResolverGroup;
|
||||
import io.netty.util.CharsetUtil;
|
||||
import io.netty.util.concurrent.DefaultThreadFactory;
|
||||
import io.netty.util.concurrent.Future;
|
||||
@ -523,7 +523,7 @@ public class ProxyHandlerTest {
|
||||
Bootstrap b = new Bootstrap();
|
||||
b.group(group);
|
||||
b.channel(NioSocketChannel.class);
|
||||
b.resolver(NoopNameResolverGroup.INSTANCE);
|
||||
b.resolver(NoopAddressResolverGroup.INSTANCE);
|
||||
b.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception {
|
||||
@ -571,7 +571,7 @@ public class ProxyHandlerTest {
|
||||
Bootstrap b = new Bootstrap();
|
||||
b.group(group);
|
||||
b.channel(NioSocketChannel.class);
|
||||
b.resolver(NoopNameResolverGroup.INSTANCE);
|
||||
b.resolver(NoopAddressResolverGroup.INSTANCE);
|
||||
b.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception {
|
||||
@ -616,7 +616,7 @@ public class ProxyHandlerTest {
|
||||
Bootstrap b = new Bootstrap();
|
||||
b.group(group);
|
||||
b.channel(NioSocketChannel.class);
|
||||
b.resolver(NoopNameResolverGroup.INSTANCE);
|
||||
b.resolver(NoopAddressResolverGroup.INSTANCE);
|
||||
b.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception {
|
||||
|
@ -20,8 +20,8 @@ import io.netty.channel.ChannelFactory;
|
||||
import io.netty.channel.EventLoop;
|
||||
import io.netty.channel.ReflectiveChannelFactory;
|
||||
import io.netty.channel.socket.DatagramChannel;
|
||||
import io.netty.resolver.NameResolver;
|
||||
import io.netty.resolver.NameResolverGroup;
|
||||
import io.netty.resolver.AddressResolver;
|
||||
import io.netty.resolver.AddressResolverGroup;
|
||||
import io.netty.util.concurrent.EventExecutor;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
@ -30,31 +30,31 @@ import java.net.InetSocketAddress;
|
||||
import static io.netty.resolver.dns.DnsNameResolver.ANY_LOCAL_ADDR;
|
||||
|
||||
/**
|
||||
* A {@link NameResolverGroup} of {@link DnsNameResolver}s.
|
||||
* A {@link AddressResolverGroup} of {@link DnsNameResolver}s.
|
||||
*/
|
||||
public class DnsNameResolverGroup extends NameResolverGroup<InetSocketAddress> {
|
||||
public class DnsAddressResolverGroup extends AddressResolverGroup<InetSocketAddress> {
|
||||
|
||||
private final ChannelFactory<? extends DatagramChannel> channelFactory;
|
||||
private final InetSocketAddress localAddress;
|
||||
private final DnsServerAddresses nameServerAddresses;
|
||||
|
||||
public DnsNameResolverGroup(
|
||||
public DnsAddressResolverGroup(
|
||||
Class<? extends DatagramChannel> channelType, DnsServerAddresses nameServerAddresses) {
|
||||
this(channelType, ANY_LOCAL_ADDR, nameServerAddresses);
|
||||
}
|
||||
|
||||
public DnsNameResolverGroup(
|
||||
public DnsAddressResolverGroup(
|
||||
Class<? extends DatagramChannel> channelType,
|
||||
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
|
||||
this(new ReflectiveChannelFactory<DatagramChannel>(channelType), localAddress, nameServerAddresses);
|
||||
}
|
||||
|
||||
public DnsNameResolverGroup(
|
||||
public DnsAddressResolverGroup(
|
||||
ChannelFactory<? extends DatagramChannel> channelFactory, DnsServerAddresses nameServerAddresses) {
|
||||
this(channelFactory, ANY_LOCAL_ADDR, nameServerAddresses);
|
||||
}
|
||||
|
||||
public DnsNameResolverGroup(
|
||||
public DnsAddressResolverGroup(
|
||||
ChannelFactory<? extends DatagramChannel> channelFactory,
|
||||
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
|
||||
this.channelFactory = channelFactory;
|
||||
@ -63,7 +63,7 @@ public class DnsNameResolverGroup extends NameResolverGroup<InetSocketAddress> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final NameResolver<InetSocketAddress> newResolver(EventExecutor executor) throws Exception {
|
||||
protected final AddressResolver<InetSocketAddress> newResolver(EventExecutor executor) throws Exception {
|
||||
if (!(executor instanceof EventLoop)) {
|
||||
throw new IllegalStateException(
|
||||
"unsupported executor type: " + StringUtil.simpleClassName(executor) +
|
||||
@ -77,11 +77,11 @@ public class DnsNameResolverGroup extends NameResolverGroup<InetSocketAddress> {
|
||||
* Creates a new {@link DnsNameResolver}. Override this method to create an alternative {@link DnsNameResolver}
|
||||
* implementation or override the default configuration.
|
||||
*/
|
||||
protected DnsNameResolver newResolver(
|
||||
protected AddressResolver<InetSocketAddress> newResolver(
|
||||
EventLoop eventLoop, ChannelFactory<? extends DatagramChannel> channelFactory,
|
||||
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) throws Exception {
|
||||
|
||||
return new DnsNameResolver(
|
||||
eventLoop, channelFactory, localAddress, nameServerAddresses);
|
||||
return new DnsNameResolver(eventLoop, channelFactory, localAddress, nameServerAddresses)
|
||||
.asAddressResolver();
|
||||
}
|
||||
}
|
@ -33,8 +33,7 @@ import io.netty.handler.codec.dns.DatagramDnsResponse;
|
||||
import io.netty.handler.codec.dns.DatagramDnsResponseDecoder;
|
||||
import io.netty.handler.codec.dns.DnsQuestion;
|
||||
import io.netty.handler.codec.dns.DnsResponse;
|
||||
import io.netty.resolver.NameResolver;
|
||||
import io.netty.resolver.SimpleNameResolver;
|
||||
import io.netty.resolver.InetNameResolver;
|
||||
import io.netty.util.NetUtil;
|
||||
import io.netty.util.ReferenceCountUtil;
|
||||
import io.netty.util.concurrent.FastThreadLocal;
|
||||
@ -42,14 +41,12 @@ import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.Promise;
|
||||
import io.netty.util.internal.OneTimeTask;
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
import io.netty.util.internal.SystemPropertyUtil;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
import java.net.IDN;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@ -62,9 +59,9 @@ import java.util.concurrent.TimeUnit;
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
/**
|
||||
* A DNS-based {@link NameResolver}.
|
||||
* A DNS-based {@link InetNameResolver}.
|
||||
*/
|
||||
public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
public class DnsNameResolver extends InetNameResolver {
|
||||
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(DnsNameResolver.class);
|
||||
|
||||
@ -74,7 +71,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
|
||||
static {
|
||||
// Note that we did not use SystemPropertyUtil.getBoolean() here to emulate the behavior of JDK.
|
||||
if ("true".equalsIgnoreCase(SystemPropertyUtil.get("java.net.preferIPv6Addresses"))) {
|
||||
if (Boolean.getBoolean("java.net.preferIPv6Addresses")) {
|
||||
DEFAULT_RESOLVE_ADDRESS_TYPES[0] = InternetProtocolFamily.IPv6;
|
||||
DEFAULT_RESOLVE_ADDRESS_TYPES[1] = InternetProtocolFamily.IPv4;
|
||||
logger.debug("-Djava.net.preferIPv6Addresses: true");
|
||||
@ -98,7 +95,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
final DnsQueryContextManager queryContextManager = new DnsQueryContextManager();
|
||||
|
||||
/**
|
||||
* Cache for {@link #doResolve(InetSocketAddress, Promise)} and {@link #doResolveAll(InetSocketAddress, Promise)}.
|
||||
* Cache for {@link #doResolve(String, Promise)} and {@link #doResolveAll(String, Promise)}.
|
||||
*/
|
||||
final ConcurrentMap<String, List<DnsCacheEntry>> resolveCache = PlatformDependent.newConcurrentHashMap();
|
||||
|
||||
@ -329,7 +326,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of the protocol families of the address resolved by {@link #resolve(SocketAddress)}
|
||||
* Returns the list of the protocol families of the address resolved by {@link #resolve(String)}
|
||||
* in the order of preference.
|
||||
* The default value depends on the value of the system property {@code "java.net.preferIPv6Addresses"}.
|
||||
*
|
||||
@ -344,7 +341,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of the protocol families of the address resolved by {@link #resolve(SocketAddress)}.
|
||||
* Sets the list of the protocol families of the address resolved by {@link #resolve(String)}.
|
||||
* Usually, both {@link InternetProtocolFamily#IPv4} and {@link InternetProtocolFamily#IPv6} are specified in the
|
||||
* order of preference. To enforce the resolve to retrieve the address of a specific protocol family, specify
|
||||
* only a single {@link InternetProtocolFamily}.
|
||||
@ -382,7 +379,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of the protocol families of the address resolved by {@link #resolve(SocketAddress)}.
|
||||
* Sets the list of the protocol families of the address resolved by {@link #resolve(String)}.
|
||||
* Usually, both {@link InternetProtocolFamily#IPv4} and {@link InternetProtocolFamily#IPv6} are specified in the
|
||||
* order of preference. To enforce the resolve to retrieve the address of a specific protocol family, specify
|
||||
* only a single {@link InternetProtocolFamily}.
|
||||
@ -594,28 +591,22 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doIsResolved(InetSocketAddress address) {
|
||||
return !address.isUnresolved();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doResolve(InetSocketAddress unresolvedAddress, Promise<InetSocketAddress> promise) throws Exception {
|
||||
final byte[] bytes = NetUtil.createByteArrayFromIpAddressString(unresolvedAddress.getHostName());
|
||||
protected void doResolve(String inetHost, Promise<InetAddress> promise) throws Exception {
|
||||
final byte[] bytes = NetUtil.createByteArrayFromIpAddressString(inetHost);
|
||||
if (bytes != null) {
|
||||
// The unresolvedAddress was created via a String that contains an ipaddress.
|
||||
promise.setSuccess(new InetSocketAddress(InetAddress.getByAddress(bytes), unresolvedAddress.getPort()));
|
||||
// The inetHost is actually an ipaddress.
|
||||
promise.setSuccess(InetAddress.getByAddress(bytes));
|
||||
return;
|
||||
}
|
||||
|
||||
final String hostname = hostname(unresolvedAddress);
|
||||
final int port = unresolvedAddress.getPort();
|
||||
final String hostname = hostname(inetHost);
|
||||
|
||||
if (!doResolveCached(hostname, port, promise)) {
|
||||
doResolveUncached(hostname, port, promise);
|
||||
if (!doResolveCached(hostname, promise)) {
|
||||
doResolveUncached(hostname, promise);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean doResolveCached(String hostname, int port, Promise<InetSocketAddress> promise) {
|
||||
private boolean doResolveCached(String hostname, Promise<InetAddress> promise) {
|
||||
final List<DnsCacheEntry> cachedEntries = resolveCache.get(hostname);
|
||||
if (cachedEntries == null) {
|
||||
return false;
|
||||
@ -644,7 +635,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
}
|
||||
|
||||
if (address != null) {
|
||||
setSuccess(promise, new InetSocketAddress(address, port));
|
||||
setSuccess(promise, address);
|
||||
} else if (cause != null) {
|
||||
if (!promise.tryFailure(cause)) {
|
||||
logger.warn("Failed to notify failure to a promise: {}", promise, cause);
|
||||
@ -656,15 +647,15 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void setSuccess(Promise<InetSocketAddress> promise, InetSocketAddress result) {
|
||||
private static void setSuccess(Promise<InetAddress> promise, InetAddress result) {
|
||||
if (!promise.trySuccess(result)) {
|
||||
logger.warn("Failed to notify success ({}) to a promise: {}", result, promise);
|
||||
}
|
||||
}
|
||||
|
||||
private void doResolveUncached(String hostname, final int port, Promise<InetSocketAddress> promise) {
|
||||
final DnsNameResolverContext<InetSocketAddress> ctx =
|
||||
new DnsNameResolverContext<InetSocketAddress>(this, hostname, promise) {
|
||||
private void doResolveUncached(String hostname, Promise<InetAddress> promise) {
|
||||
final DnsNameResolverContext<InetAddress> ctx =
|
||||
new DnsNameResolverContext<InetAddress>(this, hostname, promise) {
|
||||
@Override
|
||||
protected boolean finishResolve(
|
||||
Class<? extends InetAddress> addressType, List<DnsCacheEntry> resolvedEntries) {
|
||||
@ -673,7 +664,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
for (int i = 0; i < numEntries; i++) {
|
||||
final InetAddress a = resolvedEntries.get(i).address();
|
||||
if (addressType.isInstance(a)) {
|
||||
setSuccess(promise(), new InetSocketAddress(a, port));
|
||||
setSuccess(promise(), a);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -685,32 +676,29 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doResolveAll(
|
||||
InetSocketAddress unresolvedAddress, Promise<List<InetSocketAddress>> promise) throws Exception {
|
||||
protected void doResolveAll(String inetHost, Promise<List<InetAddress>> promise) throws Exception {
|
||||
|
||||
final byte[] bytes = NetUtil.createByteArrayFromIpAddressString(unresolvedAddress.getHostName());
|
||||
final byte[] bytes = NetUtil.createByteArrayFromIpAddressString(inetHost);
|
||||
if (bytes != null) {
|
||||
// The unresolvedAddress was created via a String that contains an ipaddress.
|
||||
promise.setSuccess(Collections.singletonList(
|
||||
new InetSocketAddress(InetAddress.getByAddress(bytes), unresolvedAddress.getPort())));
|
||||
promise.setSuccess(Collections.singletonList(InetAddress.getByAddress(bytes)));
|
||||
return;
|
||||
}
|
||||
|
||||
final String hostname = hostname(unresolvedAddress);
|
||||
final int port = unresolvedAddress.getPort();
|
||||
final String hostname = hostname(inetHost);
|
||||
|
||||
if (!doResolveAllCached(hostname, port, promise)) {
|
||||
doResolveAllUncached(hostname, port, promise);
|
||||
if (!doResolveAllCached(hostname, promise)) {
|
||||
doResolveAllUncached(hostname, promise);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean doResolveAllCached(String hostname, int port, Promise<List<InetSocketAddress>> promise) {
|
||||
private boolean doResolveAllCached(String hostname, Promise<List<InetAddress>> promise) {
|
||||
final List<DnsCacheEntry> cachedEntries = resolveCache.get(hostname);
|
||||
if (cachedEntries == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<InetSocketAddress> result = null;
|
||||
List<InetAddress> result = null;
|
||||
Throwable cause = null;
|
||||
synchronized (cachedEntries) {
|
||||
final int numEntries = cachedEntries.size();
|
||||
@ -724,9 +712,9 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
final DnsCacheEntry e = cachedEntries.get(i);
|
||||
if (f.addressType().isInstance(e.address())) {
|
||||
if (result == null) {
|
||||
result = new ArrayList<InetSocketAddress>(numEntries);
|
||||
result = new ArrayList<InetAddress>(numEntries);
|
||||
}
|
||||
result.add(new InetSocketAddress(e.address(), port));
|
||||
result.add(e.address());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -744,23 +732,22 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void doResolveAllUncached(final String hostname, final int port,
|
||||
final Promise<List<InetSocketAddress>> promise) {
|
||||
final DnsNameResolverContext<List<InetSocketAddress>> ctx =
|
||||
new DnsNameResolverContext<List<InetSocketAddress>>(this, hostname, promise) {
|
||||
private void doResolveAllUncached(final String hostname, final Promise<List<InetAddress>> promise) {
|
||||
final DnsNameResolverContext<List<InetAddress>> ctx =
|
||||
new DnsNameResolverContext<List<InetAddress>>(this, hostname, promise) {
|
||||
@Override
|
||||
protected boolean finishResolve(
|
||||
Class<? extends InetAddress> addressType, List<DnsCacheEntry> resolvedEntries) {
|
||||
|
||||
List<InetSocketAddress> result = null;
|
||||
List<InetAddress> result = null;
|
||||
final int numEntries = resolvedEntries.size();
|
||||
for (int i = 0; i < numEntries; i++) {
|
||||
final InetAddress a = resolvedEntries.get(i).address();
|
||||
if (addressType.isInstance(a)) {
|
||||
if (result == null) {
|
||||
result = new ArrayList<InetSocketAddress>(numEntries);
|
||||
result = new ArrayList<InetAddress>(numEntries);
|
||||
}
|
||||
result.add(new InetSocketAddress(a, port));
|
||||
result.add(a);
|
||||
}
|
||||
}
|
||||
|
||||
@ -775,16 +762,8 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
ctx.resolve();
|
||||
}
|
||||
|
||||
private static String hostname(InetSocketAddress addr) {
|
||||
// InetSocketAddress.getHostString() is available since Java 7.
|
||||
final String hostname;
|
||||
if (PlatformDependent.javaVersion() < 7) {
|
||||
hostname = addr.getHostName();
|
||||
} else {
|
||||
hostname = addr.getHostString();
|
||||
}
|
||||
|
||||
return IDN.toASCII(hostname);
|
||||
private static String hostname(String inetHost) {
|
||||
return IDN.toASCII(inetHost);
|
||||
}
|
||||
|
||||
void cache(String hostname, InetAddress address, long originalTtl) {
|
||||
|
@ -320,7 +320,7 @@ public class DnsNameResolverTest {
|
||||
InetAddress actual = resultB.get(e.getKey());
|
||||
if (!actual.equals(expected)) {
|
||||
// Print the content of the cache when test failure is expected.
|
||||
System.err.println("Cache for " + e.getKey() + ": " + resolver.resolveAll(e.getKey(), 0).getNow());
|
||||
System.err.println("Cache for " + e.getKey() + ": " + resolver.resolveAll(e.getKey()).getNow());
|
||||
}
|
||||
assertThat(actual, is(expected));
|
||||
}
|
||||
@ -347,8 +347,8 @@ public class DnsNameResolverTest {
|
||||
|
||||
final Map<String, InetAddress> results = new HashMap<String, InetAddress>();
|
||||
try {
|
||||
final Map<InetSocketAddress, Future<InetSocketAddress>> futures =
|
||||
new LinkedHashMap<InetSocketAddress, Future<InetSocketAddress>>();
|
||||
final Map<String, Future<InetAddress>> futures =
|
||||
new LinkedHashMap<String, Future<InetAddress>>();
|
||||
|
||||
for (String name : DOMAINS) {
|
||||
if (excludedDomains.contains(name)) {
|
||||
@ -358,19 +358,17 @@ public class DnsNameResolverTest {
|
||||
resolve(futures, name);
|
||||
}
|
||||
|
||||
for (Entry<InetSocketAddress, Future<InetSocketAddress>> e : futures.entrySet()) {
|
||||
InetSocketAddress unresolved = e.getKey();
|
||||
InetSocketAddress resolved = e.getValue().sync().getNow();
|
||||
for (Entry<String, Future<InetAddress>> e : futures.entrySet()) {
|
||||
String unresolved = e.getKey();
|
||||
InetAddress resolved = e.getValue().sync().getNow();
|
||||
|
||||
logger.info("{}: {}", unresolved.getHostString(), resolved.getAddress().getHostAddress());
|
||||
logger.info("{}: {}", unresolved, resolved.getHostAddress());
|
||||
|
||||
assertThat(resolved.isUnresolved(), is(false));
|
||||
assertThat(resolved.getHostString(), is(unresolved.getHostString()));
|
||||
assertThat(resolved.getPort(), is(unresolved.getPort()));
|
||||
assertThat(resolved.getHostName(), is(unresolved));
|
||||
|
||||
boolean typeMatches = false;
|
||||
for (InternetProtocolFamily f: famililies) {
|
||||
Class<?> resolvedType = resolved.getAddress().getClass();
|
||||
Class<?> resolvedType = resolved.getClass();
|
||||
if (f.addressType().isAssignableFrom(resolvedType)) {
|
||||
typeMatches = true;
|
||||
}
|
||||
@ -378,7 +376,7 @@ public class DnsNameResolverTest {
|
||||
|
||||
assertThat(typeMatches, is(true));
|
||||
|
||||
results.put(resolved.getHostString(), resolved.getAddress());
|
||||
results.put(resolved.getHostName(), resolved);
|
||||
}
|
||||
} finally {
|
||||
resolver.setResolveAddressTypes(oldResolveAddressTypes);
|
||||
@ -477,7 +475,7 @@ public class DnsNameResolverTest {
|
||||
|
||||
private static UnknownHostException resolveNonExistentDomain() {
|
||||
try {
|
||||
resolver.resolve("non-existent.netty.io", 0).sync();
|
||||
resolver.resolve("non-existent.netty.io").sync();
|
||||
fail();
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
@ -488,20 +486,14 @@ public class DnsNameResolverTest {
|
||||
|
||||
@Test
|
||||
public void testResolveIp() {
|
||||
InetSocketAddress unresolved =
|
||||
InetSocketAddress.createUnresolved("10.0.0.1", ThreadLocalRandom.current().nextInt(65536));
|
||||
|
||||
InetSocketAddress address = resolver.resolve(unresolved).syncUninterruptibly().getNow();
|
||||
InetAddress address = resolver.resolve("10.0.0.1").syncUninterruptibly().getNow();
|
||||
|
||||
assertEquals("10.0.0.1", address.getHostName());
|
||||
}
|
||||
|
||||
private static void resolve(
|
||||
Map<InetSocketAddress, Future<InetSocketAddress>> futures, String hostname) {
|
||||
InetSocketAddress unresolved =
|
||||
InetSocketAddress.createUnresolved(hostname, ThreadLocalRandom.current().nextInt(65536));
|
||||
private static void resolve(Map<String, Future<InetAddress>> futures, String hostname) {
|
||||
|
||||
futures.put(unresolved, resolver.resolve(unresolved));
|
||||
futures.put(hostname, resolver.resolve(hostname));
|
||||
}
|
||||
|
||||
private static void queryMx(
|
||||
|
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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.netty.resolver;
|
||||
|
||||
import io.netty.util.concurrent.EventExecutor;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.Promise;
|
||||
import io.netty.util.internal.TypeParameterMatcher;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.UnsupportedAddressTypeException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
/**
|
||||
* A skeletal {@link AddressResolver} implementation.
|
||||
*/
|
||||
public abstract class AbstractAddressResolver<T extends SocketAddress> implements AddressResolver<T> {
|
||||
|
||||
private final EventExecutor executor;
|
||||
private final TypeParameterMatcher matcher;
|
||||
|
||||
/**
|
||||
* @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned
|
||||
* by {@link #resolve(SocketAddress)}
|
||||
*/
|
||||
protected AbstractAddressResolver(EventExecutor executor) {
|
||||
this.executor = checkNotNull(executor, "executor");
|
||||
matcher = TypeParameterMatcher.find(this, AbstractAddressResolver.class, "T");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned
|
||||
* by {@link #resolve(SocketAddress)}
|
||||
* @param addressType the type of the {@link SocketAddress} supported by this resolver
|
||||
*/
|
||||
protected AbstractAddressResolver(EventExecutor executor, Class<? extends T> addressType) {
|
||||
this.executor = checkNotNull(executor, "executor");
|
||||
matcher = TypeParameterMatcher.get(addressType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned
|
||||
* by {@link #resolve(SocketAddress)}.
|
||||
*/
|
||||
protected EventExecutor executor() {
|
||||
return executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported(SocketAddress address) {
|
||||
return matcher.match(address);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isResolved(SocketAddress address) {
|
||||
if (!isSupported(address)) {
|
||||
throw new UnsupportedAddressTypeException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final T castAddress = (T) address;
|
||||
return doIsResolved(castAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by {@link #isResolved(SocketAddress)} to check if the specified {@code address} has been resolved
|
||||
* already.
|
||||
*/
|
||||
protected abstract boolean doIsResolved(T address);
|
||||
|
||||
@Override
|
||||
public final Future<T> resolve(SocketAddress address) {
|
||||
if (!isSupported(checkNotNull(address, "address"))) {
|
||||
// Address type not supported by the resolver
|
||||
return executor().newFailedFuture(new UnsupportedAddressTypeException());
|
||||
}
|
||||
|
||||
if (isResolved(address)) {
|
||||
// Resolved already; no need to perform a lookup
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
return executor.newSucceededFuture(cast);
|
||||
}
|
||||
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
final Promise<T> promise = executor().newPromise();
|
||||
doResolve(cast, promise);
|
||||
return promise;
|
||||
} catch (Exception e) {
|
||||
return executor().newFailedFuture(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Future<T> resolve(SocketAddress address, Promise<T> promise) {
|
||||
checkNotNull(address, "address");
|
||||
checkNotNull(promise, "promise");
|
||||
|
||||
if (!isSupported(address)) {
|
||||
// Address type not supported by the resolver
|
||||
return promise.setFailure(new UnsupportedAddressTypeException());
|
||||
}
|
||||
|
||||
if (isResolved(address)) {
|
||||
// Resolved already; no need to perform a lookup
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
return promise.setSuccess(cast);
|
||||
}
|
||||
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
doResolve(cast, promise);
|
||||
return promise;
|
||||
} catch (Exception e) {
|
||||
return promise.setFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Future<List<T>> resolveAll(SocketAddress address) {
|
||||
if (!isSupported(checkNotNull(address, "address"))) {
|
||||
// Address type not supported by the resolver
|
||||
return executor().newFailedFuture(new UnsupportedAddressTypeException());
|
||||
}
|
||||
|
||||
if (isResolved(address)) {
|
||||
// Resolved already; no need to perform a lookup
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
return executor.newSucceededFuture(Collections.singletonList(cast));
|
||||
}
|
||||
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
final Promise<List<T>> promise = executor().newPromise();
|
||||
doResolveAll(cast, promise);
|
||||
return promise;
|
||||
} catch (Exception e) {
|
||||
return executor().newFailedFuture(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Future<List<T>> resolveAll(SocketAddress address, Promise<List<T>> promise) {
|
||||
checkNotNull(address, "address");
|
||||
checkNotNull(promise, "promise");
|
||||
|
||||
if (!isSupported(address)) {
|
||||
// Address type not supported by the resolver
|
||||
return promise.setFailure(new UnsupportedAddressTypeException());
|
||||
}
|
||||
|
||||
if (isResolved(address)) {
|
||||
// Resolved already; no need to perform a lookup
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
return promise.setSuccess(Collections.singletonList(cast));
|
||||
}
|
||||
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
doResolveAll(cast, promise);
|
||||
return promise;
|
||||
} catch (Exception e) {
|
||||
return promise.setFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by {@link #resolve(SocketAddress)} to perform the actual name
|
||||
* resolution.
|
||||
*/
|
||||
protected abstract void doResolve(T unresolvedAddress, Promise<T> promise) throws Exception;
|
||||
|
||||
/**
|
||||
* Invoked by {@link #resolveAll(SocketAddress)} to perform the actual name
|
||||
* resolution.
|
||||
*/
|
||||
protected abstract void doResolveAll(T unresolvedAddress, Promise<List<T>> promise) throws Exception;
|
||||
|
||||
@Override
|
||||
public void close() { }
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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.netty.resolver;
|
||||
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.Promise;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.UnsupportedAddressTypeException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Resolves a possibility unresolved {@link {@link SocketAddress}}.
|
||||
*/
|
||||
public interface AddressResolver<T extends SocketAddress> extends Closeable {
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if the specified address is supported by this resolved.
|
||||
*/
|
||||
boolean isSupported(SocketAddress address);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if the specified address has been resolved.
|
||||
*
|
||||
* @throws UnsupportedAddressTypeException if the specified address is not supported by this resolver
|
||||
*/
|
||||
boolean isResolved(SocketAddress address);
|
||||
|
||||
/**
|
||||
* Resolves the specified address. If the specified address is resolved already, this method does nothing
|
||||
* but returning the original address.
|
||||
*
|
||||
* @param address the address to resolve
|
||||
*
|
||||
* @return the {@link SocketAddress} as the result of the resolution
|
||||
*/
|
||||
Future<T> resolve(SocketAddress address);
|
||||
|
||||
/**
|
||||
* Resolves the specified address. If the specified address is resolved already, this method does nothing
|
||||
* but returning the original address.
|
||||
*
|
||||
* @param address the address to resolve
|
||||
* @param promise the {@link Promise} which will be fulfilled when the name resolution is finished
|
||||
*
|
||||
* @return the {@link SocketAddress} as the result of the resolution
|
||||
*/
|
||||
Future<T> resolve(SocketAddress address, Promise<T> promise);
|
||||
|
||||
/**
|
||||
* Resolves the specified address. If the specified address is resolved already, this method does nothing
|
||||
* but returning the original address.
|
||||
*
|
||||
* @param address the address to resolve
|
||||
*
|
||||
* @return the list of the {@link SocketAddress}es as the result of the resolution
|
||||
*/
|
||||
Future<List<T>> resolveAll(SocketAddress address);
|
||||
|
||||
/**
|
||||
* Resolves the specified address. If the specified address is resolved already, this method does nothing
|
||||
* but returning the original address.
|
||||
*
|
||||
* @param address the address to resolve
|
||||
* @param promise the {@link Promise} which will be fulfilled when the name resolution is finished
|
||||
*
|
||||
* @return the list of the {@link SocketAddress}es as the result of the resolution
|
||||
*/
|
||||
Future<List<T>> resolveAll(SocketAddress address, Promise<List<T>> promise);
|
||||
|
||||
/**
|
||||
* Closes all the resources allocated and used by this resolver.
|
||||
*/
|
||||
@Override
|
||||
void close();
|
||||
}
|
@ -31,25 +31,25 @@ import java.util.concurrent.ConcurrentMap;
|
||||
/**
|
||||
* Creates and manages {@link NameResolver}s so that each {@link EventExecutor} has its own resolver instance.
|
||||
*/
|
||||
public abstract class NameResolverGroup<T extends SocketAddress> implements Closeable {
|
||||
public abstract class AddressResolverGroup<T extends SocketAddress> implements Closeable {
|
||||
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(NameResolverGroup.class);
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AddressResolverGroup.class);
|
||||
|
||||
/**
|
||||
* Note that we do not use a {@link ConcurrentMap} here because it is usually expensive to instantiate a resolver.
|
||||
*/
|
||||
private final Map<EventExecutor, NameResolver<T>> resolvers =
|
||||
new IdentityHashMap<EventExecutor, NameResolver<T>>();
|
||||
private final Map<EventExecutor, AddressResolver<T>> resolvers =
|
||||
new IdentityHashMap<EventExecutor, AddressResolver<T>>();
|
||||
|
||||
protected NameResolverGroup() { }
|
||||
protected AddressResolverGroup() { }
|
||||
|
||||
/**
|
||||
* Returns the {@link NameResolver} associated with the specified {@link EventExecutor}. If there's no associated
|
||||
* Returns the {@link AddressResolver} associated with the specified {@link EventExecutor}. If there's no associated
|
||||
* resolved found, this method creates and returns a new resolver instance created by
|
||||
* {@link #newResolver(EventExecutor)} so that the new resolver is reused on another
|
||||
* {@link #getResolver(EventExecutor)} call with the same {@link EventExecutor}.
|
||||
*/
|
||||
public NameResolver<T> getResolver(final EventExecutor executor) {
|
||||
public AddressResolver<T> getResolver(final EventExecutor executor) {
|
||||
if (executor == null) {
|
||||
throw new NullPointerException("executor");
|
||||
}
|
||||
@ -58,11 +58,11 @@ public abstract class NameResolverGroup<T extends SocketAddress> implements Clos
|
||||
throw new IllegalStateException("executor not accepting a task");
|
||||
}
|
||||
|
||||
NameResolver<T> r;
|
||||
AddressResolver<T> r;
|
||||
synchronized (resolvers) {
|
||||
r = resolvers.get(executor);
|
||||
if (r == null) {
|
||||
final NameResolver<T> newResolver;
|
||||
final AddressResolver<T> newResolver;
|
||||
try {
|
||||
newResolver = newResolver(executor);
|
||||
} catch (Exception e) {
|
||||
@ -86,9 +86,9 @@ public abstract class NameResolverGroup<T extends SocketAddress> implements Clos
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by {@link #getResolver(EventExecutor)} to create a new {@link NameResolver}.
|
||||
* Invoked by {@link #getResolver(EventExecutor)} to create a new {@link AddressResolver}.
|
||||
*/
|
||||
protected abstract NameResolver<T> newResolver(EventExecutor executor) throws Exception;
|
||||
protected abstract AddressResolver<T> newResolver(EventExecutor executor) throws Exception;
|
||||
|
||||
/**
|
||||
* Closes all {@link NameResolver}s created by this group.
|
||||
@ -96,13 +96,13 @@ public abstract class NameResolverGroup<T extends SocketAddress> implements Clos
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "SuspiciousToArrayCall" })
|
||||
public void close() {
|
||||
final NameResolver<T>[] rArray;
|
||||
final AddressResolver<T>[] rArray;
|
||||
synchronized (resolvers) {
|
||||
rArray = (NameResolver<T>[]) resolvers.values().toArray(new NameResolver[resolvers.size()]);
|
||||
rArray = (AddressResolver<T>[]) resolvers.values().toArray(new AddressResolver[resolvers.size()]);
|
||||
resolvers.clear();
|
||||
}
|
||||
|
||||
for (NameResolver<T> r: rArray) {
|
||||
for (AddressResolver<T> r: rArray) {
|
||||
try {
|
||||
r.close();
|
||||
} catch (Throwable t) {
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 The Netty Project
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
@ -21,16 +21,16 @@ import io.netty.util.concurrent.EventExecutor;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
/**
|
||||
* A {@link NameResolverGroup} of {@link DefaultNameResolver}s.
|
||||
* A {@link AddressResolverGroup} of {@link DefaultNameResolver}s.
|
||||
*/
|
||||
public final class DefaultNameResolverGroup extends NameResolverGroup<InetSocketAddress> {
|
||||
public final class DefaultAddressResolverGroup extends AddressResolverGroup<InetSocketAddress> {
|
||||
|
||||
public static final DefaultNameResolverGroup INSTANCE = new DefaultNameResolverGroup();
|
||||
public static final DefaultAddressResolverGroup INSTANCE = new DefaultAddressResolverGroup();
|
||||
|
||||
private DefaultNameResolverGroup() { }
|
||||
private DefaultAddressResolverGroup() { }
|
||||
|
||||
@Override
|
||||
protected NameResolver<InetSocketAddress> newResolver(EventExecutor executor) throws Exception {
|
||||
return new DefaultNameResolver(executor);
|
||||
protected AddressResolver<InetSocketAddress> newResolver(EventExecutor executor) throws Exception {
|
||||
return new DefaultNameResolver(executor).asAddressResolver();
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 The Netty Project
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
@ -22,49 +22,32 @@ import io.netty.util.concurrent.Promise;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link NameResolver} that resolves an {@link InetSocketAddress} using JDK's built-in domain name lookup mechanism.
|
||||
* A {@link InetNameResolver} that resolves using JDK's built-in domain name lookup mechanism.
|
||||
* Note that this resolver performs a blocking name lookup from the caller thread.
|
||||
*/
|
||||
public class DefaultNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
public class DefaultNameResolver extends InetNameResolver {
|
||||
|
||||
public DefaultNameResolver(EventExecutor executor) {
|
||||
super(executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doIsResolved(InetSocketAddress address) {
|
||||
return !address.isUnresolved();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doResolve(InetSocketAddress unresolvedAddress, Promise<InetSocketAddress> promise) throws Exception {
|
||||
protected void doResolve(String inetHost, Promise<InetAddress> promise) throws Exception {
|
||||
try {
|
||||
// Note that InetSocketAddress.getHostName() will never incur a reverse lookup here,
|
||||
// because an unresolved address always has a host name.
|
||||
promise.setSuccess(new InetSocketAddress(
|
||||
InetAddress.getByName(unresolvedAddress.getHostName()), unresolvedAddress.getPort()));
|
||||
promise.setSuccess(InetAddress.getByName(inetHost));
|
||||
} catch (UnknownHostException e) {
|
||||
promise.setFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doResolveAll(
|
||||
InetSocketAddress unresolvedAddress, Promise<List<InetSocketAddress>> promise) throws Exception {
|
||||
|
||||
protected void doResolveAll(String inetHost, Promise<List<InetAddress>> promise) throws Exception {
|
||||
try {
|
||||
// Note that InetSocketAddress.getHostName() will never incur a reverse lookup here,
|
||||
// because an unresolved address always has a host name.
|
||||
final InetAddress[] resolved = InetAddress.getAllByName(unresolvedAddress.getHostName());
|
||||
final List<InetSocketAddress> result = new ArrayList<InetSocketAddress>(resolved.length);
|
||||
for (InetAddress a: resolved) {
|
||||
result.add(new InetSocketAddress(a, unresolvedAddress.getPort()));
|
||||
}
|
||||
promise.setSuccess(result);
|
||||
promise.setSuccess(Arrays.asList(InetAddress.getAllByName(inetHost)));
|
||||
} catch (UnknownHostException e) {
|
||||
promise.setFailure(e);
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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.netty.resolver;
|
||||
|
||||
import io.netty.util.concurrent.EventExecutor;
|
||||
import io.netty.util.concurrent.Future;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
/**
|
||||
* A skeletal {@link NameResolver} implementation that resolves {@link InetAddress}.
|
||||
*/
|
||||
public abstract class InetNameResolver extends SimpleNameResolver<InetAddress> {
|
||||
|
||||
private volatile AddressResolver<InetSocketAddress> addressResolver;
|
||||
|
||||
/**
|
||||
* @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned
|
||||
* by {@link #resolve(String)}
|
||||
*/
|
||||
protected InetNameResolver(EventExecutor executor) {
|
||||
super(executor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link AddressResolver} that will use this name resolver underneath.
|
||||
*/
|
||||
public AddressResolver<InetSocketAddress> asAddressResolver() {
|
||||
AddressResolver<InetSocketAddress> result = addressResolver;
|
||||
if (result == null) {
|
||||
synchronized (this) {
|
||||
result = addressResolver;
|
||||
if (result == null) {
|
||||
addressResolver = result = new InetSocketAddressResolver(executor(), this);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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.netty.resolver;
|
||||
|
||||
import io.netty.util.concurrent.EventExecutor;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import io.netty.util.concurrent.Promise;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link AbstractAddressResolver} that resolves {@link InetAddress}.
|
||||
*/
|
||||
public class InetSocketAddressResolver extends AbstractAddressResolver<InetSocketAddress> {
|
||||
|
||||
private final NameResolver<InetAddress> nameResolver;
|
||||
|
||||
/**
|
||||
* @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned
|
||||
* by {@link #resolve(java.net.SocketAddress)}
|
||||
* @param nameResolver the {@link NameResolver} used for name resolution
|
||||
*/
|
||||
public InetSocketAddressResolver(EventExecutor executor, NameResolver<InetAddress> nameResolver) {
|
||||
super(executor, InetSocketAddress.class);
|
||||
this.nameResolver = nameResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doIsResolved(InetSocketAddress address) {
|
||||
return !address.isUnresolved();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doResolve(final InetSocketAddress unresolvedAddress, final Promise<InetSocketAddress> promise)
|
||||
throws Exception {
|
||||
// Note that InetSocketAddress.getHostName() will never incur a reverse lookup here,
|
||||
// because an unresolved address always has a host name.
|
||||
nameResolver.resolve(unresolvedAddress.getHostName())
|
||||
.addListener(new GenericFutureListener<Future<InetAddress>>() {
|
||||
@Override
|
||||
public void operationComplete(Future<InetAddress> future) throws Exception {
|
||||
if (future.isSuccess()) {
|
||||
promise.setSuccess(new InetSocketAddress(future.getNow(), unresolvedAddress.getPort()));
|
||||
} else {
|
||||
promise.setFailure(future.cause());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doResolveAll(final InetSocketAddress unresolvedAddress,
|
||||
final Promise<List<InetSocketAddress>> promise) throws Exception {
|
||||
// Note that InetSocketAddress.getHostName() will never incur a reverse lookup here,
|
||||
// because an unresolved address always has a host name.
|
||||
nameResolver.resolveAll(unresolvedAddress.getHostName())
|
||||
.addListener(new GenericFutureListener<Future<List<InetAddress>>>() {
|
||||
@Override
|
||||
public void operationComplete(Future<List<InetAddress>> future) throws Exception {
|
||||
if (future.isSuccess()) {
|
||||
List<InetAddress> inetAddresses = future.getNow();
|
||||
List<InetSocketAddress> socketAddresses =
|
||||
new ArrayList<InetSocketAddress>(inetAddresses.size());
|
||||
for (InetAddress inetAddress : inetAddresses) {
|
||||
socketAddresses.add(new InetSocketAddress(inetAddress, unresolvedAddress.getPort()));
|
||||
}
|
||||
promise.setSuccess(socketAddresses);
|
||||
} else {
|
||||
promise.setFailure(future.cause());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -20,110 +20,50 @@ import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.Promise;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.UnsupportedAddressTypeException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Resolves an arbitrary string that represents the name of an endpoint into a {@link SocketAddress}.
|
||||
* Resolves an arbitrary string that represents the name of an endpoint into an address.
|
||||
*/
|
||||
public interface NameResolver<T extends SocketAddress> extends Closeable {
|
||||
public interface NameResolver<T> extends Closeable {
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if the specified address is supported by this resolved.
|
||||
*/
|
||||
boolean isSupported(SocketAddress address);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if the specified address has been resolved.
|
||||
*
|
||||
* @throws UnsupportedAddressTypeException if the specified address is not supported by this resolver
|
||||
*/
|
||||
boolean isResolved(SocketAddress address);
|
||||
|
||||
/**
|
||||
* Resolves the specified name into a {@link SocketAddress}.
|
||||
* Resolves the specified name into an address.
|
||||
*
|
||||
* @param inetHost the name to resolve
|
||||
* @param inetPort the port number
|
||||
*
|
||||
* @return the {@link SocketAddress} as the result of the resolution
|
||||
* @return the address as the result of the resolution
|
||||
*/
|
||||
Future<T> resolve(String inetHost, int inetPort);
|
||||
Future<T> resolve(String inetHost);
|
||||
|
||||
/**
|
||||
* Resolves the specified name into a {@link SocketAddress}.
|
||||
* Resolves the specified name into an address.
|
||||
*
|
||||
* @param inetHost the name to resolve
|
||||
* @param inetPort the port number
|
||||
* @param promise the {@link Promise} which will be fulfilled when the name resolution is finished
|
||||
*
|
||||
* @return the {@link SocketAddress} as the result of the resolution
|
||||
* @return the address as the result of the resolution
|
||||
*/
|
||||
Future<T> resolve(String inetHost, int inetPort, Promise<T> promise);
|
||||
Future<T> resolve(String inetHost, Promise<T> promise);
|
||||
|
||||
/**
|
||||
* Resolves the specified address. If the specified address is resolved already, this method does nothing
|
||||
* but returning the original address.
|
||||
*
|
||||
* @param address the address to resolve
|
||||
*
|
||||
* @return the {@link SocketAddress} as the result of the resolution
|
||||
*/
|
||||
Future<T> resolve(SocketAddress address);
|
||||
|
||||
/**
|
||||
* Resolves the specified address. If the specified address is resolved already, this method does nothing
|
||||
* but returning the original address.
|
||||
*
|
||||
* @param address the address to resolve
|
||||
* @param promise the {@link Promise} which will be fulfilled when the name resolution is finished
|
||||
*
|
||||
* @return the {@link SocketAddress} as the result of the resolution
|
||||
*/
|
||||
Future<T> resolve(SocketAddress address, Promise<T> promise);
|
||||
|
||||
/**
|
||||
* Resolves the specified host name and port into a list of {@link SocketAddress}es.
|
||||
* Resolves the specified host name and port into a list of address.
|
||||
*
|
||||
* @param inetHost the name to resolve
|
||||
* @param inetPort the port number
|
||||
*
|
||||
* @return the list of the {@link SocketAddress}es as the result of the resolution
|
||||
* @return the list of the address as the result of the resolution
|
||||
*/
|
||||
Future<List<T>> resolveAll(String inetHost, int inetPort);
|
||||
Future<List<T>> resolveAll(String inetHost);
|
||||
|
||||
/**
|
||||
* Resolves the specified host name and port into a list of {@link SocketAddress}es.
|
||||
* Resolves the specified host name and port into a list of address.
|
||||
*
|
||||
* @param inetHost the name to resolve
|
||||
* @param inetPort the port number
|
||||
* @param promise the {@link Promise} which will be fulfilled when the name resolution is finished
|
||||
*
|
||||
* @return the list of the {@link SocketAddress}es as the result of the resolution
|
||||
* @return the list of the address as the result of the resolution
|
||||
*/
|
||||
Future<List<T>> resolveAll(String inetHost, int inetPort, Promise<List<T>> promise);
|
||||
|
||||
/**
|
||||
* Resolves the specified address. If the specified address is resolved already, this method does nothing
|
||||
* but returning the original address.
|
||||
*
|
||||
* @param address the address to resolve
|
||||
*
|
||||
* @return the list of the {@link SocketAddress}es as the result of the resolution
|
||||
*/
|
||||
Future<List<T>> resolveAll(SocketAddress address);
|
||||
|
||||
/**
|
||||
* Resolves the specified address. If the specified address is resolved already, this method does nothing
|
||||
* but returning the original address.
|
||||
*
|
||||
* @param address the address to resolve
|
||||
* @param promise the {@link Promise} which will be fulfilled when the name resolution is finished
|
||||
*
|
||||
* @return the list of the {@link SocketAddress}es as the result of the resolution
|
||||
*/
|
||||
Future<List<T>> resolveAll(SocketAddress address, Promise<List<T>> promise);
|
||||
Future<List<T>> resolveAll(String inetHost, Promise<List<T>> promise);
|
||||
|
||||
/**
|
||||
* Closes all the resources allocated and used by this resolver.
|
||||
|
@ -24,12 +24,12 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link NameResolver} that does not perform any resolution but always reports successful resolution.
|
||||
* A {@link AddressResolver} that does not perform any resolution but always reports successful resolution.
|
||||
* This resolver is useful when name resolution is performed by a handler in a pipeline, such as a proxy handler.
|
||||
*/
|
||||
public class NoopNameResolver extends SimpleNameResolver<SocketAddress> {
|
||||
public class NoopAddressResolver extends AbstractAddressResolver<SocketAddress> {
|
||||
|
||||
public NoopNameResolver(EventExecutor executor) {
|
||||
public NoopAddressResolver(EventExecutor executor) {
|
||||
super(executor);
|
||||
}
|
||||
|
@ -21,16 +21,16 @@ import io.netty.util.concurrent.EventExecutor;
|
||||
import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
* A {@link NameResolverGroup} of {@link NoopNameResolver}s.
|
||||
* A {@link AddressResolverGroup} of {@link NoopAddressResolver}s.
|
||||
*/
|
||||
public final class NoopNameResolverGroup extends NameResolverGroup<SocketAddress> {
|
||||
public final class NoopAddressResolverGroup extends AddressResolverGroup<SocketAddress> {
|
||||
|
||||
public static final NoopNameResolverGroup INSTANCE = new NoopNameResolverGroup();
|
||||
public static final NoopAddressResolverGroup INSTANCE = new NoopAddressResolverGroup();
|
||||
|
||||
private NoopNameResolverGroup() { }
|
||||
private NoopAddressResolverGroup() { }
|
||||
|
||||
@Override
|
||||
protected NameResolver<SocketAddress> newResolver(EventExecutor executor) throws Exception {
|
||||
return new NoopNameResolver(executor);
|
||||
protected AddressResolver<SocketAddress> newResolver(EventExecutor executor) throws Exception {
|
||||
return new NoopAddressResolver(executor);
|
||||
}
|
||||
}
|
@ -19,12 +19,7 @@ package io.netty.resolver;
|
||||
import io.netty.util.concurrent.EventExecutor;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.Promise;
|
||||
import io.netty.util.internal.TypeParameterMatcher;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.UnsupportedAddressTypeException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static io.netty.util.internal.ObjectUtil.*;
|
||||
@ -32,124 +27,39 @@ import static io.netty.util.internal.ObjectUtil.*;
|
||||
/**
|
||||
* A skeletal {@link NameResolver} implementation.
|
||||
*/
|
||||
public abstract class SimpleNameResolver<T extends SocketAddress> implements NameResolver<T> {
|
||||
public abstract class SimpleNameResolver<T> implements NameResolver<T> {
|
||||
|
||||
private final EventExecutor executor;
|
||||
private final TypeParameterMatcher matcher;
|
||||
|
||||
/**
|
||||
* @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned
|
||||
* by {@link #resolve(SocketAddress)}
|
||||
* by {@link #resolve(String)}
|
||||
*/
|
||||
protected SimpleNameResolver(EventExecutor executor) {
|
||||
if (executor == null) {
|
||||
throw new NullPointerException("executor");
|
||||
}
|
||||
|
||||
this.executor = executor;
|
||||
matcher = TypeParameterMatcher.find(this, SimpleNameResolver.class, "T");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned
|
||||
* by {@link #resolve(SocketAddress)}
|
||||
* @param addressType the type of the {@link SocketAddress} supported by this resolver
|
||||
*/
|
||||
protected SimpleNameResolver(EventExecutor executor, Class<? extends T> addressType) {
|
||||
if (executor == null) {
|
||||
throw new NullPointerException("executor");
|
||||
}
|
||||
|
||||
this.executor = executor;
|
||||
matcher = TypeParameterMatcher.get(addressType);
|
||||
this.executor = checkNotNull(executor, "executor");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned
|
||||
* by {@link #resolve(SocketAddress)}.
|
||||
* by {@link #resolve(String)}.
|
||||
*/
|
||||
protected EventExecutor executor() {
|
||||
return executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported(SocketAddress address) {
|
||||
return matcher.match(address);
|
||||
public final Future<T> resolve(String inetHost) {
|
||||
final Promise<T> promise = executor().newPromise();
|
||||
return resolve(inetHost, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isResolved(SocketAddress address) {
|
||||
if (!isSupported(address)) {
|
||||
throw new UnsupportedAddressTypeException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final T castAddress = (T) address;
|
||||
return doIsResolved(castAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by {@link #isResolved(SocketAddress)} to check if the specified {@code address} has been resolved
|
||||
* already.
|
||||
*/
|
||||
protected abstract boolean doIsResolved(T address);
|
||||
|
||||
@Override
|
||||
public final Future<T> resolve(String inetHost, int inetPort) {
|
||||
return resolve(InetSocketAddress.createUnresolved(checkNotNull(inetHost, "inetHost"), inetPort));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<T> resolve(String inetHost, int inetPort, Promise<T> promise) {
|
||||
return resolve(InetSocketAddress.createUnresolved(checkNotNull(inetHost, "inetHost"), inetPort), promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Future<T> resolve(SocketAddress address) {
|
||||
if (!isSupported(checkNotNull(address, "address"))) {
|
||||
// Address type not supported by the resolver
|
||||
return executor().newFailedFuture(new UnsupportedAddressTypeException());
|
||||
}
|
||||
|
||||
if (isResolved(address)) {
|
||||
// Resolved already; no need to perform a lookup
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
return executor.newSucceededFuture(cast);
|
||||
}
|
||||
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
final Promise<T> promise = executor().newPromise();
|
||||
doResolve(cast, promise);
|
||||
return promise;
|
||||
} catch (Exception e) {
|
||||
return executor().newFailedFuture(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Future<T> resolve(SocketAddress address, Promise<T> promise) {
|
||||
checkNotNull(address, "address");
|
||||
public Future<T> resolve(String inetHost, Promise<T> promise) {
|
||||
checkNotNull(inetHost, "inetHost");
|
||||
checkNotNull(promise, "promise");
|
||||
|
||||
if (!isSupported(address)) {
|
||||
// Address type not supported by the resolver
|
||||
return promise.setFailure(new UnsupportedAddressTypeException());
|
||||
}
|
||||
|
||||
if (isResolved(address)) {
|
||||
// Resolved already; no need to perform a lookup
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
return promise.setSuccess(cast);
|
||||
}
|
||||
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
doResolve(cast, promise);
|
||||
doResolve(inetHost, promise);
|
||||
return promise;
|
||||
} catch (Exception e) {
|
||||
return promise.setFailure(e);
|
||||
@ -157,61 +67,18 @@ public abstract class SimpleNameResolver<T extends SocketAddress> implements Nam
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Future<List<T>> resolveAll(String inetHost, int inetPort) {
|
||||
return resolveAll(InetSocketAddress.createUnresolved(checkNotNull(inetHost, "inetHost"), inetPort));
|
||||
public final Future<List<T>> resolveAll(String inetHost) {
|
||||
final Promise<List<T>> promise = executor().newPromise();
|
||||
return resolveAll(inetHost, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<List<T>> resolveAll(String inetHost, int inetPort, Promise<List<T>> promise) {
|
||||
return resolveAll(InetSocketAddress.createUnresolved(checkNotNull(inetHost, "inetHost"), inetPort), promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Future<List<T>> resolveAll(SocketAddress address) {
|
||||
if (!isSupported(checkNotNull(address, "address"))) {
|
||||
// Address type not supported by the resolver
|
||||
return executor().newFailedFuture(new UnsupportedAddressTypeException());
|
||||
}
|
||||
|
||||
if (isResolved(address)) {
|
||||
// Resolved already; no need to perform a lookup
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
return executor.newSucceededFuture(Collections.singletonList(cast));
|
||||
}
|
||||
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
final Promise<List<T>> promise = executor().newPromise();
|
||||
doResolveAll(cast, promise);
|
||||
return promise;
|
||||
} catch (Exception e) {
|
||||
return executor().newFailedFuture(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Future<List<T>> resolveAll(SocketAddress address, Promise<List<T>> promise) {
|
||||
checkNotNull(address, "address");
|
||||
public Future<List<T>> resolveAll(String inetHost, Promise<List<T>> promise) {
|
||||
checkNotNull(inetHost, "inetHost");
|
||||
checkNotNull(promise, "promise");
|
||||
|
||||
if (!isSupported(address)) {
|
||||
// Address type not supported by the resolver
|
||||
return promise.setFailure(new UnsupportedAddressTypeException());
|
||||
}
|
||||
|
||||
if (isResolved(address)) {
|
||||
// Resolved already; no need to perform a lookup
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
return promise.setSuccess(Collections.singletonList(cast));
|
||||
}
|
||||
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
final T cast = (T) address;
|
||||
doResolveAll(cast, promise);
|
||||
doResolveAll(inetHost, promise);
|
||||
return promise;
|
||||
} catch (Exception e) {
|
||||
return promise.setFailure(e);
|
||||
@ -219,16 +86,14 @@ public abstract class SimpleNameResolver<T extends SocketAddress> implements Nam
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by {@link #resolve(SocketAddress)} and {@link #resolve(String, int)} to perform the actual name
|
||||
* resolution.
|
||||
* Invoked by {@link #resolve(String)} to perform the actual name resolution.
|
||||
*/
|
||||
protected abstract void doResolve(T unresolvedAddress, Promise<T> promise) throws Exception;
|
||||
protected abstract void doResolve(String inetHost, Promise<T> promise) throws Exception;
|
||||
|
||||
/**
|
||||
* Invoked by {@link #resolveAll(SocketAddress)} and {@link #resolveAll(String, int)} to perform the actual name
|
||||
* resolution.
|
||||
* Invoked by {@link #resolveAll(String)} to perform the actual name resolution.
|
||||
*/
|
||||
protected abstract void doResolveAll(T unresolvedAddress, Promise<List<T>> promise) throws Exception;
|
||||
protected abstract void doResolveAll(String inetHost, Promise<List<T>> promise) throws Exception;
|
||||
|
||||
@Override
|
||||
public void close() { }
|
||||
|
@ -15,6 +15,6 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves an arbitrary string that represents the name of an endpoint into a {@link java.net.SocketAddress}.
|
||||
* Resolves an arbitrary string that represents the name of an endpoint into an address.
|
||||
*/
|
||||
package io.netty.resolver;
|
||||
|
@ -23,9 +23,10 @@ import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.EventLoop;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.resolver.DefaultNameResolverGroup;
|
||||
import io.netty.resolver.AddressResolver;
|
||||
import io.netty.resolver.DefaultAddressResolverGroup;
|
||||
import io.netty.resolver.NameResolver;
|
||||
import io.netty.resolver.NameResolverGroup;
|
||||
import io.netty.resolver.AddressResolverGroup;
|
||||
import io.netty.util.AttributeKey;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.FutureListener;
|
||||
@ -50,10 +51,11 @@ public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {
|
||||
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(Bootstrap.class);
|
||||
|
||||
private static final NameResolverGroup<?> DEFAULT_RESOLVER = DefaultNameResolverGroup.INSTANCE;
|
||||
private static final AddressResolverGroup<?> DEFAULT_RESOLVER = DefaultAddressResolverGroup.INSTANCE;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private volatile NameResolverGroup<SocketAddress> resolver = (NameResolverGroup<SocketAddress>) DEFAULT_RESOLVER;
|
||||
private volatile AddressResolverGroup<SocketAddress> resolver =
|
||||
(AddressResolverGroup<SocketAddress>) DEFAULT_RESOLVER;
|
||||
private volatile SocketAddress remoteAddress;
|
||||
|
||||
public Bootstrap() { }
|
||||
@ -68,11 +70,11 @@ public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {
|
||||
* Sets the {@link NameResolver} which will resolve the address of the unresolved named address.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Bootstrap resolver(NameResolverGroup<?> resolver) {
|
||||
public Bootstrap resolver(AddressResolverGroup<?> resolver) {
|
||||
if (resolver == null) {
|
||||
throw new NullPointerException("resolver");
|
||||
}
|
||||
this.resolver = (NameResolverGroup<SocketAddress>) resolver;
|
||||
this.resolver = (AddressResolverGroup<SocketAddress>) resolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -162,7 +164,7 @@ public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {
|
||||
|
||||
final Channel channel = regFuture.channel();
|
||||
final EventLoop eventLoop = channel.eventLoop();
|
||||
final NameResolver<SocketAddress> resolver = this.resolver.getResolver(eventLoop);
|
||||
final AddressResolver<SocketAddress> resolver = this.resolver.getResolver(eventLoop);
|
||||
|
||||
if (!resolver.isSupported(remoteAddress) || resolver.isResolved(remoteAddress)) {
|
||||
// Resolver has no idea about what to do with the specified remote address or it's resolved already.
|
||||
|
@ -30,9 +30,9 @@ import io.netty.channel.ServerChannel;
|
||||
import io.netty.channel.local.LocalAddress;
|
||||
import io.netty.channel.local.LocalChannel;
|
||||
import io.netty.channel.local.LocalServerChannel;
|
||||
import io.netty.resolver.NameResolver;
|
||||
import io.netty.resolver.NameResolverGroup;
|
||||
import io.netty.resolver.SimpleNameResolver;
|
||||
import io.netty.resolver.AddressResolver;
|
||||
import io.netty.resolver.AddressResolverGroup;
|
||||
import io.netty.resolver.AbstractAddressResolver;
|
||||
import io.netty.util.concurrent.EventExecutor;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.Promise;
|
||||
@ -223,7 +223,7 @@ public class BootstrapTest {
|
||||
final Bootstrap bootstrapA = new Bootstrap();
|
||||
bootstrapA.group(groupA);
|
||||
bootstrapA.channel(LocalChannel.class);
|
||||
bootstrapA.resolver(new TestNameResolverGroup(true));
|
||||
bootstrapA.resolver(new TestAddressResolverGroup(true));
|
||||
bootstrapA.handler(dummyHandler);
|
||||
|
||||
final ServerBootstrap bootstrapB = new ServerBootstrap();
|
||||
@ -242,7 +242,7 @@ public class BootstrapTest {
|
||||
final Bootstrap bootstrapA = new Bootstrap();
|
||||
bootstrapA.group(groupA);
|
||||
bootstrapA.channel(LocalChannel.class);
|
||||
bootstrapA.resolver(new TestNameResolverGroup(false));
|
||||
bootstrapA.resolver(new TestAddressResolverGroup(false));
|
||||
bootstrapA.handler(dummyHandler);
|
||||
|
||||
final ServerBootstrap bootstrapB = new ServerBootstrap();
|
||||
@ -284,17 +284,17 @@ public class BootstrapTest {
|
||||
@Sharable
|
||||
private static final class DummyHandler extends ChannelInboundHandlerAdapter { }
|
||||
|
||||
private static final class TestNameResolverGroup extends NameResolverGroup<SocketAddress> {
|
||||
private static final class TestAddressResolverGroup extends AddressResolverGroup<SocketAddress> {
|
||||
|
||||
private final boolean success;
|
||||
|
||||
TestNameResolverGroup(boolean success) {
|
||||
TestAddressResolverGroup(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NameResolver<SocketAddress> newResolver(EventExecutor executor) throws Exception {
|
||||
return new SimpleNameResolver<SocketAddress>(executor) {
|
||||
protected AddressResolver<SocketAddress> newResolver(EventExecutor executor) throws Exception {
|
||||
return new AbstractAddressResolver<SocketAddress>(executor) {
|
||||
|
||||
@Override
|
||||
protected boolean doIsResolved(SocketAddress address) {
|
||||
|
Loading…
Reference in New Issue
Block a user