From 704dd194885af34e1f15526b5a65ff33ef18680d Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Tue, 10 Apr 2018 09:39:52 +0300 Subject: [PATCH] Ping-pong --- .../proto_125/ByteArrayOutputNetStream.java | 59 +++++++++++++++++++ .../mc/core/netty/proto_125/NettyServer.java | 5 +- .../core/netty/proto_125/PacketDecoder.java | 36 +++++++++++ .../core/netty/proto_125/PacketEncoder.java | 21 +++++++ .../core/netty/proto_125/PacketHandler.java | 46 +++++++++++++++ .../core/netty/proto_125/PacketManager.java | 28 +++++++++ .../netty/proto_125/WrapperNetStream.java | 43 ++++++++++++++ .../netty/proto_125/packets/KickPacket.java | 26 ++++++++ .../netty/proto_125/packets/PingPacket.java | 10 ++++ 9 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 src/main/java/mc/core/netty/proto_125/ByteArrayOutputNetStream.java create mode 100644 src/main/java/mc/core/netty/proto_125/PacketDecoder.java create mode 100644 src/main/java/mc/core/netty/proto_125/PacketEncoder.java create mode 100644 src/main/java/mc/core/netty/proto_125/PacketHandler.java create mode 100644 src/main/java/mc/core/netty/proto_125/PacketManager.java create mode 100644 src/main/java/mc/core/netty/proto_125/WrapperNetStream.java create mode 100644 src/main/java/mc/core/netty/proto_125/packets/KickPacket.java create mode 100644 src/main/java/mc/core/netty/proto_125/packets/PingPacket.java diff --git a/src/main/java/mc/core/netty/proto_125/ByteArrayOutputNetStream.java b/src/main/java/mc/core/netty/proto_125/ByteArrayOutputNetStream.java new file mode 100644 index 0000000..9297645 --- /dev/null +++ b/src/main/java/mc/core/netty/proto_125/ByteArrayOutputNetStream.java @@ -0,0 +1,59 @@ +/* + * DmitriyMX + * 2018-04-08 + */ +package mc.core.netty.proto_125; + +import lombok.extern.slf4j.Slf4j; +import mc.core.NetStream; + +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; + +@Slf4j +public class ByteArrayOutputNetStream extends NetStream { + private ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + @Override + public void writeString(String value) { + if (value.length() > 240) { + log.warn("String \"{}\" too long!", value); + byte[] buf = value.substring(0, 240).getBytes(StandardCharsets.UTF_16BE); + writeByte(240); + writeBytes(buf); + } else { + byte[] buf = value.getBytes(StandardCharsets.UTF_16BE); + writeByte(value.length()); + writeBytes(buf); + } + } + + @Override + public byte readByte() { + throw new UnsupportedOperationException(); + } + + @Override + public void readBytes(byte[] buffer) { + throw new UnsupportedOperationException(); + } + + @Override + public int readUnsignedShort() { + throw new UnsupportedOperationException(); + } + + @Override + public void writeByte(int value) { + baos.write(value); + } + + @Override + public void writeBytes(byte[] buffer) { + baos.write(buffer, 0, buffer.length); + } + + public byte[] toByteArray() { + return baos.toByteArray(); + } +} diff --git a/src/main/java/mc/core/netty/proto_125/NettyServer.java b/src/main/java/mc/core/netty/proto_125/NettyServer.java index c397f6b..3fc7c1e 100644 --- a/src/main/java/mc/core/netty/proto_125/NettyServer.java +++ b/src/main/java/mc/core/netty/proto_125/NettyServer.java @@ -24,7 +24,10 @@ public class NettyServer implements Server { @Override protected void initChannel(SocketChannel socketChannel) { socketChannel.pipeline().addLast( - new LoggingHandler() + new LoggingHandler(), + new PacketDecoder(), + new PacketHandler(), + new PacketEncoder() ); } }; diff --git a/src/main/java/mc/core/netty/proto_125/PacketDecoder.java b/src/main/java/mc/core/netty/proto_125/PacketDecoder.java new file mode 100644 index 0000000..70fe06f --- /dev/null +++ b/src/main/java/mc/core/netty/proto_125/PacketDecoder.java @@ -0,0 +1,36 @@ +/* + * DmitriyMX + * 2018-03-25 + */ +package mc.core.netty.proto_125; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import lombok.extern.slf4j.Slf4j; +import mc.core.CSPacket; +import mc.core.NetStream; + +import java.util.List; + +@Slf4j +public class PacketDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { + log.debug("ByteBuf readableBytes: {}", in.readableBytes()); + int id = in.readUnsignedByte(); + log.debug("Pkt-Id: {} / 0x{}", id, Integer.toHexString(id).toUpperCase()); + + Class packetClass = PacketManager.getClientSidePacket(id); + if (packetClass != null) { + NetStream netStream = new WrapperNetStream(in); + CSPacket packet = packetClass.newInstance(); + packet.readSelf(netStream); + + out.add(packet); + } + + if (in.readableBytes() > 0) + in.skipBytes(in.readableBytes()); + } +} diff --git a/src/main/java/mc/core/netty/proto_125/PacketEncoder.java b/src/main/java/mc/core/netty/proto_125/PacketEncoder.java new file mode 100644 index 0000000..0846996 --- /dev/null +++ b/src/main/java/mc/core/netty/proto_125/PacketEncoder.java @@ -0,0 +1,21 @@ +/* + * DmitriyMX + * 2018-04-10 + */ +package mc.core.netty.proto_125; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; +import mc.core.SCPacket; + +public class PacketEncoder extends MessageToByteEncoder { + @Override + protected void encode(ChannelHandlerContext ctx, SCPacket pkt, ByteBuf out) throws Exception { + Integer id = PacketManager.getServirSidePacket(pkt.getClass()); + byte[] bytes = pkt.toByteArray(); + + out.writeByte(id); + out.writeBytes(bytes); + } +} diff --git a/src/main/java/mc/core/netty/proto_125/PacketHandler.java b/src/main/java/mc/core/netty/proto_125/PacketHandler.java new file mode 100644 index 0000000..7184298 --- /dev/null +++ b/src/main/java/mc/core/netty/proto_125/PacketHandler.java @@ -0,0 +1,46 @@ +/* + * DmitriyMX + * 2018-04-10 + */ +package mc.core.netty.proto_125; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import mc.core.CSPacket; +import mc.core.Config; +import mc.core.Main; +import mc.core.netty.proto_125.packets.KickPacket; +import mc.core.netty.proto_125.packets.PingPacket; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Optional; + +@Slf4j +public class PacketHandler extends SimpleChannelInboundHandler { + @Override + protected void channelRead0(ChannelHandlerContext ctx, CSPacket packet) throws Exception { + log.debug("{}: {}", packet.getClass().getSimpleName(), packet.toString()); + + Optional optionalMethod = Arrays.stream(this.getClass().getDeclaredMethods()) + .filter(method -> method.getName().equals("on" + packet.getClass().getSimpleName()) + && method.getParameterCount() == 2 + && method.getParameterTypes()[0].isAssignableFrom(Channel.class) + && method.getParameterTypes()[1].isAssignableFrom(packet.getClass())) + .findFirst(); + + if (optionalMethod.isPresent()) { + Method method = optionalMethod.get(); + method.invoke(this, ctx.channel(), packet); + } + } + + public void onPingPacket(Channel channel, PingPacket packet) { + Config config = Main.appContext.getBean("config", Config.class); + KickPacket pkt = new KickPacket(); + pkt.setPongMessage(config.getDescriptionServer(), 0, config.getMaxPlayers()); + channel.writeAndFlush(pkt); + } +} diff --git a/src/main/java/mc/core/netty/proto_125/PacketManager.java b/src/main/java/mc/core/netty/proto_125/PacketManager.java new file mode 100644 index 0000000..34ad8fb --- /dev/null +++ b/src/main/java/mc/core/netty/proto_125/PacketManager.java @@ -0,0 +1,28 @@ +/* + * DmitriyMX + * 2018-04-10 + */ +package mc.core.netty.proto_125; + +import com.google.common.collect.BiMap; +import com.google.common.collect.ImmutableBiMap; +import mc.core.CSPacket; +import mc.core.SCPacket; +import mc.core.netty.proto_125.packets.KickPacket; +import mc.core.netty.proto_125.packets.PingPacket; + +public class PacketManager { + private static final BiMap> packetMap = ImmutableBiMap.of( + 0xFE, PingPacket.class, + 0xFF, KickPacket.class + ); + + @SuppressWarnings("unchecked") + public static Class getClientSidePacket(int id) { + return (Class) packetMap.get(id); + } + + public static Integer getServirSidePacket(Class clazz) { + return packetMap.inverse().get(clazz); + } +} diff --git a/src/main/java/mc/core/netty/proto_125/WrapperNetStream.java b/src/main/java/mc/core/netty/proto_125/WrapperNetStream.java new file mode 100644 index 0000000..6c0e7fb --- /dev/null +++ b/src/main/java/mc/core/netty/proto_125/WrapperNetStream.java @@ -0,0 +1,43 @@ +/* + * DmitriyMX + * 2018-04-08 + */ +package mc.core.netty.proto_125; + +import io.netty.buffer.ByteBuf; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import mc.core.NetStream; + +import java.nio.charset.StandardCharsets; + +@Slf4j +@RequiredArgsConstructor +public class WrapperNetStream extends NetStream { + private final ByteBuf byteBuf; + + @Override + public byte readByte() { + return byteBuf.readByte(); + } + + @Override + public void readBytes(byte[] buffer) { + byteBuf.readBytes(buffer); + } + + @Override + public int readUnsignedShort() { + return byteBuf.readUnsignedShort(); + } + + @Override + public void writeByte(int value) { + byteBuf.writeByte(value); + } + + @Override + public void writeBytes(byte[] buffer) { + byteBuf.writeBytes(buffer); + } +} diff --git a/src/main/java/mc/core/netty/proto_125/packets/KickPacket.java b/src/main/java/mc/core/netty/proto_125/packets/KickPacket.java new file mode 100644 index 0000000..09379da --- /dev/null +++ b/src/main/java/mc/core/netty/proto_125/packets/KickPacket.java @@ -0,0 +1,26 @@ +/* + * DmitriyMX + * 2018-04-10 + */ +package mc.core.netty.proto_125.packets; + +import lombok.Setter; +import mc.core.SCPacket; +import mc.core.netty.proto_125.ByteArrayOutputNetStream; + +public class KickPacket implements SCPacket { + @Setter + private String reason; + + public void setPongMessage(String description, int online, int maxOnline) { + reason = String.format("%s§%d§%d", description, online, maxOnline); + } + + @Override + public byte[] toByteArray() { + ByteArrayOutputNetStream netStream = new ByteArrayOutputNetStream(); + netStream.writeByte(0); + netStream.writeString(reason); + return netStream.toByteArray(); + } +} diff --git a/src/main/java/mc/core/netty/proto_125/packets/PingPacket.java b/src/main/java/mc/core/netty/proto_125/packets/PingPacket.java new file mode 100644 index 0000000..08f8fb8 --- /dev/null +++ b/src/main/java/mc/core/netty/proto_125/packets/PingPacket.java @@ -0,0 +1,10 @@ +/* + * DmitriyMX + * 2018-04-10 + */ +package mc.core.netty.proto_125.packets; + +import mc.core.CSPacket; + +public class PingPacket implements CSPacket { +}