src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsClient.java
changeset 58308 b7192797f434
parent 48568 0255315ac8d4
equal deleted inserted replaced
58300:c3b93d6603f5 58308:b7192797f434
     1 /*
     1 /*
     2  * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    27 
    27 
    28 import java.io.IOException;
    28 import java.io.IOException;
    29 import java.net.DatagramSocket;
    29 import java.net.DatagramSocket;
    30 import java.net.DatagramPacket;
    30 import java.net.DatagramPacket;
    31 import java.net.InetAddress;
    31 import java.net.InetAddress;
       
    32 import java.net.InetSocketAddress;
    32 import java.net.Socket;
    33 import java.net.Socket;
       
    34 import java.net.SocketTimeoutException;
    33 import java.security.SecureRandom;
    35 import java.security.SecureRandom;
    34 import javax.naming.*;
    36 import javax.naming.*;
    35 
    37 
    36 import java.util.Collections;
    38 import java.util.Collections;
    37 import java.util.Map;
    39 import java.util.Map;
    80     private static final int DEFAULT_PORT = 53;
    82     private static final int DEFAULT_PORT = 53;
    81     private static final int TRANSACTION_ID_BOUND = 0x10000;
    83     private static final int TRANSACTION_ID_BOUND = 0x10000;
    82     private static final SecureRandom random = JCAUtil.getSecureRandom();
    84     private static final SecureRandom random = JCAUtil.getSecureRandom();
    83     private InetAddress[] servers;
    85     private InetAddress[] servers;
    84     private int[] serverPorts;
    86     private int[] serverPorts;
    85     private int timeout;                // initial timeout on UDP queries in ms
    87     private int timeout;                // initial timeout on UDP and TCP queries in ms
    86     private int retries;                // number of UDP retries
    88     private int retries;                // number of UDP retries
    87 
    89 
    88     private final Object udpSocketLock = new Object();
    90     private final Object udpSocketLock = new Object();
    89     private static final DNSDatagramSocketFactory factory =
    91     private static final DNSDatagramSocketFactory factory =
    90             new DNSDatagramSocketFactory(random);
    92             new DNSDatagramSocketFactory(random);
    98     //-------------------------------------------------------------------------
   100     //-------------------------------------------------------------------------
    99 
   101 
   100     /*
   102     /*
   101      * Each server is of the form "server[:port]".  IPv6 literal host names
   103      * Each server is of the form "server[:port]".  IPv6 literal host names
   102      * include delimiting brackets.
   104      * include delimiting brackets.
   103      * "timeout" is the initial timeout interval (in ms) for UDP queries,
   105      * "timeout" is the initial timeout interval (in ms) for queries,
   104      * and "retries" gives the number of retries per server.
   106      * and "retries" gives the number of retries per server.
   105      */
   107      */
   106     public DnsClient(String[] servers, int timeout, int retries)
   108     public DnsClient(String[] servers, int timeout, int retries)
   107             throws NamingException {
   109             throws NamingException {
   108         this.timeout = timeout;
   110         this.timeout = timeout;
   235                         }
   237                         }
   236                         if (hdr.truncated) {  // message is truncated -- try TCP
   238                         if (hdr.truncated) {  // message is truncated -- try TCP
   237 
   239 
   238                             // Try each server, starting with the one that just
   240                             // Try each server, starting with the one that just
   239                             // provided the truncated message.
   241                             // provided the truncated message.
       
   242                             int retryTimeout = (timeout * (1 << retry));
   240                             for (int j = 0; j < servers.length; j++) {
   243                             for (int j = 0; j < servers.length; j++) {
   241                                 int ij = (i + j) % servers.length;
   244                                 int ij = (i + j) % servers.length;
   242                                 if (doNotRetry[ij]) {
   245                                 if (doNotRetry[ij]) {
   243                                     continue;
   246                                     continue;
   244                                 }
   247                                 }
   245                                 try {
   248                                 try {
   246                                     Tcp tcp =
   249                                     Tcp tcp =
   247                                         new Tcp(servers[ij], serverPorts[ij]);
   250                                         new Tcp(servers[ij], serverPorts[ij], retryTimeout);
   248                                     byte[] msg2;
   251                                     byte[] msg2;
   249                                     try {
   252                                     try {
   250                                         msg2 = doTcpQuery(tcp, pkt);
   253                                         msg2 = doTcpQuery(tcp, pkt);
   251                                     } finally {
   254                                     } finally {
   252                                         tcp.close();
   255                                         tcp.close();
   325         Exception caughtException = null;
   328         Exception caughtException = null;
   326 
   329 
   327         // Try each name server.
   330         // Try each name server.
   328         for (int i = 0; i < servers.length; i++) {
   331         for (int i = 0; i < servers.length; i++) {
   329             try {
   332             try {
   330                 Tcp tcp = new Tcp(servers[i], serverPorts[i]);
   333                 Tcp tcp = new Tcp(servers[i], serverPorts[i], timeout);
   331                 byte[] msg;
   334                 byte[] msg;
   332                 try {
   335                 try {
   333                     msg = doTcpQuery(tcp, pkt);
   336                     msg = doTcpQuery(tcp, pkt);
   334                     Header hdr = new Header(msg, msg.length);
   337                     Header hdr = new Header(msg, msg.length);
   335                     // Check only rcode as per
   338                     // Check only rcode as per
   460     /*
   463     /*
   461      * Returns the next DNS message from the TCP socket, or null on EOF.
   464      * Returns the next DNS message from the TCP socket, or null on EOF.
   462      */
   465      */
   463     private byte[] continueTcpQuery(Tcp tcp) throws IOException {
   466     private byte[] continueTcpQuery(Tcp tcp) throws IOException {
   464 
   467 
   465         int lenHi = tcp.in.read();      // high-order byte of response length
   468         int lenHi = tcp.read();      // high-order byte of response length
   466         if (lenHi == -1) {
   469         if (lenHi == -1) {
   467             return null;        // EOF
   470             return null;        // EOF
   468         }
   471         }
   469         int lenLo = tcp.in.read();      // low-order byte of response length
   472         int lenLo = tcp.read();      // low-order byte of response length
   470         if (lenLo == -1) {
   473         if (lenLo == -1) {
   471             throw new IOException("Corrupted DNS response: bad length");
   474             throw new IOException("Corrupted DNS response: bad length");
   472         }
   475         }
   473         int len = (lenHi << 8) | lenLo;
   476         int len = (lenHi << 8) | lenLo;
   474         byte[] msg = new byte[len];
   477         byte[] msg = new byte[len];
   475         int pos = 0;                    // next unfilled position in msg
   478         int pos = 0;                    // next unfilled position in msg
   476         while (len > 0) {
   479         while (len > 0) {
   477             int n = tcp.in.read(msg, pos, len);
   480             int n = tcp.read(msg, pos, len);
   478             if (n == -1) {
   481             if (n == -1) {
   479                 throw new IOException(
   482                 throw new IOException(
   480                         "Corrupted DNS response: too little data");
   483                         "Corrupted DNS response: too little data");
   481             }
   484             }
   482             len -= n;
   485             len -= n;
   680 
   683 
   681 }
   684 }
   682 
   685 
   683 class Tcp {
   686 class Tcp {
   684 
   687 
   685     private Socket sock;
   688     private final Socket sock;
   686     java.io.InputStream in;
   689     private final java.io.InputStream in;
   687     java.io.OutputStream out;
   690     final java.io.OutputStream out;
   688 
   691     private int timeoutLeft;
   689     Tcp(InetAddress server, int port) throws IOException {
   692 
   690         sock = new Socket(server, port);
   693     Tcp(InetAddress server, int port, int timeout) throws IOException {
   691         sock.setTcpNoDelay(true);
   694         sock = new Socket();
   692         out = new java.io.BufferedOutputStream(sock.getOutputStream());
   695         try {
   693         in = new java.io.BufferedInputStream(sock.getInputStream());
   696             long start = System.currentTimeMillis();
       
   697             sock.connect(new InetSocketAddress(server, port), timeout);
       
   698             timeoutLeft = (int) (timeout - (System.currentTimeMillis() - start));
       
   699             if (timeoutLeft <= 0)
       
   700                 throw new SocketTimeoutException();
       
   701 
       
   702             sock.setTcpNoDelay(true);
       
   703             out = new java.io.BufferedOutputStream(sock.getOutputStream());
       
   704             in = new java.io.BufferedInputStream(sock.getInputStream());
       
   705         } catch (Exception e) {
       
   706             try {
       
   707                 sock.close();
       
   708             } catch (IOException ex) {
       
   709                 e.addSuppressed(ex);
       
   710             }
       
   711             throw e;
       
   712         }
   694     }
   713     }
   695 
   714 
   696     void close() throws IOException {
   715     void close() throws IOException {
   697         sock.close();
   716         sock.close();
       
   717     }
       
   718 
       
   719     private interface SocketReadOp {
       
   720         int read() throws IOException;
       
   721     }
       
   722 
       
   723     private int readWithTimeout(SocketReadOp reader) throws IOException {
       
   724         if (timeoutLeft <= 0)
       
   725             throw new SocketTimeoutException();
       
   726 
       
   727         sock.setSoTimeout(timeoutLeft);
       
   728         long start = System.currentTimeMillis();
       
   729         try {
       
   730             return reader.read();
       
   731         }
       
   732         finally {
       
   733             timeoutLeft -= System.currentTimeMillis() - start;
       
   734         }
       
   735     }
       
   736 
       
   737     int read() throws IOException {
       
   738         return readWithTimeout(() -> in.read());
       
   739     }
       
   740 
       
   741     int read(byte b[], int off, int len) throws IOException {
       
   742         return readWithTimeout(() -> in.read(b, off, len));
   698     }
   743     }
   699 }
   744 }
   700 
   745 
   701 /*
   746 /*
   702  * javaos emulation -cj
   747  * javaos emulation -cj