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.util.internal.PlatformDependent;
19 import io.netty.util.internal.logging.InternalLogger;
20 import io.netty.util.internal.logging.InternalLoggerFactory;
21
22 import java.lang.reflect.Constructor;
23 import java.lang.reflect.InvocationTargetException;
24 import java.security.AccessController;
25 import java.security.PrivilegedAction;
26 import java.util.concurrent.TimeUnit;
27 import java.util.concurrent.atomic.AtomicLong;
28
29
30
31
32 public final class DnsServerAddressStreamProviders {
33
34 private static final InternalLogger LOGGER =
35 InternalLoggerFactory.getInstance(DnsServerAddressStreamProviders.class);
36 private static final Constructor<? extends DnsServerAddressStreamProvider> STREAM_PROVIDER_CONSTRUCTOR;
37 private static final String MACOS_PROVIDER_CLASS_NAME =
38 "io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider";
39
40 static {
41 Constructor<? extends DnsServerAddressStreamProvider> constructor = null;
42 if (PlatformDependent.isOsx()) {
43 try {
44
45
46 Object maybeProvider = AccessController.doPrivileged(new PrivilegedAction<Object>() {
47 @Override
48 public Object run() {
49 try {
50 return Class.forName(
51 MACOS_PROVIDER_CLASS_NAME,
52 true,
53 DnsServerAddressStreamProviders.class.getClassLoader());
54 } catch (Throwable cause) {
55 return cause;
56 }
57 }
58 });
59 if (maybeProvider instanceof Class) {
60 @SuppressWarnings("unchecked")
61 Class<? extends DnsServerAddressStreamProvider> providerClass =
62 (Class<? extends DnsServerAddressStreamProvider>) maybeProvider;
63 constructor = providerClass.getConstructor();
64 constructor.newInstance();
65 LOGGER.debug("{}: available", MACOS_PROVIDER_CLASS_NAME);
66 } else {
67 throw (Throwable) maybeProvider;
68 }
69 } catch (ClassNotFoundException cause) {
70 LOGGER.warn("Can not find {} in the classpath, fallback to system defaults. This may result in "
71 + "incorrect DNS resolutions on MacOS. Check whether you have a dependency on "
72 + "'io.netty:netty-resolver-dns-native-macos'", MACOS_PROVIDER_CLASS_NAME);
73 } catch (Throwable cause) {
74 if (LOGGER.isDebugEnabled()) {
75 LOGGER.error("Unable to load {}, fallback to system defaults. This may result in "
76 + "incorrect DNS resolutions on MacOS. Check whether you have a dependency on "
77 + "'io.netty:netty-resolver-dns-native-macos'", MACOS_PROVIDER_CLASS_NAME, cause);
78 } else {
79 LOGGER.error("Unable to load {}, fallback to system defaults. This may result in "
80 + "incorrect DNS resolutions on MacOS. Check whether you have a dependency on "
81 + "'io.netty:netty-resolver-dns-native-macos'. Use DEBUG level to see the full stack: {}",
82 MACOS_PROVIDER_CLASS_NAME,
83 cause.getCause() != null ? cause.getCause().toString() : cause.toString());
84 }
85 constructor = null;
86 }
87 }
88 STREAM_PROVIDER_CONSTRUCTOR = constructor;
89 }
90
91 private DnsServerAddressStreamProviders() {
92 }
93
94
95
96
97
98
99
100
101 public static DnsServerAddressStreamProvider platformDefault() {
102 if (STREAM_PROVIDER_CONSTRUCTOR != null) {
103 try {
104 return STREAM_PROVIDER_CONSTRUCTOR.newInstance();
105 } catch (IllegalAccessException e) {
106
107 } catch (InstantiationException e) {
108
109 } catch (InvocationTargetException e) {
110
111 }
112 }
113 return unixDefault();
114 }
115
116 public static DnsServerAddressStreamProvider unixDefault() {
117 return DefaultProviderHolder.DEFAULT_DNS_SERVER_ADDRESS_STREAM_PROVIDER;
118 }
119
120
121
122 private static final class DefaultProviderHolder {
123
124 private static final long REFRESH_INTERVAL = TimeUnit.MINUTES.toNanos(5);
125
126
127
128 static final DnsServerAddressStreamProvider DEFAULT_DNS_SERVER_ADDRESS_STREAM_PROVIDER =
129 new DnsServerAddressStreamProvider() {
130 private volatile DnsServerAddressStreamProvider currentProvider = provider();
131 private final AtomicLong lastRefresh = new AtomicLong(System.nanoTime());
132
133 @Override
134 public DnsServerAddressStream nameServerAddressStream(String hostname) {
135 long last = lastRefresh.get();
136 DnsServerAddressStreamProvider current = currentProvider;
137 if (System.nanoTime() - last > REFRESH_INTERVAL) {
138
139
140 if (lastRefresh.compareAndSet(last, System.nanoTime())) {
141 current = currentProvider = provider();
142 }
143 }
144 return current.nameServerAddressStream(hostname);
145 }
146
147 private DnsServerAddressStreamProvider provider() {
148
149
150 return PlatformDependent.isWindows() ? DefaultDnsServerAddressStreamProvider.INSTANCE :
151 UnixResolverDnsServerAddressStreamProvider.parseSilently();
152 }
153 };
154 }
155 }