DnsNameResolver.resolveAll(...) should not include duplicates (#9021)
Motivation: DnsNameResolver#resolveAll(String) may return duplicate results in the event that the original hostname DNS response includes an IP address X and a CNAME that ends up resolving the same IP address X. This behavior is inconsistent with the JDK’s resolver and is unexpected to retrun a List with duplicate entries from a resolveAll(..) call. Modifications: - Filter out duplicates - Add unit test Result: More consistent and less suprising behavior
This commit is contained in:
parent
4eeaa4f956
commit
4bd068edf0
@ -686,10 +686,17 @@ abstract class DnsResolveContext<T> {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We want to ensure we do not have duplicates in finalResult as this may be unexpected.
|
||||
//
|
||||
// While using a LinkedHashSet or HashSet may sound like the perfect fit for this we will use an
|
||||
// ArrayList here as duplicates should be found quite unfrequently in the wild and we dont want to pay
|
||||
// for the extra memory copy and allocations in this cases later on.
|
||||
if (finalResult == null) {
|
||||
finalResult = new ArrayList<>(8);
|
||||
finalResult.add(converted);
|
||||
} else if (!finalResult.contains(converted)) {
|
||||
finalResult.add(converted);
|
||||
}
|
||||
finalResult.add(converted);
|
||||
|
||||
cache(hostname, additionals, r, converted);
|
||||
found = true;
|
||||
|
@ -2504,4 +2504,50 @@ public class DnsNameResolverTest {
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotIncludeDuplicates() throws IOException {
|
||||
final String name = "netty.io";
|
||||
final String ipv4Addr = "1.2.3.4";
|
||||
TestDnsServer dnsServer2 = new TestDnsServer(new RecordStore() {
|
||||
@Override
|
||||
public Set<ResourceRecord> getRecords(QuestionRecord question) {
|
||||
Set<ResourceRecord> records = new LinkedHashSet<ResourceRecord>(4);
|
||||
String qName = question.getDomainName().toLowerCase();
|
||||
if (qName.equals(name)) {
|
||||
records.add(new TestDnsServer.TestResourceRecord(
|
||||
qName, RecordType.CNAME,
|
||||
Collections.<String, Object>singletonMap(
|
||||
DnsAttribute.DOMAIN_NAME.toLowerCase(), "cname.netty.io")));
|
||||
records.add(new TestDnsServer.TestResourceRecord(qName,
|
||||
RecordType.A, Collections.<String, Object>singletonMap(
|
||||
DnsAttribute.IP_ADDRESS.toLowerCase(), ipv4Addr)));
|
||||
} else {
|
||||
records.add(new TestDnsServer.TestResourceRecord(qName,
|
||||
RecordType.A, Collections.<String, Object>singletonMap(
|
||||
DnsAttribute.IP_ADDRESS.toLowerCase(), ipv4Addr)));
|
||||
}
|
||||
return records;
|
||||
}
|
||||
});
|
||||
dnsServer2.start();
|
||||
DnsNameResolver resolver = null;
|
||||
try {
|
||||
DnsNameResolverBuilder builder = newResolver()
|
||||
.recursionDesired(true)
|
||||
.maxQueriesPerResolve(16)
|
||||
.nameServerProvider(new SingletonDnsServerAddressStreamProvider(dnsServer2.localAddress()));
|
||||
builder.resolvedAddressTypes(ResolvedAddressTypes.IPV4_ONLY);
|
||||
|
||||
resolver = builder.build();
|
||||
List<InetAddress> resolvedAddresses = resolver.resolveAll(name).syncUninterruptibly().getNow();
|
||||
assertEquals(Collections.singletonList(InetAddress.getByAddress(name, new byte[] { 1, 2, 3, 4 })),
|
||||
resolvedAddresses);
|
||||
} finally {
|
||||
dnsServer2.stop();
|
||||
if (resolver != null) {
|
||||
resolver.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user