diff --git a/protocol/pom.xml b/protocol/pom.xml index a347f5cc..6b972fe5 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -23,6 +23,7 @@ io.netty netty-buffer 4.0.0.Beta2 + provided 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 52127e97..880e24e2 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -6,6 +6,7 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelException; import io.netty.channel.MultithreadEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; import net.md_5.bungee.config.Configuration; import java.io.BufferedReader; import java.io.File; @@ -38,7 +39,7 @@ import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.PluginManager; import net.md_5.bungee.command.*; import net.md_5.bungee.config.YamlConfig; -import net.md_5.bungee.netty.ChannelBootstrapper; +import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.PacketFAPluginMessage; @@ -186,9 +187,11 @@ public class BungeeCord extends ProxyServer for ( ListenerInfo info : config.getListeners() ) { Channel server = new ServerBootstrap() - .childHandler( ChannelBootstrapper.SERVER ) - .localAddress( info.getHost() ) + .channel( NioServerSocketChannel.class) + .childHandler( PipelineUtils.SERVER_CHILD ) .group( eventLoops ) + .localAddress( info.getHost() ) + .attr( PipelineUtils.LISTENER, info) .bind().channel(); listeners.add( server ); 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 3bd3d24a..cd691b7c 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java @@ -9,6 +9,9 @@ import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ServerPing; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.Server; +import net.md_5.bungee.connection.PingHandler; +import net.md_5.bungee.netty.HandlerBoss; +import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.PacketFAPluginMessage; @@ -39,5 +42,6 @@ public class BungeeServerInfo extends ServerInfo @Override public void ping(final Callback callback) { + PipelineUtils.connectClient( getAddress() ).channel().pipeline().get( HandlerBoss.class ).setHandler( new PingHandler( callback ) ); } } 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 a1a4a83a..19d78af4 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -11,7 +11,8 @@ import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.event.ServerConnectEvent; import net.md_5.bungee.api.event.ServerConnectedEvent; -import net.md_5.bungee.netty.ChannelBootstrapper; +import net.md_5.bungee.netty.HandlerBoss; +import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.Packet1Login; import net.md_5.bungee.packet.Packet9Respawn; @@ -25,7 +26,7 @@ public class ServerConnector extends PacketHandler { private final ProxyServer bungee; - private final Channel ch; + private Channel ch; private final UserConnection user; private final ServerInfo target; private State thisState = State.ENCRYPT_REQUEST; @@ -36,6 +37,14 @@ public class ServerConnector extends PacketHandler ENCRYPT_REQUEST, LOGIN, FINISHED; } + @Override + public void connected(Channel channel) throws Exception + { + this.ch = channel; + channel.write( user.handshake ); + channel.write( PacketCDClientStatus.CLIENT_LOGIN ); + } + @Override public void handle(Packet1Login login) throws Exception { @@ -112,16 +121,12 @@ public class ServerConnector extends PacketHandler ProxyServer.getInstance().getPluginManager().callEvent( event ); final ServerInfo target = event.getTarget(); // Update in case the event changed target - ChannelBootstrapper.CLIENT.connectClient( info.getAddress() ).addListener( new ChannelFutureListener() + PipelineUtils.connectClient( info.getAddress() ).addListener( new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { - if ( future.isSuccess() ) - { - future.channel().write( user.handshake ); - future.channel().write( PacketCDClientStatus.CLIENT_LOGIN ); - } else + if ( !future.isSuccess() ) { future.channel().close(); ServerInfo def = ProxyServer.getInstance().getServers().get( user.getPendingConnection().getListener().getDefaultServer() ); @@ -132,6 +137,6 @@ public class ServerConnector extends PacketHandler } } } - } ).channel(); + } ).channel().pipeline().get( HandlerBoss.class).setHandler( new ServerConnector( ProxyServer.getInstance(), user, target)); } } 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 76921b60..a8ee0278 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 @@ -47,7 +47,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection { private final ProxyServer bungee; - private final Channel ch; + private Channel ch; @Getter private final ListenerInfo listener; private Packet1Login forgeLogin; @@ -66,6 +66,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection HANDSHAKE, ENCRYPT, LOGIN, FINISHED; } + @Override + public void connected(Channel channel) throws Exception + { + this.ch = channel; + } + @Override public void handle(Packet1Login login) throws Exception { diff --git a/proxy/src/main/java/net/md_5/bungee/netty/ChannelBootstrapper.java b/proxy/src/main/java/net/md_5/bungee/netty/ChannelBootstrapper.java deleted file mode 100644 index e4c81e7d..00000000 --- a/proxy/src/main/java/net/md_5/bungee/netty/ChannelBootstrapper.java +++ /dev/null @@ -1,63 +0,0 @@ -package net.md_5.bungee.netty; - -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelException; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.timeout.ReadTimeoutHandler; -import java.lang.reflect.Constructor; -import java.net.SocketAddress; -import java.util.concurrent.TimeUnit; -import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.connection.InitialHandler; -import net.md_5.bungee.ServerConnector; -import net.md_5.bungee.packet.PacketHandler; -import net.md_5.bungee.protocol.PacketDefinitions; - -public class ChannelBootstrapper extends ChannelInitializer -{ - - public static ChannelBootstrapper CLIENT = new ChannelBootstrapper( InitialHandler.class ); - public static ChannelBootstrapper SERVER = new ChannelBootstrapper( ServerConnector.class ); - private final Constructor initial; - - public ChannelFuture connectClient(SocketAddress remoteAddress) - { - return new Bootstrap() - .channel( NioSocketChannel.class ) - .group( BungeeCord.getInstance().eventLoops ) - .handler( this ) - .remoteAddress( remoteAddress ) - .connect(); - } - - private ChannelBootstrapper(Class initialHandler) - { - try - { - this.initial = initialHandler.getDeclaredConstructor(); - } catch ( NoSuchMethodException ex ) - { - throw new ExceptionInInitializerError( ex ); - } - } - - @Override - protected void initChannel(Channel ch) throws Exception - { - try - { - ch.config().setOption( ChannelOption.IP_TOS, 0x18 ); - } catch ( ChannelException ex ) - { - // IP_TOS is not supported (Windows XP / Windows Server 2003) - } - ch.pipeline().addLast( "timer", new ReadTimeoutHandler( BungeeCord.getInstance().config.getTimeout(), TimeUnit.MILLISECONDS ) ); - ch.pipeline().addLast( "decoder", new PacketDecoder( PacketDefinitions.VANILLA_PROTOCOL ) ); - - ch.pipeline().addLast( "handler", new HandlerBoss( initial.newInstance() ) ); - } -} diff --git a/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java b/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java index f57b53cb..8dcbddef 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java @@ -12,12 +12,12 @@ import net.md_5.bungee.packet.PacketHandler; * channels to maintain simple states, and only call the required, adapted * methods when the channel is connected. */ -class HandlerBoss extends ChannelInboundMessageHandlerAdapter +public class HandlerBoss extends ChannelInboundMessageHandlerAdapter { private PacketHandler handler; - HandlerBoss(PacketHandler handler) + public void setHandler(PacketHandler handler) { Preconditions.checkArgument( handler != null, "handler" ); this.handler = handler; @@ -26,19 +26,25 @@ class HandlerBoss extends ChannelInboundMessageHandlerAdapter @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { - handler.connected( ctx.channel() ); + if ( handler != null ) + { + handler.connected( ctx.channel() ); + } } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { - handler.disconnected( ctx.channel() ); + if ( handler != null ) + { + handler.disconnected( ctx.channel() ); + } } @Override protected void messageReceived(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { - if ( ctx.channel().isActive() ) + if ( handler != null && ctx.channel().isActive() ) { DefinedPacket packet = DefinedPacket.packet( msg ); if ( packet != null ) 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 new file mode 100644 index 00000000..56e69bac --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java @@ -0,0 +1,63 @@ +package net.md_5.bungee.netty; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelException; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.util.AttributeKey; +import java.net.SocketAddress; +import java.util.concurrent.TimeUnit; +import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.connection.InitialHandler; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.config.ListenerInfo; +import net.md_5.bungee.protocol.PacketDefinitions; + +public class PipelineUtils +{ + + public static final AttributeKey LISTENER = new AttributeKey<>( "ListerInfo" ); + public static final ChannelInitializer SERVER_CHILD = new ChannelInitializer() + { + @Override + protected void initChannel(Channel ch) throws Exception + { + BASE.initChannel( ch ); + ch.pipeline().get( HandlerBoss.class ).setHandler( new InitialHandler( ProxyServer.getInstance(), ch.attr( LISTENER ).get() ) ); + } + }; + private static final Base BASE = new Base(); + + private final static class Base extends ChannelInitializer + { + + @Override + public void initChannel(Channel ch) throws Exception + { + try + { + ch.config().setOption( ChannelOption.IP_TOS, 0x18 ); + } catch ( ChannelException ex ) + { + // IP_TOS is not supported (Windows XP / Windows Server 2003) + } + ch.pipeline().addLast( "timer", new ReadTimeoutHandler( BungeeCord.getInstance().config.getTimeout(), TimeUnit.MILLISECONDS ) ); + ch.pipeline().addLast( "decoder", new PacketDecoder( PacketDefinitions.VANILLA_PROTOCOL ) ); + ch.pipeline().addLast( "handler", new HandlerBoss() ); + } + }; + + public static ChannelFuture connectClient(SocketAddress remoteAddress) + { + return new Bootstrap() + .channel( NioSocketChannel.class ) + .group( BungeeCord.getInstance().eventLoops ) + .handler( BASE ) + .remoteAddress( remoteAddress ) + .connect(); + } +}