Use MacOSDnsServerAddressStreamProvider when on the classpath and we … (#10079)
Motivation:
939e928312
introduced MacOSDnsServerAddressStreamProvider which will ensure the right nameservers are selected when running on MacOS. To ensure this is done automatically on MacOS we should use it by default on these platforms.
Modifications:
Try to use MacOSDnsServerAddressStreamProvider when on MacOS via reflection and fallback if not possible
Result:
Ensure the right nameservers are used on MacOS even when a VPN (for example) is used.
This commit is contained in:
parent
161c237fb9
commit
660759b997
@ -42,10 +42,6 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||||||
*/
|
*/
|
||||||
public final class MacOSDnsServerAddressStreamProvider implements DnsServerAddressStreamProvider {
|
public final class MacOSDnsServerAddressStreamProvider implements DnsServerAddressStreamProvider {
|
||||||
|
|
||||||
// Fallback provider
|
|
||||||
private static final DnsServerAddressStreamProvider DEFAULT_PROVIDER =
|
|
||||||
DnsServerAddressStreamProviders.platformDefault();
|
|
||||||
|
|
||||||
private static final Throwable UNAVAILABILITY_CAUSE;
|
private static final Throwable UNAVAILABILITY_CAUSE;
|
||||||
|
|
||||||
private static final InternalLogger logger =
|
private static final InternalLogger logger =
|
||||||
@ -167,7 +163,7 @@ public final class MacOSDnsServerAddressStreamProvider implements DnsServerAddre
|
|||||||
if (addresses != null) {
|
if (addresses != null) {
|
||||||
return addresses.stream();
|
return addresses.stream();
|
||||||
}
|
}
|
||||||
return DEFAULT_PROVIDER.nameServerAddressStream(originalHostname);
|
return DnsServerAddressStreamProviders.unixDefault().nameServerAddressStream(originalHostname);
|
||||||
}
|
}
|
||||||
|
|
||||||
DnsServerAddresses addresses = resolverMap.get(hostname);
|
DnsServerAddresses addresses = resolverMap.get(hostname);
|
||||||
|
@ -17,6 +17,8 @@ package io.netty.resolver.dns.macos;
|
|||||||
|
|
||||||
import io.netty.resolver.dns.DnsServerAddressStream;
|
import io.netty.resolver.dns.DnsServerAddressStream;
|
||||||
import io.netty.resolver.dns.DnsServerAddressStreamProvider;
|
import io.netty.resolver.dns.DnsServerAddressStreamProvider;
|
||||||
|
import io.netty.resolver.dns.DnsServerAddressStreamProviders;
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Assume;
|
import org.junit.Assume;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
@ -30,7 +32,7 @@ public class MacOSDnsServerAddressStreamProviderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void testStream() {
|
||||||
DnsServerAddressStreamProvider provider = new MacOSDnsServerAddressStreamProvider();
|
DnsServerAddressStreamProvider provider = new MacOSDnsServerAddressStreamProvider();
|
||||||
DnsServerAddressStream stream = provider.nameServerAddressStream("netty.io");
|
DnsServerAddressStream stream = provider.nameServerAddressStream("netty.io");
|
||||||
Assert.assertNotNull(stream);
|
Assert.assertNotNull(stream);
|
||||||
@ -40,4 +42,11 @@ public class MacOSDnsServerAddressStreamProviderTest {
|
|||||||
Assert.assertNotEquals(0, stream.next().getPort());
|
Assert.assertNotEquals(0, stream.next().getPort());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultUseCorrectInstance() {
|
||||||
|
Assert.assertThat(DnsServerAddressStreamProviders.platformDefault(),
|
||||||
|
Matchers.instanceOf(MacOSDnsServerAddressStreamProvider.class));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,14 @@
|
|||||||
package io.netty.resolver.dns;
|
package io.netty.resolver.dns;
|
||||||
|
|
||||||
import io.netty.util.internal.PlatformDependent;
|
import io.netty.util.internal.PlatformDependent;
|
||||||
|
import io.netty.util.internal.logging.InternalLogger;
|
||||||
|
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
@ -24,12 +31,88 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||||||
* Utility methods related to {@link DnsServerAddressStreamProvider}.
|
* Utility methods related to {@link DnsServerAddressStreamProvider}.
|
||||||
*/
|
*/
|
||||||
public final class DnsServerAddressStreamProviders {
|
public final class DnsServerAddressStreamProviders {
|
||||||
|
|
||||||
|
private static final InternalLogger LOGGER =
|
||||||
|
InternalLoggerFactory.getInstance(DnsServerAddressStreamProviders.class);
|
||||||
|
private static final Constructor<? extends DnsServerAddressStreamProvider> STREAM_PROVIDER_CONSTRUCTOR;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Constructor<? extends DnsServerAddressStreamProvider> constructor = null;
|
||||||
|
if (PlatformDependent.isOsx()) {
|
||||||
|
try {
|
||||||
|
// As MacOSDnsServerAddressStreamProvider is contained in another jar which depends on this jar
|
||||||
|
// we use reflection to use it if its on the classpath.
|
||||||
|
Object maybeProvider = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
@Override
|
||||||
|
public Object run() {
|
||||||
|
try {
|
||||||
|
return Class.forName(
|
||||||
|
"io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider",
|
||||||
|
true,
|
||||||
|
DnsServerAddressStreamProviders.class.getClassLoader());
|
||||||
|
} catch (Throwable cause) {
|
||||||
|
return cause;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (maybeProvider instanceof Class) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Class<? extends DnsServerAddressStreamProvider> providerClass =
|
||||||
|
(Class<? extends DnsServerAddressStreamProvider>) maybeProvider;
|
||||||
|
Method method = providerClass.getMethod("ensureAvailability");
|
||||||
|
method.invoke(null);
|
||||||
|
constructor = providerClass.getConstructor();
|
||||||
|
constructor.newInstance();
|
||||||
|
} else if (!(maybeProvider instanceof ClassNotFoundException)) {
|
||||||
|
throw (Throwable) maybeProvider;
|
||||||
|
}
|
||||||
|
} catch (Throwable cause) {
|
||||||
|
LOGGER.debug(
|
||||||
|
"Unable to use MacOSDnsServerAddressStreamProvider, fallback to system defaults", cause);
|
||||||
|
constructor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
STREAM_PROVIDER_CONSTRUCTOR = constructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DnsServerAddressStreamProviders() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link DnsServerAddressStreamProvider} which inherits the DNS servers from your local host's configuration.
|
||||||
|
* <p>
|
||||||
|
* Note that only macOS and Linux are currently supported.
|
||||||
|
* @return A {@link DnsServerAddressStreamProvider} which inherits the DNS servers from your local host's
|
||||||
|
* configuration.
|
||||||
|
*/
|
||||||
|
public static DnsServerAddressStreamProvider platformDefault() {
|
||||||
|
if (STREAM_PROVIDER_CONSTRUCTOR != null) {
|
||||||
|
try {
|
||||||
|
return STREAM_PROVIDER_CONSTRUCTOR.newInstance();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// ignore
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
// ignore
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return unixDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DnsServerAddressStreamProvider unixDefault() {
|
||||||
|
return DefaultProviderHolder.DEFAULT_DNS_SERVER_ADDRESS_STREAM_PROVIDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We use a Holder class to only initialize DEFAULT_DNS_SERVER_ADDRESS_STREAM_PROVIDER if we really
|
||||||
|
// need it.
|
||||||
|
private static final class DefaultProviderHolder {
|
||||||
// We use 5 minutes which is the same as what OpenJDK is using in sun.net.dns.ResolverConfigurationImpl.
|
// We use 5 minutes which is the same as what OpenJDK is using in sun.net.dns.ResolverConfigurationImpl.
|
||||||
private static final long REFRESH_INTERVAL = TimeUnit.MINUTES.toNanos(5);
|
private static final long REFRESH_INTERVAL = TimeUnit.MINUTES.toNanos(5);
|
||||||
|
|
||||||
// TODO(scott): how is this done on Windows? This may require a JNI call to GetNetworkParams
|
// TODO(scott): how is this done on Windows? This may require a JNI call to GetNetworkParams
|
||||||
// https://msdn.microsoft.com/en-us/library/aa365968(VS.85).aspx.
|
// https://msdn.microsoft.com/en-us/library/aa365968(VS.85).aspx.
|
||||||
private static final DnsServerAddressStreamProvider DEFAULT_DNS_SERVER_ADDRESS_STREAM_PROVIDER =
|
static final DnsServerAddressStreamProvider DEFAULT_DNS_SERVER_ADDRESS_STREAM_PROVIDER =
|
||||||
new DnsServerAddressStreamProvider() {
|
new DnsServerAddressStreamProvider() {
|
||||||
private volatile DnsServerAddressStreamProvider currentProvider = provider();
|
private volatile DnsServerAddressStreamProvider currentProvider = provider();
|
||||||
private final AtomicLong lastRefresh = new AtomicLong(System.nanoTime());
|
private final AtomicLong lastRefresh = new AtomicLong(System.nanoTime());
|
||||||
@ -39,8 +122,8 @@ public final class DnsServerAddressStreamProviders {
|
|||||||
long last = lastRefresh.get();
|
long last = lastRefresh.get();
|
||||||
DnsServerAddressStreamProvider current = currentProvider;
|
DnsServerAddressStreamProvider current = currentProvider;
|
||||||
if (System.nanoTime() - last > REFRESH_INTERVAL) {
|
if (System.nanoTime() - last > REFRESH_INTERVAL) {
|
||||||
// This is slightly racy which means it will be possible still use the old configuration for a small
|
// This is slightly racy which means it will be possible still use the old configuration
|
||||||
// amount of time, but that's ok.
|
// for a small amount of time, but that's ok.
|
||||||
if (lastRefresh.compareAndSet(last, System.nanoTime())) {
|
if (lastRefresh.compareAndSet(last, System.nanoTime())) {
|
||||||
current = currentProvider = provider();
|
current = currentProvider = provider();
|
||||||
}
|
}
|
||||||
@ -55,18 +138,5 @@ public final class DnsServerAddressStreamProviders {
|
|||||||
UnixResolverDnsServerAddressStreamProvider.parseSilently();
|
UnixResolverDnsServerAddressStreamProvider.parseSilently();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private DnsServerAddressStreamProviders() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link DnsServerAddressStreamProvider} which inherits the DNS servers from your local host's configuration.
|
|
||||||
* <p>
|
|
||||||
* Note that only macOS and Linux are currently supported.
|
|
||||||
* @return A {@link DnsServerAddressStreamProvider} which inherits the DNS servers from your local host's
|
|
||||||
* configuration.
|
|
||||||
*/
|
|
||||||
public static DnsServerAddressStreamProvider platformDefault() {
|
|
||||||
return DEFAULT_DNS_SERVER_ADDRESS_STREAM_PROVIDER;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/package io.netty.resolver.dns;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class DnsServerAddressStreamProvidersTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUseCorrectProvider() {
|
||||||
|
Assert.assertSame(DnsServerAddressStreamProviders.unixDefault(),
|
||||||
|
DnsServerAddressStreamProviders.platformDefault());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user