42
42
import io .netty .util .concurrent .FastThreadLocal ;
43
43
import io .netty .util .concurrent .Future ;
44
44
import io .netty .util .concurrent .Promise ;
45
+ import io .netty .util .internal .EmptyArrays ;
45
46
import io .netty .util .internal .PlatformDependent ;
47
+ import io .netty .util .internal .StringUtil2 ;
46
48
import io .netty .util .internal .logging .InternalLogger ;
47
49
import io .netty .util .internal .logging .InternalLoggerFactory ;
48
50
51
+ import java .lang .reflect .Method ;
49
52
import java .net .IDN ;
50
53
import java .net .Inet4Address ;
51
54
import java .net .InetAddress ;
@@ -67,6 +70,7 @@ public class DnsNameResolver extends InetNameResolver {
67
70
private static final InetAddress LOCALHOST_ADDRESS ;
68
71
69
72
static final InternetProtocolFamily [] DEFAULT_RESOLVE_ADDRESS_TYPES = new InternetProtocolFamily [2 ];
73
+ static final String [] DEFAULT_SEACH_DOMAINS ;
70
74
71
75
static {
72
76
// Note that we did not use SystemPropertyUtil.getBoolean() here to emulate the behavior of JDK.
@@ -83,6 +87,24 @@ public class DnsNameResolver extends InetNameResolver {
83
87
}
84
88
}
85
89
90
+ static {
91
+ String [] searchDomains ;
92
+ try {
93
+ Class <?> configClass = Class .forName ("sun.net.dns.ResolverConfiguration" );
94
+ Method open = configClass .getMethod ("open" );
95
+ Method nameservers = configClass .getMethod ("searchlist" );
96
+ Object instance = open .invoke (null );
97
+
98
+ @ SuppressWarnings ("unchecked" )
99
+ List <String > list = (List <String >) nameservers .invoke (instance );
100
+ searchDomains = list .toArray (new String [list .size ()]);
101
+ } catch (Exception ignore ) {
102
+ // Failed to get the system name search domain list.
103
+ searchDomains = EmptyArrays .EMPTY_STRINGS ;
104
+ }
105
+ DEFAULT_SEACH_DOMAINS = searchDomains ;
106
+ }
107
+
86
108
private static final DatagramDnsResponseDecoder DECODER = new DatagramDnsResponseDecoder ();
87
109
private static final DatagramDnsQueryEncoder ENCODER = new DatagramDnsQueryEncoder ();
88
110
@@ -116,6 +138,8 @@ protected DnsServerAddressStream initialValue() throws Exception {
116
138
private final int maxPayloadSize ;
117
139
private final boolean optResourceEnabled ;
118
140
private final HostsFileEntriesResolver hostsFileEntriesResolver ;
141
+ private final String [] searchDomains ;
142
+ private final int ndots ;
119
143
120
144
/**
121
145
* Creates a new DNS-based name resolver that communicates with the specified list of DNS servers.
@@ -134,6 +158,8 @@ protected DnsServerAddressStream initialValue() throws Exception {
134
158
* @param maxPayloadSize the capacity of the datagram packet buffer
135
159
* @param optResourceEnabled if automatic inclusion of a optional records is enabled
136
160
* @param hostsFileEntriesResolver the {@link HostsFileEntriesResolver} used to check for local aliases
161
+ * @param searchDomains the list of search domain
162
+ * @param ndots the ndots value
137
163
*/
138
164
public DnsNameResolver (
139
165
EventLoop eventLoop ,
@@ -147,7 +173,9 @@ public DnsNameResolver(
147
173
boolean traceEnabled ,
148
174
int maxPayloadSize ,
149
175
boolean optResourceEnabled ,
150
- HostsFileEntriesResolver hostsFileEntriesResolver ) {
176
+ HostsFileEntriesResolver hostsFileEntriesResolver ,
177
+ String [] searchDomains ,
178
+ int ndots ) {
151
179
152
180
super (eventLoop );
153
181
checkNotNull (channelFactory , "channelFactory" );
@@ -161,6 +189,8 @@ public DnsNameResolver(
161
189
this .optResourceEnabled = optResourceEnabled ;
162
190
this .hostsFileEntriesResolver = checkNotNull (hostsFileEntriesResolver , "hostsFileEntriesResolver" );
163
191
this .resolveCache = resolveCache ;
192
+ this .searchDomains = checkNotNull (searchDomains , "searchDomains" ).clone ();
193
+ this .ndots = checkPositive (ndots , "ndots" );
164
194
165
195
Bootstrap b = new Bootstrap ();
166
196
b .group (executor ());
@@ -214,6 +244,14 @@ InternetProtocolFamily[] resolveAddressTypesUnsafe() {
214
244
return resolvedAddressTypes ;
215
245
}
216
246
247
+ final String [] searchDomains () {
248
+ return searchDomains ;
249
+ }
250
+
251
+ final int ndots () {
252
+ return ndots ;
253
+ }
254
+
217
255
/**
218
256
* Returns {@code true} if and only if this resolver sends a DNS query with the RD (recursion desired) flag set.
219
257
* The default value is {@code true}.
@@ -375,25 +413,37 @@ private static void setSuccess(Promise<InetAddress> promise, InetAddress result)
375
413
private void doResolveUncached (String hostname ,
376
414
Promise <InetAddress > promise ,
377
415
DnsCache resolveCache ) {
378
- final DnsNameResolverContext <InetAddress > ctx =
379
- new DnsNameResolverContext <InetAddress >(this , hostname , promise , resolveCache ) {
380
- @ Override
381
- protected boolean finishResolve (
382
- InternetProtocolFamily f , List <DnsCacheEntry > resolvedEntries ) {
383
-
384
- final int numEntries = resolvedEntries .size ();
385
- for (int i = 0 ; i < numEntries ; i ++) {
386
- final InetAddress a = resolvedEntries .get (i ).address ();
387
- if (addressMatchFamily (a , f )) {
388
- setSuccess (promise (), a );
389
- return true ;
390
- }
391
- }
392
- return false ;
393
- }
394
- };
416
+ SingleResolverContext ctx = new SingleResolverContext (this , hostname , resolveCache );
417
+ ctx .resolve (promise );
418
+ }
419
+
420
+ final class SingleResolverContext extends DnsNameResolverContext <InetAddress > {
421
+
422
+ SingleResolverContext (DnsNameResolver parent , String hostname , DnsCache resolveCache ) {
423
+ super (parent , hostname , resolveCache );
424
+ }
395
425
396
- ctx .resolve ();
426
+ @ Override
427
+ DnsNameResolverContext <InetAddress > newResolverContext (DnsNameResolver parent ,
428
+ String hostname , DnsCache resolveCache ) {
429
+ return new SingleResolverContext (parent , hostname , resolveCache );
430
+ }
431
+
432
+ @ Override
433
+ boolean finishResolve (
434
+ InternetProtocolFamily f , List <DnsCacheEntry > resolvedEntries ,
435
+ Promise <InetAddress > promise ) {
436
+
437
+ final int numEntries = resolvedEntries .size ();
438
+ for (int i = 0 ; i < numEntries ; i ++) {
439
+ final InetAddress a = resolvedEntries .get (i ).address ();
440
+ if (addressMatchFamily (a , f )) {
441
+ setSuccess (promise , a );
442
+ return true ;
443
+ }
444
+ }
445
+ return false ;
446
+ }
397
447
}
398
448
399
449
@ Override
@@ -471,40 +521,56 @@ private boolean doResolveAllCached(String hostname,
471
521
return true ;
472
522
}
473
523
474
- private void doResolveAllUncached (final String hostname ,
475
- final Promise <List <InetAddress >> promise ,
476
- DnsCache resolveCache ) {
477
- final DnsNameResolverContext <List <InetAddress >> ctx =
478
- new DnsNameResolverContext <List <InetAddress >>(this , hostname , promise , resolveCache ) {
479
- @ Override
480
- protected boolean finishResolve (
481
- InternetProtocolFamily f , List <DnsCacheEntry > resolvedEntries ) {
482
-
483
- List <InetAddress > result = null ;
484
- final int numEntries = resolvedEntries .size ();
485
- for (int i = 0 ; i < numEntries ; i ++) {
486
- final InetAddress a = resolvedEntries .get (i ).address ();
487
- if (addressMatchFamily (a , f )) {
488
- if (result == null ) {
489
- result = new ArrayList <InetAddress >(numEntries );
490
- }
491
- result .add (a );
492
- }
493
- }
524
+ final class ListResolverContext extends DnsNameResolverContext <List <InetAddress >> {
525
+ ListResolverContext (DnsNameResolver parent , String hostname , DnsCache resolveCache ) {
526
+ super (parent , hostname , resolveCache );
527
+ }
494
528
495
- if (result != null ) {
496
- promise ().trySuccess (result );
497
- return true ;
498
- }
499
- return false ;
529
+ @ Override
530
+ DnsNameResolverContext <List <InetAddress >> newResolverContext (DnsNameResolver parent , String hostname ,
531
+ DnsCache resolveCache ) {
532
+ return new ListResolverContext (parent , hostname , resolveCache );
533
+ }
534
+
535
+ @ Override
536
+ boolean finishResolve (
537
+ InternetProtocolFamily f , List <DnsCacheEntry > resolvedEntries ,
538
+ Promise <List <InetAddress >> promise ) {
539
+
540
+ List <InetAddress > result = null ;
541
+ final int numEntries = resolvedEntries .size ();
542
+ for (int i = 0 ; i < numEntries ; i ++) {
543
+ final InetAddress a = resolvedEntries .get (i ).address ();
544
+ if (addressMatchFamily (a , f )) {
545
+ if (result == null ) {
546
+ result = new ArrayList <InetAddress >(numEntries );
500
547
}
501
- };
548
+ result .add (a );
549
+ }
550
+ }
551
+
552
+ if (result != null ) {
553
+ promise .trySuccess (result );
554
+ return true ;
555
+ }
556
+ return false ;
557
+ }
558
+ }
502
559
503
- ctx .resolve ();
560
+ private void doResolveAllUncached (String hostname ,
561
+ Promise <List <InetAddress >> promise ,
562
+ DnsCache resolveCache ) {
563
+ DnsNameResolverContext <List <InetAddress >> ctx = new ListResolverContext (this , hostname , resolveCache );
564
+ ctx .resolve (promise );
504
565
}
505
566
506
567
private static String hostname (String inetHost ) {
507
- return IDN .toASCII (inetHost );
568
+ String hostname = IDN .toASCII (inetHost );
569
+ // Check for http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6894622
570
+ if (StringUtil2 .endsWith (inetHost , '.' ) && !StringUtil2 .endsWith (hostname , '.' )) {
571
+ hostname += "." ;
572
+ }
573
+ return hostname ;
508
574
}
509
575
510
576
/**
0 commit comments