]> git.seodisparate.com - UDPConnection/commitdiff
Receive packets in loop til none left in interval
authorStephen Seo <seo.disparate@gmail.com>
Sun, 4 Dec 2022 10:57:37 +0000 (19:57 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Sun, 4 Dec 2022 10:58:13 +0000 (19:58 +0900)
Also some formatting fixes (max 80 chars in edited code).

src/UDPConnection.cpp

index a00f1570b19cb42bc4bc618b9529cf18213123f9..0bfe9f07d3a0ecc1ac9e0adf44d0d89b44c62d84 100644 (file)
@@ -1116,639 +1116,701 @@ void UDPC::Context::update_impl() {
     deletionMap.clear();
 
     // receive packet
-    UDPC_IPV6_SOCKADDR_TYPE receivedData;
-    socklen_t receivedDataSize = sizeof(receivedData);
-    int bytes = recvfrom(
-        socketHandle,
-        recvBuf,
-        UDPC_PACKET_MAX_SIZE,
-        0,
-        (struct sockaddr*) &receivedData,
-        &receivedDataSize);
+    do {
+        UDPC_IPV6_SOCKADDR_TYPE receivedData;
+        socklen_t receivedDataSize = sizeof(receivedData);
+        int bytes = recvfrom(
+            socketHandle,
+            recvBuf,
+            UDPC_PACKET_MAX_SIZE,
+            0,
+            (struct sockaddr*) &receivedData,
+            &receivedDataSize);
 
 #if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
-    if(bytes == 0) {
-        // connection closed
-        return;
-    } else if(bytes == SOCKET_ERROR) {
-        int error = WSAGetLastError();
-        if(error != WSAEWOULDBLOCK) {
-            UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
-                "Error receiving packet, ", error);
+        if(bytes == 0) {
+            // connection closed
+            return;
+        } else if(bytes == SOCKET_ERROR) {
+            int error = WSAGetLastError();
+            if(error != WSAEWOULDBLOCK) {
+                UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+                    "Error receiving packet, ", error);
+            }
+            return;
         }
-        return;
-    }
 #else
-    if(bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
-        // no packet was received
-        return;
-    }
+        if(bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
+            // no packet was received
+            return;
+        }
 #endif
-    else if(bytes < UDPC_MIN_HEADER_SIZE) {
-        // packet size is too small, invalid packet
-        UDPC_CHECK_LOG(this,
-            UDPC_LoggingType::UDPC_VERBOSE,
-            "Received packet is smaller than header, ignoring packet from ",
-            UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-            ", port = ",
-            ntohs(receivedData.sin6_port));
-        return;
-    }
-
-    uint32_t temp;
-    std::memcpy(&temp, recvBuf, 4);
-    temp = ntohl(temp);
-    if(temp != protocolID) {
-        // Invalid protocol id in packet
-        UDPC_CHECK_LOG(this,
-            UDPC_LoggingType::UDPC_VERBOSE,
-            "Received packet has invalid protocol id, ignoring packet from ",
-            UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-            ", port = ",
-            ntohs(receivedData.sin6_port));
-        return;
-    }
-
-    std::memcpy(&temp, recvBuf + 4, 4);
-    uint32_t conID = ntohl(temp);
-    std::memcpy(&temp, recvBuf + 8, 4);
-    uint32_t seqID = ntohl(temp);
-    std::memcpy(&temp, recvBuf + 12, 4);
-    uint32_t rseq = ntohl(temp);
-    std::memcpy(&temp, recvBuf + 16, 4);
-    uint32_t ack = ntohl(temp);
-
-    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;
-    UDPC_ConnectionId identifier = UDPC_create_id_full(receivedData.sin6_addr,
-                                                       receivedData.sin6_scope_id,
-                                                       ntohs(receivedData.sin6_port));
-
-    if(isConnect && !isPing && bytes < (int)(UDPC_CON_HEADER_SIZE)) {
-        // invalid packet size
-        UDPC_CHECK_LOG(this,
-            UDPC_LoggingType::UDPC_VERBOSE,
-            "Got connect packet of invalid size from ",
-            UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-            ", port = ",
-            ntohs(receivedData.sin6_port),
-            ", ignoring");
-        return;
-    } else if ((!isConnect || (isConnect && isPing))
-            && bytes < (int)UDPC_NSFULL_HEADER_SIZE) {
-        // packet is too small
-        UDPC_CHECK_LOG(this,
-            UDPC_LoggingType::UDPC_VERBOSE,
-            "Got non-connect packet of invalid size from ",
-            UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-            ", port = ",
-            ntohs(receivedData.sin6_port),
-            ", ignoring");
-        return;
-    }
+        else if(bytes < UDPC_MIN_HEADER_SIZE) {
+            // packet size is too small, invalid packet
+            UDPC_CHECK_LOG(this,
+                UDPC_LoggingType::UDPC_VERBOSE,
+                "Received packet is smaller than header, ignoring packet from ",
+                UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
+                ", port = ",
+                ntohs(receivedData.sin6_port));
+            return;
+        }
 
-    uint32_t pktType;
-    if(isConnect && !isPing) {
-        std::memcpy(&pktType, recvBuf + UDPC_MIN_HEADER_SIZE, 4);
-        pktType = ntohl(pktType);
-        switch(pktType) {
-        case 0: // client/server connect with libsodium disabled
-            break;
-        case 1: // client connect with libsodium enabled
-            break;
-        case 2: // server connect with libsodium enabled
-            break;
-        default:
-            UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
-                "Got invalid connect pktType from ",
+        uint32_t temp;
+        std::memcpy(&temp, recvBuf, 4);
+        temp = ntohl(temp);
+        if(temp != protocolID) {
+            // Invalid protocol id in packet
+            UDPC_CHECK_LOG(this,
+                UDPC_LoggingType::UDPC_VERBOSE,
+                "Received packet has invalid protocol id, ignoring packet "
+                "from ",
                 UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-                ", port ", ntohs(receivedData.sin6_port));
+                ", port = ",
+                ntohs(receivedData.sin6_port));
             return;
         }
-    } else {
-        if(recvBuf[UDPC_MIN_HEADER_SIZE] == 0) {
-            // not signed
-            pktType = 0;
-        } else if(recvBuf[UDPC_MIN_HEADER_SIZE] == 1) {
-            // signed
-            pktType = 1;
-        } else {
-            UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
-                "Got invalid pktType from ",
+
+        std::memcpy(&temp, recvBuf + 4, 4);
+        uint32_t conID = ntohl(temp);
+        std::memcpy(&temp, recvBuf + 8, 4);
+        uint32_t seqID = ntohl(temp);
+        std::memcpy(&temp, recvBuf + 12, 4);
+        uint32_t rseq = ntohl(temp);
+        std::memcpy(&temp, recvBuf + 16, 4);
+        uint32_t ack = ntohl(temp);
+
+        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;
+        UDPC_ConnectionId identifier =
+            UDPC_create_id_full(receivedData.sin6_addr,
+                                receivedData.sin6_scope_id,
+                                ntohs(receivedData.sin6_port));
+
+        if(isConnect && !isPing && bytes < (int)(UDPC_CON_HEADER_SIZE)) {
+            // invalid packet size
+            UDPC_CHECK_LOG(this,
+                UDPC_LoggingType::UDPC_VERBOSE,
+                "Got connect packet of invalid size from ",
                 UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-                ", port ", ntohs(receivedData.sin6_port));
+                ", port = ",
+                ntohs(receivedData.sin6_port),
+                ", ignoring");
+            return;
+        } else if ((!isConnect || (isConnect && isPing))
+                && bytes < (int)UDPC_NSFULL_HEADER_SIZE) {
+            // packet is too small
+            UDPC_CHECK_LOG(this,
+                UDPC_LoggingType::UDPC_VERBOSE,
+                "Got non-connect packet of invalid size from ",
+                UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
+                ", port = ",
+                ntohs(receivedData.sin6_port),
+                ", ignoring");
             return;
         }
-    }
 
-    if(isConnect && !isPing) {
-        // is connect packet and is accepting new connections
-        std::lock_guard<std::mutex> conMapLock(conMapMutex);
-        if(!flags.test(1)
-                && conMap.find(identifier) == conMap.end()
-                && isAcceptNewConnections.load()) {
-            // is receiving as server, connection did not already exist
-            int authPolicy = this->authPolicy.load();
-            if(pktType == 1 && !flags.test(2)
-                    && authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
-                UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
-                    "Client peer ",
+        uint32_t pktType;
+        if(isConnect && !isPing) {
+            std::memcpy(&pktType, recvBuf + UDPC_MIN_HEADER_SIZE, 4);
+            pktType = ntohl(pktType);
+            switch(pktType) {
+            case 0: // client/server connect with libsodium disabled
+                break;
+            case 1: // client connect with libsodium enabled
+                break;
+            case 2: // server connect with libsodium enabled
+                break;
+            default:
+                UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
+                    "Got invalid connect pktType from ",
                     UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-                    " port ",
-                    ntohs(receivedData.sin6_port),
-                    " attempted connection with packet authentication "
-                    "enabled, but auth is disabled and AuthPolicy is STRICT");
+                    ", port ", ntohs(receivedData.sin6_port));
                 return;
-            } else if(pktType == 0 && flags.test(2)
-                    && authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
-                UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
-                    "Client peer ",
+            }
+        } else {
+            if(recvBuf[UDPC_MIN_HEADER_SIZE] == 0) {
+                // not signed
+                pktType = 0;
+            } else if(recvBuf[UDPC_MIN_HEADER_SIZE] == 1) {
+                // signed
+                pktType = 1;
+            } else {
+                UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
+                    "Got invalid pktType from ",
                     UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-                    " port ",
-                    ntohs(receivedData.sin6_port),
-                    " attempted connection with packet authentication "
-                    "disabled, but auth is enabled and AuthPolicy is STRICT");
+                    ", port ", ntohs(receivedData.sin6_port));
                 return;
             }
-            unsigned char *sk = nullptr;
-            unsigned char *pk = nullptr;
-            if(keysSet.load()) {
-                sk = this->sk;
-                pk = this->pk;
-            }
-            UDPC::ConnectionData newConnection(
-                true,
-                this,
-                receivedData.sin6_addr,
-                receivedData.sin6_scope_id,
-                ntohs(receivedData.sin6_port),
+        }
+
+        if(isConnect && !isPing) {
+            // is connect packet and is accepting new connections
+            std::lock_guard<std::mutex> conMapLock(conMapMutex);
+            if(!flags.test(1)
+                    && conMap.find(identifier) == conMap.end()
+                    && isAcceptNewConnections.load()) {
+                // is receiving as server, connection did not already exist
+                int authPolicy = this->authPolicy.load();
+                if(pktType == 1 && !flags.test(2)
+                        && authPolicy
+                            == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
+                    UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+                        "Client peer ",
+                        UDPC_atostr(
+                            (UDPC_HContext)this, receivedData.sin6_addr),
+                        " port ",
+                        ntohs(receivedData.sin6_port),
+                        " attempted connection with packet authentication "
+                        "enabled, but auth is disabled and AuthPolicy is "
+                        "STRICT");
+                    return;
+                } else if(pktType == 0 && flags.test(2)
+                        && authPolicy
+                            == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
+                    UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+                        "Client peer ",
+                        UDPC_atostr(
+                            (UDPC_HContext)this, receivedData.sin6_addr),
+                        " port ",
+                        ntohs(receivedData.sin6_port),
+                        " attempted connection with packet authentication "
+                        "disabled, but auth is enabled and AuthPolicy is "
+                        "STRICT");
+                    return;
+                }
+                unsigned char *sk = nullptr;
+                unsigned char *pk = nullptr;
+                if(keysSet.load()) {
+                    sk = this->sk;
+                    pk = this->pk;
+                }
+                UDPC::ConnectionData newConnection(
+                    true,
+                    this,
+                    receivedData.sin6_addr,
+                    receivedData.sin6_scope_id,
+                    ntohs(receivedData.sin6_port),
 #ifdef UDPC_LIBSODIUM_ENABLED
-                pktType == 1 && flags.test(2),
-                sk, pk);
+                    pktType == 1 && flags.test(2),
+                    sk, pk);
 #else
-                false,
-                sk, pk);
+                    false,
+                    sk, pk);
 #endif
 
-            if(newConnection.flags.test(5)) {
-                UDPC_CHECK_LOG(this,
-                    UDPC_LoggingType::UDPC_ERROR,
-                    "Failed to init ConnectionData instance (libsodium init "
-                    "fail) while server establishing connection with ",
-                    UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-                    ", port = ",
-                    ntohs(receivedData.sin6_port));
-                return;
-            }
-            if(pktType == 1 && flags.test(2)) {
+                if(newConnection.flags.test(5)) {
+                    UDPC_CHECK_LOG(this,
+                        UDPC_LoggingType::UDPC_ERROR,
+                        "Failed to init ConnectionData instance (libsodium init"
+                        " fail) while server establishing connection with ",
+                        UDPC_atostr(
+                            (UDPC_HContext)this, receivedData.sin6_addr),
+                        ", port = ",
+                        ntohs(receivedData.sin6_port));
+                    return;
+                }
+                if(pktType == 1 && flags.test(2)) {
 #ifdef UDPC_LIBSODIUM_ENABLED
-                std::memcpy(
-                    newConnection.peer_pk,
-                    recvBuf + UDPC_MIN_HEADER_SIZE + 4,
-                    crypto_sign_PUBLICKEYBYTES);
-                {
-                    std::lock_guard<std::mutex> pkWhitelistLock(peerPKWhitelistMutex);
-                    if(!peerPKWhitelist.empty() && peerPKWhitelist.find(UDPC::PKContainer(newConnection.peer_pk)) == peerPKWhitelist.end()) {
-                        UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
-                            "peer_pk is not in whitelist, not establishing "
-                            "connection with client");
-                        return;
+                    std::memcpy(
+                        newConnection.peer_pk,
+                        recvBuf + UDPC_MIN_HEADER_SIZE + 4,
+                        crypto_sign_PUBLICKEYBYTES);
+                    {
+                        std::lock_guard<std::mutex>
+                            pkWhitelistLock(peerPKWhitelistMutex);
+                        if(!peerPKWhitelist.empty()
+                                && peerPKWhitelist.find(
+                                    UDPC::PKContainer(newConnection.peer_pk))
+                                        == peerPKWhitelist.end()) {
+                            UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
+                                "peer_pk is not in whitelist, not establishing "
+                                "connection with client");
+                            return;
+                        }
                     }
-                }
-                newConnection.verifyMessage = std::unique_ptr<char[]>(new char[crypto_sign_BYTES]);
-                std::time_t currentTime = std::time(nullptr);
-                uint64_t receivedTime;
-                std::memcpy(
-                    &receivedTime,
-                    recvBuf + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES + 4,
-                    8);
-                UDPC::be64((char*)&receivedTime);
+                    newConnection.verifyMessage =
+                        std::unique_ptr<char[]>(new char[crypto_sign_BYTES]);
+                    std::time_t currentTime = std::time(nullptr);
+                    uint64_t receivedTime;
+                    std::memcpy(
+                        &receivedTime,
+                        recvBuf + UDPC_MIN_HEADER_SIZE + 4
+                            + crypto_sign_PUBLICKEYBYTES + 4,
+                        8);
+                    UDPC::be64((char*)&receivedTime);
 # ifndef NDEBUG
-                if(willLog(UDPC_LoggingType::UDPC_DEBUG)) {
-                    log_impl(UDPC_LoggingType::UDPC_DEBUG,
-                        "Server got verification epoch time \"",
-                        receivedTime, "\"");
-                }
+                    if(willLog(UDPC_LoggingType::UDPC_DEBUG)) {
+                        log_impl(UDPC_LoggingType::UDPC_DEBUG,
+                            "Server got verification epoch time \"",
+                            receivedTime, "\"");
+                    }
 # endif
-                std::time_t receivedTimeT = receivedTime;
-                if(currentTime < receivedTimeT || currentTime - receivedTimeT > 3) {
-                    UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
-                        "Got invalid epoch time from client, ignoring");
-                    return;
-                }
-                crypto_sign_detached(
-                    (unsigned char*)newConnection.verifyMessage.get(),
-                    nullptr,
-                    (unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES),
-                    12,
-                    newConnection.sk);
+                    std::time_t receivedTimeT = receivedTime;
+                    if(currentTime < receivedTimeT
+                            || currentTime - receivedTimeT > 3) {
+                        UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
+                            "Got invalid epoch time from client, ignoring");
+                        return;
+                    }
+                    crypto_sign_detached(
+                        (unsigned char*)newConnection.verifyMessage.get(),
+                        nullptr,
+                        (unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4
+                            + crypto_sign_PUBLICKEYBYTES),
+                        12,
+                        newConnection.sk);
 #else
