From 0077af58d0467e66cb17a101735b5cee196f70b8 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 7 Mar 2013 18:17:49 +1100 Subject: [PATCH 01/31] Start work on netty overhaul --- config/pom.xml | 14 +++ .../net/md_5/bungee/config/Configuration.java | 14 ++- .../bungee/config/ConfigurationProvider.java | 29 +++++ .../md_5/bungee/config/YamlConfiguration.java | 53 +++++++++ protocol/pom.xml | 8 ++ .../protocol}/PacketDefinitions.java | 12 +-- .../protocol/netty}/BulkChunk.java | 8 +- .../protocol/netty}/ByteHeader.java | 8 +- .../protocol/netty}/Instruction.java | 10 +- .../protocol/netty}/IntHeader.java | 8 +- .../net/md_5/bungee/protocol/netty/Item.java | 19 ++++ .../protocol/netty}/Jump.java | 8 +- .../protocol/netty}/MetaData.java | 20 ++-- .../bungee/protocol/netty/OptionalMotion.java | 18 ++++ .../protocol/netty/PacketReader.java} | 22 ++-- .../protocol/netty}/ShortHeader.java | 8 +- .../protocol/netty/UnsignedShortByte.java | 15 +++ .../java/net/md_5/mendax/datainput/Item.java | 19 ---- .../md_5/mendax/datainput/OptionalMotion.java | 18 ---- .../mendax/datainput/UnsignedShortByte.java | 15 --- proxy/pom.xml | 5 + .../main/java/net/md_5/bungee/BungeeCord.java | 67 ++++++------ .../net/md_5/bungee/BungeeServerInfo.java | 2 +- .../main/java/net/md_5/bungee/EntityMap.java | 33 ++---- .../java/net/md_5/bungee/InitialHandler.java | 2 +- .../java/net/md_5/bungee/ListenThread.java | 48 --------- .../java/net/md_5/bungee/ServerConnector.java | 91 +++++++--------- proxy/src/main/java/net/md_5/bungee/Util.java | 12 --- .../bungee/netty/ChannelBootstrapper.java | 49 +++++++++ .../net/md_5/bungee/netty/CipherCodec.java | 76 +++++++++++++ .../net/md_5/bungee/netty/HandlerBoss.java | 45 ++++++++ .../net/md_5/bungee/netty/PacketDecoder.java | 25 +++++ .../net/md_5/bungee/packet/DefinedPacket.java | 7 +- .../net/md_5/bungee/packet/PacketHandler.java | 16 ++- .../net/md_5/bungee/packet/PacketStream.java | 101 ------------------ 35 files changed, 519 insertions(+), 386 deletions(-) create mode 100644 config/src/main/java/net/md_5/bungee/config/ConfigurationProvider.java create mode 100644 config/src/main/java/net/md_5/bungee/config/YamlConfiguration.java rename protocol/src/main/java/net/md_5/{mendax => bungee/protocol}/PacketDefinitions.java (95%) rename protocol/src/main/java/net/md_5/{mendax/datainput => bungee/protocol/netty}/BulkChunk.java (54%) rename protocol/src/main/java/net/md_5/{mendax/datainput => bungee/protocol/netty}/ByteHeader.java (65%) rename protocol/src/main/java/net/md_5/{mendax/datainput => bungee/protocol/netty}/Instruction.java (82%) rename protocol/src/main/java/net/md_5/{mendax/datainput => bungee/protocol/netty}/IntHeader.java (65%) create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/netty/Item.java rename protocol/src/main/java/net/md_5/{mendax/datainput => bungee/protocol/netty}/Jump.java (62%) rename protocol/src/main/java/net/md_5/{mendax/datainput => bungee/protocol/netty}/MetaData.java (63%) create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/netty/OptionalMotion.java rename protocol/src/main/java/net/md_5/{mendax/datainput/DataInputPacketReader.java => bungee/protocol/netty/PacketReader.java} (80%) rename protocol/src/main/java/net/md_5/{mendax/datainput => bungee/protocol/netty}/ShortHeader.java (66%) create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/netty/UnsignedShortByte.java delete mode 100644 protocol/src/main/java/net/md_5/mendax/datainput/Item.java delete mode 100644 protocol/src/main/java/net/md_5/mendax/datainput/OptionalMotion.java delete mode 100644 protocol/src/main/java/net/md_5/mendax/datainput/UnsignedShortByte.java delete mode 100644 proxy/src/main/java/net/md_5/bungee/ListenThread.java create mode 100644 proxy/src/main/java/net/md_5/bungee/netty/ChannelBootstrapper.java create mode 100644 proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java create mode 100644 proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java create mode 100644 proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java delete mode 100644 proxy/src/main/java/net/md_5/bungee/packet/PacketStream.java diff --git a/config/pom.xml b/config/pom.xml index 9df70007..ad8761be 100644 --- a/config/pom.xml +++ b/config/pom.xml @@ -17,4 +17,18 @@ BungeeCord-Config Generic java configuration API intended for use with BungeeCord + + + + junit + junit + 4.11 + test + + + org.yaml + snakeyaml + 1.11 + + diff --git a/config/src/main/java/net/md_5/bungee/config/Configuration.java b/config/src/main/java/net/md_5/bungee/config/Configuration.java index f9d32c82..43af0fff 100644 --- a/config/src/main/java/net/md_5/bungee/config/Configuration.java +++ b/config/src/main/java/net/md_5/bungee/config/Configuration.java @@ -2,6 +2,7 @@ package net.md_5.bungee.config; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import lombok.AccessLevel; @@ -13,8 +14,8 @@ public final class Configuration private static final char SEPARATOR = '.'; private final Map self; - private final Map comments; - private final Map defaults; + private Map comments = new HashMap<>(); + private final Configuration defaults; private Map getHolder(String path, Map parent, boolean create) { @@ -41,12 +42,17 @@ public final class Configuration public T get(String path, T def) { Object val = get( path, self ); - return ( val != null && val.getClass().isInstance( def ) ) ? (T) val : (T) get( path, defaults ); + return ( val != null && val.getClass().isInstance( def ) ) ? (T) val : (T) defaults.get( path ); + } + + public Object get(String path) + { + return get( path, null ); } public Object getDefault(String path) { - return get( path, defaults ); + return defaults.get( path ); } public void set(String path, Object value, String comment) diff --git a/config/src/main/java/net/md_5/bungee/config/ConfigurationProvider.java b/config/src/main/java/net/md_5/bungee/config/ConfigurationProvider.java new file mode 100644 index 00000000..7d1b5327 --- /dev/null +++ b/config/src/main/java/net/md_5/bungee/config/ConfigurationProvider.java @@ -0,0 +1,29 @@ +package net.md_5.bungee.config; + +import java.io.File; +import java.io.Reader; +import java.util.HashMap; +import java.util.Map; + +public abstract class ConfigurationProvider +{ + + private static final Map, ConfigurationProvider> providers = new HashMap<>(); + + static + { + providers.put( YamlConfiguration.class, new YamlConfiguration() ); + } + + public ConfigurationProvider getProvider(Class provider) + { + return providers.get( provider ); + } + /*------------------------------------------------------------------------*/ + + public abstract Configuration load(File file); + + public abstract Configuration load(Reader reader); + + public abstract Configuration load(String string); +} diff --git a/config/src/main/java/net/md_5/bungee/config/YamlConfiguration.java b/config/src/main/java/net/md_5/bungee/config/YamlConfiguration.java new file mode 100644 index 00000000..74d84ab8 --- /dev/null +++ b/config/src/main/java/net/md_5/bungee/config/YamlConfiguration.java @@ -0,0 +1,53 @@ +package net.md_5.bungee.config; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.util.Map; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; + +public class YamlConfiguration extends ConfigurationProvider +{ + + private final ThreadLocal yaml = new ThreadLocal() + { + @Override + protected Yaml initialValue() + { + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK ); + return new Yaml( options ); + } + }; + + @Override + public Configuration load(File file) + { + try ( FileReader reader = new FileReader( file ) ) + { + return load( reader ); + } catch ( IOException ex ) + { + return null; + } + } + + @Override + @SuppressWarnings("unchecked") + public Configuration load(Reader reader) + { + Configuration conf = new Configuration( (Map) yaml.get().loadAs( reader, Map.class ), null ); + return conf; + } + + @Override + @SuppressWarnings("unchecked") + public Configuration load(String string) + { + Configuration conf = new Configuration( (Map) yaml.get().loadAs( string, Map.class ), null ); + return conf; + } +} diff --git a/protocol/pom.xml b/protocol/pom.xml index c87c8171..a347f5cc 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -17,4 +17,12 @@ BungeeCord-Protocol Minimal implementation of the Minecraft protocol for use in BungeeCord + + + + io.netty + netty-buffer + 4.0.0.Beta2 + + diff --git a/protocol/src/main/java/net/md_5/mendax/PacketDefinitions.java b/protocol/src/main/java/net/md_5/bungee/protocol/PacketDefinitions.java similarity index 95% rename from protocol/src/main/java/net/md_5/mendax/PacketDefinitions.java rename to protocol/src/main/java/net/md_5/bungee/protocol/PacketDefinitions.java index 4fdd1be6..bbe4243a 100644 --- a/protocol/src/main/java/net/md_5/mendax/PacketDefinitions.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/PacketDefinitions.java @@ -1,14 +1,13 @@ -package net.md_5.mendax; +package net.md_5.bungee.protocol; -import static net.md_5.mendax.PacketDefinitions.OpCode.*; +import static net.md_5.bungee.protocol.PacketDefinitions.OpCode.*; public class PacketDefinitions { - private static final int MAX_PACKET = 256; - public static final OpCode[][] opCodes = new OpCode[ MAX_PACKET * 2 ][]; + public static final OpCode[][] opCodes = new OpCode[ 512 ][]; public static final int VANILLA_PROTOCOL = 0; - public static final int FORGE_PROTOCOL = MAX_PACKET; + public static final int FORGE_PROTOCOL = 256; public enum OpCode { @@ -312,7 +311,8 @@ public class PacketDefinitions }; opCodes[0xFE] = new OpCode[] { - }; // Should be byte, screw you too bitchy server admins! + BYTE + }; opCodes[0xFF] = new OpCode[] { STRING diff --git a/protocol/src/main/java/net/md_5/mendax/datainput/BulkChunk.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/BulkChunk.java similarity index 54% rename from protocol/src/main/java/net/md_5/mendax/datainput/BulkChunk.java rename to protocol/src/main/java/net/md_5/bungee/protocol/netty/BulkChunk.java index 5f1b31b0..37499018 100644 --- a/protocol/src/main/java/net/md_5/mendax/datainput/BulkChunk.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/BulkChunk.java @@ -1,17 +1,17 @@ -package net.md_5.mendax.datainput; +package net.md_5.bungee.protocol.netty; -import java.io.DataInput; +import io.netty.buffer.ByteBuf; import java.io.IOException; public class BulkChunk extends Instruction { @Override - void read(DataInput in, byte[] buffer) throws IOException + void read(ByteBuf in) throws IOException { short count = in.readShort(); int size = in.readInt(); in.readBoolean(); - skip( in, buffer, size + count * 12 ); + skip( in, size + count * 12 ); } } diff --git a/protocol/src/main/java/net/md_5/mendax/datainput/ByteHeader.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/ByteHeader.java similarity index 65% rename from protocol/src/main/java/net/md_5/mendax/datainput/ByteHeader.java rename to protocol/src/main/java/net/md_5/bungee/protocol/netty/ByteHeader.java index a4bc11da..24fd1ac4 100644 --- a/protocol/src/main/java/net/md_5/mendax/datainput/ByteHeader.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/ByteHeader.java @@ -1,6 +1,6 @@ -package net.md_5.mendax.datainput; +package net.md_5.bungee.protocol.netty; -import java.io.DataInput; +import io.netty.buffer.ByteBuf; import java.io.IOException; class ByteHeader extends Instruction @@ -14,12 +14,12 @@ class ByteHeader extends Instruction } @Override - void read(DataInput in, byte[] buffer) throws IOException + void read(ByteBuf in) throws IOException { byte size = in.readByte(); for ( byte b = 0; b < size; b++ ) { - child.read( in, buffer ); + child.read( in ); } } } diff --git a/protocol/src/main/java/net/md_5/mendax/datainput/Instruction.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/Instruction.java similarity index 82% rename from protocol/src/main/java/net/md_5/mendax/datainput/Instruction.java rename to protocol/src/main/java/net/md_5/bungee/protocol/netty/Instruction.java index d246558a..6b84dc59 100644 --- a/protocol/src/main/java/net/md_5/mendax/datainput/Instruction.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/Instruction.java @@ -1,6 +1,6 @@ -package net.md_5.mendax.datainput; +package net.md_5.bungee.protocol.netty; -import java.io.DataInput; +import io.netty.buffer.ByteBuf; import java.io.IOException; abstract class Instruction @@ -27,10 +27,10 @@ abstract class Instruction // Illegal forward references below this line static final Instruction BYTE_INT = new ByteHeader( INT ); - abstract void read(DataInput in, byte[] buffer) throws IOException; + abstract void read(ByteBuf in) throws IOException; - final void skip(DataInput in, byte[] buffer, int len) throws IOException + final void skip(ByteBuf in, int len) throws IOException { - in.readFully( buffer, 0, len ); + in.readerIndex( in.readerIndex() + len ); } } diff --git a/protocol/src/main/java/net/md_5/mendax/datainput/IntHeader.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/IntHeader.java similarity index 65% rename from protocol/src/main/java/net/md_5/mendax/datainput/IntHeader.java rename to protocol/src/main/java/net/md_5/bungee/protocol/netty/IntHeader.java index 31a5c18d..2f1a011b 100644 --- a/protocol/src/main/java/net/md_5/mendax/datainput/IntHeader.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/IntHeader.java @@ -1,6 +1,6 @@ -package net.md_5.mendax.datainput; +package net.md_5.bungee.protocol.netty; -import java.io.DataInput; +import io.netty.buffer.ByteBuf; import java.io.IOException; class IntHeader extends Instruction @@ -14,12 +14,12 @@ class IntHeader extends Instruction } @Override - void read(DataInput in, byte[] buffer) throws IOException + void read(ByteBuf in) throws IOException { int size = in.readInt(); for ( int i = 0; i < size; i++ ) { - child.read( in, buffer ); + child.read( in ); } } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/netty/Item.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/Item.java new file mode 100644 index 00000000..5026b521 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/Item.java @@ -0,0 +1,19 @@ +package net.md_5.bungee.protocol.netty; + +import io.netty.buffer.ByteBuf; +import java.io.IOException; + +class Item extends Instruction +{ + + @Override + void read(ByteBuf in) throws IOException + { + short type = in.readShort(); + if ( type >= 0 ) + { + skip( in, 3 ); + SHORT_BYTE.read( in ); + } + } +} diff --git a/protocol/src/main/java/net/md_5/mendax/datainput/Jump.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/Jump.java similarity index 62% rename from protocol/src/main/java/net/md_5/mendax/datainput/Jump.java rename to protocol/src/main/java/net/md_5/bungee/protocol/netty/Jump.java index 5bf82fc7..0c9ed2a4 100644 --- a/protocol/src/main/java/net/md_5/mendax/datainput/Jump.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/Jump.java @@ -1,6 +1,6 @@ -package net.md_5.mendax.datainput; +package net.md_5.bungee.protocol.netty; -import java.io.DataInput; +import io.netty.buffer.ByteBuf; import java.io.IOException; class Jump extends Instruction @@ -18,8 +18,8 @@ class Jump extends Instruction } @Override - void read(DataInput in, byte[] buffer) throws IOException + void read(ByteBuf in) throws IOException { - skip( in, buffer, len ); + skip( in, len ); } } diff --git a/protocol/src/main/java/net/md_5/mendax/datainput/MetaData.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/MetaData.java similarity index 63% rename from protocol/src/main/java/net/md_5/mendax/datainput/MetaData.java rename to protocol/src/main/java/net/md_5/bungee/protocol/netty/MetaData.java index 6dc04584..7ebc3c16 100644 --- a/protocol/src/main/java/net/md_5/mendax/datainput/MetaData.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/MetaData.java @@ -1,13 +1,13 @@ -package net.md_5.mendax.datainput; +package net.md_5.bungee.protocol.netty; -import java.io.DataInput; +import io.netty.buffer.ByteBuf; import java.io.IOException; class MetaData extends Instruction { @Override - void read(DataInput in, byte[] buffer) throws IOException + void read(ByteBuf in) throws IOException { int x = in.readUnsignedByte(); while ( x != 127 ) @@ -16,25 +16,25 @@ class MetaData extends Instruction switch ( type ) { case 0: - BYTE.read( in, buffer ); + BYTE.read( in ); break; case 1: - SHORT.read( in, buffer ); + SHORT.read( in ); break; case 2: - INT.read( in, buffer ); + INT.read( in ); break; case 3: - FLOAT.read( in, buffer ); + FLOAT.read( in ); break; case 4: - STRING.read( in, buffer ); + STRING.read( in ); break; case 5: - ITEM.read( in, buffer ); + ITEM.read( in ); break; case 6: - skip( in, buffer, 12 ); // int, int, int + skip( in, 12 ); // int, int, int break; default: throw new IllegalArgumentException( "Unknown metadata type " + type ); diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/netty/OptionalMotion.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/OptionalMotion.java new file mode 100644 index 00000000..7e304007 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/OptionalMotion.java @@ -0,0 +1,18 @@ +package net.md_5.bungee.protocol.netty; + +import io.netty.buffer.ByteBuf; +import java.io.IOException; + +class OptionalMotion extends Instruction +{ + + @Override + void read(ByteBuf in) throws IOException + { + int data = in.readInt(); + if ( data > 0 ) + { + skip( in, 6 ); + } + } +} diff --git a/protocol/src/main/java/net/md_5/mendax/datainput/DataInputPacketReader.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/PacketReader.java similarity index 80% rename from protocol/src/main/java/net/md_5/mendax/datainput/DataInputPacketReader.java rename to protocol/src/main/java/net/md_5/bungee/protocol/netty/PacketReader.java index c697b9a0..0adfb864 100644 --- a/protocol/src/main/java/net/md_5/mendax/datainput/DataInputPacketReader.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/PacketReader.java @@ -1,16 +1,16 @@ -package net.md_5.mendax.datainput; +package net.md_5.bungee.protocol.netty; -import java.io.DataInput; +import io.netty.buffer.ByteBuf; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import net.md_5.mendax.PacketDefinitions; -import net.md_5.mendax.PacketDefinitions.OpCode; +import net.md_5.bungee.protocol.PacketDefinitions; +import net.md_5.bungee.protocol.PacketDefinitions.OpCode; -public class DataInputPacketReader +public class PacketReader { - private static final Instruction[][] instructions = new Instruction[ 256 ][]; + private static final Instruction[][] instructions = new Instruction[ PacketDefinitions.opCodes.length ][]; static { @@ -59,7 +59,7 @@ public class DataInputPacketReader } } - private static void readPacket(int packetId, DataInput in, byte[] buffer, int protocol) throws IOException + private static void readPacket(int packetId, ByteBuf in, int protocol) throws IOException { Instruction[] packetDef = null; if ( packetId + protocol < instructions.length ) @@ -74,20 +74,20 @@ public class DataInputPacketReader throw new IOException( "Unknown packet id " + packetId ); } else { - readPacket( packetId, in, buffer, PacketDefinitions.VANILLA_PROTOCOL ); + readPacket( packetId, in, PacketDefinitions.VANILLA_PROTOCOL ); return; } } for ( Instruction instruction : packetDef ) { - instruction.read( in, buffer ); + instruction.read( in ); } } - public static void readPacket(DataInput in, byte[] buffer, int protocol) throws IOException + public static void readPacket(ByteBuf in, int protocol) throws IOException { int packetId = in.readUnsignedByte(); - readPacket( packetId, in, buffer, protocol ); + readPacket( packetId, in, protocol ); } } diff --git a/protocol/src/main/java/net/md_5/mendax/datainput/ShortHeader.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/ShortHeader.java similarity index 66% rename from protocol/src/main/java/net/md_5/mendax/datainput/ShortHeader.java rename to protocol/src/main/java/net/md_5/bungee/protocol/netty/ShortHeader.java index b274af61..ece0ae3c 100644 --- a/protocol/src/main/java/net/md_5/mendax/datainput/ShortHeader.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/ShortHeader.java @@ -1,6 +1,6 @@ -package net.md_5.mendax.datainput; +package net.md_5.bungee.protocol.netty; -import java.io.DataInput; +import io.netty.buffer.ByteBuf; import java.io.IOException; class ShortHeader extends Instruction @@ -14,12 +14,12 @@ class ShortHeader extends Instruction } @Override - void read(DataInput in, byte[] buffer) throws IOException + void read(ByteBuf in) throws IOException { short size = in.readShort(); for ( short s = 0; s < size; s++ ) { - child.read( in, buffer ); + child.read( in ); } } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/netty/UnsignedShortByte.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/UnsignedShortByte.java new file mode 100644 index 00000000..2b409884 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/UnsignedShortByte.java @@ -0,0 +1,15 @@ +package net.md_5.bungee.protocol.netty; + +import io.netty.buffer.ByteBuf; +import java.io.IOException; + +class UnsignedShortByte extends Instruction +{ + + @Override + void read(ByteBuf in) throws IOException + { + int size = in.readUnsignedShort(); + skip( in, size ); + } +} diff --git a/protocol/src/main/java/net/md_5/mendax/datainput/Item.java b/protocol/src/main/java/net/md_5/mendax/datainput/Item.java deleted file mode 100644 index 411c931b..00000000 --- a/protocol/src/main/java/net/md_5/mendax/datainput/Item.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.md_5.mendax.datainput; - -import java.io.DataInput; -import java.io.IOException; - -class Item extends Instruction -{ - - @Override - void read(DataInput in, byte[] buffer) throws IOException - { - short type = in.readShort(); - if ( type >= 0 ) - { - skip( in, buffer, 3 ); - SHORT_BYTE.read( in, buffer ); - } - } -} diff --git a/protocol/src/main/java/net/md_5/mendax/datainput/OptionalMotion.java b/protocol/src/main/java/net/md_5/mendax/datainput/OptionalMotion.java deleted file mode 100644 index 55c36f65..00000000 --- a/protocol/src/main/java/net/md_5/mendax/datainput/OptionalMotion.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.md_5.mendax.datainput; - -import java.io.DataInput; -import java.io.IOException; - -public class OptionalMotion extends Instruction -{ - - @Override - void read(DataInput in, byte[] buffer) throws IOException - { - int data = in.readInt(); - if ( data > 0 ) - { - skip( in, buffer, 6 ); - } - } -} diff --git a/protocol/src/main/java/net/md_5/mendax/datainput/UnsignedShortByte.java b/protocol/src/main/java/net/md_5/mendax/datainput/UnsignedShortByte.java deleted file mode 100644 index 4b1db5a2..00000000 --- a/protocol/src/main/java/net/md_5/mendax/datainput/UnsignedShortByte.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.md_5.mendax.datainput; - -import java.io.DataInput; -import java.io.IOException; - -public class UnsignedShortByte extends Instruction -{ - - @Override - void read(DataInput in, byte[] buffer) throws IOException - { - int size = in.readUnsignedShort(); - skip( in, buffer, size ); - } -} diff --git a/proxy/pom.xml b/proxy/pom.xml index 7163f7f9..210fde51 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -19,6 +19,11 @@ Proxy component of the Elastic Portal Suite + + io.netty + netty-all + 4.0.0.Beta2 + net.md-5 bungeecord-protocol 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 c9dd9ad0..4ffd581f 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -1,5 +1,15 @@ package net.md_5.bungee; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelException; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.MultithreadEventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.handler.timeout.ReadTimeoutHandler; import net.md_5.bungee.config.Configuration; import java.io.BufferedReader; import java.io.File; @@ -10,13 +20,10 @@ import java.net.Socket; import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; @@ -36,6 +43,9 @@ 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.HandlerBoss; +import net.md_5.bungee.netty.PacketDecoder; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.PacketFAPluginMessage; @@ -64,7 +74,7 @@ public class BungeeCord extends ProxyServer /** * Thread pool. */ - public final ExecutorService threadPool = Executors.newCachedThreadPool(); + public final MultithreadEventLoopGroup eventLoops = new NioEventLoopGroup( 8, new ThreadFactoryBuilder().setNameFormat( "Netty IO Thread - %1$d" ).build() ); /** * locations.yml save thread. */ @@ -72,7 +82,7 @@ public class BungeeCord extends ProxyServer /** * Server socket listener. */ - private Collection listeners = new HashSet<>(); + private Collection listeners = new HashSet<>(); /** * Fully qualified connections. */ @@ -149,6 +159,7 @@ public class BungeeCord extends ProxyServer * * @throws IOException */ + @Override public void start() throws IOException { File plugins = new File( "plugins" ); @@ -181,30 +192,26 @@ public class BungeeCord extends ProxyServer { for ( ListenerInfo info : config.getListeners() ) { - try - { - ListenThread listener = new ListenThread( info ); - listener.start(); - listeners.add( listener ); - $().info( "Listening on " + info.getHost() ); - } catch ( IOException ex ) - { - $().log( Level.SEVERE, "Could not start listener " + info, ex ); - } + Channel server = new ServerBootstrap() + .childHandler( ChannelBootstrapper.SERVER ) + .localAddress( info.getHost() ) + .group( eventLoops ) + .bind().channel(); + listeners.add( server ); + + $().info( "Listening on " + info.getHost() ); } } public void stopListeners() { - for ( ListenThread listener : listeners ) + for ( Channel listener : listeners ) { - $().log( Level.INFO, "Closing listen thread {0}", listener.socket ); + $().log( Level.INFO, "Closing listener {0}", listener ); try { - listener.interrupt(); - listener.socket.close(); - listener.join(); - } catch ( InterruptedException | IOException ex ) + listener.close().syncUninterruptibly(); + } catch ( ChannelException ex ) { $().severe( "Could not close listen thread" ); } @@ -219,7 +226,6 @@ public class BungeeCord extends ProxyServer stopListeners(); $().info( "Closing pending connections" ); - threadPool.shutdown(); $().info( "Disconnecting " + connections.size() + " connections" ); for ( UserConnection user : connections.values() ) @@ -227,6 +233,9 @@ public class BungeeCord extends ProxyServer user.disconnect( "Proxy restarting, brb." ); } + $().info( "Closing IO threads" ); + eventLoops.shutdown(); + $().info( "Saving reconnect locations" ); reconnectHandler.save(); saveThread.cancel(); @@ -241,20 +250,6 @@ public class BungeeCord extends ProxyServer System.exit( 0 ); } - /** - * Miscellaneous method to set options on a socket based on those in the - * configuration. - * - * @param socket to set the options on - * @throws IOException when the underlying set methods thrown an exception - */ - public void setSocketOptions(Socket socket) throws IOException - { - socket.setSoTimeout( config.getTimeout() ); - socket.setTrafficClass( 0x18 ); - socket.setTcpNoDelay( true ); - } - /** * Broadcasts a packet to all clients that is connected to this instance. * 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 a17e08f7..efe6d0c2 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java @@ -15,7 +15,7 @@ import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.PacketFAPluginMessage; import net.md_5.bungee.packet.PacketFFKick; import net.md_5.bungee.packet.PacketStream; -import net.md_5.mendax.PacketDefinitions; +import net.md_5.bungee.protocol.PacketDefinitions; public class BungeeServerInfo extends ServerInfo { diff --git a/proxy/src/main/java/net/md_5/bungee/EntityMap.java b/proxy/src/main/java/net/md_5/bungee/EntityMap.java index ce9ad4cb..5a7a4b36 100644 --- a/proxy/src/main/java/net/md_5/bungee/EntityMap.java +++ b/proxy/src/main/java/net/md_5/bungee/EntityMap.java @@ -1,5 +1,7 @@ package net.md_5.bungee; +import io.netty.buffer.ByteBuf; + /** * Class to rewrite integers within packets. */ @@ -113,20 +115,20 @@ public class EntityMap }; } - public static void rewrite(byte[] packet, int oldId, int newId) + public static void rewrite(ByteBuf packet, int oldId, int newId) { - int packetId = Util.getId( packet ); + int packetId = packet.getUnsignedShort( 0 ); if ( packetId == 0x1D ) { // bulk entity - for ( int pos = 2; pos < packet.length; pos += 4 ) + for ( int pos = 2; pos < packet.writerIndex(); pos += 4 ) { - int readId = readInt( packet, pos ); + int readId = packet.getInt( pos ); if ( readId == oldId ) { - setInt( packet, pos, newId ); + packet.setInt( pos, newId ); } else if ( readId == newId ) { - setInt( packet, pos, oldId ); + packet.setInt( pos, oldId ); } } } else @@ -136,29 +138,16 @@ public class EntityMap { for ( int pos : idArray ) { - int readId = readInt( packet, pos ); + int readId = packet.getInt( pos ); if ( readId == oldId ) { - setInt( packet, pos, newId ); + packet.setInt( pos, newId ); } else if ( readId == newId ) { - setInt( packet, pos, oldId ); + packet.setInt( pos, oldId ); } } } } } - - private static void setInt(byte[] buf, int pos, int i) - { - buf[pos] = (byte) ( i >> 24 ); - buf[pos + 1] = (byte) ( i >> 16 ); - buf[pos + 2] = (byte) ( i >> 8 ); - buf[pos + 3] = (byte) i; - } - - private static int readInt(byte[] buf, int pos) - { - return ( ( ( buf[pos] & 0xFF ) << 24 ) | ( ( buf[pos + 1] & 0xFF ) << 16 ) | ( ( buf[pos + 2] & 0xFF ) << 8 ) | buf[pos + 3] & 0xFF ); - } } diff --git a/proxy/src/main/java/net/md_5/bungee/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/InitialHandler.java index ab57c741..9238998f 100644 --- a/proxy/src/main/java/net/md_5/bungee/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/InitialHandler.java @@ -32,7 +32,7 @@ import net.md_5.bungee.packet.PacketFEPing; import net.md_5.bungee.packet.PacketFFKick; import net.md_5.bungee.packet.PacketHandler; import net.md_5.bungee.packet.PacketStream; -import net.md_5.mendax.PacketDefinitions; +import net.md_5.bungee.protocol.PacketDefinitions; public class InitialHandler extends PacketHandler implements Runnable, PendingConnection { diff --git a/proxy/src/main/java/net/md_5/bungee/ListenThread.java b/proxy/src/main/java/net/md_5/bungee/ListenThread.java deleted file mode 100644 index d0e52973..00000000 --- a/proxy/src/main/java/net/md_5/bungee/ListenThread.java +++ /dev/null @@ -1,48 +0,0 @@ -package net.md_5.bungee; - -import java.io.IOException; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import static net.md_5.bungee.Logger.$; -import net.md_5.bungee.api.config.ListenerInfo; - -/** - * Thread to listen and dispatch incoming connections to the proxy. - */ -public class ListenThread extends Thread -{ - - public final ServerSocket socket; - private final ListenerInfo info; - - public ListenThread(ListenerInfo info) throws IOException - { - super( "Listen Thread - " + info ); - this.info = info; - socket = new ServerSocket(); - socket.bind( info.getHost() ); - } - - @Override - public void run() - { - while ( !isInterrupted() ) - { - try - { - Socket client = socket.accept(); - BungeeCord.getInstance().setSocketOptions( client ); - $().info( client.getInetAddress() + " has connected" ); - InitialHandler handler = new InitialHandler( client, info ); - BungeeCord.getInstance().threadPool.submit( handler ); - } catch ( SocketException ex ) - { - ex.printStackTrace(); // Now people can see why their operating system is failing them and stop bitching at me! - } catch ( IOException ex ) - { - ex.printStackTrace(); // TODO - } - } - } -} 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 b080164e..6b5ebe38 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -1,13 +1,16 @@ package net.md_5.bungee; import com.google.common.base.Preconditions; -import java.io.IOException; -import java.net.Socket; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.socket.nio.NioSocketChannel; import java.util.Queue; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.event.ServerConnectedEvent; +import net.md_5.bungee.netty.ChannelBootstrapper; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.Packet1Login; import net.md_5.bungee.packet.PacketCDClientStatus; @@ -39,6 +42,18 @@ public class ServerConnector extends PacketHandler { Preconditions.checkState( thisState == State.LOGIN, "Not exepcting LOGIN" ); loginPacket = login; + + ServerConnection server = new ServerConnection( socket, info, stream, connector.loginPacket ); + ServerConnectedEvent event = new ServerConnectedEvent( user, server ); + ProxyServer.getInstance().getPluginManager().callEvent( event ); + + stream.write( BungeeCord.getInstance().registerChannels() ); + + Queue packetQueue = ( (BungeeServerInfo) info ).getPacketQueue(); + while ( !packetQueue.isEmpty() ) + { + stream.write( packetQueue.poll() ); + } thisState = State.FINISHED; } @@ -55,63 +70,33 @@ public class ServerConnector extends PacketHandler throw new KickException( kick.message ); } - public static ServerConnection connect(UserConnection user, ServerInfo info, boolean retry) + public static void connect(final UserConnection user, final ServerInfo info, final boolean retry) { - Socket socket = null; - try + new Bootstrap() + .channel( NioSocketChannel.class ) + .group( BungeeCord.getInstance().eventLoops ) + .handler( ChannelBootstrapper.CLIENT ) + .remoteAddress( info.getAddress() ) + .connect().addListener( new ChannelFutureListener() { - socket = new Socket(); - socket.connect( info.getAddress(), BungeeCord.getInstance().config.getTimeout() ); - BungeeCord.getInstance().setSocketOptions( socket ); - PacketStream stream = new PacketStream( socket.getInputStream(), socket.getOutputStream(), user.stream.getProtocol() ); - - ServerConnector connector = new ServerConnector( stream ); - stream.write( user.handshake ); - stream.write( PacketCDClientStatus.CLIENT_LOGIN ); - - while ( connector.thisState != State.FINISHED ) + @Override + public void operationComplete(ChannelFuture future) throws Exception { - byte[] buf = stream.readPacket(); - DefinedPacket packet = DefinedPacket.packet( buf ); - packet.handle( connector ); - } - - ServerConnection server = new ServerConnection( socket, info, stream, connector.loginPacket ); - ServerConnectedEvent event = new ServerConnectedEvent( user, server ); - ProxyServer.getInstance().getPluginManager().callEvent( event ); - - stream.write( BungeeCord.getInstance().registerChannels() ); - - Queue packetQueue = ( (BungeeServerInfo) info ).getPacketQueue(); - while ( !packetQueue.isEmpty() ) - { - stream.write( packetQueue.poll() ); - } - return server; - } catch ( Exception ex ) - { - if ( socket != null ) - { - try + if ( future.isSuccess() ) { - socket.close(); - } catch ( IOException ioe ) + future.channel().write( user.handshake ); + future.channel().write( PacketCDClientStatus.CLIENT_LOGIN ); + } else { + future.channel().close(); + ServerInfo def = ProxyServer.getInstance().getServers().get( user.getPendingConnection().getListener().getDefaultServer() ); + if ( retry && !info.equals( def ) ) + { + user.sendMessage( ChatColor.RED + "Could not connect to target server, you have been moved to the default server" ); + connect( user, def, false ); + } } } - ServerInfo def = ProxyServer.getInstance().getServers().get( user.getPendingConnection().getListener().getDefaultServer() ); - if ( retry && !info.equals( def ) ) - { - user.sendMessage( ChatColor.RED + "Could not connect to target server, you have been moved to the default server" ); - return connect( user, def, false ); - } else - { - if ( ex instanceof RuntimeException ) - { - throw (RuntimeException) ex; - } - throw new RuntimeException( "Could not connect to target server " + Util.exception( ex ) ); - } - } + } ).channel(); } } diff --git a/proxy/src/main/java/net/md_5/bungee/Util.java b/proxy/src/main/java/net/md_5/bungee/Util.java index a96755bb..605cbe22 100644 --- a/proxy/src/main/java/net/md_5/bungee/Util.java +++ b/proxy/src/main/java/net/md_5/bungee/Util.java @@ -27,18 +27,6 @@ public class Util return new InetSocketAddress( split[0], port ); } - /** - * Gets the value of the first unsigned byte of the specified array. Useful - * for getting the id of a packet array . - * - * @param b the array to read from - * @return the unsigned value of the first byte - */ - public static int getId(byte[] b) - { - return b[0] & 0xFF; - } - /** * Normalizes a config path by prefix upper case letters with '_' and * turning them to lowercase. 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 new file mode 100644 index 00000000..928ec25d --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/netty/ChannelBootstrapper.java @@ -0,0 +1,49 @@ +package net.md_5.bungee.netty; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelException; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.handler.timeout.ReadTimeoutHandler; +import java.lang.reflect.Constructor; +import java.util.concurrent.TimeUnit; +import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.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; + + 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/CipherCodec.java b/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java new file mode 100644 index 00000000..b569e406 --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java @@ -0,0 +1,76 @@ +package net.md_5.bungee.netty; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToByteCodec; +import javax.crypto.Cipher; +import javax.crypto.ShortBufferException; + +/** + * This class is a complete solution for encrypting and decoding bytes in a + * Netty stream. It takes two {@link BufferedBlockCipher} instances, used for + * encryption and decryption respectively. + */ +public class CipherCodec extends ByteToByteCodec +{ + + private Cipher encrypt; + private Cipher decrypt; + private ByteBuf heapOut; + + public CipherCodec(Cipher encrypt, Cipher decrypt) + { + this.encrypt = encrypt; + this.decrypt = decrypt; + } + + @Override + public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception + { + if ( heapOut == null ) + { + heapOut = ctx.alloc().heapBuffer(); + } + cipher( encrypt, in, heapOut ); + out.writeBytes( heapOut ); + heapOut.discardSomeReadBytes(); + } + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception + { + cipher( decrypt, in, out ); + } + + @Override + public void freeInboundBuffer(ChannelHandlerContext ctx) throws Exception + { + super.freeInboundBuffer( ctx ); + decrypt = null; + } + + @Override + public void freeOutboundBuffer(ChannelHandlerContext ctx) throws Exception + { + super.freeOutboundBuffer( ctx ); + if ( heapOut != null ) + { + heapOut.release(); + heapOut = null; + } + encrypt = null; + } + + private void cipher(Cipher cipher, ByteBuf in, ByteBuf out) throws ShortBufferException + { + int available = in.readableBytes(); + int outputSize = cipher.getOutputSize( available ); + if ( out.capacity() < outputSize ) + { + out.capacity( outputSize ); + } + int processed = cipher.update( in.array(), in.arrayOffset() + in.readerIndex(), available, out.array(), out.arrayOffset() + out.writerIndex() ); + in.readerIndex( in.readerIndex() + processed ); + out.writerIndex( out.writerIndex() + processed ); + } +} 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 new file mode 100644 index 00000000..38f37419 --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java @@ -0,0 +1,45 @@ +package net.md_5.bungee.netty; + +import com.google.common.base.Preconditions; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundMessageHandlerAdapter; +import net.md_5.bungee.packet.DefinedPacket; +import net.md_5.bungee.packet.PacketHandler; + +public class HandlerBoss extends ChannelInboundMessageHandlerAdapter +{ + + private PacketHandler handler; + + HandlerBoss(PacketHandler handler) + { + Preconditions.checkArgument( handler != null, "handler" ); + this.handler = handler; + } + + @Override + protected void messageReceived(ChannelHandlerContext ctx, ByteBuf msg) throws Exception + { + if ( ctx.channel().isActive() ) + { + DefinedPacket packet = DefinedPacket.packet( msg ); + if ( packet != null ) + { + handler.handle( packet ); + } else + { + handler.handle( msg ); + } + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception + { + if ( ctx.channel().isActive() ) + { + ctx.close(); + } + } +} diff --git a/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java b/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java new file mode 100644 index 00000000..5dffe828 --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java @@ -0,0 +1,25 @@ +package net.md_5.bungee.netty; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ReplayingDecoder; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import net.md_5.bungee.protocol.netty.PacketReader; + +@AllArgsConstructor +public class PacketDecoder extends ReplayingDecoder +{ + + @Getter + @Setter + private int protocol; + + @Override + protected ByteBuf decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception + { + PacketReader.readPacket( in, protocol ); + return in.copy(); + } +} diff --git a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java index d7c20cce..a3f53fca 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java @@ -3,6 +3,7 @@ package net.md_5.bungee.packet; import com.google.common.base.Preconditions; import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; +import io.netty.buffer.ByteBuf; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.DataOutput; @@ -196,9 +197,9 @@ public abstract class DefinedPacket implements DataOutput public abstract void handle(PacketHandler handler) throws Exception; private static Class[] classes = new Class[ 256 ]; - public static DefinedPacket packet(byte[] buf) + public static DefinedPacket packet(ByteBuf buf) { - int id = Util.getId( buf ); + int id = buf.getUnsignedShort( 0); Class clazz = classes[id]; DefinedPacket ret = null; if ( clazz != null ) @@ -213,6 +214,8 @@ public abstract class DefinedPacket implements DataOutput } catch ( IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException ex ) { } + } else { + return null; } Preconditions.checkState( ret != null, "Don't know how to deal with packet ID %s", Util.hex( id ) ); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java index 04184256..7826d0af 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java @@ -1,11 +1,23 @@ package net.md_5.bungee.packet; +import io.netty.buffer.ByteBuf; + public abstract class PacketHandler { - private void nop(DefinedPacket packet) + private void nop(Object msg) { - throw new UnsupportedOperationException( "No handler defined for packet " + packet.getClass() ); + throw new UnsupportedOperationException( "No handler defined for packet " + msg.getClass() ); + } + + public void handle(ByteBuf buf) throws Exception + { + nop( buf ); + } + + public void handle(DefinedPacket packet) throws Exception + { + nop( packet ); } public void handle(Packet0KeepAlive alive) throws Exception diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketStream.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketStream.java deleted file mode 100644 index 01413568..00000000 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketStream.java +++ /dev/null @@ -1,101 +0,0 @@ -package net.md_5.bungee.packet; - -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import lombok.Getter; -import lombok.Setter; -import net.md_5.mendax.datainput.DataInputPacketReader; - -/** - * A specialized input stream to parse packets using the Mojang packet - * definitions and then return them as a byte array. - */ -public class PacketStream implements AutoCloseable -{ - - private final DataInputStream dataInput; - @Getter - private OutputStream out; - @Getter - @Setter - private int protocol; - private final TrackingInputStream tracker; - private final byte[] buffer = new byte[ 1 << 18 ]; - - public PacketStream(InputStream in, int protocol) - { - this( in, null, protocol ); - } - - public PacketStream(InputStream in, OutputStream out, int protocol) - { - tracker = new TrackingInputStream( in ); - dataInput = new DataInputStream( tracker ); - this.out = out; - this.protocol = protocol; - } - - public void write(byte[] b) throws IOException - { - out.write( b ); - } - - public void write(DefinedPacket packet) throws IOException - { - out.write( packet.getPacket() ); - } - - /** - * Read an entire packet from the stream and return it as a byte array. - * - * @return the read packet - * @throws IOException when the underlying input stream throws an exception - */ - public byte[] readPacket() throws IOException - { - tracker.out.reset(); - DataInputPacketReader.readPacket( dataInput, buffer, protocol ); - return tracker.out.toByteArray(); - } - - @Override - public void close() throws Exception - { - dataInput.close(); - } - - /** - * Input stream which will wrap another stream and copy all bytes read to a - * {@link ByteArrayOutputStream}. - */ - private class TrackingInputStream extends FilterInputStream - { - - private final ByteArrayOutputStream out = new ByteArrayOutputStream(); - - public TrackingInputStream(InputStream in) - { - super( in ); - } - - @Override - public int read() throws IOException - { - int ret = in.read(); - out.write( ret ); - return ret; - } - - @Override - public int read(byte[] b, int off, int len) throws IOException - { - int ret = in.read( b, off, len ); - out.write( b, off, ret ); - return ret; - } - } -} From 0afc52c130baa8da3dfa2111e7228032d88bf01a Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 7 Mar 2013 20:47:39 +1100 Subject: [PATCH 02/31] Upstream and downstream bridges are now uber sexy --- .../java/net/md_5/bungee/UserConnection.java | 305 +----------------- .../bungee/connection/CancelSendSignal.java | 17 + .../bungee/connection/DownstreamBridge.java | 188 +++++++++++ .../bungee/connection/UpstreamBridge.java | 64 ++++ 4 files changed, 274 insertions(+), 300 deletions(-) create mode 100644 proxy/src/main/java/net/md_5/bungee/connection/CancelSendSignal.java create mode 100644 proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java create mode 100644 proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java 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 2673fcfc..645e56ea 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -1,10 +1,5 @@ package net.md_5.bungee; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.util.Collection; @@ -16,15 +11,15 @@ import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import lombok.Getter; +import lombok.Setter; import lombok.Synchronized; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.PendingConnection; import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.event.ChatEvent; import net.md_5.bungee.api.event.PlayerDisconnectEvent; -import net.md_5.bungee.api.event.PluginMessageEvent; import net.md_5.bungee.api.event.ServerConnectEvent; +import net.md_5.bungee.connection.DownstreamBridge; import net.md_5.bungee.packet.*; public final class UserConnection extends GenericConnection implements ProxiedPlayer @@ -38,16 +33,15 @@ public final class UserConnection extends GenericConnection implements ProxiedPl private final PendingConnection pendingConnection; @Getter private ServerConnection server; - private UpstreamBridge upBridge; - private DownstreamBridge downBridge; // reconnect stuff private int clientEntityId; private int serverEntityId; private volatile boolean reconnecting; // ping stuff - private int trackingPingId; - private long pingTime; + public int trackingPingId; + public long pingTime; @Getter + @Setter private int ping = 1000; // Permissions private final Collection groups = new HashSet<>(); @@ -253,293 +247,4 @@ public final class UserConnection extends GenericConnection implements ProxiedPl { permissions.put( permission, value ); } - - private class UpstreamBridge extends Thread - { - - public UpstreamBridge() - { - super( "Upstream Bridge - " + name ); - } - - @Override - public void run() - { - while ( !socket.isClosed() ) - { - try - { - byte[] packet = stream.readPacket(); - boolean sendPacket = true; - int id = Util.getId( packet ); - - switch ( id ) - { - case 0x00: - if ( trackingPingId == new Packet0KeepAlive( packet ).id ) - { - int newPing = (int) ( System.currentTimeMillis() - pingTime ); - ProxyServer.getInstance().getTabListHandler().onPingChange( UserConnection.this, newPing ); - ping = newPing; - } - break; - case 0x03: - Packet3Chat chat = new Packet3Chat( packet ); - if ( chat.message.startsWith( "/" ) ) - { - sendPacket = !ProxyServer.getInstance().getPluginManager().dispatchCommand( UserConnection.this, chat.message.substring( 1 ) ); - } else - { - ChatEvent chatEvent = new ChatEvent( UserConnection.this, server, chat.message ); - ProxyServer.getInstance().getPluginManager().callEvent( chatEvent ); - sendPacket = !chatEvent.isCancelled(); - } - break; - case 0xFA: - // Call the onPluginMessage event - PacketFAPluginMessage message = new PacketFAPluginMessage( packet ); - - // Might matter in the future - if ( message.tag.equals( "BungeeCord" ) ) - { - continue; - } - - PluginMessageEvent event = new PluginMessageEvent( UserConnection.this, server, message.tag, message.data ); - ProxyServer.getInstance().getPluginManager().callEvent( event ); - - if ( event.isCancelled() ) - { - continue; - } - break; - } - - while ( !server.packetQueue.isEmpty() ) - { - DefinedPacket p = server.packetQueue.poll(); - if ( p != null ) - { - server.stream.write( p ); - } - } - - EntityMap.rewrite( packet, clientEntityId, serverEntityId ); - if ( sendPacket && !server.socket.isClosed() ) - { - server.stream.write( packet ); - } - - try - { - Thread.sleep( BungeeCord.getInstance().config.getSleepTime() ); - } catch ( InterruptedException ex ) - { - } - } catch ( IOException ex ) - { - disconnect( "Reached end of stream" ); - } catch ( Exception ex ) - { - disconnect( Util.exception( ex ) ); - } - } - } - } - - private class DownstreamBridge extends Thread - { - - public DownstreamBridge() - { - super( "Downstream Bridge - " + name ); - } - - @Override - public void run() - { - try - { - outer: - while ( !reconnecting ) - { - byte[] packet = server.stream.readPacket(); - int id = Util.getId( packet ); - - switch ( id ) - { - case 0x00: - trackingPingId = new Packet0KeepAlive( packet ).id; - pingTime = System.currentTimeMillis(); - break; - case 0x03: - Packet3Chat chat = new Packet3Chat( packet ); - ChatEvent chatEvent = new ChatEvent( server, UserConnection.this, chat.message ); - ProxyServer.getInstance().getPluginManager().callEvent( chatEvent ); - - if ( chatEvent.isCancelled() ) - { - continue; - } - break; - case 0xC9: - PacketC9PlayerListItem playerList = new PacketC9PlayerListItem( packet ); - if ( !ProxyServer.getInstance().getTabListHandler().onListUpdate( UserConnection.this, playerList.username, playerList.online, playerList.ping ) ) - { - continue; - } - break; - case 0xFA: - // Call the onPluginMessage event - PacketFAPluginMessage message = new PacketFAPluginMessage( packet ); - DataInputStream in = new DataInputStream( new ByteArrayInputStream( message.data ) ); - PluginMessageEvent event = new PluginMessageEvent( server, UserConnection.this, message.tag, message.data ); - ProxyServer.getInstance().getPluginManager().callEvent( event ); - - if ( event.isCancelled() ) - { - continue; - } - - if ( message.tag.equals( "BungeeCord" ) ) - { - String subChannel = in.readUTF(); - if ( subChannel.equals( "Forward" ) ) - { - String target = in.readUTF(); - String channel = in.readUTF(); - short len = in.readShort(); - byte[] data = new byte[ len ]; - in.readFully( data ); - - - ByteArrayOutputStream b = new ByteArrayOutputStream(); - DataOutputStream out = new DataOutputStream( b ); - out.writeUTF( channel ); - out.writeShort( data.length ); - out.write( data ); - - if ( target.equals( "ALL" ) ) - { - for ( ServerInfo server : BungeeCord.getInstance().getServers().values() ) - { - server.sendData( "BungeeCord", b.toByteArray() ); - } - } else - { - ServerInfo server = BungeeCord.getInstance().getServerInfo( target ); - if ( server != null ) - { - server.sendData( "BungeeCord", b.toByteArray() ); - } - } - } - if ( subChannel.equals( "Connect" ) ) - { - ServerInfo server = ProxyServer.getInstance().getServerInfo( in.readUTF() ); - if ( server != null ) - { - connect( server, true ); - break outer; - } - } - if ( subChannel.equals( "IP" ) ) - { - ByteArrayOutputStream b = new ByteArrayOutputStream(); - DataOutputStream out = new DataOutputStream( b ); - out.writeUTF( "IP" ); - out.writeUTF( getAddress().getHostString() ); - out.writeInt( getAddress().getPort() ); - getServer().sendData( "BungeeCord", b.toByteArray() ); - } - if ( subChannel.equals( "PlayerCount" ) ) - { - ServerInfo server = ProxyServer.getInstance().getServerInfo( in.readUTF() ); - if ( server != null ) - { - ByteArrayOutputStream b = new ByteArrayOutputStream(); - DataOutputStream out = new DataOutputStream( b ); - out.writeUTF( "PlayerCount" ); - out.writeUTF( server.getName() ); - out.writeInt( server.getPlayers().size() ); - getServer().sendData( "BungeeCord", b.toByteArray() ); - } - } - if ( subChannel.equals( "PlayerList" ) ) - { - ServerInfo server = ProxyServer.getInstance().getServerInfo( in.readUTF() ); - if ( server != null ) - { - ByteArrayOutputStream b = new ByteArrayOutputStream(); - DataOutputStream out = new DataOutputStream( b ); - out.writeUTF( "PlayerList" ); - out.writeUTF( server.getName() ); - - StringBuilder sb = new StringBuilder(); - for ( ProxiedPlayer p : server.getPlayers() ) - { - sb.append( p.getName() ); - sb.append( "," ); - } - out.writeUTF( sb.substring( 0, sb.length() - 1 ) ); - - getServer().sendData( "BungeeCord", b.toByteArray() ); - } - } - if ( subChannel.equals( "GetServers" ) ) - { - ByteArrayOutputStream b = new ByteArrayOutputStream(); - DataOutputStream out = new DataOutputStream( b ); - out.writeUTF( "GetServers" ); - - StringBuilder sb = new StringBuilder(); - for ( String server : ProxyServer.getInstance().getServers().keySet() ) - { - sb.append( server ); - sb.append( "," ); - } - out.writeUTF( sb.substring( 0, sb.length() - 1 ) ); - - getServer().sendData( "BungeeCord", b.toByteArray() ); - } - if ( subChannel.equals( "Message" ) ) - { - ProxiedPlayer target = ProxyServer.getInstance().getPlayer( in.readUTF() ); - if ( target != null ) - { - target.sendMessage( in.readUTF() ); - } - } - continue; - } - break; - case 0xFF: - disconnect( new PacketFFKick( packet ).message ); - break outer; - } - - while ( !packetQueue.isEmpty() ) - { - DefinedPacket p = packetQueue.poll(); - if ( p != null ) - { - stream.write( p ); - } - } - - EntityMap.rewrite( packet, serverEntityId, clientEntityId ); - stream.write( packet ); - - if ( nextServer != null ) - { - connect( nextServer, true ); - break outer; - } - } - } catch ( Exception ex ) - { - disconnect( Util.exception( ex ) ); - } - } - } } diff --git a/proxy/src/main/java/net/md_5/bungee/connection/CancelSendSignal.java b/proxy/src/main/java/net/md_5/bungee/connection/CancelSendSignal.java new file mode 100644 index 00000000..765b4bc8 --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/connection/CancelSendSignal.java @@ -0,0 +1,17 @@ +package net.md_5.bungee.connection; + +class CancelSendSignal extends Error +{ + + @Override + public synchronized Throwable initCause(Throwable cause) + { + return this; + } + + @Override + public synchronized Throwable fillInStackTrace() + { + return this; + } +} 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 new file mode 100644 index 00000000..695af1c6 --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java @@ -0,0 +1,188 @@ +package net.md_5.bungee.connection; + +import com.google.common.io.ByteArrayDataInput; +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; +import lombok.RequiredArgsConstructor; +import net.md_5.bungee.UserConnection; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.config.ServerInfo; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.event.ChatEvent; +import net.md_5.bungee.api.event.PluginMessageEvent; +import net.md_5.bungee.packet.Packet0KeepAlive; +import net.md_5.bungee.packet.Packet3Chat; +import net.md_5.bungee.packet.PacketC9PlayerListItem; +import net.md_5.bungee.packet.PacketFAPluginMessage; +import net.md_5.bungee.packet.PacketFFKick; +import net.md_5.bungee.packet.PacketHandler; + +@RequiredArgsConstructor +public class DownstreamBridge extends PacketHandler +{ + + private final ProxyServer bungee; + private final UserConnection con; + + @Override + public void handle(Packet0KeepAlive alive) throws Exception + { + con.trackingPingId = alive.id; + } + + @Override + public void handle(Packet3Chat chat) throws Exception + { + ChatEvent chatEvent = new ChatEvent( con.getServer(), con, chat.message ); + bungee.getPluginManager().callEvent( chatEvent ); + + if ( chatEvent.isCancelled() ) + { + throw new CancelSendSignal(); + } + } + + @Override + public void handle(PacketC9PlayerListItem playerList) throws Exception + { + + if ( !bungee.getTabListHandler().onListUpdate( con, playerList.username, playerList.online, playerList.ping ) ) + { + throw new CancelSendSignal(); + } + } + + @Override + public void handle(PacketFAPluginMessage pluginMessage) throws Exception + { + ByteArrayDataInput in = ByteStreams.newDataInput( pluginMessage.data ); + PluginMessageEvent event = new PluginMessageEvent( con.getServer(), con, pluginMessage.tag, pluginMessage.data.clone() ); + + if ( bungee.getPluginManager().callEvent( event ).isCancelled() ) + { + throw new CancelSendSignal(); + } + + if ( pluginMessage.tag.equals( "BungeeCord" ) ) + { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + String subChannel = in.readUTF(); + + if ( subChannel.equals( "Forward" ) ) + { + // Read data from server + String target = in.readUTF(); + String channel = in.readUTF(); + short len = in.readShort(); + byte[] data = new byte[ len ]; + in.readFully( data ); + + // Prepare new data to send + out.writeUTF( channel ); + out.writeShort( data.length ); + out.write( data ); + byte[] payload = out.toByteArray(); + + // Null out stream, important as we don't want to send to ourselves + out = null; + + if ( target.equals( "ALL" ) ) + { + for ( ServerInfo server : bungee.getServers().values() ) + { + if ( server != con.getServer().getInfo() ) + { + server.sendData( "BungeeCord", payload ); + } + } + } else + { + ServerInfo server = bungee.getServerInfo( target ); + if ( server != null ) + { + server.sendData( "BungeeCord", payload ); + } + } + } + if ( subChannel.equals( "Connect" ) ) + { + ServerInfo server = bungee.getServerInfo( in.readUTF() ); + if ( server != null ) + { + connect( server, true ); + break outer; + } + } + if ( subChannel.equals( "IP" ) ) + { + out.writeUTF( "IP" ); + out.writeUTF( con.getAddress().getHostString() ); + out.writeInt( con.getAddress().getPort() ); + } + if ( subChannel.equals( "PlayerCount" ) ) + { + ServerInfo server = bungee.getServerInfo( in.readUTF() ); + if ( server != null ) + { + out.writeUTF( "PlayerCount" ); + out.writeUTF( server.getName() ); + out.writeInt( server.getPlayers().size() ); + } + } + if ( subChannel.equals( "PlayerList" ) ) + { + ServerInfo server = bungee.getServerInfo( in.readUTF() ); + if ( server != null ) + { + out.writeUTF( "PlayerList" ); + out.writeUTF( server.getName() ); + + StringBuilder sb = new StringBuilder(); + for ( ProxiedPlayer p : server.getPlayers() ) + { + sb.append( p.getName() ); + sb.append( "," ); + } + out.writeUTF( sb.substring( 0, sb.length() - 1 ) ); + } + } + if ( subChannel.equals( "GetServers" ) ) + { + out.writeUTF( "GetServers" ); + + StringBuilder sb = new StringBuilder(); + for ( String server : bungee.getServers().keySet() ) + { + sb.append( server ); + sb.append( "," ); + } + out.writeUTF( sb.substring( 0, sb.length() - 1 ) ); + } + if ( subChannel.equals( "Message" ) ) + { + ProxiedPlayer target = bungee.getPlayer( in.readUTF() ); + if ( target != null ) + { + target.sendMessage( in.readUTF() ); + } + } + + // Check we haven't set out to null, and we have written data, if so reply back back along the BungeeCord channel + if ( out != null ) + { + byte[] b = out.toByteArray(); + if ( b.length != 0 ) + { + con.getServer().sendData( "BungeeCord", b ); + } + } + } + } + + @Override + public void handle(PacketFFKick kick) throws Exception + { + con.disconnect( "[Kicked] " + kick.message ); + throw new CancelSendSignal(); + } +} diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java new file mode 100644 index 00000000..e8c9eefc --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -0,0 +1,64 @@ +package net.md_5.bungee.connection; + +import lombok.RequiredArgsConstructor; +import net.md_5.bungee.UserConnection; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.event.ChatEvent; +import net.md_5.bungee.api.event.PluginMessageEvent; +import net.md_5.bungee.packet.Packet0KeepAlive; +import net.md_5.bungee.packet.Packet3Chat; +import net.md_5.bungee.packet.PacketFAPluginMessage; +import net.md_5.bungee.packet.PacketHandler; + +@RequiredArgsConstructor +public class UpstreamBridge extends PacketHandler +{ + + private final ProxyServer bungee; + private final UserConnection con; + + @Override + public void handle(Packet0KeepAlive alive) throws Exception + { + if ( alive.id == con.trackingPingId ) + { + int newPing = (int) ( System.currentTimeMillis() - con.pingTime ); + bungee.getTabListHandler().onPingChange( con, newPing ); + con.setPing( newPing ); + } + } + + @Override + public void handle(Packet3Chat chat) throws Exception + { + if ( chat.message.charAt( 0 ) == '/' ) + { + if ( bungee.getPluginManager().dispatchCommand( con, chat.message.substring( 1 ) ) ) + { + throw new CancelSendSignal(); + } + } else + { + ChatEvent chatEvent = new ChatEvent( con, con.getServer(), chat.message ); + if ( bungee.getPluginManager().callEvent( chatEvent ).isCancelled() ) + { + throw new CancelSendSignal(); + } + } + } + + @Override + public void handle(PacketFAPluginMessage pluginMessage) throws Exception + { + if ( pluginMessage.tag.equals( "BungeeCord" ) ) + { + throw new CancelSendSignal(); + } + + PluginMessageEvent event = new PluginMessageEvent( con, con.getServer(), pluginMessage.tag, pluginMessage.data.clone() ); + if ( bungee.getPluginManager().callEvent( event ).isCancelled() ) + { + throw new CancelSendSignal(); + } + } +} From 0f9cc766330b389f3e7baab2104ac1f845b77b79 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 7 Mar 2013 20:52:19 +1100 Subject: [PATCH 03/31] Update Server interface to remove depreceated methods --- .../md_5/bungee/api/connection/Server.java | 10 ------ .../net/md_5/bungee/ServerConnection.java | 35 +++++-------------- 2 files changed, 8 insertions(+), 37 deletions(-) diff --git a/api/src/main/java/net/md_5/bungee/api/connection/Server.java b/api/src/main/java/net/md_5/bungee/api/connection/Server.java index f94e5a96..58ae7a1f 100644 --- a/api/src/main/java/net/md_5/bungee/api/connection/Server.java +++ b/api/src/main/java/net/md_5/bungee/api/connection/Server.java @@ -24,14 +24,4 @@ public interface Server extends Connection * @param data the data to send */ public abstract void sendData(String channel, byte[] data); - - /** - * Asynchronously gets the current player count on this server. - * - * @param callback the callback to call when the count has been retrieved. - * @deprecated use the corresponding method in {@link ServerInfo} for - * clarity - */ - @Deprecated - public abstract void ping(Callback callback); } 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 62fc3507..6e6e0144 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java @@ -1,47 +1,28 @@ package net.md_5.bungee; +import io.netty.channel.Channel; import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; import lombok.Getter; -import net.md_5.bungee.api.Callback; -import net.md_5.bungee.api.ServerPing; +import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.Server; -import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.Packet1Login; import net.md_5.bungee.packet.PacketFAPluginMessage; -import net.md_5.bungee.packet.PacketStream; -/** - * Class representing a connection from the proxy to the server; ie upstream. - */ -public class ServerConnection extends GenericConnection implements Server +@RequiredArgsConstructor +public class ServerConnection implements Server { + private final Channel ch; @Getter private final ServerInfo info; - public final Packet1Login loginPacket; - public Queue packetQueue = new ConcurrentLinkedQueue<>(); - - public ServerConnection(Socket socket, ServerInfo info, PacketStream stream, Packet1Login loginPacket) - { - super( socket, stream ); - this.info = info; - this.loginPacket = loginPacket; - } + @Getter + private final Packet1Login loginPacket; @Override public void sendData(String channel, byte[] data) { - packetQueue.add( new PacketFAPluginMessage( channel, data ) ); - } - - @Override - public void ping(final Callback callback) - { - getInfo().ping( callback ); + ch.write( new PacketFAPluginMessage( channel, data ) ); } @Override From b6e76f4054e40ebd3ca12ef5b49c8e12471eea91 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 7 Mar 2013 21:04:03 +1100 Subject: [PATCH 04/31] Cleanup permissions and disconnect sequences --- .../bungee/api/connection/Connection.java | 10 ++ proxy/pom.xml | 5 + .../net/md_5/bungee/ServerConnection.java | 11 ++ .../java/net/md_5/bungee/UserConnection.java | 162 +++++++++--------- 4 files changed, 104 insertions(+), 84 deletions(-) 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 3962b9a9..ba72a96a 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 @@ -16,4 +16,14 @@ public interface Connection * @return the remote address */ public InetSocketAddress getAddress(); + + /** + * Disconnects this end of the connection for the specified reason. If this + * is an {@link ProxiedPlayer} the respective server connection will be + * closed too. + * + * @param reason the reason shown to the player / sent to the server on + * disconnect + */ + public void disconnect(String reason); } diff --git a/proxy/pom.xml b/proxy/pom.xml index 210fde51..577546fc 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -34,6 +34,11 @@ bungeecord-api ${project.version} + + net.sf.trove4j + trove4j + 3.0.3 + mysql mysql-connector-java 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 6e6e0144..1e7929d6 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java @@ -8,6 +8,7 @@ import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.Server; import net.md_5.bungee.packet.Packet1Login; import net.md_5.bungee.packet.PacketFAPluginMessage; +import net.md_5.bungee.packet.PacketFFKick; @RequiredArgsConstructor public class ServerConnection implements Server @@ -25,6 +26,16 @@ public class ServerConnection implements Server ch.write( new PacketFAPluginMessage( channel, data ) ); } + @Override + public synchronized void disconnect(String reason) + { + if ( ch.isActive() ) + { + ch.write( new PacketFFKick( reason ) ); + ch.close(); + } + } + @Override public InetSocketAddress getAddress() { 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 645e56ea..b2ed95e1 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -1,13 +1,13 @@ package net.md_5.bungee; +import gnu.trove.set.hash.THashSet; +import io.netty.channel.Channel; import java.net.InetSocketAddress; import java.net.Socket; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import lombok.Getter; @@ -20,12 +20,15 @@ import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.PlayerDisconnectEvent; import net.md_5.bungee.api.event.ServerConnectEvent; import net.md_5.bungee.connection.DownstreamBridge; +import net.md_5.bungee.connection.UpstreamBridge; import net.md_5.bungee.packet.*; -public final class UserConnection extends GenericConnection implements ProxiedPlayer +public final class UserConnection implements ProxiedPlayer { public final Packet2Handshake handshake; + private final ProxyServer bungee; + private final Channel ch; final Packet1Login forgeLogin; final List loginMessages; public Queue packetQueue = new ConcurrentLinkedQueue<>(); @@ -36,7 +39,6 @@ public final class UserConnection extends GenericConnection implements ProxiedPl // reconnect stuff private int clientEntityId; private int serverEntityId; - private volatile boolean reconnecting; // ping stuff public int trackingPingId; public long pingTime; @@ -44,12 +46,9 @@ public final class UserConnection extends GenericConnection implements ProxiedPl @Setter private int ping = 1000; // Permissions - private final Collection groups = new HashSet<>(); - private final Map permissions = new HashMap<>(); + private final Collection playerGroups = new HashSet<>(); + private final THashSet permissions = new THashSet<>(); private final Object permMutex = new Object(); - // Hack for connect timings - private ServerInfo nextServer; - private volatile boolean clientConnected = true; public UserConnection(Socket socket, PendingConnection pendingConnection, PacketStream stream, Packet2Handshake handshake, Packet1Login forgeLogin, List loginMessages) { @@ -97,86 +96,76 @@ public final class UserConnection extends GenericConnection implements ProxiedPl target = event.getTarget(); // Update in case the event changed target ProxyServer.getInstance().getTabListHandler().onServerChange( this ); - try + + reconnecting = true; + + if ( server != null ) { - reconnecting = true; - - if ( server != null ) - { - stream.write( new Packet9Respawn( (byte) 1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) ); - stream.write( new Packet9Respawn( (byte) -1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) ); - } - - ServerConnection newServer = ServerConnector.connect( this, target, true ); - if ( server == null ) - { - // Once again, first connection - clientEntityId = newServer.loginPacket.entityId; - serverEntityId = newServer.loginPacket.entityId; - // Set tab list size - Packet1Login s = newServer.loginPacket; - Packet1Login login = new Packet1Login( s.entityId, s.levelType, s.gameMode, (byte) s.dimension, s.difficulty, s.unused, (byte) pendingConnection.getListener().getTabListSize() ); - stream.write( login ); - stream.write( BungeeCord.getInstance().registerChannels() ); - - upBridge = new UpstreamBridge(); - upBridge.start(); - } else - { - try - { - downBridge.interrupt(); - downBridge.join(); - } catch ( InterruptedException ie ) - { - } - - server.disconnect( "Quitting" ); - server.getInfo().removePlayer( this ); - - Packet1Login login = newServer.loginPacket; - serverEntityId = login.entityId; - stream.write( new Packet9Respawn( login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType ) ); - } - - // Reconnect process has finished, lets get the player moving again - reconnecting = false; - - // Add to new - target.addPlayer( this ); - - // Start the bridges and move on - server = newServer; - downBridge = new DownstreamBridge(); - downBridge.start(); - } catch ( KickException ex ) - { - disconnect( ex.getMessage() ); - } catch ( Exception ex ) - { - disconnect( "Could not connect to server - " + Util.exception( ex ) ); + stream.write( new Packet9Respawn( (byte) 1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) ); + stream.write( new Packet9Respawn( (byte) -1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) ); } + + ServerConnection newServer = ServerConnector.connect( this, target, true ); + if ( server == null ) + { + // Once again, first connection + clientEntityId = newServer.loginPacket.entityId; + serverEntityId = newServer.loginPacket.entityId; + // Set tab list size + Packet1Login s = newServer.loginPacket; + Packet1Login login = new Packet1Login( s.entityId, s.levelType, s.gameMode, (byte) s.dimension, s.difficulty, s.unused, (byte) pendingConnection.getListener().getTabListSize() ); + stream.write( login ); + stream.write( BungeeCord.getInstance().registerChannels() ); + + upBridge = new UpstreamBridge(); + upBridge.start(); + } else + { + try + { + downBridge.interrupt(); + downBridge.join(); + } catch ( InterruptedException ie ) + { + } + + server.disconnect( "Quitting" ); + server.getInfo().removePlayer( this ); + + Packet1Login login = newServer.loginPacket; + serverEntityId = login.entityId; + stream.write( new Packet9Respawn( login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType ) ); + } + + // Reconnect process has finished, lets get the player moving again + reconnecting = false; + + // Add to new + target.addPlayer( this ); + + // Start the bridges and move on + server = newServer; } @Override public synchronized void disconnect(String reason) { - if ( clientConnected ) + if ( ch.isActive() ) { PlayerDisconnectEvent event = new PlayerDisconnectEvent( this ); - ProxyServer.getInstance().getPluginManager().callEvent( event ); - ProxyServer.getInstance().getTabListHandler().onDisconnect( this ); - ProxyServer.getInstance().getPlayers().remove( this ); + bungee.getPluginManager().callEvent( event ); + bungee.getTabListHandler().onDisconnect( this ); + bungee.getPlayers().remove( this ); + + ch.write( new PacketFFKick( reason ) ); + ch.close(); - super.disconnect( reason ); if ( server != null ) { server.getInfo().removePlayer( this ); server.disconnect( "Quitting" ); - ProxyServer.getInstance().getReconnectHandler().setServer( this ); + bungee.getReconnectHandler().setServer( this ); } - - clientConnected = false; } } @@ -189,20 +178,20 @@ public final class UserConnection extends GenericConnection implements ProxiedPl @Override public void sendData(String channel, byte[] data) { - server.packetQueue.add( new PacketFAPluginMessage( channel, data ) ); + ch.write( new PacketFAPluginMessage( channel, data ) ); } @Override public InetSocketAddress getAddress() { - return (InetSocketAddress) socket.getRemoteSocketAddress(); + return (InetSocketAddress) ch.remoteAddress(); } @Override @Synchronized("permMutex") public Collection getGroups() { - return Collections.unmodifiableCollection( groups ); + return Collections.unmodifiableCollection( playerGroups ); } @Override @@ -211,8 +200,8 @@ public final class UserConnection extends GenericConnection implements ProxiedPl { for ( String group : groups ) { - this.groups.add( group ); - for ( String permission : ProxyServer.getInstance().getConfigurationAdapter().getPermissions( group ) ) + playerGroups.add( group ); + for ( String permission : bungee.getConfigurationAdapter().getPermissions( group ) ) { setPermission( permission, true ); } @@ -225,8 +214,8 @@ public final class UserConnection extends GenericConnection implements ProxiedPl { for ( String group : groups ) { - this.groups.remove( group ); - for ( String permission : ProxyServer.getInstance().getConfigurationAdapter().getPermissions( group ) ) + playerGroups.remove( group ); + for ( String permission : bungee.getConfigurationAdapter().getPermissions( group ) ) { setPermission( permission, false ); } @@ -237,14 +226,19 @@ public final class UserConnection extends GenericConnection implements ProxiedPl @Synchronized("permMutex") public boolean hasPermission(String permission) { - Boolean val = permissions.get( permission ); - return ( val == null ) ? false : val; + return permissions.contains( permission ); } @Override @Synchronized("permMutex") public void setPermission(String permission, boolean value) { - permissions.put( permission, value ); + if ( value ) + { + permissions.add( permission ); + } else + { + permissions.remove( permission ); + } } } From 644deee3c673ce9f020dd9d08219e81f52474937 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 7 Mar 2013 21:33:49 +1100 Subject: [PATCH 05/31] Redo parts of login and connection sequences --- .../java/net/md_5/bungee/InitialHandler.java | 84 +++++++------------ .../java/net/md_5/bungee/ServerConnector.java | 58 +++++++++++-- .../java/net/md_5/bungee/UserConnection.java | 82 ++---------------- 3 files changed, 86 insertions(+), 138 deletions(-) diff --git a/proxy/src/main/java/net/md_5/bungee/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/InitialHandler.java index 9238998f..74060d4b 100644 --- a/proxy/src/main/java/net/md_5/bungee/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/InitialHandler.java @@ -1,17 +1,15 @@ package net.md_5.bungee; import com.google.common.base.Preconditions; +import io.netty.channel.Channel; import java.io.EOFException; -import java.io.IOException; import java.net.InetSocketAddress; -import java.net.Socket; import java.util.ArrayList; import java.util.List; import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; -import javax.crypto.CipherOutputStream; import javax.crypto.SecretKey; import lombok.Getter; +import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ServerPing; @@ -21,6 +19,8 @@ import net.md_5.bungee.api.connection.PendingConnection; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.LoginEvent; import net.md_5.bungee.api.event.ProxyPingEvent; +import net.md_5.bungee.netty.CipherCodec; +import net.md_5.bungee.netty.PacketDecoder; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.Packet1Login; import net.md_5.bungee.packet.Packet2Handshake; @@ -31,16 +31,16 @@ import net.md_5.bungee.packet.PacketFDEncryptionRequest; import net.md_5.bungee.packet.PacketFEPing; import net.md_5.bungee.packet.PacketFFKick; import net.md_5.bungee.packet.PacketHandler; -import net.md_5.bungee.packet.PacketStream; import net.md_5.bungee.protocol.PacketDefinitions; +@RequiredArgsConstructor public class InitialHandler extends PacketHandler implements Runnable, PendingConnection { - private final Socket socket; + private final ProxyServer bungee; + private final Channel ch; @Getter private final ListenerInfo listener; - private PacketStream stream; private Packet1Login forgeLogin; private Packet2Handshake handshake; private PacketFDEncryptionRequest request; @@ -51,13 +51,6 @@ public class InitialHandler extends PacketHandler implements Runnable, PendingCo 0, 0, 0, 0, 0, 2 } ); - public InitialHandler(Socket socket, ListenerInfo info) throws IOException - { - this.socket = socket; - this.listener = info; - stream = new PacketStream( socket.getInputStream(), socket.getOutputStream(), PacketDefinitions.VANILLA_PROTOCOL ); - } - private enum State { @@ -70,7 +63,8 @@ public class InitialHandler extends PacketHandler implements Runnable, PendingCo Preconditions.checkState( thisState == State.LOGIN, "Not expecting FORGE LOGIN" ); Preconditions.checkState( forgeLogin == null, "Already received FORGE LOGIN" ); forgeLogin = login; - stream.setProtocol( PacketDefinitions.FORGE_PROTOCOL ); + + ch.pipeline().get( PacketDecoder.class ).setProtocol( PacketDefinitions.FORGE_PROTOCOL ); } @Override @@ -82,28 +76,17 @@ public class InitialHandler extends PacketHandler implements Runnable, PendingCo @Override public void handle(PacketFEPing ping) throws Exception { - socket.setSoTimeout( 100 ); - boolean newPing = false; - try - { - socket.getInputStream().read(); - newPing = true; - } catch ( IOException ex ) - { - } - ServerPing pingevent = new ServerPing( BungeeCord.PROTOCOL_VERSION, BungeeCord.GAME_VERSION, - listener.getMotd(), ProxyServer.getInstance().getPlayers().size(), listener.getMaxPlayers() ); + listener.getMotd(), bungee.getPlayers().size(), listener.getMaxPlayers() ); - pingevent = ProxyServer.getInstance().getPluginManager().callEvent( new ProxyPingEvent( this, pingevent ) ).getResponse(); + pingevent = bungee.getPluginManager().callEvent( new ProxyPingEvent( this, pingevent ) ).getResponse(); - String response = ( newPing ) ? ChatColor.COLOR_CHAR + "1" + String response = ChatColor.COLOR_CHAR + "1" + "\00" + pingevent.getProtocolVersion() + "\00" + pingevent.getGameVersion() + "\00" + pingevent.getMotd() + "\00" + pingevent.getCurrentPlayers() - + "\00" + pingevent.getMaxPlayers() - : pingevent.getMotd() + ChatColor.COLOR_CHAR + pingevent.getCurrentPlayers() + ChatColor.COLOR_CHAR + pingevent.getMaxPlayers(); + + "\00" + pingevent.getMaxPlayers(); disconnect( response ); } @@ -111,9 +94,10 @@ public class InitialHandler extends PacketHandler implements Runnable, PendingCo public void handle(Packet2Handshake handshake) throws Exception { Preconditions.checkState( thisState == State.HANDSHAKE, "Not expecting HANDSHAKE" ); + Preconditions.checkArgument( handshake.username.length() <= 16, "Cannot have username longer than 16 characters" ); this.handshake = handshake; - stream.write( forgeMods ); - stream.write( request = EncryptionUtil.encryptRequest() ); + ch.write( forgeMods ); + ch.write( request = EncryptionUtil.encryptRequest() ); thisState = State.ENCRYPT; } @@ -129,7 +113,7 @@ public class InitialHandler extends PacketHandler implements Runnable, PendingCo } // Check for multiple connections - ProxiedPlayer old = ProxyServer.getInstance().getPlayer( handshake.username ); + ProxiedPlayer old = bungee.getInstance().getPlayer( handshake.username ); if ( old != null ) { old.disconnect( "You are already connected to the server" ); @@ -137,15 +121,16 @@ public class InitialHandler extends PacketHandler implements Runnable, PendingCo // fire login event LoginEvent event = new LoginEvent( this ); - ProxyServer.getInstance().getPluginManager().callEvent( event ); - if ( event.isCancelled() ) + if ( bungee.getPluginManager().callEvent( event ).isCancelled() ) { - throw new KickException( event.getCancelReason() ); + disconnect( event.getCancelReason() ); } - stream.write( new PacketFCEncryptionResponse() ); - stream = new PacketStream( new CipherInputStream( socket.getInputStream(), EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, shared ) ), - new CipherOutputStream( socket.getOutputStream(), EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, shared ) ), stream.getProtocol() ); + ch.write( new PacketFCEncryptionResponse() ); + + Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, shared ); + Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, shared ); + ch.pipeline().addBefore( "decoder", "cipher", new CipherCodec( encrypt, decrypt ) ); thisState = State.LOGIN; } @@ -186,23 +171,12 @@ public class InitialHandler extends PacketHandler implements Runnable, PendingCo } @Override - public void disconnect(String reason) + public synchronized void disconnect(String reason) { - thisState = State.FINISHED; - try + if ( ch.isActive() ) { - stream.write( new PacketFFKick( reason ) ); - } catch ( IOException ioe ) - { - } finally - { - try - { - socket.shutdownOutput(); - socket.close(); - } catch ( IOException ioe2 ) - { - } + ch.write( new PacketFFKick( reason ) ); + ch.close(); } } @@ -227,6 +201,6 @@ public class InitialHandler extends PacketHandler implements Runnable, PendingCo @Override public InetSocketAddress getAddress() { - return (InetSocketAddress) socket.getRemoteSocketAddress(); + return (InetSocketAddress) ch.remoteAddress(); } } 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 6b5ebe38..3a495488 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -2,6 +2,7 @@ package net.md_5.bungee; import com.google.common.base.Preconditions; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.socket.nio.NioSocketChannel; @@ -9,10 +10,12 @@ import java.util.Queue; import net.md_5.bungee.api.ChatColor; 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.packet.DefinedPacket; import net.md_5.bungee.packet.Packet1Login; +import net.md_5.bungee.packet.Packet9Respawn; import net.md_5.bungee.packet.PacketCDClientStatus; import net.md_5.bungee.packet.PacketFDEncryptionRequest; import net.md_5.bungee.packet.PacketFFKick; @@ -22,7 +25,9 @@ import net.md_5.bungee.packet.PacketStream; public class ServerConnector extends PacketHandler { - private final PacketStream stream; + private final ProxyServer bungee; + private final Channel ch; + private final UserConnection user; private Packet1Login loginPacket; private State thisState = State.ENCRYPT_REQUEST; @@ -45,15 +50,50 @@ public class ServerConnector extends PacketHandler ServerConnection server = new ServerConnection( socket, info, stream, connector.loginPacket ); ServerConnectedEvent event = new ServerConnectedEvent( user, server ); - ProxyServer.getInstance().getPluginManager().callEvent( event ); + bungee.getPluginManager().callEvent( event ); - stream.write( BungeeCord.getInstance().registerChannels() ); + ch.write( BungeeCord.getInstance().registerChannels() ); Queue packetQueue = ( (BungeeServerInfo) info ).getPacketQueue(); while ( !packetQueue.isEmpty() ) { - stream.write( packetQueue.poll() ); + ch.write( packetQueue.poll() ); } + + if ( user.getServer() == null ) + { + BungeeCord.getInstance().connections.put( user.getName(), this ); + bungee.getTabListHandler().onConnect( user ); + // Once again, first connection + clientEntityId = newServer.loginPacket.entityId; + serverEntityId = newServer.loginPacket.entityId; + // Set tab list size + Packet1Login s = newServer.loginPacket; + Packet1Login login = new Packet1Login( s.entityId, s.levelType, s.gameMode, (byte) s.dimension, s.difficulty, s.unused, (byte) pendingConnection.getListener().getTabListSize() ); + stream.write( login ); + stream.write( BungeeCord.getInstance().registerChannels() ); + } else + { + bungee.getTabListHandler().onServerChange( user ); + user.ch.write( new Packet9Respawn( (byte) 1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) ); + user.ch.write( new Packet9Respawn( (byte) -1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) ); + + Packet1Login login = newServer.loginPacket; + serverEntityId = login.entityId; + stream.write( new Packet9Respawn( login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType ) ); + + + // newServer.add(user) + + user.getServer().disconnect( "Quitting" ); + user.getServer().getInfo().removePlayer( user ); + + } + + // + + + thisState = State.FINISHED; } @@ -70,13 +110,17 @@ public class ServerConnector extends PacketHandler throw new KickException( kick.message ); } - public static void connect(final UserConnection user, final ServerInfo info, final boolean retry) + public static void connect(final UserConnection user, ServerInfo info, final boolean retry) { + ServerConnectEvent event = new ServerConnectEvent( user, info ); + ProxyServer.getInstance().getPluginManager().callEvent( event ); + final ServerInfo target = event.getTarget(); // Update in case the event changed target + new Bootstrap() .channel( NioSocketChannel.class ) .group( BungeeCord.getInstance().eventLoops ) .handler( ChannelBootstrapper.CLIENT ) - .remoteAddress( info.getAddress() ) + .remoteAddress( target.getAddress() ) .connect().addListener( new ChannelFutureListener() { @Override @@ -90,7 +134,7 @@ public class ServerConnector extends PacketHandler { future.channel().close(); ServerInfo def = ProxyServer.getInstance().getServers().get( user.getPendingConnection().getListener().getDefaultServer() ); - if ( retry && !info.equals( def ) ) + if ( retry && !target.equals( def ) ) { user.sendMessage( ChatColor.RED + "Could not connect to target server, you have been moved to the default server" ); connect( user, def, false ); 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 b2ed95e1..f0c6f9ed 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -1,5 +1,6 @@ package net.md_5.bungee; +import com.google.common.base.Preconditions; import gnu.trove.set.hash.THashSet; import io.netty.channel.Channel; import java.net.InetSocketAddress; @@ -18,9 +19,6 @@ import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.PendingConnection; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.PlayerDisconnectEvent; -import net.md_5.bungee.api.event.ServerConnectEvent; -import net.md_5.bungee.connection.DownstreamBridge; -import net.md_5.bungee.connection.UpstreamBridge; import net.md_5.bungee.packet.*; public final class UserConnection implements ProxiedPlayer @@ -57,10 +55,9 @@ public final class UserConnection implements ProxiedPlayer this.pendingConnection = pendingConnection; this.forgeLogin = forgeLogin; this.loginMessages = loginMessages; - name = handshake.username.substring( 0, Math.min( handshake.username.length(), 16 ) ); - displayName = name; - Collection g = ProxyServer.getInstance().getConfigurationAdapter().getGroups( name ); + + Collection g = bungee.getConfigurationAdapter().getGroups( name ); for ( String s : g ) { addGroups( s ); @@ -70,81 +67,14 @@ public final class UserConnection implements ProxiedPlayer @Override public void setDisplayName(String name) { - ProxyServer.getInstance().getTabListHandler().onDisconnect( this ); - displayName = name; - ProxyServer.getInstance().getTabListHandler().onConnect( this ); + Preconditions.checkArgument( name.length() <= 16, "Display name cannot be longer than 16 characters" ); + bungee.getTabListHandler().onDisconnect( this ); + bungee.getTabListHandler().onConnect( this ); } @Override public void connect(ServerInfo target) { - nextServer = target; - } - - public void connect(ServerInfo target, boolean force) - { - nextServer = null; - if ( server == null ) - { - // First join - BungeeCord.getInstance().connections.put( name, this ); - ProxyServer.getInstance().getTabListHandler().onConnect( this ); - } - - ServerConnectEvent event = new ServerConnectEvent( this, target ); - BungeeCord.getInstance().getPluginManager().callEvent( event ); - target = event.getTarget(); // Update in case the event changed target - - ProxyServer.getInstance().getTabListHandler().onServerChange( this ); - - reconnecting = true; - - if ( server != null ) - { - stream.write( new Packet9Respawn( (byte) 1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) ); - stream.write( new Packet9Respawn( (byte) -1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) ); - } - - ServerConnection newServer = ServerConnector.connect( this, target, true ); - if ( server == null ) - { - // Once again, first connection - clientEntityId = newServer.loginPacket.entityId; - serverEntityId = newServer.loginPacket.entityId; - // Set tab list size - Packet1Login s = newServer.loginPacket; - Packet1Login login = new Packet1Login( s.entityId, s.levelType, s.gameMode, (byte) s.dimension, s.difficulty, s.unused, (byte) pendingConnection.getListener().getTabListSize() ); - stream.write( login ); - stream.write( BungeeCord.getInstance().registerChannels() ); - - upBridge = new UpstreamBridge(); - upBridge.start(); - } else - { - try - { - downBridge.interrupt(); - downBridge.join(); - } catch ( InterruptedException ie ) - { - } - - server.disconnect( "Quitting" ); - server.getInfo().removePlayer( this ); - - Packet1Login login = newServer.loginPacket; - serverEntityId = login.entityId; - stream.write( new Packet9Respawn( login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType ) ); - } - - // Reconnect process has finished, lets get the player moving again - reconnecting = false; - - // Add to new - target.addPlayer( this ); - - // Start the bridges and move on - server = newServer; } @Override From cdf26f7950bd53314a79c3b2847c86a7cb7bb030 Mon Sep 17 00:00:00 2001 From: md_5 Date: Fri, 8 Mar 2013 17:24:09 +1100 Subject: [PATCH 06/31] Nearing a compilale state, gonna have to redo the bootstrap. --- .../net/md_5/bungee/BungeeServerInfo.java | 31 ------- .../net/md_5/bungee/GenericConnection.java | 61 ------------- .../java/net/md_5/bungee/ServerConnector.java | 85 +++++++++---------- .../java/net/md_5/bungee/UserConnection.java | 24 ++++-- .../bungee/connection/DownstreamBridge.java | 3 +- .../{ => connection}/InitialHandler.java | 39 ++------- .../md_5/bungee/connection/PingHandler.java | 41 +++++++++ .../bungee/netty/ChannelBootstrapper.java | 16 +++- .../net/md_5/bungee/netty/HandlerBoss.java | 14 ++- .../md_5/bungee/packet/Packet9Respawn.java | 2 + .../net/md_5/bungee/packet/PacketHandler.java | 18 ++-- 11 files changed, 148 insertions(+), 186 deletions(-) delete mode 100644 proxy/src/main/java/net/md_5/bungee/GenericConnection.java rename proxy/src/main/java/net/md_5/bungee/{ => connection}/InitialHandler.java (85%) create mode 100644 proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java 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 efe6d0c2..3bd3d24a 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java @@ -1,8 +1,6 @@ package net.md_5.bungee; -import java.io.DataOutputStream; import java.net.InetSocketAddress; -import java.net.Socket; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import lombok.Getter; @@ -13,9 +11,6 @@ import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.Server; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.PacketFAPluginMessage; -import net.md_5.bungee.packet.PacketFFKick; -import net.md_5.bungee.packet.PacketStream; -import net.md_5.bungee.protocol.PacketDefinitions; public class BungeeServerInfo extends ServerInfo { @@ -44,31 +39,5 @@ public class BungeeServerInfo extends ServerInfo @Override public void ping(final Callback callback) { - new Thread() - { - @Override - public void run() - { - try ( Socket socket = new Socket(); ) - { - socket.connect( getAddress() ); - - DataOutputStream out = new DataOutputStream( socket.getOutputStream() ); - out.write( 0xFE ); - out.write( 0x01 ); - - PacketStream in = new PacketStream( socket.getInputStream(), PacketDefinitions.VANILLA_PROTOCOL ); - PacketFFKick response = new PacketFFKick( in.readPacket() ); - - String[] split = response.message.split( "\00" ); - - ServerPing ping = new ServerPing( Byte.parseByte( split[1] ), split[2], split[3], Integer.parseInt( split[4] ), Integer.parseInt( split[5] ) ); - callback.done( ping, null ); - } catch ( Throwable t ) - { - callback.done( null, t ); - } - } - }.start(); } } diff --git a/proxy/src/main/java/net/md_5/bungee/GenericConnection.java b/proxy/src/main/java/net/md_5/bungee/GenericConnection.java deleted file mode 100644 index 876add99..00000000 --- a/proxy/src/main/java/net/md_5/bungee/GenericConnection.java +++ /dev/null @@ -1,61 +0,0 @@ -package net.md_5.bungee; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.Socket; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import static net.md_5.bungee.Logger.$; -import net.md_5.bungee.packet.PacketFFKick; -import net.md_5.bungee.packet.PacketStream; - -/** - * Class to represent a Minecraft connection. - */ -@EqualsAndHashCode -@RequiredArgsConstructor -public class GenericConnection -{ - - protected final Socket socket; - protected final PacketStream stream; - @Getter - public String name; - @Getter - public String displayName; - - /** - * Close the socket with the specified reason. - * - * @param reason to disconnect - */ - public void disconnect(String reason) - { - if ( socket.isClosed() ) - { - return; - } - log( "disconnected with " + reason ); - try - { - stream.write( new PacketFFKick( "[Proxy] " + reason ) ); - } catch ( IOException ex ) - { - } finally - { - try - { - socket.shutdownOutput(); - socket.close(); - } catch ( IOException ioe ) - { - } - } - } - - public void log(String message) - { - $().info( socket.getInetAddress() + ( ( name == null ) ? " " : " [" + name + "] " ) + message ); - } -} 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 3a495488..a1a4a83a 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -1,12 +1,11 @@ package net.md_5.bungee; import com.google.common.base.Preconditions; -import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; -import io.netty.channel.socket.nio.NioSocketChannel; import java.util.Queue; +import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; @@ -20,22 +19,17 @@ import net.md_5.bungee.packet.PacketCDClientStatus; import net.md_5.bungee.packet.PacketFDEncryptionRequest; import net.md_5.bungee.packet.PacketFFKick; import net.md_5.bungee.packet.PacketHandler; -import net.md_5.bungee.packet.PacketStream; +@RequiredArgsConstructor public class ServerConnector extends PacketHandler { private final ProxyServer bungee; private final Channel ch; private final UserConnection user; - private Packet1Login loginPacket; + private final ServerInfo target; private State thisState = State.ENCRYPT_REQUEST; - public ServerConnector(PacketStream stream) - { - this.stream = stream; - } - private enum State { @@ -46,54 +40,56 @@ public class ServerConnector extends PacketHandler public void handle(Packet1Login login) throws Exception { Preconditions.checkState( thisState == State.LOGIN, "Not exepcting LOGIN" ); - loginPacket = login; - ServerConnection server = new ServerConnection( socket, info, stream, connector.loginPacket ); + ServerConnection server = new ServerConnection( ch, target, login ); ServerConnectedEvent event = new ServerConnectedEvent( user, server ); bungee.getPluginManager().callEvent( event ); ch.write( BungeeCord.getInstance().registerChannels() ); - Queue packetQueue = ( (BungeeServerInfo) info ).getPacketQueue(); + Queue packetQueue = ( (BungeeServerInfo) target ).getPacketQueue(); while ( !packetQueue.isEmpty() ) { ch.write( packetQueue.poll() ); } - if ( user.getServer() == null ) + synchronized ( user.getSwitchMutex() ) { - BungeeCord.getInstance().connections.put( user.getName(), this ); - bungee.getTabListHandler().onConnect( user ); - // Once again, first connection - clientEntityId = newServer.loginPacket.entityId; - serverEntityId = newServer.loginPacket.entityId; - // Set tab list size - Packet1Login s = newServer.loginPacket; - Packet1Login login = new Packet1Login( s.entityId, s.levelType, s.gameMode, (byte) s.dimension, s.difficulty, s.unused, (byte) pendingConnection.getListener().getTabListSize() ); - stream.write( login ); - stream.write( BungeeCord.getInstance().registerChannels() ); - } else - { - bungee.getTabListHandler().onServerChange( user ); - user.ch.write( new Packet9Respawn( (byte) 1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) ); - user.ch.write( new Packet9Respawn( (byte) -1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) ); + if ( user.getServer() == null ) + { + BungeeCord.getInstance().connections.put( user.getName(), user ); + bungee.getTabListHandler().onConnect( user ); + // Once again, first connection + user.clientEntityId = login.entityId; + user.serverEntityId = login.entityId; + // Set tab list size + Packet1Login modLogin = new Packet1Login( + login.entityId, + login.levelType, + login.gameMode, + (byte) login.dimension, + login.difficulty, + login.unused, + (byte) user.getPendingConnection().getListener().getTabListSize() ); + ch.write( modLogin ); + ch.write( BungeeCord.getInstance().registerChannels() ); + } else + { + bungee.getTabListHandler().onServerChange( user ); + user.sendPacket( Packet9Respawn.DIM1_SWITCH ); + user.sendPacket( Packet9Respawn.DIM2_SWITCH ); - Packet1Login login = newServer.loginPacket; - serverEntityId = login.entityId; - stream.write( new Packet9Respawn( login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType ) ); - - - // newServer.add(user) - - user.getServer().disconnect( "Quitting" ); - user.getServer().getInfo().removePlayer( user ); + user.serverEntityId = login.entityId; + ch.write( new Packet9Respawn( login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType ) ); + // Add to new server + target.addPlayer( user ); + // Remove from old servers + user.getServer().disconnect( "Quitting" ); + user.getServer().getInfo().removePlayer( user ); + } } - // - - - thisState = State.FINISHED; } @@ -116,12 +112,7 @@ public class ServerConnector extends PacketHandler ProxyServer.getInstance().getPluginManager().callEvent( event ); final ServerInfo target = event.getTarget(); // Update in case the event changed target - new Bootstrap() - .channel( NioSocketChannel.class ) - .group( BungeeCord.getInstance().eventLoops ) - .handler( ChannelBootstrapper.CLIENT ) - .remoteAddress( target.getAddress() ) - .connect().addListener( new ChannelFutureListener() + ChannelBootstrapper.CLIENT.connectClient( info.getAddress() ).addListener( new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception 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 f0c6f9ed..0537fd83 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -4,10 +4,8 @@ import com.google.common.base.Preconditions; import gnu.trove.set.hash.THashSet; import io.netty.channel.Channel; import java.net.InetSocketAddress; -import java.net.Socket; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -35,22 +33,27 @@ public final class UserConnection implements ProxiedPlayer @Getter private ServerConnection server; // reconnect stuff - private int clientEntityId; - private int serverEntityId; + public int clientEntityId; + public int serverEntityId; // ping stuff public int trackingPingId; public long pingTime; @Getter + private String name; + @Getter + private String displayName; + @Getter @Setter private int ping = 1000; // Permissions - private final Collection playerGroups = new HashSet<>(); - private final THashSet permissions = new THashSet<>(); + private final Collection playerGroups = new THashSet<>(); + private final Collection permissions = new THashSet<>(); private final Object permMutex = new Object(); + @Getter + private final Object switchMutex = new Object(); - public UserConnection(Socket socket, PendingConnection pendingConnection, PacketStream stream, Packet2Handshake handshake, Packet1Login forgeLogin, List loginMessages) + public UserConnection(Channel channel, PendingConnection pendingConnection, Packet2Handshake handshake, Packet1Login forgeLogin, List loginMessages) { - super( socket, stream ); this.handshake = handshake; this.pendingConnection = pendingConnection; this.forgeLogin = forgeLogin; @@ -64,6 +67,11 @@ public final class UserConnection implements ProxiedPlayer } } + public void sendPacket(DefinedPacket p) + { + ch.write( p ); + } + @Override public void setDisplayName(String name) { 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 695af1c6..98c749af 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 @@ -109,8 +109,7 @@ public class DownstreamBridge extends PacketHandler ServerInfo server = bungee.getServerInfo( in.readUTF() ); if ( server != null ) { - connect( server, true ); - break outer; + con.connect( server ); } } if ( subChannel.equals( "IP" ) ) diff --git a/proxy/src/main/java/net/md_5/bungee/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java similarity index 85% rename from proxy/src/main/java/net/md_5/bungee/InitialHandler.java rename to proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java index 74060d4b..6710dce2 100644 --- a/proxy/src/main/java/net/md_5/bungee/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java @@ -1,8 +1,7 @@ -package net.md_5.bungee; +package net.md_5.bungee.connection; import com.google.common.base.Preconditions; import io.netty.channel.Channel; -import java.io.EOFException; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; @@ -10,6 +9,10 @@ import javax.crypto.Cipher; import javax.crypto.SecretKey; import lombok.Getter; import lombok.RequiredArgsConstructor; +import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.EncryptionUtil; +import net.md_5.bungee.KickException; +import net.md_5.bungee.UserConnection; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ServerPing; @@ -21,7 +24,6 @@ import net.md_5.bungee.api.event.LoginEvent; import net.md_5.bungee.api.event.ProxyPingEvent; import net.md_5.bungee.netty.CipherCodec; import net.md_5.bungee.netty.PacketDecoder; -import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.Packet1Login; import net.md_5.bungee.packet.Packet2Handshake; import net.md_5.bungee.packet.PacketCDClientStatus; @@ -34,7 +36,7 @@ import net.md_5.bungee.packet.PacketHandler; import net.md_5.bungee.protocol.PacketDefinitions; @RequiredArgsConstructor -public class InitialHandler extends PacketHandler implements Runnable, PendingConnection +public class InitialHandler extends PacketHandler implements PendingConnection { private final ProxyServer bungee; @@ -113,7 +115,7 @@ public class InitialHandler extends PacketHandler implements Runnable, PendingCo } // Check for multiple connections - ProxiedPlayer old = bungee.getInstance().getPlayer( handshake.username ); + ProxiedPlayer old = bungee.getPlayer( handshake.username ); if ( old != null ) { old.disconnect( "You are already connected to the server" ); @@ -141,35 +143,12 @@ public class InitialHandler extends PacketHandler implements Runnable, PendingCo Preconditions.checkState( thisState == State.LOGIN, "Not expecting LOGIN" ); UserConnection userCon = new UserConnection( socket, this, stream, handshake, forgeLogin, loginMessages ); - ServerInfo server = ProxyServer.getInstance().getReconnectHandler().getServer( userCon ); - userCon.connect( server, true ); + ServerInfo server = bungee.getReconnectHandler().getServer( userCon ); + userCon.connect( server ); thisState = State.FINISHED; } - @Override - public void run() - { - try - { - while ( thisState != State.FINISHED ) - { - byte[] buf = stream.readPacket(); - DefinedPacket packet = DefinedPacket.packet( buf ); - packet.handle( this ); - } - } catch ( KickException ex ) - { - disconnect( "[Proxy - Kicked] " + ex.getMessage() ); - } catch ( EOFException ex ) - { - } catch ( Exception ex ) - { - disconnect( "[Proxy Error] " + Util.exception( ex ) ); - ex.printStackTrace(); - } - } - @Override public synchronized void disconnect(String reason) { diff --git a/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java new file mode 100644 index 00000000..ff4af4d0 --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java @@ -0,0 +1,41 @@ +package net.md_5.bungee.connection; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import lombok.RequiredArgsConstructor; +import net.md_5.bungee.api.Callback; +import net.md_5.bungee.api.ServerPing; +import net.md_5.bungee.packet.PacketFFKick; +import net.md_5.bungee.packet.PacketHandler; + +@RequiredArgsConstructor +public class PingHandler extends PacketHandler +{ + + private final Callback callback; + private static final ByteBuf pingBuf = Unpooled.wrappedBuffer( new byte[] + { + (byte) 0xFE, (byte) 0x01 + } ); + + @Override + public void connected(Channel channel) throws Exception + { + channel.write( pingBuf ); + } + + @Override + public void exception(Throwable t) throws Exception + { + callback.done( null, t ); + } + + @Override + public void handle(PacketFFKick kick) throws Exception + { + String[] split = kick.message.split( "\00" ); + ServerPing ping = new ServerPing( Byte.parseByte( split[1] ), split[2], split[3], Integer.parseInt( split[4] ), Integer.parseInt( split[5] ) ); + callback.done( ping, null ); + } +} 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 index 928ec25d..e4c81e7d 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/ChannelBootstrapper.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/ChannelBootstrapper.java @@ -1,14 +1,18 @@ 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.InitialHandler; +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; @@ -20,6 +24,16 @@ public class ChannelBootstrapper extends ChannelInitializer 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 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 38f37419..c404c92a 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 @@ -18,6 +18,18 @@ public class HandlerBoss extends ChannelInboundMessageHandlerAdapter this.handler = handler; } + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception + { + handler.connected( ctx.channel() ); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception + { + handler.disconnected( ctx.channel() ); + } + @Override protected void messageReceived(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { @@ -26,7 +38,7 @@ public class HandlerBoss extends ChannelInboundMessageHandlerAdapter DefinedPacket packet = DefinedPacket.packet( msg ); if ( packet != null ) { - handler.handle( packet ); + packet.handle( handler ); } else { handler.handle( msg ); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java index 2619d3f8..a6e09e1b 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java @@ -8,6 +8,8 @@ import lombok.ToString; public class Packet9Respawn extends DefinedPacket { + public static final Packet9Respawn DIM1_SWITCH = new Packet9Respawn( (byte) 1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ); + public static final Packet9Respawn DIM2_SWITCH = new Packet9Respawn( (byte) -1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ); public int dimension; public byte difficulty; public byte gameMode; diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java index 7826d0af..e5462daf 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java @@ -1,6 +1,7 @@ package net.md_5.bungee.packet; import io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; public abstract class PacketHandler { @@ -10,16 +11,23 @@ public abstract class PacketHandler throw new UnsupportedOperationException( "No handler defined for packet " + msg.getClass() ); } + public void connected(Channel channel) throws Exception + { + } + + public void disconnected(Channel channel) throws Exception + { + } + + public void exception(Throwable t) throws Exception + { + } + public void handle(ByteBuf buf) throws Exception { nop( buf ); } - public void handle(DefinedPacket packet) throws Exception - { - nop( packet ); - } - public void handle(Packet0KeepAlive alive) throws Exception { nop( alive ); From c3d702a5b33f83c6733e9ad6d797b936e8fa8994 Mon Sep 17 00:00:00 2001 From: md_5 Date: Fri, 8 Mar 2013 17:35:01 +1100 Subject: [PATCH 07/31] Switch main packet interface to bytebuf --- .../net/md_5/bungee/packet/DefinedPacket.java | 147 +++--------------- .../net/md_5/bungee/packet/Packet1Login.java | 8 +- .../md_5/bungee/packet/Packet2Handshake.java | 8 +- .../net/md_5/bungee/packet/Packet3Chat.java | 4 +- .../md_5/bungee/packet/Packet9Respawn.java | 4 +- .../bungee/packet/PacketC9PlayerListItem.java | 4 +- .../bungee/packet/PacketFAPluginMessage.java | 4 +- .../packet/PacketFDEncryptionRequest.java | 4 +- .../net/md_5/bungee/packet/PacketFFKick.java | 4 +- 9 files changed, 41 insertions(+), 146 deletions(-) diff --git a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java index a3f53fca..58c68615 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java @@ -1,13 +1,9 @@ package net.md_5.bungee.packet; import com.google.common.base.Preconditions; -import com.google.common.io.ByteArrayDataOutput; -import com.google.common.io.ByteStreams; import io.netty.buffer.ByteBuf; -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.DataOutput; -import java.io.IOException; +import io.netty.buffer.ReferenceCounted; +import io.netty.buffer.Unpooled; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import lombok.Delegate; @@ -18,67 +14,46 @@ import net.md_5.bungee.Util; * subclasses can read and write to the backing byte array which can be * retrieved via the {@link #getPacket()} method. */ -public abstract class DefinedPacket implements DataOutput +public abstract class DefinedPacket implements ByteBuf { - private interface Overriden + @Delegate(types = { - - void readUTF(); - - void writeUTF(String s); - } - private ByteArrayInputStream bin; - private DataInputStream input; - @Delegate(excludes = Overriden.class) - private ByteArrayDataOutput out; + ByteBuf.class, ReferenceCounted.class + }) + private ByteBuf out; /** * Packet id. */ public final int id; - /** - * Already constructed packet. - */ - private byte[] packet; public DefinedPacket(int id, byte[] buf) { - bin = new ByteArrayInputStream( buf ); - input = new DataInputStream( bin ); + out = Unpooled.wrappedBuffer( buf ); if ( readUnsignedByte() != id ) { throw new IllegalArgumentException( "Wasn't expecting packet id " + Util.hex( id ) ); } this.id = id; - packet = buf; } public DefinedPacket(int id) { - out = ByteStreams.newDataOutput(); + out = Unpooled.buffer(); this.id = id; writeByte( id ); } - /** - * Gets the bytes that make up this packet. - * - * @return the bytes which make up this packet, either the original byte - * array or the newly written one. - */ - public byte[] getPacket() - { - return packet == null ? packet = out.toByteArray() : packet; - } - - @Override - public void writeUTF(String s) + public void writeString(String s) { writeShort( s.length() ); - writeChars( s ); + for ( char c : s.toCharArray() ) + { + writeChar( c ); + } } - public String readUTF() + public String readString() { short len = readShort(); char[] chars = new char[ len ]; @@ -92,99 +67,17 @@ public abstract class DefinedPacket implements DataOutput public void writeArray(byte[] b) { writeShort( b.length ); - write( b ); + writeBytes( b ); } public byte[] readArray() { short len = readShort(); byte[] ret = new byte[ len ]; - readFully( ret ); + readBytes( ret ); return ret; } - public final int available() - { - return bin.available(); - } - - public final void readFully(byte b[]) - { - try - { - input.readFully( b ); - } catch ( IOException e ) - { - throw new IllegalStateException( e ); - } - } - - public final boolean readBoolean() - { - try - { - return input.readBoolean(); - } catch ( IOException e ) - { - throw new IllegalStateException( e ); - } - } - - public final byte readByte() - { - try - { - return input.readByte(); - } catch ( IOException e ) - { - throw new IllegalStateException( e ); - } - } - - public final int readUnsignedByte() - { - try - { - return input.readUnsignedByte(); - } catch ( IOException e ) - { - throw new IllegalStateException( e ); - } - } - - public final short readShort() - { - try - { - return input.readShort(); - } catch ( IOException e ) - { - throw new IllegalStateException( e ); - } - } - - public final char readChar() - { - try - { - return input.readChar(); - } catch ( IOException e ) - { - throw new IllegalStateException( e ); - } - } - - public final int readInt() - { - try - { - return input.readInt(); - } catch ( IOException e ) - { - throw new IllegalStateException( e ); - } - } - @Override public abstract boolean equals(Object obj); @@ -195,11 +88,12 @@ public abstract class DefinedPacket implements DataOutput public abstract String toString(); public abstract void handle(PacketHandler handler) throws Exception; + @SuppressWarnings("unchecked") private static Class[] classes = new Class[ 256 ]; public static DefinedPacket packet(ByteBuf buf) { - int id = buf.getUnsignedShort( 0); + int id = buf.getUnsignedShort( 0 ); Class clazz = classes[id]; DefinedPacket ret = null; if ( clazz != null ) @@ -214,7 +108,8 @@ public abstract class DefinedPacket implements DataOutput } catch ( IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException ex ) { } - } else { + } else + { return null; } diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java index 96285c8a..1c505a7f 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java @@ -20,7 +20,7 @@ public class Packet1Login extends DefinedPacket { super( 0x01 ); writeInt( entityId ); - writeUTF( levelType ); + writeString( levelType ); writeByte( gameMode ); writeByte( dimension ); writeByte( difficulty ); @@ -32,12 +32,12 @@ public class Packet1Login extends DefinedPacket { super( 0x01, buf ); this.entityId = readInt(); - this.levelType = readUTF(); + this.levelType = readString(); this.gameMode = readByte(); - if ( available() == 4 ) + if ( readableBytes() == 4 ) { this.dimension = readByte(); - } else if ( available() == 7 ) + } else if ( readableBytes() == 7 ) { this.dimension = readInt(); } else diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java index e739880e..9d3824c5 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java @@ -17,8 +17,8 @@ public class Packet2Handshake extends DefinedPacket { super( 0x02 ); writeByte( protocolVersion ); - writeUTF( username ); - writeUTF( host ); + writeString( username ); + writeString( host ); writeInt( port ); } @@ -26,8 +26,8 @@ public class Packet2Handshake extends DefinedPacket { super( 0x02, buf ); this.procolVersion = readByte(); - this.username = readUTF(); - this.host = readUTF(); + this.username = readString(); + this.host = readString(); this.port = readInt(); } diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java index 7b0a1525..812c963e 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java @@ -13,13 +13,13 @@ public class Packet3Chat extends DefinedPacket public Packet3Chat(String message) { super( 0x03 ); - writeUTF( message ); + writeString( message ); } public Packet3Chat(byte[] buf) { super( 0x03, buf ); - this.message = readUTF(); + this.message = readString(); } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java index a6e09e1b..365e485e 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java @@ -23,7 +23,7 @@ public class Packet9Respawn extends DefinedPacket writeByte( difficulty ); writeByte( gameMode ); writeShort( worldHeight ); - writeUTF( levelType ); + writeString( levelType ); } public Packet9Respawn(byte[] buf) @@ -33,7 +33,7 @@ public class Packet9Respawn extends DefinedPacket this.difficulty = readByte(); this.gameMode = readByte(); this.worldHeight = readShort(); - this.levelType = readUTF(); + this.levelType = readString(); } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketC9PlayerListItem.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketC9PlayerListItem.java index 2ec61aa0..b9b8f541 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketC9PlayerListItem.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketC9PlayerListItem.java @@ -15,7 +15,7 @@ public class PacketC9PlayerListItem extends DefinedPacket public PacketC9PlayerListItem(byte[] packet) { super( 0xC9, packet ); - username = readUTF(); + username = readString(); online = readBoolean(); ping = readShort(); } @@ -23,7 +23,7 @@ public class PacketC9PlayerListItem extends DefinedPacket public PacketC9PlayerListItem(String username, boolean online, int ping) { super( 0xC9 ); - writeUTF( username ); + writeString( username ); writeBoolean( online ); writeShort( ping ); } diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFAPluginMessage.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFAPluginMessage.java index e6f7dd97..f58e6cc7 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFAPluginMessage.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFAPluginMessage.java @@ -14,7 +14,7 @@ public class PacketFAPluginMessage extends DefinedPacket public PacketFAPluginMessage(String tag, byte[] data) { super( 0xFA ); - writeUTF( tag ); + writeString( tag ); writeArray( data ); this.tag = tag; this.data = data; @@ -23,7 +23,7 @@ public class PacketFAPluginMessage extends DefinedPacket public PacketFAPluginMessage(byte[] buf) { super( 0xFA, buf ); - this.tag = readUTF(); + this.tag = readString(); this.data = readArray(); } diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFDEncryptionRequest.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFDEncryptionRequest.java index 886e1ad6..226af9a4 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFDEncryptionRequest.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFDEncryptionRequest.java @@ -15,7 +15,7 @@ public class PacketFDEncryptionRequest extends DefinedPacket public PacketFDEncryptionRequest(String serverId, byte[] publicKey, byte[] verifyToken) { super( 0xFD ); - writeUTF( serverId ); + writeString( serverId ); writeArray( publicKey ); writeArray( verifyToken ); this.serverId = serverId; @@ -26,7 +26,7 @@ public class PacketFDEncryptionRequest extends DefinedPacket public PacketFDEncryptionRequest(byte[] buf) { super( 0xFD, buf ); - serverId = readUTF(); + serverId = readString(); publicKey = readArray(); verifyToken = readArray(); } diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFFKick.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFFKick.java index d6d0f584..f2f816c9 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFFKick.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFFKick.java @@ -13,13 +13,13 @@ public class PacketFFKick extends DefinedPacket public PacketFFKick(String message) { super( 0xFF ); - writeUTF( message ); + writeString( message ); } public PacketFFKick(byte[] buf) { super( 0xFF, buf ); - this.message = readUTF(); + this.message = readString(); } @Override From e18fe49cf93bbbb874fbdde0226acae1b3ae9e69 Mon Sep 17 00:00:00 2001 From: md_5 Date: Fri, 8 Mar 2013 17:52:17 +1100 Subject: [PATCH 08/31] Whats this? It compiles. Doesn't mean it near works though. --- .../java/net/md_5/bungee/UserConnection.java | 4 ++- .../bungee/connection/InitialHandler.java | 2 +- .../net/md_5/bungee/packet/DefinedPacket.java | 29 +++++++++---------- .../md_5/bungee/packet/Packet0KeepAlive.java | 5 ++-- .../net/md_5/bungee/packet/Packet1Login.java | 3 +- .../md_5/bungee/packet/Packet2Handshake.java | 3 +- .../net/md_5/bungee/packet/Packet3Chat.java | 3 +- .../md_5/bungee/packet/Packet9Respawn.java | 3 +- .../bungee/packet/PacketC9PlayerListItem.java | 5 ++-- .../bungee/packet/PacketCDClientStatus.java | 3 +- .../bungee/packet/PacketFAPluginMessage.java | 3 +- .../packet/PacketFCEncryptionResponse.java | 3 +- .../packet/PacketFDEncryptionRequest.java | 3 +- .../net/md_5/bungee/packet/PacketFEPing.java | 6 +++- .../net/md_5/bungee/packet/PacketFFKick.java | 3 +- 15 files changed, 46 insertions(+), 32 deletions(-) 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 0537fd83..8cc4004d 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -52,8 +52,10 @@ public final class UserConnection implements ProxiedPlayer @Getter private final Object switchMutex = new Object(); - public UserConnection(Channel channel, PendingConnection pendingConnection, Packet2Handshake handshake, Packet1Login forgeLogin, List loginMessages) + public UserConnection(BungeeCord bungee, Channel channel, PendingConnection pendingConnection, Packet2Handshake handshake, Packet1Login forgeLogin, List loginMessages) { + this.bungee = bungee; + this.ch = channel; this.handshake = handshake; this.pendingConnection = pendingConnection; this.forgeLogin = forgeLogin; 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 6710dce2..89ec8511 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 @@ -142,7 +142,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection { Preconditions.checkState( thisState == State.LOGIN, "Not expecting LOGIN" ); - UserConnection userCon = new UserConnection( socket, this, stream, handshake, forgeLogin, loginMessages ); + UserConnection userCon = new UserConnection( (BungeeCord) bungee, ch, this, handshake, forgeLogin, loginMessages ); ServerInfo server = bungee.getReconnectHandler().getServer( userCon ); userCon.connect( server ); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java index 58c68615..6aff1861 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java @@ -1,6 +1,5 @@ package net.md_5.bungee.packet; -import com.google.common.base.Preconditions; import io.netty.buffer.ByteBuf; import io.netty.buffer.ReferenceCounted; import io.netty.buffer.Unpooled; @@ -21,26 +20,20 @@ public abstract class DefinedPacket implements ByteBuf { ByteBuf.class, ReferenceCounted.class }) - private ByteBuf out; - /** - * Packet id. - */ - public final int id; + private ByteBuf buf; - public DefinedPacket(int id, byte[] buf) + public DefinedPacket(int id, ByteBuf buf) { - out = Unpooled.wrappedBuffer( buf ); + this.buf = buf; if ( readUnsignedByte() != id ) { throw new IllegalArgumentException( "Wasn't expecting packet id " + Util.hex( id ) ); } - this.id = id; } public DefinedPacket(int id) { - out = Unpooled.buffer(); - this.id = id; + buf = Unpooled.buffer(); writeByte( id ); } @@ -90,6 +83,8 @@ public abstract class DefinedPacket implements ByteBuf public abstract void handle(PacketHandler handler) throws Exception; @SuppressWarnings("unchecked") private static Class[] classes = new Class[ 256 ]; + @SuppressWarnings("unchecked") + private static Constructor[] consructors = new Constructor[ 256 ]; public static DefinedPacket packet(ByteBuf buf) { @@ -100,7 +95,13 @@ public abstract class DefinedPacket implements ByteBuf { try { - Constructor constructor = clazz.getDeclaredConstructor( byte[].class ); + Constructor constructor = consructors[id]; + if ( constructor == null ) + { + constructor = clazz.getDeclaredConstructor( ByteBuf.class ); + consructors[id] = constructor; + } + if ( constructor != null ) { ret = constructor.newInstance( buf ); @@ -108,12 +109,8 @@ public abstract class DefinedPacket implements ByteBuf } catch ( IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException ex ) { } - } else - { - return null; } - Preconditions.checkState( ret != null, "Don't know how to deal with packet ID %s", Util.hex( id ) ); return ret; } diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet0KeepAlive.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet0KeepAlive.java index 310d99ed..4b0ba51e 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet0KeepAlive.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet0KeepAlive.java @@ -1,5 +1,6 @@ package net.md_5.bungee.packet; +import io.netty.buffer.ByteBuf; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -10,9 +11,9 @@ public class Packet0KeepAlive extends DefinedPacket public int id; - public Packet0KeepAlive(byte[] buffer) + public Packet0KeepAlive(ByteBuf buf) { - super( 0x00, buffer ); + super( 0x00, buf ); id = readInt(); } diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java index 1c505a7f..b1a4ec02 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java @@ -1,5 +1,6 @@ package net.md_5.bungee.packet; +import io.netty.buffer.ByteBuf; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -28,7 +29,7 @@ public class Packet1Login extends DefinedPacket writeByte( maxPlayers ); } - public Packet1Login(byte[] buf) + public Packet1Login(ByteBuf buf) { super( 0x01, buf ); this.entityId = readInt(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java index 9d3824c5..e5a54c59 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java @@ -1,5 +1,6 @@ package net.md_5.bungee.packet; +import io.netty.buffer.ByteBuf; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -22,7 +23,7 @@ public class Packet2Handshake extends DefinedPacket writeInt( port ); } - public Packet2Handshake(byte[] buf) + public Packet2Handshake(ByteBuf buf) { super( 0x02, buf ); this.procolVersion = readByte(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java index 812c963e..0791b68e 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java @@ -1,5 +1,6 @@ package net.md_5.bungee.packet; +import io.netty.buffer.ByteBuf; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -16,7 +17,7 @@ public class Packet3Chat extends DefinedPacket writeString( message ); } - public Packet3Chat(byte[] buf) + public Packet3Chat(ByteBuf buf) { super( 0x03, buf ); this.message = readString(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java index 365e485e..66231a1f 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java @@ -1,5 +1,6 @@ package net.md_5.bungee.packet; +import io.netty.buffer.ByteBuf; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -26,7 +27,7 @@ public class Packet9Respawn extends DefinedPacket writeString( levelType ); } - public Packet9Respawn(byte[] buf) + public Packet9Respawn(ByteBuf buf) { super( 0x09, buf ); this.dimension = readInt(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketC9PlayerListItem.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketC9PlayerListItem.java index b9b8f541..655b31de 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketC9PlayerListItem.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketC9PlayerListItem.java @@ -1,5 +1,6 @@ package net.md_5.bungee.packet; +import io.netty.buffer.ByteBuf; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -12,9 +13,9 @@ public class PacketC9PlayerListItem extends DefinedPacket public boolean online; public int ping; - public PacketC9PlayerListItem(byte[] packet) + public PacketC9PlayerListItem(ByteBuf buf) { - super( 0xC9, packet ); + super( 0xC9, buf ); username = readString(); online = readBoolean(); ping = readShort(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketCDClientStatus.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketCDClientStatus.java index 08bdc103..47887656 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketCDClientStatus.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketCDClientStatus.java @@ -1,5 +1,6 @@ package net.md_5.bungee.packet; +import io.netty.buffer.ByteBuf; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -21,7 +22,7 @@ public class PacketCDClientStatus extends DefinedPacket writeByte( payload ); } - public PacketCDClientStatus(byte[] buf) + public PacketCDClientStatus(ByteBuf buf) { super( 0xCD, buf ); } diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFAPluginMessage.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFAPluginMessage.java index f58e6cc7..f12b0fb0 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFAPluginMessage.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFAPluginMessage.java @@ -1,5 +1,6 @@ package net.md_5.bungee.packet; +import io.netty.buffer.ByteBuf; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -20,7 +21,7 @@ public class PacketFAPluginMessage extends DefinedPacket this.data = data; } - public PacketFAPluginMessage(byte[] buf) + public PacketFAPluginMessage(ByteBuf buf) { super( 0xFA, buf ); this.tag = readString(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFCEncryptionResponse.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFCEncryptionResponse.java index 0abd9d08..6670e6e5 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFCEncryptionResponse.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFCEncryptionResponse.java @@ -1,5 +1,6 @@ package net.md_5.bungee.packet; +import io.netty.buffer.ByteBuf; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -25,7 +26,7 @@ public class PacketFCEncryptionResponse extends DefinedPacket writeArray( verifyToken ); } - public PacketFCEncryptionResponse(byte[] buf) + public PacketFCEncryptionResponse(ByteBuf buf) { super( 0xFC, buf ); this.sharedSecret = readArray(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFDEncryptionRequest.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFDEncryptionRequest.java index 226af9a4..fa6e63f2 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFDEncryptionRequest.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFDEncryptionRequest.java @@ -1,5 +1,6 @@ package net.md_5.bungee.packet; +import io.netty.buffer.ByteBuf; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -23,7 +24,7 @@ public class PacketFDEncryptionRequest extends DefinedPacket this.verifyToken = verifyToken; } - public PacketFDEncryptionRequest(byte[] buf) + public PacketFDEncryptionRequest(ByteBuf buf) { super( 0xFD, buf ); serverId = readString(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFEPing.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFEPing.java index 1838a445..88e31929 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFEPing.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFEPing.java @@ -1,5 +1,6 @@ package net.md_5.bungee.packet; +import io.netty.buffer.ByteBuf; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -8,9 +9,12 @@ import lombok.ToString; public class PacketFEPing extends DefinedPacket { - public PacketFEPing(byte[] buffer) + public byte version; + + public PacketFEPing(ByteBuf buffer) { super( 0xFE, buffer ); + version = readByte(); } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFFKick.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFFKick.java index f2f816c9..7eeb12c2 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFFKick.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFFKick.java @@ -1,5 +1,6 @@ package net.md_5.bungee.packet; +import io.netty.buffer.ByteBuf; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -16,7 +17,7 @@ public class PacketFFKick extends DefinedPacket writeString( message ); } - public PacketFFKick(byte[] buf) + public PacketFFKick(ByteBuf buf) { super( 0xFF, buf ); this.message = readString(); From 9ad90039746b35971c4ccbc4502b87f6ead0a2e0 Mon Sep 17 00:00:00 2001 From: md_5 Date: Fri, 8 Mar 2013 18:07:21 +1100 Subject: [PATCH 09/31] Tigthen access + javadocs on a few netty related classes. --- proxy/src/main/java/net/md_5/bungee/BungeeCord.java | 7 ------- .../src/main/java/net/md_5/bungee/netty/CipherCodec.java | 7 +++++-- .../src/main/java/net/md_5/bungee/netty/HandlerBoss.java | 7 ++++++- .../main/java/net/md_5/bungee/netty/PacketDecoder.java | 8 ++++++++ 4 files changed, 19 insertions(+), 10 deletions(-) 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 4ffd581f..52127e97 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -4,19 +4,14 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelException; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; import io.netty.channel.MultithreadEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.handler.timeout.ReadTimeoutHandler; import net.md_5.bungee.config.Configuration; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetSocketAddress; -import java.net.Socket; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -44,8 +39,6 @@ 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.HandlerBoss; -import net.md_5.bungee.netty.PacketDecoder; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.PacketFAPluginMessage; diff --git a/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java b/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java index b569e406..530b455e 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java @@ -8,8 +8,10 @@ import javax.crypto.ShortBufferException; /** * This class is a complete solution for encrypting and decoding bytes in a - * Netty stream. It takes two {@link BufferedBlockCipher} instances, used for - * encryption and decryption respectively. + * Netty stream. It takes two {@link Cipher} instances, used for encryption and + * decryption respectively. As newer Netty versions never use a heap + * {@link ByteBuf} for writing to the channel, this class will always create one + * for temporary usage. */ public class CipherCodec extends ByteToByteCodec { @@ -69,6 +71,7 @@ public class CipherCodec extends ByteToByteCodec { out.capacity( outputSize ); } + // TODO: Try and make this use out.nioBuffer() int processed = cipher.update( in.array(), in.arrayOffset() + in.readerIndex(), available, out.array(), out.arrayOffset() + out.writerIndex() ); in.readerIndex( in.readerIndex() + processed ); out.writerIndex( out.writerIndex() + processed ); 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 c404c92a..f57b53cb 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 @@ -7,7 +7,12 @@ import io.netty.channel.ChannelInboundMessageHandlerAdapter; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.PacketHandler; -public class HandlerBoss extends ChannelInboundMessageHandlerAdapter +/** + * This class is a primitive wrapper for {@link PacketHandler} instances tied to + * channels to maintain simple states, and only call the required, adapted + * methods when the channel is connected. + */ +class HandlerBoss extends ChannelInboundMessageHandlerAdapter { private PacketHandler handler; diff --git a/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java b/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java index 5dffe828..98f0b821 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java @@ -8,6 +8,14 @@ import lombok.Getter; import lombok.Setter; import net.md_5.bungee.protocol.netty.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. + *

+ * 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 { From 9e0ae0a70d76b0f35251cd33140dcde43bc36c12 Mon Sep 17 00:00:00 2001 From: md_5 Date: Fri, 8 Mar 2013 18:26:59 +1100 Subject: [PATCH 10/31] Thread login auth properly. --- .../java/net/md_5/bungee/EncryptionUtil.java | 33 +------ .../bungee/connection/InitialHandler.java | 95 ++++++++++++++----- 2 files changed, 73 insertions(+), 55 deletions(-) diff --git a/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java b/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java index 26bbdb21..28729433 100644 --- a/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java +++ b/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java @@ -1,17 +1,10 @@ package net.md_5.bungee; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.math.BigInteger; -import java.net.URL; -import java.net.URLEncoder; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyPair; import java.security.KeyPairGenerator; -import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Random; @@ -32,7 +25,7 @@ public class EncryptionUtil { private static final Random random = new Random(); - private static KeyPair keys; + public static KeyPair keys; public static PacketFDEncryptionRequest encryptRequest() throws NoSuchAlgorithmException { @@ -66,30 +59,6 @@ public class EncryptionUtil return new SecretKeySpec( secret, "AES" ); } - public static boolean isAuthenticated(String username, String connectionHash, SecretKey shared) throws NoSuchAlgorithmException, IOException - { - String encName = URLEncoder.encode( username, "UTF-8" ); - - MessageDigest sha = MessageDigest.getInstance( "SHA-1" ); - for ( byte[] bit : new byte[][] - { - connectionHash.getBytes( "ISO_8859_1" ), shared.getEncoded(), keys.getPublic().getEncoded() - } ) - { - sha.update( bit ); - } - - String encodedHash = URLEncoder.encode( new BigInteger( sha.digest() ).toString( 16 ), "UTF-8" ); - String authURL = "http://session.minecraft.net/game/checkserver.jsp?user=" + encName + "&serverId=" + encodedHash; - String reply; - try ( BufferedReader in = new BufferedReader( new InputStreamReader( new URL( authURL ).openStream() ) ) ) - { - reply = in.readLine(); - } - - return "YES".equals( reply ); - } - public static Cipher getCipher(int opMode, Key shared) throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException { Cipher cip = Cipher.getInstance( "AES/CFB8/NoPadding" ); 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 89ec8511..76921b60 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 @@ -2,7 +2,14 @@ package net.md_5.bungee.connection; import com.google.common.base.Preconditions; import io.netty.channel.Channel; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.math.BigInteger; import java.net.InetSocketAddress; +import java.net.URL; +import java.net.URLEncoder; +import java.security.MessageDigest; import java.util.ArrayList; import java.util.List; import javax.crypto.Cipher; @@ -11,8 +18,8 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import net.md_5.bungee.BungeeCord; import net.md_5.bungee.EncryptionUtil; -import net.md_5.bungee.KickException; import net.md_5.bungee.UserConnection; +import net.md_5.bungee.Util; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ServerPing; @@ -104,37 +111,79 @@ public class InitialHandler extends PacketHandler implements PendingConnection } @Override - public void handle(PacketFCEncryptionResponse encryptResponse) throws Exception + public void handle(final PacketFCEncryptionResponse encryptResponse) throws Exception { Preconditions.checkState( thisState == State.ENCRYPT, "Not expecting ENCRYPT" ); - SecretKey shared = EncryptionUtil.getSecret( encryptResponse, request ); - if ( BungeeCord.getInstance().config.isOnlineMode() && !EncryptionUtil.isAuthenticated( handshake.username, request.serverId, shared ) ) + // TODO: This is shit + new Thread( "Login Verifier - " + getName() ) { - throw new KickException( "Not authenticated with minecraft.net" ); - } + @Override + public void run() + { + try + { + SecretKey shared = EncryptionUtil.getSecret( encryptResponse, request ); + if ( BungeeCord.getInstance().config.isOnlineMode() ) + { + String reply = null; + try + { + String encName = URLEncoder.encode( InitialHandler.this.getName(), "UTF-8" ); - // Check for multiple connections - ProxiedPlayer old = bungee.getPlayer( handshake.username ); - if ( old != null ) - { - old.disconnect( "You are already connected to the server" ); - } + MessageDigest sha = MessageDigest.getInstance( "SHA-1" ); + for ( byte[] bit : new byte[][] + { + request.serverId.getBytes( "ISO_8859_1" ), shared.getEncoded(), EncryptionUtil.keys.getPublic().getEncoded() + } ) + { + sha.update( bit ); + } - // fire login event - LoginEvent event = new LoginEvent( this ); - if ( bungee.getPluginManager().callEvent( event ).isCancelled() ) - { - disconnect( event.getCancelReason() ); - } + String encodedHash = URLEncoder.encode( new BigInteger( sha.digest() ).toString( 16 ), "UTF-8" ); + String authURL = "http://session.minecraft.net/game/checkserver.jsp?user=" + encName + "&serverId=" + encodedHash; - ch.write( new PacketFCEncryptionResponse() ); + try ( BufferedReader in = new BufferedReader( new InputStreamReader( new URL( authURL ).openStream() ) ) ) + { + reply = in.readLine(); + } + } catch ( IOException ex ) + { + } - Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, shared ); - Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, shared ); - ch.pipeline().addBefore( "decoder", "cipher", new CipherCodec( encrypt, decrypt ) ); + if ( !"YES".equals( reply ) ) + { + disconnect( "Not authenticated with Minecraft.net" ); + } - thisState = State.LOGIN; + // Check for multiple connections + ProxiedPlayer old = bungee.getPlayer( handshake.username ); + if ( old != null ) + { + old.disconnect( "You are already connected to the server" ); + } + + // fire login event + LoginEvent event = new LoginEvent( InitialHandler.this ); + if ( bungee.getPluginManager().callEvent( event ).isCancelled() ) + { + disconnect( event.getCancelReason() ); + } + } + + ch.write( new PacketFCEncryptionResponse() ); + + Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, shared ); + Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, shared ); + ch.pipeline().addBefore( "decoder", "cipher", new CipherCodec( encrypt, decrypt ) ); + + thisState = InitialHandler.State.LOGIN; + } catch ( Exception ex ) + { + disconnect( "[Report to md_5 / Server Owner] " + Util.exception( ex ) ); + } + } + }.start(); } @Override From 45c848a4fd1996ca090a467829c31d36a50250bf Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 9 Mar 2013 09:44:28 +1100 Subject: [PATCH 11/31] Cleanup channel initialization - now its time to get this show working. --- protocol/pom.xml | 1 + .../main/java/net/md_5/bungee/BungeeCord.java | 9 ++- .../net/md_5/bungee/BungeeServerInfo.java | 4 ++ .../java/net/md_5/bungee/ServerConnector.java | 23 ++++--- .../bungee/connection/InitialHandler.java | 8 ++- .../bungee/netty/ChannelBootstrapper.java | 63 ------------------- .../net/md_5/bungee/netty/HandlerBoss.java | 16 +++-- .../net/md_5/bungee/netty/PipelineUtils.java | 63 +++++++++++++++++++ 8 files changed, 106 insertions(+), 81 deletions(-) delete mode 100644 proxy/src/main/java/net/md_5/bungee/netty/ChannelBootstrapper.java create mode 100644 proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java 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(); + } +} From 8a96555cc741bdd2fb53c604209e23fe1725b52b Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 9 Mar 2013 09:54:19 +1100 Subject: [PATCH 12/31] We can now get pings! --- proxy/src/main/java/net/md_5/bungee/BungeeCord.java | 4 ++-- proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java | 1 + proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java | 5 ++++- .../src/main/java/net/md_5/bungee/packet/DefinedPacket.java | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) 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 880e24e2..a670eadf 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -187,11 +187,11 @@ public class BungeeCord extends ProxyServer for ( ListenerInfo info : config.getListeners() ) { Channel server = new ServerBootstrap() - .channel( NioServerSocketChannel.class) + .channel( NioServerSocketChannel.class ) + .childAttr( PipelineUtils.LISTENER, info ) .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/netty/HandlerBoss.java b/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java index 8dcbddef..269ae264 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 @@ -60,6 +60,7 @@ public class HandlerBoss extends ChannelInboundMessageHandlerAdapter @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + super.exceptionCaught( ctx, cause ); if ( ctx.channel().isActive() ) { ctx.close(); diff --git a/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java b/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java index 98f0b821..0f7e2d0f 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java @@ -27,7 +27,10 @@ public class PacketDecoder extends ReplayingDecoder @Override protected ByteBuf decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { + int startIndex = in.readerIndex(); PacketReader.readPacket( in, protocol ); - return in.copy(); + ByteBuf readPacket = in.copy( startIndex, in.readerIndex() - startIndex ); + System.out.println( readPacket ); + return readPacket; } } diff --git a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java index 6aff1861..f4a4e44c 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java @@ -88,7 +88,7 @@ public abstract class DefinedPacket implements ByteBuf public static DefinedPacket packet(ByteBuf buf) { - int id = buf.getUnsignedShort( 0 ); + short id = buf.getUnsignedByte( 0 ); Class clazz = classes[id]; DefinedPacket ret = null; if ( clazz != null ) From bcaafc206fca0ff8ae11a5cda109a2a2df5570a8 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 9 Mar 2013 10:10:36 +1100 Subject: [PATCH 13/31] Advancing further in the login process. --- .../java/net/md_5/bungee/protocol/netty/BulkChunk.java | 2 +- .../java/net/md_5/bungee/protocol/netty/Instruction.java | 5 ----- .../main/java/net/md_5/bungee/protocol/netty/Item.java | 2 +- .../main/java/net/md_5/bungee/protocol/netty/Jump.java | 2 +- .../java/net/md_5/bungee/protocol/netty/MetaData.java | 2 +- .../net/md_5/bungee/protocol/netty/OptionalMotion.java | 2 +- .../md_5/bungee/protocol/netty/UnsignedShortByte.java | 2 +- .../java/net/md_5/bungee/connection/InitialHandler.java | 2 +- .../src/main/java/net/md_5/bungee/netty/HandlerBoss.java | 2 +- .../main/java/net/md_5/bungee/netty/PacketDecoder.java | 9 ++++++--- 10 files changed, 14 insertions(+), 16 deletions(-) diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/netty/BulkChunk.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/BulkChunk.java index 37499018..54fee12d 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/netty/BulkChunk.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/BulkChunk.java @@ -12,6 +12,6 @@ public class BulkChunk extends Instruction short count = in.readShort(); int size = in.readInt(); in.readBoolean(); - skip( in, size + count * 12 ); + in.skipBytes( size + count * 12 ); } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/netty/Instruction.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/Instruction.java index 6b84dc59..7340055c 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/netty/Instruction.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/Instruction.java @@ -28,9 +28,4 @@ abstract class Instruction static final Instruction BYTE_INT = new ByteHeader( INT ); abstract void read(ByteBuf in) throws IOException; - - final void skip(ByteBuf in, int len) throws IOException - { - in.readerIndex( in.readerIndex() + len ); - } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/netty/Item.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/Item.java index 5026b521..529be2f3 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/netty/Item.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/Item.java @@ -12,7 +12,7 @@ class Item extends Instruction short type = in.readShort(); if ( type >= 0 ) { - skip( in, 3 ); + in.skipBytes( 3 ); SHORT_BYTE.read( in ); } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/netty/Jump.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/Jump.java index 0c9ed2a4..aca0d763 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/netty/Jump.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/Jump.java @@ -20,6 +20,6 @@ class Jump extends Instruction @Override void read(ByteBuf in) throws IOException { - skip( in, len ); + in.skipBytes( len ); } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/netty/MetaData.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/MetaData.java index 7ebc3c16..730f3686 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/netty/MetaData.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/MetaData.java @@ -34,7 +34,7 @@ class MetaData extends Instruction ITEM.read( in ); break; case 6: - skip( in, 12 ); // int, int, int + in.skipBytes( 12 ); // int, int, int break; default: throw new IllegalArgumentException( "Unknown metadata type " + type ); diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/netty/OptionalMotion.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/OptionalMotion.java index 7e304007..4e618360 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/netty/OptionalMotion.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/OptionalMotion.java @@ -12,7 +12,7 @@ class OptionalMotion extends Instruction int data = in.readInt(); if ( data > 0 ) { - skip( in, 6 ); + in.skipBytes( 6 ); } } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/netty/UnsignedShortByte.java b/protocol/src/main/java/net/md_5/bungee/protocol/netty/UnsignedShortByte.java index 2b409884..1dea256b 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/netty/UnsignedShortByte.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/netty/UnsignedShortByte.java @@ -10,6 +10,6 @@ class UnsignedShortByte extends Instruction void read(ByteBuf in) throws IOException { int size = in.readUnsignedShort(); - skip( in, size ); + in.skipBytes( size ); } } 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 a8ee0278..1cad4c47 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 @@ -179,8 +179,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection ch.write( new PacketFCEncryptionResponse() ); - Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, shared ); Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, shared ); + Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, shared ); ch.pipeline().addBefore( "decoder", "cipher", new CipherCodec( encrypt, decrypt ) ); thisState = InitialHandler.State.LOGIN; 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 269ae264..bce51eaa 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 @@ -60,7 +60,7 @@ public class HandlerBoss extends ChannelInboundMessageHandlerAdapter @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - super.exceptionCaught( ctx, cause ); + cause.printStackTrace(); if ( ctx.channel().isActive() ) { ctx.close(); diff --git a/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java b/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java index 0f7e2d0f..6d12c2d7 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java @@ -3,9 +3,11 @@ package net.md_5.bungee.netty; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ReplayingDecoder; +import java.io.IOException; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; +import net.md_5.bungee.Util; import net.md_5.bungee.protocol.netty.PacketReader; /** @@ -28,9 +30,10 @@ public class PacketDecoder extends ReplayingDecoder protected ByteBuf decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { int startIndex = in.readerIndex(); + PacketReader.readPacket( in, protocol ); - ByteBuf readPacket = in.copy( startIndex, in.readerIndex() - startIndex ); - System.out.println( readPacket ); - return readPacket; + + System.out.println( Util.hex( in.getUnsignedByte( 0 ) ) ); + return in.copy( startIndex, in.readerIndex() - startIndex ); } } From e12bc1d92ebebefb2de98e721a92dea27a45e687 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 9 Mar 2013 10:47:12 +1100 Subject: [PATCH 14/31] Closer to connecting, trying to figure out this encryption bug also present in first connect on Spigot --- .../net/md_5/bungee/BungeeServerInfo.java | 10 +++- .../java/net/md_5/bungee/ServerConnector.java | 31 ------------ .../java/net/md_5/bungee/UserConnection.java | 47 +++++++++++++++++++ .../net/md_5/bungee/netty/CipherCodec.java | 6 +++ .../net/md_5/bungee/netty/HandlerBoss.java | 3 +- .../net/md_5/bungee/netty/PipelineUtils.java | 28 ++++++----- 6 files changed, 80 insertions(+), 45 deletions(-) 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 cd691b7c..5cd5ca33 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java @@ -1,5 +1,7 @@ package net.md_5.bungee; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.socket.nio.NioSocketChannel; import java.net.InetSocketAddress; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -42,6 +44,12 @@ public class BungeeServerInfo extends ServerInfo @Override public void ping(final Callback callback) { - PipelineUtils.connectClient( getAddress() ).channel().pipeline().get( HandlerBoss.class ).setHandler( new PingHandler( callback ) ); + new Bootstrap() + .channel( NioSocketChannel.class ) + .group( BungeeCord.getInstance().eventLoops ) + .handler( PipelineUtils.BASE ) + .remoteAddress( getAddress() ) + .connect() + .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 19d78af4..f7e98127 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -2,17 +2,11 @@ package net.md_5.bungee; import com.google.common.base.Preconditions; import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; import java.util.Queue; import lombok.RequiredArgsConstructor; -import net.md_5.bungee.api.ChatColor; 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.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; @@ -114,29 +108,4 @@ public class ServerConnector extends PacketHandler { throw new KickException( kick.message ); } - - public static void connect(final UserConnection user, ServerInfo info, final boolean retry) - { - ServerConnectEvent event = new ServerConnectEvent( user, info ); - ProxyServer.getInstance().getPluginManager().callEvent( event ); - final ServerInfo target = event.getTarget(); // Update in case the event changed target - - PipelineUtils.connectClient( info.getAddress() ).addListener( new ChannelFutureListener() - { - @Override - public void operationComplete(ChannelFuture future) throws Exception - { - if ( !future.isSuccess() ) - { - future.channel().close(); - ServerInfo def = ProxyServer.getInstance().getServers().get( user.getPendingConnection().getListener().getDefaultServer() ); - if ( retry && !target.equals( def ) ) - { - user.sendMessage( ChatColor.RED + "Could not connect to target server, you have been moved to the default server" ); - connect( user, def, false ); - } - } - } - } ).channel().pipeline().get( HandlerBoss.class).setHandler( new ServerConnector( ProxyServer.getInstance(), user, target)); - } } 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 8cc4004d..f6095cc7 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -2,7 +2,12 @@ package net.md_5.bungee; import com.google.common.base.Preconditions; import gnu.trove.set.hash.THashSet; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.socket.nio.NioSocketChannel; import java.net.InetSocketAddress; import java.util.Collection; import java.util.Collections; @@ -12,11 +17,15 @@ import java.util.concurrent.ConcurrentLinkedQueue; import lombok.Getter; import lombok.Setter; import lombok.Synchronized; +import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.PendingConnection; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.PlayerDisconnectEvent; +import net.md_5.bungee.api.event.ServerConnectEvent; +import net.md_5.bungee.netty.HandlerBoss; +import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.packet.*; public final class UserConnection implements ProxiedPlayer @@ -85,6 +94,44 @@ public final class UserConnection implements ProxiedPlayer @Override public void connect(ServerInfo target) { + connect( target, true ); + } + + private void connect(ServerInfo info, final boolean retry) + { + ServerConnectEvent event = new ServerConnectEvent( this, info ); + ProxyServer.getInstance().getPluginManager().callEvent( event ); + final ServerInfo target = event.getTarget(); // Update in case the event changed target + new Bootstrap() + .channel( NioSocketChannel.class ) + .group( BungeeCord.getInstance().eventLoops ) + .handler( new ChannelInitializer() + { + @Override + protected void initChannel(Channel ch) throws Exception + { + PipelineUtils.BASE.initChannel( ch ); + ch.pipeline().get( HandlerBoss.class ).setHandler( new ServerConnector( bungee, UserConnection.this, target ) ); + } + } ) + .remoteAddress( target.getAddress() ) + .connect().addListener( new ChannelFutureListener() + { + @Override + public void operationComplete(ChannelFuture future) throws Exception + { + if ( !future.isSuccess() ) + { + future.channel().close(); + ServerInfo def = ProxyServer.getInstance().getServers().get( getPendingConnection().getListener().getDefaultServer() ); + if ( retry && !target.equals( def ) ) + { + sendMessage( ChatColor.RED + "Could not connect to target server, you have been moved to the default server" ); + connect( def, false ); + } + } + } + } ); } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java b/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java index 530b455e..9fd54eac 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java @@ -33,6 +33,9 @@ public class CipherCodec extends ByteToByteCodec { heapOut = ctx.alloc().heapBuffer(); } + System.out.println( "e) in: " + in ); + System.out.println( "e) heapOut: " + heapOut ); + System.out.println( "e) out: " + out ); cipher( encrypt, in, heapOut ); out.writeBytes( heapOut ); heapOut.discardSomeReadBytes(); @@ -41,6 +44,9 @@ public class CipherCodec extends ByteToByteCodec @Override public void decode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { + System.out.println( "d) in: " + in ); + System.out.println( "d) heapOut: " + heapOut ); + System.out.println( "d) out: " + out ); cipher( decrypt, in, out ); } 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 bce51eaa..b27d0f52 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 @@ -4,6 +4,7 @@ import com.google.common.base.Preconditions; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundMessageHandlerAdapter; +import net.md_5.bungee.Util; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.PacketHandler; @@ -60,7 +61,7 @@ public class HandlerBoss extends ChannelInboundMessageHandlerAdapter @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - cause.printStackTrace(); + System.out.println( handler + " " + Util.exception( cause ) ); if ( ctx.channel().isActive() ) { ctx.close(); 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 56e69bac..c54227b8 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 @@ -12,15 +12,20 @@ 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.ServerConnector; +import net.md_5.bungee.UserConnection; 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.api.config.ServerInfo; import net.md_5.bungee.protocol.PacketDefinitions; public class PipelineUtils { public static final AttributeKey LISTENER = new AttributeKey<>( "ListerInfo" ); + public static final AttributeKey USER = new AttributeKey<>( "User" ); + public static final AttributeKey TARGET = new AttributeKey<>( "Target" ); public static final ChannelInitializer SERVER_CHILD = new ChannelInitializer() { @Override @@ -30,9 +35,18 @@ public class PipelineUtils ch.pipeline().get( HandlerBoss.class ).setHandler( new InitialHandler( ProxyServer.getInstance(), ch.attr( LISTENER ).get() ) ); } }; - private static final Base BASE = new Base(); + public static final ChannelInitializer CLIENT = new ChannelInitializer() + { + @Override + protected void initChannel(Channel ch) throws Exception + { + BASE.initChannel( ch ); + 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(); - private final static class Base extends ChannelInitializer + public final static class Base extends ChannelInitializer { @Override @@ -50,14 +64,4 @@ public class PipelineUtils 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(); - } } From 4fb85721a965328dc9d28d4b4e9998015a507574 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 9 Mar 2013 12:08:26 +1100 Subject: [PATCH 15/31] Nearly ready to get a working connection, however few hacks due to own shortcomings and netty shortcomings. --- .../java/net/md_5/bungee/ServerConnection.java | 1 + .../java/net/md_5/bungee/ServerConnector.java | 8 +++++++- .../java/net/md_5/bungee/UserConnection.java | 5 +++-- .../bungee/connection/DownstreamBridge.java | 9 +++++++++ .../md_5/bungee/connection/InitialHandler.java | 4 ++-- .../md_5/bungee/connection/UpstreamBridge.java | 9 +++++++++ .../net/md_5/bungee/netty/CipherCodec.java | 6 ------ .../net/md_5/bungee/netty/HandlerBoss.java | 6 ++---- .../md_5/bungee/packet/Packet0KeepAlive.java | 2 +- .../net/md_5/bungee/packet/Packet1Login.java | 2 +- .../md_5/bungee/packet/Packet2Handshake.java | 2 +- .../net/md_5/bungee/packet/Packet3Chat.java | 2 +- .../net/md_5/bungee/packet/Packet9Respawn.java | 2 +- .../bungee/packet/PacketC9PlayerListItem.java | 2 +- .../bungee/packet/PacketCDClientStatus.java | 2 +- .../bungee/packet/PacketFAPluginMessage.java | 2 +- .../packet/PacketFCEncryptionResponse.java | 2 +- .../packet/PacketFDEncryptionRequest.java | 2 +- .../net/md_5/bungee/packet/PacketFEPing.java | 2 +- .../net/md_5/bungee/packet/PacketFFKick.java | 2 +- .../net/md_5/bungee/packet/PacketHandler.java | 18 ------------------ 21 files changed, 45 insertions(+), 45 deletions(-) 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 1e7929d6..ce31f304 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java @@ -14,6 +14,7 @@ import net.md_5.bungee.packet.PacketFFKick; public class ServerConnection implements Server { + @Getter private final Channel ch; @Getter private final ServerInfo info; 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 f7e98127..ebe5de79 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -7,8 +7,11 @@ import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.event.ServerConnectedEvent; +import net.md_5.bungee.connection.DownstreamBridge; +import net.md_5.bungee.netty.HandlerBoss; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.Packet1Login; +import net.md_5.bungee.packet.Packet2Handshake; import net.md_5.bungee.packet.Packet9Respawn; import net.md_5.bungee.packet.PacketCDClientStatus; import net.md_5.bungee.packet.PacketFDEncryptionRequest; @@ -35,7 +38,8 @@ public class ServerConnector extends PacketHandler public void connected(Channel channel) throws Exception { this.ch = channel; - channel.write( user.handshake ); + // TODO: Fix this crap + channel.write( new Packet2Handshake( user.handshake.procolVersion, user.handshake.username, user.handshake.host, user.handshake.port ) ); channel.write( PacketCDClientStatus.CLIENT_LOGIN ); } @@ -91,6 +95,8 @@ public class ServerConnector extends PacketHandler user.getServer().disconnect( "Quitting" ); user.getServer().getInfo().removePlayer( user ); } + + ch.pipeline().get( HandlerBoss.class ).setHandler( new DownstreamBridge( bungee, user ) ); } thisState = State.FINISHED; 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 f6095cc7..36cf93e3 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -33,7 +33,7 @@ public final class UserConnection implements ProxiedPlayer public final Packet2Handshake handshake; private final ProxyServer bungee; - private final Channel ch; + public final Channel ch; final Packet1Login forgeLogin; final List loginMessages; public Queue packetQueue = new ConcurrentLinkedQueue<>(); @@ -69,7 +69,8 @@ public final class UserConnection implements ProxiedPlayer this.pendingConnection = pendingConnection; this.forgeLogin = forgeLogin; this.loginMessages = loginMessages; - + this.name = handshake.username; + this.displayName = name; Collection g = bungee.getConfigurationAdapter().getGroups( name ); for ( String s : g ) 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 98c749af..d426690b 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 @@ -3,7 +3,9 @@ package net.md_5.bungee.connection; import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; +import io.netty.buffer.ByteBuf; import lombok.RequiredArgsConstructor; +import net.md_5.bungee.EntityMap; import net.md_5.bungee.UserConnection; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; @@ -24,6 +26,13 @@ public class DownstreamBridge extends PacketHandler private final ProxyServer bungee; private final UserConnection con; + @Override + public void handle(ByteBuf buf) throws Exception + { + EntityMap.rewrite( buf, con.serverEntityId, con.clientEntityId ); + con.ch.write( buf ); + } + @Override public void handle(Packet0KeepAlive alive) throws Exception { 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 1cad4c47..65195ad2 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 @@ -177,10 +177,10 @@ public class InitialHandler extends PacketHandler implements PendingConnection } } - ch.write( new PacketFCEncryptionResponse() ); - Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, shared ); Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, shared ); + ch.write( new PacketFCEncryptionResponse() ); + ch.config().setAutoRead( false ); ch.pipeline().addBefore( "decoder", "cipher", new CipherCodec( encrypt, decrypt ) ); thisState = InitialHandler.State.LOGIN; diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index e8c9eefc..04e5e8c9 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -1,6 +1,8 @@ package net.md_5.bungee.connection; +import io.netty.buffer.ByteBuf; import lombok.RequiredArgsConstructor; +import net.md_5.bungee.EntityMap; import net.md_5.bungee.UserConnection; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.event.ChatEvent; @@ -17,6 +19,13 @@ public class UpstreamBridge extends PacketHandler private final ProxyServer bungee; private final UserConnection con; + @Override + public void handle(ByteBuf buf) throws Exception + { + EntityMap.rewrite( buf, con.clientEntityId, con.serverEntityId ); + con.getServer().getCh().write( buf ); + } + @Override public void handle(Packet0KeepAlive alive) throws Exception { diff --git a/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java b/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java index 9fd54eac..530b455e 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java @@ -33,9 +33,6 @@ public class CipherCodec extends ByteToByteCodec { heapOut = ctx.alloc().heapBuffer(); } - System.out.println( "e) in: " + in ); - System.out.println( "e) heapOut: " + heapOut ); - System.out.println( "e) out: " + out ); cipher( encrypt, in, heapOut ); out.writeBytes( heapOut ); heapOut.discardSomeReadBytes(); @@ -44,9 +41,6 @@ public class CipherCodec extends ByteToByteCodec @Override public void decode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { - System.out.println( "d) in: " + in ); - System.out.println( "d) heapOut: " + heapOut ); - System.out.println( "d) out: " + out ); cipher( decrypt, in, out ); } 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 b27d0f52..9292bc5e 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 @@ -51,17 +51,15 @@ public class HandlerBoss extends ChannelInboundMessageHandlerAdapter if ( packet != null ) { packet.handle( handler ); - } else - { - handler.handle( msg ); } + handler.handle( msg ); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - System.out.println( handler + " " + Util.exception( cause ) ); + cause.printStackTrace(); if ( ctx.channel().isActive() ) { ctx.close(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet0KeepAlive.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet0KeepAlive.java index 4b0ba51e..e8e77623 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet0KeepAlive.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet0KeepAlive.java @@ -11,7 +11,7 @@ public class Packet0KeepAlive extends DefinedPacket public int id; - public Packet0KeepAlive(ByteBuf buf) + Packet0KeepAlive(ByteBuf buf) { super( 0x00, buf ); id = readInt(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java index b1a4ec02..533cd4db 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java @@ -29,7 +29,7 @@ public class Packet1Login extends DefinedPacket writeByte( maxPlayers ); } - public Packet1Login(ByteBuf buf) + Packet1Login(ByteBuf buf) { super( 0x01, buf ); this.entityId = readInt(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java index e5a54c59..2a494926 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java @@ -23,7 +23,7 @@ public class Packet2Handshake extends DefinedPacket writeInt( port ); } - public Packet2Handshake(ByteBuf buf) + Packet2Handshake(ByteBuf buf) { super( 0x02, buf ); this.procolVersion = readByte(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java index 0791b68e..7ad898df 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java @@ -17,7 +17,7 @@ public class Packet3Chat extends DefinedPacket writeString( message ); } - public Packet3Chat(ByteBuf buf) + Packet3Chat(ByteBuf buf) { super( 0x03, buf ); this.message = readString(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java index 66231a1f..a086d8e6 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java @@ -27,7 +27,7 @@ public class Packet9Respawn extends DefinedPacket writeString( levelType ); } - public Packet9Respawn(ByteBuf buf) + Packet9Respawn(ByteBuf buf) { super( 0x09, buf ); this.dimension = readInt(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketC9PlayerListItem.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketC9PlayerListItem.java index 655b31de..13ba4694 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketC9PlayerListItem.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketC9PlayerListItem.java @@ -13,7 +13,7 @@ public class PacketC9PlayerListItem extends DefinedPacket public boolean online; public int ping; - public PacketC9PlayerListItem(ByteBuf buf) + PacketC9PlayerListItem(ByteBuf buf) { super( 0xC9, buf ); username = readString(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketCDClientStatus.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketCDClientStatus.java index 47887656..9773bc31 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketCDClientStatus.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketCDClientStatus.java @@ -22,7 +22,7 @@ public class PacketCDClientStatus extends DefinedPacket writeByte( payload ); } - public PacketCDClientStatus(ByteBuf buf) + PacketCDClientStatus(ByteBuf buf) { super( 0xCD, buf ); } diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFAPluginMessage.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFAPluginMessage.java index f12b0fb0..d7cc5ee0 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFAPluginMessage.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFAPluginMessage.java @@ -21,7 +21,7 @@ public class PacketFAPluginMessage extends DefinedPacket this.data = data; } - public PacketFAPluginMessage(ByteBuf buf) + PacketFAPluginMessage(ByteBuf buf) { super( 0xFA, buf ); this.tag = readString(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFCEncryptionResponse.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFCEncryptionResponse.java index 6670e6e5..38f885a8 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFCEncryptionResponse.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFCEncryptionResponse.java @@ -26,7 +26,7 @@ public class PacketFCEncryptionResponse extends DefinedPacket writeArray( verifyToken ); } - public PacketFCEncryptionResponse(ByteBuf buf) + PacketFCEncryptionResponse(ByteBuf buf) { super( 0xFC, buf ); this.sharedSecret = readArray(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFDEncryptionRequest.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFDEncryptionRequest.java index fa6e63f2..a6df1164 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFDEncryptionRequest.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFDEncryptionRequest.java @@ -24,7 +24,7 @@ public class PacketFDEncryptionRequest extends DefinedPacket this.verifyToken = verifyToken; } - public PacketFDEncryptionRequest(ByteBuf buf) + PacketFDEncryptionRequest(ByteBuf buf) { super( 0xFD, buf ); serverId = readString(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFEPing.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFEPing.java index 88e31929..1df353dc 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFEPing.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFEPing.java @@ -11,7 +11,7 @@ public class PacketFEPing extends DefinedPacket public byte version; - public PacketFEPing(ByteBuf buffer) + PacketFEPing(ByteBuf buffer) { super( 0xFE, buffer ); version = readByte(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFFKick.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFFKick.java index 7eeb12c2..d7d80b74 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFFKick.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFFKick.java @@ -17,7 +17,7 @@ public class PacketFFKick extends DefinedPacket writeString( message ); } - public PacketFFKick(ByteBuf buf) + PacketFFKick(ByteBuf buf) { super( 0xFF, buf ); this.message = readString(); diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java index e5462daf..f487f641 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java @@ -6,11 +6,6 @@ import io.netty.channel.Channel; public abstract class PacketHandler { - private void nop(Object msg) - { - throw new UnsupportedOperationException( "No handler defined for packet " + msg.getClass() ); - } - public void connected(Channel channel) throws Exception { } @@ -25,66 +20,53 @@ public abstract class PacketHandler public void handle(ByteBuf buf) throws Exception { - nop( buf ); } public void handle(Packet0KeepAlive alive) throws Exception { - nop( alive ); } public void handle(Packet1Login login) throws Exception { - nop( login ); } public void handle(Packet2Handshake handshake) throws Exception { - nop( handshake ); } public void handle(Packet3Chat chat) throws Exception { - nop( chat ); } public void handle(Packet9Respawn respawn) throws Exception { - nop( respawn ); } public void handle(PacketC9PlayerListItem playerList) throws Exception { - nop( playerList ); } public void handle(PacketCDClientStatus clientStatus) throws Exception { - nop( clientStatus ); } public void handle(PacketFAPluginMessage pluginMessage) throws Exception { - nop( pluginMessage ); } public void handle(PacketFCEncryptionResponse encryptResponse) throws Exception { - nop( encryptResponse ); } public void handle(PacketFDEncryptionRequest encryptRequest) throws Exception { - nop( encryptRequest ); } public void handle(PacketFEPing ping) throws Exception { - nop( ping ); } public void handle(PacketFFKick kick) throws Exception { - nop( kick ); } } From 504f703fbb2ba5fb947222fdc3b8c4afe4e32a67 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 9 Mar 2013 12:35:32 +1100 Subject: [PATCH 16/31] This is so tiring --- .../src/main/java/net/md_5/bungee/EntityMap.java | 2 +- .../java/net/md_5/bungee/ServerConnector.java | 3 +++ .../md_5/bungee/connection/CancelSendSignal.java | 2 +- .../md_5/bungee/connection/InitialHandler.java | 3 +++ .../md_5/bungee/connection/UpstreamBridge.java | 12 +++++++++++- .../java/net/md_5/bungee/netty/HandlerBoss.java | 16 +++++++++++++--- .../net/md_5/bungee/netty/PipelineUtils.java | 9 ++++----- 7 files changed, 36 insertions(+), 11 deletions(-) diff --git a/proxy/src/main/java/net/md_5/bungee/EntityMap.java b/proxy/src/main/java/net/md_5/bungee/EntityMap.java index 5a7a4b36..b3637c30 100644 --- a/proxy/src/main/java/net/md_5/bungee/EntityMap.java +++ b/proxy/src/main/java/net/md_5/bungee/EntityMap.java @@ -117,7 +117,7 @@ public class EntityMap public static void rewrite(ByteBuf packet, int oldId, int newId) { - int packetId = packet.getUnsignedShort( 0 ); + int packetId = packet.getUnsignedByte( 0 ); if ( packetId == 0x1D ) { // bulk entity for ( int pos = 2; pos < packet.writerIndex(); pos += 4 ) 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 ebe5de79..40995a8d 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -7,6 +7,7 @@ import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.event.ServerConnectedEvent; +import net.md_5.bungee.connection.CancelSendSignal; import net.md_5.bungee.connection.DownstreamBridge; import net.md_5.bungee.netty.HandlerBoss; import net.md_5.bungee.packet.DefinedPacket; @@ -100,6 +101,8 @@ public class ServerConnector extends PacketHandler } thisState = State.FINISHED; + + throw new CancelSendSignal(); } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/connection/CancelSendSignal.java b/proxy/src/main/java/net/md_5/bungee/connection/CancelSendSignal.java index 765b4bc8..fce136c6 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/CancelSendSignal.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/CancelSendSignal.java @@ -1,6 +1,6 @@ package net.md_5.bungee.connection; -class CancelSendSignal extends Error +public class CancelSendSignal extends Error { @Override 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 65195ad2..6d8335c5 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 @@ -30,6 +30,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.LoginEvent; import net.md_5.bungee.api.event.ProxyPingEvent; import net.md_5.bungee.netty.CipherCodec; +import net.md_5.bungee.netty.HandlerBoss; import net.md_5.bungee.netty.PacketDecoder; import net.md_5.bungee.packet.Packet1Login; import net.md_5.bungee.packet.Packet2Handshake; @@ -198,6 +199,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection Preconditions.checkState( thisState == State.LOGIN, "Not expecting LOGIN" ); UserConnection userCon = new UserConnection( (BungeeCord) bungee, ch, this, handshake, forgeLogin, loginMessages ); + ch.pipeline().get( HandlerBoss.class ).setHandler( new UpstreamBridge( bungee, userCon ) ); + ServerInfo server = bungee.getReconnectHandler().getServer( userCon ); userCon.connect( server ); diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index 04e5e8c9..3ad9461f 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -8,6 +8,7 @@ import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.event.ChatEvent; import net.md_5.bungee.api.event.PluginMessageEvent; import net.md_5.bungee.packet.Packet0KeepAlive; +import net.md_5.bungee.packet.Packet1Login; import net.md_5.bungee.packet.Packet3Chat; import net.md_5.bungee.packet.PacketFAPluginMessage; import net.md_5.bungee.packet.PacketHandler; @@ -23,7 +24,16 @@ public class UpstreamBridge extends PacketHandler public void handle(ByteBuf buf) throws Exception { EntityMap.rewrite( buf, con.clientEntityId, con.serverEntityId ); - con.getServer().getCh().write( buf ); + if ( con.getServer() != null ) + { + con.getServer().getCh().write( buf ); + } + } + + @Override + public void handle(Packet1Login login) throws Exception + { + super.handle( login ); //To change body of generated methods, choose Tools | Templates. } @Override 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 9292bc5e..22728baf 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 @@ -4,7 +4,7 @@ import com.google.common.base.Preconditions; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundMessageHandlerAdapter; -import net.md_5.bungee.Util; +import net.md_5.bungee.connection.CancelSendSignal; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.PacketHandler; @@ -48,11 +48,21 @@ public class HandlerBoss extends ChannelInboundMessageHandlerAdapter if ( handler != null && ctx.channel().isActive() ) { DefinedPacket packet = DefinedPacket.packet( msg ); + boolean sendPacket = true; if ( packet != null ) { - packet.handle( handler ); + try + { + packet.handle( handler ); + } catch ( CancelSendSignal ex ) + { + sendPacket = false; + } + } + if ( sendPacket ) + { + handler.handle( msg ); } - handler.handle( msg ); } } 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 c54227b8..d1977f56 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,15 +1,14 @@ package net.md_5.bungee.netty; -import io.netty.bootstrap.Bootstrap; +import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelException; -import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; -import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.channel.ChannelOutboundMessageHandlerAdapter; 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.ServerConnector; @@ -46,7 +45,7 @@ public class PipelineUtils }; public static final Base BASE = new Base(); - public final static class Base extends ChannelInitializer + public final static class Base extends ChannelInitializer { @Override From 65255028362605e0993bf4c04d02ab858d054391 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 9 Mar 2013 14:19:12 +1100 Subject: [PATCH 17/31] We can login now. Kindof. *wipes sweat off brow. --- pom.xml | 2 +- protocol/pom.xml | 5 +-- proxy/pom.xml | 2 +- .../java/net/md_5/bungee/ServerConnector.java | 9 +++--- .../bungee/connection/DownstreamBridge.java | 3 ++ .../bungee/connection/InitialHandler.java | 20 ++++++------ .../bungee/connection/UpstreamBridge.java | 8 ++--- .../net/md_5/bungee/netty/CipherCodec.java | 31 ++----------------- .../net/md_5/bungee/netty/HandlerBoss.java | 2 +- .../net/md_5/bungee/netty/PacketDecoder.java | 5 --- .../net/md_5/bungee/netty/PipelineUtils.java | 2 ++ .../net/md_5/bungee/packet/DefinedPacket.java | 4 +++ 12 files changed, 34 insertions(+), 59 deletions(-) diff --git a/pom.xml b/pom.xml index 2b9a2e4b..fc5c3e48 100644 --- a/pom.xml +++ b/pom.xml @@ -92,7 +92,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.0 + 2.5.1 1.7 1.7 diff --git a/protocol/pom.xml b/protocol/pom.xml index 6b972fe5..e624fdcf 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -21,8 +21,9 @@ io.netty - netty-buffer - 4.0.0.Beta2 + + netty-all + 4.0.0.Beta3-SNAPSHOT provided diff --git a/proxy/pom.xml b/proxy/pom.xml index 577546fc..8f718f1a 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -22,7 +22,7 @@ io.netty netty-all - 4.0.0.Beta2 + 4.0.0.Beta3-SNAPSHOT net.md-5 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 40995a8d..3bdab4b9 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -79,7 +79,7 @@ public class ServerConnector extends PacketHandler login.difficulty, login.unused, (byte) user.getPendingConnection().getListener().getTabListSize() ); - ch.write( modLogin ); + user.ch.write( modLogin ); ch.write( BungeeCord.getInstance().registerChannels() ); } else { @@ -88,15 +88,16 @@ public class ServerConnector extends PacketHandler user.sendPacket( Packet9Respawn.DIM2_SWITCH ); user.serverEntityId = login.entityId; - ch.write( new Packet9Respawn( login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType ) ); + user.ch.write( new Packet9Respawn( login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType ) ); - // Add to new server - target.addPlayer( user ); // Remove from old servers user.getServer().disconnect( "Quitting" ); user.getServer().getInfo().removePlayer( user ); } + // Add to new server + target.addPlayer( user ); + ch.pipeline().get( HandlerBoss.class ).setHandler( new DownstreamBridge( bungee, user ) ); } 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 d426690b..1922e444 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 @@ -7,6 +7,7 @@ import io.netty.buffer.ByteBuf; import lombok.RequiredArgsConstructor; import net.md_5.bungee.EntityMap; import net.md_5.bungee.UserConnection; +import net.md_5.bungee.Util; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; @@ -30,6 +31,8 @@ public class DownstreamBridge extends PacketHandler public void handle(ByteBuf buf) throws Exception { EntityMap.rewrite( buf, con.serverEntityId, con.clientEntityId ); + System.out.println( "Got packet from server: " + Util.hex( buf.getUnsignedByte( 0 ) ) ); + System.out.println( buf ); con.ch.write( buf ); } 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 6d8335c5..c4b76fb4 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 @@ -92,18 +92,18 @@ public class InitialHandler extends PacketHandler implements PendingConnection @Override public void handle(PacketFEPing ping) throws Exception { - ServerPing pingevent = new ServerPing( BungeeCord.PROTOCOL_VERSION, BungeeCord.GAME_VERSION, + ServerPing response = new ServerPing( bungee.getProtocolVersion(), bungee.getGameVersion(), listener.getMotd(), bungee.getPlayers().size(), listener.getMaxPlayers() ); - pingevent = bungee.getPluginManager().callEvent( new ProxyPingEvent( this, pingevent ) ).getResponse(); + response = bungee.getPluginManager().callEvent( new ProxyPingEvent( this, response ) ).getResponse(); - String response = ChatColor.COLOR_CHAR + "1" - + "\00" + pingevent.getProtocolVersion() - + "\00" + pingevent.getGameVersion() - + "\00" + pingevent.getMotd() - + "\00" + pingevent.getCurrentPlayers() - + "\00" + pingevent.getMaxPlayers(); - disconnect( response ); + String kickMessage = ChatColor.DARK_BLUE + + "\00" + response.getProtocolVersion() + + "\00" + response.getGameVersion() + + "\00" + response.getMotd() + + "\00" + response.getCurrentPlayers() + + "\00" + response.getMaxPlayers(); + disconnect( kickMessage ); } @Override @@ -181,7 +181,6 @@ public class InitialHandler extends PacketHandler implements PendingConnection Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, shared ); Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, shared ); ch.write( new PacketFCEncryptionResponse() ); - ch.config().setAutoRead( false ); ch.pipeline().addBefore( "decoder", "cipher", new CipherCodec( encrypt, decrypt ) ); thisState = InitialHandler.State.LOGIN; @@ -205,6 +204,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection userCon.connect( server ); thisState = State.FINISHED; + throw new CancelSendSignal(); } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index 3ad9461f..6f2dd6ad 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -4,6 +4,7 @@ import io.netty.buffer.ByteBuf; import lombok.RequiredArgsConstructor; import net.md_5.bungee.EntityMap; import net.md_5.bungee.UserConnection; +import net.md_5.bungee.Util; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.event.ChatEvent; import net.md_5.bungee.api.event.PluginMessageEvent; @@ -24,18 +25,13 @@ public class UpstreamBridge extends PacketHandler public void handle(ByteBuf buf) throws Exception { EntityMap.rewrite( buf, con.clientEntityId, con.serverEntityId ); + System.out.println( "Got packet from client: " + Util.hex( buf.getUnsignedByte( 0 ) ) ); if ( con.getServer() != null ) { con.getServer().getCh().write( buf ); } } - @Override - public void handle(Packet1Login login) throws Exception - { - super.handle( login ); //To change body of generated methods, choose Tools | Templates. - } - @Override public void handle(Packet0KeepAlive alive) throws Exception { diff --git a/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java b/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java index 530b455e..565ee157 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java @@ -18,7 +18,6 @@ public class CipherCodec extends ByteToByteCodec private Cipher encrypt; private Cipher decrypt; - private ByteBuf heapOut; public CipherCodec(Cipher encrypt, Cipher decrypt) { @@ -29,13 +28,7 @@ public class CipherCodec extends ByteToByteCodec @Override public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { - if ( heapOut == null ) - { - heapOut = ctx.alloc().heapBuffer(); - } - cipher( encrypt, in, heapOut ); - out.writeBytes( heapOut ); - heapOut.discardSomeReadBytes(); + cipher( encrypt, in, out ); } @Override @@ -44,25 +37,6 @@ public class CipherCodec extends ByteToByteCodec cipher( decrypt, in, out ); } - @Override - public void freeInboundBuffer(ChannelHandlerContext ctx) throws Exception - { - super.freeInboundBuffer( ctx ); - decrypt = null; - } - - @Override - public void freeOutboundBuffer(ChannelHandlerContext ctx) throws Exception - { - super.freeOutboundBuffer( ctx ); - if ( heapOut != null ) - { - heapOut.release(); - heapOut = null; - } - encrypt = null; - } - private void cipher(Cipher cipher, ByteBuf in, ByteBuf out) throws ShortBufferException { int available = in.readableBytes(); @@ -71,8 +45,7 @@ public class CipherCodec extends ByteToByteCodec { out.capacity( outputSize ); } - // TODO: Try and make this use out.nioBuffer() - int processed = cipher.update( in.array(), in.arrayOffset() + in.readerIndex(), available, out.array(), out.arrayOffset() + out.writerIndex() ); + int processed = cipher.update( in.nioBuffer(), out.nioBuffer( out.readerIndex(), outputSize ) ); in.readerIndex( in.readerIndex() + processed ); out.writerIndex( out.writerIndex() + processed ); } 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 22728baf..9e97f9e2 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 @@ -43,7 +43,7 @@ public class HandlerBoss extends ChannelInboundMessageHandlerAdapter } @Override - protected void messageReceived(ChannelHandlerContext ctx, ByteBuf msg) throws Exception + public void messageReceived(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { if ( handler != null && ctx.channel().isActive() ) { diff --git a/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java b/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java index 6d12c2d7..696f0148 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/PacketDecoder.java @@ -3,11 +3,9 @@ package net.md_5.bungee.netty; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ReplayingDecoder; -import java.io.IOException; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; -import net.md_5.bungee.Util; import net.md_5.bungee.protocol.netty.PacketReader; /** @@ -30,10 +28,7 @@ public class PacketDecoder extends ReplayingDecoder protected ByteBuf decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { int startIndex = in.readerIndex(); - PacketReader.readPacket( in, protocol ); - - System.out.println( Util.hex( in.getUnsignedByte( 0 ) ) ); return in.copy( startIndex, in.readerIndex() - startIndex ); } } 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 d1977f56..f5f7e443 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 @@ -2,6 +2,7 @@ package net.md_5.bungee.netty; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; +import io.netty.channel.ChannelConfig; import io.netty.channel.ChannelException; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; @@ -32,6 +33,7 @@ public class PipelineUtils { BASE.initChannel( ch ); ch.pipeline().get( HandlerBoss.class ).setHandler( new InitialHandler( ProxyServer.getInstance(), ch.attr( LISTENER ).get() ) ); + ch.config().setDefaultHandlerByteBufType( ChannelConfig.ChannelHandlerByteBufType.HEAP ); } }; public static final ChannelInitializer CLIENT = new ChannelInitializer() diff --git a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java index f4a4e44c..421fe87d 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java @@ -104,7 +104,11 @@ public abstract class DefinedPacket implements ByteBuf if ( constructor != null ) { + buf.markReaderIndex(); + buf.markWriterIndex(); ret = constructor.newInstance( buf ); + buf.resetReaderIndex(); + buf.resetWriterIndex(); } } catch ( IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException ex ) { From f0a19e0f45f050e7d9e89c9a32b03079f7d44398 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 9 Mar 2013 14:23:40 +1100 Subject: [PATCH 18/31] Small cleanup of packet classes --- .../main/java/net/md_5/bungee/packet/DefinedPacket.java | 2 -- .../src/main/java/net/md_5/bungee/packet/Packet1Login.java | 7 +++++++ .../main/java/net/md_5/bungee/packet/Packet2Handshake.java | 4 ++++ .../src/main/java/net/md_5/bungee/packet/Packet3Chat.java | 1 + .../main/java/net/md_5/bungee/packet/Packet9Respawn.java | 5 +++++ .../java/net/md_5/bungee/packet/PacketCDClientStatus.java | 4 ++++ .../net/md_5/bungee/packet/PacketFCEncryptionResponse.java | 2 ++ 7 files changed, 23 insertions(+), 2 deletions(-) diff --git a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java index 421fe87d..e8d0914c 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java @@ -105,10 +105,8 @@ public abstract class DefinedPacket implements ByteBuf if ( constructor != null ) { buf.markReaderIndex(); - buf.markWriterIndex(); ret = constructor.newInstance( buf ); buf.resetReaderIndex(); - buf.resetWriterIndex(); } } catch ( IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException ex ) { diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java index 533cd4db..d8bb34bd 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet1Login.java @@ -27,6 +27,13 @@ public class Packet1Login extends DefinedPacket writeByte( difficulty ); writeByte( unused ); writeByte( maxPlayers ); + this.entityId = entityId; + this.levelType = levelType; + this.gameMode = gameMode; + this.dimension = dimension; + this.difficulty = difficulty; + this.unused = unused; + this.maxPlayers = maxPlayers; } Packet1Login(ByteBuf buf) diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java index 2a494926..0908a8db 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet2Handshake.java @@ -21,6 +21,10 @@ public class Packet2Handshake extends DefinedPacket writeString( username ); writeString( host ); writeInt( port ); + this.procolVersion = protocolVersion; + this.username = username; + this.host = host; + this.port = port; } Packet2Handshake(ByteBuf buf) diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java index 7ad898df..f9de2991 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet3Chat.java @@ -15,6 +15,7 @@ public class Packet3Chat extends DefinedPacket { super( 0x03 ); writeString( message ); + this.message = message; } Packet3Chat(ByteBuf buf) diff --git a/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java b/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java index a086d8e6..49aa371d 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/Packet9Respawn.java @@ -25,6 +25,11 @@ public class Packet9Respawn extends DefinedPacket writeByte( gameMode ); writeShort( worldHeight ); writeString( levelType ); + this.dimension = dimension; + this.difficulty = difficulty; + this.gameMode = gameMode; + this.worldHeight = worldHeight; + this.levelType = levelType; } Packet9Respawn(ByteBuf buf) diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketCDClientStatus.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketCDClientStatus.java index 9773bc31..1084c9ad 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketCDClientStatus.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketCDClientStatus.java @@ -9,6 +9,10 @@ import lombok.ToString; public class PacketCDClientStatus extends DefinedPacket { + /** + * Represents the packet the client sends to the server when it is ready to + * login. + */ public static PacketCDClientStatus CLIENT_LOGIN = new PacketCDClientStatus( (byte) 0 ); /** diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketFCEncryptionResponse.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketFCEncryptionResponse.java index 38f885a8..f98d7e7d 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketFCEncryptionResponse.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketFCEncryptionResponse.java @@ -24,6 +24,8 @@ public class PacketFCEncryptionResponse extends DefinedPacket super( 0xFC ); writeArray( sharedSecret ); writeArray( verifyToken ); + this.sharedSecret = sharedSecret; + this.verifyToken = verifyToken; } PacketFCEncryptionResponse(ByteBuf buf) From f0766ebcfbd852ca118a8fc57a0efa1e61e8e3bd Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 9 Mar 2013 14:27:24 +1100 Subject: [PATCH 19/31] Bridge packets both ways. --- proxy/src/main/java/net/md_5/bungee/ServerConnector.java | 1 + proxy/src/main/java/net/md_5/bungee/UserConnection.java | 4 +++- .../main/java/net/md_5/bungee/connection/UpstreamBridge.java | 1 - 3 files changed, 4 insertions(+), 2 deletions(-) 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 3bdab4b9..5b47bf0b 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -98,6 +98,7 @@ public class ServerConnector extends PacketHandler // Add to new server target.addPlayer( user ); + user.setServer( server ); ch.pipeline().get( HandlerBoss.class ).setHandler( new DownstreamBridge( bungee, user ) ); } 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 36cf93e3..b189387e 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -14,6 +14,7 @@ import java.util.Collections; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; +import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import lombok.Synchronized; @@ -33,13 +34,14 @@ public final class UserConnection implements ProxiedPlayer public final Packet2Handshake handshake; private final ProxyServer bungee; - public final Channel ch; + public final Channel ch; final Packet1Login forgeLogin; final List loginMessages; public Queue packetQueue = new ConcurrentLinkedQueue<>(); @Getter private final PendingConnection pendingConnection; @Getter + @Setter(AccessLevel.PACKAGE) private ServerConnection server; // reconnect stuff public int clientEntityId; diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index 6f2dd6ad..6a807df7 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -9,7 +9,6 @@ import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.event.ChatEvent; import net.md_5.bungee.api.event.PluginMessageEvent; import net.md_5.bungee.packet.Packet0KeepAlive; -import net.md_5.bungee.packet.Packet1Login; import net.md_5.bungee.packet.Packet3Chat; import net.md_5.bungee.packet.PacketFAPluginMessage; import net.md_5.bungee.packet.PacketHandler; From 0c69814db7dd42982228194ec41c8b38f51150c3 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 9 Mar 2013 14:29:54 +1100 Subject: [PATCH 20/31] Make sendMessage work again --- proxy/src/main/java/net/md_5/bungee/UserConnection.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) 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 b189387e..28c1b7b6 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -12,8 +12,6 @@ import java.net.InetSocketAddress; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; @@ -37,7 +35,6 @@ public final class UserConnection implements ProxiedPlayer public final Channel ch; final Packet1Login forgeLogin; final List loginMessages; - public Queue packetQueue = new ConcurrentLinkedQueue<>(); @Getter private final PendingConnection pendingConnection; @Getter @@ -162,7 +159,7 @@ public final class UserConnection implements ProxiedPlayer @Override public void sendMessage(String message) { - packetQueue.add( new Packet3Chat( message ) ); + ch.write( new Packet3Chat( message ) ); } @Override From b4d104d258a6316c154515c2e2d5ce4be467971b Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 9 Mar 2013 14:31:39 +1100 Subject: [PATCH 21/31] *actually compile (wire up the broadcast method) --- proxy/src/main/java/net/md_5/bungee/BungeeCord.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a670eadf..ba7d1709 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -255,7 +255,7 @@ public class BungeeCord extends ProxyServer { for ( UserConnection con : connections.values() ) { - con.packetQueue.add( packet ); + con.sendPacket( packet ); } } From 0ce02251d4780d5197b5451a4649296688ff4a94 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 9 Mar 2013 16:35:59 +1100 Subject: [PATCH 22/31] Start work on a little spit and polish, with cleaner exceptions. --- .../java/net/md_5/bungee/BungeeServerInfo.java | 17 ++++++++++++++++- .../java/net/md_5/bungee/ServerConnector.java | 8 +++++++- .../java/net/md_5/bungee/UserConnection.java | 5 +++++ .../bungee/connection/DownstreamBridge.java | 8 ++++++++ .../md_5/bungee/connection/InitialHandler.java | 6 ++++++ .../net/md_5/bungee/connection/PingHandler.java | 8 ++++++++ .../md_5/bungee/connection/UpstreamBridge.java | 6 ++++++ .../java/net/md_5/bungee/netty/HandlerBoss.java | 13 ++++++++++++- .../net/md_5/bungee/packet/PacketHandler.java | 3 +++ .../net/md_5/bungee/tablist/GlobalTabList.java | 2 +- .../bungee/tablist/ServerUniqueTabList.java | 2 +- 11 files changed, 73 insertions(+), 5 deletions(-) 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 5cd5ca33..8f5ca6bb 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java @@ -1,6 +1,9 @@ package net.md_5.bungee; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelOption; import io.netty.channel.socket.nio.NioSocketChannel; import java.net.InetSocketAddress; import java.util.Queue; @@ -48,8 +51,20 @@ public class BungeeServerInfo extends ServerInfo .channel( NioSocketChannel.class ) .group( BungeeCord.getInstance().eventLoops ) .handler( PipelineUtils.BASE ) + .option( ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000 ) // TODO: Configurable .remoteAddress( getAddress() ) .connect() - .channel().pipeline().get( HandlerBoss.class ).setHandler( new PingHandler( callback ) ); + .addListener( new ChannelFutureListener() + { + @Override + public void operationComplete(ChannelFuture future) throws Exception + { + if ( !future.isSuccess() ) + { + callback.done( null, future.cause() ); + } + } + } ) + .channel().pipeline().get( HandlerBoss.class ).setHandler( new PingHandler( this, 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 5b47bf0b..1b1594fd 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -99,7 +99,7 @@ public class ServerConnector extends PacketHandler target.addPlayer( user ); user.setServer( server ); - ch.pipeline().get( HandlerBoss.class ).setHandler( new DownstreamBridge( bungee, user ) ); + ch.pipeline().get( HandlerBoss.class ).setHandler( new DownstreamBridge( bungee, user, server ) ); } thisState = State.FINISHED; @@ -119,4 +119,10 @@ public class ServerConnector extends PacketHandler { throw new KickException( kick.message ); } + + @Override + public String toString() + { + return "[" + user.getName() + "] <-> ServerConnector [" + target.getName() + "]"; + } } 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 28c1b7b6..58288ef5 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -7,6 +7,7 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; import io.netty.channel.socket.nio.NioSocketChannel; import java.net.InetSocketAddress; import java.util.Collection; @@ -114,6 +115,7 @@ public final class UserConnection implements ProxiedPlayer ch.pipeline().get( HandlerBoss.class ).setHandler( new ServerConnector( bungee, UserConnection.this, target ) ); } } ) + .option( ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000 ) // TODO: Configurable .remoteAddress( target.getAddress() ) .connect().addListener( new ChannelFutureListener() { @@ -128,6 +130,9 @@ public final class UserConnection implements ProxiedPlayer { sendMessage( ChatColor.RED + "Could not connect to target server, you have been moved to the default server" ); connect( def, false ); + } else + { + disconnect( "Server down, could not connect to default!" ); } } } 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 1922e444..aa9a7ee4 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 @@ -11,6 +11,7 @@ import net.md_5.bungee.Util; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.connection.Server; import net.md_5.bungee.api.event.ChatEvent; import net.md_5.bungee.api.event.PluginMessageEvent; import net.md_5.bungee.packet.Packet0KeepAlive; @@ -26,6 +27,7 @@ public class DownstreamBridge extends PacketHandler private final ProxyServer bungee; private final UserConnection con; + private final Server server; @Override public void handle(ByteBuf buf) throws Exception @@ -196,4 +198,10 @@ public class DownstreamBridge extends PacketHandler con.disconnect( "[Kicked] " + kick.message ); throw new CancelSendSignal(); } + + @Override + public String toString() + { + return "[" + con.getName() + "] <-> DownstreamBridge <-> [" + server.getInfo().getName() + "]"; + } } 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 c4b76fb4..8ed41ee2 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 @@ -240,4 +240,10 @@ public class InitialHandler extends PacketHandler implements PendingConnection { return (InetSocketAddress) ch.remoteAddress(); } + + @Override + public String toString() + { + return "[" + ( ( getName() != null ) ? getName() : getAddress() ) + "] <-> InitialHandler"; + } } diff --git a/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java index ff4af4d0..3ad97380 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java @@ -6,6 +6,7 @@ import io.netty.channel.Channel; import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.Callback; import net.md_5.bungee.api.ServerPing; +import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.packet.PacketFFKick; import net.md_5.bungee.packet.PacketHandler; @@ -13,6 +14,7 @@ import net.md_5.bungee.packet.PacketHandler; public class PingHandler extends PacketHandler { + private final ServerInfo target; private final Callback callback; private static final ByteBuf pingBuf = Unpooled.wrappedBuffer( new byte[] { @@ -38,4 +40,10 @@ public class PingHandler extends PacketHandler ServerPing ping = new ServerPing( Byte.parseByte( split[1] ), split[2], split[3], Integer.parseInt( split[4] ), Integer.parseInt( split[5] ) ); callback.done( ping, null ); } + + @Override + public String toString() + { + return "[Ping Handler] -> " + target.getName(); + } } diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index 6a807df7..f099ce46 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -75,4 +75,10 @@ public class UpstreamBridge extends PacketHandler throw new CancelSendSignal(); } } + + @Override + public String toString() + { + return "[" + con.getName() + "] -> UpstreamBridge"; + } } 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 9e97f9e2..01c031cd 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 @@ -4,6 +4,9 @@ import com.google.common.base.Preconditions; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundMessageHandlerAdapter; +import io.netty.handler.timeout.ReadTimeoutException; +import java.util.logging.Level; +import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.connection.CancelSendSignal; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.PacketHandler; @@ -30,6 +33,7 @@ public class HandlerBoss extends ChannelInboundMessageHandlerAdapter if ( handler != null ) { handler.connected( ctx.channel() ); + ProxyServer.getInstance().getLogger().log( Level.INFO, "{0} has connected", handler ); } } @@ -38,6 +42,7 @@ public class HandlerBoss extends ChannelInboundMessageHandlerAdapter { if ( handler != null ) { + ProxyServer.getInstance().getLogger().log( Level.INFO, "{0} has disconnected", handler ); handler.disconnected( ctx.channel() ); } } @@ -69,9 +74,15 @@ public class HandlerBoss extends ChannelInboundMessageHandlerAdapter @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - cause.printStackTrace(); if ( ctx.channel().isActive() ) { + if ( cause instanceof ReadTimeoutException ) + { + ProxyServer.getInstance().getLogger().log( Level.WARNING, handler + " - read timed out" ); + } else + { + ProxyServer.getInstance().getLogger().log( Level.SEVERE, handler + " - encountered exception", cause ); + } ctx.close(); } } diff --git a/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java b/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java index f487f641..f64dfd9a 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/PacketHandler.java @@ -6,6 +6,9 @@ import io.netty.channel.Channel; public abstract class PacketHandler { + @Override + public abstract String toString(); + public void connected(Channel channel) throws Exception { } diff --git a/proxy/src/main/java/net/md_5/bungee/tablist/GlobalTabList.java b/proxy/src/main/java/net/md_5/bungee/tablist/GlobalTabList.java index eb8ae0e9..576f8874 100644 --- a/proxy/src/main/java/net/md_5/bungee/tablist/GlobalTabList.java +++ b/proxy/src/main/java/net/md_5/bungee/tablist/GlobalTabList.java @@ -22,7 +22,7 @@ public class GlobalTabList implements TabListHandler UserConnection con = (UserConnection) player; for ( ProxiedPlayer p : ProxyServer.getInstance().getPlayers() ) { - con.packetQueue.add( new PacketC9PlayerListItem( p.getDisplayName(), true, p.getPing() ) ); + con.sendPacket(new PacketC9PlayerListItem( p.getDisplayName(), true, p.getPing() ) ); } BungeeCord.getInstance().broadcast( new PacketC9PlayerListItem( player.getDisplayName(), true, player.getPing() ) ); } diff --git a/proxy/src/main/java/net/md_5/bungee/tablist/ServerUniqueTabList.java b/proxy/src/main/java/net/md_5/bungee/tablist/ServerUniqueTabList.java index 091d5cad..3c17aab5 100644 --- a/proxy/src/main/java/net/md_5/bungee/tablist/ServerUniqueTabList.java +++ b/proxy/src/main/java/net/md_5/bungee/tablist/ServerUniqueTabList.java @@ -40,7 +40,7 @@ public class ServerUniqueTabList implements TabListHandler { for ( String username : usernames ) { - ( (UserConnection) player ).packetQueue.add( new PacketC9PlayerListItem( username, false, 9999 ) ); + ( (UserConnection) player ).sendPacket(new PacketC9PlayerListItem( username, false, 9999 ) ); } usernames.clear(); } From 3be83cb5a46374f0bd057fb943b5f25eb233e3b0 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 9 Mar 2013 17:59:44 +1100 Subject: [PATCH 23/31] Disconnect when exception caught --- .../java/net/md_5/bungee/connection/DownstreamBridge.java | 6 ++++++ .../java/net/md_5/bungee/connection/UpstreamBridge.java | 6 ++++++ 2 files changed, 12 insertions(+) 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 aa9a7ee4..50f5231f 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 @@ -29,6 +29,12 @@ public class DownstreamBridge extends PacketHandler private final UserConnection con; private final Server server; + @Override + public void exception(Throwable t) throws Exception + { + con.disconnect( Util.exception( t ) ); + } + @Override public void handle(ByteBuf buf) throws Exception { diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index f099ce46..6d80ae5c 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -20,6 +20,12 @@ public class UpstreamBridge extends PacketHandler private final ProxyServer bungee; private final UserConnection con; + @Override + public void exception(Throwable t) throws Exception + { + con.disconnect( Util.exception( t ) ); + } + @Override public void handle(ByteBuf buf) throws Exception { From 6e18403cd97ccaf494308522e41b3182beddce7b Mon Sep 17 00:00:00 2001 From: md_5 Date: Mon, 11 Mar 2013 09:11:36 +1100 Subject: [PATCH 24/31] Ensure all resources are closed all the time. --- .../java/net/md_5/bungee/UserConnection.java | 13 +------------ .../bungee/connection/DownstreamBridge.java | 13 +++++++++++-- .../bungee/connection/UpstreamBridge.java | 19 ++++++++++++++++++- 3 files changed, 30 insertions(+), 15 deletions(-) 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 58288ef5..b2b74bd3 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -144,20 +144,9 @@ public final class UserConnection implements ProxiedPlayer { if ( ch.isActive() ) { - PlayerDisconnectEvent event = new PlayerDisconnectEvent( this ); - bungee.getPluginManager().callEvent( event ); - bungee.getTabListHandler().onDisconnect( this ); - bungee.getPlayers().remove( this ); - ch.write( new PacketFFKick( reason ) ); ch.close(); - - if ( server != null ) - { - server.getInfo().removePlayer( this ); - server.disconnect( "Quitting" ); - bungee.getReconnectHandler().setServer( this ); - } + server.disconnect( "Quitting" ); } } 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 50f5231f..fc161326 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 @@ -4,6 +4,7 @@ import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; import io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; import lombok.RequiredArgsConstructor; import net.md_5.bungee.EntityMap; import net.md_5.bungee.UserConnection; @@ -35,12 +36,20 @@ public class DownstreamBridge extends PacketHandler con.disconnect( Util.exception( t ) ); } + @Override + public void disconnected(Channel channel) throws Exception + { + // We lost connection to the server + server.getInfo().removePlayer( con ); + bungee.getReconnectHandler().setServer( con ); + + con.disconnect( "[Proxy] Lost connection to server D:" ); + } + @Override public void handle(ByteBuf buf) throws Exception { EntityMap.rewrite( buf, con.serverEntityId, con.clientEntityId ); - System.out.println( "Got packet from server: " + Util.hex( buf.getUnsignedByte( 0 ) ) ); - System.out.println( buf ); con.ch.write( buf ); } diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index 6d80ae5c..d71a0ef3 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -1,12 +1,14 @@ package net.md_5.bungee.connection; import io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; import lombok.RequiredArgsConstructor; import net.md_5.bungee.EntityMap; import net.md_5.bungee.UserConnection; import net.md_5.bungee.Util; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.event.ChatEvent; +import net.md_5.bungee.api.event.PlayerDisconnectEvent; import net.md_5.bungee.api.event.PluginMessageEvent; import net.md_5.bungee.packet.Packet0KeepAlive; import net.md_5.bungee.packet.Packet3Chat; @@ -26,11 +28,26 @@ public class UpstreamBridge extends PacketHandler con.disconnect( Util.exception( t ) ); } + @Override + public void disconnected(Channel channel) throws Exception + { + // We lost connection to the client + PlayerDisconnectEvent event = new PlayerDisconnectEvent( con ); + bungee.getPluginManager().callEvent( event ); + bungee.getTabListHandler().onDisconnect( con ); + bungee.getPlayers().remove( con ); + + if ( con.getServer() != null ) + { + con.getServer().disconnect( "Quitting" ); + } + + } + @Override public void handle(ByteBuf buf) throws Exception { EntityMap.rewrite( buf, con.clientEntityId, con.serverEntityId ); - System.out.println( "Got packet from client: " + Util.hex( buf.getUnsignedByte( 0 ) ) ); if ( con.getServer() != null ) { con.getServer().getCh().write( buf ); From fa5804ec86a58f0f35abcfaecb0e321f34029c3c Mon Sep 17 00:00:00 2001 From: md_5 Date: Mon, 11 Mar 2013 09:18:39 +1100 Subject: [PATCH 25/31] OMG WTF BBQ IT WORKS. LETS IRON OUT BUGS AND GET OUR RELEASE TARGET, ONLY 12 HOURS LEFT. --- api/src/main/java/net/md_5/bungee/api/connection/Server.java | 2 -- proxy/src/main/java/net/md_5/bungee/ServerConnection.java | 4 ++++ proxy/src/main/java/net/md_5/bungee/ServerConnector.java | 3 ++- .../java/net/md_5/bungee/connection/DownstreamBridge.java | 5 ++++- .../main/java/net/md_5/bungee/connection/UpstreamBridge.java | 1 - 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/api/src/main/java/net/md_5/bungee/api/connection/Server.java b/api/src/main/java/net/md_5/bungee/api/connection/Server.java index 58ae7a1f..06eb6d1a 100644 --- a/api/src/main/java/net/md_5/bungee/api/connection/Server.java +++ b/api/src/main/java/net/md_5/bungee/api/connection/Server.java @@ -1,7 +1,5 @@ package net.md_5.bungee.api.connection; -import net.md_5.bungee.api.Callback; -import net.md_5.bungee.api.ServerPing; import net.md_5.bungee.api.config.ServerInfo; /** 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 ce31f304..6ce751a5 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java @@ -4,6 +4,7 @@ import io.netty.channel.Channel; import java.net.InetSocketAddress; import lombok.Getter; import lombok.RequiredArgsConstructor; +import lombok.Setter; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.Server; import net.md_5.bungee.packet.Packet1Login; @@ -20,6 +21,9 @@ public class ServerConnection implements Server private final ServerInfo info; @Getter private final Packet1Login loginPacket; + @Getter + @Setter + private boolean isObsolete; @Override public void sendData(String channel, byte[] data) 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 1b1594fd..152b8424 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -91,11 +91,12 @@ public class ServerConnector extends PacketHandler user.ch.write( new Packet9Respawn( login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType ) ); // Remove from old servers + user.getServer().setObsolete( true ); user.getServer().disconnect( "Quitting" ); - user.getServer().getInfo().removePlayer( user ); } // Add to new server + // TODO: Move this to the connected() method of DownstreamBridge target.addPlayer( user ); user.setServer( server ); 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 fc161326..1d4223c1 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 @@ -7,6 +7,7 @@ import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import lombok.RequiredArgsConstructor; import net.md_5.bungee.EntityMap; +import net.md_5.bungee.ServerConnection; import net.md_5.bungee.UserConnection; import net.md_5.bungee.Util; import net.md_5.bungee.api.ProxyServer; @@ -28,7 +29,7 @@ public class DownstreamBridge extends PacketHandler private final ProxyServer bungee; private final UserConnection con; - private final Server server; + private final ServerConnection server; @Override public void exception(Throwable t) throws Exception @@ -43,7 +44,9 @@ public class DownstreamBridge extends PacketHandler server.getInfo().removePlayer( con ); bungee.getReconnectHandler().setServer( con ); + if (!server.isObsolete()){ con.disconnect( "[Proxy] Lost connection to server D:" ); + } } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index d71a0ef3..b503116d 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -41,7 +41,6 @@ public class UpstreamBridge extends PacketHandler { con.getServer().disconnect( "Quitting" ); } - } @Override From 0b7b87d9c3016a1585ae31271b761a3cb62d129e Mon Sep 17 00:00:00 2001 From: md_5 Date: Mon, 11 Mar 2013 09:30:49 +1100 Subject: [PATCH 26/31] Wait 100ms before closing socket to give server time to process. --- .../main/java/net/md_5/bungee/ServerConnection.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) 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 6ce751a5..9a424b98 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java @@ -1,7 +1,10 @@ package net.md_5.bungee; import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; import java.net.InetSocketAddress; +import java.util.concurrent.TimeUnit; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; @@ -37,7 +40,14 @@ public class ServerConnection implements Server if ( ch.isActive() ) { ch.write( new PacketFFKick( reason ) ); - ch.close(); + ch.eventLoop().schedule( new Runnable() + { + @Override + public void run() + { + ch.close(); + } + }, 100, TimeUnit.MILLISECONDS ); } } From 6ae5feee60841431886921dd9ad17f9fa49eb7c9 Mon Sep 17 00:00:00 2001 From: md_5 Date: Mon, 11 Mar 2013 09:39:37 +1100 Subject: [PATCH 27/31] Error handling when cannot connect to server. --- .../java/net/md_5/bungee/UserConnection.java | 19 +++++++++++++++---- .../bungee/connection/InitialHandler.java | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) 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 b2b74bd3..8fa7589b 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -13,6 +13,7 @@ import java.net.InetSocketAddress; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.logging.Level; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; @@ -95,10 +96,10 @@ public final class UserConnection implements ProxiedPlayer @Override public void connect(ServerInfo target) { - connect( target, true ); + connect( target, false ); } - private void connect(ServerInfo info, final boolean retry) + public void connect(ServerInfo info, final boolean retry) { ServerConnectEvent event = new ServerConnectEvent( this, info ); ProxyServer.getInstance().getPluginManager().callEvent( event ); @@ -132,7 +133,13 @@ public final class UserConnection implements ProxiedPlayer connect( def, false ); } else { - disconnect( "Server down, could not connect to default!" ); + if ( server == null ) + { + disconnect( "Server down, could not connect to default! " + future.cause().getClass().getName() ); + } else + { + sendMessage( ChatColor.RED + "Could not connect to target server: " + future.cause().getClass().getName() ); + } } } } @@ -144,9 +151,13 @@ public final class UserConnection implements ProxiedPlayer { if ( ch.isActive() ) { + bungee.getLogger().log( Level.INFO, "[" + getName() + "] disconnected with: " + reason ); ch.write( new PacketFFKick( reason ) ); ch.close(); - server.disconnect( "Quitting" ); + if ( server != null ) + { + server.disconnect( "Quitting" ); + } } } 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 8ed41ee2..8466d619 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 @@ -201,7 +201,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection ch.pipeline().get( HandlerBoss.class ).setHandler( new UpstreamBridge( bungee, userCon ) ); ServerInfo server = bungee.getReconnectHandler().getServer( userCon ); - userCon.connect( server ); + userCon.connect( server, true ); thisState = State.FINISHED; throw new CancelSendSignal(); From cfd10f57149d2941662e477b78c3c1f5f187c219 Mon Sep 17 00:00:00 2001 From: md_5 Date: Mon, 11 Mar 2013 09:47:42 +1100 Subject: [PATCH 28/31] Handle when user gets kicked midway through login to other server --- proxy/src/main/java/net/md_5/bungee/ServerConnector.java | 7 +++++++ .../java/net/md_5/bungee/connection/DownstreamBridge.java | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) 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 152b8424..bc21a10f 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -95,6 +95,13 @@ public class ServerConnector extends PacketHandler user.getServer().disconnect( "Quitting" ); } + // TODO: Fix this? + if ( !user.ch.isActive() ) + { + server.disconnect( "Quitting" ); + throw new IllegalStateException( "No client connected for pending server!" ); + } + // Add to new server // TODO: Move this to the connected() method of DownstreamBridge target.addPlayer( user ); 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 1d4223c1..b724b14a 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 @@ -13,7 +13,6 @@ import net.md_5.bungee.Util; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.connection.Server; import net.md_5.bungee.api.event.ChatEvent; import net.md_5.bungee.api.event.PluginMessageEvent; import net.md_5.bungee.packet.Packet0KeepAlive; @@ -44,8 +43,9 @@ public class DownstreamBridge extends PacketHandler server.getInfo().removePlayer( con ); bungee.getReconnectHandler().setServer( con ); - if (!server.isObsolete()){ - con.disconnect( "[Proxy] Lost connection to server D:" ); + if ( !server.isObsolete() ) + { + con.disconnect( "[Proxy] Lost connection to server D:" ); } } From 2e33ab1460d4c807e2611f72f756b2ac2f8e4ee7 Mon Sep 17 00:00:00 2001 From: md_5 Date: Mon, 11 Mar 2013 09:52:53 +1100 Subject: [PATCH 29/31] Remove outdated javadoc --- proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java b/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java index 565ee157..a67ab0da 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/CipherCodec.java @@ -9,9 +9,7 @@ import javax.crypto.ShortBufferException; /** * This class is a complete solution for encrypting and decoding bytes in a * Netty stream. It takes two {@link Cipher} instances, used for encryption and - * decryption respectively. As newer Netty versions never use a heap - * {@link ByteBuf} for writing to the channel, this class will always create one - * for temporary usage. + * decryption respectively. */ public class CipherCodec extends ByteToByteCodec { From 76319371f7b0c5ca981632ca90099d5eb02dfd13 Mon Sep 17 00:00:00 2001 From: md_5 Date: Mon, 11 Mar 2013 10:06:14 +1100 Subject: [PATCH 30/31] Small code / api cleanup. Need to fix kicking in general, especially in ServerConnector before release. --- .../net/md_5/bungee/api/connection/PendingConnection.java | 8 -------- .../net/md_5/bungee/api/connection/ProxiedPlayer.java | 7 ------- proxy/src/main/java/net/md_5/bungee/Logger.java | 3 +-- proxy/src/main/java/net/md_5/bungee/ServerConnection.java | 2 -- proxy/src/main/java/net/md_5/bungee/UserConnection.java | 1 - .../java/net/md_5/bungee/connection/InitialHandler.java | 4 ++-- .../main/java/net/md_5/bungee/netty/PipelineUtils.java | 3 --- 7 files changed, 3 insertions(+), 25 deletions(-) diff --git a/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java b/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java index 4c952f37..0334afc6 100644 --- a/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java +++ b/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java @@ -30,14 +30,6 @@ public interface PendingConnection extends Connection */ public InetSocketAddress getVirtualHost(); - /** - * Completely kick this user from the proxy and all of its child - * connections. - * - * @param reason the disconnect reason displayed to the player - */ - public void disconnect(String reason); - /** * Get the listener that accepted this connection. * diff --git a/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java b/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java index 0cc70ab0..b0e45598 100644 --- a/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java +++ b/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java @@ -48,13 +48,6 @@ public interface ProxiedPlayer extends Connection, CommandSender */ public int getPing(); - /** - * Disconnect (remove) this player from the proxy with the specified reason. - * - * @param reason the reason displayed to the player - */ - public void disconnect(String reason); - /** * Send a plugin message to this player. * diff --git a/proxy/src/main/java/net/md_5/bungee/Logger.java b/proxy/src/main/java/net/md_5/bungee/Logger.java index 76190f3c..aa38547d 100644 --- a/proxy/src/main/java/net/md_5/bungee/Logger.java +++ b/proxy/src/main/java/net/md_5/bungee/Logger.java @@ -3,7 +3,6 @@ package net.md_5.bungee; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; -import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.logging.FileHandler; import java.util.logging.Formatter; @@ -21,7 +20,7 @@ public class Logger extends java.util.logging.Logger public Logger() { - super( "RubberBand", null ); + super( "BungeeCord", null ); try { FileHandler handler = new FileHandler( "proxy.log", 1 << 14, 1, true ); 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 9a424b98..6a55e2c9 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java @@ -1,8 +1,6 @@ package net.md_5.bungee; import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; import java.net.InetSocketAddress; import java.util.concurrent.TimeUnit; import lombok.Getter; 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 8fa7589b..be29988a 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -23,7 +23,6 @@ import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.PendingConnection; import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.event.PlayerDisconnectEvent; import net.md_5.bungee.api.event.ServerConnectEvent; import net.md_5.bungee.netty.HandlerBoss; import net.md_5.bungee.netty.PipelineUtils; 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 8466d619..08eae435 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 @@ -184,9 +184,9 @@ public class InitialHandler extends PacketHandler implements PendingConnection ch.pipeline().addBefore( "decoder", "cipher", new CipherCodec( encrypt, decrypt ) ); thisState = InitialHandler.State.LOGIN; - } catch ( Exception ex ) + } catch ( Throwable t ) { - disconnect( "[Report to md_5 / Server Owner] " + Util.exception( ex ) ); + disconnect( "[Report to md_5 / Server Owner] " + Util.exception( t ) ); } } }.start(); 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 f5f7e443..0e128da1 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,13 +1,10 @@ package net.md_5.bungee.netty; -import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelConfig; import io.netty.channel.ChannelException; -import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; -import io.netty.channel.ChannelOutboundMessageHandlerAdapter; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.util.AttributeKey; import java.util.concurrent.TimeUnit; From 9fb814003b7bf530373d9ea1d7a80056f92692d1 Mon Sep 17 00:00:00 2001 From: md_5 Date: Mon, 11 Mar 2013 10:15:14 +1100 Subject: [PATCH 31/31] Handle kicks when trying to login to server. Now we have to be about done. --- .../main/java/net/md_5/bungee/KickException.java | 14 -------------- .../java/net/md_5/bungee/ServerConnection.java | 5 +++++ .../main/java/net/md_5/bungee/ServerConnector.java | 10 +++++++++- 3 files changed, 14 insertions(+), 15 deletions(-) delete mode 100644 proxy/src/main/java/net/md_5/bungee/KickException.java diff --git a/proxy/src/main/java/net/md_5/bungee/KickException.java b/proxy/src/main/java/net/md_5/bungee/KickException.java deleted file mode 100644 index 5b495e00..00000000 --- a/proxy/src/main/java/net/md_5/bungee/KickException.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.md_5.bungee; - -/** - * Exception, which when thrown will disconnect the player from the proxy with - * the specified message. - */ -public class KickException extends RuntimeException -{ - - public KickException(String message) - { - super( message ); - } -} 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 6a55e2c9..c74b124b 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java @@ -34,6 +34,11 @@ public class ServerConnection implements Server @Override public synchronized void disconnect(String reason) + { + disconnect( ch, reason ); + } + + static void disconnect(final Channel ch, String reason) { if ( ch.isActive() ) { 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 bc21a10f..9c138201 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -4,6 +4,7 @@ import com.google.common.base.Preconditions; import io.netty.channel.Channel; import java.util.Queue; import lombok.RequiredArgsConstructor; +import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.event.ServerConnectedEvent; @@ -125,7 +126,14 @@ public class ServerConnector extends PacketHandler @Override public void handle(PacketFFKick kick) throws Exception { - throw new KickException( kick.message ); + String message = ChatColor.RED + "Kicked whilst connecting to " + target.getName() + ": " + kick.message; + if ( user.getServer() == null ) + { + user.disconnect( message ); + } else + { + user.sendMessage( message ); + } } @Override