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