diff --git a/HTTPServer.cpp b/HTTPServer.cpp
index c7d1fcaf..f02b0ba9 100644
--- a/HTTPServer.cpp
+++ b/HTTPServer.cpp
@@ -139,6 +139,8 @@ namespace util
for (auto it: i2p::tunnel::tunnels.GetOutboundTunnels ())
{
it->GetTunnelConfig ()->Print (s);
+ if (it->GetTunnelPool ())
+ s << " " << "Pool";
s << " " << (int)it->GetNumSentBytes () << "
";
}
diff --git a/Streaming.cpp b/Streaming.cpp
index 6f623f4a..d365e57c 100644
--- a/Streaming.cpp
+++ b/Streaming.cpp
@@ -171,7 +171,7 @@ namespace stream
CreateDataMessage (this, packet, size), m_LocalDestination->GetLeaseSet ());
if (!m_OutboundTunnel)
- m_OutboundTunnel = i2p::tunnel::tunnels.GetNextOutboundTunnel ();
+ m_OutboundTunnel = m_LocalDestination->GetTunnelPool ()->GetNextOutboundTunnel ();
auto leases = m_RemoteLeaseSet.GetNonExpiredLeases ();
if (m_OutboundTunnel && !leases.empty ())
{
diff --git a/Streaming.h b/Streaming.h
index 8f0f289a..b0f7fda9 100644
--- a/Streaming.h
+++ b/Streaming.h
@@ -108,6 +108,7 @@ namespace stream
const i2p::data::Keys& GetKeys () const { return m_Keys; };
const i2p::data::Identity& GetIdentity () const { return m_Identity; };
I2NPMessage * GetLeaseSet ();
+ i2p::tunnel::TunnelPool * GetTunnelPool () const { return m_Pool; };
void Sign (uint8_t * buf, int len, uint8_t * signature) const;
Stream * CreateNewStream (const i2p::data::LeaseSet& remote);
diff --git a/Tunnel.cpp b/Tunnel.cpp
index e9e59b86..5d93c50a 100644
--- a/Tunnel.cpp
+++ b/Tunnel.cpp
@@ -390,13 +390,16 @@ namespace tunnel
if (ts > (*it)->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
{
LogPrint ("Tunnel ", (*it)->GetTunnelID (), " expired");
+ auto pool = (*it)->GetTunnelPool ();
+ if (pool)
+ pool->TunnelExpired (*it);
it = m_OutboundTunnels.erase (it);
}
else
it++;
}
- if (m_OutboundTunnels.size () < 10)
+ if (m_OutboundTunnels.size () < 15) // TODO: store exploratory tunnels explicitly
{
// trying to create one more oubound tunnel
if (m_InboundTunnels.empty ()) return;
@@ -520,6 +523,9 @@ namespace tunnel
void Tunnels::AddOutboundTunnel (OutboundTunnel * newTunnel)
{
m_OutboundTunnels.push_back (newTunnel);
+ auto pool = newTunnel->GetTunnelPool ();
+ if (pool)
+ pool->TunnelCreated (newTunnel);
}
void Tunnels::AddInboundTunnel (InboundTunnel * newTunnel)
diff --git a/TunnelPool.cpp b/TunnelPool.cpp
index 37854db2..6d6516ec 100644
--- a/TunnelPool.cpp
+++ b/TunnelPool.cpp
@@ -11,7 +11,7 @@ namespace i2p
namespace tunnel
{
TunnelPool::TunnelPool (i2p::data::LocalDestination * localDestination, int numTunnels):
- m_LocalDestination (localDestination), m_NumTunnels (numTunnels)
+ m_LocalDestination (localDestination), m_NumTunnels (numTunnels), m_LastOutboundTunnel (nullptr)
{
CryptoPP::AutoSeededRandomPool rnd;
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
@@ -22,6 +22,8 @@ namespace tunnel
{
for (auto it: m_InboundTunnels)
it->SetTunnelPool (nullptr);
+ for (auto it: m_OutboundTunnels)
+ it->SetTunnelPool (nullptr);
}
void TunnelPool::TunnelCreated (InboundTunnel * createdTunnel)
@@ -37,6 +39,16 @@ namespace tunnel
if (m_LocalDestination)
m_LocalDestination->UpdateLeaseSet ();
}
+
+ void TunnelPool::TunnelCreated (OutboundTunnel * createdTunnel)
+ {
+ m_OutboundTunnels.insert (createdTunnel);
+ }
+
+ void TunnelPool::TunnelExpired (OutboundTunnel * expiredTunnel)
+ {
+ m_OutboundTunnels.erase (expiredTunnel);
+ }
std::vector TunnelPool::GetInboundTunnels (int num) const
{
@@ -51,16 +63,37 @@ namespace tunnel
return v;
}
+ OutboundTunnel * TunnelPool::GetNextOutboundTunnel ()
+ {
+ if (m_OutboundTunnels.empty ()) return nullptr;
+ auto tunnel = *m_OutboundTunnels.begin ();
+ if (m_LastOutboundTunnel && tunnel == m_LastOutboundTunnel)
+ {
+ for (auto it: m_OutboundTunnels)
+ if (it != m_LastOutboundTunnel)
+ {
+ tunnel = it;
+ break;
+ }
+ }
+ m_LastOutboundTunnel = tunnel;
+ return tunnel;
+ }
+
void TunnelPool::CreateTunnels ()
{
int num = m_InboundTunnels.size ();
for (int i = num; i < m_NumTunnels; i++)
CreateInboundTunnel ();
+ num = m_OutboundTunnels.size ();
+ for (int i = num; i < m_NumTunnels; i++)
+ CreateOutboundTunnel ();
}
void TunnelPool::CreateInboundTunnel ()
{
- OutboundTunnel * outboundTunnel = tunnels.GetNextOutboundTunnel ();
+ OutboundTunnel * outboundTunnel = m_OutboundTunnels.size () > 0 ?
+ *m_OutboundTunnels.begin () : tunnels.GetNextOutboundTunnel ();
LogPrint ("Creating destination inbound tunnel...");
auto firstHop = i2p::data::netdb.GetRandomRouter (outboundTunnel ? outboundTunnel->GetEndpointRouter () : nullptr);
auto secondHop = i2p::data::netdb.GetRandomRouter (firstHop);
@@ -75,5 +108,25 @@ namespace tunnel
outboundTunnel);
tunnel->SetTunnelPool (this);
}
+
+ void TunnelPool::CreateOutboundTunnel ()
+ {
+ InboundTunnel * inboundTunnel = m_InboundTunnels.size () > 0 ?
+ *m_InboundTunnels.begin () : tunnels.GetNextInboundTunnel ();
+ if (inboundTunnel)
+ {
+ LogPrint ("Creating destination outbound tunnel...");
+ auto firstHop = i2p::data::netdb.GetRandomRouter (&i2p::context.GetRouterInfo ());
+ auto secondHop = i2p::data::netdb.GetRandomRouter (firstHop);
+ auto * tunnel = tunnels.CreateTunnel (
+ new TunnelConfig (std::vector
+ {
+ firstHop,
+ secondHop
+ },
+ inboundTunnel->GetTunnelConfig ()));
+ tunnel->SetTunnelPool (this);
+ }
+ }
}
}
diff --git a/TunnelPool.h b/TunnelPool.h
index 8dad4051..f8b6aab5 100644
--- a/TunnelPool.h
+++ b/TunnelPool.h
@@ -29,19 +29,24 @@ namespace tunnel
void CreateTunnels ();
void TunnelCreated (InboundTunnel * createdTunnel);
void TunnelExpired (InboundTunnel * expiredTunnel);
+ void TunnelCreated (OutboundTunnel * createdTunnel);
+ void TunnelExpired (OutboundTunnel * expiredTunnel);
std::vector GetInboundTunnels (int num) const;
-
+ OutboundTunnel * GetNextOutboundTunnel ();
+
private:
void CreateInboundTunnel ();
-
+ void CreateOutboundTunnel ();
+
private:
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
i2p::data::LocalDestination * m_LocalDestination;
int m_NumTunnels;
std::set m_InboundTunnels; // recent tunnel appears first
-
+ std::set m_OutboundTunnels;
+ OutboundTunnel * m_LastOutboundTunnel;
};
}
}