Skip to content

Commit 6c69dc2

Browse files
committed
Backport latest DNS changes, close AsyncHttpClient#1200
1 parent 4e09bf7 commit 6c69dc2

File tree

5 files changed

+202
-67
lines changed

5 files changed

+202
-67
lines changed

netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsAddressResolverGroup.java

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,46 +22,44 @@
2222
import io.netty.channel.socket.DatagramChannel;
2323
import io.netty.resolver.AddressResolver;
2424
import io.netty.resolver.AddressResolverGroup;
25+
import io.netty.resolver.InetSocketAddressResolver;
26+
import io.netty.resolver.NameResolver;
2527
import io.netty.util.concurrent.EventExecutor;
28+
import io.netty.util.concurrent.Promise;
2629
import io.netty.util.internal.StringUtil;
2730

31+
import java.net.InetAddress;
2832
import java.net.InetSocketAddress;
33+
import java.util.List;
34+
import java.util.concurrent.ConcurrentMap;
2935

30-
import static io.netty.resolver.dns.DnsNameResolver.ANY_LOCAL_ADDR;
36+
import static io.netty.util.internal.PlatformDependent.newConcurrentHashMap;
3137

3238
/**
3339
* A {@link AddressResolverGroup} of {@link DnsNameResolver}s.
3440
*/
3541
public class DnsAddressResolverGroup extends AddressResolverGroup<InetSocketAddress> {
3642

3743
private final ChannelFactory<? extends DatagramChannel> channelFactory;
38-
private final InetSocketAddress localAddress;
3944
private final DnsServerAddresses nameServerAddresses;
4045

41-
public DnsAddressResolverGroup(
42-
Class<? extends DatagramChannel> channelType, DnsServerAddresses nameServerAddresses) {
43-
this(channelType, ANY_LOCAL_ADDR, nameServerAddresses);
44-
}
46+
private final ConcurrentMap<String, Promise<InetAddress>> resolvesInProgress = newConcurrentHashMap();
47+
private final ConcurrentMap<String, Promise<List<InetAddress>>> resolveAllsInProgress = newConcurrentHashMap();
4548

4649
public DnsAddressResolverGroup(
4750
Class<? extends DatagramChannel> channelType,
48-
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
49-
this(new ReflectiveChannelFactory<DatagramChannel>(channelType), localAddress, nameServerAddresses);
50-
}
51-
52-
public DnsAddressResolverGroup(
53-
ChannelFactory<? extends DatagramChannel> channelFactory, DnsServerAddresses nameServerAddresses) {
54-
this(channelFactory, ANY_LOCAL_ADDR, nameServerAddresses);
51+
DnsServerAddresses nameServerAddresses) {
52+
this(new ReflectiveChannelFactory<DatagramChannel>(channelType), nameServerAddresses);
5553
}
5654

5755
public DnsAddressResolverGroup(
5856
ChannelFactory<? extends DatagramChannel> channelFactory,
59-
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
57+
DnsServerAddresses nameServerAddresses) {
6058
this.channelFactory = channelFactory;
61-
this.localAddress = localAddress;
6259
this.nameServerAddresses = nameServerAddresses;
6360
}
6461

62+
@SuppressWarnings("deprecation")
6563
@Override
6664
protected final AddressResolver<InetSocketAddress> newResolver(EventExecutor executor) throws Exception {
6765
if (!(executor instanceof EventLoop)) {
@@ -70,22 +68,36 @@ protected final AddressResolver<InetSocketAddress> newResolver(EventExecutor exe
7068
" (expected: " + StringUtil.simpleClassName(EventLoop.class));
7169
}
7270

73-
return newResolver((EventLoop) executor, channelFactory, localAddress, nameServerAddresses);
71+
return newResolver((EventLoop) executor, channelFactory, nameServerAddresses);
7472
}
7573

7674
/**
77-
* Creates a new {@link DnsNameResolver}. Override this method to create an alternative {@link DnsNameResolver}
78-
* implementation or override the default configuration.
75+
* @deprecated Override {@link #newNameResolver(EventLoop, ChannelFactory, DnsServerAddresses)}.
7976
*/
77+
@Deprecated
8078
protected AddressResolver<InetSocketAddress> newResolver(
8179
EventLoop eventLoop, ChannelFactory<? extends DatagramChannel> channelFactory,
82-
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) throws Exception {
80+
DnsServerAddresses nameServerAddresses) throws Exception {
8381

82+
final NameResolver<InetAddress> resolver = new InflightNameResolver<InetAddress>(
83+
eventLoop,
84+
newNameResolver(eventLoop, channelFactory, nameServerAddresses),
85+
resolvesInProgress,
86+
resolveAllsInProgress);
87+
88+
return new InetSocketAddressResolver(eventLoop, resolver);
89+
}
90+
91+
/**
92+
* Creates a new {@link NameResolver}. Override this method to create an alternative {@link NameResolver}
93+
* implementation or override the default configuration.
94+
*/
95+
protected NameResolver<InetAddress> newNameResolver(EventLoop eventLoop,
96+
ChannelFactory<? extends DatagramChannel> channelFactory,
97+
DnsServerAddresses nameServerAddresses) throws Exception {
8498
return new DnsNameResolverBuilder(eventLoop)
8599
.channelFactory(channelFactory)
86-
.localAddress(localAddress)
87100
.nameServerAddresses(nameServerAddresses)
88-
.build()
89-
.asAddressResolver();
101+
.build();
90102
}
91103
}

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

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
import io.netty.bootstrap.Bootstrap;
1919
import io.netty.bootstrap.ChannelFactory;
2020
import io.netty.channel.AddressedEnvelope;
21+
import io.netty.channel.Channel;
2122
import io.netty.channel.ChannelFuture;
2223
import io.netty.channel.ChannelFutureListener;
2324
import io.netty.channel.ChannelHandlerContext;
2425
import io.netty.channel.ChannelInboundHandlerAdapter;
2526
import io.netty.channel.ChannelInitializer;
27+
import io.netty.channel.ChannelOption;
2628
import io.netty.channel.EventLoop;
2729
import io.netty.channel.FixedRecvByteBufAllocator;
2830
import io.netty.channel.socket.DatagramChannel;
@@ -64,8 +66,6 @@ public class DnsNameResolver extends InetNameResolver {
6466
private static final String LOCALHOST = "localhost";
6567
private static final InetAddress LOCALHOST_ADDRESS;
6668

67-
static final InetSocketAddress ANY_LOCAL_ADDR = new InetSocketAddress(0);
68-
6969
static final InternetProtocolFamily[] DEFAULT_RESOLVE_ADDRESS_TYPES = new InternetProtocolFamily[2];
7070

7171
static {
@@ -87,7 +87,7 @@ public class DnsNameResolver extends InetNameResolver {
8787
private static final DatagramDnsQueryEncoder ENCODER = new DatagramDnsQueryEncoder();
8888

8989
final DnsServerAddresses nameServerAddresses;
90-
final ChannelFuture bindFuture;
90+
final Future<Channel> channelFuture;
9191
final DatagramChannel ch;
9292

9393
/**
@@ -122,7 +122,6 @@ protected DnsServerAddressStream initialValue() throws Exception {
122122
*
123123
* @param eventLoop the {@link EventLoop} which will perform the communication with the DNS servers
124124
* @param channelFactory the {@link ChannelFactory} that will create a {@link DatagramChannel}
125-
* @param localAddress the local address of the {@link DatagramChannel}
126125
* @param nameServerAddresses the addresses of the DNS server. For each DNS query, a new stream is created from
127126
* this to determine which DNS server should be contacted for the next retry in case
128127
* of failure.
@@ -139,9 +138,8 @@ protected DnsServerAddressStream initialValue() throws Exception {
139138
public DnsNameResolver(
140139
EventLoop eventLoop,
141140
ChannelFactory<? extends DatagramChannel> channelFactory,
142-
InetSocketAddress localAddress,
143141
DnsServerAddresses nameServerAddresses,
144-
DnsCache resolveCache,
142+
final DnsCache resolveCache,
145143
long queryTimeoutMillis,
146144
InternetProtocolFamily[] resolvedAddressTypes,
147145
boolean recursionDesired,
@@ -153,7 +151,6 @@ public DnsNameResolver(
153151

154152
super(eventLoop);
155153
checkNotNull(channelFactory, "channelFactory");
156-
checkNotNull(localAddress, "localAddress");
157154
this.nameServerAddresses = checkNotNull(nameServerAddresses, "nameServerAddresses");
158155
this.queryTimeoutMillis = checkPositive(queryTimeoutMillis, "queryTimeoutMillis");
159156
this.resolvedAddressTypes = checkNonEmpty(resolvedAddressTypes, "resolvedAddressTypes");
@@ -165,34 +162,28 @@ public DnsNameResolver(
165162
this.hostsFileEntriesResolver = checkNotNull(hostsFileEntriesResolver, "hostsFileEntriesResolver");
166163
this.resolveCache = resolveCache;
167164

168-
bindFuture = newChannel(channelFactory, localAddress);
169-
ch = (DatagramChannel) bindFuture.channel();
170-
ch.config().setRecvByteBufAllocator(new FixedRecvByteBufAllocator(maxPayloadSize));
171-
}
172-
173-
private ChannelFuture newChannel(
174-
ChannelFactory<? extends DatagramChannel> channelFactory, InetSocketAddress localAddress) {
175-
176165
Bootstrap b = new Bootstrap();
177166
b.group(executor());
178167
b.channelFactory(channelFactory);
179-
final DnsResponseHandler responseHandler = new DnsResponseHandler();
168+
b.option(ChannelOption.DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION, true);
169+
final DnsResponseHandler responseHandler = new DnsResponseHandler(executor().<Channel>newPromise());
180170
b.handler(new ChannelInitializer<DatagramChannel>() {
181171
@Override
182172
protected void initChannel(DatagramChannel ch) throws Exception {
183173
ch.pipeline().addLast(DECODER, ENCODER, responseHandler);
184174
}
185175
});
186176

187-
ChannelFuture bindFuture = b.bind(localAddress);
188-
bindFuture.channel().closeFuture().addListener(new ChannelFutureListener() {
177+
channelFuture = responseHandler.channelActivePromise;
178+
ch = (DatagramChannel) b.register().channel();
179+
ch.config().setRecvByteBufAllocator(new FixedRecvByteBufAllocator(maxPayloadSize));
180+
181+
ch.closeFuture().addListener(new ChannelFutureListener() {
189182
@Override
190183
public void operationComplete(ChannelFuture future) throws Exception {
191184
resolveCache.clear();
192185
}
193186
});
194-
195-
return bindFuture;
196187
}
197188

198189
/**
@@ -336,7 +327,7 @@ private boolean doResolveCached(String hostname,
336327
Promise<InetAddress> promise,
337328
DnsCache resolveCache) {
338329
final List<DnsCacheEntry> cachedEntries = resolveCache.get(hostname);
339-
if (cachedEntries == null) {
330+
if (cachedEntries == null || cachedEntries.isEmpty()) {
340331
return false;
341332
}
342333

@@ -442,7 +433,7 @@ private boolean doResolveAllCached(String hostname,
442433
Promise<List<InetAddress>> promise,
443434
DnsCache resolveCache) {
444435
final List<DnsCacheEntry> cachedEntries = resolveCache.get(hostname);
445-
if (cachedEntries == null) {
436+
if (cachedEntries == null || cachedEntries.isEmpty()) {
446437
return false;
447438
}
448439

@@ -605,6 +596,13 @@ private static Promise<AddressedEnvelope<DnsResponse, InetSocketAddress>> cast(P
605596
}
606597

607598
private final class DnsResponseHandler extends ChannelInboundHandlerAdapter {
599+
600+
private final Promise<Channel> channelActivePromise;
601+
602+
DnsResponseHandler(Promise<Channel> channelActivePromise) {
603+
this.channelActivePromise = channelActivePromise;
604+
}
605+
608606
@Override
609607
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
610608
try {
@@ -627,6 +625,12 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
627625
}
628626
}
629627

628+
@Override
629+
public void channelActive(ChannelHandlerContext ctx) throws Exception {
630+
super.channelActive(ctx);
631+
channelActivePromise.setSuccess(ctx.channel());
632+
}
633+
630634
@Override
631635
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
632636
logger.warn("{} Unexpected exception: ", ch, cause);

netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverBuilder.java

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package io.netty.resolver.dns;
1717

1818
import static io.netty.util.internal.ObjectUtil2.intValue;
19+
1920
import io.netty.bootstrap.ChannelFactory;
2021
import io.netty.channel.EventLoop;
2122
import io.netty.channel.ReflectiveChannelFactory;
@@ -24,8 +25,6 @@
2425
import io.netty.resolver.HostsFileEntriesResolver;
2526
import io.netty.util.internal.InternalThreadLocalMap;
2627

27-
import java.net.InetSocketAddress;
28-
import java.util.ArrayList;
2928
import java.util.List;
3029

3130
import static io.netty.util.internal.ObjectUtil.checkNotNull;
@@ -37,7 +36,6 @@ public final class DnsNameResolverBuilder {
3736

3837
private final EventLoop eventLoop;
3938
private ChannelFactory<? extends DatagramChannel> channelFactory;
40-
private InetSocketAddress localAddress = DnsNameResolver.ANY_LOCAL_ADDR;
4139
private DnsServerAddresses nameServerAddresses = DnsServerAddresses.defaultAddresses();
4240
private DnsCache resolveCache;
4341
private Integer minTtl;
@@ -46,7 +44,7 @@ public final class DnsNameResolverBuilder {
4644
private long queryTimeoutMillis = 5000;
4745
private InternetProtocolFamily[] resolvedAddressTypes = DnsNameResolver.DEFAULT_RESOLVE_ADDRESS_TYPES;
4846
private boolean recursionDesired = true;
49-
private int maxQueriesPerResolve = 3;
47+
private int maxQueriesPerResolve = 16;
5048
private boolean traceEnabled;
5149
private int maxPayloadSize = 4096;
5250
private boolean optResourceEnabled = true;
@@ -84,17 +82,6 @@ public DnsNameResolverBuilder channelType(Class<? extends DatagramChannel> chann
8482
return channelFactory(new ReflectiveChannelFactory<DatagramChannel>(channelType));
8583
}
8684

87-
/**
88-
* Sets the local address of the {@link DatagramChannel}
89-
*
90-
* @param localAddress the local address
91-
* @return {@code this}
92-
*/
93-
public DnsNameResolverBuilder localAddress(InetSocketAddress localAddress) {
94-
this.localAddress = localAddress;
95-
return this;
96-
}
97-
9885
/**
9986
* Sets the addresses of the DNS server.
10087
*
@@ -170,7 +157,7 @@ public DnsNameResolverBuilder resolvedAddressTypes(InternetProtocolFamily... res
170157
checkNotNull(resolvedAddressTypes, "resolvedAddressTypes");
171158

172159
final List<InternetProtocolFamily> list =
173-
new ArrayList<InternetProtocolFamily>(InternetProtocolFamily.values().length);
160+
InternalThreadLocalMap.get().arrayList(InternetProtocolFamily.values().length);
174161

175162
for (InternetProtocolFamily f : resolvedAddressTypes) {
176163
if (f == null) {
@@ -207,7 +194,7 @@ public DnsNameResolverBuilder resolvedAddressTypes(Iterable<InternetProtocolFami
207194
checkNotNull(resolvedAddressTypes, "resolveAddressTypes");
208195

209196
final List<InternetProtocolFamily> list =
210-
new ArrayList<InternetProtocolFamily>(InternetProtocolFamily.values().length);
197+
InternalThreadLocalMap.get().arrayList(InternetProtocolFamily.values().length);
211198

212199
for (InternetProtocolFamily f : resolvedAddressTypes) {
213200
if (f == null) {
@@ -316,7 +303,6 @@ public DnsNameResolver build() {
316303
return new DnsNameResolver(
317304
eventLoop,
318305
channelFactory,
319-
localAddress,
320306
nameServerAddresses,
321307
cache,
322308
queryTimeoutMillis,

netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsQueryContext.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import io.netty.buffer.Unpooled;
1919
import io.netty.channel.AddressedEnvelope;
20+
import io.netty.channel.Channel;
2021
import io.netty.channel.ChannelFuture;
2122
import io.netty.channel.ChannelFutureListener;
2223
import io.netty.handler.codec.dns.DatagramDnsQuery;
@@ -27,9 +28,10 @@
2728
import io.netty.handler.codec.dns.DnsRecordType;
2829
import io.netty.handler.codec.dns.DnsResponse;
2930
import io.netty.handler.codec.dns.DnsSection;
31+
import io.netty.util.concurrent.Future;
32+
import io.netty.util.concurrent.GenericFutureListener;
3033
import io.netty.util.concurrent.Promise;
3134
import io.netty.util.concurrent.ScheduledFuture;
32-
import io.netty.util.internal.OneTimeTask;
3335
import io.netty.util.internal.StringUtil;
3436
import io.netty.util.internal.logging.InternalLogger;
3537
import io.netty.util.internal.logging.InternalLoggerFactory;
@@ -108,12 +110,12 @@ void query() {
108110
}
109111

110112
private void sendQuery(final DnsQuery query) {
111-
if (parent.bindFuture.isDone()) {
113+
if (parent.channelFuture.isDone()) {
112114
writeQuery(query);
113115
} else {
114-
parent.bindFuture.addListener(new ChannelFutureListener() {
116+
parent.channelFuture.addListener(new GenericFutureListener<Future<? super Channel>>() {
115117
@Override
116-
public void operationComplete(ChannelFuture future) throws Exception {
118+
public void operationComplete(Future<? super Channel> future) throws Exception {
117119
if (future.isSuccess()) {
118120
writeQuery(query);
119121
} else {
@@ -147,7 +149,7 @@ private void onQueryWriteCompletion(ChannelFuture writeFuture) {
147149
// Schedule a query timeout task if necessary.
148150
final long queryTimeoutMillis = parent.queryTimeoutMillis();
149151
if (queryTimeoutMillis > 0) {
150-
timeoutFuture = parent.ch.eventLoop().schedule(new OneTimeTask() {
152+
timeoutFuture = parent.ch.eventLoop().schedule(new Runnable() {
151153
@Override
152154
public void run() {
153155
if (promise.isDone()) {

0 commit comments

Comments
 (0)