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
8f7ef1cabb
commit
e63c596f24
@ -695,10 +695,17 @@ abstract class DnsResolveContext<T> {
|
|||||||
continue;
|
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) {
|
if (finalResult == null) {
|
||||||
finalResult = new ArrayList<T>(8);
|
finalResult = new ArrayList<T>(8);
|
||||||
|
finalResult.add(converted);
|
||||||
|
} else if (!finalResult.contains(converted)) {
|
||||||
|
finalResult.add(converted);
|
||||||
}
|
}
|
||||||
finalResult.add(converted);
|
|
||||||
|
|
||||||
cache(hostname, additionals, r, converted);
|
cache(hostname, additionals, r, converted);
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -2539,4 +2539,50 @@ public class DnsNameResolverTest {
|
|||||||
}
|
}
|
||||||
return list;
|
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