-                assert(!"libsodium disabled, invalid state");
-                UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
-                    "libsodium is disabled, cannot process received packet");
-                return;
+                    assert(!"libsodium disabled, invalid state");
+                    UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+                        "libsodium is disabled, cannot process received "
+                        "packet");
+                    return;
 #endif
-            }
-            UDPC_CHECK_LOG(this,
-                UDPC_LoggingType::UDPC_INFO,
-                "Establishing connection with client ",
-                UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-                ", port = ",
-                ntohs(receivedData.sin6_port),
-                ", giving client id = ", newConnection.id,
-                pktType == 1 && flags.test(2) ?
-                    ", libsodium enabled" : ", libsodium disabled");
-
-            idMap.insert(std::make_pair(newConnection.id, identifier));
-            conMap.insert(std::make_pair(identifier, std::move(newConnection)));
-            auto addrConIter = addrConMap.find(identifier.addr);
-            if(addrConIter == addrConMap.end()) {
-                auto insertResult = addrConMap.insert(
-                    std::make_pair(
-                        identifier.addr,
-                        std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher>{}
-                    ));
-                assert(insertResult.second
-                        && "Must successfully insert into addrConMap");
-                addrConIter = insertResult.first;
-            }
-            addrConIter->second.insert(identifier);
-            if(isReceivingEvents.load()) {
-                std::lock_guard<std::mutex> extEvLock(externalEventsMutex);
-                externalEvents.push_back(UDPC_Event{
-                    UDPC_ET_CONNECTED,
-                    identifier,
-                    false});
-            }
-        } else if (flags.test(1)) {
-            // is client
-            auto iter = conMap.find(identifier);
-            if(iter == conMap.end() || !iter->second.flags.test(3)) {
-                UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_DEBUG,
-                    "client dropped pkt from ",
-                    UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-                    ", port ", ntohs(receivedData.sin6_port));
-                return;
-            }
-            int authPolicy = this->authPolicy.load();
-            if(pktType == 2 && !iter->second.flags.test(6)
-                    && authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
-                // This block actually should never happen, because the server
-                // receives a packet first. If client requests without auth,
-                // then the server will either deny connection (if strict) or
-                // fallback to a connection without auth (if fallback).
-                UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
-                    "Server peer ",
-                    UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-                    " port ",
-                    ntohs(receivedData.sin6_port),
-                    " attempted connection with packet authentication "
-                    "enabled, but auth is disabled and AuthPolicy is STRICT");
-                return;
-            } else if(pktType == 0 && iter->second.flags.test(6)
-                    && authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
-                UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
-                    "Server peer ",
+                }
+                UDPC_CHECK_LOG(this,
+                    UDPC_LoggingType::UDPC_INFO,
+                    "Establishing connection with client ",
                     UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-                    " port ",
+                    ", port = ",
                     ntohs(receivedData.sin6_port),
-                    " attempted connection with packet authentication "
-                    "disabled, but auth is enabled and AuthPolicy is STRICT");
-                return;
-            }
+                    ", giving client id = ", newConnection.id,
+                    pktType == 1 && flags.test(2) ?
+                        ", libsodium enabled" : ", libsodium disabled");
+
+                idMap.insert(std::make_pair(newConnection.id, identifier));
+                conMap.insert(std::make_pair(identifier,
+                                             std::move(newConnection)));
+                auto addrConIter = addrConMap.find(identifier.addr);
+                if(addrConIter == addrConMap.end()) {
+                    auto insertResult = addrConMap.insert(
+                        std::make_pair(
+                            identifier.addr,
+                            std::unordered_set<UDPC_ConnectionId,
+                                               UDPC::ConnectionIdHasher>{}
+                        ));
+                    assert(insertResult.second
+                            && "Must successfully insert into addrConMap");
+                    addrConIter = insertResult.first;
+                }
+                addrConIter->second.insert(identifier);
+                if(isReceivingEvents.load()) {
+                    std::lock_guard<std::mutex> extEvLock(externalEventsMutex);
+                    externalEvents.push_back(UDPC_Event{
+                        UDPC_ET_CONNECTED,
+                        identifier,
+                        false});
+                }
+            } else if (flags.test(1)) {
+                // is client
+                auto iter = conMap.find(identifier);
+                if(iter == conMap.end() || !iter->second.flags.test(3)) {
+                    UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_DEBUG,
+                        "client dropped pkt from ",
+                        UDPC_atostr(
+                            (UDPC_HContext)this, receivedData.sin6_addr),
+                        ", port ", ntohs(receivedData.sin6_port));
+                    return;
+                }
+                int authPolicy = this->authPolicy.load();
+                if(pktType == 2 && !iter->second.flags.test(6)
+                        && authPolicy
+                            == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
+                    // This block actually should never happen, because the
+                    // server receives a packet first. If client requests
+                    // without auth, then the server will either deny
+                    // connection (if strict) or fallback to a connection
+                    // without auth (if fallback).
+                    UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+                        "Server peer ",
+                        UDPC_atostr(
+                            (UDPC_HContext)this, receivedData.sin6_addr),
+                        " port ",
+                        ntohs(receivedData.sin6_port),
+                        " attempted connection with packet authentication "
+                        "enabled, but auth is disabled and AuthPolicy is "
+                        "STRICT");
+                    return;
+                } else if(pktType == 0 && iter->second.flags.test(6)
+                        && authPolicy
+                            == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
+                    UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+                        "Server peer ",
+                        UDPC_atostr(
+                            (UDPC_HContext)this, receivedData.sin6_addr),
+                        " port ",
+                        ntohs(receivedData.sin6_port),
+                        " attempted connection with packet authentication "
+                        "disabled, but auth is enabled and AuthPolicy is "
+                        "STRICT");
+                    return;
+                }
 
