|
|
|
@ -123,7 +123,10 @@ namespace transport
@@ -123,7 +123,10 @@ namespace transport
|
|
|
|
|
payloadSize += CreateI2NPBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize, std::move (msg)); |
|
|
|
|
} |
|
|
|
|
else if (len > SSU2_MAX_PAYLOAD_SIZE - 32) // message too long
|
|
|
|
|
m_SendQueue.pop_front (); // drop it. TODO: fragmentation
|
|
|
|
|
{ |
|
|
|
|
m_SendQueue.pop_front (); |
|
|
|
|
SendFragmentedMessage (msg); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
// send right a way
|
|
|
|
@ -147,6 +150,31 @@ namespace transport
@@ -147,6 +150,31 @@ namespace transport
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SSU2Session::SendFragmentedMessage (std::shared_ptr<I2NPMessage> msg) |
|
|
|
|
{ |
|
|
|
|
uint32_t msgID; |
|
|
|
|
memcpy (&msgID, msg->GetHeader () + I2NP_HEADER_MSGID_OFFSET, 4); |
|
|
|
|
uint8_t payload[SSU2_MAX_PAYLOAD_SIZE]; |
|
|
|
|
size_t payloadSize = 0; |
|
|
|
|
payloadSize += CreateAckBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize); |
|
|
|
|
auto size = CreateFirstFragmentBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - 32 - payloadSize, msg); |
|
|
|
|
if (!size) return; |
|
|
|
|
payloadSize += size; |
|
|
|
|
payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize); |
|
|
|
|
auto firstPacket = SendData (payload, payloadSize); |
|
|
|
|
if (firstPacket) |
|
|
|
|
m_SentPackets.emplace (firstPacket->packetNum, firstPacket); |
|
|
|
|
uint8_t fragmentNum = 0; |
|
|
|
|
while (msg->offset < msg->len) |
|
|
|
|
{ |
|
|
|
|
payloadSize += CreateFollowOnFragmentBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize - 16, msg, fragmentNum, msgID); |
|
|
|
|
payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize); |
|
|
|
|
auto followonPacket = SendData (payload, payloadSize); |
|
|
|
|
if (followonPacket) |
|
|
|
|
m_SentPackets.emplace (followonPacket->packetNum, followonPacket); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SSU2Session::Resend (uint64_t ts) |
|
|
|
|
{ |
|
|
|
|
if (m_SendQueue.empty ()) return; |
|
|
|
@ -1038,6 +1066,42 @@ namespace transport
@@ -1038,6 +1066,42 @@ namespace transport
|
|
|
|
|
memcpy (buf + 3, msgBuf, msgLen); |
|
|
|
|
return msgLen + 3; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size_t SSU2Session::CreateFirstFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg) |
|
|
|
|
{ |
|
|
|
|
if (len < 12) return 0; |
|
|
|
|
msg->ToNTCP2 (); |
|
|
|
|
auto msgBuf = msg->GetNTCP2Header (); |
|
|
|
|
auto msgLen = msg->GetNTCP2Length (); |
|
|
|
|
if (msgLen + 3 <= len) return 0; |
|
|
|
|
msgLen = len - 3; |
|
|
|
|
buf[0] = eSSU2BlkFirstFragment; |
|
|
|
|
htobe16buf (buf + 1, msgLen); // size
|
|
|
|
|
memcpy (buf + 3, msgBuf, msgLen); |
|
|
|
|
msg->offset = (msgBuf - buf) + msgLen; |
|
|
|
|
return msgLen + 3; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size_t SSU2Session::CreateFollowOnFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg, uint8_t& fragmentNum, uint32_t msgID) |
|
|
|
|
{ |
|
|
|
|
if (len < 8) return 0; |
|
|
|
|
bool isLast = true; |
|
|
|
|
auto msgLen = msg->len - msg->offset; |
|
|
|
|
if (msgLen + 8 > len) |
|
|
|
|
{ |
|
|
|
|
msgLen = len - 8; |
|
|
|
|
isLast = false; |
|
|
|
|
} |
|
|
|
|
buf[0] = eSSU2BlkFollowOnFragment; |
|
|
|
|
htobe16buf (buf + 1, msgLen); // size
|
|
|
|
|
fragmentNum++; |
|
|
|
|
buf[3] = fragmentNum << 1; |
|
|
|
|
if (isLast) buf[3] |= 0x01; |
|
|
|
|
memcpy (buf + 4, &msgID, 4); |
|
|
|
|
memcpy (buf + 8, msg->buf + msg->offset, msgLen); |
|
|
|
|
msg->offset += msgLen; |
|
|
|
|
return msgLen + 8; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::shared_ptr<const i2p::data::RouterInfo> SSU2Session::ExtractRouterInfo (const uint8_t * buf, size_t size) |
|
|
|
|
{ |
|
|
|
|