From ead8a213625603234347b99fa936f2c0a56fb557 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Mon, 29 Jul 2019 00:19:15 -0400 Subject: [PATCH] Most proper clean way of using a DnsAddressResolverGroup with AHC Let us never speak of this again. --- .../proxy/network/ConnectionManager.java | 13 ++-- ...dressResolverGroupNameResolverAdapter.java | 68 +++++++++++++++++++ 2 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/network/netty/DnsAddressResolverGroupNameResolverAdapter.java diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java b/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java index 85f5ca1af..d1c3dba9b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java @@ -6,6 +6,7 @@ import static org.asynchttpclient.Dsl.config; import com.google.common.base.Preconditions; import com.velocitypowered.natives.util.Natives; import com.velocitypowered.proxy.VelocityServer; +import com.velocitypowered.proxy.network.netty.DnsAddressResolverGroupNameResolverAdapter; import com.velocitypowered.proxy.protocol.netty.GS4QueryHandler; import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.ServerBootstrap; @@ -16,6 +17,7 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.WriteBufferWaterMark; import io.netty.resolver.dns.DnsAddressResolverGroup; import io.netty.resolver.dns.DnsNameResolverBuilder; +import io.netty.util.concurrent.EventExecutor; import java.net.InetSocketAddress; import java.util.HashMap; import java.util.Map; @@ -59,13 +61,10 @@ public final class ConnectionManager { this.workerGroup = this.transportType.createEventLoopGroup(TransportType.Type.WORKER); this.serverChannelInitializer = new ServerChannelInitializerHolder( new ServerChannelInitializer(this.server)); - - DnsNameResolverBuilder builder = new DnsNameResolverBuilder() + this.resolverGroup = new DnsAddressResolverGroup(new DnsNameResolverBuilder() .channelType(this.transportType.datagramChannelClass) .negativeTtl(15) - .ndots(1); - - this.resolverGroup = new DnsAddressResolverGroup(builder); + .ndots(1)); this.httpClient = asyncHttpClient(config() .setEventLoopGroup(this.workerGroup) .setUserAgent(server.getVersion().getName() + "/" + server.getVersion().getVersion()) @@ -74,7 +73,9 @@ public final class ConnectionManager { public FilterContext filter(FilterContext ctx) throws FilterException { return new FilterContextBuilder<>(ctx) .request(new RequestBuilder(ctx.getRequest()) - .setNameResolver(builder.eventLoop(workerGroup.next()).build()) + .setNameResolver( + new DnsAddressResolverGroupNameResolverAdapter(resolverGroup, workerGroup) + ) .build()) .build(); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/netty/DnsAddressResolverGroupNameResolverAdapter.java b/proxy/src/main/java/com/velocitypowered/proxy/network/netty/DnsAddressResolverGroupNameResolverAdapter.java new file mode 100644 index 000000000..9de466f84 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/netty/DnsAddressResolverGroupNameResolverAdapter.java @@ -0,0 +1,68 @@ +package com.velocitypowered.proxy.network.netty; + +import io.netty.channel.EventLoopGroup; +import io.netty.resolver.InetNameResolver; +import io.netty.resolver.dns.DnsAddressResolverGroup; +import io.netty.util.concurrent.EventExecutor; +import io.netty.util.concurrent.FutureListener; +import io.netty.util.concurrent.ImmediateEventExecutor; +import io.netty.util.concurrent.Promise; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; + +public class DnsAddressResolverGroupNameResolverAdapter extends InetNameResolver { + + private final DnsAddressResolverGroup resolverGroup; + private final EventLoopGroup group; + + public DnsAddressResolverGroupNameResolverAdapter( + DnsAddressResolverGroup resolverGroup, EventLoopGroup group) { + super(ImmediateEventExecutor.INSTANCE); + this.resolverGroup = resolverGroup; + this.group = group; + } + + @Override + protected void doResolve(String inetHost, Promise promise) throws Exception { + EventExecutor executor = this.findExecutor(); + resolverGroup.getResolver(executor).resolve(InetSocketAddress.createUnresolved(inetHost, 17)) + .addListener((FutureListener) future -> { + if (future.isSuccess()) { + promise.trySuccess(future.getNow().getAddress()); + } else { + promise.tryFailure(future.cause()); + } + }); + } + + @Override + protected void doResolveAll(String inetHost, Promise> promise) + throws Exception { + EventExecutor executor = this.findExecutor(); + resolverGroup.getResolver(executor).resolveAll(InetSocketAddress.createUnresolved(inetHost, 17)) + .addListener((FutureListener>) future -> { + if (future.isSuccess()) { + List addresses = new ArrayList<>(future.getNow().size()); + for (InetSocketAddress address : future.getNow()) { + addresses.add(address.getAddress()); + } + promise.trySuccess(addresses); + } else { + promise.tryFailure(future.cause()); + } + }); + } + + private EventExecutor findExecutor() { + for (EventExecutor executor : group) { + if (executor.inEventLoop()) { + return executor; + } + } + + // otherwise, pick one + return group.next(); + } +}