-            if(pktType == 2 && flags.test(2) && iter->second.flags.test(6)) {
+                if(pktType == 2 && flags.test(2)
+                        && iter->second.flags.test(6)) {
 #ifdef UDPC_LIBSODIUM_ENABLED
-                std::memcpy(iter->second.peer_pk,
-                    recvBuf + UDPC_MIN_HEADER_SIZE + 4,
-                    crypto_sign_PUBLICKEYBYTES);
-                {
-                    std::lock_guard<std::mutex> pkWhitelistLock(peerPKWhitelistMutex);
-                    if(!peerPKWhitelist.empty() && peerPKWhitelist.find(UDPC::PKContainer(iter->second.peer_pk)) == peerPKWhitelist.end()) {
+                    std::memcpy(iter->second.peer_pk,
+                        recvBuf + UDPC_MIN_HEADER_SIZE + 4,
+                        crypto_sign_PUBLICKEYBYTES);
+                    {
+                        std::lock_guard<std::mutex>
+                            pkWhitelistLock(peerPKWhitelistMutex);
+                        if(!peerPKWhitelist.empty()
+                                && peerPKWhitelist.find(
+                                    UDPC::PKContainer(iter->second.peer_pk))
+                                        == peerPKWhitelist.end()) {
+                            UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
+                                "peer_pk is not in whitelist, not establishing "
+                                "connection with server");
+                            return;
+                        }
+                    }
+                    if(crypto_sign_verify_detached(
+                        (unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4
+                            + crypto_sign_PUBLICKEYBYTES),
+                        (unsigned char*)(iter->second.verifyMessage.get()),
+                        12,
+                        iter->second.peer_pk) != 0) {
                         UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
-                            "peer_pk is not in whitelist, not establishing "
-                            "connection with server");
+                            "Failed to verify peer (server) ",
+                            UDPC_atostr(
+                                (UDPC_HContext)this, receivedData.sin6_addr),
+                            ", port = ",
+                            ntohs(receivedData.sin6_port));
                         return;
                     }
-                }
-                if(crypto_sign_verify_detached(
-                    (unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES),
-                    (unsigned char*)(iter->second.verifyMessage.get()),
-                    12,
-                    iter->second.peer_pk) != 0) {
-                    UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
-                        "Failed to verify peer (server) ",
-                        UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-                        ", port = ",
-                        ntohs(receivedData.sin6_port));
-                    return;
-                }
 #else
