1 /*
  2  * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  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
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.net.spi;
 27 
 28 import java.lang.annotation.Native;
 29 import java.net.InetAddress;
 30 import java.net.UnknownHostException;
 31 import java.util.stream.Stream;
 32 
 33 /**
 34  * This interface defines operations for looking-up host names and IP addresses.
 35  * An instance of {@code InetAddressResolver} is
 36  * <a href="{@docRoot}/java.base/java/net/InetAddress.html#resolverProviders">installed</a>
 37  * as a <i>system-wide resolver</i>.
 38  * {@link InetAddress} delegates all lookup requests to the installed <i>system-wide resolver</i>
 39  * instance.
 40  * <p>
 41  * The <i>system-wide resolver</i> can be customized by
 42  * <a href="{@docRoot}/java.base/java/net/InetAddress.html#resolverProviders">deploying an implementation</a>
 43  * of {@link InetAddressResolverProvider}.
 44  */
 45 public interface InetAddressResolver {
 46 
 47     /**
 48      * Given the name of a host, returns a stream of IP addresses of the requested
 49      * address family associated with a provided hostname.
 50      * <p>
 51      * {@code host} should be a machine name, such as "{@code www.example.com}",
 52      * not a textual representation of its IP address. No validation is performed on
 53      * the given {@code host} name: if a textual representation is supplied, the name
 54      * resolution is likely to fail and {@link UnknownHostException} may be thrown.
 55      * <p>
 56      * The address family type and addresses order are specified by the {@code LookupPolicy} instance.
 57      * Lookup operation characteristics could be acquired with {@link LookupPolicy#characteristics()}. If
 58      * {@link InetAddressResolver.LookupPolicy#IPV4} and {@link InetAddressResolver.LookupPolicy#IPV6}
 59      * characteristics provided then this method returns addresses of both IPV4 and IPV6 families.
 60      *
 61      * @param host         the specified hostname
 62      * @param lookupPolicy the address lookup policy
 63      * @return a stream of IP addresses for the requested host
 64      * @throws NullPointerException if {@code host} is {@code null}
 65      * @throws UnknownHostException if no IP address for the {@code host} could be found
 66      * @see LookupPolicy
 67      */
 68     Stream<InetAddress> lookupAddresses(String host, LookupPolicy lookupPolicy) throws UnknownHostException;
 69 
 70     /**
 71      * Lookup the host name corresponding to the raw IP address provided.
 72      *
 73      * <p>{@code addr} argument is in network byte order: the highest order byte of the address
 74      * is in {@code addr[0]}.
 75      *
 76      * <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
 77      * must be 16 bytes long.
 78      *
 79      * @param addr byte array representing a raw IP address
 80      * @return {@code String} representing the host name mapping
 81      * @throws UnknownHostException     if no host found for the specified IP address
 82      * @throws IllegalArgumentException if IP address is of illegal length
 83      */
 84     String lookupHostName(byte[] addr) throws UnknownHostException;
 85 
 86     /**
 87      * A {@code LookupPolicy} object describes characteristics that can be applied to a lookup operation.
 88      * In particular, it is used to specify which ordering and filtering should be performed when
 89      * {@linkplain InetAddressResolver#lookupAddresses(String, LookupPolicy) looking up a host addresses}.
 90      * <p>
 91      * The default platform-wide lookup policy is constructed by consulting
 92      * <a href="doc-files/net-properties.html#Ipv4IPv6">System Properties</a> which affect
 93      * how IPv4 and IPv6 addresses are returned.
 94      */
 95     final class LookupPolicy {
 96 
 97         /**
 98          * Specifies if IPv4 addresses need to be queried during lookup.
 99          */
100         @Native
101         public static final int IPV4 = 1 << 0;
102 
103         /**
104          * Specifies if IPv6 addresses need to be queried during lookup.
105          */
106         @Native
107         public static final int IPV6 = 1 << 1;
108 
109         /**
110          * Specifies if IPv4 addresses should be returned first by {@code InetAddressResolver}.
111          */
112         @Native
113         public static final int IPV4_FIRST = 1 << 2;
114 
115         /**
116          * Specifies if IPv6 addresses should be returned first by {@code InetAddressResolver}.
117          */
118         @Native
119         public static final int IPV6_FIRST = 1 << 3;
120 
121         private final int characteristics;
122 
123         private LookupPolicy(int characteristics) {
124             this.characteristics = characteristics;
125         }
126 
127         /**
128          * This factory method creates {@link LookupPolicy LookupPolicy} instance with the provided
129          * {@code characteristics} value.
130          * <p> The {@code characteristics} value is an integer bit mask which defines
131          * parameters of a forward lookup operation. These parameters define at least:
132          * <ul>
133          *     <li>the family type of the returned addresses</li>
134          *     <li>the order in which a {@linkplain InetAddressResolver resolver}
135          *         implementation should return its results</li>
136          * </ul>
137          * <p> To request addresses of specific family types the following bit masks can be combined:
138          * <ul>
139          *     <li>{@link LookupPolicy#IPV4}: to request IPv4 addresses</li>
140          *     <li>{@link LookupPolicy#IPV6}: to request IPv6 addresses</li>
141          * </ul>
142          * <br>It is an error if neither {@link LookupPolicy#IPV4} or {@link LookupPolicy#IPV6} are set.
143          * <p> To request a specific ordering of the results:
144          * <ul>
145          *     <li>{@link LookupPolicy#IPV4_FIRST}: return IPv4 addresses before any IPv6 address</li>
146          *     <li>{@link LookupPolicy#IPV6_FIRST}: return IPv6 addresses before any IPv4 address</li>
147          * </ul>
148          * <br>If neither {@link LookupPolicy#IPV4_FIRST} or {@link LookupPolicy#IPV6_FIRST} are set it
149          * implies <a href="{@docRoot}/java.base/java/net/doc-files/net-properties.html#Ipv4IPv6">"system"</a>
150          * order of addresses.
151          * It is an error to request both {@link LookupPolicy#IPV4_FIRST} and {@link LookupPolicy#IPV6_FIRST}.
152          *
153          * @param characteristics value which represents the set of lookup characteristics
154          * @return an instance of {@code InetAddressResolver.LookupPolicy}
155          * @throws IllegalArgumentException if illegal characteristic bit mask is provided
156          * @see InetAddressResolver#lookupAddresses(String, LookupPolicy)
157          */
158         public static final LookupPolicy of(int characteristics) {
159             // At least one type of addresses should be requested
160             if ((characteristics & IPV4) == 0 && (characteristics & IPV6) == 0) {
161                 throw new IllegalArgumentException("No address type specified");
162             }
163 
164             // Requested order of addresses couldn't be determined
165             if ((characteristics & IPV4_FIRST) != 0 && (characteristics & IPV6_FIRST) != 0) {
166                 throw new IllegalArgumentException("Addresses order cannot be determined");
167             }
168 
169             // If IPv4 addresses requested to be returned first then they should be requested too
170             if ((characteristics & IPV4_FIRST) != 0 && (characteristics & IPV4) == 0) {
171                 throw new IllegalArgumentException("Addresses order and type do not match");
172             }
173 
174             // If IPv6 addresses requested to be returned first then they should be requested too
175             if ((characteristics & IPV6_FIRST) != 0 && (characteristics & IPV6) == 0) {
176                 throw new IllegalArgumentException("Addresses order and type do not match");
177             }
178             return new LookupPolicy(characteristics);
179         }
180 
181         /**
182          * Returns an integer value which specifies lookup operation characteristics.
183          * Type and order of address families queried during resolution of host IP addresses.
184          *
185          * @return a characteristics value
186          * @see InetAddressResolver#lookupAddresses(String, LookupPolicy)
187          */
188         public final int characteristics() {
189             return characteristics;
190         }
191     }
192 }