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