Checkpoint

This commit is contained in:
md_5 2013-10-12 11:36:53 +11:00
parent b358fd25f5
commit 1b41682e37
10 changed files with 66 additions and 96 deletions

View File

@ -1,5 +1,6 @@
package net.md_5.bungee.protocol; package net.md_5.bungee.protocol;
import com.google.common.base.Charsets;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec; import io.netty.handler.codec.MessageToMessageCodec;
@ -31,15 +32,20 @@ public class MinecraftCodec extends MessageToMessageCodec<ByteBuf, DefinedPacket
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception
{ {
Protocol.ProtocolDirection prot = ( server ) ? protocol.TO_SERVER : protocol.TO_CLIENT; Protocol.ProtocolDirection prot = ( server ) ? protocol.TO_SERVER : protocol.TO_CLIENT;
ByteBuf copy = msg.copy();
int packetId = DefinedPacket.readVarInt( msg ); int packetId = DefinedPacket.readVarInt( msg );
ByteBuf copy = msg.copy();
DefinedPacket packet = null; DefinedPacket packet = null;
if ( prot.hasPacket( packetId ) ) if ( prot.hasPacket( packetId ) )
{ {
packet = prot.createPacket( packetId ); packet = prot.createPacket( packetId );
packet.read( msg ); packet.read( msg );
if ( msg.readableBytes() != 0 )
{
System.out.println( msg.toString( Charsets.UTF_8 ) );
throw new BadPacketException( "Did not read all bytes from packet " + packetId + " Protocol " + protocol + " Direction " + prot );
}
} }
out.add( new PacketWrapper( packet, copy ) ); out.add( new PacketWrapper( packet, copy ) );

View File

@ -3,7 +3,6 @@ package net.md_5.bungee.protocol;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.Setter; import lombok.Setter;
import net.md_5.bungee.protocol.DefinedPacket;
@RequiredArgsConstructor @RequiredArgsConstructor
public class PacketWrapper public class PacketWrapper

View File

@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
import gnu.trove.map.TObjectIntMap; import gnu.trove.map.TObjectIntMap;
import gnu.trove.map.hash.TObjectIntHashMap; import gnu.trove.map.hash.TObjectIntHashMap;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.protocol.packet.Chat; import net.md_5.bungee.protocol.packet.Chat;
import net.md_5.bungee.protocol.packet.ClientSettings; import net.md_5.bungee.protocol.packet.ClientSettings;
import net.md_5.bungee.protocol.packet.EncryptionRequest; import net.md_5.bungee.protocol.packet.EncryptionRequest;
@ -92,12 +93,14 @@ public enum Protocol
public static final int PROTOCOL_VERSION = 0x00; public static final int PROTOCOL_VERSION = 0x00;
public static final String MINECRAFT_VERSION = "13w41a"; public static final String MINECRAFT_VERSION = "13w41a";
/*========================================================================*/ /*========================================================================*/
public final ProtocolDirection TO_SERVER = new ProtocolDirection(); public final ProtocolDirection TO_SERVER = new ProtocolDirection( "TO_SERVER" );
public final ProtocolDirection TO_CLIENT = new ProtocolDirection(); public final ProtocolDirection TO_CLIENT = new ProtocolDirection( "TO_CLIENT" );
@RequiredArgsConstructor
public class ProtocolDirection public class ProtocolDirection
{ {
private final String name;
private final TObjectIntMap<Class<? extends DefinedPacket>> packetMap = new TObjectIntHashMap<>( MAX_PACKET_ID ); private final TObjectIntMap<Class<? extends DefinedPacket>> packetMap = new TObjectIntHashMap<>( MAX_PACKET_ID );
private final Class<? extends DefinedPacket>[] packetClasses = new Class[ MAX_PACKET_ID ]; private final Class<? extends DefinedPacket>[] packetClasses = new Class[ MAX_PACKET_ID ];
private final Constructor<? extends DefinedPacket>[] packetConstructors = new Constructor[ MAX_PACKET_ID ]; private final Constructor<? extends DefinedPacket>[] packetConstructors = new Constructor[ MAX_PACKET_ID ];
@ -107,6 +110,12 @@ public enum Protocol
return id < MAX_PACKET_ID && packetConstructors[id] != null; return id < MAX_PACKET_ID && packetConstructors[id] != null;
} }
@Override
public String toString()
{
return name;
}
public final DefinedPacket createPacket(int id) public final DefinedPacket createPacket(int id)
{ {
if ( id > MAX_PACKET_ID ) if ( id > MAX_PACKET_ID )

View File

@ -15,18 +15,21 @@ import net.md_5.bungee.protocol.AbstractPacketHandler;
public class LoginSuccess extends DefinedPacket public class LoginSuccess extends DefinedPacket
{ {
private String data; private String uuid;
private String username;
@Override @Override
public void read(ByteBuf buf) public void read(ByteBuf buf)
{ {
data = readString( buf ); uuid = readString( buf );
username = readString( buf );
} }
@Override @Override
public void write(ByteBuf buf) public void write(ByteBuf buf)
{ {
writeString( data, buf ); writeString( uuid, buf );
writeString( username, buf );
} }
@Override @Override

View File

@ -3,11 +3,8 @@ package net.md_5.bungee;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import java.io.DataInput;
import java.util.Objects; import java.util.Objects;
import java.util.Queue; import java.util.Queue;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
@ -22,17 +19,17 @@ import net.md_5.bungee.connection.CancelSendSignal;
import net.md_5.bungee.connection.DownstreamBridge; import net.md_5.bungee.connection.DownstreamBridge;
import net.md_5.bungee.netty.HandlerBoss; import net.md_5.bungee.netty.HandlerBoss;
import net.md_5.bungee.netty.ChannelWrapper; import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.netty.CipherDecoder;
import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.netty.PacketHandler;
import net.md_5.bungee.netty.PipelineUtils;
import net.md_5.bungee.protocol.MinecraftOutput; import net.md_5.bungee.protocol.MinecraftOutput;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.PacketWrapper;
import net.md_5.bungee.protocol.Protocol;
import net.md_5.bungee.protocol.packet.Login; import net.md_5.bungee.protocol.packet.Login;
import net.md_5.bungee.protocol.packet.Respawn; import net.md_5.bungee.protocol.packet.Respawn;
import net.md_5.bungee.protocol.packet.ScoreboardObjective; import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.PluginMessage; import net.md_5.bungee.protocol.packet.PluginMessage;
import net.md_5.bungee.protocol.packet.EncryptionResponse;
import net.md_5.bungee.protocol.packet.Kick; import net.md_5.bungee.protocol.packet.Kick;
import net.md_5.bungee.protocol.packet.LoginSuccess;
@RequiredArgsConstructor @RequiredArgsConstructor
public class ServerConnector extends PacketHandler public class ServerConnector extends PacketHandler
@ -42,14 +39,12 @@ public class ServerConnector extends PacketHandler
private ChannelWrapper ch; private ChannelWrapper ch;
private final UserConnection user; private final UserConnection user;
private final BungeeServerInfo target; private final BungeeServerInfo target;
private State thisState = State.ENCRYPT_REQUEST; private State thisState = State.LOGIN_SUCCESS;
private SecretKey secretkey;
private boolean sentMessages;
private enum State private enum State
{ {
ENCRYPT_REQUEST, ENCRYPT_RESPONSE, LOGIN, FINISHED; LOGIN_SUCCESS, ENCRYPT_RESPONSE, LOGIN, FINISHED;
} }
@Override @Override
@ -74,15 +69,12 @@ public class ServerConnector extends PacketHandler
out.writeUTF( "Login" ); out.writeUTF( "Login" );
out.writeUTF( user.getAddress().getHostString() ); out.writeUTF( user.getAddress().getHostString() );
out.writeInt( user.getAddress().getPort() ); out.writeInt( user.getAddress().getPort() );
channel.write( new PluginMessage( "BungeeCord", out.toByteArray() ) ); // channel.write( new PluginMessage( "BungeeCord", out.toByteArray() ) ); MOJANG
// channel.write( user.getPendingConnection().getHandshake() ); FIX channel.write( user.getPendingConnection().getHandshake() );
// Skip encryption if we are not using Forge channel.setProtocol( Protocol.LOGIN );
if ( user.getPendingConnection().getForgeLogin() == null ) channel.write( user.getPendingConnection().getLoginRequest() );
{
channel.write( PacketConstants.CLIENT_LOGIN );
}
} }
@Override @Override
@ -91,6 +83,24 @@ public class ServerConnector extends PacketHandler
user.getPendingConnects().remove( target ); user.getPendingConnects().remove( target );
} }
@Override
public void handle(PacketWrapper packet) throws Exception
{
int packetID = DefinedPacket.readVarInt( packet.buf );
System.out.println( packetID + " : " + packet.packet );
super.handle( packet ); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void handle(LoginSuccess loginSuccess) throws Exception
{
Preconditions.checkState( thisState == State.LOGIN_SUCCESS, "Not exepcting LOGIN_SUCCESS" );
ch.setProtocol( Protocol.GAME );
thisState = State.LOGIN;
throw new CancelSendSignal();
}
@Override @Override
public void handle(Login login) throws Exception public void handle(Login login) throws Exception
{ {
@ -114,13 +124,6 @@ public class ServerConnector extends PacketHandler
{ {
ch.write( message ); ch.write( message );
} }
if ( !sentMessages )
{
for ( PluginMessage message : user.getPendingConnection().getLoginMessages() )
{
ch.write( message );
}
}
if ( user.getSettings() != null ) if ( user.getSettings() != null )
{ {
@ -194,20 +197,6 @@ public class ServerConnector extends PacketHandler
throw new CancelSendSignal(); throw new CancelSendSignal();
} }
@Override
public void handle(EncryptionResponse encryptResponse) throws Exception
{
Preconditions.checkState( thisState == State.ENCRYPT_RESPONSE, "Not expecting ENCRYPT_RESPONSE" );
Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, secretkey );
ch.addBefore( PipelineUtils.FRAME_DECODER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) );
ch.write( user.getPendingConnection().getForgeLogin() );
ch.write( PacketConstants.CLIENT_LOGIN );
thisState = State.LOGIN;
}
@Override @Override
public void handle(Kick kick) throws Exception public void handle(Kick kick) throws Exception
{ {
@ -233,39 +222,6 @@ public class ServerConnector extends PacketHandler
} }
} }
@Override
public void handle(PluginMessage pluginMessage) throws Exception
{
if ( pluginMessage.equals( PacketConstants.I_AM_BUNGEE ) )
{
throw new IllegalStateException( "May not connect to another BungeCord!" );
}
DataInput in = pluginMessage.getStream();
if ( pluginMessage.getTag().equals( "FML" ) && in.readUnsignedByte() == 0 )
{
int count = in.readInt();
for ( int i = 0; i < count; i++ )
{
in.readUTF();
}
if ( in.readByte() != 0 )
{
// TODO: Using forge flag
}
}
user.unsafe().sendPacket( pluginMessage ); // We have to forward these to the user, especially with Forge as stuff might break
if ( !sentMessages && user.getPendingConnection().getForgeLogin() != null )
{
for ( PluginMessage message : user.getPendingConnection().getLoginMessages() )
{
ch.write( message );
}
sentMessages = true;
}
}
@Override @Override
public String toString() public String toString()
{ {

View File

@ -32,7 +32,11 @@ import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.netty.HandlerBoss; import net.md_5.bungee.netty.HandlerBoss;
import net.md_5.bungee.protocol.PacketWrapper; import net.md_5.bungee.protocol.PacketWrapper;
import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.netty.PipelineUtils;
import static net.md_5.bungee.netty.PipelineUtils.FRAME_DECODER;
import static net.md_5.bungee.netty.PipelineUtils.PACKET_CODEC;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.MinecraftCodec;
import net.md_5.bungee.protocol.Protocol;
import net.md_5.bungee.protocol.packet.Chat; import net.md_5.bungee.protocol.packet.Chat;
import net.md_5.bungee.protocol.packet.ClientSettings; import net.md_5.bungee.protocol.packet.ClientSettings;
import net.md_5.bungee.protocol.packet.PluginMessage; import net.md_5.bungee.protocol.packet.PluginMessage;
@ -200,6 +204,7 @@ public final class UserConnection implements ProxiedPlayer
protected void initChannel(Channel ch) throws Exception protected void initChannel(Channel ch) throws Exception
{ {
PipelineUtils.BASE.initChannel( ch ); PipelineUtils.BASE.initChannel( ch );
ch.pipeline().addAfter( FRAME_DECODER, PACKET_CODEC, new MinecraftCodec( Protocol.HANDSHAKE, false ) );
ch.pipeline().get( HandlerBoss.class ).setHandler( new ServerConnector( bungee, UserConnection.this, target ) ); ch.pipeline().get( HandlerBoss.class ).setHandler( new ServerConnector( bungee, UserConnection.this, target ) );
} }
}; };

View File

@ -74,7 +74,7 @@ public class DownstreamBridge extends PacketHandler
{ {
if ( !server.isObsolete() ) if ( !server.isObsolete() )
{ {
EntityMap.rewrite( packet.buf, con.getServerEntityId(), con.getClientEntityId() ); // EntityMap.rewrite( packet.buf, con.getServerEntityId(), con.getClientEntityId() );
con.sendPacket( packet ); con.sendPacket( packet );
} }
} }

View File

@ -104,7 +104,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
{ {
int len = DefinedPacket.readVarInt( packet.buf ); int len = DefinedPacket.readVarInt( packet.buf );
int id = DefinedPacket.readVarInt( packet.buf ); int id = DefinedPacket.readVarInt( packet.buf );
throw new UnsupportedOperationException( "Cannot handle unknown packet at login!" ); // throw new UnsupportedOperationException( "Cannot handle unknown packet at login!" );
} }
@Override @Override
@ -343,7 +343,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection
{ {
UUID = java.util.UUID.randomUUID().toString(); UUID = java.util.UUID.randomUUID().toString();
} }
unsafe.sendPacket( new LoginSuccess( BungeeCord.getInstance().gson.toJson( new LoginResult( UUID ) ) ) ); System.out.println( ch.getHandle().pipeline() );
unsafe.sendPacket( new LoginSuccess( UUID, getName() ) );
ch.setProtocol( Protocol.GAME ); ch.setProtocol( Protocol.GAME );
UserConnection userCon = new UserConnection( bungee, ch, getName(), InitialHandler.this ); UserConnection userCon = new UserConnection( bungee, ch, getName(), InitialHandler.this );
@ -361,7 +362,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
{ {
server = AbstractReconnectHandler.getForcedHost( InitialHandler.this ); server = AbstractReconnectHandler.getForcedHost( InitialHandler.this );
} }
userCon.connect( server, true ); // userCon.connect( server, true );
thisState = State.FINISHED; thisState = State.FINISHED;
} }

