下面列出了 io.netty.handler.codec.dns.DnsRawRecord #io.netty.handler.codec.dns.DefaultDnsQuestion 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Test
void removedWhenNoCacheHit() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("foo.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "1.1.1.1", 1))))
) {
final EventLoop eventLoop = eventLoopExtension.get();
final DnsResolverGroupBuilder builder = builder(server);
try (RefreshingAddressResolverGroup group = builder.build(eventLoop)) {
final AddressResolver<InetSocketAddress> resolver = group.getResolver(eventLoop);
final long start = System.nanoTime();
final Future<InetSocketAddress> foo = resolver.resolve(
InetSocketAddress.createUnresolved("foo.com", 36462));
await().untilAsserted(() -> assertThat(foo.isSuccess()).isTrue());
assertThat(foo.getNow().getAddress().getHostAddress()).isEqualTo("1.1.1.1");
final ConcurrentMap<String, CompletableFuture<CacheEntry>> cache = group.cache();
await().until(cache::isEmpty);
assertThat(System.nanoTime() - start).isGreaterThanOrEqualTo(
(long) (TimeUnit.SECONDS.toNanos(1) * 0.9));
}
}
}
@Test
void cacheClearWhenClosed() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("foo.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "1.1.1.1"))))
) {
final EventLoop eventLoop = eventLoopExtension.get();
final RefreshingAddressResolverGroup group = builder(server).build(eventLoop);
final AddressResolver<InetSocketAddress> resolver = group.getResolver(eventLoop);
final Future<InetSocketAddress> foo = resolver.resolve(
InetSocketAddress.createUnresolved("foo.com", 36462));
await().untilAsserted(() -> assertThat(foo.isSuccess()).isTrue());
assertThat(foo.getNow().getAddress().getHostAddress()).isEqualTo("1.1.1.1");
final ConcurrentMap<String, CompletableFuture<CacheEntry>> cache = group.cache();
assertThat(cache.size()).isEqualTo(1);
final CacheEntry cacheEntry = cache.get("foo.com").join();
group.close();
await().until(() -> {
final ScheduledFuture<?> future = cacheEntry.refreshFuture;
return future != null && future.isCancelled();
});
assertThat(cache).isEmpty();
}
}
@Test
void timeout() {
try (TestDnsServer server1 = new TestDnsServer(ImmutableMap.of(), new TimeoutHandler());
TestDnsServer server2 = new TestDnsServer(ImmutableMap.of(), new TimeoutHandler());
TestDnsServer server3 = new TestDnsServer(ImmutableMap.of(), new TimeoutHandler());
TestDnsServer server4 = new TestDnsServer(ImmutableMap.of(), new TimeoutHandler());
TestDnsServer server5 = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("foo.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "1.1.1.1"))))) {
final DnsResolverGroupBuilder builder = builder(server1, server2, server3, server4, server5)
.negativeTtl(60)
.queryTimeoutMillis(1000);
final ClientFactory factory =
ClientFactory.builder().addressResolverGroupFactory(builder::build).build();
final WebClient client = WebClient.builder("http://foo.com").factory(factory).build();
assertThatThrownBy(() -> client.get("/").aggregate().join())
.hasCauseInstanceOf(UnprocessedRequestException.class)
.hasRootCauseExactlyInstanceOf(DnsTimeoutException.class);
}
}
@Test
void returnPartialDnsQuestions() throws Exception {
// Returns IPv6 correctly and make IPv4 timeout.
try (TestDnsServer server = new TestDnsServer(
ImmutableMap.of(
new DefaultDnsQuestion("foo.com.", AAAA),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "::1", 1))))
) {
final EventLoop eventLoop = eventLoopExtension.get();
final DnsResolverGroupBuilder builder = builder(server)
.queryTimeoutMillis(1000)
.resolvedAddressTypes(ResolvedAddressTypes.IPV4_PREFERRED);
try (RefreshingAddressResolverGroup group = builder.build(eventLoop)) {
final AddressResolver<InetSocketAddress> resolver = group.getResolver(eventLoop);
final Future<InetSocketAddress> future = resolver.resolve(
InetSocketAddress.createUnresolved("foo.com", 36462));
await().until(future::isDone);
assertThat(future.getNow().getAddress().getHostAddress()).isEqualTo("0:0:0:0:0:0:0:1");
}
}
}
@Test
void preferredOrderIpv4() throws Exception {
try (TestDnsServer server = new TestDnsServer(
ImmutableMap.of(
new DefaultDnsQuestion("foo.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "1.1.1.1")),
new DefaultDnsQuestion("foo.com.", AAAA),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "::1", 1))),
new DelayHandler(A))
) {
final EventLoop eventLoop = eventLoopExtension.get();
final DnsResolverGroupBuilder builder = builder(server)
.resolvedAddressTypes(ResolvedAddressTypes.IPV4_PREFERRED);
try (RefreshingAddressResolverGroup group = builder.build(eventLoop)) {
final AddressResolver<InetSocketAddress> resolver = group.getResolver(eventLoop);
final Future<InetSocketAddress> future = resolver.resolve(
InetSocketAddress.createUnresolved("foo.com", 36462));
await().until(future::isSuccess);
assertThat(future.getNow().getAddress().getHostAddress()).isEqualTo("1.1.1.1");
}
}
}
@Test
void preferredOrderIpv6() throws Exception {
try (TestDnsServer server = new TestDnsServer(
ImmutableMap.of(
new DefaultDnsQuestion("foo.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "1.1.1.1")),
new DefaultDnsQuestion("foo.com.", AAAA),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "::1", 1))),
new DelayHandler(AAAA))
) {
final EventLoop eventLoop = eventLoopExtension.get();
final DnsResolverGroupBuilder builder = builder(server)
.resolvedAddressTypes(ResolvedAddressTypes.IPV6_PREFERRED);
try (RefreshingAddressResolverGroup group = builder.build(eventLoop)) {
final AddressResolver<InetSocketAddress> resolver = group.getResolver(eventLoop);
final Future<InetSocketAddress> future = resolver.resolve(
InetSocketAddress.createUnresolved("foo.com", 36462));
await().until(future::isSuccess);
assertThat(future.getNow().getAddress().getHostAddress()).isEqualTo("0:0:0:0:0:0:0:1");
}
}
}
@Test
public void srv() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("foo.com.", SRV),
new DefaultDnsResponse(0).addRecord(ANSWER, newSrvRecord("foo.com.", 1, 2, "a.foo.com."))
.addRecord(ANSWER, newSrvRecord("foo.com.", 3, 4, "b.foo.com."))
.addRecord(ANSWER, newSrvRecord("unrelated.com.", 0, 0, "asdf.com."))
.addRecord(ANSWER, newTooShortSrvRecord("foo.com."))
.addRecord(ANSWER, newBadNameSrvRecord("foo.com."))
))) {
try (DnsServiceEndpointGroup group =
DnsServiceEndpointGroup.builder("foo.com")
.serverAddresses(server.addr())
.build()) {
assertThat(group.whenReady().get()).containsExactly(
Endpoint.of("a.foo.com", 2).withWeight(1),
Endpoint.of("b.foo.com", 4).withWeight(3));
}
}
}
@Test
public void cname() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("bar.com.", SRV),
new DefaultDnsResponse(0).addRecord(ANSWER, newCnameRecord("bar.com.", "baz.com."))
.addRecord(ANSWER, newSrvRecord("baz.com.", 5, 6, "c.baz.com."))
))) {
try (DnsServiceEndpointGroup group =
DnsServiceEndpointGroup.builder("bar.com")
.serverAddresses(server.addr())
.build()) {
assertThat(group.whenReady().get()).containsExactly(
Endpoint.of("c.baz.com", 6).withWeight(5));
}
}
}
@Test
public void ipV4Only() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("foo.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "1.1.1.1"))
.addRecord(ANSWER, newAddressRecord("unrelated.com", "1.2.3.4")),
new DefaultDnsQuestion("foo.com.", AAAA),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "::1"))
))) {
try (DnsAddressEndpointGroup group =
DnsAddressEndpointGroup.builder("foo.com")
.port(8080)
.serverAddresses(server.addr())
.resolvedAddressTypes(ResolvedAddressTypes.IPV4_ONLY)
.build()) {
assertThat(group.whenReady().get()).containsExactly(
Endpoint.of("foo.com", 8080).withIpAddr("1.1.1.1"));
}
}
}
@Test
public void ipV6Only() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("bar.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("bar.com.", "1.1.1.1")),
new DefaultDnsQuestion("bar.com.", AAAA),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("bar.com.", "::1"))
.addRecord(ANSWER, newAddressRecord("bar.com.", "::1234:5678:90ab"))
.addRecord(ANSWER, newAddressRecord("bar.com.",
"2404:6800:4004:806::2013"))
))) {
try (DnsAddressEndpointGroup group =
DnsAddressEndpointGroup.builder("bar.com")
.port(8080)
.serverAddresses(server.addr())
.resolvedAddressTypes(ResolvedAddressTypes.IPV6_ONLY)
.build()) {
assertThat(group.whenReady().get(10, TimeUnit.SECONDS)).containsExactly(
Endpoint.of("bar.com", 8080).withIpAddr("2404:6800:4004:806::2013"),
Endpoint.of("bar.com", 8080).withIpAddr("::1"),
Endpoint.of("bar.com", 8080).withIpAddr("::1234:5678:90ab"));
}
}
}
@Test
public void ipV4AndIpV6() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("baz.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("baz.com.", "1.1.1.1")),
new DefaultDnsQuestion("baz.com.", AAAA),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("baz.com.", "::1"))
))) {
try (DnsAddressEndpointGroup group =
DnsAddressEndpointGroup.builder("baz.com")
.port(8080)
.serverAddresses(server.addr())
.resolvedAddressTypes(ResolvedAddressTypes.IPV4_PREFERRED)
.build()) {
assertThat(group.whenReady().get()).containsExactly(
Endpoint.of("baz.com", 8080).withIpAddr("1.1.1.1"),
Endpoint.of("baz.com", 8080).withIpAddr("::1"));
}
}
}
@Test
public void platformDefault() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("baz.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("baz.com.", "1.1.1.1")),
new DefaultDnsQuestion("baz.com.", AAAA),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("baz.com.", "::1"))
))) {
try (DnsAddressEndpointGroup group =
DnsAddressEndpointGroup.builder("baz.com")
.port(8080)
.serverAddresses(server.addr())
.build()) {
assertThat(group.whenReady().get()).contains(
Endpoint.of("baz.com", 8080).withIpAddr("1.1.1.1"));
}
}
}
@Test
public void cname() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("a.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newBadAddressRecord("a.com.", true))
.addRecord(ANSWER, newCnameRecord("a.com.", "b.com."))
.addRecord(ANSWER, newAddressRecord("b.com.", "1.1.1.1")),
new DefaultDnsQuestion("a.com.", AAAA),
new DefaultDnsResponse(0).addRecord(ANSWER, newBadAddressRecord("a.com.", false))
.addRecord(ANSWER, newCnameRecord("a.com.", "b.com."))
.addRecord(ANSWER, newAddressRecord("b.com.", "::1"))
))) {
try (DnsAddressEndpointGroup group =
DnsAddressEndpointGroup.builder("a.com")
.port(8080)
.serverAddresses(server.addr())
.resolvedAddressTypes(ResolvedAddressTypes.IPV4_PREFERRED)
.build()) {
assertThat(group.whenReady().get()).containsExactly(
Endpoint.of("a.com", 8080).withIpAddr("1.1.1.1"),
Endpoint.of("a.com", 8080).withIpAddr("::1"));
}
}
}
@Test
public void mixedLoopbackAddresses() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("foo.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "127.0.0.1")),
new DefaultDnsQuestion("foo.com.", AAAA),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "::1"))
))) {
try (DnsAddressEndpointGroup group =
DnsAddressEndpointGroup.builder("foo.com")
.port(8080)
.serverAddresses(server.addr())
.resolvedAddressTypes(ResolvedAddressTypes.IPV4_PREFERRED)
.build()) {
assertThat(group.whenReady().get()).containsExactly(
Endpoint.of("foo.com", 8080).withIpAddr("127.0.0.1"));
}
}
}
@Test
public void ipV4MappedOrCompatibleAddresses() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("bar.com.", AAAA),
new DefaultDnsResponse(0).addRecord(ANSWER, newCompatibleAddressRecord("bar.com.", "1.1.1.1"))
.addRecord(ANSWER, newCompatibleAddressRecord("bar.com.", "1.1.1.2"))
.addRecord(ANSWER, newMappedAddressRecord("bar.com.", "1.1.1.1"))
.addRecord(ANSWER, newMappedAddressRecord("bar.com.", "1.1.1.3"))
))) {
try (DnsAddressEndpointGroup group =
DnsAddressEndpointGroup.builder("bar.com")
.port(8080)
.serverAddresses(server.addr())
.resolvedAddressTypes(ResolvedAddressTypes.IPV6_ONLY)
.build()) {
assertThat(group.whenReady().get()).containsExactly(
Endpoint.of("bar.com", 8080).withIpAddr("1.1.1.1"),
Endpoint.of("bar.com", 8080).withIpAddr("1.1.1.2"),
Endpoint.of("bar.com", 8080).withIpAddr("1.1.1.3"));
}
}
}
@Test
public void noPort() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("no-port.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("no-port.com", "1.1.1.1"))
))) {
try (DnsAddressEndpointGroup group =
DnsAddressEndpointGroup.builder("no-port.com")
.serverAddresses(server.addr())
.resolvedAddressTypes(ResolvedAddressTypes.IPV4_ONLY)
.build()) {
assertThat(group.whenReady().get()).containsExactly(
Endpoint.of("no-port.com").withIpAddr("1.1.1.1"));
}
}
}
@EnumSource(value = ResolvedAddressTypes.class, names = { "IPV4_PREFERRED", "IPV6_PREFERRED" })
@ParameterizedTest
public void partialIpV4Response(ResolvedAddressTypes resolvedAddressTypes) throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
// Respond A record only.
// Respond with NXDOMAIN for AAAA.
new DefaultDnsQuestion("partial.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("partial.com", "1.1.1.1"))
))) {
try (DnsAddressEndpointGroup group =
DnsAddressEndpointGroup.builder("partial.com")
.serverAddresses(server.addr())
.resolvedAddressTypes(resolvedAddressTypes)
.backoff(Backoff.fixed(500))
.build()) {
assertThat(group.whenReady().get()).containsExactly(
Endpoint.of("partial.com").withIpAddr("1.1.1.1"));
}
}
}
@EnumSource(value = ResolvedAddressTypes.class, names = { "IPV4_PREFERRED", "IPV6_PREFERRED" })
@ParameterizedTest
public void partialIpV6Response(ResolvedAddressTypes resolvedAddressTypes) throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
// Respond AAAA record only.
// Respond with NXDOMAIN for A.
new DefaultDnsQuestion("partial.com.", AAAA),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("partial.com", "::1"))
))) {
try (DnsAddressEndpointGroup group =
DnsAddressEndpointGroup.builder("partial.com")
.serverAddresses(server.addr())
.resolvedAddressTypes(resolvedAddressTypes)
.backoff(Backoff.fixed(500))
.build()) {
assertThat(group.whenReady().get()).containsExactly(
Endpoint.of("partial.com").withIpAddr("::1"));
}
}
}
private static DnsQuestion newQuestion(String hostname, DnsRecordType type) {
try {
return new DefaultDnsQuestion(hostname, type);
} catch (IllegalArgumentException e) {
// java.net.IDN.toASCII(...) may throw an IllegalArgumentException if it fails to parse the hostname
return null;
}
}
@Test
void refreshing() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("baz.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("baz.com.", "1.1.1.1", 1))))
) {
final EventLoop eventLoop = eventLoopExtension.get();
try (RefreshingAddressResolverGroup group = builder(server).build(eventLoop)) {
final AddressResolver<InetSocketAddress> resolver = group.getResolver(eventLoop);
final long start = System.nanoTime();
final Future<InetSocketAddress> foo = resolver.resolve(
InetSocketAddress.createUnresolved("baz.com", 36462));
await().untilAsserted(() -> assertThat(foo.isSuccess()).isTrue());
assertThat(foo.getNow().getAddress().getHostAddress()).isEqualTo("1.1.1.1");
final ConcurrentMap<String, CompletableFuture<CacheEntry>> cache = group.cache();
assertThat(cache.size()).isOne();
assertThat(cache.get("baz.com").join().address()).isEqualTo(
InetAddress.getByAddress("baz.com", new byte[] { 1, 1, 1, 1 }));
// Resolve one more to increase cache hits.
resolver.resolve(InetSocketAddress.createUnresolved("baz.com", 36462));
server.setResponses(ImmutableMap.of(
new DefaultDnsQuestion("baz.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("baz.com.", "2.2.2.2"))));
await().until(() -> {
final CompletableFuture<CacheEntry> future = cache.get("baz.com");
return future != null && future.join().address().equals(
InetAddress.getByAddress("baz.com", new byte[] { 2, 2, 2, 2 }));
});
assertThat(System.nanoTime() - start).isGreaterThanOrEqualTo(
(long) (TimeUnit.SECONDS.toNanos(1) * 0.9)); // ttl 2 seconds * buffer (90%)
}
}
}
@Test
public void txt() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("foo.com.", TXT),
new DefaultDnsResponse(0).addRecord(ANSWER, newTxtRecord("foo.com.", "endpoint=a.foo.com"))
.addRecord(ANSWER, newTxtRecord("foo.com.", "endpoint=b.foo.com"))
.addRecord(ANSWER, newTxtRecord("unrelated.com.", "endpoint=c.com"))
.addRecord(ANSWER, newTooShortTxtRecord("foo.com."))
.addRecord(ANSWER, newTooLongTxtRecord("foo.com."))
.addRecord(ANSWER, newTxtRecord("foo.com.", "unrelated_txt"))
.addRecord(ANSWER, newTxtRecord("foo.com.", "endpoint=group:foo"))
.addRecord(ANSWER, newTxtRecord("foo.com.", "endpoint=b:a:d"))
))) {
try (DnsTextEndpointGroup group = DnsTextEndpointGroup.builder("foo.com", txt -> {
final String txtStr = new String(txt, StandardCharsets.US_ASCII);
if (txtStr.startsWith("endpoint=")) {
return Endpoint.parse(txtStr.substring(9));
} else {
return null;
}
}).serverAddresses(server.addr()).build()) {
assertThat(group.whenReady().get()).containsExactly(
Endpoint.of("a.foo.com"),
Endpoint.of("b.foo.com"));
}
}
}
@Test
public void noPort() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("no-port.com.", SRV),
new DefaultDnsResponse(0).addRecord(ANSWER, newSrvRecord("no-port.com.", 7, 0, "d.no-port.com"))
))) {
try (DnsServiceEndpointGroup group =
DnsServiceEndpointGroup.builder("no-port.com")
.serverAddresses(server.addr()).build()) {
assertThat(group.whenReady().get()).containsExactly(
Endpoint.of("d.no-port.com"));
}
}
}
@Test
public void backoff() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of())) { // Respond nothing.
try (DnsAddressEndpointGroup group =
DnsAddressEndpointGroup.builder("backoff.com")
.serverAddresses(server.addr())
.resolvedAddressTypes(ResolvedAddressTypes.IPV4_PREFERRED)
.backoff(Backoff.fixed(500))
.build()) {
await().untilAsserted(() -> assertThat(group.attemptsSoFar).isGreaterThan(2));
assertThat(group.endpoints()).isEmpty();
// Start to respond correctly.
server.setResponses(ImmutableMap.of(
new DefaultDnsQuestion("backoff.com.", A),
new DefaultDnsResponse(0)
.addRecord(ANSWER, newAddressRecord("backoff.com", "1.1.1.1", 1)),
new DefaultDnsQuestion("backoff.com.", AAAA),
new DefaultDnsResponse(0)
.addRecord(ANSWER, newAddressRecord("backoff.com", "::1", 1))));
await().untilAsserted(() -> assertThat(group.endpoints()).containsExactly(
Endpoint.of("backoff.com").withIpAddr("1.1.1.1"),
Endpoint.of("backoff.com").withIpAddr("::1")));
}
}
}
@Test
public void backoffOnEmptyResponse() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
// Respond with empty records.
new DefaultDnsQuestion("empty.com.", A), new DefaultDnsResponse(0),
new DefaultDnsQuestion("empty.com.", AAAA), new DefaultDnsResponse(0)
))) {
try (DnsAddressEndpointGroup group =
DnsAddressEndpointGroup.builder("empty.com")
.serverAddresses(server.addr())
.resolvedAddressTypes(ResolvedAddressTypes.IPV4_PREFERRED)
.backoff(Backoff.fixed(500))
.build()) {
await().untilAsserted(() -> assertThat(group.attemptsSoFar).isGreaterThan(2));
assertThat(group.endpoints()).isEmpty();
// Start to respond correctly.
server.setResponses(ImmutableMap.of(
new DefaultDnsQuestion("empty.com.", A),
new DefaultDnsResponse(0)
.addRecord(ANSWER, newAddressRecord("empty.com", "1.1.1.1", 1)),
new DefaultDnsQuestion("empty.com.", AAAA),
new DefaultDnsResponse(0)
.addRecord(ANSWER, newAddressRecord("empty.com", "::1", 1))));
await().untilAsserted(() -> assertThat(group.endpoints()).containsExactly(
Endpoint.of("empty.com").withIpAddr("1.1.1.1"),
Endpoint.of("empty.com").withIpAddr("::1")));
}
}
}
private static void queryMx(
DnsNameResolver resolver,
Map<String, Future<AddressedEnvelope<DnsResponse, InetSocketAddress>>> futures,
String hostname) throws Exception {
futures.put(hostname, resolver.query(new DefaultDnsQuestion(hostname, DnsRecordType.MX)));
}
@Test
void resolve() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("foo.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "1.1.1.1")),
new DefaultDnsQuestion("bar.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("bar.com.", "1.2.3.4"))))
) {
final EventLoop eventLoop = eventLoopExtension.get();
try (RefreshingAddressResolverGroup group = builder(server).build(eventLoop)) {
final AddressResolver<InetSocketAddress> resolver = group.getResolver(eventLoop);
final Future<InetSocketAddress> foo = resolver.resolve(
InetSocketAddress.createUnresolved("foo.com", 36462));
await().untilAsserted(() -> assertThat(foo.isSuccess()).isTrue());
InetSocketAddress addr = foo.getNow();
assertThat(addr.getAddress().getHostAddress()).isEqualTo("1.1.1.1");
assertThat(addr.getPort()).isEqualTo(36462);
final ConcurrentMap<String, CompletableFuture<CacheEntry>> cache = group.cache();
assertThat(cache.size()).isOne();
final Future<InetSocketAddress> bar = resolver.resolve(
InetSocketAddress.createUnresolved("bar.com", 36462));
await().untilAsserted(() -> assertThat(bar.isSuccess()).isTrue());
addr = bar.getNow();
assertThat(addr.getAddress().getHostAddress()).isEqualTo("1.2.3.4");
assertThat(addr.getPort()).isEqualTo(36462);
assertThat(cache.size()).isEqualTo(2);
final Future<InetSocketAddress> foo1 = resolver.resolve(
InetSocketAddress.createUnresolved("foo.com", 80));
addr = foo1.getNow();
assertThat(addr.getAddress().getHostAddress()).isEqualTo("1.1.1.1");
assertThat(addr.getPort()).isEqualTo(80);
assertThat(cache.size()).isEqualTo(2);
final List<InetAddress> addresses =
cache.values()
.stream()
.map(future -> future.join().address())
.collect(toImmutableList());
assertThat(addresses).containsExactlyInAnyOrder(
InetAddress.getByAddress("foo.com", new byte[] { 1, 1, 1, 1 }),
InetAddress.getByAddress("bar.com", new byte[] { 1, 2, 3, 4 }));
}
}
}
@Test
void removedWhenExceedingBackoffMaxAttempts() throws Exception {
try (TestDnsServer server = new TestDnsServer(ImmutableMap.of(
new DefaultDnsQuestion("foo.com.", A),
new DefaultDnsResponse(0).addRecord(ANSWER, newAddressRecord("foo.com.", "1.1.1.1", 1))))
) {
final EventLoop eventLoop = eventLoopExtension.get();
final DnsResolverGroupBuilder builder = builder(server);
builder.refreshBackoff(Backoff.ofDefault().withMaxAttempts(1));
try (RefreshingAddressResolverGroup group = builder.build(eventLoop)) {
final AddressResolver<InetSocketAddress> resolver = group.getResolver(eventLoop);
final long start = System.nanoTime();
final Future<InetSocketAddress> foo = resolver.resolve(
InetSocketAddress.createUnresolved("foo.com", 36462));
await().untilAsserted(() -> assertThat(foo.isSuccess()).isTrue());
assertThat(foo.getNow().getAddress().getHostAddress()).isEqualTo("1.1.1.1");
server.setResponses(ImmutableMap.of());
// Schedule resolve() every 500 millis to keep cache hits greater than 0.
for (int i = 1; i <= 4; i++) {
eventLoop.schedule(
() -> resolver.resolve(InetSocketAddress.createUnresolved("foo.com", 36462)),
500 * i, TimeUnit.MILLISECONDS);
}
final ConcurrentMap<String, CompletableFuture<CacheEntry>> cache = group.cache();
await().until(cache::isEmpty);
assertThat(System.nanoTime() - start).isGreaterThanOrEqualTo(
(long) (TimeUnit.SECONDS.toNanos(1) * 0.9)); // buffer (90%)
final Future<InetSocketAddress> future = resolver.resolve(
InetSocketAddress.createUnresolved("foo.com", 36462));
await().until(future::isDone);
assertThat(future.cause()).isInstanceOf(UnknownHostException.class);
}
}
}
private void resolveAddress() {
boolean debug = getFlag(BuiltinFlags.PRINT_DEBUG, false);
String name = this.getPacketProtocol().getSRVRecordPrefix() + "._tcp." + this.getHost();
if(debug) {
System.out.println("[PacketLib] Attempting SRV lookup for \"" + name + "\".");
}
AddressedEnvelope<DnsResponse, InetSocketAddress> envelope = null;
try(DnsNameResolver resolver = new DnsNameResolverBuilder(this.group.next())
.channelType(NioDatagramChannel.class)
.build()) {
envelope = resolver.query(new DefaultDnsQuestion(name, DnsRecordType.SRV)).get();
DnsResponse response = envelope.content();
if(response.count(DnsSection.ANSWER) > 0) {
DefaultDnsRawRecord record = response.recordAt(DnsSection.ANSWER, 0);
if(record.type() == DnsRecordType.SRV) {
ByteBuf buf = record.content();
buf.skipBytes(4); // Skip priority and weight.
int port = buf.readUnsignedShort();
String host = DefaultDnsRecordDecoder.decodeName(buf);
if(host.endsWith(".")) {
host = host.substring(0, host.length() - 1);
}
if(debug) {
System.out.println("[PacketLib] Found SRV record containing \"" + host + ":" + port + "\".");
}
this.host = host;
this.port = port;
} else if(debug) {
System.out.println("[PacketLib] Received non-SRV record in response.");
}
} else if(debug) {
System.out.println("[PacketLib] No SRV record found.");
}
} catch(Exception e) {
if(debug) {
System.out.println("[PacketLib] Failed to resolve SRV record.");
e.printStackTrace();
}
} finally {
if(envelope != null) {
envelope.release();
}
}
}
private List<DnsRecord> lookupRecords() throws InterruptedException, ExecutionException, TimeoutException {
return resolver.resolveAll(new DefaultDnsQuestion(query, DnsRecordType.SRV), Collections.emptyList())
.get(resolveTimeout.getMillis(), TimeUnit.MILLISECONDS);
}