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 }