-                assert(!"libsodium disabled, invalid state");
-                UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
-                    "libsodium is disabled, cannot process received packet");
-                return;
+                    assert(!"libsodium disabled, invalid state");
+                    UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+                        "libsodium is disabled, cannot process received "
+                        "packet");
+                    return;
 #endif
-            } else if(pktType == 0 && iter->second.flags.test(6)) {
-                iter->second.flags.reset(6);
-                if(iter->second.flags.test(7)) {
-                    UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
-                        "peer is not using libsodium, but peer_pk was "
-                        "pre-set, dropping to no-verification mode");
+                } else if(pktType == 0 && iter->second.flags.test(6)) {
+                    iter->second.flags.reset(6);
+                    if(iter->second.flags.test(7)) {
+                        UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
+                            "peer is not using libsodium, but peer_pk was "
+                            "pre-set, dropping to no-verification mode");
+                    }
                 }
-            }
 
-            iter->second.flags.reset(3);
-            iter->second.id = conID;
-            iter->second.flags.set(4);
-            UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_INFO,
-                "Established connection with server ",
-                UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-                ", port = ",
-                ntohs(receivedData.sin6_port),
-                ", got id = ", conID,
-                flags.test(2) && iter->second.flags.test(6) ?
-                    ", libsodium enabled" : ", libsodium disabled");
-            if(isReceivingEvents.load()) {
-                std::lock_guard<std::mutex> extEvLock(externalEventsMutex);
-                externalEvents.push_back(UDPC_Event{
-                    UDPC_ET_CONNECTED,
-                    identifier,
-                    false});
+                iter->second.flags.reset(3);
+                iter->second.id = conID;
+                iter->second.flags.set(4);
+                UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_INFO,
+                    "Established connection with server ",
+                    UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
+                    ", port = ",
+                    ntohs(receivedData.sin6_port),
+                    ", got id = ", conID,
+                    flags.test(2) && iter->second.flags.test(6) ?
+                        ", libsodium enabled" : ", libsodium disabled");
+                if(isReceivingEvents.load()) {
+                    std::lock_guard<std::mutex> extEvLock(externalEventsMutex);
+                    externalEvents.push_back(UDPC_Event{
+                        UDPC_ET_CONNECTED,
+                        identifier,
+                        false});
+                }
             }
+            return;
         }
-        return;
-    }
 
-    std::lock_guard<std::mutex> conMapLock(conMapMutex);
-    auto iter = conMap.find(identifier);
-    if(iter == conMap.end() || iter->second.flags.test(3)
-            || !iter->second.flags.test(4) || iter->second.id != conID) {
-        return;
-    } else if(isPing && !isConnect) {
-        iter->second.flags.set(0);
-    }
-
-    if(pktType == 1) {
-#ifdef UDPC_LIBSODIUM_ENABLED
-        // verify signature of header
-        unsigned char sig[crypto_sign_BYTES];
-        std::memcpy(sig, recvBuf + UDPC_MIN_HEADER_SIZE + 1, crypto_sign_BYTES);
-        std::memset(recvBuf + UDPC_MIN_HEADER_SIZE + 1, 0, crypto_sign_BYTES);
-        if(crypto_sign_verify_detached(
-            sig,
-            (unsigned char*)recvBuf,
-            bytes,
-            iter->second.peer_pk) != 0) {
-            UDPC_CHECK_LOG(
-                this,
-                UDPC_LoggingType::UDPC_INFO,
-                "Failed to verify received packet from",
-                UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-                ", port = ",
-                ntohs(receivedData.sin6_port),
-                ", ignoring");
+        std::lock_guard<std::mutex> conMapLock(conMapMutex);
+        auto iter = conMap.find(identifier);
+        if(iter == conMap.end() || iter->second.flags.test(3)
+                || !iter->second.flags.test(4) || iter->second.id != conID) {
             return;
+        } else if(isPing && !isConnect) {
+            iter->second.flags.set(0);
         }
+
+        if(pktType == 1) {
+#ifdef UDPC_LIBSODIUM_ENABLED
+            // verify signature of header
+            unsigned char sig[crypto_sign_BYTES];
+            std::memcpy(sig,
+                        recvBuf + UDPC_MIN_HEADER_SIZE + 1,
+                        crypto_sign_BYTES);
+            std::memset(recvBuf + UDPC_MIN_HEADER_SIZE + 1,
+                        0,
+                        crypto_sign_BYTES);
+            if(crypto_sign_verify_detached(
+                sig,
+                (unsigned char*)recvBuf,
+                bytes,
+                iter->second.peer_pk) != 0) {
+                UDPC_CHECK_LOG(
+                    this,
+                    UDPC_LoggingType::UDPC_INFO,
+                    "Failed to verify received packet from",
+                    UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
+                    ", port = ",
+                    ntohs(receivedData.sin6_port),
+                    ", ignoring");
+                return;
+            }
 #else
-        assert(!"libsodium disabled, invalid state");
-        UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
-            "libsodium is disabled, cannot process received packet");
-        return;
+            assert(!"libsodium disabled, invalid state");
+            UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+                "libsodium is disabled, cannot process received packet");
+            return;
 #endif
-    }
+        }
 
-    // packet is valid
-    UDPC_CHECK_LOG(this,
-        UDPC_LoggingType::UDPC_VERBOSE,
-        "Received valid packet from ",
-        UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
-        ", port = ",
-        ntohs(receivedData.sin6_port),
-        ", packet id = ", seqID,
-        ", good mode = ", iter->second.flags.test(1) ? "yes" : "no",
-        isPing && !isConnect ? ", ping"
-            : (isPing && isConnect ? ", disc" : ""));
-
-    // 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);
+        // packet is valid
+        UDPC_CHECK_LOG(this,
+            UDPC_LoggingType::UDPC_VERBOSE,
+            "Received valid packet from ",
+            UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
+            ", port = ",
+            ntohs(receivedData.sin6_port),
+            ", packet id = ", seqID,
+            ", good mode = ", iter->second.flags.test(1) ? "yes" : "no",
+            isPing && !isConnect ? ", ping"
+                : (isPing && isConnect ? ", disc" : ""));
+
+        // 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()) {
+                    std::lock_guard<std::mutex> extEvLock(externalEventsMutex);
+                    externalEvents.push_back(UDPC_Event{
+                        UDPC_ET_DISCONNECTED, identifier, false});
+                }
+                conMap.erase(conIter);
+                return;
             }
