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