mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-09 15:50:26 +03:00
send fragmented messages
This commit is contained in:
parent
51cbffd097
commit
678a1ae0fb
@ -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)
|
||||
{
|
||||
|
@ -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:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user