Browse Source

handle transit tunnel build messages in separate thread

openssl
orignal 4 days ago
parent
commit
d241e5d5cb
  1. 73
      libi2pd/TransitTunnel.cpp
  2. 23
      libi2pd/TransitTunnel.h
  3. 8
      libi2pd/Tunnel.cpp
  4. 5
      libi2pd/Tunnel.h

73
libi2pd/TransitTunnel.cpp

@ -122,15 +122,87 @@ namespace tunnel
} }
} }
TransitTunnels::TransitTunnels ():
m_IsRunning (false)
{
}
TransitTunnels::~TransitTunnels ()
{
Stop ();
}
void TransitTunnels::Start () void TransitTunnels::Start ()
{ {
m_IsRunning = true;
m_Thread.reset (new std::thread (std::bind (&TransitTunnels::Run, this)));
} }
void TransitTunnels::Stop () void TransitTunnels::Stop ()
{ {
m_IsRunning = false;
m_TunnelBuildMsgQueue.WakeUp ();
if (m_Thread)
{
m_Thread->join ();
m_Thread = nullptr;
}
m_TransitTunnels.clear (); m_TransitTunnels.clear ();
} }
void TransitTunnels::Run ()
{
i2p::util::SetThreadName("TBM");
uint64_t lastTs = 0;
std::list<std::shared_ptr<I2NPMessage> > msgs;
while (m_IsRunning)
{
try
{
if (m_TunnelBuildMsgQueue.Wait (TRANSIT_TUNNELS_QUEUE_WAIT_INTERVAL, 0))
{
m_TunnelBuildMsgQueue.GetWholeQueue (msgs);
while (!msgs.empty ())
{
auto msg = msgs.front (); msgs.pop_front ();
if (!msg) continue;
uint8_t typeID = msg->GetTypeID ();
switch (typeID)
{
case eI2NPShortTunnelBuild:
HandleShortTransitTunnelBuildMsg (std::move (msg));
break;
case eI2NPVariableTunnelBuild:
HandleVariableTransitTunnelBuildMsg (std::move (msg));
break;
default:
LogPrint (eLogWarning, "TransitTunnel: Unexpected message type ", (int) typeID);
}
if (!m_IsRunning) break;
}
}
if (m_IsRunning)
{
uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
if (ts >= lastTs + TUNNEL_MANAGE_INTERVAL || ts + TUNNEL_MANAGE_INTERVAL < lastTs)
{
ManageTransitTunnels (ts);
lastTs = ts;
}
}
}
catch (std::exception& ex)
{
LogPrint (eLogError, "TransitTunnel: Runtime exception: ", ex.what ());
}
}
}
void TransitTunnels::PostTransitTunnelBuildMsg (std::shared_ptr<I2NPMessage>&& msg)
{
if (msg) m_TunnelBuildMsgQueue.Put (msg);
}
void TransitTunnels::HandleShortTransitTunnelBuildMsg (std::shared_ptr<I2NPMessage>&& msg) void TransitTunnels::HandleShortTransitTunnelBuildMsg (std::shared_ptr<I2NPMessage>&& msg)
{ {
if (!msg) return; if (!msg) return;
@ -234,6 +306,7 @@ namespace tunnel
{ {
if (transitTunnel) if (transitTunnel)
{ {
LogPrint (eLogDebug, "TransitTunnel: Failed to send reply for transit tunnel ", transitTunnel->GetTunnelID ());
auto t = transitTunnel->GetCreationTime (); auto t = transitTunnel->GetCreationTime ();
if (t > i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT) if (t > i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT)
// make transit tunnel expired // make transit tunnel expired

23
libi2pd/TransitTunnel.h

@ -14,6 +14,7 @@
#include <mutex> #include <mutex>
#include <memory> #include <memory>
#include "Crypto.h" #include "Crypto.h"
#include "Queue.h"
#include "I2NPProtocol.h" #include "I2NPProtocol.h"
#include "TunnelEndpoint.h" #include "TunnelEndpoint.h"
#include "TunnelGateway.h" #include "TunnelGateway.h"
@ -109,33 +110,45 @@ namespace tunnel
const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey, const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey,
bool isGateway, bool isEndpoint); bool isGateway, bool isEndpoint);
const int TRANSIT_TUNNELS_QUEUE_WAIT_INTERVAL = 10; // in seconds
class TransitTunnels class TransitTunnels
{ {
public: public:
TransitTunnels ();
~TransitTunnels ();
void Start (); void Start ();
void Stop (); void Stop ();
void ManageTransitTunnels (uint64_t ts); void PostTransitTunnelBuildMsg (std::shared_ptr<I2NPMessage>&& msg);
size_t GetNumTransitTunnels () const { return m_TransitTunnels.size (); } size_t GetNumTransitTunnels () const { return m_TransitTunnels.size (); }
int GetTransitTunnelsExpirationTimeout (); int GetTransitTunnelsExpirationTimeout ();
void HandleShortTransitTunnelBuildMsg (std::shared_ptr<I2NPMessage>&& msg);
void HandleVariableTransitTunnelBuildMsg (std::shared_ptr<I2NPMessage>&& msg);
private: private:
bool AddTransitTunnel (std::shared_ptr<TransitTunnel> tunnel); bool AddTransitTunnel (std::shared_ptr<TransitTunnel> tunnel);
void ManageTransitTunnels (uint64_t ts);
void HandleShortTransitTunnelBuildMsg (std::shared_ptr<I2NPMessage>&& msg);
void HandleVariableTransitTunnelBuildMsg (std::shared_ptr<I2NPMessage>&& msg);
bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText); bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText);
void Run ();
private: private:
volatile bool m_IsRunning;
std::unique_ptr<std::thread> m_Thread;
std::list<std::shared_ptr<TransitTunnel> > m_TransitTunnels; std::list<std::shared_ptr<TransitTunnel> > m_TransitTunnels;
i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_TunnelBuildMsgQueue;
public: public:
// for HTTP only // for HTTP only
auto& GetTransitTunnels () const { return m_TransitTunnels; }; const auto& GetTransitTunnels () const { return m_TransitTunnels; };
}; };
} }
} }

