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
3e7bd25589
commit
541fe86fe0
|
@ -36,7 +36,7 @@ import io.netty.handler.codec.LineBasedFrameDecoder;
|
||||||
import io.netty.handler.ssl.SslContext;
|
import io.netty.handler.ssl.SslContext;
|
||||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
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.CharsetUtil;
|
||||||
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
|
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
|
||||||
import io.netty.util.concurrent.Future;
|
import io.netty.util.concurrent.Future;
|
||||||
|
@ -523,7 +523,7 @@ public class ProxyHandlerTest {
|
||||||
Bootstrap b = new Bootstrap();
|
Bootstrap b = new Bootstrap();
|
||||||
b.group(group);
|
b.group(group);
|
||||||
b.channel(NioSocketChannel.class);
|
b.channel(NioSocketChannel.class);
|
||||||
b.resolver(NoopNameResolverGroup.INSTANCE);
|
b.resolver(NoopAddressResolverGroup.INSTANCE);
|
||||||
b.handler(new ChannelInitializer<SocketChannel>() {
|
b.handler(new ChannelInitializer<SocketChannel>() {
|
||||||
@Override
|
@Override
|
||||||
protected void initChannel(SocketChannel ch) throws Exception {
|
protected void initChannel(SocketChannel ch) throws Exception {
|
||||||
|
@ -571,7 +571,7 @@ public class ProxyHandlerTest {
|
||||||
Bootstrap b = new Bootstrap();
|
Bootstrap b = new Bootstrap();
|
||||||
b.group(group);
|
b.group(group);
|
||||||
b.channel(NioSocketChannel.class);
|
b.channel(NioSocketChannel.class);
|
||||||
b.resolver(NoopNameResolverGroup.INSTANCE);
|
b.resolver(NoopAddressResolverGroup.INSTANCE);
|
||||||
b.handler(new ChannelInitializer<SocketChannel>() {
|
b.handler(new ChannelInitializer<SocketChannel>() {
|
||||||
@Override
|
@Override
|
||||||
protected void initChannel(SocketChannel ch) throws Exception {
|
protected void initChannel(SocketChannel ch) throws Exception {
|
||||||
|
@ -616,7 +616,7 @@ public class ProxyHandlerTest {
|
||||||
Bootstrap b = new Bootstrap();
|
Bootstrap b = new Bootstrap();
|
||||||
b.group(group);
|
b.group(group);
|
||||||
b.channel(NioSocketChannel.class);
|
b.channel(NioSocketChannel.class);
|
||||||
b.resolver(NoopNameResolverGroup.INSTANCE);
|
b.resolver(NoopAddressResolverGroup.INSTANCE);
|
||||||
b.handler(new ChannelInitializer<SocketChannel>() {
|
b.handler(new ChannelInitializer<SocketChannel>() {
|
||||||
@Override
|
@Override
|
||||||
protected void initChannel(SocketChannel ch) throws Exception {
|
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.EventLoop;
|
||||||
import io.netty.channel.ReflectiveChannelFactory;
|
import io.netty.channel.ReflectiveChannelFactory;
|
||||||
import io.netty.channel.socket.DatagramChannel;
|
import io.netty.channel.socket.DatagramChannel;
|
||||||
import io.netty.resolver.NameResolver;
|
import io.netty.resolver.AddressResolver;
|
||||||
import io.netty.resolver.NameResolverGroup;
|
import io.netty.resolver.AddressResolverGroup;
|
||||||
import io.netty.util.concurrent.EventExecutor;
|
import io.netty.util.concurrent.EventExecutor;
|
||||||
import io.netty.util.internal.StringUtil;
|
import io.netty.util.internal.StringUtil;
|
||||||
|
|
||||||
|
@ -30,31 +30,31 @@ import java.net.InetSocketAddress;
|
||||||
import static io.netty.resolver.dns.DnsNameResolver.ANY_LOCAL_ADDR;
|
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 ChannelFactory<? extends DatagramChannel> channelFactory;
|
||||||
private final InetSocketAddress localAddress;
|
private final InetSocketAddress localAddress;
|
||||||
private final DnsServerAddresses nameServerAddresses;
|
private final DnsServerAddresses nameServerAddresses;
|
||||||
|
|
||||||
public DnsNameResolverGroup(
|
public DnsAddressResolverGroup(
|
||||||
Class<? extends DatagramChannel> channelType, DnsServerAddresses nameServerAddresses) {
|
Class<? extends DatagramChannel> channelType, DnsServerAddresses nameServerAddresses) {
|
||||||
this(channelType, ANY_LOCAL_ADDR, nameServerAddresses);
|
this(channelType, ANY_LOCAL_ADDR, nameServerAddresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DnsNameResolverGroup(
|
public DnsAddressResolverGroup(
|
||||||
Class<? extends DatagramChannel> channelType,
|
Class<? extends DatagramChannel> channelType,
|
||||||
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
|
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
|
||||||
this(new ReflectiveChannelFactory<DatagramChannel>(channelType), localAddress, nameServerAddresses);
|
this(new ReflectiveChannelFactory<DatagramChannel>(channelType), localAddress, nameServerAddresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DnsNameResolverGroup(
|
public DnsAddressResolverGroup(
|
||||||
ChannelFactory<? extends DatagramChannel> channelFactory, DnsServerAddresses nameServerAddresses) {
|
ChannelFactory<? extends DatagramChannel> channelFactory, DnsServerAddresses nameServerAddresses) {
|
||||||
this(channelFactory, ANY_LOCAL_ADDR, nameServerAddresses);
|
this(channelFactory, ANY_LOCAL_ADDR, nameServerAddresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DnsNameResolverGroup(
|
public DnsAddressResolverGroup(
|
||||||
ChannelFactory<? extends DatagramChannel> channelFactory,
|
ChannelFactory<? extends DatagramChannel> channelFactory,
|
||||||
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
|
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
|
||||||
this.channelFactory = channelFactory;
|
this.channelFactory = channelFactory;
|
||||||
|
@ -63,7 +63,7 @@ public class DnsNameResolverGroup extends NameResolverGroup<InetSocketAddress> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final NameResolver<InetSocketAddress> newResolver(EventExecutor executor) throws Exception {
|
protected final AddressResolver<InetSocketAddress> newResolver(EventExecutor executor) throws Exception {
|
||||||
if (!(executor instanceof EventLoop)) {
|
if (!(executor instanceof EventLoop)) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"unsupported executor type: " + StringUtil.simpleClassName(executor) +
|
"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}
|
* Creates a new {@link DnsNameResolver}. Override this method to create an alternative {@link DnsNameResolver}
|
||||||
* implementation or override the default configuration.
|
* implementation or override the default configuration.
|
||||||
*/
|
*/
|
||||||
protected DnsNameResolver newResolver(
|
protected AddressResolver<InetSocketAddress> newResolver(
|
||||||
EventLoop eventLoop, ChannelFactory<? extends DatagramChannel> channelFactory,
|
EventLoop eventLoop, ChannelFactory<? extends DatagramChannel> channelFactory,
|
||||||
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) throws Exception {
|
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) throws Exception {
|
||||||
|
|
||||||
return new DnsNameResolver(
|
return new DnsNameResolver(eventLoop, channelFactory, localAddress, nameServerAddresses)
|
||||||
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.DatagramDnsResponseDecoder;
|
||||||
import io.netty.handler.codec.dns.DnsQuestion;
|
import io.netty.handler.codec.dns.DnsQuestion;
|
||||||
import io.netty.handler.codec.dns.DnsResponse;
|
import io.netty.handler.codec.dns.DnsResponse;
|
||||||
import io.netty.resolver.NameResolver;
|
import io.netty.resolver.InetNameResolver;
|
||||||
import io.netty.resolver.SimpleNameResolver;
|
|
||||||
import io.netty.util.NetUtil;
|
import io.netty.util.NetUtil;
|
||||||
import io.netty.util.ReferenceCountUtil;
|
import io.netty.util.ReferenceCountUtil;
|
||||||
import io.netty.util.concurrent.FastThreadLocal;
|
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.concurrent.Promise;
|
||||||
import io.netty.util.internal.OneTimeTask;
|
import io.netty.util.internal.OneTimeTask;
|
||||||
import io.netty.util.internal.PlatformDependent;
|
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.InternalLogger;
|
||||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||||
|
|
||||||
import java.net.IDN;
|
import java.net.IDN;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -62,9 +59,9 @@ import java.util.concurrent.TimeUnit;
|
||||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
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);
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(DnsNameResolver.class);
|
||||||
|
|
||||||
|
@ -74,7 +71,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// Note that we did not use SystemPropertyUtil.getBoolean() here to emulate the behavior of JDK.
|
// 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[0] = InternetProtocolFamily.IPv6;
|
||||||
DEFAULT_RESOLVE_ADDRESS_TYPES[1] = InternetProtocolFamily.IPv4;
|
DEFAULT_RESOLVE_ADDRESS_TYPES[1] = InternetProtocolFamily.IPv4;
|
||||||
logger.debug("-Djava.net.preferIPv6Addresses: true");
|
logger.debug("-Djava.net.preferIPv6Addresses: true");
|
||||||
|
@ -98,7 +95,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||||
final DnsQueryContextManager queryContextManager = new DnsQueryContextManager();
|
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();
|
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.
|
* in the order of preference.
|
||||||
* The default value depends on the value of the system property {@code "java.net.preferIPv6Addresses"}.
|
* 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
|
* 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
|
* order of preference. To enforce the resolve to retrieve the address of a specific protocol family, specify
|
||||||
* only a single {@link InternetProtocolFamily}.
|
* 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
|
* 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
|
* order of preference. To enforce the resolve to retrieve the address of a specific protocol family, specify
|
||||||
* only a single {@link InternetProtocolFamily}.
|
* only a single {@link InternetProtocolFamily}.
|
||||||
|
@ -594,28 +591,22 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean doIsResolved(InetSocketAddress address) {
|
protected void doResolve(String inetHost, Promise<InetAddress> promise) throws Exception {
|
||||||
return !address.isUnresolved();
|
final byte[] bytes = NetUtil.createByteArrayFromIpAddressString(inetHost);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doResolve(InetSocketAddress unresolvedAddress, Promise<InetSocketAddress> promise) throws Exception {
|
|
||||||
final byte[] bytes = NetUtil.createByteArrayFromIpAddressString(unresolvedAddress.getHostName());
|
|
||||||
if (bytes != null) {
|
if (bytes != null) {
|
||||||
// The unresolvedAddress was created via a String that contains an ipaddress.
|
// The inetHost is actually an ipaddress.
|
||||||
promise.setSuccess(new InetSocketAddress(InetAddress.getByAddress(bytes), unresolvedAddress.getPort()));
|
promise.setSuccess(InetAddress.getByAddress(bytes));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String hostname = hostname(unresolvedAddress);
|
final String hostname = hostname(inetHost);
|
||||||
final int port = unresolvedAddress.getPort();
|
|
||||||
|
|
||||||
if (!doResolveCached(hostname, port, promise)) {
|
if (!doResolveCached(hostname, promise)) {
|
||||||
doResolveUncached(hostname, port, 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);
|
final List<DnsCacheEntry> cachedEntries = resolveCache.get(hostname);
|
||||||
if (cachedEntries == null) {
|
if (cachedEntries == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -644,7 +635,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address != null) {
|
if (address != null) {
|
||||||
setSuccess(promise, new InetSocketAddress(address, port));
|
setSuccess(promise, address);
|
||||||
} else if (cause != null) {
|
} else if (cause != null) {
|
||||||
if (!promise.tryFailure(cause)) {
|
if (!promise.tryFailure(cause)) {
|
||||||
logger.warn("Failed to notify failure to a promise: {}", promise, cause);
|
logger.warn("Failed to notify failure to a promise: {}", promise, cause);
|
||||||
|
@ -656,15 +647,15 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setSuccess(Promise<InetSocketAddress> promise, InetSocketAddress result) {
|
private static void setSuccess(Promise<InetAddress> promise, InetAddress result) {
|
||||||
if (!promise.trySuccess(result)) {
|
if (!promise.trySuccess(result)) {
|
||||||
logger.warn("Failed to notify success ({}) to a promise: {}", result, promise);
|
logger.warn("Failed to notify success ({}) to a promise: {}", result, promise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doResolveUncached(String hostname, final int port, Promise<InetSocketAddress> promise) {
|
private void doResolveUncached(String hostname, Promise<InetAddress> promise) {
|
||||||
final DnsNameResolverContext<InetSocketAddress> ctx =
|
final DnsNameResolverContext<InetAddress> ctx =
|
||||||
new DnsNameResolverContext<InetSocketAddress>(this, hostname, promise) {
|
new DnsNameResolverContext<InetAddress>(this, hostname, promise) {
|
||||||
@Override
|
@Override
|
||||||
protected boolean finishResolve(
|
protected boolean finishResolve(
|
||||||
Class<? extends InetAddress> addressType, List<DnsCacheEntry> resolvedEntries) {
|
Class<? extends InetAddress> addressType, List<DnsCacheEntry> resolvedEntries) {
|
||||||
|
@ -673,7 +664,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||||
for (int i = 0; i < numEntries; i++) {
|
for (int i = 0; i < numEntries; i++) {
|
||||||
final InetAddress a = resolvedEntries.get(i).address();
|
final InetAddress a = resolvedEntries.get(i).address();
|
||||||
if (addressType.isInstance(a)) {
|
if (addressType.isInstance(a)) {
|
||||||
setSuccess(promise(), new InetSocketAddress(a, port));
|
setSuccess(promise(), a);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -685,32 +676,29 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doResolveAll(
|
protected void doResolveAll(String inetHost, Promise<List<InetAddress>> promise) throws Exception {
|
||||||
InetSocketAddress unresolvedAddress, Promise<List<InetSocketAddress>> promise) throws Exception {
|
|
||||||
|
|
||||||
final byte[] bytes = NetUtil.createByteArrayFromIpAddressString(unresolvedAddress.getHostName());
|
final byte[] bytes = NetUtil.createByteArrayFromIpAddressString(inetHost);
|
||||||
if (bytes != null) {
|
if (bytes != null) {
|
||||||
// The unresolvedAddress was created via a String that contains an ipaddress.
|
// The unresolvedAddress was created via a String that contains an ipaddress.
|
||||||
promise.setSuccess(Collections.singletonList(
|
promise.setSuccess(Collections.singletonList(InetAddress.getByAddress(bytes)));
|
||||||
new InetSocketAddress(InetAddress.getByAddress(bytes), unresolvedAddress.getPort())));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String hostname = hostname(unresolvedAddress);
|
final String hostname = hostname(inetHost);
|
||||||
final int port = unresolvedAddress.getPort();
|
|
||||||
|
|
||||||
if (!doResolveAllCached(hostname, port, promise)) {
|
if (!doResolveAllCached(hostname, promise)) {
|
||||||
doResolveAllUncached(hostname, port, 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);
|
final List<DnsCacheEntry> cachedEntries = resolveCache.get(hostname);
|
||||||
if (cachedEntries == null) {
|
if (cachedEntries == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<InetSocketAddress> result = null;
|
List<InetAddress> result = null;
|
||||||
Throwable cause = null;
|
Throwable cause = null;
|
||||||
synchronized (cachedEntries) {
|
synchronized (cachedEntries) {
|
||||||
final int numEntries = cachedEntries.size();
|
final int numEntries = cachedEntries.size();
|
||||||
|
@ -724,9 +712,9 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||||
final DnsCacheEntry e = cachedEntries.get(i);
|
final DnsCacheEntry e = cachedEntries.get(i);
|
||||||
if (f.addressType().isInstance(e.address())) {
|
if (f.addressType().isInstance(e.address())) {
|
||||||
if (result == null) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doResolveAllUncached(final String hostname, final int port,
|
private void doResolveAllUncached(final String hostname, final Promise<List<InetAddress>> promise) {
|
||||||
final Promise<List<InetSocketAddress>> promise) {
|
final DnsNameResolverContext<List<InetAddress>> ctx =
|
||||||
final DnsNameResolverContext<List<InetSocketAddress>> ctx =
|
new DnsNameResolverContext<List<InetAddress>>(this, hostname, promise) {
|
||||||
new DnsNameResolverContext<List<InetSocketAddress>>(this, hostname, promise) {
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean finishResolve(
|
protected boolean finishResolve(
|
||||||
Class<? extends InetAddress> addressType, List<DnsCacheEntry> resolvedEntries) {
|
Class<? extends InetAddress> addressType, List<DnsCacheEntry> resolvedEntries) {
|
||||||
|
|
||||||
List<InetSocketAddress> result = null;
|
List<InetAddress> result = null;
|
||||||
final int numEntries = resolvedEntries.size();
|
final int numEntries = resolvedEntries.size();
|
||||||
for (int i = 0; i < numEntries; i++) {
|
for (int i = 0; i < numEntries; i++) {
|
||||||
final InetAddress a = resolvedEntries.get(i).address();
|
final InetAddress a = resolvedEntries.get(i).address();
|
||||||
if (addressType.isInstance(a)) {
|
if (addressType.isInstance(a)) {
|
||||||
if (result == null) {
|
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();
|
ctx.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String hostname(InetSocketAddress addr) {
|
private static String hostname(String inetHost) {
|
||||||
// InetSocketAddress.getHostString() is available since Java 7.
|
return IDN.toASCII(inetHost);
|
||||||
final String hostname;
|
|
||||||
if (PlatformDependent.javaVersion() < 7) {
|
|
||||||
hostname = addr.getHostName();
|
|
||||||
} else {
|
|
||||||
hostname = addr.getHostString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return IDN.toASCII(hostname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cache(String hostname, InetAddress address, long originalTtl) {
|
void cache(String hostname, InetAddress address, long originalTtl) {
|
||||||
|
|
|
@ -320,7 +320,7 @@ public class DnsNameResolverTest {
|
||||||
InetAddress actual = resultB.get(e.getKey());
|
InetAddress actual = resultB.get(e.getKey());
|
||||||
if (!actual.equals(expected)) {
|
if (!actual.equals(expected)) {
|
||||||
// Print the content of the cache when test failure is 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));
|
assertThat(actual, is(expected));
|
||||||
}
|
}
|
||||||
|
@ -347,8 +347,8 @@ public class DnsNameResolverTest {
|
||||||
|
|
||||||
final Map<String, InetAddress> results = new HashMap<String, InetAddress>();
|
final Map<String, InetAddress> results = new HashMap<String, InetAddress>();
|
||||||
try {
|
try {
|
||||||
final Map<InetSocketAddress, Future<InetSocketAddress>> futures =
|
final Map<String, Future<InetAddress>> futures =
|
||||||
new LinkedHashMap<InetSocketAddress, Future<InetSocketAddress>>();
|
new LinkedHashMap<String, Future<InetAddress>>();
|
||||||
|
|
||||||
for (String name : DOMAINS) {
|
for (String name : DOMAINS) {
|
||||||
if (excludedDomains.contains(name)) {
|
if (excludedDomains.contains(name)) {
|
||||||
|
@ -358,19 +358,17 @@ public class DnsNameResolverTest {
|
||||||
resolve(futures, name);
|
resolve(futures, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Entry<InetSocketAddress, Future<InetSocketAddress>> e : futures.entrySet()) {
|
for (Entry<String, Future<InetAddress>> e : futures.entrySet()) {
|
||||||
InetSocketAddress unresolved = e.getKey();
|
String unresolved = e.getKey();
|
||||||
InetSocketAddress resolved = e.getValue().sync().getNow();
|
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.getHostName(), is(unresolved));
|
||||||
assertThat(resolved.getHostString(), is(unresolved.getHostString()));
|
|
||||||
assertThat(resolved.getPort(), is(unresolved.getPort()));
|
|
||||||
|
|
||||||
boolean typeMatches = false;
|
boolean typeMatches = false;
|
||||||
for (InternetProtocolFamily f: famililies) {
|
for (InternetProtocolFamily f: famililies) {
|
||||||
Class<?> resolvedType = resolved.getAddress().getClass();
|
Class<?> resolvedType = resolved.getClass();
|
||||||
if (f.addressType().isAssignableFrom(resolvedType)) {
|
if (f.addressType().isAssignableFrom(resolvedType)) {
|
||||||
typeMatches = true;
|
typeMatches = true;
|
||||||
}
|
}
|
||||||
|
@ -378,7 +376,7 @@ public class DnsNameResolverTest {
|
||||||
|
|
||||||
assertThat(typeMatches, is(true));
|
assertThat(typeMatches, is(true));
|
||||||
|
|
||||||
results.put(resolved.getHostString(), resolved.getAddress());
|
results.put(resolved.getHostName(), resolved);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
resolver.setResolveAddressTypes(oldResolveAddressTypes);
|
resolver.setResolveAddressTypes(oldResolveAddressTypes);
|
||||||
|
@ -477,7 +475,7 @@ public class DnsNameResolverTest {
|
||||||
|
|
||||||
private static UnknownHostException resolveNonExistentDomain() {
|
private static UnknownHostException resolveNonExistentDomain() {
|
||||||
try {
|
try {
|
||||||
resolver.resolve("non-existent.netty.io", 0).sync();
|
resolver.resolve("non-existent.netty.io").sync();
|
||||||
fail();
|
fail();
|
||||||
return null;
|
return null;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -488,20 +486,14 @@ public class DnsNameResolverTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResolveIp() {
|
public void testResolveIp() {
|
||||||
InetSocketAddress unresolved =
|
InetAddress address = resolver.resolve("10.0.0.1").syncUninterruptibly().getNow();
|
||||||
InetSocketAddress.createUnresolved("10.0.0.1", ThreadLocalRandom.current().nextInt(65536));
|
|
||||||
|
|
||||||
InetSocketAddress address = resolver.resolve(unresolved).syncUninterruptibly().getNow();
|
|
||||||
|
|
||||||
assertEquals("10.0.0.1", address.getHostName());
|
assertEquals("10.0.0.1", address.getHostName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void resolve(
|
private static void resolve(Map<String, Future<InetAddress>> futures, String hostname) {
|
||||||
Map<InetSocketAddress, Future<InetSocketAddress>> futures, String hostname) {
|
|
||||||
InetSocketAddress unresolved =
|
|
||||||
InetSocketAddress.createUnresolved(hostname, ThreadLocalRandom.current().nextInt(65536));
|
|
||||||
|
|
||||||
futures.put(unresolved, resolver.resolve(unresolved));
|
futures.put(hostname, resolver.resolve(hostname));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void queryMx(
|
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.
|
* 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.
|
* 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 =
|
private final Map<EventExecutor, AddressResolver<T>> resolvers =
|
||||||
new IdentityHashMap<EventExecutor, NameResolver<T>>();
|
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
|
* 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 #newResolver(EventExecutor)} so that the new resolver is reused on another
|
||||||
* {@link #getResolver(EventExecutor)} call with the same {@link EventExecutor}.
|
* {@link #getResolver(EventExecutor)} call with the same {@link EventExecutor}.
|
||||||
*/
|
*/
|
||||||
public NameResolver<T> getResolver(EventExecutor executor) {
|
public AddressResolver<T> getResolver(final EventExecutor executor) {
|
||||||
if (executor == null) {
|
if (executor == null) {
|
||||||
throw new NullPointerException("executor");
|
throw new NullPointerException("executor");
|
||||||
}
|
}
|
||||||
|
@ -61,12 +61,12 @@ public abstract class NameResolverGroup<T extends SocketAddress> implements Clos
|
||||||
return getResolver0(executor.unwrap());
|
return getResolver0(executor.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
private NameResolver<T> getResolver0(final EventExecutor executor) {
|
private AddressResolver<T> getResolver0(final EventExecutor executor) {
|
||||||
NameResolver<T> r;
|
AddressResolver<T> r;
|
||||||
synchronized (resolvers) {
|
synchronized (resolvers) {
|
||||||
r = resolvers.get(executor);
|
r = resolvers.get(executor);
|
||||||
if (r == null) {
|
if (r == null) {
|
||||||
final NameResolver<T> newResolver;
|
final AddressResolver<T> newResolver;
|
||||||
try {
|
try {
|
||||||
newResolver = newResolver(executor);
|
newResolver = newResolver(executor);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -90,9 +90,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.
|
* Closes all {@link NameResolver}s created by this group.
|
||||||
|
@ -100,13 +100,13 @@ public abstract class NameResolverGroup<T extends SocketAddress> implements Clos
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({ "unchecked", "SuspiciousToArrayCall" })
|
@SuppressWarnings({ "unchecked", "SuspiciousToArrayCall" })
|
||||||
public void close() {
|
public void close() {
|
||||||
final NameResolver<T>[] rArray;
|
final AddressResolver<T>[] rArray;
|
||||||
synchronized (resolvers) {
|
synchronized (resolvers) {
|
||||||
rArray = (NameResolver<T>[]) resolvers.values().toArray(new NameResolver[resolvers.size()]);
|
rArray = (AddressResolver<T>[]) resolvers.values().toArray(new AddressResolver[resolvers.size()]);
|
||||||
resolvers.clear();
|
resolvers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (NameResolver<T> r: rArray) {
|
for (AddressResolver<T> r: rArray) {
|
||||||
try {
|
try {
|
||||||
r.close();
|
r.close();
|
||||||
} catch (Throwable t) {
|
} 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,
|
* 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
|
* 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;
|
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
|
@Override
|
||||||
protected NameResolver<InetSocketAddress> newResolver(EventExecutor executor) throws Exception {
|
protected AddressResolver<InetSocketAddress> newResolver(EventExecutor executor) throws Exception {
|
||||||
return new DefaultNameResolver(executor);
|
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,
|
* 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
|
* 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.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
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.
|
* 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) {
|
public DefaultNameResolver(EventExecutor executor) {
|
||||||
super(executor);
|
super(executor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean doIsResolved(InetSocketAddress address) {
|
protected void doResolve(String inetHost, Promise<InetAddress> promise) throws Exception {
|
||||||
return !address.isUnresolved();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doResolve(InetSocketAddress unresolvedAddress, Promise<InetSocketAddress> promise) throws Exception {
|
|
||||||
try {
|
try {
|
||||||
// Note that InetSocketAddress.getHostName() will never incur a reverse lookup here,
|
promise.setSuccess(InetAddress.getByName(inetHost));
|
||||||
// because an unresolved address always has a host name.
|
|
||||||
promise.setSuccess(new InetSocketAddress(
|
|
||||||
InetAddress.getByName(unresolvedAddress.getHostName()), unresolvedAddress.getPort()));
|
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
promise.setFailure(e);
|
promise.setFailure(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doResolveAll(
|
protected void doResolveAll(String inetHost, Promise<List<InetAddress>> promise) throws Exception {
|
||||||
InetSocketAddress unresolvedAddress, Promise<List<InetSocketAddress>> promise) throws Exception {
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Note that InetSocketAddress.getHostName() will never incur a reverse lookup here,
|
promise.setSuccess(Arrays.asList(InetAddress.getAllByName(inetHost)));
|
||||||
// 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);
|
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
promise.setFailure(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 io.netty.util.concurrent.Promise;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.net.SocketAddress;
|
|
||||||
import java.nio.channels.UnsupportedAddressTypeException;
|
|
||||||
import java.util.List;
|
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.
|
* Resolves the specified name into an address.
|
||||||
*/
|
|
||||||
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}.
|
|
||||||
*
|
*
|
||||||
* @param inetHost the name to resolve
|
* @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 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
|
* @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
|
* Resolves the specified host name and port into a list of address.
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
* @param inetHost the name to resolve
|
* @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 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
|
* @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);
|
Future<List<T>> resolveAll(String inetHost, 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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes all the resources allocated and used by this resolver.
|
* Closes all the resources allocated and used by this resolver.
|
||||||
|
|
|
@ -24,12 +24,12 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
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.
|
* 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);
|
super(executor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,16 +21,16 @@ import io.netty.util.concurrent.EventExecutor;
|
||||||
import java.net.SocketAddress;
|
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
|
@Override
|
||||||
protected NameResolver<SocketAddress> newResolver(EventExecutor executor) throws Exception {
|
protected AddressResolver<SocketAddress> newResolver(EventExecutor executor) throws Exception {
|
||||||
return new NoopNameResolver(executor);
|
return new NoopAddressResolver(executor);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,12 +19,7 @@ package io.netty.resolver;
|
||||||
import io.netty.util.concurrent.EventExecutor;
|
import io.netty.util.concurrent.EventExecutor;
|
||||||
import io.netty.util.concurrent.Future;
|
import io.netty.util.concurrent.Future;
|
||||||
import io.netty.util.concurrent.Promise;
|
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 java.util.List;
|
||||||
|
|
||||||
import static io.netty.util.internal.ObjectUtil.*;
|
import static io.netty.util.internal.ObjectUtil.*;
|
||||||
|
@ -32,124 +27,39 @@ import static io.netty.util.internal.ObjectUtil.*;
|
||||||
/**
|
/**
|
||||||
* A skeletal {@link NameResolver} implementation.
|
* 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 EventExecutor executor;
|
||||||
private final TypeParameterMatcher matcher;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned
|
* @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) {
|
protected SimpleNameResolver(EventExecutor executor) {
|
||||||
if (executor == null) {
|
this.executor = checkNotNull(executor, "executor");
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned
|
* 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() {
|
protected EventExecutor executor() {
|
||||||
return executor;
|
return executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSupported(SocketAddress address) {
|
public final Future<T> resolve(String inetHost) {
|
||||||
return matcher.match(address);
|
final Promise<T> promise = executor().newPromise();
|
||||||
|
return resolve(inetHost, promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean isResolved(SocketAddress address) {
|
public Future<T> resolve(String inetHost, Promise<T> promise) {
|
||||||
if (!isSupported(address)) {
|
checkNotNull(inetHost, "inetHost");
|
||||||
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");
|
|
||||||
checkNotNull(promise, "promise");
|
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 {
|
try {
|
||||||
@SuppressWarnings("unchecked")
|
doResolve(inetHost, promise);
|
||||||
final T cast = (T) address;
|
|
||||||
doResolve(cast, promise);
|
|
||||||
return promise;
|
return promise;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return promise.setFailure(e);
|
return promise.setFailure(e);
|
||||||
|
@ -157,61 +67,18 @@ public abstract class SimpleNameResolver<T extends SocketAddress> implements Nam
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Future<List<T>> resolveAll(String inetHost, int inetPort) {
|
public final Future<List<T>> resolveAll(String inetHost) {
|
||||||
return resolveAll(InetSocketAddress.createUnresolved(checkNotNull(inetHost, "inetHost"), inetPort));
|
final Promise<List<T>> promise = executor().newPromise();
|
||||||
|
return resolveAll(inetHost, promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Future<List<T>> resolveAll(String inetHost, int inetPort, Promise<List<T>> promise) {
|
public Future<List<T>> resolveAll(String inetHost, Promise<List<T>> promise) {
|
||||||
return resolveAll(InetSocketAddress.createUnresolved(checkNotNull(inetHost, "inetHost"), inetPort), promise);
|
checkNotNull(inetHost, "inetHost");
|
||||||
}
|
|
||||||
|
|
||||||
@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");
|
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 {
|
try {
|
||||||
@SuppressWarnings("unchecked")
|
doResolveAll(inetHost, promise);
|
||||||
final T cast = (T) address;
|
|
||||||
doResolveAll(cast, promise);
|
|
||||||
return promise;
|
return promise;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return promise.setFailure(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
|
* Invoked by {@link #resolve(String)} to perform the actual name resolution.
|
||||||
* 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
|
* Invoked by {@link #resolveAll(String)} to perform the actual name resolution.
|
||||||
* 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
|
@Override
|
||||||
public void close() { }
|
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;
|
package io.netty.resolver;
|
||||||
|
|
|
@ -23,9 +23,10 @@ import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelPromise;
|
import io.netty.channel.ChannelPromise;
|
||||||
import io.netty.channel.EventLoop;
|
import io.netty.channel.EventLoop;
|
||||||
import io.netty.channel.EventLoopGroup;
|
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.NameResolver;
|
||||||
import io.netty.resolver.NameResolverGroup;
|
import io.netty.resolver.AddressResolverGroup;
|
||||||
import io.netty.util.AttributeKey;
|
import io.netty.util.AttributeKey;
|
||||||
import io.netty.util.concurrent.Future;
|
import io.netty.util.concurrent.Future;
|
||||||
import io.netty.util.concurrent.FutureListener;
|
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 InternalLogger logger = InternalLoggerFactory.getInstance(Bootstrap.class);
|
||||||
|
|
||||||
private static final NameResolverGroup<?> DEFAULT_RESOLVER = DefaultNameResolverGroup.INSTANCE;
|
private static final AddressResolverGroup<?> DEFAULT_RESOLVER = DefaultAddressResolverGroup.INSTANCE;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private volatile NameResolverGroup<SocketAddress> resolver = (NameResolverGroup<SocketAddress>) DEFAULT_RESOLVER;
|
private volatile AddressResolverGroup<SocketAddress> resolver =
|
||||||
|
(AddressResolverGroup<SocketAddress>) DEFAULT_RESOLVER;
|
||||||
private volatile SocketAddress remoteAddress;
|
private volatile SocketAddress remoteAddress;
|
||||||
|
|
||||||
public Bootstrap() { }
|
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.
|
* Sets the {@link NameResolver} which will resolve the address of the unresolved named address.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Bootstrap resolver(NameResolverGroup<?> resolver) {
|
public Bootstrap resolver(AddressResolverGroup<?> resolver) {
|
||||||
if (resolver == null) {
|
if (resolver == null) {
|
||||||
throw new NullPointerException("resolver");
|
throw new NullPointerException("resolver");
|
||||||
}
|
}
|
||||||
this.resolver = (NameResolverGroup<SocketAddress>) resolver;
|
this.resolver = (AddressResolverGroup<SocketAddress>) resolver;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +164,7 @@ public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {
|
||||||
|
|
||||||
final Channel channel = regFuture.channel();
|
final Channel channel = regFuture.channel();
|
||||||
final EventLoop eventLoop = channel.eventLoop();
|
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)) {
|
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.
|
// 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.LocalAddress;
|
||||||
import io.netty.channel.local.LocalChannel;
|
import io.netty.channel.local.LocalChannel;
|
||||||
import io.netty.channel.local.LocalServerChannel;
|
import io.netty.channel.local.LocalServerChannel;
|
||||||
import io.netty.resolver.NameResolver;
|
import io.netty.resolver.AddressResolver;
|
||||||
import io.netty.resolver.NameResolverGroup;
|
import io.netty.resolver.AddressResolverGroup;
|
||||||
import io.netty.resolver.SimpleNameResolver;
|
import io.netty.resolver.AbstractAddressResolver;
|
||||||
import io.netty.util.concurrent.EventExecutor;
|
import io.netty.util.concurrent.EventExecutor;
|
||||||
import io.netty.util.concurrent.Future;
|
import io.netty.util.concurrent.Future;
|
||||||
import io.netty.util.concurrent.Promise;
|
import io.netty.util.concurrent.Promise;
|
||||||
|
@ -221,7 +221,7 @@ public class BootstrapTest {
|
||||||
final Bootstrap bootstrapA = new Bootstrap();
|
final Bootstrap bootstrapA = new Bootstrap();
|
||||||
bootstrapA.group(groupA);
|
bootstrapA.group(groupA);
|
||||||
bootstrapA.channel(LocalChannel.class);
|
bootstrapA.channel(LocalChannel.class);
|
||||||
bootstrapA.resolver(new TestNameResolverGroup(true));
|
bootstrapA.resolver(new TestAddressResolverGroup(true));
|
||||||
bootstrapA.handler(dummyHandler);
|
bootstrapA.handler(dummyHandler);
|
||||||
|
|
||||||
final ServerBootstrap bootstrapB = new ServerBootstrap();
|
final ServerBootstrap bootstrapB = new ServerBootstrap();
|
||||||
|
@ -240,7 +240,7 @@ public class BootstrapTest {
|
||||||
final Bootstrap bootstrapA = new Bootstrap();
|
final Bootstrap bootstrapA = new Bootstrap();
|
||||||
bootstrapA.group(groupA);
|
bootstrapA.group(groupA);
|
||||||
bootstrapA.channel(LocalChannel.class);
|
bootstrapA.channel(LocalChannel.class);
|
||||||
bootstrapA.resolver(new TestNameResolverGroup(false));
|
bootstrapA.resolver(new TestAddressResolverGroup(false));
|
||||||
bootstrapA.handler(dummyHandler);
|
bootstrapA.handler(dummyHandler);
|
||||||
|
|
||||||
final ServerBootstrap bootstrapB = new ServerBootstrap();
|
final ServerBootstrap bootstrapB = new ServerBootstrap();
|
||||||
|
@ -282,17 +282,17 @@ public class BootstrapTest {
|
||||||
@Sharable
|
@Sharable
|
||||||
private static final class DummyHandler extends ChannelHandlerAdapter { }
|
private static final class DummyHandler extends ChannelHandlerAdapter { }
|
||||||
|
|
||||||
private static final class TestNameResolverGroup extends NameResolverGroup<SocketAddress> {
|
private static final class TestAddressResolverGroup extends AddressResolverGroup<SocketAddress> {
|
||||||
|
|
||||||
private final boolean success;
|
private final boolean success;
|
||||||
|
|
||||||
TestNameResolverGroup(boolean success) {
|
TestAddressResolverGroup(boolean success) {
|
||||||
this.success = success;
|
this.success = success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected NameResolver<SocketAddress> newResolver(EventExecutor executor) throws Exception {
|
protected AddressResolver<SocketAddress> newResolver(EventExecutor executor) throws Exception {
|
||||||
return new SimpleNameResolver<SocketAddress>(executor) {
|
return new AbstractAddressResolver<SocketAddress>(executor) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean doIsResolved(SocketAddress address) {
|
protected boolean doIsResolved(SocketAddress address) {
|
||||||
|
|
Loading…
Reference in New Issue