1 /*
2 * Copyright 2014 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16
17 package io.netty5.resolver.dns;
18
19 import java.net.InetSocketAddress;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.List;
23
24 import static io.netty5.util.internal.ObjectUtil.checkNonEmpty;
25 import static java.util.Objects.requireNonNull;
26
27 /**
28 * Provides an infinite sequence of DNS server addresses to {@link DnsNameResolver}.
29 */
30 @SuppressWarnings("IteratorNextCanNotThrowNoSuchElementException")
31 public abstract class DnsServerAddresses {
32 /**
33 * @deprecated Use {@link DefaultDnsServerAddressStreamProvider#defaultAddressList()}.
34 * <p>
35 * Returns the list of the system DNS server addresses. If it failed to retrieve the list of the system DNS server
36 * addresses from the environment, it will return {@code "8.8.8.8"} and {@code "8.8.4.4"}, the addresses of the
37 * Google public DNS servers.
38 */
39 @Deprecated
40 public static List<InetSocketAddress> defaultAddressList() {
41 return DefaultDnsServerAddressStreamProvider.defaultAddressList();
42 }
43
44 /**
45 * @deprecated Use {@link DefaultDnsServerAddressStreamProvider#defaultAddresses()}.
46 * <p>
47 * Returns the {@link DnsServerAddresses} that yields the system DNS server addresses sequentially. If it failed to
48 * retrieve the list of the system DNS server addresses from the environment, it will use {@code "8.8.8.8"} and
49 * {@code "8.8.4.4"}, the addresses of the Google public DNS servers.
50 * <p>
51 * This method has the same effect with the following code:
52 * <pre>
53 * DnsServerAddresses.sequential(DnsServerAddresses.defaultAddressList());
54 * </pre>
55 * </p>
56 */
57 @Deprecated
58 public static DnsServerAddresses defaultAddresses() {
59 return DefaultDnsServerAddressStreamProvider.defaultAddresses();
60 }
61
62 /**
63 * Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} sequentially. Once the
64 * last address is yielded, it will start again from the first address.
65 */
66 public static DnsServerAddresses sequential(Iterable<? extends InetSocketAddress> addresses) {
67 return sequential0(sanitize(addresses));
68 }
69
70 /**
71 * Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} sequentially. Once the
72 * last address is yielded, it will start again from the first address.
73 */
74 public static DnsServerAddresses sequential(InetSocketAddress... addresses) {
75 return sequential0(sanitize(addresses));
76 }
77
78 private static DnsServerAddresses sequential0(final List<InetSocketAddress> addresses) {
79 if (addresses.size() == 1) {
80 return singleton(addresses.get(0));
81 }
82
83 return new DefaultDnsServerAddresses("sequential", addresses) {
84 @Override
85 public DnsServerAddressStream stream() {
86 return new SequentialDnsServerAddressStream(addresses, 0);
87 }
88 };
89 }
90
91 /**
92 * Returns the {@link DnsServerAddresses} that yields the specified {@code address} in a shuffled order. Once all
93 * addresses are yielded, the addresses are shuffled again.
94 */
95 public static DnsServerAddresses shuffled(Iterable<? extends InetSocketAddress> addresses) {
96 return shuffled0(sanitize(addresses));
97 }
98
99 /**
100 * Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} in a shuffled order. Once all
101 * addresses are yielded, the addresses are shuffled again.
102 */
103 public static DnsServerAddresses shuffled(InetSocketAddress... addresses) {
104 return shuffled0(sanitize(addresses));
105 }
106
107 private static DnsServerAddresses shuffled0(List<InetSocketAddress> addresses) {
108 if (addresses.size() == 1) {
109 return singleton(addresses.get(0));
110 }
111
112 return new DefaultDnsServerAddresses("shuffled", addresses) {
113 @Override
114 public DnsServerAddressStream stream() {
115 return new ShuffledDnsServerAddressStream(addresses);
116 }
117 };
118 }
119
120 /**
121 * Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} in a rotational sequential
122 * order. It is similar to {@link #sequential(Iterable)}, but each {@link DnsServerAddressStream} starts from
123 * a different starting point. For example, the first {@link #stream()} will start from the first address, the
124 * second one will start from the second address, and so on.
125 */
126 public static DnsServerAddresses rotational(Iterable<? extends InetSocketAddress> addresses) {
127 return rotational0(sanitize(addresses));
128 }
129
130 /**
131 * Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} in a rotational sequential
132 * order. It is similar to {@link #sequential(Iterable)}, but each {@link DnsServerAddressStream} starts from
133 * a different starting point. For example, the first {@link #stream()} will start from the first address, the
134 * second one will start from the second address, and so on.
135 */
136 public static DnsServerAddresses rotational(InetSocketAddress... addresses) {
137 return rotational0(sanitize(addresses));
138 }
139
140 private static DnsServerAddresses rotational0(List<InetSocketAddress> addresses) {
141 if (addresses.size() == 1) {
142 return singleton(addresses.get(0));
143 }
144
145 return new RotationalDnsServerAddresses(addresses);
146 }
147
148 /**
149 * Returns the {@link DnsServerAddresses} that yields only a single {@code address}.
150 */
151 public static DnsServerAddresses singleton(final InetSocketAddress address) {
152 requireNonNull(address, "address");
153 if (address.isUnresolved()) {
154 throw new IllegalArgumentException("cannot use an unresolved DNS server address: " + address);
155 }
156
157 return new SingletonDnsServerAddresses(address);
158 }
159
160 private static List<InetSocketAddress> sanitize(Iterable<? extends InetSocketAddress> addresses) {
161 requireNonNull(addresses, "addresses");
162
163 final List<InetSocketAddress> list;
164 if (addresses instanceof Collection) {
165 list = new ArrayList<>(((Collection<?>) addresses).size());
166 } else {
167 list = new ArrayList<>(4);
168 }
169
170 for (InetSocketAddress a : addresses) {
171 if (a == null) {
172 break;
173 }
174 if (a.isUnresolved()) {
175 throw new IllegalArgumentException("cannot use an unresolved DNS server address: " + a);
176 }
177 list.add(a);
178 }
179
180 return checkNonEmpty(list, "list");
181 }
182
183 private static List<InetSocketAddress> sanitize(InetSocketAddress[] addresses) {
184 requireNonNull(addresses, "addresses");
185
186 List<InetSocketAddress> list = new ArrayList<>(addresses.length);
187 for (InetSocketAddress a: addresses) {
188 if (a == null) {
189 break;
190 }
191 if (a.isUnresolved()) {
192 throw new IllegalArgumentException("cannot use an unresolved DNS server address: " + a);
193 }
194 list.add(a);
195 }
196
197 if (list.isEmpty()) {
198 return DefaultDnsServerAddressStreamProvider.defaultAddressList();
199 }
200
201 return list;
202 }
203
204 /**
205 * Starts a new infinite stream of DNS server addresses. This method is invoked by {@link DnsNameResolver} on every
206 * uncached {@link DnsNameResolver#resolve(String)}or {@link DnsNameResolver#resolveAll(String)}.
207 */
208 public abstract DnsServerAddressStream stream();
209 }