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