]> git.seodisparate.com - UDPConnection/commitdiff
Impl disc. request (untested), del make_unique
authorStephen Seo <seo.disparate@gmail.com>
Tue, 17 Dec 2019 11:04:31 +0000 (20:04 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Tue, 17 Dec 2019 11:05:56 +0000 (20:05 +0900)
src/UDPC_Defines.hpp
src/UDPConnection.cpp
src/test/UDPC_NetworkTest.c

index 6afde2db8c14c98739d5f8116fd40bbaad4ad96c..f5d0c416b0b7663a014db19f151865ae4d2870a0 100644 (file)
@@ -224,6 +224,7 @@ public:
     std::unordered_map<UDPC_IPV6_ADDR_TYPE, std::unordered_set<UDPC_ConnectionId, ConnectionIdHasher>, IPV6_Hasher> addrConMap;
     // id to ipv6 address and port (as UDPC_ConnectionId)
     std::unordered_map<uint32_t, UDPC_ConnectionId> idMap;
+    std::unordered_set<UDPC_ConnectionId, ConnectionIdHasher> deletionMap;
     TSLQueue<UDPC_PacketInfo> receivedPkts;
     TSLQueue<UDPC_PacketInfo> cSendPkts;
     // handled internally
index 8ad59c8e7546161a80b3a86399e0a8a25214a661..b3e0e7b5a8efb9a5e695e53d3b559ffeee248ed3 100644 (file)
@@ -304,7 +304,7 @@ void UDPC::Context::update_impl() {
                     auto timeT = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
                     ss << std::put_time(std::gmtime(&timeT), "%c %Z");
                     auto timeString = ss.str();
-                    newCon.verifyMessage = std::make_unique<char[]>(4 + timeString.size());
+                    newCon.verifyMessage = std::unique_ptr<char[]>(new char[4 + timeString.size()]);
                     *((uint32_t*)newCon.verifyMessage.get()) = timeString.size();
                     std::memcpy(newCon.verifyMessage.get() + 4, timeString.c_str(), timeString.size());
 #ifndef NDEBUG
@@ -389,7 +389,7 @@ void UDPC::Context::update_impl() {
                     auto timeT = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
                     ss << std::put_time(std::gmtime(&timeT), "%c %Z");
                     auto timeString = ss.str();
-                    newCon.verifyMessage = std::make_unique<char[]>(4 + timeString.size());
+                    newCon.verifyMessage = std::unique_ptr<char[]>(new char[4 + timeString.size()]);
                     *((uint32_t*)newCon.verifyMessage.get()) = timeString.size();
                     std::memcpy(newCon.verifyMessage.get() + 4, timeString.c_str(), timeString.size());
 #ifndef NDEBUG
@@ -447,39 +447,17 @@ void UDPC::Context::update_impl() {
                         for(auto identIter = addrConIter->second.begin();
                                 identIter != addrConIter->second.end();
                                 ++identIter) {
-                            auto conIter = conMap.find(*identIter);
-                            assert(conIter != conMap.end() &&
-                                "conMap must have connection listed in addrConMap");
-                            if(conIter->second.flags.test(4)) {
-                                idMap.erase(conIter->second.id);
-                            }
-                            if(isReceivingEvents.load()) {
-                                externalEvents.push(UDPC_Event{
-                                    UDPC_ET_DISCONNECTED, conIter->first, false});
-                            }
-                            conMap.erase(conIter);
+                            assert(conMap.find(*identIter) != conMap.end()
+                                && "conMap must have connection listed in "
+                                "addrConMap");
+                            deletionMap.insert(*identIter);
                         }
-                        addrConMap.erase(addrConIter);
                     }
                 } else {
                     // drop only specific connection with addr and port
                     auto iter = conMap.find(optE->conId);
                     if(iter != conMap.end()) {
-                        if(iter->second.flags.test(4)) {
-                            idMap.erase(iter->second.id);
-                        }
-                        auto addrConIter = addrConMap.find(optE->conId.addr);
-                        if(addrConIter != addrConMap.end()) {
-                            addrConIter->second.erase(optE->conId);
-                            if(addrConIter->second.empty()) {
-                                addrConMap.erase(addrConIter);
-                            }
-                        }
-                        if(isReceivingEvents.load()) {
-                            externalEvents.push(UDPC_Event{
-                                UDPC_ET_DISCONNECTED, iter->first, false});
-                        }
-                        conMap.erase(iter);
+                        deletionMap.insert(iter->first);
                     }
                 }
                 break;
@@ -660,9 +638,83 @@ void UDPC::Context::update_impl() {
 
     // update send (only if triggerSend flag is set)
     for(auto iter = conMap.begin(); iter != conMap.end(); ++iter) {
-        if(!iter->second.flags.test(0)) {
+        auto delIter = deletionMap.find(iter->first);
+        if(!iter->second.flags.test(0) && delIter == deletionMap.end()) {
+            continue;
+        } else if(delIter != deletionMap.end()) {
+            if(iter->second.flags.test(3)) {
+                // not initiated connection yet, no need to send disconnect pkt
+                continue;
+            }
+            unsigned int sendSize = 0;
+            std::unique_ptr<char[]> buf;
+            if(flags.test(2) && iter->second.flags.test(6)) {
+                sendSize = UDPC_LSFULL_HEADER_SIZE;
+                buf = std::unique_ptr<char[]>(new char[sendSize]);
+                *((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 1;
+            } else {
+                sendSize = UDPC_NSFULL_HEADER_SIZE;
+                buf = std::unique_ptr<char[]>(new char[sendSize]);
+                *((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 0;
+            }
+            UDPC::preparePacket(
+                buf.get(),
+                protocolID,
+                iter->second.id,
+                iter->second.rseq,
+                iter->second.ack,
+                &iter->second.lseq,
+                0x3);
+            if(flags.test(2) && iter->second.flags.test(6)) {
+#ifdef UDPC_LIBSODIUM_ENABLED
+                if(crypto_sign_detached(
+                    (unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE + 1), nullptr,
+                    (unsigned char*)buf.get(), UDPC_MIN_HEADER_SIZE,
+                    iter->second.sk) != 0) {
+                    UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+                        "Failed to sign packet for peer ",
+                        UDPC_atostr((UDPC_HContext)this, iter->first.addr),
+                        ", port ",
+                        iter->second.port);
+                    continue;
+                }
+#else
+                assert(!"libsodium disabled, invalid state");
+                UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+                    "libsodium is disabled, cannot send packet");
+                continue;
+#endif
+            }
+
+            UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
+            destinationInfo.sin6_family = AF_INET6;
+            std::memcpy(
+                UDPC_IPV6_ADDR_SUB(destinationInfo.sin6_addr),
+                UDPC_IPV6_ADDR_SUB(iter->first.addr),
+                16);
+            destinationInfo.sin6_port = htons(iter->second.port);
+            destinationInfo.sin6_flowinfo = 0;
+            destinationInfo.sin6_scope_id = iter->first.scope_id;
+            long int sentBytes = sendto(
+                socketHandle,
+                buf.get(),
+                sendSize,
+                0,
+                (struct sockaddr*) &destinationInfo,
+                sizeof(UDPC_IPV6_SOCKADDR_TYPE));
+            if(sentBytes != sendSize) {
+                UDPC_CHECK_LOG(this,
+                    UDPC_LoggingType::UDPC_ERROR,
+                    "Failed to send disconnect packet to ",
+                    UDPC_atostr((UDPC_HContext)this, iter->first.addr),
+                    ", port = ",
+                    iter->second.port);
+                continue;
+            }
             continue;
         }
+
+        // clear triggerSend flag
         iter->second.flags.reset(0);
 
         if(iter->second.flags.test(3)) {
@@ -681,7 +733,7 @@ void UDPC::Context::update_impl() {
                     assert(iter->second.verifyMessage
                         && "Verify message should already exist");
                     sendSize = UDPC_CCL_HEADER_SIZE + *((uint32_t*)iter->second.verifyMessage.get());
-                    buf = std::make_unique<char[]>(sendSize);
+                    buf = std::unique_ptr<char[]>(new char[sendSize]);
                     // set type 1
                     *((uint32_t*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = htonl(1);
                     // set public key
@@ -708,7 +760,7 @@ void UDPC::Context::update_impl() {
 #endif
                 } else {
                     sendSize = UDPC_CON_HEADER_SIZE;
-                    buf = std::make_unique<char[]>(sendSize);
+                    buf = std::unique_ptr<char[]>(new char[sendSize]);
                     *((uint32_t*)(buf.get() + 20)) = 0;
                 }
                 UDPC::preparePacket(
@@ -758,7 +810,7 @@ void UDPC::Context::update_impl() {
                 if(flags.test(2) && iter->second.flags.test(6)) {
 #ifdef UDPC_LIBSODIUM_ENABLED
                     sendSize = UDPC_CSR_HEADER_SIZE;
-                    buf = std::make_unique<char[]>(sendSize);
+                    buf = std::unique_ptr<char[]>(new char[sendSize]);
                     // set type
                     *((uint32_t*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = htonl(2);
                     // set pubkey
@@ -780,7 +832,7 @@ void UDPC::Context::update_impl() {
 #endif
                 } else {
                     sendSize = UDPC_CON_HEADER_SIZE;
-                    buf = std::make_unique<char[]>(sendSize);
+                    buf = std::unique_ptr<char[]>(new char[sendSize]);
                     *((uint32_t*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 0;
                 }
                 UDPC::preparePacket(
@@ -834,11 +886,11 @@ void UDPC::Context::update_impl() {
             std::unique_ptr<char[]> buf;
             if(flags.test(2) && iter->second.flags.test(6)) {
                 sendSize = UDPC_LSFULL_HEADER_SIZE;
-                buf = std::make_unique<char[]>(sendSize);
+                buf = std::unique_ptr<char[]>(new char[sendSize]);
                 *((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 1;
             } else {
                 sendSize = UDPC_NSFULL_HEADER_SIZE;
-                buf = std::make_unique<char[]>(sendSize);
+                buf = std::unique_ptr<char[]>(new char[sendSize]);
                 *((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 0;
             }
             UDPC::preparePacket(
@@ -929,11 +981,11 @@ void UDPC::Context::update_impl() {
             unsigned int sendSize = 0;
             if(flags.test(2) && iter->second.flags.test(6)) {
                 sendSize = UDPC_LSFULL_HEADER_SIZE + pInfo.dataSize;
-                buf = std::make_unique<char[]>(sendSize);
+                buf = std::unique_ptr<char[]>(new char[sendSize]);
                 *((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 1;
             } else {
                 sendSize = UDPC_NSFULL_HEADER_SIZE + pInfo.dataSize;
-                buf = std::make_unique<char[]>(sendSize);
+                buf = std::unique_ptr<char[]>(new char[sendSize]);
                 *((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 0;
             }
 
@@ -1033,6 +1085,29 @@ void UDPC::Context::update_impl() {
         iter->second.sent = now;
     }
 
+    // remove queued for deletion
+    for(auto delIter = deletionMap.begin(); delIter != deletionMap.end(); ++delIter) {
+        auto iter = conMap.find(*delIter);
+        if(iter != conMap.end()) {
+            if(iter->second.flags.test(4)) {
+                idMap.erase(iter->second.id);
+            }
+            auto addrConIter = addrConMap.find(delIter->addr);
+            if(addrConIter != addrConMap.end()) {
+                addrConIter->second.erase(*delIter);
+                if(addrConIter->second.empty()) {
+                    addrConMap.erase(addrConIter);
+                }
+            }
+            if(isReceivingEvents.load()) {
+                externalEvents.push(UDPC_Event{
+                    UDPC_ET_DISCONNECTED, iter->first, false});
+            }
+            conMap.erase(iter);
+        }
+    }
+    deletionMap.clear();
+
     // receive packet
     UDPC_IPV6_SOCKADDR_TYPE receivedData;
     socklen_t receivedDataSize = sizeof(receivedData);
@@ -1095,8 +1170,9 @@ void UDPC::Context::update_impl() {
     bool isNotRecChecked = conID & UDPC_ID_NO_REC_CHK;
     bool isResending = conID & UDPC_ID_RESENDING;
     conID &= 0x0FFFFFFF;
+    UDPC_ConnectionId identifier{receivedData.sin6_addr, receivedData.sin6_scope_id, ntohs(receivedData.sin6_port)};
 
-    if(isConnect && bytes < (int)(UDPC_CON_HEADER_SIZE)) {
+    if(isConnect && !isPing && bytes < (int)(UDPC_CON_HEADER_SIZE)) {
         // invalid packet size
         UDPC_CHECK_LOG(this,
             UDPC_LoggingType::UDPC_VERBOSE,
@@ -1106,7 +1182,8 @@ void UDPC::Context::update_impl() {
             ntohs(receivedData.sin6_port),
             ", ignoring");
         return;
-    } else if (!isConnect && bytes < (int)UDPC_NSFULL_HEADER_SIZE) {
+    } else if ((!isConnect || (isConnect && isPing))
+            && bytes < (int)UDPC_NSFULL_HEADER_SIZE) {
         // packet is too small
         UDPC_CHECK_LOG(this,
             UDPC_LoggingType::UDPC_VERBOSE,
@@ -1118,10 +1195,8 @@ void UDPC::Context::update_impl() {
         return;
     }
 
-    UDPC_ConnectionId identifier{receivedData.sin6_addr, receivedData.sin6_scope_id, ntohs(receivedData.sin6_port)};
-
     uint32_t pktType = 0;
-    if(isConnect) {
+    if(isConnect && !isPing) {
         pktType = ntohl(*((uint32_t*)(recvBuf + UDPC_MIN_HEADER_SIZE)));
         switch(pktType) {
         case 0: // client/server connect with libsodium disabled
@@ -1153,7 +1228,7 @@ void UDPC::Context::update_impl() {
         }
     }
 
-    if(isConnect) {
+    if(isConnect && !isPing) {
         // is connect packet and is accepting new connections
         if(!flags.test(1)
                 && conMap.find(identifier) == conMap.end()
@@ -1227,7 +1302,7 @@ void UDPC::Context::update_impl() {
                     newConnection.peer_pk,
                     recvBuf + UDPC_MIN_HEADER_SIZE + 4,
                     crypto_sign_PUBLICKEYBYTES);
-                newConnection.verifyMessage = std::make_unique<char[]>(crypto_sign_BYTES);
+                newConnection.verifyMessage = std::unique_ptr<char[]>(new char[crypto_sign_BYTES]);
                 crypto_sign_detached(
                     (unsigned char*)newConnection.verifyMessage.get(),
                     nullptr,
@@ -1376,7 +1451,7 @@ void UDPC::Context::update_impl() {
     if(iter == conMap.end() || iter->second.flags.test(3)
             || !iter->second.flags.test(4) || iter->second.id != conID) {
         return;
-    } else if(isPing) {
+    } else if(isPing && !isConnect) {
         iter->second.flags.set(0);
     }
 
@@ -1417,6 +1492,32 @@ void UDPC::Context::update_impl() {
         ", good mode = ", iter->second.flags.test(1) ? "yes" : "no",
         isPing ? ", ping" : "");
 
+    // check if is delete
+    if(isConnect && isPing) {
+        auto conIter = conMap.find(identifier);
+        if(conIter != conMap.end()) {
+            UDPC_CHECK_LOG(this,
+                UDPC_LoggingType::UDPC_VERBOSE,
+                "Packet is request-disconnect packet, deleting connection...");
+            if(conIter->second.flags.test(4)) {
+                idMap.erase(conIter->second.id);
+            }
+            auto addrConIter = addrConMap.find(identifier.addr);
+            if(addrConIter != addrConMap.end()) {
+                addrConIter->second.erase(identifier);
+                if(addrConIter->second.empty()) {
+                    addrConMap.erase(addrConIter);
+                }
+            }
+            if(isReceivingEvents.load()) {
+                externalEvents.push(UDPC_Event{
+                    UDPC_ET_DISCONNECTED, identifier, false});
+            }
+            conMap.erase(conIter);
+            return;
+        }
+    }
+
     // update rtt
     for(auto sentIter = iter->second.sentPkts.rbegin(); sentIter != iter->second.sentPkts.rend(); ++sentIter) {
         uint32_t id = ntohl(*((uint32_t*)(sentIter->data + 8)));
index 8e7a0d8b47aafabb5c86c591dfd164a264a6a49f..2a8348e6ff76a90ecb27e84dfc98c15e120ab1c0 100644 (file)
@@ -304,6 +304,22 @@ int main(int argc, char **argv) {
             break;
         }
     }
+
+    UDPC_set_accept_new_connections(context, 0);
+
+    puts("Dropping all connections...");
+    UDPC_ConnectionId *ids = UDPC_get_list_connected(context, NULL);
+    UDPC_ConnectionId *current = ids;
+    while(current->scope_id != 0 && current->port != 0) {
+        UDPC_drop_connection(context, *current, 0);
+        ++current;
+    }
+    UDPC_free_list_connected(ids);
+
+    puts("Waiting 2 seconds for disconnect packets to be sent...");
+    sleep_seconds(2);
+
+    puts("Cleaning up UDPC context...");
     UDPC_destroy(context);
 
     return 0;