Browse Source

fixed race condition

pull/102/head
orignal 10 years ago
parent
commit
ec3462fabe
  1. 43
      TunnelPool.cpp
  2. 9
      TunnelPool.h

43
TunnelPool.cpp

@ -25,7 +25,10 @@ namespace tunnel
void TunnelPool::TunnelCreated (InboundTunnel * createdTunnel) void TunnelPool::TunnelCreated (InboundTunnel * createdTunnel)
{ {
m_InboundTunnels.insert (createdTunnel); {
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
m_InboundTunnels.insert (createdTunnel);
}
m_LocalDestination.SetLeaseSetUpdated (); m_LocalDestination.SetLeaseSetUpdated ();
} }
@ -34,15 +37,18 @@ namespace tunnel
if (expiredTunnel) if (expiredTunnel)
{ {
expiredTunnel->SetTunnelPool (nullptr); expiredTunnel->SetTunnelPool (nullptr);
m_InboundTunnels.erase (expiredTunnel);
for (auto it: m_Tests) for (auto it: m_Tests)
if (it.second.second == expiredTunnel) it.second.second = nullptr; if (it.second.second == expiredTunnel) it.second.second = nullptr;
RecreateInboundTunnel (expiredTunnel); RecreateInboundTunnel (expiredTunnel);
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
m_InboundTunnels.erase (expiredTunnel);
} }
} }
void TunnelPool::TunnelCreated (OutboundTunnel * createdTunnel) void TunnelPool::TunnelCreated (OutboundTunnel * createdTunnel)
{ {
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
m_OutboundTunnels.insert (createdTunnel); m_OutboundTunnels.insert (createdTunnel);
} }
@ -51,10 +57,12 @@ namespace tunnel
if (expiredTunnel) if (expiredTunnel)
{ {
expiredTunnel->SetTunnelPool (nullptr); expiredTunnel->SetTunnelPool (nullptr);
m_OutboundTunnels.erase (expiredTunnel);
for (auto it: m_Tests) for (auto it: m_Tests)
if (it.second.first == expiredTunnel) it.second.first = nullptr; if (it.second.first == expiredTunnel) it.second.first = nullptr;
RecreateOutboundTunnel (expiredTunnel); RecreateOutboundTunnel (expiredTunnel);
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
m_OutboundTunnels.erase (expiredTunnel);
} }
} }
@ -62,6 +70,7 @@ namespace tunnel
{ {
std::vector<InboundTunnel *> v; std::vector<InboundTunnel *> v;
int i = 0; int i = 0;
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
for (auto it : m_InboundTunnels) for (auto it : m_InboundTunnels)
{ {
if (i >= num) break; if (i >= num) break;
@ -74,19 +83,21 @@ namespace tunnel
return v; return v;
} }
OutboundTunnel * TunnelPool::GetNextOutboundTunnel (OutboundTunnel * suggested) OutboundTunnel * TunnelPool::GetNextOutboundTunnel (OutboundTunnel * suggested) const
{ {
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
return GetNextTunnel (m_OutboundTunnels, suggested); return GetNextTunnel (m_OutboundTunnels, suggested);
} }
InboundTunnel * TunnelPool::GetNextInboundTunnel (InboundTunnel * suggested) InboundTunnel * TunnelPool::GetNextInboundTunnel (InboundTunnel * suggested) const
{ {
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
return GetNextTunnel (m_InboundTunnels, suggested); return GetNextTunnel (m_InboundTunnels, suggested);
} }
template<class TTunnels> template<class TTunnels>
typename TTunnels::value_type TunnelPool::GetNextTunnel (TTunnels& tunnels, typename TTunnels::value_type TunnelPool::GetNextTunnel (TTunnels& tunnels,
typename TTunnels::value_type suggested) typename TTunnels::value_type suggested) const
{ {
if (tunnels.empty ()) return nullptr; if (tunnels.empty ()) return nullptr;
if (suggested && tunnels.count (suggested) > 0 && suggested->IsEstablished ()) if (suggested && tunnels.count (suggested) > 0 && suggested->IsEstablished ())
@ -110,14 +121,20 @@ namespace tunnel
void TunnelPool::CreateTunnels () void TunnelPool::CreateTunnels ()
{ {
int num = 0; int num = 0;
for (auto it : m_InboundTunnels) {
if (it->IsEstablished ()) num++; std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
for (auto it : m_InboundTunnels)
if (it->IsEstablished ()) num++;
}
for (int i = num; i < m_NumTunnels; i++) for (int i = num; i < m_NumTunnels; i++)
CreateInboundTunnel (); CreateInboundTunnel ();
num = 0; num = 0;
for (auto it : m_OutboundTunnels) {
if (it->IsEstablished ()) num++; std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
for (auto it : m_OutboundTunnels)
if (it->IsEstablished ()) num++;
}
for (int i = num; i < m_NumTunnels; i++) for (int i = num; i < m_NumTunnels; i++)
CreateOutboundTunnel (); CreateOutboundTunnel ();
} }
@ -134,6 +151,7 @@ namespace tunnel
if (it.second.first->GetState () == eTunnelStateTestFailed) if (it.second.first->GetState () == eTunnelStateTestFailed)
{ {
it.second.first->SetState (eTunnelStateFailed); it.second.first->SetState (eTunnelStateFailed);
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
m_OutboundTunnels.erase (it.second.first); m_OutboundTunnels.erase (it.second.first);
} }
else else
@ -144,7 +162,10 @@ namespace tunnel
if (it.second.second->GetState () == eTunnelStateTestFailed) if (it.second.second->GetState () == eTunnelStateTestFailed)
{ {
it.second.second->SetState (eTunnelStateFailed); it.second.second->SetState (eTunnelStateFailed);
m_InboundTunnels.erase (it.second.second); {
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
m_InboundTunnels.erase (it.second.second);
}
m_LocalDestination.SetLeaseSetUpdated (); m_LocalDestination.SetLeaseSetUpdated ();
} }
else else

9
TunnelPool.h

@ -5,6 +5,7 @@
#include <set> #include <set>
#include <vector> #include <vector>
#include <utility> #include <utility>
#include <mutex>
#include "Identity.h" #include "Identity.h"
#include "LeaseSet.h" #include "LeaseSet.h"
#include "RouterInfo.h" #include "RouterInfo.h"
@ -38,8 +39,8 @@ namespace tunnel
void TunnelCreated (OutboundTunnel * createdTunnel); void TunnelCreated (OutboundTunnel * createdTunnel);
void TunnelExpired (OutboundTunnel * expiredTunnel); void TunnelExpired (OutboundTunnel * expiredTunnel);
std::vector<InboundTunnel *> GetInboundTunnels (int num) const; std::vector<InboundTunnel *> GetInboundTunnels (int num) const;
OutboundTunnel * GetNextOutboundTunnel (OutboundTunnel * suggested = nullptr); OutboundTunnel * GetNextOutboundTunnel (OutboundTunnel * suggested = nullptr) const;
InboundTunnel * GetNextInboundTunnel (InboundTunnel * suggested = nullptr); InboundTunnel * GetNextInboundTunnel (InboundTunnel * suggested = nullptr) const;
const i2p::data::IdentHash& GetIdentHash () const { return m_LocalDestination.GetIdentHash (); }; const i2p::data::IdentHash& GetIdentHash () const { return m_LocalDestination.GetIdentHash (); };
void TestTunnels (); void TestTunnels ();
@ -53,14 +54,16 @@ namespace tunnel
void RecreateOutboundTunnel (OutboundTunnel * tunnel); void RecreateOutboundTunnel (OutboundTunnel * tunnel);
template<class TTunnels> template<class TTunnels>
typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels, typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels,
typename TTunnels::value_type suggested = nullptr); typename TTunnels::value_type suggested = nullptr) const;
const i2p::data::RouterInfo * SelectNextHop (const i2p::data::RouterInfo * prevHop) const; const i2p::data::RouterInfo * SelectNextHop (const i2p::data::RouterInfo * prevHop) const;
private: private:
i2p::data::LocalDestination& m_LocalDestination; i2p::data::LocalDestination& m_LocalDestination;
int m_NumHops, m_NumTunnels; int m_NumHops, m_NumTunnels;
mutable std::mutex m_InboundTunnelsMutex;
std::set<InboundTunnel *, TunnelCreationTimeCmp> m_InboundTunnels; // recent tunnel appears first std::set<InboundTunnel *, TunnelCreationTimeCmp> m_InboundTunnels; // recent tunnel appears first
mutable std::mutex m_OutboundTunnelsMutex;
std::set<OutboundTunnel *, TunnelCreationTimeCmp> m_OutboundTunnels; std::set<OutboundTunnel *, TunnelCreationTimeCmp> m_OutboundTunnels;
std::map<uint32_t, std::pair<OutboundTunnel *, InboundTunnel *> > m_Tests; std::map<uint32_t, std::pair<OutboundTunnel *, InboundTunnel *> > m_Tests;

Loading…
Cancel
Save