View File

@ -59,7 +59,7 @@ public class UpstreamBridge extends PacketHandler
@Override @Override
public void handle(PacketWrapper packet) throws Exception public void handle(PacketWrapper packet) throws Exception
{ {
EntityMap.rewrite( packet.buf, con.getClientEntityId(), con.getServerEntityId() ); // EntityMap.rewrite( packet.buf, con.getClientEntityId(), con.getServerEntityId() );
if ( con.getServer() != null ) if ( con.getServer() != null )
{ {
con.getServer().getCh().write( packet ); con.getServer().getCh().write( packet );

View File

@ -10,7 +10,6 @@ import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import net.md_5.bungee.BungeeCord; import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.BungeeServerInfo; import net.md_5.bungee.BungeeServerInfo;
import net.md_5.bungee.ServerConnector;
import net.md_5.bungee.UserConnection; import net.md_5.bungee.UserConnection;
import net.md_5.bungee.connection.InitialHandler; import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
@ -40,19 +39,10 @@ public class PipelineUtils
BASE.initChannel( ch ); BASE.initChannel( ch );
ch.pipeline().addAfter( FRAME_DECODER, PACKET_CODEC, new MinecraftCodec( Protocol.HANDSHAKE, true ) ); ch.pipeline().addAfter( FRAME_DECODER, PACKET_CODEC, new MinecraftCodec( Protocol.HANDSHAKE, true ) );
System.out.println( ch.pipeline() );
ch.pipeline().get( HandlerBoss.class ).setHandler( new InitialHandler( ProxyServer.getInstance(), ch.attr( LISTENER ).get() ) ); ch.pipeline().get( HandlerBoss.class ).setHandler( new InitialHandler( ProxyServer.getInstance(), ch.attr( LISTENER ).get() ) );
} }
}; };
public static final ChannelInitializer<Channel> CLIENT = new ChannelInitializer<Channel>()
{
@Override
protected void initChannel(Channel ch) throws Exception
{
BASE.initChannel( ch );
ch.pipeline().addAfter( FRAME_DECODER, PACKET_CODEC, new MinecraftCodec( Protocol.LOGIN, false) );
ch.pipeline().get( HandlerBoss.class ).setHandler( new ServerConnector( ProxyServer.getInstance(), ch.attr( USER ).get(), ch.attr( TARGET ).get() ) );
}
};
public static final Base BASE = new Base(); public static final Base BASE = new Base();
private static final Varint21LengthFieldPrepender framePrepender = new Varint21LengthFieldPrepender(); private static final Varint21LengthFieldPrepender framePrepender = new Varint21LengthFieldPrepender();
public static String TIMEOUT_HANDLER = "timeout"; public static String TIMEOUT_HANDLER = "timeout";
@ -76,9 +66,10 @@ public class PipelineUtils
{ {
// IP_TOS is not supported (Windows XP / Windows Server 2003) // IP_TOS is not supported (Windows XP / Windows Server 2003)
} }
ch.pipeline().addLast( FRAME_PREPENDER, framePrepender );
ch.pipeline().addLast( TIMEOUT_HANDLER, new ReadTimeoutHandler( BungeeCord.getInstance().config.getTimeout(), TimeUnit.MILLISECONDS ) ); ch.pipeline().addLast( TIMEOUT_HANDLER, new ReadTimeoutHandler( BungeeCord.getInstance().config.getTimeout(), TimeUnit.MILLISECONDS ) );
ch.pipeline().addLast( FRAME_DECODER, new Varint21FrameDecoder() ); ch.pipeline().addLast( FRAME_DECODER, new Varint21FrameDecoder() );
ch.pipeline().addLast( FRAME_PREPENDER, framePrepender );
ch.pipeline().addLast( BOSS_HANDLER, new HandlerBoss() ); ch.pipeline().addLast( BOSS_HANDLER, new HandlerBoss() );
} }