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