Skip to content

Commit 6393506

Browse files
slandellenormanmaurer
authored andcommitted
Extract SocketAdress logic from NameResolver
Motivation: As discussed in netty#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>.
1 parent 89ff831 commit 6393506

File tree

18 files changed

+602
-400
lines changed

18 files changed

+602
-400
lines changed

handler-proxy/src/test/java/io/netty/handler/proxy/ProxyHandlerTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
import io.netty.handler.ssl.SslContext;
3737
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
3838
import io.netty.handler.ssl.util.SelfSignedCertificate;
39-
import io.netty.resolver.NoopNameResolverGroup;
39+
import io.netty.resolver.NoopAddressResolverGroup;
4040
import io.netty.util.CharsetUtil;
4141
import io.netty.util.concurrent.DefaultThreadFactory;
4242
import io.netty.util.concurrent.Future;
@@ -523,7 +523,7 @@ protected void test() throws Exception {
523523
Bootstrap b = new Bootstrap();
524524
b.group(group);
525525
b.channel(NioSocketChannel.class);
526-
b.resolver(NoopNameResolverGroup.INSTANCE);
526+
b.resolver(NoopAddressResolverGroup.INSTANCE);
527527
b.handler(new ChannelInitializer<SocketChannel>() {
528528
@Override
529529
protected void initChannel(SocketChannel ch) throws Exception {
@@ -571,7 +571,7 @@ protected void test() throws Exception {
571571
Bootstrap b = new Bootstrap();
572572
b.group(group);
573573
b.channel(NioSocketChannel.class);
574-
b.resolver(NoopNameResolverGroup.INSTANCE);
574+
b.resolver(NoopAddressResolverGroup.INSTANCE);
575575
b.handler(new ChannelInitializer<SocketChannel>() {
576576
@Override
577577
protected void initChannel(SocketChannel ch) throws Exception {
@@ -616,7 +616,7 @@ protected void test() throws Exception {
616616
Bootstrap b = new Bootstrap();
617617
b.group(group);
618618
b.channel(NioSocketChannel.class);
619-
b.resolver(NoopNameResolverGroup.INSTANCE);
619+
b.resolver(NoopAddressResolverGroup.INSTANCE);
620620
b.handler(new ChannelInitializer<SocketChannel>() {
621621
@Override
622622
protected void initChannel(SocketChannel ch) throws Exception {

resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverGroup.java renamed to resolver-dns/src/main/java/io/netty/resolver/dns/DnsAddressResolverGroup.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
import io.netty.channel.EventLoop;
2121
import io.netty.channel.ReflectiveChannelFactory;
2222
import io.netty.channel.socket.DatagramChannel;
23-
import io.netty.resolver.NameResolver;
24-
import io.netty.resolver.NameResolverGroup;
23+
import io.netty.resolver.AddressResolver;
24+
import io.netty.resolver.AddressResolverGroup;
2525
import io.netty.util.concurrent.EventExecutor;
2626
import io.netty.util.internal.StringUtil;
2727

@@ -30,31 +30,31 @@
3030
import static io.netty.resolver.dns.DnsNameResolver.ANY_LOCAL_ADDR;
3131

3232
/**
33-
* A {@link NameResolverGroup} of {@link DnsNameResolver}s.
33+
* A {@link AddressResolverGroup} of {@link DnsNameResolver}s.
3434
*/
35-
public class DnsNameResolverGroup extends NameResolverGroup<InetSocketAddress> {
35+
public class DnsAddressResolverGroup extends AddressResolverGroup<InetSocketAddress> {
3636

3737
private final ChannelFactory<? extends DatagramChannel> channelFactory;
3838
private final InetSocketAddress localAddress;
3939
private final DnsServerAddresses nameServerAddresses;
4040

41-
public DnsNameResolverGroup(
41+
public DnsAddressResolverGroup(
4242
Class<? extends DatagramChannel> channelType, DnsServerAddresses nameServerAddresses) {
4343
this(channelType, ANY_LOCAL_ADDR, nameServerAddresses);
4444
}
4545

46-
public DnsNameResolverGroup(
46+
public DnsAddressResolverGroup(
4747
Class<? extends DatagramChannel> channelType,
4848
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
4949
this(new ReflectiveChannelFactory<DatagramChannel>(channelType), localAddress, nameServerAddresses);
5050
}
5151

52-
public DnsNameResolverGroup(
52+
public DnsAddressResolverGroup(
5353
ChannelFactory<? extends DatagramChannel> channelFactory, DnsServerAddresses nameServerAddresses) {
5454
this(channelFactory, ANY_LOCAL_ADDR, nameServerAddresses);
5555
}
5656

57-
public DnsNameResolverGroup(
57+
public DnsAddressResolverGroup(
5858
ChannelFactory<? extends DatagramChannel> channelFactory,
5959
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
6060
this.channelFactory = channelFactory;
@@ -63,7 +63,7 @@ public DnsNameResolverGroup(
6363
}
6464

6565
@Override
66-
protected final NameResolver<InetSocketAddress> newResolver(EventExecutor executor) throws Exception {
66+
protected final AddressResolver<InetSocketAddress> newResolver(EventExecutor executor) throws Exception {
6767
if (!(executor instanceof EventLoop)) {
6868
throw new IllegalStateException(
6969
"unsupported executor type: " + StringUtil.simpleClassName(executor) +
@@ -77,11 +77,11 @@ protected final NameResolver<InetSocketAddress> newResolver(EventExecutor execut
7777
* Creates a new {@link DnsNameResolver}. Override this method to create an alternative {@link DnsNameResolver}
7878
* implementation or override the default configuration.
7979
*/
80-
protected DnsNameResolver newResolver(
80+
protected AddressResolver<InetSocketAddress> newResolver(
8181
EventLoop eventLoop, ChannelFactory<? extends DatagramChannel> channelFactory,
8282
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) throws Exception {
8383

84-
return new DnsNameResolver(
85-
eventLoop, channelFactory, localAddress, nameServerAddresses);
84+
return new DnsNameResolver(eventLoop, channelFactory, localAddress, nameServerAddresses)
85+
.asAddressResolver();
8686
}
8787
}

resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolver.java

Lines changed: 40 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,20 @@
3333
import io.netty.handler.codec.dns.DatagramDnsResponseDecoder;
3434
import io.netty.handler.codec.dns.DnsQuestion;
3535
import io.netty.handler.codec.dns.DnsResponse;
36-
import io.netty.resolver.NameResolver;
37-
import io.netty.resolver.SimpleNameResolver;
36+
import io.netty.resolver.InetNameResolver;
3837
import io.netty.util.NetUtil;
3938
import io.netty.util.ReferenceCountUtil;
4039
import io.netty.util.concurrent.FastThreadLocal;
4140
import io.netty.util.concurrent.Future;
4241
import io.netty.util.concurrent.Promise;
4342
import io.netty.util.internal.OneTimeTask;
4443
import io.netty.util.internal.PlatformDependent;
45-
import io.netty.util.internal.SystemPropertyUtil;
4644
import io.netty.util.internal.logging.InternalLogger;
4745
import io.netty.util.internal.logging.InternalLoggerFactory;
4846

4947
import java.net.IDN;
5048
import java.net.InetAddress;
5149
import java.net.InetSocketAddress;
52-
import java.net.SocketAddress;
5350
import java.util.ArrayList;
5451
import java.util.Arrays;
5552
import java.util.Collections;
@@ -62,9 +59,9 @@
6259
import static io.netty.util.internal.ObjectUtil.checkNotNull;
6360

6461
/**
65-
* A DNS-based {@link NameResolver}.
62+
* A DNS-based {@link InetNameResolver}.
6663
*/
67-
public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
64+
public class DnsNameResolver extends InetNameResolver {
6865

6966
private static final InternalLogger logger = InternalLoggerFactory.getInstance(DnsNameResolver.class);
7067

@@ -74,7 +71,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
7471

7572
static {
7673
// Note that we did not use SystemPropertyUtil.getBoolean() here to emulate the behavior of JDK.
77-
if ("true".equalsIgnoreCase(SystemPropertyUtil.get("java.net.preferIPv6Addresses"))) {
74+
if (Boolean.getBoolean("java.net.preferIPv6Addresses")) {
7875
DEFAULT_RESOLVE_ADDRESS_TYPES[0] = InternetProtocolFamily.IPv6;
7976
DEFAULT_RESOLVE_ADDRESS_TYPES[1] = InternetProtocolFamily.IPv4;
8077
logger.debug("-Djava.net.preferIPv6Addresses: true");
@@ -98,7 +95,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
9895
final DnsQueryContextManager queryContextManager = new DnsQueryContextManager();
9996

10097
/**
101-
* Cache for {@link #doResolve(InetSocketAddress, Promise)} and {@link #doResolveAll(InetSocketAddress, Promise)}.
98+
* Cache for {@link #doResolve(String, Promise)} and {@link #doResolveAll(String, Promise)}.
10299
*/
103100
final ConcurrentMap<String, List<DnsCacheEntry>> resolveCache = PlatformDependent.newConcurrentHashMap();
104101

@@ -329,7 +326,7 @@ public DnsNameResolver setQueryTimeoutMillis(long queryTimeoutMillis) {
329326
}
330327

331328
/**
332-
* Returns the list of the protocol families of the address resolved by {@link #resolve(SocketAddress)}
329+
* Returns the list of the protocol families of the address resolved by {@link #resolve(String)}
333330
* in the order of preference.
334331
* The default value depends on the value of the system property {@code "java.net.preferIPv6Addresses"}.
335332
*
@@ -344,7 +341,7 @@ InternetProtocolFamily[] resolveAddressTypesUnsafe() {
344341
}
345342

346343
/**
347-
* Sets the list of the protocol families of the address resolved by {@link #resolve(SocketAddress)}.
344+
* Sets the list of the protocol families of the address resolved by {@link #resolve(String)}.
348345
* Usually, both {@link InternetProtocolFamily#IPv4} and {@link InternetProtocolFamily#IPv6} are specified in the
349346
* order of preference. To enforce the resolve to retrieve the address of a specific protocol family, specify
350347
* only a single {@link InternetProtocolFamily}.
@@ -382,7 +379,7 @@ public DnsNameResolver setResolveAddressTypes(InternetProtocolFamily... resolveA
382379
}
383380

384381
/**
385-
* Sets the list of the protocol families of the address resolved by {@link #resolve(SocketAddress)}.
382+
* Sets the list of the protocol families of the address resolved by {@link #resolve(String)}.
386383
* Usually, both {@link InternetProtocolFamily#IPv4} and {@link InternetProtocolFamily#IPv6} are specified in the
387384
* order of preference. To enforce the resolve to retrieve the address of a specific protocol family, specify
388385
* only a single {@link InternetProtocolFamily}.
@@ -594,28 +591,22 @@ protected EventLoop executor() {
594591
}
595592

596593
@Override
597-
protected boolean doIsResolved(InetSocketAddress address) {
598-
return !address.isUnresolved();
599-
}
600-
601-
@Override
602-
protected void doResolve(InetSocketAddress unresolvedAddress, Promise<InetSocketAddress> promise) throws Exception {
603-
final byte[] bytes = NetUtil.createByteArrayFromIpAddressString(unresolvedAddress.getHostName());
594+
protected void doResolve(String inetHost, Promise<InetAddress> promise) throws Exception {
595+
final byte[] bytes = NetUtil.createByteArrayFromIpAddressString(inetHost);
604596
if (bytes != null) {
605-
// The unresolvedAddress was created via a String that contains an ipaddress.
606-
promise.setSuccess(new InetSocketAddress(InetAddress.getByAddress(bytes), unresolvedAddress.getPort()));
597+
// The inetHost is actually an ipaddress.
598+
promise.setSuccess(InetAddress.getByAddress(bytes));
607599
return;
608600
}
609601

610-
final String hostname = hostname(unresolvedAddress);
611-
final int port = unresolvedAddress.getPort();
602+
final String hostname = hostname(inetHost);
612603

613-
if (!doResolveCached(hostname, port, promise)) {
614-
doResolveUncached(hostname, port, promise);
604+
if (!doResolveCached(hostname, promise)) {
605+
doResolveUncached(hostname, promise);
615606
}
616607
}
617608

618-
private boolean doResolveCached(String hostname, int port, Promise<InetSocketAddress> promise) {
609+
private boolean doResolveCached(String hostname, Promise<InetAddress> promise) {
619610
final List<DnsCacheEntry> cachedEntries = resolveCache.get(hostname);
620611
if (cachedEntries == null) {
621612
return false;
@@ -644,7 +635,7 @@ private boolean doResolveCached(String hostname, int port, Promise<InetSocketAdd
644635
}
645636

646637
if (address != null) {
647-
setSuccess(promise, new InetSocketAddress(address, port));
638+
setSuccess(promise, address);
648639
} else if (cause != null) {
649640
if (!promise.tryFailure(cause)) {
650641
logger.warn("Failed to notify failure to a promise: {}", promise, cause);
@@ -656,15 +647,15 @@ private boolean doResolveCached(String hostname, int port, Promise<InetSocketAdd
656647
return true;
657648
}
658649

659-
private static void setSuccess(Promise<InetSocketAddress> promise, InetSocketAddress result) {
650+
private static void setSuccess(Promise<InetAddress> promise, InetAddress result) {
660651
if (!promise.trySuccess(result)) {
661652
logger.warn("Failed to notify success ({}) to a promise: {}", result, promise);
662653
}
663654
}
664655

665-
private void doResolveUncached(String hostname, final int port, Promise<InetSocketAddress> promise) {
666-
final DnsNameResolverContext<InetSocketAddress> ctx =
667-
new DnsNameResolverContext<InetSocketAddress>(this, hostname, promise) {
656+
private void doResolveUncached(String hostname, Promise<InetAddress> promise) {
657+
final DnsNameResolverContext<InetAddress> ctx =
658+
new DnsNameResolverContext<InetAddress>(this, hostname, promise) {
668659
@Override
669660
protected boolean finishResolve(
670661
Class<? extends InetAddress> addressType, List<DnsCacheEntry> resolvedEntries) {
@@ -673,7 +664,7 @@ protected boolean finishResolve(
673664
for (int i = 0; i < numEntries; i++) {
674665
final InetAddress a = resolvedEntries.get(i).address();
675666
if (addressType.isInstance(a)) {
676-
setSuccess(promise(), new InetSocketAddress(a, port));
667+
setSuccess(promise(), a);
677668
return true;
678669
}
679670
}
@@ -685,32 +676,29 @@ protected boolean finishResolve(
685676
}
686677

687678
@Override
688-
protected void doResolveAll(
689-
InetSocketAddress unresolvedAddress, Promise<List<InetSocketAddress>> promise) throws Exception {
679+
protected void doResolveAll(String inetHost, Promise<List<InetAddress>> promise) throws Exception {
690680

691-
final byte[] bytes = NetUtil.createByteArrayFromIpAddressString(unresolvedAddress.getHostName());
681+
final byte[] bytes = NetUtil.createByteArrayFromIpAddressString(inetHost);
692682
if (bytes != null) {
693683
// The unresolvedAddress was created via a String that contains an ipaddress.
694-
promise.setSuccess(Collections.singletonList(
695-
new InetSocketAddress(InetAddress.getByAddress(bytes), unresolvedAddress.getPort())));
684+
promise.setSuccess(Collections.singletonList(InetAddress.getByAddress(bytes)));
696685
return;
697686
}
698687

699-
final String hostname = hostname(unresolvedAddress);
700-
final int port = unresolvedAddress.getPort();
688+
final String hostname = hostname(inetHost);
701689

702-
if (!doResolveAllCached(hostname, port, promise)) {
703-
doResolveAllUncached(hostname, port, promise);
690+
if (!doResolveAllCached(hostname, promise)) {
691+
doResolveAllUncached(hostname, promise);
704692
}
705693
}
706694

707-
private boolean doResolveAllCached(String hostname, int port, Promise<List<InetSocketAddress>> promise) {
695+
private boolean doResolveAllCached(String hostname, Promise<List<InetAddress>> promise) {
708696
final List<DnsCacheEntry> cachedEntries = resolveCache.get(hostname);
709697
if (cachedEntries == null) {
710698
return false;
711699
}
712700

713-
List<InetSocketAddress> result = null;
701+
List<InetAddress> result = null;
714702
Throwable cause = null;
715703
synchronized (cachedEntries) {
716704
final int numEntries = cachedEntries.size();
@@ -724,9 +712,9 @@ private boolean doResolveAllCached(String hostname, int port, Promise<List<InetS
724712
final DnsCacheEntry e = cachedEntries.get(i);
725713
if (f.addressType().isInstance(e.address())) {
726714
if (result == null) {
727-
result = new ArrayList<InetSocketAddress>(numEntries);
715+
result = new ArrayList<InetAddress>(numEntries);
728716
}
729-
result.add(new InetSocketAddress(e.address(), port));
717+
result.add(e.address());
730718
}
731719
}
732720
}
@@ -744,23 +732,22 @@ private boolean doResolveAllCached(String hostname, int port, Promise<List<InetS
744732
return true;
745733
}
746734

747-
private void doResolveAllUncached(final String hostname, final int port,
748-
final Promise<List<InetSocketAddress>> promise) {
749-
final DnsNameResolverContext<List<InetSocketAddress>> ctx =
750-
new DnsNameResolverContext<List<InetSocketAddress>>(this, hostname, promise) {
735+
private void doResolveAllUncached(final String hostname, final Promise<List<InetAddress>> promise) {
736+
final DnsNameResolverContext<List<InetAddress>> ctx =
737+
new DnsNameResolverContext<List<InetAddress>>(this, hostname, promise) {
751738
@Override
752739
protected boolean finishResolve(
753740
Class<? extends InetAddress> addressType, List<DnsCacheEntry> resolvedEntries) {
754741

755-
List<InetSocketAddress> result = null;
742+
List<InetAddress> result = null;
756743
final int numEntries = resolvedEntries.size();
757744
for (int i = 0; i < numEntries; i++) {
758745
final InetAddress a = resolvedEntries.get(i).address();
759746
if (addressType.isInstance(a)) {
760747
if (result == null) {
761-
result = new ArrayList<InetSocketAddress>(numEntries);
748+
result = new ArrayList<InetAddress>(numEntries);
762749
}
763-
result.add(new InetSocketAddress(a, port));
750+
result.add(a);
764751
}
765752
}
766753

@@ -775,16 +762,8 @@ protected boolean finishResolve(
775762
ctx.resolve();
776763
}
777764

778-
private static String hostname(InetSocketAddress addr) {
779-
// InetSocketAddress.getHostString() is available since Java 7.
780-
final String hostname;
781-
if (PlatformDependent.javaVersion() < 7) {
782-
hostname = addr.getHostName();
783-
} else {
784-
hostname = addr.getHostString();
785-
}
786-
787-
return IDN.toASCII(hostname);
765+
private static String hostname(String inetHost) {
766+
return IDN.toASCII(inetHost);
788767
}
789768

790769
void cache(String hostname, InetAddress address, long originalTtl) {

0 commit comments

Comments
 (0)