|
|
@ -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); |
|
|
|