diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 4fa52690..4eed7ea8 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -386,7 +386,13 @@ namespace data } else if (address->transportStyle == eTransportSSU2) { - // TODO: + if (address->IsV4 ()) supportedTransports |= eSSU2V4; + if (address->IsV6 ()) supportedTransports |= eSSU2V6; + if (address->port) + { + if (address->host.is_v4 ()) m_ReachableTransports |= eSSU2V4; + if (address->host.is_v6 ()) m_ReachableTransports |= eSSU2V6; + } } if (supportedTransports) { @@ -693,11 +699,6 @@ namespace data return m_SupportedTransports & (eSSUV4 | eSSUV6); } - bool RouterInfo::IsSSUV6 () const - { - return m_SupportedTransports & eSSUV6; - } - bool RouterInfo::IsNTCP2 (bool v4only) const { if (v4only) @@ -706,25 +707,6 @@ namespace data return m_SupportedTransports & (eNTCP2V4 | eNTCP2V6); } - bool RouterInfo::IsNTCP2V6 () const - { - return m_SupportedTransports & eNTCP2V6; - } - - bool RouterInfo::IsV6 () const - { - return m_SupportedTransports & (eSSUV6 | eNTCP2V6); - } - - bool RouterInfo::IsV4 () const - { - return m_SupportedTransports & (eSSUV4 | eNTCP2V4); - } - - bool RouterInfo::IsMesh () const - { - return m_SupportedTransports & eNTCP2V6Mesh; - } void RouterInfo::EnableV6 () { @@ -841,6 +823,24 @@ namespace data }); } + std::shared_ptr RouterInfo::GetSSU2V4Address () const + { + return GetAddress ( + [](std::shared_ptr address)->bool + { + return (address->transportStyle == eTransportSSU2) && address->IsV4(); + }); + } + + std::shared_ptr RouterInfo::GetSSU2V6Address () const + { + return GetAddress ( + [](std::shared_ptr address)->bool + { + return (address->transportStyle == eTransportSSU2) && address->IsV6(); + }); + } + template std::shared_ptr RouterInfo::GetAddress (Filter filter) const { diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index cf2bc4c7..d099e806 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -67,6 +67,8 @@ namespace data eSSUV4 = 0x04, eSSUV6 = 0x08, eNTCP2V6Mesh = 0x10, + eSSU2V4 = 0x20, + eSSU2V6 = 0x40, eAllTransports = 0xFF }; typedef uint8_t CompatibleTransports; @@ -186,6 +188,8 @@ namespace data std::shared_ptr GetSSUAddress (bool v4only = true) const; std::shared_ptr GetSSUV6Address () const; std::shared_ptr GetYggdrasilAddress () const; + std::shared_ptr GetSSU2V4Address () const; + std::shared_ptr GetSSU2V6Address () const; void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0); void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, @@ -199,12 +203,14 @@ namespace data bool IsReachable () const { return m_Caps & Caps::eReachable; }; bool IsECIES () const { return m_RouterIdentity->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; }; bool IsSSU (bool v4only = true) const; - bool IsSSUV6 () const; + bool IsSSUV6 () const { return m_SupportedTransports & eSSUV6; }; bool IsNTCP2 (bool v4only = true) const; - bool IsNTCP2V6 () const; - bool IsV6 () const; - bool IsV4 () const; - bool IsMesh () const; + bool IsNTCP2V6 () const { return m_SupportedTransports & eNTCP2V6; }; + bool IsSSU2V4 () const { return m_SupportedTransports & eSSU2V4; }; + bool IsSSU2V6 () const { return m_SupportedTransports & eSSU2V6; }; + bool IsV6 () const { return m_SupportedTransports & (eSSUV6 | eNTCP2V6 | eSSU2V6); }; + bool IsV4 () const { return m_SupportedTransports & (eSSUV4 | eNTCP2V4 | eSSU2V4); }; + bool IsMesh () const { return m_SupportedTransports & eNTCP2V6Mesh; }; void EnableV6 (); void DisableV6 (); void EnableV4 (); diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 902f1371..011c44b9 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -48,6 +48,11 @@ namespace transport { } + void SSU2Session::Connect () + { + SendSessionRequest (); + } + void SSU2Session::SendSessionRequest () { // we are Alice @@ -488,6 +493,21 @@ namespace transport boost::system::error_code ec; m_Socket.send_to (bufs, to, 0, ec); } - + + bool SSU2Server::CreateSession (std::shared_ptr router, + std::shared_ptr address) + { + if (router && address) + GetService ().post ( + [this, router, address]() + { + auto session = std::make_shared (*this, router, address); + session->Connect (); + }); + else + return false; + return true; + } + } } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index d1e67590..76500367 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -81,7 +81,8 @@ namespace transport ~SSU2Session (); void SetRemoteEndpoint (const boost::asio::ip::udp::endpoint& ep) { m_RemoteEndpoint = ep; }; - + + void Connect (); void Done () override {}; void SendI2NPMessages (const std::vector >& msgs) override {}; @@ -130,6 +131,9 @@ namespace transport void Send (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen, const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to); + + bool CreateSession (std::shared_ptr router, + std::shared_ptr address); private: diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index e9d69adf..687ec0b0 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -536,6 +536,40 @@ namespace transport } } } + if (peer.numAttempts == 5 || peer.numAttempts == 6) // SSU2 + { + if (m_SSU2Server) + { + std::shared_ptr address; + if (peer.numAttempts == 5) // SSU2 ipv6 + { + if (context.GetRouterInfo ().IsSSU2V6 () && peer.router->IsReachableBy (RouterInfo::eSSU2V6)) + { + address = peer.router->GetSSU2V6Address (); + if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) + address = nullptr; + } + peer.numAttempts++; + } + if (!address && peer.numAttempts == 6) // SSU2 ipv4 + { + if (context.GetRouterInfo ().IsSSU2V4 () && peer.router->IsReachableBy (RouterInfo::eSSU2V4)) + { + address = peer.router->GetSSU2V4Address (); + if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) + address = nullptr; + } + peer.numAttempts++; + } + if (address && address->published) + { + if (m_SSU2Server->CreateSession (peer.router, address)) + return true; + } + } + else + peer.numAttempts += 2; + } LogPrint (eLogInfo, "Transports: No compatble NTCP2 or SSU addresses available"); i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed peer.Done ();