send fragmented messages

This commit is contained in:
orignal 2022-04-09 11:42:34 -04:00
parent 51cbffd097
commit 678a1ae0fb
2 changed files with 68 additions and 1 deletions

View File

@ -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
}
}
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
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)
{

View File

@ -153,6 +153,7 @@ namespace transport
void Established ();
void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
void SendQueue ();
void SendFragmentedMessage (std::shared_ptr<I2NPMessage> msg);
void ProcessSessionRequest (Header& header, uint8_t * buf, size_t len);
void ProcessTokenRequest (Header& header, uint8_t * buf, size_t len);
@ -182,6 +183,8 @@ namespace transport
size_t CreateAckBlock (uint8_t * buf, size_t len);
size_t CreatePaddingBlock (uint8_t * buf, size_t len, size_t minSize = 0);
size_t CreateI2NPBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage>&& msg);
size_t CreateFirstFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg);
size_t CreateFollowOnFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg, uint8_t& fragmentNum, uint32_t msgID);
private: