From aad2d68edbc9df8981b1d94ceb723d4e802a1a8b Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 31 Jan 2021 17:25:07 -0500 Subject: [PATCH] NTCP2 transports through the Yggdrasil --- libi2pd/Config.cpp | 6 ++++++ libi2pd/NTCP2.cpp | 2 +- libi2pd/RouterContext.cpp | 9 +++++++++ libi2pd/RouterContext.h | 2 ++ libi2pd/RouterInfo.cpp | 35 +++++++++++++++++++++++++++++++++++ libi2pd/RouterInfo.h | 4 ++++ libi2pd/Transports.cpp | 16 +++++++++++++++- 7 files changed, 72 insertions(+), 2 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 5de489d0..eb7a230e 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -276,6 +276,11 @@ namespace config { ("cpuext.force", bool_switch()->default_value(false), "Force usage of CPU extensions. Useful when cpuinfo is not available on virtual machines") ; + options_description meshnets("Meshnet transports options"); + meshnets.add_options() + ("meshnets.yggdrasil", bool_switch()->default_value(false), "Support transports through the Yggdrasil (deafult: false)") + ; + m_OptionsDesc .add(general) .add(limits) @@ -297,6 +302,7 @@ namespace config { .add(nettime) .add(persist) .add(cpuext) + .add(meshnets) ; } diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 1c2a71cf..130a6a20 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1181,7 +1181,7 @@ namespace transport auto conn = std::make_shared(*this); m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1)); } - else if (address->host.is_v6() && context.SupportsV6 ()) + else if (address->host.is_v6() && (context.SupportsV6 () || context.SupportsMesh ())) { m_NTCP2V6Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService ())); try diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index ce1eede0..33cfb943 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -521,6 +521,15 @@ namespace i2p UpdateRouterInfo (); } + void RouterContext::SetSupportsMesh (bool supportsmesh) + { + if (supportsmesh) + m_RouterInfo.EnableMesh (); + else + m_RouterInfo.DisableMesh (); + UpdateRouterInfo (); + } + void RouterContext::UpdateNTCP2V6Address (const boost::asio::ip::address& host) { bool updated = false; diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 8c13b842..81921d1c 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -107,8 +107,10 @@ namespace i2p void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; }; bool SupportsV6 () const { return m_RouterInfo.IsV6 (); }; bool SupportsV4 () const { return m_RouterInfo.IsV4 (); }; + bool SupportsMesh () const { return m_RouterInfo.IsMesh (); }; void SetSupportsV6 (bool supportsV6); void SetSupportsV4 (bool supportsV4); + void SetSupportsMesh (bool supportsmesh); bool IsECIES () const { return GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; }; std::unique_ptr& GetCurrentNoiseState () { return m_CurrentNoiseState; }; diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 34d377cb..3f710aec 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -847,6 +847,11 @@ namespace data return m_SupportedTransports & (eSSUV4 | eNTCP2V4); } + bool RouterInfo::IsMesh () const + { + return m_SupportedTransports & eNTCP2V6Mesh; + } + void RouterInfo::EnableV6 () { if (!IsV6 ()) @@ -892,6 +897,27 @@ namespace data } } + void RouterInfo::EnableMesh () + { + if (!IsMesh ()) + m_SupportedTransports |= eNTCP2V6Mesh; + } + + void RouterInfo::DisableMesh () + { + if (IsMesh ()) + { + m_SupportedTransports &= ~eNTCP2V6Mesh; + for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) + { + auto addr = *it; + if (i2p::util::net::IsYggdrasilAddress (addr->host)) + it = m_Addresses->erase (it); + else + ++it; + } + } + } bool RouterInfo::UsesIntroducer () const { @@ -957,6 +983,15 @@ namespace data return address->IsPublishedNTCP2 () && address->host.is_v6 (); }); } + + std::shared_ptr RouterInfo::GetYggdrasilAddress () const + { + return GetAddress ( + [](std::shared_ptr address)->bool + { + return i2p::util::net::IsYggdrasilAddress (address->host); + }); + } std::shared_ptr RouterInfo::GetProfile () const { diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 50ed3576..fc55a9e2 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -155,6 +155,7 @@ namespace data std::shared_ptr GetPublishedNTCP2V6Address () const; std::shared_ptr GetSSUAddress (bool v4only = true) const; std::shared_ptr GetSSUV6Address () const; + std::shared_ptr GetYggdrasilAddress () 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, const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0); @@ -171,10 +172,13 @@ namespace data bool IsNTCP2 (bool v4only = true) const; bool IsV6 () const; bool IsV4 () const; + bool IsMesh () const; void EnableV6 (); void DisableV6 (); void EnableV4 (); void DisableV4 (); + void EnableMesh (); + void DisableMesh (); bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; }; bool HasValidAddresses () const { return m_SupportedTransports; }; bool UsesIntroducer () const; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 18459264..5d6fc5f1 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -442,13 +442,27 @@ namespace transport if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ())) { auto address = peer.router->GetSSUAddress (!context.SupportsV6 ()); - if (!m_CheckReserved || !i2p::util::net::IsInReservedRange(address->host)) + if (address && (!m_CheckReserved || !i2p::util::net::IsInReservedRange(address->host))) { m_SSUServer->CreateSession (peer.router, address->host, address->port); return true; } } } + if (peer.numAttempts == 3) // Mesh + { + peer.numAttempts++; + if (context.SupportsMesh () && m_NTCP2Server) + { + auto address = peer.router->GetYggdrasilAddress (); + if (address) + { + auto s = std::make_shared (*m_NTCP2Server, peer.router, address); + m_NTCP2Server->Connect (address->host, address->port, s); + return true; + } + } + } LogPrint (eLogInfo, "Transports: No NTCP or SSU addresses available"); i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed peer.Done ();