1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.resolver.dns;
17
18 import io.netty.channel.ChannelFactory;
19 import io.netty.channel.EventLoop;
20 import io.netty.channel.ReflectiveChannelFactory;
21 import io.netty.channel.socket.DatagramChannel;
22 import io.netty.channel.socket.InternetProtocolFamily;
23 import io.netty.channel.socket.SocketChannel;
24 import io.netty.resolver.HostsFileEntriesResolver;
25 import io.netty.resolver.ResolvedAddressTypes;
26 import io.netty.util.concurrent.Future;
27 import io.netty.util.internal.EmptyArrays;
28 import io.netty.util.internal.ObjectUtil;
29 import io.netty.util.internal.logging.InternalLogger;
30 import io.netty.util.internal.logging.InternalLoggerFactory;
31
32 import java.net.SocketAddress;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.List;
36
37 import static io.netty.util.internal.ObjectUtil.checkNotNull;
38 import static io.netty.util.internal.ObjectUtil.intValue;
39
40
41
42
43 public final class DnsNameResolverBuilder {
44
45 private static final InternalLogger logger = InternalLoggerFactory.getInstance(DnsNameResolverBuilder.class);
46
47 volatile EventLoop eventLoop;
48 private ChannelFactory<? extends DatagramChannel> channelFactory;
49 private ChannelFactory<? extends SocketChannel> socketChannelFactory;
50 private boolean retryOnTimeout;
51
52 private DnsCache resolveCache;
53 private DnsCnameCache cnameCache;
54 private AuthoritativeDnsServerCache authoritativeDnsServerCache;
55 private SocketAddress localAddress;
56 private Integer minTtl;
57 private Integer maxTtl;
58 private Integer negativeTtl;
59 private long queryTimeoutMillis = -1;
60 private ResolvedAddressTypes resolvedAddressTypes = DnsNameResolver.DEFAULT_RESOLVE_ADDRESS_TYPES;
61 private boolean completeOncePreferredResolved;
62 private boolean recursionDesired = true;
63 private int maxQueriesPerResolve = -1;
64 private boolean traceEnabled;
65 private int maxPayloadSize = 4096;
66 private boolean optResourceEnabled = true;
67 private HostsFileEntriesResolver hostsFileEntriesResolver = HostsFileEntriesResolver.DEFAULT;
68 private DnsServerAddressStreamProvider dnsServerAddressStreamProvider =
69 DnsServerAddressStreamProviders.platformDefault();
70 private DnsServerAddressStream queryDnsServerAddressStream;
71 private DnsQueryLifecycleObserverFactory dnsQueryLifecycleObserverFactory =
72 NoopDnsQueryLifecycleObserverFactory.INSTANCE;
73 private String[] searchDomains;
74 private int ndots = -1;
75 private boolean decodeIdn = true;
76
77 private int maxNumConsolidation;
78
79
80
81
82 public DnsNameResolverBuilder() {
83 }
84
85
86
87
88
89
90
91 public DnsNameResolverBuilder(EventLoop eventLoop) {
92 eventLoop(eventLoop);
93 }
94
95
96
97
98
99
100
101 public DnsNameResolverBuilder eventLoop(EventLoop eventLoop) {
102 this.eventLoop = eventLoop;
103 return this;
104 }
105
106 protected ChannelFactory<? extends DatagramChannel> channelFactory() {
107 return this.channelFactory;
108 }
109
110
111
112
113
114
115
116
117
118 public DnsNameResolverBuilder channelFactory(ChannelFactory<? extends DatagramChannel> channelFactory) {
119 this.channelFactory = channelFactory;
120 return this;
121 }
122
123
124
125
126
127
128
129
130
131
132 public DnsNameResolverBuilder channelType(Class<? extends DatagramChannel> channelType) {
133 return channelFactory(new ReflectiveChannelFactory<DatagramChannel>(channelType));
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147
148 public DnsNameResolverBuilder socketChannelFactory(ChannelFactory<? extends SocketChannel> channelFactory) {
149 return socketChannelFactory(channelFactory, false);
150 }
151
152
153
154
155
156
157
158
159
160
161
162
163
164 public DnsNameResolverBuilder socketChannelType(Class<? extends SocketChannel> channelType) {
165 return socketChannelType(channelType, false);
166 }
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183 public DnsNameResolverBuilder socketChannelFactory(
184 ChannelFactory<? extends SocketChannel> channelFactory, boolean retryOnTimeout) {
185 this.socketChannelFactory = channelFactory;
186 this.retryOnTimeout = retryOnTimeout;
187 return this;
188 }
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205 public DnsNameResolverBuilder socketChannelType(
206 Class<? extends SocketChannel> channelType, boolean retryOnTimeout) {
207 if (channelType == null) {
208 return socketChannelFactory(null, retryOnTimeout);
209 }
210 return socketChannelFactory(new ReflectiveChannelFactory<SocketChannel>(channelType), retryOnTimeout);
211 }
212
213
214
215
216
217
218
219 public DnsNameResolverBuilder resolveCache(DnsCache resolveCache) {
220 this.resolveCache = resolveCache;
221 return this;
222 }
223
224
225
226
227
228
229
230 public DnsNameResolverBuilder cnameCache(DnsCnameCache cnameCache) {
231 this.cnameCache = cnameCache;
232 return this;
233 }
234
235
236
237
238
239
240 public DnsNameResolverBuilder dnsQueryLifecycleObserverFactory(DnsQueryLifecycleObserverFactory
241 lifecycleObserverFactory) {
242 this.dnsQueryLifecycleObserverFactory = checkNotNull(lifecycleObserverFactory, "lifecycleObserverFactory");
243 return this;
244 }
245
246
247
248
249
250
251
252
253 @Deprecated
254 public DnsNameResolverBuilder authoritativeDnsServerCache(DnsCache authoritativeDnsServerCache) {
255 this.authoritativeDnsServerCache = new AuthoritativeDnsServerCacheAdapter(authoritativeDnsServerCache);
256 return this;
257 }
258
259
260
261
262
263
264
265 public DnsNameResolverBuilder authoritativeDnsServerCache(AuthoritativeDnsServerCache authoritativeDnsServerCache) {
266 this.authoritativeDnsServerCache = authoritativeDnsServerCache;
267 return this;
268 }
269
270
271
272
273
274
275 public DnsNameResolverBuilder localAddress(SocketAddress localAddress) {
276 this.localAddress = localAddress;
277 return this;
278 }
279
280
281
282
283
284
285
286
287
288
289
290
291
292 public DnsNameResolverBuilder ttl(int minTtl, int maxTtl) {
293 this.maxTtl = maxTtl;
294 this.minTtl = minTtl;
295 return this;
296 }
297
298
299
300
301
302
303
304 public DnsNameResolverBuilder negativeTtl(int negativeTtl) {
305 this.negativeTtl = negativeTtl;
306 return this;
307 }
308
309
310
311
312
313
314
315
316 public DnsNameResolverBuilder queryTimeoutMillis(long queryTimeoutMillis) {
317 this.queryTimeoutMillis = queryTimeoutMillis;
318 return this;
319 }
320
321
322
323
324
325
326
327
328 public static ResolvedAddressTypes computeResolvedAddressTypes(InternetProtocolFamily... internetProtocolFamilies) {
329 if (internetProtocolFamilies == null || internetProtocolFamilies.length == 0) {
330 return DnsNameResolver.DEFAULT_RESOLVE_ADDRESS_TYPES;
331 }
332 if (internetProtocolFamilies.length > 2) {
333 throw new IllegalArgumentException("No more than 2 InternetProtocolFamilies");
334 }
335
336 switch(internetProtocolFamilies[0]) {
337 case IPv4:
338 return (internetProtocolFamilies.length >= 2
339 && internetProtocolFamilies[1] == InternetProtocolFamily.IPv6) ?
340 ResolvedAddressTypes.IPV4_PREFERRED: ResolvedAddressTypes.IPV4_ONLY;
341 case IPv6:
342 return (internetProtocolFamilies.length >= 2
343 && internetProtocolFamilies[1] == InternetProtocolFamily.IPv4) ?
344 ResolvedAddressTypes.IPV6_PREFERRED: ResolvedAddressTypes.IPV6_ONLY;
345 default:
346 throw new IllegalArgumentException(
347 "Couldn't resolve ResolvedAddressTypes from InternetProtocolFamily array");
348 }
349 }
350
351
352
353
354
355
356
357
358
359 public DnsNameResolverBuilder resolvedAddressTypes(ResolvedAddressTypes resolvedAddressTypes) {
360 this.resolvedAddressTypes = resolvedAddressTypes;
361 return this;
362 }
363
364
365
366
367
368
369
370
371 public DnsNameResolverBuilder completeOncePreferredResolved(boolean completeOncePreferredResolved) {
372 this.completeOncePreferredResolved = completeOncePreferredResolved;
373 return this;
374 }
375
376
377
378
379
380
381
382 public DnsNameResolverBuilder recursionDesired(boolean recursionDesired) {
383 this.recursionDesired = recursionDesired;
384 return this;
385 }
386
387
388
389
390
391
392
393 public DnsNameResolverBuilder maxQueriesPerResolve(int maxQueriesPerResolve) {
394 this.maxQueriesPerResolve = maxQueriesPerResolve;
395 return this;
396 }
397
398
399
400
401
402
403
404
405
406
407 @Deprecated
408 public DnsNameResolverBuilder traceEnabled(boolean traceEnabled) {
409 this.traceEnabled = traceEnabled;
410 return this;
411 }
412
413
414
415
416
417
418
419 public DnsNameResolverBuilder maxPayloadSize(int maxPayloadSize) {
420 this.maxPayloadSize = maxPayloadSize;
421 return this;
422 }
423
424
425
426
427
428
429
430
431
432 public DnsNameResolverBuilder optResourceEnabled(boolean optResourceEnabled) {
433 this.optResourceEnabled = optResourceEnabled;
434 return this;
435 }
436
437
438
439
440
441
442 public DnsNameResolverBuilder hostsFileEntriesResolver(HostsFileEntriesResolver hostsFileEntriesResolver) {
443 this.hostsFileEntriesResolver = hostsFileEntriesResolver;
444 return this;
445 }
446
447 protected DnsServerAddressStreamProvider nameServerProvider() {
448 return this.dnsServerAddressStreamProvider;
449 }
450
451
452
453
454
455
456 public DnsNameResolverBuilder nameServerProvider(DnsServerAddressStreamProvider dnsServerAddressStreamProvider) {
457 this.dnsServerAddressStreamProvider =
458 checkNotNull(dnsServerAddressStreamProvider, "dnsServerAddressStreamProvider");
459 return this;
460 }
461
462 protected DnsServerAddressStream queryServerAddressStream() {
463 return this.queryDnsServerAddressStream;
464 }
465
466
467
468
469
470 public DnsNameResolverBuilder queryServerAddressStream(DnsServerAddressStream queryServerAddressStream) {
471 this.queryDnsServerAddressStream =
472 checkNotNull(queryServerAddressStream, "queryServerAddressStream");
473 return this;
474 }
475
476
477
478
479
480
481
482 public DnsNameResolverBuilder searchDomains(Iterable<String> searchDomains) {
483 checkNotNull(searchDomains, "searchDomains");
484
485 final List<String> list = new ArrayList<String>(4);
486
487 for (String f : searchDomains) {
488 if (f == null) {
489 break;
490 }
491
492
493 if (list.contains(f)) {
494 continue;
495 }
496
497 list.add(f);
498 }
499
500 this.searchDomains = list.toArray(EmptyArrays.EMPTY_STRINGS);
501 return this;
502 }
503
504
505
506
507
508
509
510
511 public DnsNameResolverBuilder ndots(int ndots) {
512 this.ndots = ndots;
513 return this;
514 }
515
516 private DnsCache newCache() {
517 return new DefaultDnsCache(intValue(minTtl, 0), intValue(maxTtl, Integer.MAX_VALUE), intValue(negativeTtl, 0));
518 }
519
520 private AuthoritativeDnsServerCache newAuthoritativeDnsServerCache() {
521 return new DefaultAuthoritativeDnsServerCache(
522 intValue(minTtl, 0), intValue(maxTtl, Integer.MAX_VALUE),
523
524
525 new NameServerComparator(DnsNameResolver.preferredAddressType(resolvedAddressTypes).addressType()));
526 }
527
528 private DnsServerAddressStream newQueryServerAddressStream(
529 DnsServerAddressStreamProvider dnsServerAddressStreamProvider) {
530 return new ThreadLocalNameServerAddressStream(dnsServerAddressStreamProvider);
531 }
532
533 private DnsCnameCache newCnameCache() {
534 return new DefaultDnsCnameCache(
535 intValue(minTtl, 0), intValue(maxTtl, Integer.MAX_VALUE));
536 }
537
538
539
540
541
542
543
544
545 public DnsNameResolverBuilder decodeIdn(boolean decodeIdn) {
546 this.decodeIdn = decodeIdn;
547 return this;
548 }
549
550
551
552
553
554
555
556
557
558
559 public DnsNameResolverBuilder consolidateCacheSize(int maxNumConsolidation) {
560 this.maxNumConsolidation = ObjectUtil.checkPositiveOrZero(maxNumConsolidation, "maxNumConsolidation");
561 return this;
562 }
563
564
565
566
567
568
569 public DnsNameResolver build() {
570 if (eventLoop == null) {
571 throw new IllegalStateException("eventLoop should be specified to build a DnsNameResolver.");
572 }
573
574 if (resolveCache != null && (minTtl != null || maxTtl != null || negativeTtl != null)) {
575 logger.debug("resolveCache and TTLs are mutually exclusive. TTLs are ignored.");
576 }
577
578 if (cnameCache != null && (minTtl != null || maxTtl != null || negativeTtl != null)) {
579 logger.debug("cnameCache and TTLs are mutually exclusive. TTLs are ignored.");
580 }
581
582 if (authoritativeDnsServerCache != null && (minTtl != null || maxTtl != null || negativeTtl != null)) {
583 logger.debug("authoritativeDnsServerCache and TTLs are mutually exclusive. TTLs are ignored.");
584 }
585
586 DnsCache resolveCache = this.resolveCache != null ? this.resolveCache : newCache();
587 DnsCnameCache cnameCache = this.cnameCache != null ? this.cnameCache : newCnameCache();
588 AuthoritativeDnsServerCache authoritativeDnsServerCache = this.authoritativeDnsServerCache != null ?
589 this.authoritativeDnsServerCache : newAuthoritativeDnsServerCache();
590
591 DnsServerAddressStream queryDnsServerAddressStream = this.queryDnsServerAddressStream != null ?
592 this.queryDnsServerAddressStream : newQueryServerAddressStream(dnsServerAddressStreamProvider);
593
594 return new DnsNameResolver(
595 eventLoop,
596 channelFactory,
597 socketChannelFactory,
598 retryOnTimeout,
599 resolveCache,
600 cnameCache,
601 authoritativeDnsServerCache,
602 localAddress,
603 dnsQueryLifecycleObserverFactory,
604 queryTimeoutMillis,
605 resolvedAddressTypes,
606 recursionDesired,
607 maxQueriesPerResolve,
608 traceEnabled,
609 maxPayloadSize,
610 optResourceEnabled,
611 hostsFileEntriesResolver,
612 dnsServerAddressStreamProvider,
613 queryDnsServerAddressStream,
614 searchDomains,
615 ndots,
616 decodeIdn,
617 completeOncePreferredResolved,
618 maxNumConsolidation);
619 }
620
621
622
623
624
625
626 public DnsNameResolverBuilder copy() {
627 DnsNameResolverBuilder copiedBuilder = new DnsNameResolverBuilder();
628
629 if (eventLoop != null) {
630 copiedBuilder.eventLoop(eventLoop);
631 }
632
633 if (channelFactory != null) {
634 copiedBuilder.channelFactory(channelFactory);
635 }
636
637 copiedBuilder.socketChannelFactory(socketChannelFactory, retryOnTimeout);
638
639 if (resolveCache != null) {
640 copiedBuilder.resolveCache(resolveCache);
641 }
642
643 if (cnameCache != null) {
644 copiedBuilder.cnameCache(cnameCache);
645 }
646 if (maxTtl != null && minTtl != null) {
647 copiedBuilder.ttl(minTtl, maxTtl);
648 }
649
650 if (negativeTtl != null) {
651 copiedBuilder.negativeTtl(negativeTtl);
652 }
653
654 if (authoritativeDnsServerCache != null) {
655 copiedBuilder.authoritativeDnsServerCache(authoritativeDnsServerCache);
656 }
657
658 if (dnsQueryLifecycleObserverFactory != null) {
659 copiedBuilder.dnsQueryLifecycleObserverFactory(dnsQueryLifecycleObserverFactory);
660 }
661
662 copiedBuilder.queryTimeoutMillis(queryTimeoutMillis);
663 copiedBuilder.resolvedAddressTypes(resolvedAddressTypes);
664 copiedBuilder.recursionDesired(recursionDesired);
665 copiedBuilder.maxQueriesPerResolve(maxQueriesPerResolve);
666 copiedBuilder.traceEnabled(traceEnabled);
667 copiedBuilder.maxPayloadSize(maxPayloadSize);
668 copiedBuilder.optResourceEnabled(optResourceEnabled);
669 copiedBuilder.hostsFileEntriesResolver(hostsFileEntriesResolver);
670
671 if (dnsServerAddressStreamProvider != null) {
672 copiedBuilder.nameServerProvider(dnsServerAddressStreamProvider);
673 }
674
675 if (queryDnsServerAddressStream != null) {
676 copiedBuilder.queryServerAddressStream(queryDnsServerAddressStream);
677 }
678
679 if (searchDomains != null) {
680 copiedBuilder.searchDomains(Arrays.asList(searchDomains));
681 }
682
683 copiedBuilder.ndots(ndots);
684 copiedBuilder.decodeIdn(decodeIdn);
685 copiedBuilder.completeOncePreferredResolved(completeOncePreferredResolved);
686 copiedBuilder.localAddress(localAddress);
687 copiedBuilder.consolidateCacheSize(maxNumConsolidation);
688 return copiedBuilder;
689 }
690 }