]> git.seodisparate.com - UDPConnection/commitdiff
More impl: rtt and timepoint per sent pkt
authorStephen Seo <seo.disparate@gmail.com>
Thu, 22 Aug 2019 11:16:07 +0000 (20:16 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Thu, 22 Aug 2019 11:16:07 +0000 (20:16 +0900)
cpp_impl/src/UDPC_Defines.hpp
cpp_impl/src/UDPConnection.cpp
cpp_impl/src/UDPConnection.h

index 3a70e866cc2b16a1b94f41bf00ba8d88172b2e96..0f3c4fdc84945aff388ce56ee0a4f3a0f66e5811 100644 (file)
@@ -7,6 +7,7 @@
 #define UDPC_BAD_MODE_SEND_INTERVAL (1.0f / 10.0f)
 #define UDPC_SENT_PKTS_MAX_SIZE 33
 #define UDPC_QUEUED_PKTS_MAX_SIZE 32
+#define UDPC_GOOD_RTT_LIMIT_SEC 0.25f
 
 #define UDPC_ID_CONNECT 0x80000000
 #define UDPC_ID_PING 0x40000000
@@ -19,7 +20,9 @@
 #include <cstdint>
 #include <deque>
 #include <unordered_map>
+#include <queue>
 #include <random>
+#include <memory>
 
 #include "TSQueue.hpp"
 #include "UDPConnection.h"
@@ -31,8 +34,18 @@ static const auto INIT_PKT_INTERVAL_DT = std::chrono::seconds(5);
 static const auto HEARTBEAT_PKT_INTERVAL_DT = std::chrono::milliseconds(150);
 static const auto PACKET_TIMEOUT_TIME = std::chrono::seconds(1);
 
+// forward declaration
 struct Context;
 
+struct SentPktInfo {
+    typedef std::shared_ptr<SentPktInfo> Ptr;
+
+    SentPktInfo();
+
+    uint32_t id;
+    std::chrono::steady_clock::time_point sentTime;
+};
+
 struct ConnectionData {
     ConnectionData();
     ConnectionData(bool isServer, Context *ctx);
@@ -45,6 +58,8 @@ struct ConnectionData {
     ConnectionData(ConnectionData&& other) = default;
     ConnectionData& operator=(ConnectionData&& other) = default;
 
+    void cleanupSentPkts();
+
     /*
      * 0 - trigger send
      * 1 - is good mode
@@ -66,6 +81,8 @@ struct ConnectionData {
     std::deque<UDPC_PacketInfo> sentPkts;
     TSQueue<UDPC_PacketInfo> sendPkts;
     TSQueue<UDPC_PacketInfo> priorityPkts;
+    // pkt id to pkt shared_ptr
+    std::unordered_map<uint32_t, SentPktInfo::Ptr> sentInfoMap;
     std::chrono::steady_clock::time_point received;
     std::chrono::steady_clock::time_point sent;
     float rtt;
@@ -116,6 +133,10 @@ void preparePacket(char *data, uint32_t protocolID, uint32_t conID,
 
 uint32_t generateConnectionID(Context &ctx);
 
+float durationToFSec(
+    const std::chrono::steady_clock::time_point& older,
+    const std::chrono::steady_clock::time_point& newer);
+
 } // namespace UDPC
 
 #endif
index c1731c4fab948266c1555aa447636310161ee8ea..5485df2ca2c2201ec4a109724585e95361af1bea 100644 (file)
@@ -7,6 +7,11 @@
 #include <optional>
 #include <vector>
 
+UDPC::SentPktInfo::SentPktInfo() :
+id(0),
+sentTime(std::chrono::steady_clock::now())
+{}
+
 UDPC::ConnectionData::ConnectionData() :
 flags(),
 timer(0.0f),
@@ -33,6 +38,15 @@ UDPC::ConnectionData::ConnectionData()
     }
 }
 
+void UDPC::ConnectionData::cleanupSentPkts() {
+    uint32_t id;
+    while(sentPkts.size() > UDPC_SENT_PKTS_MAX_SIZE) {
+        id = *((uint32_t*)(sentPkts.front().data + 8));
+        sentInfoMap.erase(id);
+        sentPkts.pop_front();
+    }
+}
+
 UDPC::Context::Context(bool isThreaded)
     : _contextIdentifier(UDPC_CONTEXT_IDENTIFIER), flags(),
       isAcceptNewConnections(true), protocolID(UDPC_DEFAULT_PROTOCOL_ID),
@@ -122,6 +136,14 @@ uint32_t UDPC::generateConnectionID(Context &ctx) {
     return id;
 }
 
+float UDPC::durationToFSec(
+        const std::chrono::steady_clock::time_point& older,
+        const std::chrono::steady_clock::time_point& newer) {
+    const auto dt = newer - older;
+    return (float)dt.count()
+        * (float)decltype(dt)::period::num / (float)decltype(dt)::period::den;
+}
+
 void *UDPC_init(uint16_t listenPort, uint32_t listenAddr, int isClient) {
     UDPC::Context *ctx = new UDPC::Context(false);
 
@@ -200,21 +222,16 @@ void UDPC_update(void *ctx) {
         return;
     }
 
+    const auto prevNow = std::move(c->lastUpdated);
     const auto now = std::chrono::steady_clock::now();
-    const auto dt = now - c->lastUpdated;
-    const float dt_fs = (float)dt.count() * (float)decltype(dt)::period::num /
-                        (float)decltype(dt)::period::den;
+    c->lastUpdated = now;
 
-    std::chrono::steady_clock::duration temp_dt;
     float temp_dt_fs;
     {
         // check timed out, check good/bad mode with rtt, remove timed out
         std::vector<uint32_t> removed;
         for(auto iter = c->conMap.begin(); iter != c->conMap.end(); ++iter) {
-            temp_dt = now - iter->second.received;
-            temp_dt_fs = (float)temp_dt.count() *
-                         (float)decltype(temp_dt)::period::num /
-                         (float)decltype(temp_dt)::period::den;
+            temp_dt_fs = UDPC::durationToFSec(iter->second.received, now);
             if(temp_dt_fs >= UDPC_TIMEOUT_SECONDS) {
                 removed.push_back(iter->first);
                 continue;
@@ -384,11 +401,15 @@ void UDPC_update(void *ctx) {
             pInfo.receiver = iter->first;
             pInfo.senderPort = c->socketInfo.sin_port;
             pInfo.receiverPort = iter->second.port;
+            *((uint32_t*)(pInfo.data + 8)) = iter->second.lseq - 1;
 
             iter->second.sentPkts.push_back(std::move(pInfo));
-            while(iter->second.sentPkts.size() > UDPC_SENT_PKTS_MAX_SIZE) {
-                iter->second.sentPkts.pop_front();
-            }
+            iter->second.cleanupSentPkts();
+
+            // store other pkt info
+            UDPC::SentPktInfo::Ptr sentPktInfo = std::make_shared<UDPC::SentPktInfo>();
+            sentPktInfo->id = iter->second.lseq - 1;
+            iter->second.sentInfoMap.insert(std::make_pair(sentPktInfo->id, sentPktInfo));
         } else {
             // sendPkts or priorityPkts not empty
             UDPC_PacketInfo pInfo;
@@ -440,11 +461,9 @@ void UDPC_update(void *ctx) {
                 sentPInfo.receiverPort = iter->second.port;
 
                 iter->second.sentPkts.push_back(std::move(pInfo));
-                while(iter->second.sentPkts.size() > UDPC_SENT_PKTS_MAX_SIZE) {
-                    iter->second.sentPkts.pop_front();
-                }
+                iter->second.cleanupSentPkts();
             } else {
-                // is not check-received, no data stored but other data is kept
+                // is not check-received, only id stored in data array
                 UDPC_PacketInfo sentPInfo;
                 sentPInfo.flags = 0x4;
                 sentPInfo.dataSize = 0;
@@ -452,12 +471,16 @@ void UDPC_update(void *ctx) {
                 sentPInfo.receiver = iter->first;
                 sentPInfo.senderPort = c->socketInfo.sin_port;
                 sentPInfo.receiverPort = iter->second.port;
+                *((uint32_t*)(sentPInfo.data + 8)) = iter->second.lseq - 1;
 
                 iter->second.sentPkts.push_back(std::move(pInfo));
-                while(iter->second.sentPkts.size() > UDPC_SENT_PKTS_MAX_SIZE) {
-                    iter->second.sentPkts.pop_front();
-                }
+                iter->second.cleanupSentPkts();
             }
+
+            // store other pkt info
+            UDPC::SentPktInfo::Ptr sentPktInfo = std::make_shared<UDPC::SentPktInfo>();
+            sentPktInfo->id = iter->second.lseq - 1;
+            iter->second.sentInfoMap.insert(std::make_pair(sentPktInfo->id, sentPktInfo));
         }
     }
 
@@ -541,6 +564,30 @@ void UDPC_update(void *ctx) {
     // packet is valid
     // TODO log received valid packet
 
+    // update rtt
+    for(auto sentIter = iter->second.sentPkts.rbegin(); sentIter != iter->second.sentPkts.rend(); ++sentIter) {
+        uint32_t id = *((uint32_t*)(sentIter->data + 8));
+        if(id == rseq) {
+            auto sentInfoIter = iter->second.sentInfoMap.find(id);
+            assert(sentInfoIter != iter->second.sentInfoMap.end()
+                    && "sentInfoMap should have known stored id");
+            float diff = UDPC::durationToFSec(sentInfoIter->second->sentTime, now);
+            if(diff > iter->second.rtt) {
+                iter->second.rtt += (diff - iter->second.rtt) / 10.0f;
+            } else {
+                iter->second.rtt -= (iter->second.rtt - diff) / 10.0f;
+            }
+
+            iter->second.flags.set(2, iter->second.rtt <= UDPC_GOOD_RTT_LIMIT_SEC);
+
+            // TODO verbose log rtt
+            break;
+        }
+    }
+
+    iter->second.received = now;
+    // TODO impl check pkt timeout
+
     // TODO impl
 }
 
index 5cd1cef8d3cf1dd4bf60dcbaa0a95d50e48b7d2c..bbd5160706f77c664d9820f70c4394dea7d2cec3 100644 (file)
@@ -47,6 +47,7 @@ extern "C" {
 typedef enum { SILENT, ERROR, WARNING, VERBOSE, INFO } UDPC_LoggingType;
 
 typedef struct {
+    // id is stored at offset 8, size 4 (uint32_t) even for "empty" PktInfos
     char data[UDPC_PACKET_MAX_SIZE];
     /*
      * 0x1 - connect