]> git.seodisparate.com - UDPConnection/commitdiff
Store connections based on both addr and port
authorStephen Seo <seo.disparate@gmail.com>
Tue, 27 Aug 2019 08:00:29 +0000 (17:00 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Tue, 27 Aug 2019 08:00:29 +0000 (17:00 +0900)
Previous implementation only stored based on addr only, preventing
connections from/to the same address but different ports.

cpp_impl/src/UDPC_Defines.hpp
cpp_impl/src/UDPConnection.cpp
cpp_impl/src/UDPConnection.h

index c6263b39ad378fccd502e419ab14e13990cbd512..0325b1ec500c726bbcb99dc1ab32d427f8b5ab1a 100644 (file)
@@ -50,6 +50,37 @@ struct SentPktInfo {
     std::chrono::steady_clock::time_point sentTime;
 };
 
+struct ConnectionIdentifier {
+    ConnectionIdentifier();
+    ConnectionIdentifier(uint32_t addr, uint16_t port);
+
+    // copy
+    ConnectionIdentifier(const ConnectionIdentifier& other) = default;
+    ConnectionIdentifier& operator =(const ConnectionIdentifier& other) = default;
+
+    // move
+    ConnectionIdentifier(ConnectionIdentifier&& other) = default;
+    ConnectionIdentifier& operator =(ConnectionIdentifier&& other) = default;
+
+    uint64_t id;
+
+    /// expects address to be in network byte order (big-endian)
+    void setAddr(uint32_t addr);
+    /// expects port to be in native order (not network byte order)
+    void setPort(uint16_t port);
+
+    /// returns address as a 4 byte unsigned int in network byte order (big-endian)
+    uint32_t getAddr() const;
+    /// returns port as a 2 byte unsigned int in native order (not network byte order)
+    uint16_t getPort() const;
+
+    bool operator ==(const ConnectionIdentifier& other) const;
+
+    struct Hasher {
+        std::size_t operator()(const ConnectionIdentifier& key) const;
+    };
+};
+
 struct ConnectionData {
     ConnectionData();
     ConnectionData(bool isServer, Context *ctx);
@@ -114,10 +145,10 @@ struct Context {
     struct sockaddr_in socketInfo;
 
     std::chrono::steady_clock::time_point lastUpdated;
-    // ipv4 address to ConnectionData
-    std::unordered_map<uint32_t, ConnectionData> conMap;
+    // ipv4 address and port to ConnectionData
+    std::unordered_map<ConnectionIdentifier, ConnectionData, ConnectionIdentifier::Hasher> conMap;
     // id to ipv4 address
-    std::unordered_map<uint32_t, uint32_t> idMap;
+    std::unordered_map<uint32_t, ConnectionIdentifier> idMap;
 
     std::default_random_engine rng_engine;
 
index ba2b6855d212bb14d8ee78558ae955eb9c5050e6..9c5ad2e760b8014daccca196676053a16116fa1c 100644 (file)
@@ -6,12 +6,48 @@
 #include <cstring>
 #include <optional>
 #include <vector>
+#include <functional>
 
 UDPC::SentPktInfo::SentPktInfo() :
 id(0),
 sentTime(std::chrono::steady_clock::now())
 {}
 
+UDPC::ConnectionIdentifier::ConnectionIdentifier() :
+id(0)
+{}
+
+UDPC::ConnectionIdentifier::ConnectionIdentifier(uint32_t addr, uint16_t port) :
+UDPC::ConnectionIdentifier::ConnectionIdentifier()
+{
+    *((uint32_t*)&id) = addr;
+    *((uint16_t*)(((unsigned char*)&id) + 4)) = port;
+}
+
+void UDPC::ConnectionIdentifier::setAddr(uint32_t addr) {
+    *((uint32_t*)&id) = addr;
+}
+
+void UDPC::ConnectionIdentifier::setPort(uint16_t port) {
+    *((uint16_t*)(((unsigned char*)&id) + 4)) = port;
+}
+
+uint32_t UDPC::ConnectionIdentifier::getAddr() const {
+    return *((uint32_t*)&id);
+}
+
+uint16_t UDPC::ConnectionIdentifier::getPort() const {
+    return *((uint16_t*)(((unsigned char*)&id) + 4));
+}
+
+bool UDPC::ConnectionIdentifier::operator==(const ConnectionIdentifier& other) const {
+    return id == other.id;
+}
+
+std::size_t UDPC::ConnectionIdentifier::Hasher::operator()(const ConnectionIdentifier& key) const {
+    return std::hash<uint64_t>()(key.id);
+}
+
 UDPC::ConnectionData::ConnectionData() :
 flags(),
 timer(std::chrono::steady_clock::duration::zero()),
@@ -230,7 +266,7 @@ void UDPC_update(void *ctx) {
     std::chrono::steady_clock::duration temp_dt_fs;
     {
         // check timed out, check good/bad mode with rtt, remove timed out
-        std::vector<uint32_t> removed;
+        std::vector<UDPC::ConnectionIdentifier> removed;
         for(auto iter = c->conMap.begin(); iter != c->conMap.end(); ++iter) {
             temp_dt_fs = now - iter->second.received;
             if(temp_dt_fs >= UDPC::CONNECTION_TIMEOUT) {
@@ -319,7 +355,7 @@ void UDPC_update(void *ctx) {
 
                 struct sockaddr_in destinationInfo;
                 destinationInfo.sin_family = AF_INET;
-                destinationInfo.sin_addr.s_addr = iter->first;
+                destinationInfo.sin_addr.s_addr = iter->first.getAddr();
                 destinationInfo.sin_port = htons(iter->second.port);
                 long int sentBytes = sendto(
                     c->socketHandle,
@@ -348,7 +384,7 @@ void UDPC_update(void *ctx) {
 
                 struct sockaddr_in destinationInfo;
                 destinationInfo.sin_family = AF_INET;
-                destinationInfo.sin_addr.s_addr = iter->first;
+                destinationInfo.sin_addr.s_addr = iter->first.getAddr();
                 destinationInfo.sin_port = htons(iter->second.port);
                 long int sentBytes = sendto(
                     c->socketHandle,
@@ -384,7 +420,7 @@ void UDPC_update(void *ctx) {
 
             struct sockaddr_in destinationInfo;
             destinationInfo.sin_family = AF_INET;
-            destinationInfo.sin_addr.s_addr = iter->first;
+            destinationInfo.sin_addr.s_addr = iter->first.getAddr();
             destinationInfo.sin_port = htons(iter->second.port);
             long int sentBytes = sendto(
                 c->socketHandle,
@@ -399,7 +435,7 @@ void UDPC_update(void *ctx) {
 
             UDPC_PacketInfo pInfo{{0}, 0, 0, 0, 0, 0, 0};
             pInfo.sender = UDPC::LOCAL_ADDR;
-            pInfo.receiver = iter->first;
+            pInfo.receiver = iter->first.getAddr();
             pInfo.senderPort = c->socketInfo.sin_port;
             pInfo.receiverPort = iter->second.port;
             *((uint32_t*)(pInfo.data + 8)) = htonl(iter->second.lseq - 1);
@@ -437,7 +473,7 @@ void UDPC_update(void *ctx) {
 
             struct sockaddr_in destinationInfo;
             destinationInfo.sin_family = AF_INET;
-            destinationInfo.sin_addr.s_addr = iter->first;
+            destinationInfo.sin_addr.s_addr = iter->first.getAddr();
             destinationInfo.sin_port = htons(iter->second.port);
             long int sentBytes = sendto(
                 c->socketHandle,
@@ -457,7 +493,7 @@ void UDPC_update(void *ctx) {
                 sentPInfo.flags = 0;
                 sentPInfo.dataSize = 20 + pInfo.dataSize;
                 sentPInfo.sender = UDPC::LOCAL_ADDR;
-                sentPInfo.receiver = iter->first;
+                sentPInfo.receiver = iter->first.getAddr();
                 sentPInfo.senderPort = c->socketInfo.sin_port;
                 sentPInfo.receiverPort = iter->second.port;
 
@@ -469,7 +505,7 @@ void UDPC_update(void *ctx) {
                 sentPInfo.flags = 0x4;
                 sentPInfo.dataSize = 0;
                 sentPInfo.sender = UDPC::LOCAL_ADDR;
-                sentPInfo.receiver = iter->first;
+                sentPInfo.receiver = iter->first.getAddr();
                 sentPInfo.senderPort = c->socketInfo.sin_port;
                 sentPInfo.receiverPort = iter->second.port;
                 *((uint32_t*)(sentPInfo.data + 8)) = htonl(iter->second.lseq - 1);
@@ -526,22 +562,24 @@ void UDPC_update(void *ctx) {
     bool isResending = conID & UDPC_ID_RESENDING;
     conID &= 0x0FFFFFFF;
 
+    UDPC::ConnectionIdentifier identifier(receivedData.sin_addr.s_addr, ntohs(receivedData.sin_port));
+
     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()) {
+                && c->conMap.find(identifier) == c->conMap.end()) {
             // is receiving as server, connection did not already exist
             // TODO log establishing connection with client peer
             UDPC::ConnectionData newConnection(true, c);
             newConnection.addr = receivedData.sin_addr.s_addr;
             newConnection.port = ntohs(receivedData.sin_port);
 
-            c->idMap.insert(std::make_pair(newConnection.id, newConnection.addr));
-            c->conMap.insert(std::make_pair(newConnection.addr, std::move(newConnection)));
+            c->idMap.insert(std::make_pair(newConnection.id, identifier));
+            c->conMap.insert(std::make_pair(identifier, std::move(newConnection)));
             // TODO trigger event server established connection with client
         } else if (c->flags.test(1)) {
             // is client
-            auto iter = c->conMap.find(receivedData.sin_addr.s_addr);
+            auto iter = c->conMap.find(identifier);
             if(iter == c->conMap.end() || !iter->second.flags.test(3)) {
                 return;
             }
@@ -553,7 +591,7 @@ void UDPC_update(void *ctx) {
         return;
     }
 
-    auto iter = c->conMap.find(receivedData.sin_addr.s_addr);
+    auto iter = c->conMap.find(identifier);
     if(iter == c->conMap.end() || iter->second.flags.test(3)
             || !iter->second.flags.test(4) || iter->second.id != conID) {
         return;
@@ -698,13 +736,15 @@ void UDPC_update(void *ctx) {
     }
 }
 
-int UDPC_get_queue_send_available(void *ctx, uint32_t addr) {
+int UDPC_get_queue_send_available(void *ctx, uint32_t addr, uint16_t port) {
     UDPC::Context *c = UDPC::verifyContext(ctx);
     if(!c) {
         return 0;
     }
 
-    auto iter = c->conMap.find(addr);
+    UDPC::ConnectionIdentifier identifier(addr, port);
+
+    auto iter = c->conMap.find(identifier);
     if(iter != c->conMap.end()) {
         return iter->second.sendPkts.capacity() - iter->second.sendPkts.size();
     } else {
@@ -712,7 +752,7 @@ int UDPC_get_queue_send_available(void *ctx, uint32_t addr) {
     }
 }
 
-void UDPC_queue_send(void *ctx, uint32_t destAddr,
+void UDPC_queue_send(void *ctx, uint32_t destAddr, uint16_t destPort,
                      uint32_t isChecked, void *data, uint32_t size) {
     if(size == 0 || !data) {
         return;
@@ -723,7 +763,9 @@ void UDPC_queue_send(void *ctx, uint32_t destAddr,
         return;
     }
 
-    auto iter = c->conMap.find(destAddr);
+    UDPC::ConnectionIdentifier identifier(destAddr, destPort);
+
+    auto iter = c->conMap.find(identifier);
     if(iter == c->conMap.end()) {
         // TODO log failed to add packet to queue; unknown recipient
         return;
@@ -749,13 +791,15 @@ int UDPC_set_accept_new_connections(void *ctx, int isAccepting) {
     return c->isAcceptNewConnections.exchange(isAccepting == 0 ? false : true);
 }
 
-int UDPC_drop_connection(void *ctx, uint32_t addr) {
+int UDPC_drop_connection(void *ctx, uint32_t addr, uint16_t port) {
     UDPC::Context *c = UDPC::verifyContext(ctx);
     if(!c) {
         return 0;
     }
 
-    auto iter = c->conMap.find(addr);
+    UDPC::ConnectionIdentifier identifier(addr, port);
+
+    auto iter = c->conMap.find(identifier);
     if(iter != c->conMap.end()) {
         c->conMap.erase(iter);
         return 1;
index 94a2383fca642071cb082b02a36caea6a3009053..31af2b406e58c4d294236f51b9d2a4fdcd0d688c 100644 (file)
@@ -63,7 +63,9 @@ typedef struct {
     uint16_t receiverPort;
 } UDPC_PacketInfo;
 
+/// listenPort must be in native byte order, listenAddr must be in network byte order (big-endian)
 void *UDPC_init(uint16_t listenPort, uint32_t listenAddr, int isClient);
+/// listenPort must be in native byte order, listenAddr must be in network byte order (big-endian)
 void *UDPC_init_threaded_update(uint16_t listenPort, uint32_t listenAddr,
                                 int isClient);
 
@@ -71,14 +73,18 @@ void UDPC_destroy(void *ctx);
 
 void UDPC_update(void *ctx);
 
-int UDPC_get_queue_send_available(void *ctx, uint32_t addr);
+/// port must be in native byte order, addr must be in network byte order (big-endian)
+int UDPC_get_queue_send_available(void *ctx, uint32_t addr, uint16_t port);
 
-void UDPC_queue_send(void *ctx, uint32_t destAddr,
+/// destPort must be in native byte order, destAddr must be in network byte order (big-endian)
+void UDPC_queue_send(void *ctx, uint32_t destAddr, uint16_t destPort,
                      uint32_t isChecked, void *data, uint32_t size);
 
 int UDPC_set_accept_new_connections(void *ctx, int isAccepting);
 
-int UDPC_drop_connection(void *ctx, uint32_t addr);
+// TODO implement drop_connection for all connections on an address and any port
+/// addr must be in network byte order (big-endian), port must be in native byte order
+int UDPC_drop_connection(void *ctx, uint32_t addr, uint16_t port);
 
 uint32_t UDPC_set_protocol_id(void *ctx, uint32_t id);
 
@@ -86,8 +92,10 @@ UDPC_LoggingType set_logging_type(void *ctx, UDPC_LoggingType loggingType);
 
 UDPC_PacketInfo UDPC_get_received(void *ctx);
 
+/// addr must be in network byte order
 const char *UDPC_atostr(void *ctx, uint32_t addr);
 
+/// returns a 4 byte unsigned integer address in network byte order
 uint32_t UDPC_strtoa(const char *addrStr);
 
 #ifdef __cplusplus