Browse Source

cumulative ACK bitfields

pull/1601/head
orignal 4 years ago
parent
commit
fc2dc9a019
  1. 31
      libi2pd/SSUData.cpp
  2. 6
      libi2pd/SSUData.h

31
libi2pd/SSUData.cpp

@ -185,6 +185,11 @@ namespace transport
std::unique_ptr<IncompleteMessage>(new IncompleteMessage (msg)))).first; std::unique_ptr<IncompleteMessage>(new IncompleteMessage (msg)))).first;
} }
std::unique_ptr<IncompleteMessage>& incompleteMessage = it->second; std::unique_ptr<IncompleteMessage>& 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 // handle current fragment
if (fragmentNum == incompleteMessage->nextFragmentNum) if (fragmentNum == incompleteMessage->nextFragmentNum)
@ -266,7 +271,7 @@ namespace transport
} }
} }
else else
SendFragmentAck (msgID, fragmentNum); SendFragmentAck (msgID, incompleteMessage->receivedFragmentsBits);
buf += fragmentSize; buf += fragmentSize;
} }
} }
@ -394,13 +399,9 @@ namespace transport
m_Session.Send (buf, 48); 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) if (!bits) return;
{
LogPrint (eLogWarning, "SSU: Fragment number ", fragmentNum, " exceeds 64");
return;
}
uint8_t buf[64 + 18] = {0}; uint8_t buf[64 + 18] = {0};
uint8_t * payload = buf + sizeof (SSUHeader); uint8_t * payload = buf + sizeof (SSUHeader);
*payload = DATA_FLAG_ACK_BITFIELDS_INCLUDED; // flag *payload = DATA_FLAG_ACK_BITFIELDS_INCLUDED; // flag
@ -410,14 +411,16 @@ namespace transport
// one ack // one ack
*(uint32_t *)(payload) = htobe32 (msgID); // msgID *(uint32_t *)(payload) = htobe32 (msgID); // msgID
payload += 4; payload += 4;
div_t d = div (fragmentNum, 7); size_t len = 0;
memset (payload, 0x80, d.quot); // 0x80 means non-last while (bits)
payload += d.quot; {
*payload = 0x01 << d.rem; // set corresponding bit *payload = (bits & 0x7F); // next 7 bits
payload++; bits >>= 7;
if (bits) *payload &= 0x80; // 0x80 means non-last
payload++; len++;
}
*payload = 0; // number of fragments *payload = 0; // number of fragments
len = (len <= 4) ? 48 : 64; // 48 = 37 + 7 + 4
size_t len = d.quot < 4 ? 48 : 64; // 48 = 37 + 7 + 4 (3+1)
// encrypt message with session key // encrypt message with session key
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, len); m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, len);
m_Session.Send (buf, len); m_Session.Send (buf, len);

6
libi2pd/SSUData.h

@ -75,9 +75,11 @@ namespace transport
std::shared_ptr<I2NPMessage> msg; std::shared_ptr<I2NPMessage> msg;
int nextFragmentNum; int nextFragmentNum;
uint32_t lastFragmentInsertTime; // in seconds uint32_t lastFragmentInsertTime; // in seconds
uint64_t receivedFragmentsBits;
std::set<std::unique_ptr<Fragment>, FragmentCmp> savedFragments; std::set<std::unique_ptr<Fragment>, FragmentCmp> savedFragments;
IncompleteMessage (std::shared_ptr<I2NPMessage> m): msg (m), nextFragmentNum (0), lastFragmentInsertTime (0) {}; IncompleteMessage (std::shared_ptr<I2NPMessage> m): msg (m), nextFragmentNum (0),
lastFragmentInsertTime (0), receivedFragmentsBits (0) {};
void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize); void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize);
}; };
@ -109,7 +111,7 @@ namespace transport
private: private:
void SendMsgAck (uint32_t msgID); 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 ProcessAcks (uint8_t *& buf, uint8_t flag);
void ProcessFragments (uint8_t * buf); void ProcessFragments (uint8_t * buf);
void ProcessSentMessageAck (uint32_t msgID); void ProcessSentMessageAck (uint32_t msgID);

Loading…
Cancel
Save