1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.resolver.dns;
17
18 import io.netty5.util.internal.PlatformDependent;
19 import io.netty5.util.internal.logging.InternalLogger;
20 import io.netty5.util.internal.logging.InternalLoggerFactory;
21
22 import java.lang.invoke.MethodHandle;
23 import java.lang.invoke.MethodHandles;
24 import java.lang.invoke.MethodType;
25 import java.lang.reflect.InvocationTargetException;
26 import java.security.AccessController;
27 import java.security.PrivilegedAction;
28 import java.util.concurrent.TimeUnit;
29 import java.util.concurrent.atomic.AtomicLong;
30
31
32
33
34 public final class DnsServerAddressStreamProviders {
35
36 private static final InternalLogger LOGGER =
37 InternalLoggerFactory.getInstance(DnsServerAddressStreamProviders.class);
38 private static final MethodHandle STREAM_PROVIDER_CONSTRUCTOR_HANDLE;
39 private static final String MACOS_PROVIDER_CLASS_NAME =
40 "io.netty5.resolver.dns.macos.MacOSDnsServerAddressStreamProvider";
41
42 static {
43 MethodHandle constructorHandle = null;
44 if (PlatformDependent.isOsx()) {
45 try {
46
47
48 Object maybeProvider = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
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 if (maybeProvider instanceof Class) {
59 @SuppressWarnings("unchecked")
60 Class<? extends DnsServerAddressStreamProvider> providerClass =
61 (Class<? extends DnsServerAddressStreamProvider>) maybeProvider;
62 MethodHandles.Lookup lookup = MethodHandles.lookup();
63 constructorHandle = lookup.findConstructor(providerClass, MethodType.methodType(void.class));
64 constructorHandle.invoke();
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.", MACOS_PROVIDER_CLASS_NAME);
72 } catch (Throwable cause) {
73 LOGGER.error("Unable to load {}, fallback to system defaults. This may result in "
74 + "incorrect DNS resolutions on MacOS.", MACOS_PROVIDER_CLASS_NAME, cause);
75 constructorHandle = null;
76 }
77 }
78 STREAM_PROVIDER_CONSTRUCTOR_HANDLE = constructorHandle;
79 }
80
81 private DnsServerAddressStreamProviders() {
82 }
83
84
85
86
87
88
89
90
91 public static DnsServerAddressStreamProvider platformDefault() {
92 if (STREAM_PROVIDER_CONSTRUCTOR_HANDLE != null) {
93 try {
94 return (DnsServerAddressStreamProvider) STREAM_PROVIDER_CONSTRUCTOR_HANDLE.invoke();
95 } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
96
97 } catch (Throwable cause) {
98 PlatformDependent.throwException(cause);
99 }
100 }
101 return unixDefault();
102 }
103
104 public static DnsServerAddressStreamProvider unixDefault() {
105 return DefaultProviderHolder.DEFAULT_DNS_SERVER_ADDRESS_STREAM_PROVIDER;
106 }
107
108
109
110 private static final class DefaultProviderHolder {
111
112 private static final long REFRESH_INTERVAL = TimeUnit.MINUTES.toNanos(5);
113
114
115
116 static final DnsServerAddressStreamProvider DEFAULT_DNS_SERVER_ADDRESS_STREAM_PROVIDER =
117 new DnsServerAddressStreamProvider() {
118 private volatile DnsServerAddressStreamProvider currentProvider = provider();
119 private final AtomicLong lastRefresh = new AtomicLong(System.nanoTime());
120
121 @Override
122 public DnsServerAddressStream nameServerAddressStream(String hostname) {
123 long last = lastRefresh.get();
124 DnsServerAddressStreamProvider current = currentProvider;
125 if (System.nanoTime() - last > REFRESH_INTERVAL) {
126
127
128 if (lastRefresh.compareAndSet(last, System.nanoTime())) {
129 current = currentProvider = provider();
130 }
131 }
132 return current.nameServerAddressStream(hostname);
133 }
134
135 private DnsServerAddressStreamProvider provider() {
136
137
138 return PlatformDependent.isWindows() ? DefaultDnsServerAddressStreamProvider.INSTANCE :
139 UnixResolverDnsServerAddressStreamProvider.parseSilently();
140 }
141 };
142 }
143 }