Browse Source

random size of fragments

pull/1786/head
orignal 2 years ago
parent
commit
46a549c875
  1. 49
      libi2pd/SSU2Session.cpp
  2. 4
      libi2pd/SSU2Session.h

49
libi2pd/SSU2Session.cpp

@ -265,6 +265,7 @@ namespace transport
auto nextResend = i2p::util::GetSecondsSinceEpoch () + SSU2_RESEND_INTERVAL; auto nextResend = i2p::util::GetSecondsSinceEpoch () + SSU2_RESEND_INTERVAL;
auto packet = std::make_shared<SentPacket>(); auto packet = std::make_shared<SentPacket>();
size_t ackBlockSize = CreateAckBlock (packet->payload, m_MaxPayloadSize); size_t ackBlockSize = CreateAckBlock (packet->payload, m_MaxPayloadSize);
bool ackBlockSent = false;
packet->payloadSize += ackBlockSize; packet->payloadSize += ackBlockSize;
while (!m_SendQueue.empty () && m_SentPackets.size () <= m_WindowSize) while (!m_SendQueue.empty () && m_SentPackets.size () <= m_WindowSize)
{ {
@ -273,7 +274,8 @@ namespace transport
if (len > m_MaxPayloadSize) // message too long if (len > m_MaxPayloadSize) // message too long
{ {
m_SendQueue.pop_front (); m_SendQueue.pop_front ();
SendFragmentedMessage (msg); if (SendFragmentedMessage (msg))
ackBlockSent = true;
} }
else if (packet->payloadSize + len <= m_MaxPayloadSize) else if (packet->payloadSize + len <= m_MaxPayloadSize)
{ {
@ -289,6 +291,7 @@ namespace transport
// complete current packet // complete current packet
if (packet->payloadSize > ackBlockSize) // more than just ack block if (packet->payloadSize > ackBlockSize) // more than just ack block
{ {
ackBlockSent = true;
// try to add padding // try to add padding
if (packet->payloadSize + 16 < m_MaxPayloadSize) if (packet->payloadSize + 16 < m_MaxPayloadSize)
packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize);
@ -299,6 +302,7 @@ namespace transport
if (len + 8 < m_MaxPayloadSize) if (len + 8 < m_MaxPayloadSize)
{ {
// keep Ack block and drop some ranges // keep Ack block and drop some ranges
ackBlockSent = true;
packet->payloadSize = m_MaxPayloadSize - len; packet->payloadSize = m_MaxPayloadSize - len;
if (packet->payloadSize & 0x01) packet->payloadSize--; // make it even if (packet->payloadSize & 0x01) packet->payloadSize--; // make it even
htobe16buf (packet->payload + 1, packet->payloadSize - 3); // new block size htobe16buf (packet->payload + 1, packet->payloadSize - 3); // new block size
@ -316,43 +320,66 @@ namespace transport
packet = newPacket; // just ack block packet = newPacket; // just ack block
} }
}; };
if (packet->payloadSize) if (packet->payloadSize > ackBlockSize)
{ {
ackBlockSent = true;
if (packet->payloadSize + 16 < m_MaxPayloadSize) if (packet->payloadSize + 16 < m_MaxPayloadSize)
packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize);
uint32_t packetNum = SendData (packet->payload, packet->payloadSize); uint32_t packetNum = SendData (packet->payload, packet->payloadSize);
packet->nextResendTime = nextResend; packet->nextResendTime = nextResend;
m_SentPackets.emplace (packetNum, packet); m_SentPackets.emplace (packetNum, packet);
} }
return true; return ackBlockSent;
} }
return false; return false;
} }
void SSU2Session::SendFragmentedMessage (std::shared_ptr<I2NPMessage> msg) bool SSU2Session::SendFragmentedMessage (std::shared_ptr<I2NPMessage> msg)
{ {
size_t lastFragmentSize = (msg->GetNTCP2Length () + 3 - m_MaxPayloadSize) % (m_MaxPayloadSize - 8);
size_t extraSize = m_MaxPayloadSize - lastFragmentSize;
bool ackBlockSent = false;
uint32_t msgID; uint32_t msgID;
memcpy (&msgID, msg->GetHeader () + I2NP_HEADER_MSGID_OFFSET, 4); memcpy (&msgID, msg->GetHeader () + I2NP_HEADER_MSGID_OFFSET, 4);
auto nextResend = i2p::util::GetSecondsSinceEpoch () + SSU2_RESEND_INTERVAL; auto nextResend = i2p::util::GetSecondsSinceEpoch () + SSU2_RESEND_INTERVAL;
auto packet = std::make_shared<SentPacket>(); auto packet = std::make_shared<SentPacket>();
packet->payloadSize = CreateAckBlock (packet->payload, m_MaxPayloadSize); if (extraSize >= 8)
auto size = CreateFirstFragmentBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - 16 - packet->payloadSize, msg); {
if (!size) return; packet->payloadSize = CreateAckBlock (packet->payload, extraSize);
ackBlockSent = true;
if (packet->payloadSize + 12 < m_MaxPayloadSize)
{
uint32_t packetNum = SendData (packet->payload, packet->payloadSize);
packet->nextResendTime = nextResend;
m_SentPackets.emplace (packetNum, packet);
packet = std::make_shared<SentPacket>();
}
else
extraSize -= packet->payloadSize;
}
size_t offset = extraSize > 0 ? (rand () % extraSize) : 0;
if (offset + packet->payloadSize >= m_MaxPayloadSize) offset = 0;
auto size = CreateFirstFragmentBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - offset - packet->payloadSize, msg);
if (!size) return false;
extraSize -= offset;
packet->payloadSize += size; packet->payloadSize += size;
packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - 16 - packet->payloadSize);
uint32_t firstPacketNum = SendData (packet->payload, packet->payloadSize); uint32_t firstPacketNum = SendData (packet->payload, packet->payloadSize);
packet->nextResendTime = nextResend; packet->nextResendTime = nextResend;
m_SentPackets.emplace (firstPacketNum, packet); m_SentPackets.emplace (firstPacketNum, packet);
uint8_t fragmentNum = 0; uint8_t fragmentNum = 0;
while (msg->offset < msg->len) while (msg->offset < msg->len)
{ {
offset = extraSize > 0 ? (rand () % extraSize) : 0;
packet = std::make_shared<SentPacket>(); packet = std::make_shared<SentPacket>();
packet->payloadSize = CreateFollowOnFragmentBlock (packet->payload, m_MaxPayloadSize - 16, msg, fragmentNum, msgID); packet->payloadSize = CreateFollowOnFragmentBlock (packet->payload, m_MaxPayloadSize - offset, msg, fragmentNum, msgID);
packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - 16 - packet->payloadSize); extraSize -= offset;
if (msg->offset >= msg->len && packet->payloadSize + 16 < m_MaxPayloadSize) // last fragment
packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize);
uint32_t followonPacketNum = SendData (packet->payload, packet->payloadSize); uint32_t followonPacketNum = SendData (packet->payload, packet->payloadSize);
packet->nextResendTime = nextResend; packet->nextResendTime = nextResend;
m_SentPackets.emplace (followonPacketNum, packet); m_SentPackets.emplace (followonPacketNum, packet);
} }
return ackBlockSent;
} }
void SSU2Session::Resend (uint64_t ts) void SSU2Session::Resend (uint64_t ts)
@ -863,7 +890,7 @@ namespace transport
m_Address = ri->GetSSU2AddressWithStaticKey (S, m_RemoteEndpoint.address ().is_v6 ()); m_Address = ri->GetSSU2AddressWithStaticKey (S, m_RemoteEndpoint.address ().is_v6 ());
if (!m_Address) if (!m_Address)
{ {
LogPrint (eLogError, "SSU2: No SSU2 address with static key found in SessionConfirmed"); LogPrint (eLogError, "SSU2: No SSU2 address with static key found in SessionConfirmed from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ()));
return false; return false;
} }
// update RouterInfo in netdb // update RouterInfo in netdb

4
libi2pd/SSU2Session.h

@ -250,8 +250,8 @@ namespace transport
void ScheduleConnectTimer (); void ScheduleConnectTimer ();
void HandleConnectTimer (const boost::system::error_code& ecode); void HandleConnectTimer (const boost::system::error_code& ecode);
void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs); void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
bool SendQueue (); bool SendQueue (); // returns true if ack block was sent
void SendFragmentedMessage (std::shared_ptr<I2NPMessage> msg); bool SendFragmentedMessage (std::shared_ptr<I2NPMessage> msg);
void ResendHandshakePacket (); void ResendHandshakePacket ();
void ProcessSessionRequest (Header& header, uint8_t * buf, size_t len); void ProcessSessionRequest (Header& header, uint8_t * buf, size_t len);

Loading…
Cancel
Save