From 26aebd5183d5f470d99002d29a2995d114f3eed6 Mon Sep 17 00:00:00 2001 From: Collin Smith Date: Sat, 20 Jun 2020 02:01:05 -0700 Subject: [PATCH] Created ReliableUtil class with utility methods to set and get header data encoded within a reliable UDP packet outside of fbs --- .../riiablo/server/netty/ReliableUtil.java | 74 +++++++++++++++++++ .../server/netty/ReliableUtilTest.java | 56 ++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 server/netty/src/com/riiablo/server/netty/ReliableUtil.java create mode 100644 server/netty/src/com/riiablo/server/netty/ReliableUtilTest.java diff --git a/server/netty/src/com/riiablo/server/netty/ReliableUtil.java b/server/netty/src/com/riiablo/server/netty/ReliableUtil.java new file mode 100644 index 00000000..85a16dd1 --- /dev/null +++ b/server/netty/src/com/riiablo/server/netty/ReliableUtil.java @@ -0,0 +1,74 @@ +package com.riiablo.server.netty; + +import io.netty.buffer.ByteBuf; +import java.nio.ByteBuffer; +import org.apache.commons.lang3.Validate; + +public class ReliableUtil { + private ReliableUtil() {} + + private static final int PROTOCOL_OFFSET = 0; + private static final int PROTOCOL_SIZE = 1; // ubyte + + private static final int SEQ_OFFSET = PROTOCOL_OFFSET + PROTOCOL_SIZE; + private static final int SEQ_SIZE = 2; // ushort + + private static final int ACK_OFFSET = SEQ_OFFSET + SEQ_SIZE; + private static final int ACK_SIZE = 2; // ushort + + private static final int ACK_BITS_OFFSET = ACK_OFFSET + ACK_SIZE; + private static final int ACK_BITS_SIZE = 4; // int + + private static final int CONTENT_SIZE_OFFSET = ACK_BITS_OFFSET + ACK_BITS_SIZE; + private static final int CONTENT_SIZE_SIZE = 2; // ushort + + static final int CONTENT_OFFSET = CONTENT_SIZE_OFFSET + CONTENT_SIZE_SIZE; + + public static int getProtocol(ByteBuf bb) { + return bb.getUnsignedByte(PROTOCOL_OFFSET); + } + + public static int getSEQ(ByteBuf bb) { + return bb.getUnsignedShort(SEQ_OFFSET); + } + + public static int getACK(ByteBuf bb) { + return bb.getUnsignedShort(ACK_OFFSET); + } + + public static int getACK_BITS(ByteBuf bb) { + return bb.getInt(ACK_BITS_OFFSET); + } + + public static int getContentSize(ByteBuf bb) { + return bb.getUnsignedShort(CONTENT_SIZE_OFFSET); + } + + public static ByteBuf getContent(ByteBuf bb) { + return bb.slice(CONTENT_OFFSET, getContentSize(bb)); + } + + static void setProtocol(ByteBuf bb, int value) { + bb.setByte(PROTOCOL_OFFSET, value); + } + + static void setSEQ(ByteBuf bb, int value) { + bb.setShort(SEQ_OFFSET, value); + } + + static void setACK(ByteBuf bb, int value) { + bb.setShort(ACK_OFFSET, value); + } + + static void setACK_BITS(ByteBuf bb, int value) { + bb.setInt(ACK_BITS_OFFSET, value); + } + + static void setContent(ByteBuf bb, ByteBuffer src) { + Validate.isTrue(src.remaining() <= 0xFFFF, "cannot encode content size as ushort, src.remaining()=" + src.remaining()); + src.mark(); + bb.setShort(CONTENT_SIZE_OFFSET, src.remaining()); + bb.setBytes(CONTENT_OFFSET, src); + src.reset(); + } +} diff --git a/server/netty/src/com/riiablo/server/netty/ReliableUtilTest.java b/server/netty/src/com/riiablo/server/netty/ReliableUtilTest.java new file mode 100644 index 00000000..ef2f8d95 --- /dev/null +++ b/server/netty/src/com/riiablo/server/netty/ReliableUtilTest.java @@ -0,0 +1,56 @@ +package com.riiablo.server.netty; + +import com.google.flatbuffers.FlatBufferBuilder; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.Unpooled; +import io.netty.util.ReferenceCountUtil; +import org.apache.commons.lang3.StringUtils; + +import com.riiablo.net.packet.netty.Connection; +import com.riiablo.net.packet.netty.Netty; +import com.riiablo.net.packet.netty.NettyData; + +public class ReliableUtilTest { + public static void main(String[] args) { + ByteBuf bb = null; + try { + bb = Unpooled.buffer(); + test(bb); + } finally { + ReferenceCountUtil.release(bb); + } + } + + static void test(ByteBuf bb) { + final int PROTOCOL = 0b10010001; + final int SEQ = 0xF0F0; + final int ACK = 0x0F0F; + final int ACK_BITS = 0xFF0000FF; + + ReliableUtil.setProtocol(bb, PROTOCOL); + ReliableUtil.setSEQ(bb, SEQ); + ReliableUtil.setACK(bb, ACK); + ReliableUtil.setACK_BITS(bb, ACK_BITS); + + bb.writerIndex(ReliableUtil.CONTENT_OFFSET); // hack to force writer position passed header + System.out.println(ByteBufUtil.hexDump(bb)); // note: hexDump requires writerIndex + + FlatBufferBuilder builder = new FlatBufferBuilder(); + Connection.startConnection(builder); + int dataOffset = Connection.endConnection(builder); + int offset = Netty.createNetty(builder, PROTOCOL, SEQ, ACK, ACK_BITS, NettyData.Connection, dataOffset); + Netty.finishNettyBuffer(builder, offset); + ReliableUtil.setContent(bb, builder.dataBuffer()); + + bb.writerIndex(ReliableUtil.CONTENT_OFFSET + ReliableUtil.getContentSize(bb)); // hack to force writer position passed content + System.out.println(ByteBufUtil.hexDump(bb)); // note: hexDump requires writerIndex + + System.out.printf("%-8s %-5s %02x%n", "PROTOCOL", PROTOCOL == ReliableUtil.getProtocol(bb), ReliableUtil.getProtocol(bb)); + System.out.printf("%-8s %-5s %04x%n", "SEQ", SEQ == ReliableUtil.getSEQ(bb), ReliableUtil.getSEQ(bb)); + System.out.printf("%-8s %-5s %04x%n", "ACK", ACK == ReliableUtil.getACK(bb), ReliableUtil.getACK(bb)); + System.out.printf("%-8s %-5s %08x%n", "ACK_BITS", ACK_BITS == ReliableUtil.getACK_BITS(bb), ReliableUtil.getACK_BITS(bb)); + System.out.printf("%-8s %-5s %04x%n", "CSIZE", builder.dataBuffer().remaining() == ReliableUtil.getContentSize(bb), ReliableUtil.getContentSize(bb)); + System.out.printf("%-8s %-5s %s%n", "CONTENT", StringUtils.equals(ByteBufUtil.hexDump(builder.sizedByteArray()), ByteBufUtil.hexDump(ReliableUtil.getContent(bb))), ByteBufUtil.hexDump(ReliableUtil.getContent(bb))); + } +}