8
libi2pd/Tunnel.cpp

@ -373,6 +373,7 @@ namespace tunnel
std::shared_ptr<TunnelBase> Tunnels::GetTunnel (uint32_t tunnelID) std::shared_ptr<TunnelBase> Tunnels::GetTunnel (uint32_t tunnelID)
{ {
std::lock_guard<std::mutex> l(m_TunnelsMutex);
auto it = m_Tunnels.find(tunnelID); auto it = m_Tunnels.find(tunnelID);
if (it != m_Tunnels.end ()) if (it != m_Tunnels.end ())
return it->second; return it->second;
@ -382,11 +383,13 @@ namespace tunnel
bool Tunnels::AddTunnel (std::shared_ptr<TunnelBase> tunnel) bool Tunnels::AddTunnel (std::shared_ptr<TunnelBase> tunnel)
{ {
if (!tunnel) return false; if (!tunnel) return false;
std::lock_guard<std::mutex> l(m_TunnelsMutex);
return m_Tunnels.emplace (tunnel->GetTunnelID (), tunnel).second; return m_Tunnels.emplace (tunnel->GetTunnelID (), tunnel).second;
} }
void Tunnels::RemoveTunnel (uint32_t tunnelID) void Tunnels::RemoveTunnel (uint32_t tunnelID)
{ {
std::lock_guard<std::mutex> l(m_TunnelsMutex);
m_Tunnels.erase (tunnelID); m_Tunnels.erase (tunnelID);
} }
@ -655,7 +658,7 @@ namespace tunnel
return; return;
} }
else else
m_TransitTunnels.HandleShortTransitTunnelBuildMsg (std::move (msg)); m_TransitTunnels.PostTransitTunnelBuildMsg (std::move (msg));
} }
void Tunnels::HandleVariableTunnelBuildMsg (std::shared_ptr<I2NPMessage> msg) void Tunnels::HandleVariableTunnelBuildMsg (std::shared_ptr<I2NPMessage> msg)
@ -678,7 +681,7 @@ namespace tunnel
} }
} }
else else
m_TransitTunnels.HandleVariableTransitTunnelBuildMsg (std::move (msg)); m_TransitTunnels.PostTransitTunnelBuildMsg (std::move (msg));
} }
void Tunnels::HandleTunnelBuildReplyMsg (std::shared_ptr<I2NPMessage> msg, bool isShort) void Tunnels::HandleTunnelBuildReplyMsg (std::shared_ptr<I2NPMessage> msg, bool isShort)
@ -710,7 +713,6 @@ namespace tunnel
ManagePendingTunnels (ts); ManagePendingTunnels (ts);
ManageInboundTunnels (ts); ManageInboundTunnels (ts);
ManageOutboundTunnels (ts); ManageOutboundTunnels (ts);
m_TransitTunnels.ManageTransitTunnels (ts);
} }
void Tunnels::ManagePendingTunnels (uint64_t ts) void Tunnels::ManagePendingTunnels (uint64_t ts)

5
libi2pd/Tunnel.h

@ -300,8 +300,9 @@ namespace tunnel
std::map<uint32_t, std::shared_ptr<OutboundTunnel> > m_PendingOutboundTunnels; // by replyMsgID std::map<uint32_t, std::shared_ptr<OutboundTunnel> > m_PendingOutboundTunnels; // by replyMsgID
std::list<std::shared_ptr<InboundTunnel> > m_InboundTunnels; std::list<std::shared_ptr<InboundTunnel> > m_InboundTunnels;
std::list<std::shared_ptr<OutboundTunnel> > m_OutboundTunnels; std::list<std::shared_ptr<OutboundTunnel> > m_OutboundTunnels;
mutable std::mutex m_TunnelsMutex;
std::unordered_map<uint32_t, std::shared_ptr<TunnelBase> > m_Tunnels; // tunnelID->tunnel known by this id std::unordered_map<uint32_t, std::shared_ptr<TunnelBase> > m_Tunnels; // tunnelID->tunnel known by this id
std::mutex m_PoolsMutex; mutable std::mutex m_PoolsMutex;
std::list<std::shared_ptr<TunnelPool>> m_Pools; std::list<std::shared_ptr<TunnelPool>> m_Pools;
std::shared_ptr<TunnelPool> m_ExploratoryPool; std::shared_ptr<TunnelPool> m_ExploratoryPool;
i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_Queue; i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_Queue;
@ -320,7 +321,7 @@ namespace tunnel
// for HTTP only // for HTTP only
const decltype(m_OutboundTunnels)& GetOutboundTunnels () const { return m_OutboundTunnels; }; const decltype(m_OutboundTunnels)& GetOutboundTunnels () const { return m_OutboundTunnels; };
const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; }; const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; };
auto& GetTransitTunnels () const { return m_TransitTunnels.GetTransitTunnels (); }; const auto& GetTransitTunnels () const { return m_TransitTunnels.GetTransitTunnels (); };
size_t CountTransitTunnels() const; size_t CountTransitTunnels() const;
size_t CountInboundTunnels() const; size_t CountInboundTunnels() const;

Loading…
Cancel
Save