diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0222ccdf..66d15cae 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1150,7 +1150,7 @@ namespace data return GetRandomRouter ( [v4only](std::shared_ptr router)->bool { - return !router->IsHidden () && router->IsPeerTesting () && router->IsSSU (v4only); + return !router->IsHidden () && router->IsPeerTesting (v4only); }); } diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 424f23c5..de641602 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -215,6 +215,7 @@ namespace data } else address->transportStyle = eTransportUnknown; + address->caps = 0; address->port = 0; uint16_t size, r = 0; s.read ((char *)&size, sizeof (size)); if (!s) return; @@ -250,7 +251,7 @@ namespace data LogPrint (eLogWarning, "RouterInfo: Unexpected field 'key' for NTCP"); } else if (!strcmp (key, "caps")) - ExtractCaps (value); + address->caps = ExtractCaps (value); else if (!strcmp (key, "s")) // ntcp2 static key { Base64ToByteStream (value, strlen (value), address->ntcp2->staticKey, 32); @@ -353,7 +354,7 @@ namespace data // extract caps if (!strcmp (key, "caps")) - ExtractCaps (value); + m_Caps = ExtractCaps (value); // extract version else if (!strcmp (key, ROUTER_INFO_PROPERTY_VERSION)) { @@ -402,44 +403,46 @@ namespace data return m_Family == fam; } - void RouterInfo::ExtractCaps (const char * value) + uint8_t RouterInfo::ExtractCaps (const char * value) { + uint8_t caps = 0; const char * cap = value; while (*cap) { switch (*cap) { case CAPS_FLAG_FLOODFILL: - m_Caps |= Caps::eFloodfill; + caps |= Caps::eFloodfill; break; case CAPS_FLAG_HIGH_BANDWIDTH1: case CAPS_FLAG_HIGH_BANDWIDTH2: case CAPS_FLAG_HIGH_BANDWIDTH3: - m_Caps |= Caps::eHighBandwidth; + caps |= Caps::eHighBandwidth; break; case CAPS_FLAG_EXTRA_BANDWIDTH1: case CAPS_FLAG_EXTRA_BANDWIDTH2: - m_Caps |= Caps::eExtraBandwidth | Caps::eHighBandwidth; + caps |= Caps::eExtraBandwidth | Caps::eHighBandwidth; break; case CAPS_FLAG_HIDDEN: - m_Caps |= Caps::eHidden; + caps |= Caps::eHidden; break; case CAPS_FLAG_REACHABLE: - m_Caps |= Caps::eReachable; + caps |= Caps::eReachable; break; case CAPS_FLAG_UNREACHABLE: - m_Caps |= Caps::eUnreachable; + caps |= Caps::eUnreachable; break; case CAPS_FLAG_SSU_TESTING: - m_Caps |= Caps::eSSUTesting; + caps |= Caps::eSSUTesting; break; case CAPS_FLAG_SSU_INTRODUCER: - m_Caps |= Caps::eSSUIntroducer; + caps |= Caps::eSSUIntroducer; break; default: ; } cap++; } + return caps; } void RouterInfo::UpdateCapsProperty () @@ -496,8 +499,8 @@ namespace data WriteString ("caps", properties); properties << '='; std::string caps; - if (IsPeerTesting ()) caps += CAPS_FLAG_SSU_TESTING; - if (IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER; + if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU_TESTING; + if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER; WriteString (caps, properties); properties << ';'; } @@ -721,7 +724,8 @@ namespace data addr->host = boost::asio::ip::address::from_string (host); addr->port = port; addr->transportStyle = eTransportSSU; - addr->cost = 10; // NTCP should have priority over SSU + addr->cost = 10; // NTCP2 should have priority over SSU + addr->caps = i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer; // BC; addr->date = 0; addr->ssu.reset (new SSUExt ()); addr->ssu->mtu = mtu; @@ -745,6 +749,7 @@ namespace data addr->port = port; addr->transportStyle = eTransportNTCP; addr->cost = port ? 3 : 14; // override from RouterContext::PublishNTCP2Address + addr->caps = 0; addr->date = 0; addr->ntcp2.reset (new NTCP2Ext ()); if (port) addr->ntcp2->isPublished = true; @@ -794,8 +799,7 @@ namespace data void RouterInfo::SetCaps (const char * caps) { SetProperty ("caps", caps); - m_Caps = 0; - ExtractCaps (caps); + m_Caps = ExtractCaps (caps); } void RouterInfo::SetProperty (const std::string& key, const std::string& value) @@ -1020,5 +1024,28 @@ namespace data return IsReachable () && m_Version >= NETDB_MIN_FLOODFILL_VERSION && GetIdentity ()->GetSigningKeyType () != SIGNING_KEY_TYPE_DSA_SHA1; } + + bool RouterInfo::IsPeerTesting (bool v4only) const + { + auto supportedTransports = m_SupportedTransports & (eSSUV4 | eSSUV6); + if (!supportedTransports) return false; // no SSU + if (v4only && !(supportedTransports & eSSUV4)) return false; // no SSU v4 + return GetAddress ( + [](std::shared_ptr address)->bool + { + return (address->transportStyle == eTransportSSU) && address->IsPeerTesting (); + }) != nullptr; + } + + bool RouterInfo::IsIntroducer () const + { + // TODO: support ipv6 + if (!(m_SupportedTransports & eSSUV4)) return false; + return GetAddress ( + [](std::shared_ptr address)->bool + { + return (address->transportStyle == eTransportSSU) && address->IsIntroducer (); + }) != nullptr; + } } } diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index c712545e..af8dd8bd 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -111,7 +111,7 @@ namespace data boost::asio::ip::address host; int port; uint64_t date; - uint8_t cost; + uint8_t cost, caps; std::unique_ptr ssu; // not null for SSU std::unique_ptr ntcp2; // not null for NTCP2 @@ -134,6 +134,9 @@ namespace data bool IsNTCP2 () const { return (bool)ntcp2; }; bool IsPublishedNTCP2 () const { return IsNTCP2 () && ntcp2->isPublished; }; + + bool IsIntroducer () const { return caps & eSSUIntroducer; }; + bool IsPeerTesting () const { return caps & eSSUTesting; }; }; typedef std::list > Addresses; @@ -183,12 +186,12 @@ namespace data bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; }; bool HasValidAddresses () const { return m_SupportedTransports; }; bool UsesIntroducer () const; - bool IsIntroducer () const { return m_Caps & eSSUIntroducer; }; - bool IsPeerTesting () const { return m_Caps & eSSUTesting; }; bool IsHidden () const { return m_Caps & eHidden; }; bool IsHighBandwidth () const { return m_Caps & RouterInfo::eHighBandwidth; }; bool IsExtraBandwidth () const { return m_Caps & RouterInfo::eExtraBandwidth; }; bool IsEligibleFloodfill () const; + bool IsPeerTesting (bool v4only) const; + bool IsIntroducer () const; uint8_t GetCaps () const { return m_Caps; }; void SetCaps (uint8_t caps); @@ -231,7 +234,7 @@ namespace data void WriteToStream (std::ostream& s) const; size_t ReadString (char* str, size_t len, std::istream& s) const; void WriteString (const std::string& str, std::ostream& s) const; - void ExtractCaps (const char * value); + uint8_t ExtractCaps (const char * value); template std::shared_ptr GetAddress (Filter filter) const; void UpdateCapsProperty (); diff --git a/libi2pd/SSU.cpp b/libi2pd/SSU.cpp index 79b4f35f..b1d5b77c 100644 --- a/libi2pd/SSU.cpp +++ b/libi2pd/SSU.cpp @@ -442,21 +442,21 @@ namespace transport { auto address = router->GetSSUAddress (v4only || !context.SupportsV6 ()); if (address) - CreateSession (router, address->host, address->port, peerTest); + CreateSession (router, address, peerTest); else LogPrint (eLogWarning, "SSU: Router ", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), " doesn't have SSU address"); } void SSUServer::CreateSession (std::shared_ptr router, - const boost::asio::ip::address& addr, int port, bool peerTest) + std::shared_ptr address, bool peerTest) { - if (router) + if (router && address) { if (router->UsesIntroducer ()) m_Service.post (std::bind (&SSUServer::CreateSessionThroughIntroducer, this, router, peerTest)); // always V4 thread else { - boost::asio::ip::udp::endpoint remoteEndpoint (addr, port); + boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port); m_Service.post (std::bind (&SSUServer::CreateDirectSession, this, router, remoteEndpoint, peerTest)); } } diff --git a/libi2pd/SSU.h b/libi2pd/SSU.h index d20f1c9d..bce50a22 100644 --- a/libi2pd/SSU.h +++ b/libi2pd/SSU.h @@ -54,7 +54,7 @@ namespace transport void Stop (); void CreateSession (std::shared_ptr router, bool peerTest = false, bool v4only = false); void CreateSession (std::shared_ptr router, - const boost::asio::ip::address& addr, int port, bool peerTest = false); + std::shared_ptr address, bool peerTest = false); void CreateDirectSession (std::shared_ptr router, boost::asio::ip::udp::endpoint remoteEndpoint, bool peerTest); std::shared_ptr FindSession (std::shared_ptr router) const; std::shared_ptr FindSession (const boost::asio::ip::udp::endpoint& e) const; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 6bed627f..bb79dfdc 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -455,7 +455,7 @@ namespace transport } if (address) { - m_SSUServer->CreateSession (peer.router, address->host, address->port); + m_SSUServer->CreateSession (peer.router, address); return true; } }