It compiles

This commit is contained in:
md_5 2013-10-11 20:00:54 +11:00
parent 7be929bb08
commit d900417d95
24 changed files with 186 additions and 199 deletions

View File

@ -180,7 +180,7 @@ public abstract class ProxyServer
* *
* @return the Minecraft protocol version * @return the Minecraft protocol version
*/ */
public abstract byte getProtocolVersion(); public abstract int getProtocolVersion();
/** /**
* Factory method to construct an implementation specific server info * Factory method to construct an implementation specific server info

View File

@ -21,7 +21,7 @@ public interface PendingConnection extends Connection
* *
* @return the protocol version of the remote client * @return the protocol version of the remote client
*/ */
byte getVersion(); int getVersion();
/** /**
* Get the requested virtual host that the client tried to connect to. * Get the requested virtual host that the client tried to connect to.

View File

@ -6,6 +6,7 @@ import lombok.ToString;
import net.md_5.bungee.api.connection.PendingConnection; import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.protocol.packet.Packet2Handshake; import net.md_5.bungee.protocol.packet.Packet2Handshake;
import net.md_5.bungee.api.plugin.Event; import net.md_5.bungee.api.plugin.Event;
import net.md_5.bungee.protocol.packet.Handshake;
/** /**
* Event called to represent a player first making their presence and username * Event called to represent a player first making their presence and username
@ -24,9 +25,9 @@ public class PlayerHandshakeEvent extends Event
/** /**
* The handshake. * The handshake.
*/ */
private final Packet2Handshake handshake; private final Handshake handshake;
public PlayerHandshakeEvent(PendingConnection connection, Packet2Handshake handshake) public PlayerHandshakeEvent(PendingConnection connection, Handshake handshake)
{ {
this.connection = connection; this.connection = connection;
this.handshake = handshake; this.handshake = handshake;

View File

@ -21,7 +21,7 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-buffer</artifactId> <artifactId>netty-codec</artifactId>
<version>${netty.version}</version> <version>${netty.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>

View File

@ -5,6 +5,7 @@ import net.md_5.bungee.protocol.packet.ClientSettings;
import net.md_5.bungee.protocol.packet.ClientStatus; import net.md_5.bungee.protocol.packet.ClientStatus;
import net.md_5.bungee.protocol.packet.Login; import net.md_5.bungee.protocol.packet.Login;
import net.md_5.bungee.protocol.packet.Chat; import net.md_5.bungee.protocol.packet.Chat;
import net.md_5.bungee.protocol.packet.EncryptionRequest;
import net.md_5.bungee.protocol.packet.PlayerListItem; import net.md_5.bungee.protocol.packet.PlayerListItem;
import net.md_5.bungee.protocol.packet.TabComplete; import net.md_5.bungee.protocol.packet.TabComplete;
import net.md_5.bungee.protocol.packet.ScoreboardObjective; import net.md_5.bungee.protocol.packet.ScoreboardObjective;
@ -70,6 +71,10 @@ public abstract class AbstractPacketHandler
{ {
} }
public void handle(EncryptionRequest encryptionRequest) throws Exception
{
}
public void handle(ScoreboardDisplay displayScoreboard) throws Exception public void handle(ScoreboardDisplay displayScoreboard) throws Exception
{ {
} }

View File

@ -8,7 +8,7 @@ import lombok.RequiredArgsConstructor;
public abstract class DefinedPacket public abstract class DefinedPacket
{ {
public void writeString(String s, ByteBuf buf) public static void writeString(String s, ByteBuf buf)
{ {
// TODO: Check len - use Guava? // TODO: Check len - use Guava?
byte[] b = s.getBytes( Charsets.UTF_8 ); byte[] b = s.getBytes( Charsets.UTF_8 );
@ -16,7 +16,7 @@ public abstract class DefinedPacket
buf.writeBytes( b ); buf.writeBytes( b );
} }
public String readString(ByteBuf buf) public static String readString(ByteBuf buf)
{ {
int len = readVarInt( buf ); int len = readVarInt( buf );
byte[] b = new byte[ len ]; byte[] b = new byte[ len ];
@ -25,14 +25,14 @@ public abstract class DefinedPacket
return new String( b, Charsets.UTF_8 ); return new String( b, Charsets.UTF_8 );
} }
public void writeArray(byte[] b, ByteBuf buf) public static void writeArray(byte[] b, ByteBuf buf)
{ {
// TODO: Check len - use Guava? // TODO: Check len - use Guava?
buf.writeShort( b.length ); buf.writeShort( b.length );
buf.writeBytes( b ); buf.writeBytes( b );
} }
public byte[] readArray(ByteBuf buf) public static byte[] readArray(ByteBuf buf)
{ {
// TODO: Check len - use Guava? // TODO: Check len - use Guava?
short len = buf.readShort(); short len = buf.readShort();
@ -41,7 +41,7 @@ public abstract class DefinedPacket
return ret; return ret;
} }
public int readVarInt(ByteBuf input) public static int readVarInt(ByteBuf input)
{ {
int out = 0; int out = 0;
int bytes = 0; int bytes = 0;
@ -66,7 +66,7 @@ public abstract class DefinedPacket
return out; return out;
} }
public void writeVarInt(int value, ByteBuf output) public static void writeVarInt(int value, ByteBuf output)
{ {
int part; int part;
while ( true ) while ( true )

View File

@ -0,0 +1,38 @@
package net.md_5.bungee.protocol;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import java.util.List;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class MinecraftCodec extends MessageToMessageCodec<ByteBuf, DefinedPacket>
{
private Protocol protocol;
@Override
protected void encode(ChannelHandlerContext ctx, DefinedPacket msg, List<Object> out) throws Exception
{
ByteBuf buf = ctx.alloc().buffer();
DefinedPacket.writeVarInt( protocol.getId( msg.getClass() ), buf );
msg.write( buf );
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception
{
int packetId = DefinedPacket.readVarInt( msg );
ByteBuf copy = msg.copy();
DefinedPacket packet = null;
if ( protocol.hasPacket( packetId ) )
{
packet = protocol.createPacket( packetId );
packet.read( msg );
}
out.add( new PacketWrapper( packet, copy ) );
}
}

View File

@ -1,4 +1,4 @@
package net.md_5.bungee.netty; package net.md_5.bungee.protocol;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;

View File

@ -5,6 +5,7 @@ import gnu.trove.map.hash.TObjectIntHashMap;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
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.EncryptionResponse; import net.md_5.bungee.protocol.packet.EncryptionResponse;
import net.md_5.bungee.protocol.packet.Handshake; import net.md_5.bungee.protocol.packet.Handshake;
import net.md_5.bungee.protocol.packet.KeepAlive; import net.md_5.bungee.protocol.packet.KeepAlive;
@ -82,7 +83,7 @@ public enum Protocol
{ {
registerPacket( 0x00, Kick.class ); registerPacket( 0x00, Kick.class );
registerPacket( 0x01, EncryptionResponse.class ); registerPacket( 0x01, EncryptionRequest.class );
registerPacket( 0x02, LoginSuccess.class ); registerPacket( 0x02, LoginSuccess.class );
} }
}, },
@ -92,15 +93,23 @@ public enum Protocol
{ {
registerPacket( 0x00, LoginRequest.class ); registerPacket( 0x00, LoginRequest.class );
registerPacket( 0x01, EncryptionResponse.class );
} }
}; };
/*========================================================================*/ /*========================================================================*/
public static final int MAX_PACKET_ID = 0xFF; public static final int MAX_PACKET_ID = 0xFF;
public static final int PROTOCOL_VERSION = 0x00;
public static final String MINECRAFT_VERSION = "13w41a";
/*========================================================================*/ /*========================================================================*/
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 ];
public boolean hasPacket(int id)
{
return id < MAX_PACKET_ID && packetConstructors[id] != null;
}
public final DefinedPacket createPacket(int id) public final DefinedPacket createPacket(int id)
{ {
if ( id > MAX_PACKET_ID ) if ( id > MAX_PACKET_ID )

View File

@ -0,0 +1,43 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class EncryptionRequest extends DefinedPacket
{
private String serverId;
private byte[] publicKey;
private byte[] verifyToken;
@Override
public void read(ByteBuf buf)
{
serverId = readString( buf );
publicKey = readArray( buf );
verifyToken = readArray( buf );
}
@Override
public void write(ByteBuf buf)
{
writeString( serverId, buf );
writeArray( publicKey, buf );
writeArray( verifyToken, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@ -16,16 +16,16 @@ public class Handshake extends DefinedPacket
{ {
private int protocolVersion; private int protocolVersion;
private String serverAddress; private String host;
private int serverPort; private int port;
private int requestedProtocol; private int requestedProtocol;
@Override @Override
public void read(ByteBuf buf) public void read(ByteBuf buf)
{ {
protocolVersion = readVarInt( buf ); protocolVersion = readVarInt( buf );
serverAddress = readString( buf ); host = readString( buf );
serverPort = readVarInt( buf ); port = readVarInt( buf );
requestedProtocol = readVarInt( buf ); requestedProtocol = readVarInt( buf );
} }
@ -33,8 +33,8 @@ public class Handshake extends DefinedPacket
public void write(ByteBuf buf) public void write(ByteBuf buf)
{ {
writeVarInt( protocolVersion, buf ); writeVarInt( protocolVersion, buf );
writeString( serverAddress, buf ); writeString( host, buf );
writeVarInt( serverPort, buf ); writeVarInt( port, buf );
writeVarInt( requestedProtocol, buf ); writeVarInt( requestedProtocol, buf );
} }

View File

@ -58,9 +58,9 @@ import net.md_5.bungee.config.YamlConfig;
import net.md_5.bungee.log.LoggingOutputStream; import net.md_5.bungee.log.LoggingOutputStream;
import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.netty.PipelineUtils;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
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.PluginMessage; import net.md_5.bungee.protocol.packet.PluginMessage;
import net.md_5.bungee.protocol.Vanilla;
import net.md_5.bungee.query.RemoteQuery; import net.md_5.bungee.query.RemoteQuery;
import net.md_5.bungee.tab.Custom; import net.md_5.bungee.tab.Custom;
import net.md_5.bungee.util.CaseInsensitiveMap; import net.md_5.bungee.util.CaseInsensitiveMap;
@ -453,15 +453,15 @@ public class BungeeCord extends ProxyServer
} }
@Override @Override
public byte getProtocolVersion() public int getProtocolVersion()
{ {
return Vanilla.PROTOCOL_VERSION; return Protocol.PROTOCOL_VERSION;
} }
@Override @Override
public String getGameVersion() public String getGameVersion()
{ {
return Vanilla.GAME_VERSION; return Protocol.MINECRAFT_VERSION;
} }
@Override @Override

View File

@ -16,7 +16,7 @@ import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import lombok.Getter; import lombok.Getter;
import net.md_5.bungee.protocol.packet.EncryptionResponse; import net.md_5.bungee.protocol.packet.EncryptionResponse;
import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest; import net.md_5.bungee.protocol.packet.EncryptionRequest;
/** /**
* Class containing all encryption related methods for the proxy. * Class containing all encryption related methods for the proxy.
@ -40,16 +40,16 @@ public class EncryptionUtil
} }
} }
public static PacketFDEncryptionRequest encryptRequest(boolean onlinemode) public static EncryptionRequest encryptRequest(boolean onlinemode)
{ {
String hash = ( onlinemode ) ? Long.toString( random.nextLong(), 16 ) : "-"; String hash = ( onlinemode ) ? Long.toString( random.nextLong(), 16 ) : "-";
byte[] pubKey = keys.getPublic().getEncoded(); byte[] pubKey = keys.getPublic().getEncoded();
byte[] verify = new byte[ 4 ]; byte[] verify = new byte[ 4 ];
random.nextBytes( verify ); random.nextBytes( verify );
return new PacketFDEncryptionRequest( hash, pubKey, verify ); return new EncryptionRequest( hash, pubKey, verify );
} }
public static SecretKey getSecret(EncryptionResponse resp, PacketFDEncryptionRequest request) throws GeneralSecurityException public static SecretKey getSecret(EncryptionResponse resp, EncryptionRequest request) throws GeneralSecurityException
{ {
Cipher cipher = Cipher.getInstance( "RSA" ); Cipher cipher = Cipher.getInstance( "RSA" );
cipher.init( Cipher.DECRYPT_MODE, keys.getPrivate() ); cipher.init( Cipher.DECRYPT_MODE, keys.getPrivate() );
@ -71,7 +71,7 @@ public class EncryptionUtil
return cip; return cip;
} }
public static PublicKey getPubkey(PacketFDEncryptionRequest request) throws GeneralSecurityException public static PublicKey getPubkey(EncryptionRequest request) throws GeneralSecurityException
{ {
return KeyFactory.getInstance( "RSA" ).generatePublic( new X509EncodedKeySpec( request.getPublicKey() ) ); return KeyFactory.getInstance( "RSA" ).generatePublic( new X509EncodedKeySpec( request.getPublicKey() ) );
} }

View File

@ -4,7 +4,6 @@ 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.io.DataInput;
import java.security.PublicKey;
import java.util.Objects; import java.util.Objects;
import java.util.Queue; import java.util.Queue;
import javax.crypto.Cipher; import javax.crypto.Cipher;
@ -24,22 +23,16 @@ 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.CipherDecoder;
import net.md_5.bungee.netty.CipherEncoder;
import net.md_5.bungee.netty.PacketDecoder;
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.netty.PipelineUtils;
import net.md_5.bungee.protocol.Forge;
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.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.Team;
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.EncryptionResponse;
import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest;
import net.md_5.bungee.protocol.packet.Kick; import net.md_5.bungee.protocol.packet.Kick;
import net.md_5.bungee.protocol.packet.forge.Forge1Login;
@RequiredArgsConstructor @RequiredArgsConstructor
public class ServerConnector extends PacketHandler public class ServerConnector extends PacketHandler
@ -83,7 +76,7 @@ public class ServerConnector extends PacketHandler
out.writeInt( user.getAddress().getPort() ); out.writeInt( user.getAddress().getPort() );
channel.write( new PluginMessage( "BungeeCord", out.toByteArray() ) ); channel.write( new PluginMessage( "BungeeCord", out.toByteArray() ) );
channel.write( user.getPendingConnection().getHandshake() ); // channel.write( user.getPendingConnection().getHandshake() ); FIX
// Skip encryption if we are not using Forge // Skip encryption if we are not using Forge
if ( user.getPendingConnection().getForgeLogin() == null ) if ( user.getPendingConnection().getForgeLogin() == null )
@ -143,16 +136,9 @@ public class ServerConnector extends PacketHandler
user.setServerEntityId( login.getEntityId() ); user.setServerEntityId( login.getEntityId() );
// Set tab list size, this sucks balls, TODO: what shall we do about packet mutability // Set tab list size, this sucks balls, TODO: what shall we do about packet mutability
Login modLogin; Login modLogin = new Login( login.getEntityId(), login.getLevelType(), login.getGameMode(), (byte) login.getDimension(), login.getDifficulty(), login.getUnused(),
if ( ch.getHandle().pipeline().get( PacketDecoder.class ).getProtocol() == Forge.getInstance() ) (byte) user.getPendingConnection().getListener().getTabListSize() );
{
modLogin = new Forge1Login( login.getEntityId(), login.getLevelType(), login.getGameMode(), login.getDimension(), login.getDifficulty(), login.getUnused(),
(byte) user.getPendingConnection().getListener().getTabListSize() );
} else
{
modLogin = new Login( login.getEntityId(), login.getLevelType(), login.getGameMode(), (byte) login.getDimension(), login.getDifficulty(), login.getUnused(),
(byte) user.getPendingConnection().getListener().getTabListSize() );
}
user.unsafe().sendPacket( modLogin ); user.unsafe().sendPacket( modLogin );
MinecraftOutput out = new MinecraftOutput(); MinecraftOutput out = new MinecraftOutput();
@ -169,7 +155,7 @@ public class ServerConnector extends PacketHandler
} }
for ( Team team : serverScoreboard.getTeams() ) for ( Team team : serverScoreboard.getTeams() )
{ {
user.unsafe().sendPacket( new Team( team.getName() ) ); user.unsafe().sendPacket( new net.md_5.bungee.protocol.packet.Team( team.getName() ) );
} }
serverScoreboard.clear(); serverScoreboard.clear();
@ -208,39 +194,13 @@ public class ServerConnector extends PacketHandler
throw new CancelSendSignal(); throw new CancelSendSignal();
} }
@Override
public void handle(PacketFDEncryptionRequest encryptRequest) throws Exception
{
Preconditions.checkState( thisState == State.ENCRYPT_REQUEST, "Not expecting ENCRYPT_REQUEST" );
// Only need to handle this if we want to use encryption
if ( user.getPendingConnection().getForgeLogin() != null )
{
PublicKey publickey = EncryptionUtil.getPubkey( encryptRequest );
this.secretkey = EncryptionUtil.getSecret();
byte[] shared = EncryptionUtil.encrypt( publickey, secretkey.getEncoded() );
byte[] token = EncryptionUtil.encrypt( publickey, encryptRequest.getVerifyToken() );
ch.write( new EncryptionResponse( shared, token ) );
Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, secretkey );
ch.addBefore( PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) );
thisState = State.ENCRYPT_RESPONSE;
} else
{
thisState = State.LOGIN;
}
}
@Override @Override
public void handle(EncryptionResponse encryptResponse) throws Exception public void handle(EncryptionResponse encryptResponse) throws Exception
{ {
Preconditions.checkState( thisState == State.ENCRYPT_RESPONSE, "Not expecting ENCRYPT_RESPONSE" ); Preconditions.checkState( thisState == State.ENCRYPT_RESPONSE, "Not expecting ENCRYPT_RESPONSE" );
Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, secretkey ); Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, secretkey );
ch.addBefore( PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) ); ch.addBefore( PipelineUtils.FRAME_DECODER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) );
ch.write( user.getPendingConnection().getForgeLogin() ); ch.write( user.getPendingConnection().getForgeLogin() );
@ -292,7 +252,6 @@ public class ServerConnector extends PacketHandler
if ( in.readByte() != 0 ) if ( in.readByte() != 0 )
{ {
// TODO: Using forge flag // TODO: Using forge flag
ch.getHandle().pipeline().get( PacketDecoder.class ).setProtocol( Forge.getInstance() );
} }
} }

View File

@ -30,7 +30,7 @@ import net.md_5.bungee.api.tab.TabListHandler;
import net.md_5.bungee.connection.InitialHandler; import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.netty.ChannelWrapper; 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.netty.PacketWrapper; import net.md_5.bungee.protocol.PacketWrapper;
import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.netty.PipelineUtils;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.packet.Chat; import net.md_5.bungee.protocol.packet.Chat;

View File

@ -21,13 +21,12 @@ import net.md_5.bungee.api.score.Scoreboard;
import net.md_5.bungee.api.score.Team; import net.md_5.bungee.api.score.Team;
import net.md_5.bungee.netty.ChannelWrapper; import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.netty.PacketHandler;
import net.md_5.bungee.netty.PacketWrapper; import net.md_5.bungee.protocol.PacketWrapper;
import net.md_5.bungee.protocol.packet.KeepAlive; import net.md_5.bungee.protocol.packet.KeepAlive;
import net.md_5.bungee.protocol.packet.PlayerListItem; import net.md_5.bungee.protocol.packet.PlayerListItem;
import net.md_5.bungee.protocol.packet.ScoreboardObjective; import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore; import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay; import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.Team;
import net.md_5.bungee.protocol.packet.PluginMessage; import net.md_5.bungee.protocol.packet.PluginMessage;
import net.md_5.bungee.protocol.packet.Kick; import net.md_5.bungee.protocol.packet.Kick;
@ -138,7 +137,7 @@ public class DownstreamBridge extends PacketHandler
} }
@Override @Override
public void handle(Team team) throws Exception public void handle(net.md_5.bungee.protocol.packet.Team team) throws Exception
{ {
Scoreboard serverScoreboard = con.getServerSentScoreboard(); Scoreboard serverScoreboard = con.getServerSentScoreboard();
// Remove team and move on // Remove team and move on

View File

@ -4,14 +4,11 @@ import com.google.common.base.Preconditions;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import io.netty.util.concurrent.ScheduledFuture; import io.netty.util.concurrent.ScheduledFuture;
import java.math.BigInteger;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level; import java.util.logging.Level;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
@ -38,23 +35,20 @@ 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.CipherDecoder;
import net.md_5.bungee.netty.CipherEncoder; import net.md_5.bungee.netty.CipherEncoder;
import net.md_5.bungee.netty.PacketDecoder;
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.netty.PipelineUtils;
import net.md_5.bungee.protocol.Forge;
import net.md_5.bungee.protocol.MinecraftInput; import net.md_5.bungee.protocol.MinecraftInput;
import net.md_5.bungee.protocol.Vanilla;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.packet.Login; import net.md_5.bungee.protocol.packet.Login;
import net.md_5.bungee.protocol.packet.Packet2Handshake; import net.md_5.bungee.protocol.packet.Handshake;
import net.md_5.bungee.protocol.packet.ClientStatus; import net.md_5.bungee.protocol.packet.ClientStatus;
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.EncryptionResponse;
import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest; import net.md_5.bungee.protocol.packet.EncryptionRequest;
import net.md_5.bungee.protocol.packet.PacketFEPing;
import net.md_5.bungee.protocol.packet.Kick; import net.md_5.bungee.protocol.packet.Kick;
import net.md_5.bungee.api.AbstractReconnectHandler; import net.md_5.bungee.api.AbstractReconnectHandler;
import net.md_5.bungee.api.event.PlayerHandshakeEvent; import net.md_5.bungee.api.event.PlayerHandshakeEvent;
import net.md_5.bungee.protocol.packet.LoginRequest;
@RequiredArgsConstructor @RequiredArgsConstructor
public class InitialHandler extends PacketHandler implements PendingConnection public class InitialHandler extends PacketHandler implements PendingConnection
@ -67,8 +61,10 @@ public class InitialHandler extends PacketHandler implements PendingConnection
@Getter @Getter
private Login forgeLogin; private Login forgeLogin;
@Getter @Getter
private Packet2Handshake handshake; private Handshake handshake;
private PacketFDEncryptionRequest request; @Getter
private LoginRequest loginRequest;
private EncryptionRequest request;
@Getter @Getter
private List<PluginMessage> loginMessages = new ArrayList<>(); private List<PluginMessage> loginMessages = new ArrayList<>();
@Getter @Getter
@ -170,35 +166,25 @@ public class InitialHandler extends PacketHandler implements PendingConnection
forced.ping( pingBack ); forced.ping( pingBack );
} else } else
{ {
pingBack.done( new ServerPing( bungee.getProtocolVersion(), bungee.getGameVersion(), motd, bungee.getOnlineCount(), listener.getMaxPlayers() ), null ); // pingBack.done( new ServerPing( bungee.getProtocolVersion(), bungee.getGameVersion(), motd, bungee.getOnlineCount(), listener.getMaxPlayers() ), null );
} }
} }
/*
@Override
public void handle(PacketFEPing ping) throws Exception
{
pingFuture = ch.getHandle().eventLoop().schedule( new Runnable()
{
@Override
public void run()
{
respondToPing();
}
}, 200, TimeUnit.MILLISECONDS );
}*/
@Override @Override
public void handle(PacketFEPing ping) throws Exception public void handle(Handshake handshake) throws Exception
{
pingFuture = ch.getHandle().eventLoop().schedule( new Runnable()
{
@Override
public void run()
{
respondToPing();
}
}, 200, TimeUnit.MILLISECONDS );
}
@Override
public void handle(Login login) throws Exception
{
Preconditions.checkState( thisState == State.LOGIN, "Not expecting FORGE LOGIN" );
Preconditions.checkState( forgeLogin == null, "Already received FORGE LOGIN" );
forgeLogin = login;
ch.getHandle().pipeline().get( PacketDecoder.class ).setProtocol( Forge.getInstance() );
}
@Override
public void handle(Packet2Handshake handshake) throws Exception
{ {
Preconditions.checkState( thisState == State.HANDSHAKE, "Not expecting HANDSHAKE" ); Preconditions.checkState( thisState == State.HANDSHAKE, "Not expecting HANDSHAKE" );
this.handshake = handshake; this.handshake = handshake;
@ -207,15 +193,22 @@ public class InitialHandler extends PacketHandler implements PendingConnection
bungee.getPluginManager().callEvent( new PlayerHandshakeEvent( InitialHandler.this, handshake ) ); bungee.getPluginManager().callEvent( new PlayerHandshakeEvent( InitialHandler.this, handshake ) );
if ( handshake.getProtocolVersion() > Vanilla.PROTOCOL_VERSION ) if ( handshake.getProtocolVersion() > bungee.getProtocolVersion() )
{ {
disconnect( bungee.getTranslation( "outdated_server" ) ); disconnect( bungee.getTranslation( "outdated_server" ) );
} else if ( handshake.getProtocolVersion() < Vanilla.PROTOCOL_VERSION ) } else if ( handshake.getProtocolVersion() < bungee.getProtocolVersion() )
{ {
disconnect( bungee.getTranslation( "outdated_client" ) ); disconnect( bungee.getTranslation( "outdated_client" ) );
} }
if ( handshake.getUsername().length() > 16 ) }
@Override
public void handle(LoginRequest loginRequest) throws Exception
{
this.loginRequest = loginRequest;
if ( getName().length() > 16 )
{ {
disconnect( "Cannot have username longer than 16 characters" ); disconnect( "Cannot have username longer than 16 characters" );
return; return;
@ -229,7 +222,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
} }
// If offline mode and they are already on, don't allow connect // If offline mode and they are already on, don't allow connect
if ( !isOnlineMode() && bungee.getPlayer( handshake.getUsername() ) != null ) if ( !isOnlineMode() && bungee.getPlayer( getName() ) != null )
{ {
disconnect( bungee.getTranslation( "already_connected" ) ); disconnect( bungee.getTranslation( "already_connected" ) );
return; return;
@ -249,7 +242,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
sharedKey = EncryptionUtil.getSecret( encryptResponse, request ); sharedKey = EncryptionUtil.getSecret( encryptResponse, request );
Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, sharedKey ); Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, sharedKey );
ch.addBefore( PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) ); ch.addBefore( PipelineUtils.FRAME_DECODER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) );
if ( this.onlineMode ) if ( this.onlineMode )
{ {
@ -295,7 +288,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
private void finish() private void finish()
{ {
// Check for multiple connections // Check for multiple connections
ProxiedPlayer old = bungee.getPlayer( handshake.getUsername() ); ProxiedPlayer old = bungee.getPlayer( getName() );
if ( old != null ) if ( old != null )
{ {
old.disconnect( bungee.getTranslation( "already_connected" ) ); old.disconnect( bungee.getTranslation( "already_connected" ) );
@ -381,11 +374,11 @@ public class InitialHandler extends PacketHandler implements PendingConnection
@Override @Override
public String getName() public String getName()
{ {
return ( handshake == null ) ? null : handshake.getUsername(); return ( loginRequest == null ) ? null : loginRequest.getData();
} }
@Override @Override
public byte getVersion() public int getVersion()
{ {
return ( handshake == null ) ? version : handshake.getProtocolVersion(); return ( handshake == null ) ? version : handshake.getProtocolVersion();
} }

View File

@ -10,7 +10,7 @@ import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PluginMessageEvent; import net.md_5.bungee.api.event.PluginMessageEvent;
import net.md_5.bungee.netty.ChannelWrapper; import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.netty.PacketHandler;
import net.md_5.bungee.netty.PacketWrapper; import net.md_5.bungee.protocol.PacketWrapper;
import net.md_5.bungee.protocol.packet.KeepAlive; import net.md_5.bungee.protocol.packet.KeepAlive;
import net.md_5.bungee.protocol.packet.Chat; import net.md_5.bungee.protocol.packet.Chat;
import net.md_5.bungee.protocol.packet.TabComplete; import net.md_5.bungee.protocol.packet.TabComplete;

View File

@ -1,5 +1,6 @@
package net.md_5.bungee.netty; package net.md_5.bungee.netty;
import net.md_5.bungee.protocol.PacketWrapper;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler;

View File

@ -1,19 +0,0 @@
package net.md_5.bungee.netty;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import net.md_5.bungee.protocol.DefinedPacket;
@ChannelHandler.Sharable
public class DefinedPacketEncoder extends MessageToByteEncoder<DefinedPacket>
{
@Override
protected void encode(ChannelHandlerContext ctx, DefinedPacket msg, ByteBuf out) throws Exception
{
out.writeByte( msg.getId() );
msg.write( out );
}
}

View File

@ -1,5 +1,6 @@
package net.md_5.bungee.netty; package net.md_5.bungee.netty;
import net.md_5.bungee.protocol.PacketWrapper;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;

View File

@ -1,50 +0,0 @@
package net.md_5.bungee.netty;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import net.md_5.bungee.protocol.Protocol;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.skip.PacketReader;
/**
* This class will attempt to read a packet from {@link PacketReader}, with the
* specified {@link #protocol} before returning a new {@link ByteBuf} with the
* copied contents of all bytes read in this frame.
* <p/>
* It is based on {@link ReplayingDecoder} so that packets will only be returned
* when all needed data is present.
*/
@AllArgsConstructor
public class PacketDecoder extends ReplayingDecoder<Void>
{
@Getter
@Setter
private Protocol protocol;
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception
{
// While we have enough data
while ( true )
{
// Store our start index
int startIndex = in.readerIndex();
// Run packet through framer
DefinedPacket packet = protocol.read( in.readUnsignedByte(), in );
// If we got this far, it means we have formed a packet, so lets grab the end index
int endIndex = in.readerIndex();
// Allocate a buffer big enough for all bytes we have read
ByteBuf buf = in.copy( startIndex, endIndex - startIndex );
// Checkpoint our state incase we don't have enough data for another packet
checkpoint();
// Store our decoded message
out.add( new PacketWrapper( packet, buf ) );
}
}
}

View File

@ -1,5 +1,7 @@
package net.md_5.bungee.netty; package net.md_5.bungee.netty;
import net.md_5.bungee.protocol.PacketWrapper;
public abstract class PacketHandler extends net.md_5.bungee.protocol.AbstractPacketHandler public abstract class PacketHandler extends net.md_5.bungee.protocol.AbstractPacketHandler
{ {

View File

@ -4,6 +4,7 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelException; import io.netty.channel.ChannelException;
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOption;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.util.AttributeKey; import io.netty.util.AttributeKey;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@ -15,7 +16,8 @@ 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;
import net.md_5.bungee.api.config.ListenerInfo; import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.protocol.Vanilla; import net.md_5.bungee.protocol.MinecraftCodec;
import net.md_5.bungee.protocol.Protocol;
public class PipelineUtils public class PipelineUtils
{ {
@ -49,13 +51,15 @@ public class PipelineUtils
} }
}; };
public static final Base BASE = new Base(); public static final Base BASE = new Base();
private static final DefinedPacketEncoder packetEncoder = new DefinedPacketEncoder(); private static final ProtobufVarint32FrameDecoder frameDecoder = new ProtobufVarint32FrameDecoder();
private static final ProtobufVarint32FrameDecoder framePrepender = new ProtobufVarint32FrameDecoder();
public static String TIMEOUT_HANDLER = "timeout"; public static String TIMEOUT_HANDLER = "timeout";
public static String PACKET_DECODE_HANDLER = "packet-decoder"; public static String PACKET_CODEC = "packet-codec";
public static String PACKET_ENCODE_HANDLER = "packet-encoder";
public static String BOSS_HANDLER = "inbound-boss"; public static String BOSS_HANDLER = "inbound-boss";
public static String ENCRYPT_HANDLER = "encrypt"; public static String ENCRYPT_HANDLER = "encrypt";
public static String DECRYPT_HANDLER = "decrypt"; public static String DECRYPT_HANDLER = "decrypt";
public static String FRAME_DECODER = "frame-decoder";
public static String FRAME_PREPENDER = "frame-prepender";
public final static class Base extends ChannelInitializer<Channel> public final static class Base extends ChannelInitializer<Channel>
{ {
@ -72,8 +76,9 @@ public class PipelineUtils
} }
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( PACKET_DECODE_HANDLER, new PacketDecoder( Vanilla.getInstance() ) ); ch.pipeline().addLast( FRAME_DECODER, frameDecoder );
ch.pipeline().addLast( PACKET_ENCODE_HANDLER, packetEncoder ); ch.pipeline().addLast( PACKET_CODEC, new MinecraftCodec( Protocol.SERVER_HANDSHAKE ) );
ch.pipeline().addLast( FRAME_PREPENDER, framePrepender );
ch.pipeline().addLast( BOSS_HANDLER, new HandlerBoss() ); ch.pipeline().addLast( BOSS_HANDLER, new HandlerBoss() );
} }
}; };