From d1bbde9308d3535bd830daf15e230b03a121e043 Mon Sep 17 00:00:00 2001 From: Tux Date: Wed, 21 Dec 2016 03:13:03 -0500 Subject: [PATCH] Optionally use async Netty DNS resolver We no longer need to cache the address for the session server now. diff --git a/api/src/main/java/net/md_5/bungee/api/ProxyConfig.java b/api/src/main/java/net/md_5/bungee/api/ProxyConfig.java index 749059ab..6141128b 100644 --- a/api/src/main/java/net/md_5/bungee/api/ProxyConfig.java +++ b/api/src/main/java/net/md_5/bungee/api/ProxyConfig.java @@ -221,6 +221,13 @@ public interface ProxyConfig */ String getGameVersion(); + /** + * Whether Netty's async DNS resolver is used for account authentication. + * + * @return whether Netty's async DNS resolver is used for account authentication. + */ + boolean isUseNettyDnsResolver(); + // Throttling options /** diff --git a/proxy/pom.xml b/proxy/pom.xml index f5610a53..31e172c7 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -36,6 +36,20 @@ ${netty.version} compile + + + io.netty + netty-resolver-dns + ${netty.version} + compile + + + io.netty + netty-resolver-dns-native-macos + ${netty.version} + osx-x86_64 + + io.netty netty-handler diff --git a/proxy/src/main/java/io/github/waterfallmc/waterfall/conf/WaterfallConfiguration.java b/proxy/src/main/java/io/github/waterfallmc/waterfall/conf/WaterfallConfiguration.java index 111404fb..ef44d334 100644 --- a/proxy/src/main/java/io/github/waterfallmc/waterfall/conf/WaterfallConfiguration.java +++ b/proxy/src/main/java/io/github/waterfallmc/waterfall/conf/WaterfallConfiguration.java @@ -15,6 +15,12 @@ public class WaterfallConfiguration extends Configuration { */ private String gameVersion; + /** + * Whether we use Netty's async DNS resolver for the HttpClient. + *

Default is true (use Netty's async DNS resolver)

+ */ + private boolean useNettyDnsResolver = true; + /* * Throttling options * Helps prevent players from overloading the servers behind us @@ -35,6 +41,7 @@ public class WaterfallConfiguration extends Configuration { YamlConfig config = new YamlConfig(new File("waterfall.yml")); config.load(false); // Load, but no permissions gameVersion = config.getString("game_version", "").isEmpty() ? Joiner.on(", ").join(ProtocolConstants.SUPPORTED_VERSIONS) : config.getString("game_version", ""); + useNettyDnsResolver = config.getBoolean("use_netty_dns_resolver", useNettyDnsResolver); // Throttling options tabThrottle = config.getInt("throttling.tab_complete", tabThrottle); disableModernTabLimiter = config.getBoolean("disable_modern_tab_limiter", disableModernTabLimiter); @@ -45,6 +52,11 @@ public class WaterfallConfiguration extends Configuration { return gameVersion; } + @Override + public boolean isUseNettyDnsResolver() { + return useNettyDnsResolver; + } + @Override public int getTabThrottle() { return tabThrottle; diff --git a/proxy/src/main/java/net/md_5/bungee/http/HttpClient.java b/proxy/src/main/java/net/md_5/bungee/http/HttpClient.java index e0c52f21..37337429 100644 --- a/proxy/src/main/java/net/md_5/bungee/http/HttpClient.java +++ b/proxy/src/main/java/net/md_5/bungee/http/HttpClient.java @@ -28,6 +28,10 @@ public class HttpClient public static final int TIMEOUT = 5000; private static final Cache addressCache = CacheBuilder.newBuilder().expireAfterWrite( 1, TimeUnit.MINUTES ).build(); + // Waterfall Start - optionally use async resolver from Netty + private static final io.netty.resolver.dns.DnsAddressResolverGroup dnsResolverGroup = + new io.netty.resolver.dns.DnsAddressResolverGroup(PipelineUtils.getDatagramChannel(), io.netty.resolver.dns.DefaultDnsServerAddressStreamProvider.INSTANCE); + // Waterfall End @SuppressWarnings("UnusedAssignment") public static void get(String url, EventLoop eventLoop, final Callback callback) @@ -57,19 +61,21 @@ public class HttpClient } } - InetAddress inetHost = addressCache.getIfPresent( uri.getHost() ); - if ( inetHost == null ) - { - try - { - inetHost = InetAddress.getByName( uri.getHost() ); - } catch ( UnknownHostException ex ) - { - callback.done( null, ex ); - return; - } - addressCache.put( uri.getHost(), inetHost ); - } + // Waterfall Start - Move address creation to implementation method + //InetAddress inetHost = addressCache.getIfPresent( uri.getHost() ); + //if ( inetHost == null ) + //{ + // try + // { + // inetHost = InetAddress.getByName( uri.getHost() ); + // } catch ( UnknownHostException ex ) + // { + // callback.done( null, ex ); + // return; + // } + // addressCache.put( uri.getHost(), inetHost ); + //} + // Waterfall End ChannelFutureListener future = new ChannelFutureListener() { @@ -92,7 +98,40 @@ public class HttpClient } }; + + // Waterfall Start - Optionally use Netty's async DNS Resolver + if (net.md_5.bungee.api.ProxyServer.getInstance().getConfig().isUseNettyDnsResolver()) { + getWithNettyResolver(eventLoop, uri, port, future, callback, ssl); + } else { + getWithDefaultResolver(eventLoop, uri, port, future, callback, ssl); + } + //new Bootstrap().channel( PipelineUtils.getChannel() ).group( eventLoop ).handler( new HttpInitializer( callback, ssl, uri.getHost(), port ) ). + // option( ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT ).remoteAddress( inetHost, port ).connect().addListener( future ); + } + + private static void getWithNettyResolver(EventLoop eventLoop, URI uri, int port, ChannelFutureListener future, Callback callback, boolean ssl) { + java.net.InetSocketAddress address = java.net.InetSocketAddress.createUnresolved(uri.getHost(), port); + new Bootstrap().channel( PipelineUtils.getChannel( null ) ).group( eventLoop ).handler( new HttpInitializer( callback, ssl, uri.getHost(), port ) ). + option( ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT ).resolver(dnsResolverGroup).remoteAddress( address ).connect().addListener( future ); + } + + private static void getWithDefaultResolver(EventLoop eventLoop, URI uri, int port, ChannelFutureListener future, Callback callback, boolean ssl) { + // This is identical to the Bungee implementation of #get other than the absence of the ChannelFutureListener creation + InetAddress inetHost = addressCache.getIfPresent( uri.getHost() ); + if ( inetHost == null ) + { + try + { + inetHost = InetAddress.getByName( uri.getHost() ); + } catch ( UnknownHostException ex ) + { + callback.done( null, ex ); + return; + } + addressCache.put( uri.getHost(), inetHost ); + } new Bootstrap().channel( PipelineUtils.getChannel( null ) ).group( eventLoop ).handler( new HttpInitializer( callback, ssl, uri.getHost(), port ) ). option( ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT ).remoteAddress( inetHost, port ).connect().addListener( future ); } + // Waterfall End } -- 2.31.0