# HG changeset patch # User aefimov # Date 1573773400 0 # Node ID 258033faefc937dd76e6f49bf7cf19590b8c0d02 # Parent b92aac38b046529989aba79aed49d1fa1b4f02ac aefimov-dns-client-branch: Fix timeouts, add platform specific file locations diff -r b92aac38b046 -r 258033faefc9 src/jdk.dns.client/share/classes/jdk/dns/client/NetworkNamesResolver.java --- a/src/jdk.dns.client/share/classes/jdk/dns/client/NetworkNamesResolver.java Thu Nov 14 23:13:47 2019 +0000 +++ b/src/jdk.dns.client/share/classes/jdk/dns/client/NetworkNamesResolver.java Thu Nov 14 23:16:40 2019 +0000 @@ -131,6 +131,9 @@ public List getAllHostsByAddr(InetAddress address) throws UnknownHostException { // First try hosts file // TODO: Add nsswitch.conf to select proper order + if (DEBUG) { + System.err.println("Resolver API: Reverse lookup call for address:"+address); + } try { return List.of(hostsFileResolver.getByAddress(address)); } catch (UnknownHostException uhe) { diff -r b92aac38b046 -r 258033faefc9 src/jdk.dns.client/share/classes/jdk/dns/client/internal/DnsClient.java --- a/src/jdk.dns.client/share/classes/jdk/dns/client/internal/DnsClient.java Thu Nov 14 23:13:47 2019 +0000 +++ b/src/jdk.dns.client/share/classes/jdk/dns/client/internal/DnsClient.java Thu Nov 14 23:16:40 2019 +0000 @@ -37,15 +37,16 @@ import java.net.DatagramPacket; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.PortUnreachableException; import java.net.Socket; import java.net.SocketTimeoutException; import java.net.UnknownHostException; -import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.SecureRandom; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -99,7 +100,6 @@ private int timeout; // initial timeout on UDP and TCP queries in ms private int retries; // number of UDP retries - private static final SecureRandom random; static { @@ -131,6 +131,10 @@ var serversList = new ArrayList(); var serverPortsList = new ArrayList(); + if (DEBUG) { + System.err.println("DNS Client: servers list:" + servers); + } + for (String serverString : servers) { // Is optional port given? @@ -305,6 +309,11 @@ } return new ResourceRecords(msg, msg.length, hdr, false); + } catch (PortUnreachableException e) { + if (caughtException == null) { + caughtException = e; + } + doNotRetry[i] = true; } catch (IOException e) { if (DEBUG) { dprint("Caught IOException:" + e); @@ -312,13 +321,6 @@ if (caughtException == null) { caughtException = e; } - // Use reflection to allow pre-1.4 compilation. - // This won't be needed much longer. - if (e.getClass().getName().equals( - "java.net.PortUnreachableException")) { - doNotRetry[i] = true; - } - // doNotRetry set - needs to be added } catch (DnsNameNotFoundException e) { // This is authoritative, so return immediately throw e; @@ -394,12 +396,12 @@ long start = System.currentTimeMillis(); + dc.socket().receive(ipkt); byte[] data = ipkt.getData(); - ByteBuffer bb = ByteBuffer.wrap(data); - dc.read(bb); + int length = ipkt.getLength(); long end = System.currentTimeMillis(); - if (isMatchResponse(data, xid)) { + if (isMatchResponse(data, length, xid)) { return data; } timeoutLeft = pktTimeout - ((int) (end - start)); @@ -537,10 +539,10 @@ * Also checks that the domain name, type and class in the response * match those in the original query. */ - private boolean isMatchResponse(byte[] pkt, int xid) + private boolean isMatchResponse(byte[] pkt, int length, int xid) throws DnsResolverException { - Header hdr = new Header(pkt, pkt.length); + Header hdr = new Header(pkt, length); if (hdr.query) { throw new DnsResolverException("DNS error: expecting response"); } @@ -557,7 +559,7 @@ checkResponseCode(hdr); if (!hdr.query && hdr.numQuestions == 1) { - ResourceRecord rr = new ResourceRecord(pkt, pkt.length, + ResourceRecord rr = new ResourceRecord(pkt, length, Header.HEADER_SIZE, true, false); // Retrieve the original query @@ -608,7 +610,7 @@ queuesLock.lock(); try { if (reqs.containsKey(hdr.xid)) { // enqueue only the first response - resps.put(hdr.xid, pkt); + resps.put(hdr.xid, Arrays.copyOf(pkt, length)); } } finally { queuesLock.unlock(); diff -r b92aac38b046 -r 258033faefc9 src/jdk.dns.client/share/classes/jdk/dns/client/internal/HostsFileResolver.java --- a/src/jdk.dns.client/share/classes/jdk/dns/client/internal/HostsFileResolver.java Thu Nov 14 23:13:47 2019 +0000 +++ b/src/jdk.dns.client/share/classes/jdk/dns/client/internal/HostsFileResolver.java Thu Nov 14 23:16:40 2019 +0000 @@ -26,6 +26,7 @@ package jdk.dns.client.internal; import jdk.dns.client.internal.util.ReloadTracker; +import jdk.dns.conf.DnsResolverConfiguration; import sun.net.util.IPAddressUtil; import java.net.InetAddress; @@ -53,12 +54,13 @@ public class HostsFileResolver { private static final String HOSTS_FILE_LOCATION_PROPERTY_VALUE = AccessController.doPrivileged((PrivilegedAction) - () -> System.getProperty("jdk.net.hosts.file", "/etc/hosts") + () -> System.getProperty("jdk.dns.client.hosts.file", + DnsResolverConfiguration.getDefaultHostsFileLocation()) ); private static final ReadWriteLock LOCK = new ReentrantReadWriteLock(); // 300 seconds, similar to DnsResolverConfiguration in millis since Epoch - private static final long REFRESH_TIMEOUT_MILLIS = 300_000; + private static final long REFRESH_TIMEOUT_NANOS = 300_000_000_000L; private static final ReloadTracker HOSTS_FILE_TRACKER; private static volatile Map HOST_ADDRESSES = Collections.emptyMap(); @@ -262,7 +264,7 @@ // TODO: Revisit try { var pea = (PrivilegedExceptionAction) () -> - ReloadTracker.newInstance(Paths.get(HOSTS_FILE_LOCATION_PROPERTY_VALUE), REFRESH_TIMEOUT_MILLIS); + ReloadTracker.newInstance(Paths.get(HOSTS_FILE_LOCATION_PROPERTY_VALUE), REFRESH_TIMEOUT_NANOS); HOSTS_FILE_TRACKER = System.getSecurityManager() == null ? pea.run() : AccessController.doPrivileged(pea); } catch (PrivilegedActionException pae) { diff -r b92aac38b046 -r 258033faefc9 src/jdk.dns.client/share/classes/jdk/dns/client/internal/util/ReloadTracker.java --- a/src/jdk.dns.client/share/classes/jdk/dns/client/internal/util/ReloadTracker.java Thu Nov 14 23:13:47 2019 +0000 +++ b/src/jdk.dns.client/share/classes/jdk/dns/client/internal/util/ReloadTracker.java Thu Nov 14 23:16:40 2019 +0000 @@ -25,20 +25,18 @@ package jdk.dns.client.internal.util; -import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.security.AccessController; import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.concurrent.atomic.AtomicLong; public class ReloadTracker { - public static ReloadTracker newInstance(Path fileToTrack, long refreshTimeoutMillis) { + public static ReloadTracker newInstance(Path fileToTrack, long refreshTimeoutNanos) { Path absolutePath = fileToTrack.toAbsolutePath(); - return new ReloadTracker(absolutePath, refreshTimeoutMillis); + return new ReloadTracker(absolutePath, refreshTimeoutNanos); } public static class ReloadStatus { @@ -66,9 +64,9 @@ } - private ReloadTracker(Path filePath, long refreshTimeoutMillis) { + private ReloadTracker(Path filePath, long refreshTimeoutNanos) { this.filePath = filePath; - this.refreshTimeoutMillis = refreshTimeoutMillis; + this.refreshTimeoutNanos = refreshTimeoutNanos; } @@ -92,13 +90,13 @@ } return new ReloadStatus(fileExists, (lastModificationTime != lastSeenChanged.get()) || - (System.currentTimeMillis() - lastReload > refreshTimeoutMillis), + (System.nanoTime() - lastReload > refreshTimeoutNanos), lastModificationTime); } public void updateTimestamps(ReloadStatus rs) { lastSeenChanged.set(rs.lastModificationTimestamp); - lastRefreshed.set(System.currentTimeMillis()); + lastRefreshed.set(System.nanoTime()); } // Last timestamp when tracked file has been reloaded by consumer of this utility class @@ -106,7 +104,7 @@ // Last processed FS last modified timestamp private final AtomicLong lastSeenChanged = new AtomicLong(-1); // Refresh timeout - private final long refreshTimeoutMillis; + private final long refreshTimeoutNanos; // Path of the tracked file private final Path filePath; } diff -r b92aac38b046 -r 258033faefc9 src/jdk.dns.client/unix/classes/jdk/dns/conf/DnsResolverConfiguration.java --- a/src/jdk.dns.client/unix/classes/jdk/dns/conf/DnsResolverConfiguration.java Thu Nov 14 23:13:47 2019 +0000 +++ b/src/jdk.dns.client/unix/classes/jdk/dns/conf/DnsResolverConfiguration.java Thu Nov 14 23:16:40 2019 +0000 @@ -47,6 +47,11 @@ */ public class DnsResolverConfiguration { + + public static String getDefaultHostsFileLocation() { + return "/etc/hosts"; + } + // Lock held whilst loading configuration or checking private static final ReadWriteLock LOCK = new ReentrantReadWriteLock(); @@ -56,16 +61,16 @@ private static final ReloadTracker RESOLVE_CONF_TRACKER; - // Cache timeout (300 seconds) - should be converted into property + // Cache timeout (300 seconds) in nano seconds - should be converted into property // or configured as preference in the future. - private static final int TIMEOUT = 300_000; + private static final long TIMEOUT = 300_000_000_000L; // Parse /etc/resolv.conf to get the values for a particular // keyword. // private List resolvconf(String keyword, - int maxperkeyword, - int maxkeywords) { + int maxperkeyword, + int maxkeywords) { LinkedList ll = new LinkedList<>(); try { @@ -266,7 +271,10 @@ static native String fallbackDomain0(); static { - var pa = (PrivilegedAction) () -> {System.loadLibrary("resolver"); return null;}; + var pa = (PrivilegedAction) () -> { + System.loadLibrary("resolver"); + return null; + }; if (System.getSecurityManager() == null) { pa.run(); } else {