Repository: eclipse-vertx/vert.x

Problem statement:
DNS client should support calling a DNS server over IpV6
Step to reproduce:
`vertx.createDnsClient(53, "2001:4860:4860::8888").lookup4("vertx.io", res -> {});
`
=> the result fails with the following exception: 'java.net.SocketException: Address family not supported by protocol'

Expected: The DnsClient should be able to call a Dns server over IpV4 or IpV6

As a sidenote, I also tried using the full IpV6 address "2001:4860:4860:0:0:0:0:8888" but it doesn't work as well.

If time permits, I'll investigate this issue and provide a fix for it



Hints:

Patch:
diff --git a/src/main/java/io/vertx/core/dns/impl/DnsClientImpl.java b/src/main/java/io/vertx/core/dns/impl/DnsClientImpl.java
--- a/src/main/java/io/vertx/core/dns/impl/DnsClientImpl.java
+++ b/src/main/java/io/vertx/core/dns/impl/DnsClientImpl.java
@@ -82,11 +82,14 @@ public DnsClientImpl(VertxInternal vertx, DnsClientOptions options) {
     }
 
     this.dnsServer = new InetSocketAddress(options.getHost(), options.getPort());
+    if (this.dnsServer.isUnresolved()) {
+    	throw new IllegalArgumentException("Cannot resolve the host to a valid ip address");
+    }
     this.vertx = vertx;
 
     Transport transport = vertx.transport();
     actualCtx = vertx.getOrCreateContext();
-    channel = transport.datagramChannel(InternetProtocolFamily.IPv4);
+    channel = transport.datagramChannel(this.dnsServer.getAddress() instanceof Inet4Address ? InternetProtocolFamily.IPv4 : InternetProtocolFamily.IPv6);
     channel.config().setOption(ChannelOption.DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION, true);
     channel.config().setMaxMessagesPerRead(1);
     channel.config().setAllocator(PartialPooledByteBufAllocator.INSTANCE);


Test patch:
diff --git a/src/test/java/io/vertx/test/core/DNSTest.java b/src/test/java/io/vertx/test/core/DNSTest.java
--- a/src/test/java/io/vertx/test/core/DNSTest.java
+++ b/src/test/java/io/vertx/test/core/DNSTest.java
@@ -110,6 +110,36 @@ public void testResolveA() throws Exception {
     dnsServer.stop();
   }
 
+  @Test
+  public void testUnresolvedDnsServer() throws Exception {
+    final String ip = "10.0.0.1";
+    try {
+    	DnsClient dns = vertx.createDnsClient(new DnsClientOptions().setHost("iamanunresolvablednsserver.com").setPort(53));
+    	fail();
+    } catch (Exception e) {
+    	assertTrue(e instanceof IllegalArgumentException);
+    	assertEquals("Cannot resolve the host to a valid ip address", e.getMessage());
+    }
+  }
+  
+  @Test
+  public void testResolveAIpV6() throws Exception {
+    final String ip = "10.0.0.1";
+    // force the fake dns server to Ipv6
+    DnsClient dns = prepareDns(FakeDNSServer.testResolveA(ip).ipAddress("::1"));
+    dns.resolveA("vertx.io", onSuccess(result -> {
+      assertFalse(result.isEmpty());
+      assertEquals(1, result.size());
+      assertEquals(ip, result.get(0));
+      ((DnsClientImpl) dns).inProgressQueries(num -> {
+        assertEquals(0, (int)num);
+        testComplete();
+      });
+    }));
+    await();
+    dnsServer.stop();
+  }
+
   @Test
   public void testResolveAAAA() throws Exception {
     DnsClient dns = prepareDns(FakeDNSServer.testResolveAAAA("::1"));
diff --git a/src/test/java/io/vertx/test/fakedns/FakeDNSServer.java b/src/test/java/io/vertx/test/fakedns/FakeDNSServer.java
--- a/src/test/java/io/vertx/test/fakedns/FakeDNSServer.java
+++ b/src/test/java/io/vertx/test/fakedns/FakeDNSServer.java
@@ -59,7 +59,9 @@ public static RecordStore A_store(Map<String, String> entries) {
   }
 
   public static final int PORT = 53530;
+  public static final String IP_ADDRESS = "127.0.0.1";
 
+  private String ipAddress = IP_ADDRESS;
   private int port = PORT;
   private final RecordStore store;
   private DatagramAcceptor acceptor;
@@ -77,6 +79,11 @@ public InetSocketAddress localAddress() {
     return (InetSocketAddress) getTransports()[0].getAcceptor().getLocalAddress();
   }
 
+  public FakeDNSServer ipAddress(String ipAddress) {
+    this.ipAddress = ipAddress;
+    return this;
+  }
+
   public FakeDNSServer port(int p) {
     port = p;
     return this;
@@ -325,7 +332,7 @@ public Set<ResourceRecord> getRecords(QuestionRecord questionRecord)
 
   @Override
   public void start() throws IOException {
-    UdpTransport transport = new UdpTransport("127.0.0.1", port);
+    UdpTransport transport = new UdpTransport(ipAddress, port);
     setTransports( transport );
 
     acceptor = transport.getAcceptor();