diff --git a/src/main/java/io/nats/client/impl/SocketDataPort.java b/src/main/java/io/nats/client/impl/SocketDataPort.java index f3f546665..cd6ac2fc3 100644 --- a/src/main/java/io/nats/client/impl/SocketDataPort.java +++ b/src/main/java/io/nats/client/impl/SocketDataPort.java @@ -23,12 +23,14 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketException; -import java.net.URISyntaxException; +import java.net.*; import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import static io.nats.client.support.NatsConstants.SECURE_WEBSOCKET_PROTOCOL; @@ -81,7 +83,7 @@ public void connect(NatsConnection conn, NatsUri nuri, long timeoutNanos) throws socket.setTcpNoDelay(true); socket.setReceiveBufferSize(2 * 1024 * 1024); socket.setSendBufferSize(2 * 1024 * 1024); - socket.connect(new InetSocketAddress(host, port), (int) timeout); + socket.connect(new InetSocketAddress(getIpV4Addresses(nuri).get(0).getHost(), port), (int) timeout); if (soLinger > -1) { socket.setSoLinger(true, soLinger); } @@ -113,6 +115,39 @@ public void connect(NatsConnection conn, NatsUri nuri, long timeoutNanos) throws } } + private List getIpV4Addresses(NatsUri nuri) { + if (nuri.hostIsIpAddress()) { + return Arrays.asList(nuri); + } + try { + InetAddress[] addresses = InetAddress.getAllByName(nuri.getHost()); + return filterIpv6Address(Arrays.asList(addresses), nuri); + } catch (UnknownHostException e) { + System.out.println(String.format("[WARN] Ignoring Address %s as Error in resolving host: %s", nuri.getHost(), e.getMessage())); + } + return Arrays.asList(nuri); + } + + + private List filterIpv6Address(List inetAddresses, NatsUri nuri) { + List natsUris = new ArrayList<>(); + for (InetAddress addr : inetAddresses) { + try { + if (addr instanceof Inet6Address) { + continue; + } + natsUris.add(nuri.reHost(addr.getHostAddress())); + } catch (URISyntaxException e) { + System.out.println(String.format("[WARN] Ignoring Address %s as Error in while rehostToNri: %s", nuri.getHost(), e.getMessage())); + } + } + if (natsUris.size() < 1) { + natsUris.add(nuri); + } + Collections.shuffle(natsUris, ThreadLocalRandom.current()); + return natsUris; + } + /** * Upgrade the port to SSL. If it is already secured, this is a no-op. * If the data port type doesn't support SSL it should throw an exception.