diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index d2cb1a26..5bb27a40 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -851,6 +851,7 @@ namespace transport m_PacketsPool.CleanUpMt (); m_SentPacketsPool.CleanUp (); + m_IncompleteMessagesPool.CleanUp (); m_FragmentsPool.CleanUp (); ScheduleCleanup (); } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 68d507ca..8b755f60 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -98,8 +98,9 @@ namespace transport void RescheduleIntroducersUpdateTimerV6 (); i2p::util::MemoryPool& GetSentPacketsPool () { return m_SentPacketsPool; }; + i2p::util::MemoryPool& GetIncompleteMessagesPool () { return m_IncompleteMessagesPool; }; i2p::util::MemoryPool& GetFragmentsPool () { return m_FragmentsPool; }; - + private: boost::asio::ip::udp::socket& OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint); @@ -152,6 +153,7 @@ namespace transport std::list m_Introducers, m_IntroducersV6; // introducers we are connected to i2p::util::MemoryPoolMt m_PacketsPool; i2p::util::MemoryPool m_SentPacketsPool; + i2p::util::MemoryPool m_IncompleteMessagesPool; i2p::util::MemoryPool m_FragmentsPool; boost::asio::deadline_timer m_TerminationTimer, m_CleanupTimer, m_ResendTimer, m_IntroducersUpdateTimer, m_IntroducersUpdateTimerV6; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 0f53bf7b..5e97b461 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1772,7 +1772,7 @@ namespace transport } else { - m = std::make_shared(); + m = m_Server.GetIncompleteMessagesPool ().AcquireShared (); m_IncompleteMessages.emplace (msgID, m); } m->msg = msg; @@ -1791,11 +1791,17 @@ namespace transport { if (len < 5) return; uint8_t fragmentNum = buf[0] >> 1; + if (!fragmentNum || fragmentNum >= SSU2_MAX_NUM_FRAGMENTS) + { + LogPrint (eLogWarning, "SSU2: Invalid follow-on fragment num ", fragmentNum); + return; + } bool isLast = buf[0] & 0x01; uint32_t msgID; memcpy (&msgID, buf + 1, 4); auto it = m_IncompleteMessages.find (msgID); if (it != m_IncompleteMessages.end ()) { + if (fragmentNum < it->second->nextFragmentNum) return; // duplicate if (it->second->nextFragmentNum == fragmentNum && fragmentNum < SSU2_MAX_NUM_FRAGMENTS && it->second->msg) { @@ -1823,16 +1829,11 @@ namespace transport else { // follow-on fragment before first fragment - auto msg = std::make_shared (); + auto msg = m_Server.GetIncompleteMessagesPool ().AcquireShared (); msg->nextFragmentNum = 0; it = m_IncompleteMessages.emplace (msgID, msg).first; } // insert out of sequence fragment - if (fragmentNum >= SSU2_MAX_NUM_FRAGMENTS) - { - LogPrint (eLogWarning, "SSU2: Fragment number ", fragmentNum, " exceeds ", SSU2_MAX_NUM_FRAGMENTS); - return; - } auto fragment = m_Server.GetFragmentsPool ().AcquireShared (); memcpy (fragment->buf, buf + 5, len -5); fragment->len = len - 5; diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 08a4b7cf..ef9ab573 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -345,7 +345,7 @@ namespace transport uint32_t m_SendPacketNum, m_ReceivePacketNum; std::set m_OutOfSequencePackets; // packet nums > receive packet num std::map > m_SentPackets; // packetNum -> packet - std::map > m_IncompleteMessages; // I2NP + std::unordered_map > m_IncompleteMessages; // msgID -> I2NP std::map, uint64_t > > m_RelaySessions; // nonce->(Alice, timestamp) for Bob or nonce->(Charlie, timestamp) for Alice std::map, uint64_t > > m_PeerTests; // same as for relay sessions std::list > m_SendQueue;