From 09b734344f31e18d0fa31c39acba6d012aa2cc56 Mon Sep 17 00:00:00 2001
From: Daniel Karbach <daniel.karbach@localhorst.tv>
Date: Wed, 2 Sep 2015 23:40:21 +0200
Subject: [PATCH] tag packets withsequence numbers

acks are already transmitted to the other side,
but they're not used yet
---
 src/net/Connection.hpp | 13 +++++++----
 src/net/Packet.hpp     |  7 ++++++
 src/net/net.cpp        | 52 +++++++++++++++++++++++++++++++++++++-----
 3 files changed, 62 insertions(+), 10 deletions(-)

diff --git a/src/net/Connection.hpp b/src/net/Connection.hpp
index 49e9cda..ade65eb 100644
--- a/src/net/Connection.hpp
+++ b/src/net/Connection.hpp
@@ -1,8 +1,10 @@
 #ifndef BLANK_NET_CONNECTION_HPP_
 #define BLANK_NET_CONNECTION_HPP_
 
+#include "Packet.hpp"
 #include "../app/IntervalTimer.hpp"
 
+#include <cstdint>
 #include <SDL_net.h>
 
 
@@ -17,24 +19,27 @@ public:
 
 	bool Matches(const IPaddress &) const noexcept;
 
-	void FlagSend() noexcept;
-	void FlagRecv() noexcept;
-
 	bool ShouldPing() const noexcept;
 	bool TimedOut() const noexcept;
 
 	void Update(int dt);
 
-
 	void SendPing(UDPpacket &, UDPsocket);
 
 	void Send(UDPpacket &, UDPsocket);
+	void Received(const UDPpacket &);
+
+private:
+	void FlagSend() noexcept;
+	void FlagRecv() noexcept;
 
 private:
 	IPaddress addr;
 	IntervalTimer send_timer;
 	IntervalTimer recv_timer;
 
+	Packet::TControl ctrl;
+
 };
 
 }
diff --git a/src/net/Packet.hpp b/src/net/Packet.hpp
index d547990..b7c8a5f 100644
--- a/src/net/Packet.hpp
+++ b/src/net/Packet.hpp
@@ -16,8 +16,15 @@ struct Packet {
 		LOGIN = 1,
 	};
 
+	struct TControl {
+		std::uint16_t seq;
+		std::uint16_t ack;
+		std::uint32_t hist;
+	};
+
 	struct Header {
 		std::uint32_t tag;
+		TControl ctrl;
 		std::uint8_t type;
 	} header;
 
diff --git a/src/net/net.cpp b/src/net/net.cpp
index 20b6f5c..314410e 100644
--- a/src/net/net.cpp
+++ b/src/net/net.cpp
@@ -75,7 +75,7 @@ void Client::HandlePacket(const UDPpacket &udp_pack) {
 		return;
 	}
 
-	conn.FlagRecv();
+	conn.Received(udp_pack);
 	cout << "I got something!" << endl;
 }
 
@@ -102,7 +102,8 @@ void Client::SendLogin(const string &name) {
 Connection::Connection(const IPaddress &addr)
 : addr(addr)
 , send_timer(5000)
-, recv_timer(10000) {
+, recv_timer(10000)
+, ctrl{ 0, 0xFFFF, 0xFFFF } {
 	send_timer.Start();
 	recv_timer.Start();
 }
@@ -133,14 +134,53 @@ void Connection::Update(int dt) {
 }
 
 
-void Connection::Send(UDPpacket &pack, UDPsocket sock) {
-	pack.address = addr;
-	if (SDLNet_UDP_Send(sock, -1, &pack) == 0) {
+void Connection::Send(UDPpacket &udp_pack, UDPsocket sock) {
+	Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
+	pack.header.ctrl = ctrl;
+
+	udp_pack.address = addr;
+	if (SDLNet_UDP_Send(sock, -1, &udp_pack) == 0) {
 		throw NetError("SDLNet_UDP_Send");
 	}
+
 	FlagSend();
 }
 
+void Connection::Received(const UDPpacket &udp_pack) {
+	Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
+
+	int diff = std::int16_t(pack.header.ctrl.seq) - std::int16_t(ctrl.ack);
+
+	if (diff > 0) {
+		// incoming more recent than last acked
+
+		// TODO: packets considered lost are detected here
+		//       this should have ones for all of them:
+		//       ~hist & ((1 << dist) - 1) if dist is < 32
+
+		if (diff >= 32) {
+			// missed more than the last 32 oO
+			ctrl.hist = 0;
+		} else {
+			ctrl.hist >>= diff;
+			ctrl.hist |= 1 << (32 - diff);
+		}
+	} else if (diff < 0) {
+		// incoming older than acked
+		if (diff > -32) {
+			// too late :/
+		} else {
+			ctrl.hist |= 1 << (32 + diff);
+		}
+	} else {
+		// incoming the same as last acked oO
+	}
+
+	ctrl.ack = pack.header.ctrl.seq;
+
+	FlagRecv();
+}
+
 void Connection::SendPing(UDPpacket &udp_pack, UDPsocket sock) {
 	Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
 	udp_pack.len = pack.Ping();
@@ -230,7 +270,7 @@ void Server::HandlePacket(const UDPpacket &udp_pack) {
 	}
 
 	Connection &client = GetClient(udp_pack.address);
-	client.FlagRecv();
+	client.Received(udp_pack);
 
 	switch (pack.header.type) {
 		case Packet::PING:
-- 
2.39.5