From fc2dc9a0199bf1983673ead4adde19b6ec1c9dec Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 12 Dec 2020 21:40:07 -0500 Subject: [PATCH] cumulative ACK bitfields --- libi2pd/SSUData.cpp | 35 +++++++++++++++++++---------------- libi2pd/SSUData.h | 6 ++++-- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/libi2pd/SSUData.cpp b/libi2pd/SSUData.cpp index 4e0e712f..5458cc97 100644 --- a/libi2pd/SSUData.cpp +++ b/libi2pd/SSUData.cpp @@ -185,7 +185,12 @@ namespace transport std::unique_ptr(new IncompleteMessage (msg)))).first; } std::unique_ptr& incompleteMessage = it->second; - + // mark fragment as received + if (fragmentNum < 64) + incompleteMessage->receivedFragmentsBits |= (0x01 << fragmentNum); + else + LogPrint (eLogWarning, "SSU: Fragment number ", fragmentNum, " exceeds 64"); + // handle current fragment if (fragmentNum == incompleteMessage->nextFragmentNum) { @@ -220,7 +225,7 @@ namespace transport // missing fragment LogPrint (eLogWarning, "SSU: Missing fragments from ", (int)incompleteMessage->nextFragmentNum, " to ", fragmentNum - 1, " of message ", msgID); auto savedFragment = new Fragment (fragmentNum, buf, fragmentSize, isLast); - if (incompleteMessage->savedFragments.insert (std::unique_ptr(savedFragment)).second) + if (incompleteMessage->savedFragments.insert (std::unique_ptr(savedFragment)).second) incompleteMessage->lastFragmentInsertTime = i2p::util::GetSecondsSinceEpoch (); else LogPrint (eLogWarning, "SSU: Fragment ", (int)fragmentNum, " of message ", msgID, " already saved"); @@ -266,7 +271,7 @@ namespace transport } } else - SendFragmentAck (msgID, fragmentNum); + SendFragmentAck (msgID, incompleteMessage->receivedFragmentsBits); buf += fragmentSize; } } @@ -394,13 +399,9 @@ namespace transport m_Session.Send (buf, 48); } - void SSUData::SendFragmentAck (uint32_t msgID, int fragmentNum) + void SSUData::SendFragmentAck (uint32_t msgID, uint64_t bits) { - if (fragmentNum > 64) - { - LogPrint (eLogWarning, "SSU: Fragment number ", fragmentNum, " exceeds 64"); - return; - } + if (!bits) return; uint8_t buf[64 + 18] = {0}; uint8_t * payload = buf + sizeof (SSUHeader); *payload = DATA_FLAG_ACK_BITFIELDS_INCLUDED; // flag @@ -410,14 +411,16 @@ namespace transport // one ack *(uint32_t *)(payload) = htobe32 (msgID); // msgID payload += 4; - div_t d = div (fragmentNum, 7); - memset (payload, 0x80, d.quot); // 0x80 means non-last - payload += d.quot; - *payload = 0x01 << d.rem; // set corresponding bit - payload++; + size_t len = 0; + while (bits) + { + *payload = (bits & 0x7F); // next 7 bits + bits >>= 7; + if (bits) *payload &= 0x80; // 0x80 means non-last + payload++; len++; + } *payload = 0; // number of fragments - - size_t len = d.quot < 4 ? 48 : 64; // 48 = 37 + 7 + 4 (3+1) + len = (len <= 4) ? 48 : 64; // 48 = 37 + 7 + 4 // encrypt message with session key m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, len); m_Session.Send (buf, len); diff --git a/libi2pd/SSUData.h b/libi2pd/SSUData.h index 2e606053..902c009a 100644 --- a/libi2pd/SSUData.h +++ b/libi2pd/SSUData.h @@ -75,9 +75,11 @@ namespace transport std::shared_ptr msg; int nextFragmentNum; uint32_t lastFragmentInsertTime; // in seconds + uint64_t receivedFragmentsBits; std::set, FragmentCmp> savedFragments; - IncompleteMessage (std::shared_ptr m): msg (m), nextFragmentNum (0), lastFragmentInsertTime (0) {}; + IncompleteMessage (std::shared_ptr m): msg (m), nextFragmentNum (0), + lastFragmentInsertTime (0), receivedFragmentsBits (0) {}; void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize); }; @@ -109,7 +111,7 @@ namespace transport private: void SendMsgAck (uint32_t msgID); - void SendFragmentAck (uint32_t msgID, int fragmentNum); + void SendFragmentAck (uint32_t msgID, uint64_t bits); void ProcessAcks (uint8_t *& buf, uint8_t flag); void ProcessFragments (uint8_t * buf); void ProcessSentMessageAck (uint32_t msgID);