mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-02-02 11:04:00 +01:00
memory pool for SSU messages and fragments
This commit is contained in:
parent
5e2e1a1e3d
commit
e054c6e82c
|
@ -919,6 +919,11 @@ namespace transport
|
||||||
}
|
}
|
||||||
if (numDeleted > 0)
|
if (numDeleted > 0)
|
||||||
LogPrint (eLogDebug, "SSU: ", numDeleted, " peer tests have been expired");
|
LogPrint (eLogDebug, "SSU: ", numDeleted, " peer tests have been expired");
|
||||||
|
// some cleaups. TODO: use separate timer
|
||||||
|
m_FragmentsPool.CleanUp ();
|
||||||
|
m_IncompleteMessagesPool.CleanUp ();
|
||||||
|
m_SentMessagesPool.CleanUp ();
|
||||||
|
|
||||||
SchedulePeerTestsCleanupTimer ();
|
SchedulePeerTestsCleanupTimer ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -18,6 +18,7 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
|
#include "util.h"
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
|
@ -63,6 +64,10 @@ namespace transport
|
||||||
void DeleteAllSessions ();
|
void DeleteAllSessions ();
|
||||||
|
|
||||||
boost::asio::io_service& GetService () { return m_Service; };
|
boost::asio::io_service& GetService () { return m_Service; };
|
||||||
|
i2p::util::MemoryPool<Fragment>& GetFragmentsPool () { return m_FragmentsPool; };
|
||||||
|
i2p::util::MemoryPool<IncompleteMessage>& GetIncompleteMessagesPool () { return m_IncompleteMessagesPool; };
|
||||||
|
i2p::util::MemoryPool<SentMessage>& GetSentMessagesPool () { return m_SentMessagesPool; };
|
||||||
|
|
||||||
uint16_t GetPort () const { return m_Endpoint.port (); };
|
uint16_t GetPort () const { return m_Endpoint.port (); };
|
||||||
void SetLocalAddress (const boost::asio::ip::address& localAddress);
|
void SetLocalAddress (const boost::asio::ip::address& localAddress);
|
||||||
|
|
||||||
|
@ -136,6 +141,10 @@ namespace transport
|
||||||
std::map<uint32_t, std::shared_ptr<SSUSession> > m_Relays; // we are introducer
|
std::map<uint32_t, std::shared_ptr<SSUSession> > m_Relays; // we are introducer
|
||||||
std::map<uint32_t, PeerTest> m_PeerTests; // nonce -> creation time in milliseconds
|
std::map<uint32_t, PeerTest> m_PeerTests; // nonce -> creation time in milliseconds
|
||||||
|
|
||||||
|
i2p::util::MemoryPool<Fragment> m_FragmentsPool;
|
||||||
|
i2p::util::MemoryPool<IncompleteMessage> m_IncompleteMessagesPool;
|
||||||
|
i2p::util::MemoryPool<SentMessage> m_SentMessagesPool;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// for HTTP only
|
// for HTTP only
|
||||||
const decltype(m_Sessions)& GetSessions () const { return m_Sessions; };
|
const decltype(m_Sessions)& GetSessions () const { return m_Sessions; };
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -140,7 +140,7 @@ namespace transport
|
||||||
if (bitfield & mask)
|
if (bitfield & mask)
|
||||||
{
|
{
|
||||||
if (fragment < numSentFragments)
|
if (fragment < numSentFragments)
|
||||||
it->second->fragments[fragment].reset (nullptr);
|
it->second->fragments[fragment] = nullptr;
|
||||||
}
|
}
|
||||||
fragment++;
|
fragment++;
|
||||||
mask <<= 1;
|
mask <<= 1;
|
||||||
|
@ -182,9 +182,9 @@ namespace transport
|
||||||
auto msg = NewI2NPShortMessage ();
|
auto msg = NewI2NPShortMessage ();
|
||||||
msg->len -= I2NP_SHORT_HEADER_SIZE;
|
msg->len -= I2NP_SHORT_HEADER_SIZE;
|
||||||
it = m_IncompleteMessages.insert (std::make_pair (msgID,
|
it = m_IncompleteMessages.insert (std::make_pair (msgID,
|
||||||
std::unique_ptr<IncompleteMessage>(new IncompleteMessage (msg)))).first;
|
m_Session.GetServer ().GetIncompleteMessagesPool ().AcquireShared (msg))).first;
|
||||||
}
|
}
|
||||||
std::unique_ptr<IncompleteMessage>& incompleteMessage = it->second;
|
auto& incompleteMessage = it->second;
|
||||||
// mark fragment as received
|
// mark fragment as received
|
||||||
if (fragmentNum < 64)
|
if (fragmentNum < 64)
|
||||||
incompleteMessage->receivedFragmentsBits |= (0x01 << fragmentNum);
|
incompleteMessage->receivedFragmentsBits |= (0x01 << fragmentNum);
|
||||||
|
@ -224,8 +224,8 @@ namespace transport
|
||||||
{
|
{
|
||||||
// missing fragment
|
// missing fragment
|
||||||
LogPrint (eLogWarning, "SSU: Missing fragments from ", (int)incompleteMessage->nextFragmentNum, " to ", fragmentNum - 1, " of message ", msgID);
|
LogPrint (eLogWarning, "SSU: Missing fragments from ", (int)incompleteMessage->nextFragmentNum, " to ", fragmentNum - 1, " of message ", msgID);
|
||||||
auto savedFragment = new Fragment (fragmentNum, buf, fragmentSize, isLast);
|
auto savedFragment = m_Session.GetServer ().GetFragmentsPool ().AcquireShared (fragmentNum, buf, fragmentSize, isLast);
|
||||||
if (incompleteMessage->savedFragments.insert (std::unique_ptr<Fragment>(savedFragment)).second)
|
if (incompleteMessage->savedFragments.insert (savedFragment).second)
|
||||||
incompleteMessage->lastFragmentInsertTime = i2p::util::GetSecondsSinceEpoch ();
|
incompleteMessage->lastFragmentInsertTime = i2p::util::GetSecondsSinceEpoch ();
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "SSU: Fragment ", (int)fragmentNum, " of message ", msgID, " already saved");
|
LogPrint (eLogWarning, "SSU: Fragment ", (int)fragmentNum, " of message ", msgID, " already saved");
|
||||||
|
@ -313,8 +313,8 @@ namespace transport
|
||||||
if (m_SentMessages.empty ()) // schedule resend at first message only
|
if (m_SentMessages.empty ()) // schedule resend at first message only
|
||||||
ScheduleResend ();
|
ScheduleResend ();
|
||||||
|
|
||||||
auto ret = m_SentMessages.insert (std::make_pair (msgID, std::unique_ptr<SentMessage>(new SentMessage)));
|
auto ret = m_SentMessages.insert (std::make_pair (msgID, m_Session.GetServer ().GetSentMessagesPool ().AcquireShared ()));
|
||||||
std::unique_ptr<SentMessage>& sentMessage = ret.first->second;
|
auto& sentMessage = ret.first->second;
|
||||||
if (ret.second)
|
if (ret.second)
|
||||||
{
|
{
|
||||||
sentMessage->nextResendTime = i2p::util::GetSecondsSinceEpoch () + RESEND_INTERVAL;
|
sentMessage->nextResendTime = i2p::util::GetSecondsSinceEpoch () + RESEND_INTERVAL;
|
||||||
|
@ -328,7 +328,7 @@ namespace transport
|
||||||
uint32_t fragmentNum = 0;
|
uint32_t fragmentNum = 0;
|
||||||
while (len > 0 && fragmentNum <= 127)
|
while (len > 0 && fragmentNum <= 127)
|
||||||
{
|
{
|
||||||
Fragment * fragment = new Fragment;
|
auto fragment = m_Session.GetServer ().GetFragmentsPool ().AcquireShared ();
|
||||||
fragment->fragmentNum = fragmentNum;
|
fragment->fragmentNum = fragmentNum;
|
||||||
uint8_t * payload = fragment->buf + sizeof (SSUHeader);
|
uint8_t * payload = fragment->buf + sizeof (SSUHeader);
|
||||||
*payload = DATA_FLAG_WANT_REPLY; // for compatibility
|
*payload = DATA_FLAG_WANT_REPLY; // for compatibility
|
||||||
|
@ -358,7 +358,7 @@ namespace transport
|
||||||
size += padding;
|
size += padding;
|
||||||
}
|
}
|
||||||
fragment->len = size;
|
fragment->len = size;
|
||||||
fragments.push_back (std::unique_ptr<Fragment> (fragment));
|
fragments.push_back (fragment);
|
||||||
|
|
||||||
// encrypt message with session key
|
// encrypt message with session key
|
||||||
uint8_t buf[SSU_V4_MAX_PACKET_SIZE + 18];
|
uint8_t buf[SSU_V4_MAX_PACKET_SIZE + 18];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -64,7 +64,7 @@ namespace transport
|
||||||
|
|
||||||
struct FragmentCmp
|
struct FragmentCmp
|
||||||
{
|
{
|
||||||
bool operator() (const std::unique_ptr<Fragment>& f1, const std::unique_ptr<Fragment>& f2) const
|
bool operator() (const std::shared_ptr<Fragment>& f1, const std::shared_ptr<Fragment>& f2) const
|
||||||
{
|
{
|
||||||
return f1->fragmentNum < f2->fragmentNum;
|
return f1->fragmentNum < f2->fragmentNum;
|
||||||
};
|
};
|
||||||
|
@ -76,7 +76,7 @@ namespace transport
|
||||||
int nextFragmentNum;
|
int nextFragmentNum;
|
||||||
uint32_t lastFragmentInsertTime; // in seconds
|
uint32_t lastFragmentInsertTime; // in seconds
|
||||||
uint64_t receivedFragmentsBits;
|
uint64_t receivedFragmentsBits;
|
||||||
std::set<std::unique_ptr<Fragment>, FragmentCmp> savedFragments;
|
std::set<std::shared_ptr<Fragment>, FragmentCmp> savedFragments;
|
||||||
|
|
||||||
IncompleteMessage (std::shared_ptr<I2NPMessage> m): msg (m), nextFragmentNum (0),
|
IncompleteMessage (std::shared_ptr<I2NPMessage> m): msg (m), nextFragmentNum (0),
|
||||||
lastFragmentInsertTime (0), receivedFragmentsBits (0) {};
|
lastFragmentInsertTime (0), receivedFragmentsBits (0) {};
|
||||||
|
@ -85,7 +85,7 @@ namespace transport
|
||||||
|
|
||||||
struct SentMessage
|
struct SentMessage
|
||||||
{
|
{
|
||||||
std::vector<std::unique_ptr<Fragment> > fragments;
|
std::vector<std::shared_ptr<Fragment> > fragments;
|
||||||
uint32_t nextResendTime; // in seconds
|
uint32_t nextResendTime; // in seconds
|
||||||
int numResends;
|
int numResends;
|
||||||
};
|
};
|
||||||
|
@ -126,8 +126,8 @@ namespace transport
|
||||||
private:
|
private:
|
||||||
|
|
||||||
SSUSession& m_Session;
|
SSUSession& m_Session;
|
||||||
std::unordered_map<uint32_t, std::unique_ptr<IncompleteMessage> > m_IncompleteMessages;
|
std::unordered_map<uint32_t, std::shared_ptr<IncompleteMessage> > m_IncompleteMessages;
|
||||||
std::unordered_map<uint32_t, std::unique_ptr<SentMessage> > m_SentMessages;
|
std::unordered_map<uint32_t, std::shared_ptr<SentMessage> > m_SentMessages;
|
||||||
std::unordered_set<uint32_t> m_ReceivedMessages;
|
std::unordered_set<uint32_t> m_ReceivedMessages;
|
||||||
boost::asio::deadline_timer m_ResendTimer, m_IncompleteMessagesCleanupTimer;
|
boost::asio::deadline_timer m_ResendTimer, m_IncompleteMessagesCleanupTimer;
|
||||||
int m_MaxPacketSize, m_PacketSize;
|
int m_MaxPacketSize, m_PacketSize;
|
||||||
|
|
|
@ -89,7 +89,8 @@ namespace transport
|
||||||
void Done ();
|
void Done ();
|
||||||
void Failed ();
|
void Failed ();
|
||||||
const boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; };
|
const boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; };
|
||||||
|
SSUServer& GetServer () { return m_Server; };
|
||||||
|
|
||||||
bool IsV6 () const { return m_RemoteEndpoint.address ().is_v6 (); };
|
bool IsV6 () const { return m_RemoteEndpoint.address ().is_v6 (); };
|
||||||
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||||
void SendPeerTest (); // Alice
|
void SendPeerTest (); // Alice
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -50,6 +50,11 @@ namespace util
|
||||||
|
|
||||||
MemoryPool (): m_Head (nullptr) {}
|
MemoryPool (): m_Head (nullptr) {}
|
||||||
~MemoryPool ()
|
~MemoryPool ()
|
||||||
|
{
|
||||||
|
CleanUp ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CleanUp ()
|
||||||
{
|
{
|
||||||
while (m_Head)
|
while (m_Head)
|
||||||
{
|
{
|
||||||
|
@ -57,8 +62,8 @@ namespace util
|
||||||
m_Head = static_cast<T*>(*(void * *)m_Head); // next
|
m_Head = static_cast<T*>(*(void * *)m_Head); // next
|
||||||
::operator delete ((void *)tmp);
|
::operator delete ((void *)tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... TArgs>
|
template<typename... TArgs>
|
||||||
T * Acquire (TArgs&&... args)
|
T * Acquire (TArgs&&... args)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue