]> git.seodisparate.com - UDPConnection/commitdiff
Some WIP impl of receiving packet handling
authorStephen Seo <seo.disparate@gmail.com>
Sun, 18 Aug 2019 10:14:14 +0000 (19:14 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Sun, 18 Aug 2019 10:14:14 +0000 (19:14 +0900)
cpp_impl/src/UDPC_Defines.hpp
cpp_impl/src/UDPConnection.cpp

index f6f8ab678769279611bed749d109de635570fcee..5fc3a1210398e2d3221dd0eccebaae827b663056 100644 (file)
@@ -6,6 +6,7 @@
 #define UDPC_GOOD_MODE_SEND_INTERVAL (1.0f / 30.0f)
 #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_ID_CONNECT 0x80000000
 #define UDPC_ID_PING 0x40000000
@@ -18,6 +19,7 @@
 #include <cstdint>
 #include <deque>
 #include <unordered_map>
+#include <random>
 
 #include "TSQueue.hpp"
 #include "UDPConnection.h"
@@ -27,8 +29,14 @@ namespace UDPC {
 static uint32_t LOCAL_ADDR = 0;
 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);
+
+struct Context;
 
 struct ConnectionData {
+    ConnectionData();
+    ConnectionData(bool isServer, Context *ctx);
+
     /*
      * 0 - trigger send
      * 1 - is good mode
@@ -59,9 +67,11 @@ struct Context {
     Context(bool isThreaded);
 
     uint_fast32_t _contextIdentifier;
+    char recvBuf[UDPC_PACKET_MAX_SIZE];
     /*
      * 0 - is threaded
      * 1 - is client
+     * 2 - is accepting new connections
      */
     std::bitset<32> flags;
     std::atomic_bool isAcceptNewConnections;
@@ -73,9 +83,13 @@ struct Context {
     struct sockaddr_in socketInfo;
 
     std::chrono::steady_clock::time_point lastUpdated;
+    // ipv4 address to ConnectionData
     std::unordered_map<uint32_t, ConnectionData> conMap;
+    // id to ipv4 address
     std::unordered_map<uint32_t, uint32_t> idMap;
 
+    std::default_random_engine rng_engine;
+
 }; // struct Context
 
 Context *verifyContext(void *ctx);
@@ -92,6 +106,8 @@ bool isBigEndian();
 void preparePacket(char *data, uint32_t protocolID, uint32_t conID,
                    uint32_t rseq, uint32_t ack, uint32_t *seqID, int flags);
 
+uint32_t generateConnectionID(Context &ctx);
+
 } // namespace UDPC
 
 #endif
index 2407077abfe794e2b895e9d411f45fb609a44928..8cfd391a634dec6f9090058c57f58ab69359139a 100644 (file)
@@ -7,14 +7,36 @@
 #include <optional>
 #include <vector>
 
+UDPC::ConnectionData::ConnectionData() :
+flags(),
+sentPkts(),
+sendPkts(UDPC_QUEUED_PKTS_MAX_SIZE),
+priorityPkts(UDPC_QUEUED_PKTS_MAX_SIZE),
+received(std::chrono::steady_clock::now()),
+sent(std::chrono::steady_clock::now())
+{
+}
+
+UDPC::ConnectionData::ConnectionData(bool isServer, Context *ctx) :
+UDPC::ConnectionData::ConnectionData()
+{
+    if(isServer) {
+        flags.set(0);
+        flags.set(3);
+        id = UDPC::generateConnectionID(*ctx);
+        flags.set(4);
+    }
+}
+
 UDPC::Context::Context(bool isThreaded)
     : _contextIdentifier(UDPC_CONTEXT_IDENTIFIER), flags(),
       isAcceptNewConnections(true), protocolID(UDPC_DEFAULT_PROTOCOL_ID),
 #ifndef NDEBUG
-      loggingType(INFO)
+      loggingType(INFO),
 #else
-      loggingType(WARNING)
+      loggingType(WARNING),
 #endif
+      rng_engine()
 {
     if(isThreaded) {
         flags.set(0);
@@ -29,6 +51,8 @@ UDPC::Context::Context(bool isThreaded)
             UDPC::LOCAL_ADDR = 0x0100007F;
         }
     }
+
+    rng_engine.seed(std::chrono::system_clock::now().time_since_epoch().count());
 }
 
 UDPC::Context *UDPC::verifyContext(void *ctx) {
@@ -84,6 +108,15 @@ void UDPC::preparePacket(char *data, uint32_t protocolID, uint32_t conID,
     std::memcpy(data + 16, &temp, 4);
 }
 
+uint32_t UDPC::generateConnectionID(Context &ctx) {
+    auto dist = std::uniform_int_distribution<uint32_t>(0, 0xFFFFFFFF);
+    uint32_t id = dist(ctx.rng_engine);
+    while(ctx.idMap.find(id) != ctx.idMap.end()) {
+        id = dist(ctx.rng_engine);
+    }
+    return id;
+}
+
 void *UDPC_init(uint16_t listenPort, uint32_t listenAddr, int isClient) {
     UDPC::Context *ctx = new UDPC::Context(false);
 
@@ -423,7 +456,58 @@ void UDPC_update(void *ctx) {
         }
     }
 
-    // TODO receive packet
+    // receive packet
+#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
+    typedef int socklen_t;
+#endif
+    struct sockaddr_in receivedData;
+    socklen_t receivedDataSize = sizeof(receivedData);
+    int bytes = recvfrom(
+        c->socketHandle,
+        c->recvBuf,
+        UDPC_PACKET_MAX_SIZE,
+        0,
+        (struct sockaddr*) &receivedData,
+        &receivedDataSize);
+
+    if(bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
+        // no packet was received
+        return;
+    } else if(bytes < 20) {
+        // packet size is too small, invalid packet
+        // TODO log this
+        return;
+    }
+
+    uint32_t temp = ntohl(*((uint32_t*)c->recvBuf));
+    if(temp != c->protocolID) {
+        // Invalid protocol id in packet
+        // TODO log this
+        return;
+    }
+
+    uint32_t conID = ntohl(*((uint32_t*)(c->recvBuf + 4)));
+    uint32_t seqID = ntohl(*((uint32_t*)(c->recvBuf + 8)));
+    uint32_t rseq = ntohl(*((uint32_t*)(c->recvBuf + 12)));
+    uint32_t ack = htonl(*((uint32_t*)(c->recvBuf + 16)));
+
+    bool isConnect = conID & UDPC_ID_CONNECT;
+    bool isPing = conID & UDPC_ID_PING;
+    bool isNotRecChecked = conID & UDPC_ID_NO_REC_CHK;
+    bool isResending = conID & UDPC_ID_RESENDING;
+    conID &= 0x0FFFFFFF;
+
+    if(isConnect && c->flags.test(2)) {
+        // is connect packet and is accepting new connections
+        if(!c->flags.test(1)
+                && c->conMap.find(receivedData.sin_addr.s_addr) == c->conMap.end()) {
+            // is receiving as server, connection did not already exist
+            // TODO log establishing connection with client peer
+            UDPC::ConnectionData newConnection(true, c);
+            // TODO update idMap and conMap with new CD
+            // TODO impl establish connection with client peer as server
+        }
+    }
 
     // TODO impl
 }