-            if(isReceivingEvents.load()) {
-                std::lock_guard<std::mutex> extEvLock(externalEventsMutex);
-                externalEvents.push_back(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;
-        std::memcpy(&id, sentIter->data + 8, 4);
-        id = ntohl(id);
-        if(id == rseq) {
-            auto sentInfoIter = iter->second.sentInfoMap.find(id);
-            assert(sentInfoIter != iter->second.sentInfoMap.end()
-                    && "sentInfoMap should have known stored id");
-            auto diff = now - sentInfoIter->second->sentTime;
-            if(diff > iter->second.rtt) {
-                iter->second.rtt += (diff - iter->second.rtt) / 10;
-            } else {
-                iter->second.rtt -= (iter->second.rtt - diff) / 10;
-            }
+        // update rtt
+        for(auto sentIter = iter->second.sentPkts.rbegin();
+                sentIter != iter->second.sentPkts.rend();
+                ++sentIter) {
+            uint32_t id;
+            std::memcpy(&id, sentIter->data + 8, 4);
+            id = ntohl(id);
+            if(id == rseq) {
+                auto sentInfoIter = iter->second.sentInfoMap.find(id);
+                assert(sentInfoIter != iter->second.sentInfoMap.end()
+                        && "sentInfoMap should have known stored id");
+                auto diff = now - sentInfoIter->second->sentTime;
+                if(diff > iter->second.rtt) {
+                    iter->second.rtt += (diff - iter->second.rtt) / 10;
+                } else {
+                    iter->second.rtt -= (iter->second.rtt - diff) / 10;
+                }
 
-            iter->second.flags.set(2, iter->second.rtt <= UDPC::GOOD_RTT_LIMIT);
+                iter->second.flags.set(
+                    2, iter->second.rtt <= UDPC::GOOD_RTT_LIMIT);
 
-            UDPC_CHECK_LOG(this,
-                UDPC_LoggingType::UDPC_VERBOSE,
-                "RTT: ",
-                UDPC::durationToFSec(iter->second.rtt) * 1000.0f,
-                " milliseconds");
-            break;
+                UDPC_CHECK_LOG(this,
+                    UDPC_LoggingType::UDPC_VERBOSE,
+                    "RTT: ",
+                    UDPC::durationToFSec(iter->second.rtt) * 1000.0f,
+                    " milliseconds");
+                break;
+            }
         }
-    }
 
-    iter->second.received = now;
+        iter->second.received = now;
 
-    // check pkt timeout
-    --rseq;
-    for(; ack != 0; ack = ack << 1) {
-        if((ack & 0x80000000) != 0) {
-            --rseq;
-            continue;
-        }
+        // check pkt timeout
+        --rseq;
+        for(; ack != 0; ack = ack << 1) {
+            if((ack & 0x80000000) != 0) {
+                --rseq;
+                continue;
+            }
 
-        // pkt not received yet, find it in sent to check if it timed out
-        for(auto sentIter = iter->second.sentPkts.rbegin(); sentIter != iter->second.sentPkts.rend(); ++sentIter) {
-            uint32_t sentID;
-            std::memcpy(&sentID, sentIter->data + 8, 4);
-            sentID = ntohl(sentID);
-            if(sentID == rseq) {
-                if((sentIter->flags & 0x4) != 0 || (sentIter->flags & 0x8) != 0) {
-                    // already resent or not rec-checked pkt
-                    break;
-                }
-                auto sentInfoIter = iter->second.sentInfoMap.find(sentID);
-                assert(sentInfoIter != iter->second.sentInfoMap.end()
-                        && "Every entry in sentPkts must have a corresponding entry in sentInfoMap");
-                auto duration = now - sentInfoIter->second->sentTime;
-                if(duration > UDPC::PACKET_TIMEOUT_TIME) {
-                    bool pktSigned = sentIter->data[UDPC_MIN_HEADER_SIZE] == 1;
-                    if((pktSigned && sentIter->dataSize <= UDPC_LSFULL_HEADER_SIZE)
-                        || (!pktSigned && sentIter->dataSize <= UDPC_NSFULL_HEADER_SIZE)) {
-                        UDPC_CHECK_LOG(this,
-                            UDPC_LoggingType::UDPC_VERBOSE,
-                            "Timed out packet has no payload (probably "
-                            "heartbeat packet), ignoring it");
-                        sentIter->flags |= 0x8;
+            // pkt not received yet, find it in sent to check if it timed out
+            for(auto sentIter = iter->second.sentPkts.rbegin();
+                    sentIter != iter->second.sentPkts.rend();
+                    ++sentIter) {
+                uint32_t sentID;
+                std::memcpy(&sentID, sentIter->data + 8, 4);
+                sentID = ntohl(sentID);
+                if(sentID == rseq) {
+                    if((sentIter->flags & 0x4) != 0
+                            || (sentIter->flags & 0x8) != 0) {
+                        // already resent or not rec-checked pkt
                         break;
                     }
+                    auto sentInfoIter = iter->second.sentInfoMap.find(sentID);
+                    assert(sentInfoIter != iter->second.sentInfoMap.end()
+                            && "Every entry in sentPkts must have a "
+                            "corresponding entry in sentInfoMap");
+                    auto duration = now - sentInfoIter->second->sentTime;
+                    if(duration > UDPC::PACKET_TIMEOUT_TIME) {
+                        bool pktSigned =
+                            sentIter->data[UDPC_MIN_HEADER_SIZE] == 1;
+                        if((pktSigned
+                                && sentIter->dataSize
+                                    <= UDPC_LSFULL_HEADER_SIZE
+                                ) ||
+                                    (!pktSigned
+                                    && sentIter->dataSize
+                                        <= UDPC_NSFULL_HEADER_SIZE)) {
+                            UDPC_CHECK_LOG(this,
+                                UDPC_LoggingType::UDPC_VERBOSE,
+                                "Timed out packet has no payload (probably "
+                                "heartbeat packet), ignoring it");
+                            sentIter->flags |= 0x8;
+                            break;
+                        }
 
-                    UDPC_PacketInfo resendingData = UDPC::get_empty_pinfo();
-                    if(pktSigned) {
-                        resendingData.dataSize = sentIter->dataSize - UDPC_LSFULL_HEADER_SIZE;
-                        resendingData.data = (char*)std::malloc(resendingData.dataSize);
-                        std::memcpy(resendingData.data,
-                            sentIter->data + UDPC_LSFULL_HEADER_SIZE,
-                            resendingData.dataSize);
-                    } else {
-                        resendingData.dataSize = sentIter->dataSize - UDPC_NSFULL_HEADER_SIZE;
-                        resendingData.data = (char*)std::malloc(resendingData.dataSize);
-                        std::memcpy(resendingData.data,
-                            sentIter->data + UDPC_NSFULL_HEADER_SIZE,
-                            resendingData.dataSize);
+                        UDPC_PacketInfo resendingData = UDPC::get_empty_pinfo();
+                        if(pktSigned) {
+                            resendingData.dataSize =
+                                sentIter->dataSize - UDPC_LSFULL_HEADER_SIZE;
+                            resendingData.data =
+                                (char*)std::malloc(resendingData.dataSize);
+                            std::memcpy(resendingData.data,
+                                sentIter->data + UDPC_LSFULL_HEADER_SIZE,
+                                resendingData.dataSize);
+                        } else {
+                            resendingData.dataSize =
+                                sentIter->dataSize - UDPC_NSFULL_HEADER_SIZE;
+                            resendingData.data =
+                                (char*)std::malloc(resendingData.dataSize);
+                            std::memcpy(resendingData.data,
+                                sentIter->data + UDPC_NSFULL_HEADER_SIZE,
+                                resendingData.dataSize);
+                        }
+                        resendingData.flags = 0;
+                        iter->second.priorityPkts.push_back(resendingData);
                     }
-                    resendingData.flags = 0;
-                    iter->second.priorityPkts.push_back(resendingData);
+                    break;
                 }
-                break;
             }
-        }
 
-        --rseq;
-    }
+            --rseq;
+        }
 
-    // calculate sequence and ack
-    bool isOutOfOrder = false;
-    uint32_t diff = 0;
-    if(seqID > iter->second.rseq) {
-        diff = seqID - iter->second.rseq;
-        if(diff <= 0x7FFFFFFF) {
-            // sequence is more recent
-            iter->second.rseq = seqID;
-            iter->second.ack = (iter->second.ack >> diff) | 0x80000000;
-        } else {
-            // sequence is older, recalc diff
-            diff = 0xFFFFFFFF - seqID + 1 + iter->second.rseq;
-            if((iter->second.ack & (0x80000000 >> (diff - 1))) != 0) {
-                // already received packet
-                UDPC_CHECK_LOG(this,
-                    UDPC_LoggingType::UDPC_VERBOSE,
-                    "Received packet is already marked as received, ignoring it");
-                return;
+        // calculate sequence and ack
+        bool isOutOfOrder = false;
+        uint32_t diff = 0;
+        if(seqID > iter->second.rseq) {
+            diff = seqID - iter->second.rseq;
+            if(diff <= 0x7FFFFFFF) {
+                // sequence is more recent
+                iter->second.rseq = seqID;
+                iter->second.ack = (iter->second.ack >> diff) | 0x80000000;
+            } else {
+                // sequence is older, recalc diff
+                diff = 0xFFFFFFFF - seqID + 1 + iter->second.rseq;
+                if((iter->second.ack & (0x80000000 >> (diff - 1))) != 0) {
+                    // already received packet
+                    UDPC_CHECK_LOG(this,
+                        UDPC_LoggingType::UDPC_VERBOSE,
+                        "Received packet is already marked as received, "
+                        "ignoring it");
+                    return;
+                }
+                iter->second.ack |= 0x80000000 >> (diff - 1);
+                isOutOfOrder = true;
             }
-            iter->second.ack |= 0x80000000 >> (diff - 1);
-            isOutOfOrder = true;
-        }
-    } else if(seqID < iter->second.rseq) {
-        diff = iter->second.rseq - seqID;
-        if(diff <= 0x7FFFFFFF) {
-            // sequence is older
-            if((iter->second.ack & (0x80000000 >> (diff - 1))) != 0) {
-                // already received packet
-                UDPC_CHECK_LOG(this,
-                    UDPC_LoggingType::UDPC_VERBOSE,
-                    "Received packet is already marked as received, ignoring it");
-                return;
+        } else if(seqID < iter->second.rseq) {
+            diff = iter->second.rseq - seqID;
+            if(diff <= 0x7FFFFFFF) {
+                // sequence is older
+                if((iter->second.ack & (0x80000000 >> (diff - 1))) != 0) {
+                    // already received packet
+                    UDPC_CHECK_LOG(this,
+                        UDPC_LoggingType::UDPC_VERBOSE,
+                        "Received packet is already marked as received, "
+                        "ignoring it");
+                    return;
+                }
+                iter->second.ack |= 0x80000000 >> (diff - 1);
+                isOutOfOrder = true;
+            } else {
+                // sequence is more recent, recalc diff
+                diff = 0xFFFFFFFF - iter->second.rseq + 1 + seqID;
+                iter->second.rseq = seqID;
+                iter->second.ack = (iter->second.ack >> diff) | 0x80000000;
             }
-            iter->second.ack |= 0x80000000 >> (diff - 1);
-            isOutOfOrder = true;
         } else {
-            // sequence is more recent, recalc diff
-            diff = 0xFFFFFFFF - iter->second.rseq + 1 + seqID;
-            iter->second.rseq = seqID;
-            iter->second.ack = (iter->second.ack >> diff) | 0x80000000;
+            // already received packet
+            UDPC_CHECK_LOG(this,
+                UDPC_LoggingType::UDPC_VERBOSE,
+                "Received packet is already marked as received, ignoring it");
+            return;
         }
-    } else {
-        // already received packet
-        UDPC_CHECK_LOG(this,
-            UDPC_LoggingType::UDPC_VERBOSE,
-            "Received packet is already marked as received, ignoring it");
-        return;
-    }
 
-    if(isOutOfOrder) {
-        UDPC_CHECK_LOG(this,
-            UDPC_LoggingType::UDPC_INFO,
-            "Received packet is out of order");
-    }
-
-    if(pktType == 0 && bytes > (int)UDPC_NSFULL_HEADER_SIZE) {
-        UDPC_PacketInfo recPktInfo = UDPC::get_empty_pinfo();
-        recPktInfo.dataSize = bytes - UDPC_NSFULL_HEADER_SIZE;
-        recPktInfo.data = (char*)std::malloc(recPktInfo.dataSize);
-        std::memcpy(recPktInfo.data,
-                    recvBuf + UDPC_NSFULL_HEADER_SIZE,
-                    recPktInfo.dataSize);
-        recPktInfo.flags =
-            (isConnect ? 0x1 : 0)
-            | (isPing ? 0x2 : 0)
-            | (isNotRecChecked ? 0x4 : 0)
-            | (isResending ? 0x8 : 0);
-        recPktInfo.sender.addr = receivedData.sin6_addr;
-        recPktInfo.receiver.addr = in6addr_loopback;
-        recPktInfo.sender.port = ntohs(receivedData.sin6_port);
-        recPktInfo.receiver.port = ntohs(socketInfo.sin6_port);
-        recPktInfo.rtt = durationToMS(iter->second.rtt);
-        recPktInfo.id = seqID;
-
-        std::lock_guard<std::mutex> receivedPktsLock(receivedPktsMutex);
-        receivedPkts.push_back(recPktInfo);
-    } else if(pktType == 1 && bytes > (int)UDPC_LSFULL_HEADER_SIZE) {
-        UDPC_PacketInfo recPktInfo = UDPC::get_empty_pinfo();
-        recPktInfo.dataSize = bytes - UDPC_LSFULL_HEADER_SIZE;
-        recPktInfo.data = (char*)std::malloc(recPktInfo.dataSize);
-        std::memcpy(recPktInfo.data,
-                    recvBuf + UDPC_LSFULL_HEADER_SIZE,
-                    recPktInfo.dataSize);
-        recPktInfo.flags =
-            (isConnect ? 0x1 : 0)
-            | (isPing ? 0x2 : 0)
-            | (isNotRecChecked ? 0x4 : 0)
-            | (isResending ? 0x8 : 0);
-        recPktInfo.sender.addr = receivedData.sin6_addr;
-        recPktInfo.receiver.addr = in6addr_loopback;
-        recPktInfo.sender.port = ntohs(receivedData.sin6_port);
-        recPktInfo.receiver.port = ntohs(socketInfo.sin6_port);
-        recPktInfo.rtt = durationToMS(iter->second.rtt);
-        recPktInfo.id = seqID;
-
-        std::lock_guard<std::mutex> receivedPktsLock(receivedPktsMutex);
-        receivedPkts.push_back(recPktInfo);
-    } else {
-        UDPC_CHECK_LOG(this,
-            UDPC_LoggingType::UDPC_VERBOSE,
-            "Received packet has no payload (probably heartbeat packet)");
-    }
+        if(isOutOfOrder) {
+            UDPC_CHECK_LOG(this,
+                UDPC_LoggingType::UDPC_INFO,
+                "Received packet is out of order");
+        }
+
+        if(pktType == 0 && bytes > (int)UDPC_NSFULL_HEADER_SIZE) {
+            UDPC_PacketInfo recPktInfo = UDPC::get_empty_pinfo();
+            recPktInfo.dataSize = bytes - UDPC_NSFULL_HEADER_SIZE;
+            recPktInfo.data = (char*)std::malloc(recPktInfo.dataSize);
+            std::memcpy(recPktInfo.data,
+                        recvBuf + UDPC_NSFULL_HEADER_SIZE,
+                        recPktInfo.dataSize);
+            recPktInfo.flags =
+                (isConnect ? 0x1 : 0)
+                | (isPing ? 0x2 : 0)
+                | (isNotRecChecked ? 0x4 : 0)
+                | (isResending ? 0x8 : 0);
+            recPktInfo.sender.addr = receivedData.sin6_addr;
+            recPktInfo.receiver.addr = in6addr_loopback;
+            recPktInfo.sender.port = ntohs(receivedData.sin6_port);
+            recPktInfo.receiver.port = ntohs(socketInfo.sin6_port);
+            recPktInfo.rtt = durationToMS(iter->second.rtt);
+            recPktInfo.id = seqID;
+
+            std::lock_guard<std::mutex> receivedPktsLock(receivedPktsMutex);
+            receivedPkts.push_back(recPktInfo);
+        } else if(pktType == 1 && bytes > (int)UDPC_LSFULL_HEADER_SIZE) {
+            UDPC_PacketInfo recPktInfo = UDPC::get_empty_pinfo();
+            recPktInfo.dataSize = bytes - UDPC_LSFULL_HEADER_SIZE;
+            recPktInfo.data = (char*)std::malloc(recPktInfo.dataSize);
+            std::memcpy(recPktInfo.data,
+                        recvBuf + UDPC_LSFULL_HEADER_SIZE,
+                        recPktInfo.dataSize);
+            recPktInfo.flags =
+                (isConnect ? 0x1 : 0)
+                | (isPing ? 0x2 : 0)
+                | (isNotRecChecked ? 0x4 : 0)
+                | (isResending ? 0x8 : 0);
+            recPktInfo.sender.addr = receivedData.sin6_addr;
+            recPktInfo.receiver.addr = in6addr_loopback;
+            recPktInfo.sender.port = ntohs(receivedData.sin6_port);
+            recPktInfo.receiver.port = ntohs(socketInfo.sin6_port);
+            recPktInfo.rtt = durationToMS(iter->second.rtt);
+            recPktInfo.id = seqID;
+
+            std::lock_guard<std::mutex> receivedPktsLock(receivedPktsMutex);
+            receivedPkts.push_back(recPktInfo);
+        } else {
+            UDPC_CHECK_LOG(this,
+                UDPC_LoggingType::UDPC_VERBOSE,
+                "Received packet has no payload (probably heartbeat packet)");
+        }
+    } while (true);
 }
 
 UDPC::Context *UDPC::verifyContext(UDPC_HContext ctx) {