Cleanup channel initialization - now its time to get this show working.

This commit is contained in:
md_5 2013-03-09 09:44:28 +11:00
parent 9e0ae0a70d
commit 45c848a4fd
8 changed files with 106 additions and 81 deletions

View File

@ -23,6 +23,7 @@
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-buffer</artifactId> <artifactId>netty-buffer</artifactId>
<version>4.0.0.Beta2</version> <version>4.0.0.Beta2</version>
<scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -6,6 +6,7 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelException; import io.netty.channel.ChannelException;
import io.netty.channel.MultithreadEventLoopGroup; import io.netty.channel.MultithreadEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import net.md_5.bungee.config.Configuration; import net.md_5.bungee.config.Configuration;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; 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.api.plugin.PluginManager;
import net.md_5.bungee.command.*; import net.md_5.bungee.command.*;
import net.md_5.bungee.config.YamlConfig; 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.DefinedPacket;
import net.md_5.bungee.packet.PacketFAPluginMessage; import net.md_5.bungee.packet.PacketFAPluginMessage;
@ -186,9 +187,11 @@ public class BungeeCord extends ProxyServer
for ( ListenerInfo info : config.getListeners() ) for ( ListenerInfo info : config.getListeners() )
{ {
Channel server = new ServerBootstrap() Channel server = new ServerBootstrap()
.childHandler( ChannelBootstrapper.SERVER ) .channel( NioServerSocketChannel.class)
.localAddress( info.getHost() ) .childHandler( PipelineUtils.SERVER_CHILD )
.group( eventLoops ) .group( eventLoops )
.localAddress( info.getHost() )
.attr( PipelineUtils.LISTENER, info)
.bind().channel(); .bind().channel();
listeners.add( server ); listeners.add( server );

View File

@ -9,6 +9,9 @@ import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.ServerPing; import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.Server; 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.DefinedPacket;
import net.md_5.bungee.packet.PacketFAPluginMessage; import net.md_5.bungee.packet.PacketFAPluginMessage;
@ -39,5 +42,6 @@ public class BungeeServerInfo extends ServerInfo
@Override @Override
public void ping(final Callback<ServerPing> callback) public void ping(final Callback<ServerPing> callback)
{ {
PipelineUtils.connectClient( getAddress() ).channel().pipeline().get( HandlerBoss.class ).setHandler( new PingHandler( callback ) );
} }
} }

View File

@ -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.config.ServerInfo;
import net.md_5.bungee.api.event.ServerConnectEvent; import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.event.ServerConnectedEvent; 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.DefinedPacket;
import net.md_5.bungee.packet.Packet1Login; import net.md_5.bungee.packet.Packet1Login;
import net.md_5.bungee.packet.Packet9Respawn; import net.md_5.bungee.packet.Packet9Respawn;
@ -25,7 +26,7 @@ public class ServerConnector extends PacketHandler
{ {
private final ProxyServer bungee; private final ProxyServer bungee;
private final Channel ch; private Channel ch;
private final UserConnection user; private final UserConnection user;
private final ServerInfo target; private final ServerInfo target;
private State thisState = State.ENCRYPT_REQUEST; private State thisState = State.ENCRYPT_REQUEST;
@ -36,6 +37,14 @@ public class ServerConnector extends PacketHandler
ENCRYPT_REQUEST, LOGIN, FINISHED; 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 @Override
public void handle(Packet1Login login) throws Exception public void handle(Packet1Login login) throws Exception
{ {
@ -112,16 +121,12 @@ public class ServerConnector extends PacketHandler
ProxyServer.getInstance().getPluginManager().callEvent( event ); ProxyServer.getInstance().getPluginManager().callEvent( event );
final ServerInfo target = event.getTarget(); // Update in case the event changed target 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 @Override
public void operationComplete(ChannelFuture future) throws Exception public void operationComplete(ChannelFuture future) throws Exception
{ {
if ( future.isSuccess() ) if ( !future.isSuccess() )
{
future.channel().write( user.handshake );
future.channel().write( PacketCDClientStatus.CLIENT_LOGIN );
} else
{ {
future.channel().close(); future.channel().close();
ServerInfo def = ProxyServer.getInstance().getServers().get( user.getPendingConnection().getListener().getDefaultServer() ); 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));
} }
} }

View File

@ -47,7 +47,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
{ {
private final ProxyServer bungee; private final ProxyServer bungee;
private final Channel ch; private Channel ch;
@Getter @Getter
private final ListenerInfo listener; private final ListenerInfo listener;
private Packet1Login forgeLogin; private Packet1Login forgeLogin;
@ -66,6 +66,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
HANDSHAKE, ENCRYPT, LOGIN, FINISHED; HANDSHAKE, ENCRYPT, LOGIN, FINISHED;
} }
@Override
public void connected(Channel channel) throws Exception
{
this.ch = channel;
}
@Override @Override
public void handle(Packet1Login login) throws Exception public void handle(Packet1Login login) throws Exception
{ {

View File

@ -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<Channel>
{
public static ChannelBootstrapper CLIENT = new ChannelBootstrapper( InitialHandler.class );
public static ChannelBootstrapper SERVER = new ChannelBootstrapper( ServerConnector.class );
private final Constructor<? extends PacketHandler> initial;
public ChannelFuture connectClient(SocketAddress remoteAddress)
{
return new Bootstrap()
.channel( NioSocketChannel.class )
.group( BungeeCord.getInstance().eventLoops )
.handler( this )
.remoteAddress( remoteAddress )
.connect();
}
private ChannelBootstrapper(Class<? extends PacketHandler> 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() ) );
}
}

View File

@ -12,12 +12,12 @@ import net.md_5.bungee.packet.PacketHandler;
* channels to maintain simple states, and only call the required, adapted * channels to maintain simple states, and only call the required, adapted
* methods when the channel is connected. * methods when the channel is connected.
*/ */
class HandlerBoss extends ChannelInboundMessageHandlerAdapter<ByteBuf> public class HandlerBoss extends ChannelInboundMessageHandlerAdapter<ByteBuf>
{ {
private PacketHandler handler; private PacketHandler handler;
HandlerBoss(PacketHandler handler) public void setHandler(PacketHandler handler)
{ {
Preconditions.checkArgument( handler != null, "handler" ); Preconditions.checkArgument( handler != null, "handler" );
this.handler = handler; this.handler = handler;
@ -25,20 +25,26 @@ class HandlerBoss extends ChannelInboundMessageHandlerAdapter<ByteBuf>
@Override @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception public void channelActive(ChannelHandlerContext ctx) throws Exception
{
if ( handler != null )
{ {
handler.connected( ctx.channel() ); handler.connected( ctx.channel() );
} }
}
@Override @Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception public void channelInactive(ChannelHandlerContext ctx) throws Exception
{
if ( handler != null )
{ {
handler.disconnected( ctx.channel() ); handler.disconnected( ctx.channel() );
} }
}
@Override @Override
protected void messageReceived(ChannelHandlerContext ctx, ByteBuf msg) throws Exception protected void messageReceived(ChannelHandlerContext ctx, ByteBuf msg) throws Exception
{ {
if ( ctx.channel().isActive() ) if ( handler != null && ctx.channel().isActive() )
{ {
DefinedPacket packet = DefinedPacket.packet( msg ); DefinedPacket packet = DefinedPacket.packet( msg );
if ( packet != null ) if ( packet != null )

View File

@ -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<ListenerInfo> LISTENER = new AttributeKey<>( "ListerInfo" );
public static final ChannelInitializer<Channel> SERVER_CHILD = new ChannelInitializer<Channel>()
{
@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<Channel>
{
@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();
}
}