From f1149b8f21ba51108fe5b7de16f417878b0b07ed Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Mon, 26 Mar 2018 22:43:23 +0300 Subject: [PATCH] Ping --- .../java/mc/core/netty/PacketDecoder.java | 14 ++++- .../java/mc/core/netty/PacketHandler.java | 4 ++ src/main/java/mc/core/netty/State.java | 8 ++- src/main/java/mc/core/netty/Utils.java | 54 ++++++++++++++++--- .../{ => packets}/HandshakeRequestPacket.java | 8 ++- .../HandshakeResponsePacket.java | 3 +- .../mc/core/netty/packets/PingPacket.java | 45 ++++++++++++++++ 7 files changed, 123 insertions(+), 13 deletions(-) rename src/main/java/mc/core/netty/{ => packets}/HandshakeRequestPacket.java (85%) rename src/main/java/mc/core/netty/{ => packets}/HandshakeResponsePacket.java (95%) create mode 100644 src/main/java/mc/core/netty/packets/PingPacket.java diff --git a/src/main/java/mc/core/netty/PacketDecoder.java b/src/main/java/mc/core/netty/PacketDecoder.java index 0f65ffd..b8a8933 100644 --- a/src/main/java/mc/core/netty/PacketDecoder.java +++ b/src/main/java/mc/core/netty/PacketDecoder.java @@ -7,17 +7,22 @@ package mc.core.netty; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ReplayingDecoder; +import lombok.extern.slf4j.Slf4j; +import mc.core.Packet; import java.util.List; import java.util.Optional; +import java.util.StringJoiner; import static mc.core.netty.Utils.readVarInt; +@Slf4j public class PacketDecoder extends ReplayingDecoder { @Override protected void decode(ChannelHandlerContext context, ByteBuf byteBuf, List list) throws Exception { int length = readVarInt(byteBuf); int id = readVarInt(byteBuf); + log.debug("PktLEN: {} | PktID: {}", length, id); Optional> packetClass = context.channel().attr(State.ATTR_STATE).get().getPacketClass(id); @@ -25,9 +30,16 @@ public class PacketDecoder extends ReplayingDecoder { NettyPacket packet = packetClass.get().newInstance(); packet.fillFromByteBuf(byteBuf); list.add(packet); + if (length < packet.getSize()) { + log.warn("WTF?! length < packet.getSize() !!"); + log.warn("Packet size: {}", packet.getSize()); + } else if (length > packet.getSize()) { + log.debug("skipBytes {}", length - packet.getSize()); + byteBuf.skipBytes(length - packet.getSize()); + } } else { list.add(new UnknownPacket(length, id)); - byteBuf.skipBytes(length); + byteBuf.skipBytes(length-1); } } } diff --git a/src/main/java/mc/core/netty/PacketHandler.java b/src/main/java/mc/core/netty/PacketHandler.java index 47f0634..6159d42 100644 --- a/src/main/java/mc/core/netty/PacketHandler.java +++ b/src/main/java/mc/core/netty/PacketHandler.java @@ -7,6 +7,8 @@ package mc.core.netty; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import lombok.extern.slf4j.Slf4j; +import mc.core.netty.packets.HandshakeRequestPacket; +import mc.core.netty.packets.HandshakeResponsePacket; import static mc.core.netty.Utils.equalsPacket; @@ -24,6 +26,8 @@ public class PacketHandler extends SimpleChannelInboundHandler { packet.toString()); if (equalsPacket(packet, "HandshakeRequestPacket")) { + HandshakeRequestPacket pkt = (HandshakeRequestPacket) packet; + context.channel().attr(State.ATTR_STATE).set(pkt.getNextState()); context.channel().writeAndFlush(new HandshakeResponsePacket()); } } diff --git a/src/main/java/mc/core/netty/State.java b/src/main/java/mc/core/netty/State.java index ea5b778..e884835 100644 --- a/src/main/java/mc/core/netty/State.java +++ b/src/main/java/mc/core/netty/State.java @@ -7,13 +7,19 @@ package mc.core.netty; import com.google.common.collect.ImmutableMap; import io.netty.util.AttributeKey; import lombok.Getter; +import mc.core.netty.packets.HandshakeRequestPacket; +import mc.core.netty.packets.PingPacket; import java.util.Arrays; import java.util.Map; import java.util.Optional; public enum State { - Handshaking(1, ImmutableMap.of(0, HandshakeRequestPacket.class)); + Handshaking(1, ImmutableMap.of( + 0, HandshakeRequestPacket.class, + 1, PingPacket.class + )), + Status(0, ImmutableMap.of(1, PingPacket.class)); public static final AttributeKey ATTR_STATE = AttributeKey.newInstance("ATTR_STATE"); diff --git a/src/main/java/mc/core/netty/Utils.java b/src/main/java/mc/core/netty/Utils.java index a15e34b..115f274 100644 --- a/src/main/java/mc/core/netty/Utils.java +++ b/src/main/java/mc/core/netty/Utils.java @@ -32,18 +32,45 @@ public class Utils { } public static void writeVarInt(int value, ByteBuf byteBuf) { + writeVarLong(value, byteBuf); + } + + public static int lengthVarInt(int value) { + return lengthVarLong(value); + } + + public static long readVarLong(ByteBuf byteBuf) { + long result = 0; + byte read; + int numRead = 0; + + do { + read = byteBuf.readByte(); + int value = (read & 0b01111111); + result |= (value << (7 * numRead)); + + numRead++; + if (numRead > 10) { + log.warn("VarLong is too big"); + break; + } + } while ((read & 0b10000000) != 0); + + return result; + } + + public static void writeVarLong(long value, ByteBuf byteBuf) { do { byte temp = (byte)(value & 0b01111111); value >>>= 7; if (value != 0) { temp |= 0b10000000; } - byteBuf.writeByte(temp); } while (value != 0); } - public static int lengthVarInt(int value) { + public static int lengthVarLong(long value) { int result = 0; do { @@ -54,8 +81,19 @@ public class Utils { return result; } - public static int lengthString(String value) { - return lengthVarInt(value.length()) + value.length(); + public static int readUnsignedShort(ByteBuf byteBuf) { + return byteBuf.readUnsignedShort(); + } + + public static int lengthUnsignedShort(int value) { + int result = 0; + + do { + value >>>= 8; + result++; + } while (value != 0); + + return result; } public static String readString(ByteBuf byteBuf) { @@ -69,15 +107,15 @@ public class Utils { return new String(buffer, StandardCharsets.UTF_8); } - public static int readUnsignedShort(ByteBuf byteBuf) { - return byteBuf.readUnsignedShort(); - } - public static void writeString(String value, ByteBuf byteBuf) { writeVarInt(value.length(), byteBuf); byteBuf.writeBytes(value.getBytes()); } + public static int lengthString(String value) { + return lengthVarInt(value.length()) + value.length(); + } + public static boolean equalsPacket(NettyPacket packet, String name) { return packet.getClass().getSimpleName().equals(name); } diff --git a/src/main/java/mc/core/netty/HandshakeRequestPacket.java b/src/main/java/mc/core/netty/packets/HandshakeRequestPacket.java similarity index 85% rename from src/main/java/mc/core/netty/HandshakeRequestPacket.java rename to src/main/java/mc/core/netty/packets/HandshakeRequestPacket.java index eb5cd19..5f18c84 100644 --- a/src/main/java/mc/core/netty/HandshakeRequestPacket.java +++ b/src/main/java/mc/core/netty/packets/HandshakeRequestPacket.java @@ -2,12 +2,15 @@ * DmitriyMX * 2018-03-25 */ -package mc.core.netty; +package mc.core.netty.packets; import io.netty.buffer.ByteBuf; import lombok.Getter; import lombok.ToString; import mc.core.NotSupportException; +import mc.core.netty.NettyPacket; +import mc.core.netty.State; +import mc.core.netty.UnknowState; import java.util.Optional; @@ -35,11 +38,12 @@ public class HandshakeRequestPacket implements NettyPacket { serverPort = readUnsignedShort(byteBuf); final int nextStateInt = readVarInt(byteBuf); nextState = State.getById(nextStateInt).orElseThrow(() -> new UnknowState(nextStateInt)); + byteBuf.skipBytes(2); //TODO magic size = lengthVarInt(id) + lengthVarInt(protocolVersion) + lengthString(serverAddress) - + lengthVarInt(serverPort) + + lengthUnsignedShort(serverPort) + lengthVarInt(nextState.getId()); } diff --git a/src/main/java/mc/core/netty/HandshakeResponsePacket.java b/src/main/java/mc/core/netty/packets/HandshakeResponsePacket.java similarity index 95% rename from src/main/java/mc/core/netty/HandshakeResponsePacket.java rename to src/main/java/mc/core/netty/packets/HandshakeResponsePacket.java index 2693c46..f89fa0c 100644 --- a/src/main/java/mc/core/netty/HandshakeResponsePacket.java +++ b/src/main/java/mc/core/netty/packets/HandshakeResponsePacket.java @@ -2,11 +2,12 @@ * DmitriyMX * 2018-03-25 */ -package mc.core.netty; +package mc.core.netty.packets; import com.google.gson.JsonObject; import io.netty.buffer.ByteBuf; import mc.core.NotSupportException; +import mc.core.netty.NettyPacket; import static mc.core.netty.Utils.*; diff --git a/src/main/java/mc/core/netty/packets/PingPacket.java b/src/main/java/mc/core/netty/packets/PingPacket.java new file mode 100644 index 0000000..e16eff9 --- /dev/null +++ b/src/main/java/mc/core/netty/packets/PingPacket.java @@ -0,0 +1,45 @@ +/* + * DmitriyMX + * 2018-03-26 + */ +package mc.core.netty.packets; + +import io.netty.buffer.ByteBuf; +import lombok.ToString; +import mc.core.netty.NettyPacket; + +import static mc.core.netty.Utils.*; + +@ToString +public class PingPacket implements NettyPacket { + private static final int id = 1; + private long payload; + private int size; + + @Override + public void writeSelf(ByteBuf byteBuf) { + long payload = System.currentTimeMillis(); + int size = lengthVarLong(payload); + + writeVarInt(size, byteBuf); + writeVarInt(id, byteBuf); + writeVarLong(payload, byteBuf); + } + + @Override + public void fillFromByteBuf(ByteBuf byteBuf) { + payload = readVarLong(byteBuf); + size = lengthVarInt(id) + + lengthVarLong(payload); + } + + @Override + public int getSize() { + return size; + } + + @Override + public int getId() { + return id; + } +}