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.Arrays;
36 import java.util.LinkedHashSet;
37 import java.util.Set;
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 Set<String> domains = new LinkedHashSet<String>(4);
561
562 for (String f : searchDomains) {
563 if (f == null) {
564 break;
565 }
566
567
568 domains.add(f);
569 }
570
571 this.searchDomains = domains.toArray(EmptyArrays.EMPTY_STRINGS);
572 return this;
573 }
574
575
576
577
578
579
580
581
582 public DnsNameResolverBuilder ndots(int ndots) {
583 this.ndots = ndots;
584 return this;
585 }
586
587 DnsCache getOrNewCache() {
588 if (this.resolveCache != null) {
589 return this.resolveCache;
590 }
591 return new DefaultDnsCache(intValue(minTtl, 0), intValue(maxTtl, Integer.MAX_VALUE), intValue(negativeTtl, 0));
592 }
593
594 AuthoritativeDnsServerCache getOrNewAuthoritativeDnsServerCache() {
595 if (this.authoritativeDnsServerCache != null) {
596 return this.authoritativeDnsServerCache;
597 }
598 return new DefaultAuthoritativeDnsServerCache(
599 intValue(minTtl, 0), intValue(maxTtl, Integer.MAX_VALUE),
600
601
602 new NameServerComparator(DnsNameResolver.addressType(
603 DnsNameResolver.preferredAddressType(resolvedAddressTypes))));
604 }
605
606 private DnsServerAddressStream newQueryServerAddressStream(
607 DnsServerAddressStreamProvider dnsServerAddressStreamProvider) {
608 return new ThreadLocalNameServerAddressStream(dnsServerAddressStreamProvider);
609 }
610
611 DnsCnameCache getOrNewCnameCache() {
612 if (this.cnameCache != null) {
613 return this.cnameCache;
614 }
615 return new DefaultDnsCnameCache(
616 intValue(minTtl, 0), intValue(maxTtl, Integer.MAX_VALUE));
617 }
618
619
620
621
622
623
624
625
626 public DnsNameResolverBuilder decodeIdn(boolean decodeIdn) {
627 this.decodeIdn = decodeIdn;
628 return this;
629 }
630
631
632
633
634
635
636
637
638
639
640 public DnsNameResolverBuilder consolidateCacheSize(int maxNumConsolidation) {
641 this.maxNumConsolidation = ObjectUtil.checkPositiveOrZero(maxNumConsolidation, "maxNumConsolidation");
642 return this;
643 }
644
645
646
647
648
649
650
651
652
653 public DnsNameResolverBuilder datagramChannelStrategy(DnsNameResolverChannelStrategy datagramChannelStrategy) {
654 this.datagramChannelStrategy = ObjectUtil.checkNotNull(datagramChannelStrategy, "datagramChannelStrategy");
655 return this;
656 }
657
658
659
660
661
662
663 public DnsNameResolver build() {
664 if (eventLoop == null) {
665 throw new IllegalStateException("eventLoop should be specified to build a DnsNameResolver.");
666 }
667
668 if (resolveCache != null && (minTtl != null || maxTtl != null || negativeTtl != null)) {
669 logger.debug("resolveCache and TTLs are mutually exclusive. TTLs are ignored.");
670 }
671
672 if (cnameCache != null && (minTtl != null || maxTtl != null || negativeTtl != null)) {
673 logger.debug("cnameCache and TTLs are mutually exclusive. TTLs are ignored.");
674 }
675
676 if (authoritativeDnsServerCache != null && (minTtl != null || maxTtl != null || negativeTtl != null)) {
677 logger.debug("authoritativeDnsServerCache and TTLs are mutually exclusive. TTLs are ignored.");
678 }
679
680 DnsCache resolveCache = getOrNewCache();
681 DnsCnameCache cnameCache = getOrNewCnameCache();
682 AuthoritativeDnsServerCache authoritativeDnsServerCache = getOrNewAuthoritativeDnsServerCache();
683
684 DnsServerAddressStream queryDnsServerAddressStream = this.queryDnsServerAddressStream != null ?
685 this.queryDnsServerAddressStream : newQueryServerAddressStream(dnsServerAddressStreamProvider);
686
687 return new DnsNameResolver(
688 eventLoop,
689 datagramChannelFactory,
690 socketChannelFactory,
691 retryOnTimeout,
692 resolveCache,
693 cnameCache,
694 authoritativeDnsServerCache,
695 localAddress,
696 dnsQueryLifecycleObserverFactory,
697 queryTimeoutMillis,
698 resolvedAddressTypes,
699 recursionDesired,
700 maxQueriesPerResolve,
701 traceEnabled,
702 maxPayloadSize,
703 optResourceEnabled,
704 hostsFileEntriesResolver,
705 dnsServerAddressStreamProvider,
706 queryDnsServerAddressStream,
707 searchDomains,
708 ndots,
709 decodeIdn,
710 completeOncePreferredResolved,
711 maxNumConsolidation,
712 datagramChannelStrategy);
713 }
714
715
716
717
718
719
720 public DnsNameResolverBuilder copy() {
721 DnsNameResolverBuilder copiedBuilder = new DnsNameResolverBuilder();
722
723 if (eventLoop != null) {
724 copiedBuilder.eventLoop(eventLoop);
725 }
726
727 if (datagramChannelFactory != null) {
728 copiedBuilder.datagramChannelFactory(datagramChannelFactory);
729 }
730
731 copiedBuilder.socketChannelFactory(socketChannelFactory, retryOnTimeout);
732
733 if (resolveCache != null) {
734 copiedBuilder.resolveCache(resolveCache);
735 }
736
737 if (cnameCache != null) {
738 copiedBuilder.cnameCache(cnameCache);
739 }
740 if (maxTtl != null && minTtl != null) {
741 copiedBuilder.ttl(minTtl, maxTtl);
742 }
743
744 if (negativeTtl != null) {
745 copiedBuilder.negativeTtl(negativeTtl);
746 }
747
748 if (authoritativeDnsServerCache != null) {
749 copiedBuilder.authoritativeDnsServerCache(authoritativeDnsServerCache);
750 }
751
752 if (dnsQueryLifecycleObserverFactory != null) {
753 copiedBuilder.dnsQueryLifecycleObserverFactory(dnsQueryLifecycleObserverFactory);
754 }
755
756 copiedBuilder.queryTimeoutMillis(queryTimeoutMillis);
757 copiedBuilder.resolvedAddressTypes(resolvedAddressTypes);
758 copiedBuilder.recursionDesired(recursionDesired);
759 copiedBuilder.maxQueriesPerResolve(maxQueriesPerResolve);
760 copiedBuilder.traceEnabled(traceEnabled);
761 copiedBuilder.maxPayloadSize(maxPayloadSize);
762 copiedBuilder.optResourceEnabled(optResourceEnabled);
763 copiedBuilder.hostsFileEntriesResolver(hostsFileEntriesResolver);
764
765 if (dnsServerAddressStreamProvider != null) {
766 copiedBuilder.nameServerProvider(dnsServerAddressStreamProvider);
767 }
768
769 if (queryDnsServerAddressStream != null) {
770 copiedBuilder.queryServerAddressStream(queryDnsServerAddressStream);
771 }
772
773 if (searchDomains != null) {
774 copiedBuilder.searchDomains(Arrays.asList(searchDomains));
775 }
776
777 copiedBuilder.ndots(ndots);
778 copiedBuilder.decodeIdn(decodeIdn);
779 copiedBuilder.completeOncePreferredResolved(completeOncePreferredResolved);
780 copiedBuilder.localAddress(localAddress);
781 copiedBuilder.consolidateCacheSize(maxNumConsolidation);
782 copiedBuilder.datagramChannelStrategy(datagramChannelStrategy);
783 return copiedBuilder;
784 }
785 }