From 510342e232a174a2368edc14b98cc56801d2a818 Mon Sep 17 00:00:00 2001 From: Collin Smith Date: Thu, 18 Jun 2020 20:46:57 -0700 Subject: [PATCH] Implemented some basic reliable udp logic Seq should increment and wrap around at 0xFFFF Added special case for ack < 0 (init first packet) Added netty packet creation functions to ReliableChannelHandler Header creation is difficult because I can't mutate existing packets easily -- experimenting --- .../src/com/riiablo/server/netty/Client.java | 6 +-- .../server/netty/ReliableChannelHandler.java | 49 ++++++++++++++++++- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/server/netty/src/com/riiablo/server/netty/Client.java b/server/netty/src/com/riiablo/server/netty/Client.java index 88b60fda..1b26dcbd 100644 --- a/server/netty/src/com/riiablo/server/netty/Client.java +++ b/server/netty/src/com/riiablo/server/netty/Client.java @@ -23,8 +23,6 @@ import com.badlogic.gdx.backends.headless.HeadlessApplicationConfiguration; import com.riiablo.codec.Animation; import com.riiablo.net.packet.netty.Connection; -import com.riiablo.net.packet.netty.Header; -import com.riiablo.net.packet.netty.Netty; import com.riiablo.net.packet.netty.NettyData; public class Client extends ApplicationAdapter { @@ -81,11 +79,9 @@ public class Client extends ApplicationAdapter { Gdx.app.log(TAG, "Connecting to " + remoteAddress.getHostString() + ":" + remoteAddress.getPort()); FlatBufferBuilder builder = new FlatBufferBuilder(); - int headerOffset = Header.createHeader(builder, -1, -1, 0); Connection.startConnection(builder); int dataOffset = Connection.endConnection(builder); - int offset = Netty.createNetty(builder, headerOffset, NettyData.Connection, dataOffset); - Netty.finishSizePrefixedNettyBuffer(builder, offset); + createNetty(builder, NettyData.Connection, dataOffset); ByteBuf byteBuf = Unpooled.wrappedBuffer(builder.dataBuffer()); ctx.writeAndFlush(byteBuf); diff --git a/server/netty/src/com/riiablo/server/netty/ReliableChannelHandler.java b/server/netty/src/com/riiablo/server/netty/ReliableChannelHandler.java index 130140b9..342f6edd 100644 --- a/server/netty/src/com/riiablo/server/netty/ReliableChannelHandler.java +++ b/server/netty/src/com/riiablo/server/netty/ReliableChannelHandler.java @@ -1,6 +1,7 @@ package com.riiablo.server.netty; import com.google.flatbuffers.ByteBufferUtil; +import com.google.flatbuffers.FlatBufferBuilder; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandler; @@ -24,6 +25,7 @@ public class ReliableChannelHandler implements ChannelHandler, ChannelInboundHan private static final String TAG = "ReliableChannelHandler"; private static final boolean DEBUG = true; + private static final boolean DEBUG_SEQ = DEBUG && true; private static final boolean DEBUG_OUTBOUND = DEBUG && true; private final TypeParameterMatcher matcher; @@ -57,16 +59,59 @@ public class ReliableChannelHandler implements ChannelHandler, ChannelInboundHan } protected void processHeader(ChannelHandlerContext ctx, Header header) throws Exception { - Gdx.app.log(TAG, " " + String.format("SEQ:%d ACK:%d ACK_BITS:%08x", header.sequence(), header.ack(), header.ackBits())); + Gdx.app.log(TAG, " incoming " + String.format("SEQ:%d ACK:%d ACK_BITS:%08x", header.sequence(), header.ack(), header.ackBits())); + int remoteSeq = header.sequence(); + if (ack < 0) { + ack = remoteSeq; + Gdx.app.log(TAG, " init ack=" + ack); + } else if (sequenceGreater(remoteSeq, ack)) { + int shift = difference(remoteSeq, ack); + Gdx.app.log(TAG, " remoteSeq=" + remoteSeq + "; ack=" + ack + "; shift=" + shift); + ack_bits <<= shift; + ack_bits |= (1 << (shift - 1)); + ack = remoteSeq; + } else { + int diff = difference(ack, remoteSeq); + Gdx.app.log(TAG, " diff=" + diff); + if (diff <= Integer.SIZE) { + ack_bits |= (1 << (diff - 1)); + } + } + + Gdx.app.log(TAG, " " + String.format("ACK:%d ACK_BITS:%08x", ack, ack_bits)); + } + + protected static boolean sequenceGreater(int a, int b) { + return ((a > b) && (a - b <= Short.MAX_VALUE)) + || ((a < b) && (b - a > Short.MAX_VALUE)); + } + + protected static int difference(int a, int b) { + assert sequenceGreater(a, b) : a + "<" + b; + if ((a > b) && (a - b <= Short.MAX_VALUE)) { + return a - b; + } else { + return a + 0xFFFF - b + 1; + } } protected void processPacket(ChannelHandlerContext ctx, Netty netty) throws Exception { } + protected void createNetty(FlatBufferBuilder builder, byte data_type, int dataOffset) { + int headerOffset = createHeader(builder); + int offset = Netty.createNetty(builder, headerOffset, data_type, dataOffset); + Netty.finishSizePrefixedNettyBuffer(builder, offset); + } + + protected int createHeader(FlatBufferBuilder builder) { + return Header.createHeader(builder, seq = (seq + 1) & 0xFFFF, ack, ack_bits); + } + protected void channelWrite0(ChannelHandlerContext ctx, Object msg) throws Exception { InetSocketAddress receiver = (InetSocketAddress) ctx.channel().remoteAddress(); - Gdx.app.log(TAG, "channelRead0 Packet to " + receiver.getHostName() + ":" + receiver.getPort()); + Gdx.app.log(TAG, "channelWrite0 Packet to " + receiver.getHostName() + ":" + receiver.getPort()); ByteBuf out = (ByteBuf) msg; try { Gdx.app.debug(TAG, "out.nioBufferCount()=" + out.nioBufferCount());