diff --git a/NetDb.cpp b/NetDb.cpp index 75669260..4a460d8f 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -427,7 +427,7 @@ namespace data auto inbound = i2p::tunnel::tunnels.GetNextInboundTunnel (); if (outbound && inbound) { - auto floodfill = GetRandomNTCPRouter (true); + auto floodfill = GetRandomRouter (outbound->GetEndpointRouter (), true); if (floodfill) { LogPrint ("Exploring new routers ..."); @@ -495,19 +495,29 @@ namespace data return last; } - const RouterInfo * NetDb::GetRandomRouter () const + const RouterInfo * NetDb::GetRandomRouter (const RouterInfo * compatibleWith, bool floodfillOnly) const { CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); - uint32_t ind = rnd.GenerateWord32 (0, m_RouterInfos.size () - 1), i = 0; - RouterInfo * last = nullptr; - for (auto it: m_RouterInfos) + uint32_t ind = rnd.GenerateWord32 (0, m_RouterInfos.size () - 1); + for (int j = 0; j < 2; j++) { - if (!it.second->IsUnreachable ()) - last = it.second; - if (i >= ind) break; - else i++; + uint32_t i = 0; + for (auto it: m_RouterInfos) + { + if (i >= ind) + { + if (!it.second->IsUnreachable () && + (!compatibleWith || it.second->IsCompatible (*compatibleWith)) && + (!floodfillOnly || it.second->IsFloodfill ())) + return it.second; + } + else + i++; + } + // we couldn't find anything, try second pass + ind = 0; } - return last; + return nullptr; // seem we have too few routers } void NetDb::PostI2NPMsg (I2NPMessage * msg) diff --git a/NetDb.h b/NetDb.h index 03be5ed6..7f56c169 100644 --- a/NetDb.h +++ b/NetDb.h @@ -68,7 +68,7 @@ namespace data void HandleDatabaseSearchReplyMsg (I2NPMessage * msg); const RouterInfo * GetRandomNTCPRouter (bool floodfillOnly = false) const; - const RouterInfo * GetRandomRouter () const; + const RouterInfo * GetRandomRouter (const RouterInfo * compatibleWith = nullptr, bool floodfillOnly = false) const; void PostI2NPMsg (I2NPMessage * msg); diff --git a/RouterInfo.cpp b/RouterInfo.cpp index ee9a60c2..8126d622 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -13,19 +13,18 @@ #include "RouterContext.h" - namespace i2p { namespace data { RouterInfo::RouterInfo (const char * filename): - m_IsUpdated (false), m_IsUnreachable (false) + m_IsUpdated (false), m_IsUnreachable (false), m_SupportedTransports (0) { ReadFromFile (filename); } RouterInfo::RouterInfo (const uint8_t * buf, int len): - m_IsUpdated (true) + m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0) { memcpy (m_Buffer, buf, len); m_BufferLen = len; @@ -111,7 +110,15 @@ namespace data // TODO: we should try to resolve address here LogPrint ("Unexpected address ", value); SetUnreachable (true); - } + } + else + { + // add supported protocol + if (address.host.is_v4 ()) + m_SupportedTransports |= (address.transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4; + else + m_SupportedTransports |= (address.transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6; + } } else if (!strcmp (key, "port")) address.port = boost::lexical_cast(value); @@ -275,17 +282,12 @@ namespace data bool RouterInfo::IsNTCP (bool v4only) const { - for (auto& address : m_Addresses) - { - if (address.transportStyle == eTransportNTCP) - { - if (!v4only || address.host.is_v4 ()) - return true; - } - } - return false; - } - + if (v4only) + return m_SupportedTransports & eNTCPV4; + else + return m_SupportedTransports & (eNTCPV4 | eNTCPV6); + } + RouterInfo::Address * RouterInfo::GetNTCPAddress (bool v4only) { for (auto& address : m_Addresses) diff --git a/RouterInfo.h b/RouterInfo.h index 44dae3f1..76ebf7cf 100644 --- a/RouterInfo.h +++ b/RouterInfo.h @@ -17,6 +17,14 @@ namespace data { public: + enum SupportedTranports + { + eNTCPV4 = 0x01, + eNTCPV6 = 0x20, + eSSUV4 = 0x40, + eSSUV6 = 0x80 + }; + enum TransportStyle { eTransportUnknown = 0, @@ -53,6 +61,8 @@ namespace data const char * GetProperty (const char * key) const; bool IsFloodfill () const; bool IsNTCP (bool v4only = true) const; + bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; }; + void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; }; bool IsUnreachable () const { return m_IsUnreachable; }; @@ -91,6 +101,7 @@ namespace data std::vector
m_Addresses; std::map m_Properties; bool m_IsUpdated, m_IsUnreachable; + uint8_t m_SupportedTransports; }; } } diff --git a/Tunnel.cpp b/Tunnel.cpp index fe904369..1163f47e 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -397,11 +397,12 @@ namespace tunnel { LogPrint ("Creating two hops outbound tunnel..."); + auto firstHop = i2p::data::netdb.GetRandomNTCPRouter (); // first hop must be NTCP CreateTunnel ( new TunnelConfig (std::vector { - i2p::data::netdb.GetRandomNTCPRouter (), // first hop must be NTCP - i2p::data::netdb.GetRandomRouter () + firstHop, + i2p::data::netdb.GetRandomRouter (firstHop) }, inboundTunnel->GetTunnelConfig ())); } @@ -449,8 +450,8 @@ namespace tunnel CreateTunnel ( new TunnelConfig (std::vector { - i2p::data::netdb.GetRandomNTCPRouter (), - router != &i2p::context.GetRouterInfo () ? router : i2p::data::netdb.GetRandomNTCPRouter () + i2p::data::netdb.GetRandomRouter (outboundTunnel->GetEndpointRouter ()), + router != &i2p::context.GetRouterInfo () ? router : i2p::data::netdb.GetRandomNTCPRouter () // last hop must be NTCP }), outboundTunnel); } diff --git a/Tunnel.h b/Tunnel.h index a189da0d..3498eae3 100644 --- a/Tunnel.h +++ b/Tunnel.h @@ -67,7 +67,8 @@ namespace tunnel void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg); void SendTunnelDataMsg (std::vector msgs); // multiple messages - + const i2p::data::RouterInfo * GetEndpointRouter () const + { return GetTunnelConfig ()->GetLastHop ()->router; }; size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); }; // implements TunnelBase