From 679035c3bf0da45feed2316fe1e65d813134b62f Mon Sep 17 00:00:00 2001 From: Dan Mulloy Date: Sat, 16 Jul 2016 15:46:23 -0400 Subject: [PATCH] Fix an error with wire packets Addresses #224 --- .../protocol/injector/netty/WirePacket.java | 79 ++++++++++++++++--- .../protocol/injector/WirePacketTest.java | 53 +++++++++++++ 2 files changed, 120 insertions(+), 12 deletions(-) create mode 100644 modules/ProtocolLib/src/test/java/com/comphenix/protocol/injector/WirePacketTest.java diff --git a/modules/API/src/main/java/com/comphenix/protocol/injector/netty/WirePacket.java b/modules/API/src/main/java/com/comphenix/protocol/injector/netty/WirePacket.java index 7f2ac2bc..e053d2cb 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/injector/netty/WirePacket.java +++ b/modules/API/src/main/java/com/comphenix/protocol/injector/netty/WirePacket.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import java.lang.reflect.Method; +import java.util.Arrays; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.PacketContainer; @@ -78,16 +79,7 @@ public class WirePacket { * @param output Output to write to */ public void writeId(ByteBuf output) { - checkNotNull(output, "output cannot be null!"); - // From PacketDataSerializer#d(int) - - int i = id; - while ((i & -128) != 0) { - output.writeByte(i & 127 | 128); - i >>>= 7; - } - - output.writeByte(i); + writeVarInt(output, id); } /** @@ -118,6 +110,39 @@ public class WirePacket { return buffer; } + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + + if (obj instanceof WirePacket) { + WirePacket that = (WirePacket) obj; + return this.id == that.id && + Arrays.equals(this.bytes, that.bytes); + } + + return false; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Arrays.hashCode(bytes); + result = prime * result + id; + return result; + } + + @Override + public String toString() { + return "WirePacket[id=" + id + ", bytes=" + Arrays.toString(bytes) + "]"; + } + + private static byte[] getBytes(ByteBuf buffer) { + byte[] array = new byte[buffer.readableBytes()]; + buffer.readBytes(array); + return array; + } + /** * Creates a WirePacket from an existing PacketContainer * @param packet Existing packet @@ -137,7 +162,7 @@ public class WirePacket { throw new RuntimeException("Failed to serialize packet contents.", ex); } - return new WirePacket(id, buffer.array()); + return new WirePacket(id, getBytes(buffer)); } /** @@ -162,6 +187,36 @@ public class WirePacket { throw new RuntimeException("Failed to serialize packet contents.", ex); } - return new WirePacket(id, buffer.array()); + return new WirePacket(id, getBytes(buffer)); + } + + public static void writeVarInt(ByteBuf output, int i) { + checkNotNull(output, "output cannot be null!"); + + while ((i & -128) != 0) { + output.writeByte(i & 127 | 128); + i >>>= 7; + } + + output.writeByte(i); + } + + public static int readVarInt(ByteBuf input) { + checkNotNull(input, "input cannot be null!"); + + int i = 0; + int j = 0; + + byte b0; + + do { + b0 = input.readByte(); + i |= (b0 & 127) << j++ * 7; + if (j > 5) { + throw new RuntimeException("VarInt too big"); + } + } while ((b0 & 128) == 128); + + return i; } } diff --git a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/injector/WirePacketTest.java b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/injector/WirePacketTest.java new file mode 100644 index 00000000..4cf9bed0 --- /dev/null +++ b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/injector/WirePacketTest.java @@ -0,0 +1,53 @@ +/** + * (c) 2016 dmulloy2 + */ +package com.comphenix.protocol.injector; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.comphenix.protocol.BukkitInitialization; +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.injector.netty.WirePacket; + +import io.netty.buffer.ByteBuf; + +/** + * @author dmulloy2 + */ +public class WirePacketTest { + + @BeforeClass + public static void beforeClass() { + BukkitInitialization.initializePackage(); + } + + @Test + public void testPackets() { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.CHAT); + WirePacket wire = WirePacket.fromPacket(packet); + WirePacket handle = WirePacket.fromPacket(packet.getHandle()); + assertEquals(wire, handle); + } + + @Test + public void testSerialization() { + int id = 42; + byte[] array = { 1, 3, 7, 21, 88, 67, 8 }; + + WirePacket packet = new WirePacket(id, array); + + ByteBuf buf = packet.serialize(); + + int backId = WirePacket.readVarInt(buf); + byte[] backArray = new byte[buf.readableBytes()]; + buf.readBytes(backArray); + + assertEquals(id, backId); + assertArrayEquals(array, backArray); + } +} \ No newline at end of file