diff --git a/ClientContext.cpp b/ClientContext.cpp
index ea459a13..2cdd3ae9 100644
--- a/ClientContext.cpp
+++ b/ClientContext.cpp
@@ -100,15 +100,21 @@ namespace client
void ClientContext::Stop ()
{
- LogPrint(eLogInfo, "Clients: stopping HTTP Proxy");
- m_HttpProxy->Stop();
- delete m_HttpProxy;
- m_HttpProxy = nullptr;
+ if (m_HttpProxy)
+ {
+ LogPrint(eLogInfo, "Clients: stopping HTTP Proxy");
+ m_HttpProxy->Stop();
+ delete m_HttpProxy;
+ m_HttpProxy = nullptr;
+ }
- LogPrint(eLogInfo, "Clients: stopping SOCKS Proxy");
- m_SocksProxy->Stop();
- delete m_SocksProxy;
- m_SocksProxy = nullptr;
+ if (m_SocksProxy)
+ {
+ LogPrint(eLogInfo, "Clients: stopping SOCKS Proxy");
+ m_SocksProxy->Stop();
+ delete m_SocksProxy;
+ m_SocksProxy = nullptr;
+ }
for (auto& it: m_ClientTunnels)
{
diff --git a/HTTPServer.cpp b/HTTPServer.cpp
index 85dbec42..3b92d4bc 100644
--- a/HTTPServer.cpp
+++ b/HTTPServer.cpp
@@ -447,6 +447,13 @@ namespace util
s << "
\r\nRouters: " << i2p::data::netdb.GetNumRouters () << " ";
s << "Floodfills: " << i2p::data::netdb.GetNumFloodfills () << " ";
s << "LeaseSets: " << i2p::data::netdb.GetNumLeaseSets () << "
\r\n";
+
+ size_t clientTunnelCount = i2p::tunnel::tunnels.CountOutboundTunnels();
+ clientTunnelCount += i2p::tunnel::tunnels.CountInboundTunnels();
+ size_t transitTunnelCount = i2p::tunnel::tunnels.CountTransitTunnels();
+
+ s << "Client Tunnels: " << std::to_string(clientTunnelCount) << " ";
+ s << "Transit Tunnels: " << std::to_string(transitTunnelCount) << "
\r\n";
}
void HTTPConnection::HandleCommand (const std::string& command, std::stringstream& s)
@@ -603,13 +610,13 @@ namespace util
for (auto it: i2p::tunnel::tunnels.GetInboundTunnels ())
{
- it.second->Print (s);
- auto state = it.second->GetState ();
+ it->Print (s);
+ auto state = it->GetState ();
if (state == i2p::tunnel::eTunnelStateFailed)
s << " " << "Failed";
else if (state == i2p::tunnel::eTunnelStateExpiring)
s << " " << "Exp";
- s << " " << (int)it.second->GetNumReceivedBytes () << "
\r\n";
+ s << " " << (int)it->GetNumReceivedBytes () << "
\r\n";
s << std::endl;
}
}
@@ -619,13 +626,13 @@ namespace util
s << "Transit tunnels:
\r\n
\r\n";
for (auto it: i2p::tunnel::tunnels.GetTransitTunnels ())
{
- if (dynamic_cast(it.second))
- s << it.second->GetTunnelID () << " ⇒ ";
- else if (dynamic_cast(it.second))
- s << " ⇒ " << it.second->GetTunnelID ();
+ if (std::dynamic_pointer_cast(it))
+ s << it->GetTunnelID () << " ⇒ ";
+ else if (std::dynamic_pointer_cast(it))
+ s << " ⇒ " << it->GetTunnelID ();
else
- s << " ⇒ " << it.second->GetTunnelID () << " ⇒ ";
- s << " " << it.second->GetNumTransmittedBytes () << "
\r\n";
+ s << " ⇒ " << it->GetTunnelID () << " ⇒ ";
+ s << " " << it->GetNumTransmittedBytes () << "
\r\n";
}
}
diff --git a/I2NPProtocol.cpp b/I2NPProtocol.cpp
index dff66951..7cebf96a 100644
--- a/I2NPProtocol.cpp
+++ b/I2NPProtocol.cpp
@@ -301,8 +301,7 @@ namespace i2p
i2p::tunnel::tunnels.GetTransitTunnels ().size () <= MAX_NUM_TRANSIT_TUNNELS &&
!i2p::transport::transports.IsBandwidthExceeded ())
{
- i2p::tunnel::TransitTunnel * transitTunnel =
- i2p::tunnel::CreateTransitTunnel (
+ auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
bufbe32toh (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
diff --git a/NetDb.cpp b/NetDb.cpp
index 501852bb..eb1380de 100644
--- a/NetDb.cpp
+++ b/NetDb.cpp
@@ -677,7 +677,7 @@ namespace data
excludedRouters.insert (excluded);
excluded += 32;
}
- replyMsg = CreateDatabaseSearchReply (ident, GetClosestFloodfills (ident, 3, excludedRouters));
+ replyMsg = CreateDatabaseSearchReply (ident, GetClosestFloodfills (ident, 3, excludedRouters, true));
}
}
@@ -884,7 +884,7 @@ namespace data
}
std::vector NetDb::GetClosestFloodfills (const IdentHash& destination, size_t num,
- std::set& excluded) const
+ std::set& excluded, bool closeThanUsOnly) const
{
struct Sorted
{
@@ -895,6 +895,8 @@ namespace data
std::set sorted;
IdentHash destKey = CreateRoutingKey (destination);
+ XORMetric ourMetric;
+ if (closeThanUsOnly) ourMetric = destKey ^ i2p::context.GetIdentHash ();
{
std::unique_lock l(m_FloodfillsMutex);
for (auto it: m_Floodfills)
@@ -902,6 +904,7 @@ namespace data
if (!it->IsUnreachable ())
{
XORMetric m = destKey ^ it->GetIdentHash ();
+ if (closeThanUsOnly && ourMetric < m) continue;
if (sorted.size () < num)
sorted.insert ({it, m});
else if (m < sorted.rbegin ()->metric)
@@ -960,9 +963,9 @@ namespace data
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
for (auto it = m_LeaseSets.begin (); it != m_LeaseSets.end ();)
{
- if (ts > it->second->GetExpirationTime ())
+ if (ts > it->second->GetExpirationTime () - LEASE_ENDDATE_THRESHOLD)
{
- LogPrint (eLogWarning, "NetDb: LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired");
+ LogPrint (eLogInfo, "NetDb: LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired");
it = m_LeaseSets.erase (it);
}
else
diff --git a/NetDb.h b/NetDb.h
index 7b196330..536ff644 100644
--- a/NetDb.h
+++ b/NetDb.h
@@ -60,7 +60,7 @@ namespace data
std::shared_ptr GetRandomIntroducer () const;
std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded, bool closeThanUsOnly = false) const;
std::vector GetClosestFloodfills (const IdentHash& destination, size_t num,
- std::set& excluded) const;
+ std::set& excluded, bool closeThanUsOnly = false) const;
std::shared_ptr GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const;
void SetUnreachable (const IdentHash& ident, bool unreachable);
diff --git a/TransitTunnel.cpp b/TransitTunnel.cpp
index 81773bb5..0d54fc11 100644
--- a/TransitTunnel.cpp
+++ b/TransitTunnel.cpp
@@ -85,7 +85,7 @@ namespace tunnel
m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg);
}
- TransitTunnel * CreateTransitTunnel (uint32_t receiveTunnelID,
+ std::shared_ptr CreateTransitTunnel (uint32_t receiveTunnelID,
const uint8_t * nextIdent, uint32_t nextTunnelID,
const uint8_t * layerKey,const uint8_t * ivKey,
bool isGateway, bool isEndpoint)
@@ -93,17 +93,17 @@ namespace tunnel
if (isEndpoint)
{
LogPrint (eLogInfo, "TransitTunnel: endpoint ", receiveTunnelID, " created");
- return new TransitTunnelEndpoint (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
+ return std::make_shared (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
}
else if (isGateway)
{
LogPrint (eLogInfo, "TransitTunnel: gateway ", receiveTunnelID, " created");
- return new TransitTunnelGateway (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
+ return std::make_shared (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
}
else
{
LogPrint (eLogInfo, "TransitTunnel: ", receiveTunnelID, "->", nextTunnelID, " created");
- return new TransitTunnelParticipant (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
+ return std::make_shared (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
}
}
}
diff --git a/TransitTunnel.h b/TransitTunnel.h
index e611d685..2a1908df 100644
--- a/TransitTunnel.h
+++ b/TransitTunnel.h
@@ -93,7 +93,7 @@ namespace tunnel
TunnelEndpoint m_Endpoint;
};
- TransitTunnel * CreateTransitTunnel (uint32_t receiveTunnelID,
+ std::shared_ptr CreateTransitTunnel (uint32_t receiveTunnelID,
const uint8_t * nextIdent, uint32_t nextTunnelID,
const uint8_t * layerKey,const uint8_t * ivKey,
bool isGateway, bool isEndpoint);
diff --git a/Tunnel.cpp b/Tunnel.cpp
index f7102327..37dd6d67 100644
--- a/Tunnel.cpp
+++ b/Tunnel.cpp
@@ -205,6 +205,26 @@ namespace tunnel
PrintHops (s);
s << " ⇒ " << GetTunnelID () << ":me";
}
+
+ ZeroHopsInboundTunnel::ZeroHopsInboundTunnel ():
+ InboundTunnel (std::make_shared ()),
+ m_NumReceivedBytes (0)
+ {
+ }
+
+ void ZeroHopsInboundTunnel::SendTunnelDataMsg (std::shared_ptr msg)
+ {
+ if (msg)
+ {
+ m_NumReceivedBytes += msg->GetLength ();
+ HandleI2NPMessage (msg);
+ }
+ }
+
+ void ZeroHopsInboundTunnel::Print (std::stringstream& s) const
+ {
+ s << " ⇒ " << GetTunnelID () << ":me";
+ }
void OutboundTunnel::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr msg)
{
@@ -257,27 +277,16 @@ namespace tunnel
Tunnels::~Tunnels ()
{
- for (auto& it : m_TransitTunnels)
- delete it.second;
- m_TransitTunnels.clear ();
}
-
- std::shared_ptr Tunnels::GetInboundTunnel (uint32_t tunnelID)
+
+ std::shared_ptr Tunnels::GetTunnel (uint32_t tunnelID)
{
- auto it = m_InboundTunnels.find(tunnelID);
- if (it != m_InboundTunnels.end ())
+ auto it = m_Tunnels.find(tunnelID);
+ if (it != m_Tunnels.end ())
return it->second;
return nullptr;
}
-
- TransitTunnel * Tunnels::GetTransitTunnel (uint32_t tunnelID)
- {
- auto it = m_TransitTunnels.find(tunnelID);
- if (it != m_TransitTunnels.end ())
- return it->second;
- return nullptr;
- }
-
+
std::shared_ptr Tunnels::GetPendingInboundTunnel (uint32_t replyMsgID)
{
return GetPendingTunnel (replyMsgID, m_PendingInboundTunnels);
@@ -306,11 +315,11 @@ namespace tunnel
size_t minReceived = 0;
for (auto it : m_InboundTunnels)
{
- if (!it.second->IsEstablished ()) continue;
- if (!tunnel || it.second->GetNumReceivedBytes () < minReceived)
+ if (!it->IsEstablished ()) continue;
+ if (!tunnel || it->GetNumReceivedBytes () < minReceived)
{
- tunnel = it.second;
- minReceived = it.second->GetNumReceivedBytes ();
+ tunnel = it;
+ minReceived = it->GetNumReceivedBytes ();
}
}
return tunnel;
@@ -363,14 +372,12 @@ namespace tunnel
}
}
- void Tunnels::AddTransitTunnel (TransitTunnel * tunnel)
+ void Tunnels::AddTransitTunnel (std::shared_ptr tunnel)
{
- std::unique_lock l(m_TransitTunnelsMutex);
- if (!m_TransitTunnels.insert (std::make_pair (tunnel->GetTunnelID (), tunnel)).second)
- {
- LogPrint (eLogError, "Tunnel: transit tunnel with id ", tunnel->GetTunnelID (), " already exists");
- delete tunnel;
- }
+ if (m_Tunnels.emplace (tunnel->GetTunnelID (), tunnel).second)
+ m_TransitTunnels.push_back (tunnel);
+ else
+ LogPrint (eLogError, "Tunnel: tunnel with id ", tunnel->GetTunnelID (), " already exists");
}
void Tunnels::Start ()
@@ -404,10 +411,10 @@ namespace tunnel
if (msg)
{
uint32_t prevTunnelID = 0, tunnelID = 0;
- TunnelBase * prevTunnel = nullptr;
+ std::shared_ptr prevTunnel;
do
{
- TunnelBase * tunnel = nullptr;
+ std::shared_ptr tunnel;
uint8_t typeID = msg->GetTypeID ();
switch (typeID)
{
@@ -420,10 +427,8 @@ namespace tunnel
else if (prevTunnel)
prevTunnel->FlushTunnelDataMsgs ();
- if (!tunnel && typeID == eI2NPTunnelData)
- tunnel = GetInboundTunnel (tunnelID).get ();
if (!tunnel)
- tunnel = GetTransitTunnel (tunnelID);
+ tunnel = GetTunnel (tunnelID);
if (tunnel)
{
if (typeID == eI2NPTunnelData)
@@ -471,7 +476,7 @@ namespace tunnel
}
}
- void Tunnels::HandleTunnelGatewayMsg (TunnelBase * tunnel, std::shared_ptr msg)
+ void Tunnels::HandleTunnelGatewayMsg (std::shared_ptr tunnel, std::shared_ptr msg)
{
if (!tunnel)
{
@@ -580,6 +585,7 @@ namespace tunnel
auto pool = tunnel->GetTunnelPool ();
if (pool)
pool->TunnelExpired (tunnel);
+ // we don't have outbound tunnels in m_Tunnels
it = m_OutboundTunnels.erase (it);
}
else
@@ -621,13 +627,14 @@ namespace tunnel
{
for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();)
{
- auto tunnel = it->second;
+ auto tunnel = *it;
if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
{
LogPrint (eLogDebug, "Tunnel: tunnel with id ", tunnel->GetTunnelID (), " expired");
auto pool = tunnel->GetTunnelPool ();
if (pool)
pool->TunnelExpired (tunnel);
+ m_Tunnels.erase (tunnel->GetTunnelID ());
it = m_InboundTunnels.erase (it);
}
else
@@ -682,15 +689,12 @@ namespace tunnel
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
for (auto it = m_TransitTunnels.begin (); it != m_TransitTunnels.end ();)
{
- if (ts > it->second->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
+ auto tunnel = *it;
+ if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
{
- auto tmp = it->second;
- LogPrint (eLogDebug, "Tunnel: Transit tunnel with id ", tmp->GetTunnelID (), " expired");
- {
- std::unique_lock l(m_TransitTunnelsMutex);
- it = m_TransitTunnels.erase (it);
- }
- delete tmp;
+ LogPrint (eLogDebug, "Tunnel: Transit tunnel with id ", tunnel->GetTunnelID (), " expired");
+ m_Tunnels.erase (tunnel->GetTunnelID ());
+ it = m_TransitTunnels.erase (it);
}
else
it++;
@@ -744,6 +748,7 @@ namespace tunnel
void Tunnels::AddOutboundTunnel (std::shared_ptr newTunnel)
{
+ // we don't need to insert it to m_Tunnels
m_OutboundTunnels.push_back (newTunnel);
auto pool = newTunnel->GetTunnelPool ();
if (pool && pool->IsActive ())
@@ -754,46 +759,79 @@ namespace tunnel
void Tunnels::AddInboundTunnel (std::shared_ptr newTunnel)
{
- m_InboundTunnels[newTunnel->GetTunnelID ()] = newTunnel;
- auto pool = newTunnel->GetTunnelPool ();
- if (!pool)
- {
- // build symmetric outbound tunnel
- CreateTunnel (std::make_shared(newTunnel->GetInvertedPeers (),
- newTunnel->GetNextTunnelID (), newTunnel->GetNextIdentHash ()),
- GetNextOutboundTunnel ());
+ if (m_Tunnels.emplace (newTunnel->GetTunnelID (), newTunnel).second)
+ {
+ m_InboundTunnels.push_back (newTunnel);
+ auto pool = newTunnel->GetTunnelPool ();
+ if (!pool)
+ {
+ // build symmetric outbound tunnel
+ CreateTunnel (std::make_shared(newTunnel->GetInvertedPeers (),
+ newTunnel->GetNextTunnelID (), newTunnel->GetNextIdentHash ()),
+ GetNextOutboundTunnel ());
+ }
+ else
+ {
+ if (pool->IsActive ())
+ pool->TunnelCreated (newTunnel);
+ else
+ newTunnel->SetTunnelPool (nullptr);
+ }
}
else
- {
- if (pool->IsActive ())
- pool->TunnelCreated (newTunnel);
- else
- newTunnel->SetTunnelPool (nullptr);
- }
+ LogPrint (eLogError, "Tunnel: tunnel with id ", newTunnel->GetTunnelID (), " already exists");
}
void Tunnels::CreateZeroHopsInboundTunnel ()
{
- CreateTunnel (
+ /*CreateTunnel (
std::make_shared (std::vector >
{
i2p::context.GetIdentity ()
- }));
+ }));*/
+ auto inboundTunnel = std::make_shared ();
+ m_InboundTunnels.push_back (inboundTunnel);
+ m_Tunnels[inboundTunnel->GetTunnelID ()] = inboundTunnel;
+
+ // create paired outbound tunnel, TODO: move to separate function
+ CreateTunnel (
+ std::make_shared (std::vector >
+ {
+ i2p::context.GetIdentity ()
+ }, inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ()));
}
int Tunnels::GetTransitTunnelsExpirationTimeout ()
{
int timeout = 0;
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
- std::unique_lock l(m_TransitTunnelsMutex);
+ // TODO: possible race condition with I2PControl
for (auto it: m_TransitTunnels)
{
- int t = it.second->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT - ts;
+ int t = it->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT - ts;
if (t > timeout) timeout = t;
}
return timeout;
- }
+ }
+
+ size_t Tunnels::CountTransitTunnels() const
+ {
+ // TODO: locking
+ return m_TransitTunnels.size();
+ }
+
+ size_t Tunnels::CountInboundTunnels() const
+ {
+ // TODO: locking
+ return m_InboundTunnels.size();
+ }
+
+ size_t Tunnels::CountOutboundTunnels() const
+ {
+ // TODO: locking
+ return m_OutboundTunnels.size();
+ }
}
}
diff --git a/Tunnel.h b/Tunnel.h
index 138a48fc..34d0a0ab 100644
--- a/Tunnel.h
+++ b/Tunnel.h
@@ -3,6 +3,7 @@
#include
#include