ConnectionUtils { public static InetAddress findConnectingAddress(InetSocketAddress targetAddress, long maxWaitMillis, long startLoggingAfter) throws IOException { if (targetAddress == null) { throw new NullPointerException("targetAddress must not be null"); } if (maxWaitMillis <= 0) { throw new IllegalArgumentException("Max wait time must be positive"); } final long startTimeNanos = System.nanoTime(); long currentSleepTime = MIN_SLEEP_TIME; long elapsedTimeMillis = 0; final List<AddressDetectionState> strategies = Collections.unmodifiableList( Arrays.asList( AddressDetectionState.LOCAL_HOST, AddressDetectionState.ADDRESS, AddressDetectionState.FAST_CONNECT, AddressDetectionState.SLOW_CONNECT)); while (elapsedTimeMillis < maxWaitMillis) { boolean logging = elapsedTimeMillis >= startLoggingAfter; if (logging) { LOG.info("Trying to connect to " + targetAddress); } for (AddressDetectionState strategy : strategies) { InetAddress address = findAddressUsingStrategy(strategy, targetAddress, logging); if (address != null) { return address; } } elapsedTimeMillis = (System.nanoTime() - startTimeNanos) / 1_000_000; long toWait = Math.min(maxWaitMillis - elapsedTimeMillis, currentSleepTime); if (toWait > 0) { if (logging) { LOG.info("Could not connect. Waiting for {} msecs before next attempt", toWait); } else { LOG.debug("Could not connect. Waiting for {} msecs before next attempt", toWait); } try { Thread.sleep(toWait); } catch (InterruptedException e) { throw new IOException("Connection attempts have been interrupted."); } } currentSleepTime = Math.min(2 * currentSleepTime, MAX_SLEEP_TIME); } LOG.warn("Could not connect to {}. Selecting a local address using heuristics.", targetAddress); InetAddress heuristic = findAddressUsingStrategy(AddressDetectionState.HEURISTIC, targetAddress, true); if (heuristic != null) { return heuristic; } else { LOG.warn("Could not find any IPv4 address that is not loopback or link-local. Using localhost address."); return InetAddress.getLocalHost(); } }  static InetAddress findConnectingAddress(InetSocketAddress targetAddress,
							long maxWaitMillis, long startLoggingAfter);  }
@Test public void testReturnLocalHostAddressUsingHeuristics() throws Exception { try (ServerSocket blocker = new ServerSocket(0, 1, InetAddress.getLocalHost())) { InetSocketAddress unreachable = new InetSocketAddress("localhost", blocker.getLocalPort()); final long start = System.nanoTime(); InetAddress add = ConnectionUtils.findConnectingAddress(unreachable, 2000, 400); assertTrue(System.nanoTime() - start < 30_000_000_000L); assertNotNull(add); assertEquals(InetAddress.getLocalHost(), add); } }
@Test public void testFindConnectingAddressWhenGetLocalHostThrows() throws Exception { PowerMockito.mockStatic(InetAddress.class); Mockito.when(InetAddress.getLocalHost()).thenThrow(new UnknownHostException()).thenCallRealMethod(); final InetAddress loopbackAddress = Inet4Address.getByName("127.0.0.1"); Thread socketServerThread; try (ServerSocket socket = new ServerSocket(0, 1, loopbackAddress)) { socket.setSoTimeout(10_000); socketServerThread = new Thread(new Runnable() { @Override public void run() { try { socket.accept(); } catch (IOException e) { } } }); socketServerThread.start(); final InetSocketAddress socketAddress = new InetSocketAddress(loopbackAddress, socket.getLocalPort()); final InetAddress address = ConnectionUtils.findConnectingAddress( socketAddress, 2000, 400); PowerMockito.verifyStatic(); assertNotNull(address); } }