From b70cb014130ee35641e33f240bcc151343af06b9 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 16 Jan 2020 10:36:13 +1100 Subject: [PATCH] Add beta support for binding bungee to unix socket addresses --- api/pom.xml | 6 ++++ api/src/main/java/net/md_5/bungee/Util.java | 25 +++++++++++++--- .../java/net/md_5/bungee/api/ProxyServer.java | 13 +++++++++ .../md_5/bungee/api/config/ListenerInfo.java | 15 +++++++++- .../md_5/bungee/api/config/ServerInfo.java | 12 ++++++++ .../bungee/api/connection/Connection.java | 10 +++++++ .../bungee/api/ServerConnectRequestTest.java | 7 +++++ .../md_5/bungee/util/AddressParseTest.java | 26 +++++++++++++++-- .../main/java/net/md_5/bungee/BungeeCord.java | 21 ++++++++++---- .../net/md_5/bungee/BungeeServerInfo.java | 15 +++++++--- .../net/md_5/bungee/ConnectionThrottle.java | 18 ++++++++++-- .../net/md_5/bungee/ServerConnection.java | 7 +++++ .../java/net/md_5/bungee/ServerConnector.java | 3 +- .../java/net/md_5/bungee/UserConnection.java | 11 +++++-- .../net/md_5/bungee/command/CommandIP.java | 2 +- .../java/net/md_5/bungee/conf/YamlConfig.java | 6 ++-- .../bungee/connection/DownstreamBridge.java | 13 +++++++-- .../bungee/connection/InitialHandler.java | 13 +++++++-- .../java/net/md_5/bungee/http/HttpClient.java | 2 +- .../net/md_5/bungee/netty/ChannelWrapper.java | 6 ++-- .../net/md_5/bungee/netty/PipelineUtils.java | 29 +++++++++++++++---- .../java/net/md_5/bungee/ThrottleTest.java | 7 +++-- 22 files changed, 223 insertions(+), 44 deletions(-) diff --git a/api/pom.xml b/api/pom.xml index 30eef5dc..5d782001 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -43,5 +43,11 @@ ${project.version} compile + + io.netty + netty-transport-native-unix-common + ${netty.version} + compile + diff --git a/api/src/main/java/net/md_5/bungee/Util.java b/api/src/main/java/net/md_5/bungee/Util.java index 5e5b53a7..31101f6b 100644 --- a/api/src/main/java/net/md_5/bungee/Util.java +++ b/api/src/main/java/net/md_5/bungee/Util.java @@ -2,7 +2,9 @@ package net.md_5.bungee; import com.google.common.base.Joiner; import com.google.common.primitives.UnsignedLongs; +import io.netty.channel.unix.DomainSocketAddress; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.net.URI; import java.net.URISyntaxException; import java.util.UUID; @@ -21,15 +23,30 @@ public class Util * @param hostline in the format of 'host:port' * @return the constructed hostname + port. */ - public static InetSocketAddress getAddr(String hostline) + public static SocketAddress getAddr(String hostline) { - URI uri; + URI uri = null; try { - uri = new URI( "tcp://" + hostline ); + uri = new URI( hostline ); } catch ( URISyntaxException ex ) { - throw new IllegalArgumentException( "Bad hostline: " + hostline, ex ); + } + + if ( uri != null && "unix".equals( uri.getScheme() ) ) + { + return new DomainSocketAddress( uri.getPath() ); + } + + if ( uri == null || uri.getHost() == null ) + { + try + { + uri = new URI( "tcp://" + hostline ); + } catch ( URISyntaxException ex ) + { + throw new IllegalArgumentException( "Bad hostline: " + hostline, ex ); + } } if ( uri.getHost() == null ) diff --git a/api/src/main/java/net/md_5/bungee/api/ProxyServer.java b/api/src/main/java/net/md_5/bungee/api/ProxyServer.java index 490a0944..1f330bd2 100644 --- a/api/src/main/java/net/md_5/bungee/api/ProxyServer.java +++ b/api/src/main/java/net/md_5/bungee/api/ProxyServer.java @@ -3,6 +3,7 @@ package net.md_5.bungee.api; import com.google.common.base.Preconditions; import java.io.File; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.Collection; import java.util.Map; import java.util.UUID; @@ -206,6 +207,18 @@ public abstract class ProxyServer */ public abstract ServerInfo constructServerInfo(String name, InetSocketAddress address, String motd, boolean restricted); + /** + * Factory method to construct an implementation specific server info + * instance. + * + * @param name name of the server + * @param address connectable Minecraft address + port of the server + * @param motd the motd when used as a forced server + * @param restricted whether the server info restricted property will be set + * @return the constructed instance + */ + public abstract ServerInfo constructServerInfo(String name, SocketAddress address, String motd, boolean restricted); + /** * Returns the console overlord for this proxy. Being the console, this * command server cannot have permissions or groups, and will be able to diff --git a/api/src/main/java/net/md_5/bungee/api/config/ListenerInfo.java b/api/src/main/java/net/md_5/bungee/api/config/ListenerInfo.java index 42b84063..71abdc87 100644 --- a/api/src/main/java/net/md_5/bungee/api/config/ListenerInfo.java +++ b/api/src/main/java/net/md_5/bungee/api/config/ListenerInfo.java @@ -1,6 +1,7 @@ package net.md_5.bungee.api.config; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.List; import java.util.Map; import lombok.AllArgsConstructor; @@ -18,7 +19,7 @@ public class ListenerInfo /** * Host to bind to. */ - private final InetSocketAddress host; + private final SocketAddress socketAddress; /** * Displayed MOTD. */ @@ -102,4 +103,16 @@ public class ListenerInfo { return ( serverPriority.size() > 1 ) ? serverPriority.get( 1 ) : getDefaultServer(); } + + /** + * Gets the bind address as an InetSocketAddress if possible. + * + * @return bind host + * @deprecated BungeeCord can listen via Unix domain sockets + */ + @Deprecated + public InetSocketAddress getHost() + { + return (InetSocketAddress) socketAddress; + } } diff --git a/api/src/main/java/net/md_5/bungee/api/config/ServerInfo.java b/api/src/main/java/net/md_5/bungee/api/config/ServerInfo.java index 19773843..d90e30a2 100644 --- a/api/src/main/java/net/md_5/bungee/api/config/ServerInfo.java +++ b/api/src/main/java/net/md_5/bungee/api/config/ServerInfo.java @@ -1,6 +1,7 @@ package net.md_5.bungee.api.config; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.Collection; import net.md_5.bungee.api.Callback; import net.md_5.bungee.api.CommandSender; @@ -26,9 +27,20 @@ public interface ServerInfo * class. * * @return the IP and port pair for this server + * @deprecated BungeeCord can connect via Unix domain sockets */ + @Deprecated InetSocketAddress getAddress(); + /** + * Gets the connectable address this server. Implementations + * expect this to be used as the unique identifier per each instance of this + * class. + * + * @return the address for this server + */ + SocketAddress getSocketAddress(); + /** * Get the set of all players on this server. * diff --git a/api/src/main/java/net/md_5/bungee/api/connection/Connection.java b/api/src/main/java/net/md_5/bungee/api/connection/Connection.java index bfafaa86..f59b49c7 100644 --- a/api/src/main/java/net/md_5/bungee/api/connection/Connection.java +++ b/api/src/main/java/net/md_5/bungee/api/connection/Connection.java @@ -1,6 +1,7 @@ package net.md_5.bungee.api.connection; import java.net.InetSocketAddress; +import java.net.SocketAddress; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.protocol.DefinedPacket; @@ -16,9 +17,18 @@ public interface Connection * Gets the remote address of this connection. * * @return the remote address + * @deprecated BungeeCord can accept connections via Unix domain sockets */ + @Deprecated InetSocketAddress getAddress(); + /** + * Gets the remote address of this connection. + * + * @return the remote address + */ + SocketAddress getSocketAddress(); + /** * Disconnects this end of the connection for the specified reason. If this * is an {@link ProxiedPlayer} the respective server connection will be diff --git a/api/src/test/java/net/md_5/bungee/api/ServerConnectRequestTest.java b/api/src/test/java/net/md_5/bungee/api/ServerConnectRequestTest.java index 0d1f801a..3bae8064 100644 --- a/api/src/test/java/net/md_5/bungee/api/ServerConnectRequestTest.java +++ b/api/src/test/java/net/md_5/bungee/api/ServerConnectRequestTest.java @@ -1,6 +1,7 @@ package net.md_5.bungee.api; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.Collection; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; @@ -19,6 +20,12 @@ public class ServerConnectRequestTest return null; } + @Override + public SocketAddress getSocketAddress() + { + return null; + } + @Override public InetSocketAddress getAddress() { diff --git a/api/src/test/java/net/md_5/bungee/util/AddressParseTest.java b/api/src/test/java/net/md_5/bungee/util/AddressParseTest.java index 256c8d58..a0752255 100644 --- a/api/src/test/java/net/md_5/bungee/util/AddressParseTest.java +++ b/api/src/test/java/net/md_5/bungee/util/AddressParseTest.java @@ -1,6 +1,8 @@ package net.md_5.bungee.util; +import io.netty.channel.unix.DomainSocketAddress; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.Arrays; import java.util.Collection; import lombok.RequiredArgsConstructor; @@ -44,6 +46,9 @@ public class AddressParseTest }, { "[0:0:0:0:0:0:0:1]:1337", "0:0:0:0:0:0:0:1", 1337 + }, + { + "unix:///var/run/bungee.sock", "/var/run/bungee.sock", -1 } } ); } @@ -54,8 +59,23 @@ public class AddressParseTest @Test public void test() { - InetSocketAddress parsed = Util.getAddr( line ); - Assert.assertEquals( host, parsed.getHostString() ); - Assert.assertEquals( port, parsed.getPort() ); + SocketAddress parsed = Util.getAddr( line ); + + if ( parsed instanceof InetSocketAddress ) + { + InetSocketAddress tcp = (InetSocketAddress) parsed; + + Assert.assertEquals( host, tcp.getHostString() ); + Assert.assertEquals( port, tcp.getPort() ); + } else if ( parsed instanceof DomainSocketAddress ) + { + DomainSocketAddress unix = (DomainSocketAddress) parsed; + + Assert.assertEquals( host, unix.path() ); + Assert.assertEquals( -1, port ); + } else + { + throw new AssertionError( "Unknown socket " + parsed ); + } } } diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java index ad24d012..97568416 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -23,6 +23,7 @@ import java.io.FileReader; import java.io.IOException; import java.io.PrintStream; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; @@ -304,7 +305,7 @@ public class BungeeCord extends ProxyServer { if ( info.isProxyProtocol() ) { - getLogger().log( Level.WARNING, "Using PROXY protocol for listener {0}, please ensure this listener is adequately firewalled.", info.getHost() ); + getLogger().log( Level.WARNING, "Using PROXY protocol for listener {0}, please ensure this listener is adequately firewalled.", info.getSocketAddress() ); if ( connectionThrottle != null ) { @@ -321,24 +322,26 @@ public class BungeeCord extends ProxyServer if ( future.isSuccess() ) { listeners.add( future.channel() ); - getLogger().log( Level.INFO, "Listening on {0}", info.getHost() ); + getLogger().log( Level.INFO, "Listening on {0}", info.getSocketAddress() ); } else { - getLogger().log( Level.WARNING, "Could not bind to host " + info.getHost(), future.cause() ); + getLogger().log( Level.WARNING, "Could not bind to host " + info.getSocketAddress(), future.cause() ); } } }; new ServerBootstrap() - .channel( PipelineUtils.getServerChannel() ) + .channel( PipelineUtils.getServerChannel( info.getSocketAddress() ) ) .option( ChannelOption.SO_REUSEADDR, true ) // TODO: Move this elsewhere! .childAttr( PipelineUtils.LISTENER, info ) .childHandler( PipelineUtils.SERVER_CHILD ) .group( eventLoops ) - .localAddress( info.getHost() ) + .localAddress( info.getSocketAddress() ) .bind().addListener( listener ); if ( info.isQueryEnabled() ) { + Preconditions.checkArgument( info.getSocketAddress() instanceof InetSocketAddress, "Can only create query listener on UDP address" ); + ChannelFutureListener bindListener = new ChannelFutureListener() { @Override @@ -350,7 +353,7 @@ public class BungeeCord extends ProxyServer getLogger().log( Level.INFO, "Started query on {0}", future.channel().localAddress() ); } else { - getLogger().log( Level.WARNING, "Could not bind to host " + info.getHost(), future.cause() ); + getLogger().log( Level.WARNING, "Could not bind to host " + info.getSocketAddress(), future.cause() ); } } }; @@ -643,6 +646,12 @@ public class BungeeCord extends ProxyServer @Override public ServerInfo constructServerInfo(String name, InetSocketAddress address, String motd, boolean restricted) + { + return constructServerInfo( name, (SocketAddress) address, motd, restricted ); + } + + @Override + public ServerInfo constructServerInfo(String name, SocketAddress address, String motd, boolean restricted) { return new BungeeServerInfo( name, address, motd, restricted ); } diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java b/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java index 3ff3446b..cab2c21b 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java @@ -6,6 +6,7 @@ import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelOption; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -41,7 +42,7 @@ public class BungeeServerInfo implements ServerInfo @Getter private final String name; @Getter - private final InetSocketAddress address; + private final SocketAddress socketAddress; private final Collection players = new ArrayList<>(); @Getter private final String motd; @@ -91,7 +92,7 @@ public class BungeeServerInfo implements ServerInfo @Override public int hashCode() { - return address.hashCode(); + return socketAddress.hashCode(); } @Override @@ -122,6 +123,12 @@ public class BungeeServerInfo implements ServerInfo } } + @Override + public InetSocketAddress getAddress() + { + return (InetSocketAddress) socketAddress; + } + @Override public void ping(final Callback callback) { @@ -147,11 +154,11 @@ public class BungeeServerInfo implements ServerInfo } }; new Bootstrap() - .channel( PipelineUtils.getChannel() ) + .channel( PipelineUtils.getChannel( socketAddress ) ) .group( BungeeCord.getInstance().eventLoops ) .handler( PipelineUtils.BASE ) .option( ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000 ) // TODO: Configurable - .remoteAddress( getAddress() ) + .remoteAddress( socketAddress ) .connect() .addListener( listener ); } diff --git a/proxy/src/main/java/net/md_5/bungee/ConnectionThrottle.java b/proxy/src/main/java/net/md_5/bungee/ConnectionThrottle.java index b6c66dce..39724a85 100644 --- a/proxy/src/main/java/net/md_5/bungee/ConnectionThrottle.java +++ b/proxy/src/main/java/net/md_5/bungee/ConnectionThrottle.java @@ -6,6 +6,8 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.concurrent.TimeUnit; public class ConnectionThrottle @@ -38,14 +40,26 @@ public class ConnectionThrottle this.throttleLimit = throttleLimit; } - public void unthrottle(InetAddress address) + public void unthrottle(SocketAddress socketAddress) { + if ( !( socketAddress instanceof InetSocketAddress ) ) + { + return; + } + + InetAddress address = ( (InetSocketAddress) socketAddress ).getAddress(); int throttleCount = throttle.getUnchecked( address ) - 1; throttle.put( address, throttleCount ); } - public boolean throttle(InetAddress address) + public boolean throttle(SocketAddress socketAddress) { + if ( !( socketAddress instanceof InetSocketAddress ) ) + { + return false; + } + + InetAddress address = ( (InetSocketAddress) socketAddress ).getAddress(); int throttleCount = throttle.getUnchecked( address ) + 1; throttle.put( address, throttleCount ); diff --git a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java index d11d601e..06a0afd5 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java @@ -2,6 +2,7 @@ package net.md_5.bungee; import com.google.common.base.Preconditions; import java.net.InetSocketAddress; +import java.net.SocketAddress; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; @@ -65,6 +66,12 @@ public class ServerConnection implements Server @Override public InetSocketAddress getAddress() + { + return (InetSocketAddress) getSocketAddress(); + } + + @Override + public SocketAddress getSocketAddress() { return getInfo().getAddress(); } diff --git a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java index cc171600..2ebfef5e 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -3,6 +3,7 @@ package net.md_5.bungee; import com.google.common.base.Preconditions; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; +import java.net.InetSocketAddress; import java.util.Locale; import java.util.Queue; import java.util.Set; @@ -96,7 +97,7 @@ public class ServerConnector extends PacketHandler Handshake originalHandshake = user.getPendingConnection().getHandshake(); Handshake copiedHandshake = new Handshake( originalHandshake.getProtocolVersion(), originalHandshake.getHost(), originalHandshake.getPort(), 2 ); - if ( BungeeCord.getInstance().config.isIpForward() ) + if ( BungeeCord.getInstance().config.isIpForward() && user.getSocketAddress() instanceof InetSocketAddress ) { String newHost = copiedHandshake.getHost() + "\00" + user.getAddress().getHostString() + "\00" + user.getUUID(); diff --git a/proxy/src/main/java/net/md_5/bungee/UserConnection.java b/proxy/src/main/java/net/md_5/bungee/UserConnection.java index 5b72efea..3d7e9043 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -10,6 +10,7 @@ import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.util.internal.PlatformDependent; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -359,13 +360,13 @@ public final class UserConnection implements ProxiedPlayer } }; Bootstrap b = new Bootstrap() - .channel( PipelineUtils.getChannel() ) + .channel( PipelineUtils.getChannel( target.getAddress() ) ) .group( ch.getHandle().eventLoop() ) .handler( initializer ) .option( ChannelOption.CONNECT_TIMEOUT_MILLIS, request.getConnectTimeout() ) .remoteAddress( target.getAddress() ); // Windows is bugged, multi homed users will just have to live with random connecting IPs - if ( getPendingConnection().getListener().isSetLocalAddress() && !PlatformDependent.isWindows() ) + if ( getPendingConnection().getListener().isSetLocalAddress() && !PlatformDependent.isWindows() && getPendingConnection().getListener().getSocketAddress() instanceof InetSocketAddress ) { b.localAddress( getPendingConnection().getListener().getHost().getHostString(), 0 ); } @@ -497,6 +498,12 @@ public final class UserConnection implements ProxiedPlayer @Override public InetSocketAddress getAddress() + { + return (InetSocketAddress) getSocketAddress(); + } + + @Override + public SocketAddress getSocketAddress() { return ch.getRemoteAddress(); } diff --git a/proxy/src/main/java/net/md_5/bungee/command/CommandIP.java b/proxy/src/main/java/net/md_5/bungee/command/CommandIP.java index 8fd4975b..1fd5a546 100644 --- a/proxy/src/main/java/net/md_5/bungee/command/CommandIP.java +++ b/proxy/src/main/java/net/md_5/bungee/command/CommandIP.java @@ -26,7 +26,7 @@ public class CommandIP extends PlayerCommand sender.sendMessage( ProxyServer.getInstance().getTranslation( "user_not_online" ) ); } else { - sender.sendMessage( ProxyServer.getInstance().getTranslation( "command_ip", args[0], user.getAddress() ) ); + sender.sendMessage( ProxyServer.getInstance().getTranslation( "command_ip", args[0], user.getSocketAddress() ) ); } } } diff --git a/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java b/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java index 4cfb13c0..bc7e3a0d 100644 --- a/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java +++ b/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java @@ -6,7 +6,7 @@ import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; -import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -215,7 +215,7 @@ public class YamlConfig implements ConfigurationAdapter String addr = get( "address", "localhost:25565", val ); String motd = ChatColor.translateAlternateColorCodes( '&', get( "motd", "&1Just another BungeeCord - Forced Host", val ) ); boolean restricted = get( "restricted", false, val ); - InetSocketAddress address = Util.getAddr( addr ); + SocketAddress address = Util.getAddr( addr ); ServerInfo info = ProxyServer.getInstance().constructServerInfo( name, address, motd, restricted ); ret.put( name, info ); } @@ -246,7 +246,7 @@ public class YamlConfig implements ConfigurationAdapter boolean forceDefault = get( "force_default_server", false, val ); String host = get( "host", "0.0.0.0:25577", val ); int tabListSize = get( "tab_size", 60, val ); - InetSocketAddress address = Util.getAddr( host ); + SocketAddress address = Util.getAddr( host ); Map forced = new CaseInsensitiveMap<>( get( "forced_hosts", forcedDef, val ) ); String tabListName = get( "tab_list", "GLOBAL_PING", val ); DefaultTabList value = DefaultTabList.valueOf( tabListName.toUpperCase( Locale.ROOT ) ); diff --git a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java index 63162de0..b66712d2 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java @@ -15,7 +15,9 @@ import com.mojang.brigadier.tree.LiteralCommandNode; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.Unpooled; +import io.netty.channel.unix.DomainSocketAddress; import java.io.DataInput; +import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -359,8 +361,15 @@ public class DownstreamBridge extends PacketHandler if ( subChannel.equals( "IP" ) ) { out.writeUTF( "IP" ); - out.writeUTF( con.getAddress().getHostString() ); - out.writeInt( con.getAddress().getPort() ); + if ( con.getSocketAddress() instanceof InetSocketAddress ) + { + out.writeUTF( con.getAddress().getHostString() ); + out.writeInt( con.getAddress().getPort() ); + } else + { + out.writeUTF( "unix://" + ( (DomainSocketAddress) con.getSocketAddress() ).path() ); + out.writeInt( 0 ); + } } if ( subChannel.equals( "PlayerCount" ) ) { diff --git a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java index 18c9fa6f..a53b113c 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java @@ -5,6 +5,7 @@ import com.google.common.base.Preconditions; import com.google.gson.Gson; import java.math.BigInteger; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.net.URLEncoder; import java.security.MessageDigest; import java.util.List; @@ -236,7 +237,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection unsafe.sendPacket( new StatusResponse( gson.toJson( pingResult.getResponse() ) ) ); if ( bungee.getConnectionThrottle() != null ) { - bungee.getConnectionThrottle().unthrottle( getAddress().getAddress() ); + bungee.getConnectionThrottle().unthrottle( getSocketAddress() ); } } }; @@ -418,7 +419,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection } String encodedHash = URLEncoder.encode( new BigInteger( sha.digest() ).toString( 16 ), "UTF-8" ); - String preventProxy = ( ( BungeeCord.getInstance().config.isPreventProxyConnections() ) ? "&ip=" + URLEncoder.encode( getAddress().getAddress().getHostAddress(), "UTF-8" ) : "" ); + String preventProxy = ( BungeeCord.getInstance().config.isPreventProxyConnections() && getSocketAddress() instanceof InetSocketAddress ) ? "&ip=" + URLEncoder.encode( getAddress().getAddress().getHostAddress(), "UTF-8" ) : ""; String authURL = "https://sessionserver.mojang.com/session/minecraft/hasJoined?username=" + encName + "&serverId=" + encodedHash + preventProxy; Callback handler = new Callback() @@ -591,6 +592,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection @Override public InetSocketAddress getAddress() + { + return (InetSocketAddress) getSocketAddress(); + } + + @Override + public SocketAddress getSocketAddress() { return ch.getRemoteAddress(); } @@ -625,7 +632,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection @Override public String toString() { - return "[" + ( ( getName() != null ) ? getName() : getAddress() ) + "] <-> InitialHandler"; + return "[" + ( ( getName() != null ) ? getName() : getSocketAddress() ) + "] <-> InitialHandler"; } @Override 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 f95d5b6f..e0c52f21 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 @@ -92,7 +92,7 @@ public class HttpClient } }; - new Bootstrap().channel( PipelineUtils.getChannel() ).group( eventLoop ).handler( new HttpInitializer( callback, ssl, 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 ).remoteAddress( inetHost, port ).connect().addListener( future ); } } diff --git a/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java b/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java index 0ef21887..6be2d942 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java @@ -5,7 +5,7 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; -import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.concurrent.TimeUnit; import lombok.Getter; import lombok.Setter; @@ -23,7 +23,7 @@ public class ChannelWrapper private final Channel ch; @Getter @Setter - private InetSocketAddress remoteAddress; + private SocketAddress remoteAddress; @Getter private volatile boolean closed; @Getter @@ -32,7 +32,7 @@ public class ChannelWrapper public ChannelWrapper(ChannelHandlerContext ctx) { this.ch = ctx.channel(); - this.remoteAddress = (InetSocketAddress) this.ch.remoteAddress(); + this.remoteAddress = ( this.ch.remoteAddress() == null ) ? this.ch.parent().localAddress() : this.ch.remoteAddress(); } public void setProtocol(Protocol protocol) diff --git a/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java b/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java index f75ec97d..44e28846 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java @@ -1,5 +1,6 @@ package net.md_5.bungee.netty; +import com.google.common.base.Preconditions; import io.netty.buffer.PooledByteBufAllocator; import io.netty.channel.Channel; import io.netty.channel.ChannelException; @@ -10,18 +11,22 @@ import io.netty.channel.ServerChannel; import io.netty.channel.WriteBufferWaterMark; import io.netty.channel.epoll.Epoll; import io.netty.channel.epoll.EpollDatagramChannel; +import io.netty.channel.epoll.EpollDomainSocketChannel; import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.epoll.EpollServerDomainSocketChannel; import io.netty.channel.epoll.EpollServerSocketChannel; import io.netty.channel.epoll.EpollSocketChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.channel.unix.DomainSocketAddress; import io.netty.handler.codec.haproxy.HAProxyMessageDecoder; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.util.AttributeKey; import io.netty.util.internal.PlatformDependent; -import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -51,7 +56,7 @@ public class PipelineUtils @Override protected void initChannel(Channel ch) throws Exception { - if ( BungeeCord.getInstance().getConnectionThrottle() != null && BungeeCord.getInstance().getConnectionThrottle().throttle( ( (InetSocketAddress) ch.remoteAddress() ).getAddress() ) ) + if ( BungeeCord.getInstance().getConnectionThrottle() != null && BungeeCord.getInstance().getConnectionThrottle().throttle( ch.remoteAddress() ) ) { ch.close(); return; @@ -109,17 +114,31 @@ public class PipelineUtils return epoll ? new EpollEventLoopGroup( threads, factory ) : new NioEventLoopGroup( threads, factory ); } - public static Class getServerChannel() + public static Class getServerChannel(SocketAddress address) { + if ( address instanceof DomainSocketAddress ) + { + Preconditions.checkState( epoll, "Epoll required to have UNIX sockets" ); + + return EpollServerDomainSocketChannel.class; + } + return epoll ? EpollServerSocketChannel.class : NioServerSocketChannel.class; } - public static Class getChannel() + public static Class getChannel(SocketAddress address) { + if ( address instanceof DomainSocketAddress ) + { + Preconditions.checkState( epoll, "Epoll required to have UNIX sockets" ); + + return EpollDomainSocketChannel.class; + } + return epoll ? EpollSocketChannel.class : NioSocketChannel.class; } - public static Class getDatagramChannel() + public static Class getDatagramChannel() { return epoll ? EpollDatagramChannel.class : NioDatagramChannel.class; } diff --git a/proxy/src/test/java/net/md_5/bungee/ThrottleTest.java b/proxy/src/test/java/net/md_5/bungee/ThrottleTest.java index f4c11675..84510827 100644 --- a/proxy/src/test/java/net/md_5/bungee/ThrottleTest.java +++ b/proxy/src/test/java/net/md_5/bungee/ThrottleTest.java @@ -2,6 +2,7 @@ package net.md_5.bungee; import com.google.common.base.Ticker; import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.concurrent.TimeUnit; import org.junit.Assert; @@ -27,14 +28,14 @@ public class ThrottleTest { FixedTicker ticker = new FixedTicker(); ConnectionThrottle throttle = new ConnectionThrottle( ticker, 10, 3 ); - InetAddress address; + InetSocketAddress address; try { - address = InetAddress.getLocalHost(); + address = new InetSocketAddress( InetAddress.getLocalHost(), 0 ); } catch ( UnknownHostException ex ) { - address = InetAddress.getByName( null ); + address = new InetSocketAddress( InetAddress.getByName( null ), 0 ); } Assert.assertFalse( "Address should not be throttled", throttle.throttle( address ) ); // 1