From 68d015763e894c800eb4725a351d131e80d5e3b6 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 11 Mar 2022 16:17:44 -0500 Subject: [PATCH] recognize SSU2 addresses --- libi2pd/RouterInfo.cpp | 29 +++++++++++++++++++++++------ libi2pd/RouterInfo.h | 4 +++- libi2pd/SSU2.cpp | 37 ++++++++++++++++++++++++++++++------- libi2pd/SSU2.h | 12 +++++++----- libi2pd/Transports.cpp | 11 +++++++++-- libi2pd/Transports.h | 4 +++- 6 files changed, 75 insertions(+), 22 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 8d6c7120..fbdb04b9 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -221,9 +221,9 @@ namespace data ReadString (transportStyle, 6, s); if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2 address->transportStyle = eTransportNTCP; - else if (!strcmp (transportStyle, "SSU")) + else if (!strncmp (transportStyle, "SSU", 3)) // SSU or SSU2 { - address->transportStyle = eTransportSSU; + address->transportStyle = (transportStyle[3] == '2') ? eTransportSSU2 : eTransportSSU; address->ssu.reset (new SSUExt ()); address->ssu->mtu = 0; } @@ -266,12 +266,12 @@ namespace data } else if (!strcmp (key, "caps")) address->caps = ExtractAddressCaps (value); - else if (!strcmp (key, "s")) // ntcp2 static key + else if (!strcmp (key, "s")) // ntcp2 or ssu2 static key { Base64ToByteStream (value, strlen (value), address->s, 32); isStaticKey = true; } - else if (!strcmp (key, "i")) // ntcp2 iv + else if (!strcmp (key, "i")) // ntcp2 iv or ssu2 intro { Base64ToByteStream (value, strlen (value), address->i, 16); address->published = true; // presence if "i" means "published" @@ -378,6 +378,10 @@ namespace data } } } + else if (address->transportStyle == eTransportSSU2) + { + // TODO: + } if (supportedTransports) { if (!(m_SupportedTransports & supportedTransports)) // avoid duplicates @@ -1104,6 +1108,19 @@ namespace data WriteString (caps, properties); properties << ';'; } + else if (address.transportStyle == eTransportSSU2) + { + WriteString ("SSU2", s); + // caps + WriteString ("caps", properties); + properties << '='; + std::string caps; + if (address.IsV4 ()) caps += CAPS_FLAG_V4; + if (address.IsV6 ()) caps += CAPS_FLAG_V6; + if (caps.empty ()) caps += CAPS_FLAG_V4; + WriteString (caps, properties); + properties << ';'; + } else WriteString ("", s); @@ -1203,9 +1220,9 @@ namespace data WriteString (boost::lexical_cast(address.port), properties); properties << ';'; } - if (address.IsNTCP2 ()) + if (address.IsNTCP2 () || address.IsSSU2 ()) { - // publish s and v for NTCP2 + // publish s and v for NTCP2 or SSU2 WriteString ("s", properties); properties << '='; WriteString (address.s.ToBase64 (), properties); properties << ';'; WriteString ("v", properties); properties << '='; diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index e7f2fd3d..c1e2f307 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -92,7 +92,8 @@ namespace data { eTransportUnknown = 0, eTransportNTCP, - eTransportSSU + eTransportSSU, + eTransportSSU2 }; typedef Tag<32> IntroKey; // should be castable to MacKey and AESKey @@ -141,6 +142,7 @@ namespace data } bool IsNTCP2 () const { return transportStyle == eTransportNTCP; }; + bool IsSSU2 () const { return transportStyle == eTransportSSU2; }; bool IsPublishedNTCP2 () const { return IsNTCP2 () && published; }; bool IsReachableSSU () const { return (bool)ssu && (published || !ssu->introducers.empty ()); }; bool UsesIntroducer () const { return (bool)ssu && !ssu->introducers.empty (); }; diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 802f398c..b1c918b2 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -196,25 +196,48 @@ namespace transport return true; } - SSU2Server::SSU2Server (int port): - m_Socket (m_Service), m_Endpoint (boost::asio::ip::udp::v6 (), port) + SSU2Server::SSU2Server (): + RunnableServiceWithWork ("SSU2"), m_Socket (GetService ()) { } - void SSU2Server::OpenSocket () + void SSU2Server::Start () + { + if (!IsRunning ()) + { + StartIOService (); + auto& addresses = i2p::context.GetRouterInfo ().GetAddresses (); + for (const auto& address: addresses) + { + if (!address) continue; + if (address->transportStyle == i2p::data::RouterInfo::eTransportSSU2 && address->port) + { + OpenSocket (address->port); + break; + } + } + } + } + + void SSU2Server::Stop () + { + StopIOService (); + } + + void SSU2Server::OpenSocket (int port) { try { m_Socket.open (boost::asio::ip::udp::v6()); m_Socket.set_option (boost::asio::socket_base::receive_buffer_size (SSU2_SOCKET_RECEIVE_BUFFER_SIZE)); m_Socket.set_option (boost::asio::socket_base::send_buffer_size (SSU2_SOCKET_SEND_BUFFER_SIZE)); - m_Socket.bind (m_Endpoint); - LogPrint (eLogInfo, "SSU2: Start listening port ", m_Endpoint.port()); + m_Socket.bind (boost::asio::ip::udp::endpoint (boost::asio::ip::udp::v6(), port)); + LogPrint (eLogInfo, "SSU2: Start listening port ", port); } catch (std::exception& ex ) { - LogPrint (eLogError, "SSU2: Failed to bind to port ", m_Endpoint.port(), ": ", ex.what()); - ThrowFatal ("Unable to start SSU2 transport at port ", m_Endpoint.port(), ": ", ex.what ()); + LogPrint (eLogError, "SSU2: Failed to bind to port ", port, ": ", ex.what()); + ThrowFatal ("Unable to start SSU2 transport at port ", port, ": ", ex.what ()); } } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 99abb06b..528fd9c0 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -76,13 +76,17 @@ namespace transport uint64_t m_DestConnID, m_SourceConnID; }; - class SSU2Server + class SSU2Server: private i2p::util::RunnableServiceWithWork { public: - SSU2Server (int port); + SSU2Server (); ~SSU2Server () {}; + void Start (); + void Stop (); + boost::asio::io_service& GetService () { return GetIOService (); }; + void AddSession (uint64_t connID, std::shared_ptr session); void AddPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep, std::shared_ptr session); @@ -91,14 +95,12 @@ namespace transport private: - void OpenSocket (); + void OpenSocket (int port); void ProcessNextPacket (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); private: - boost::asio::io_service m_Service; boost::asio::ip::udp::socket m_Socket; - boost::asio::ip::udp::endpoint m_Endpoint; std::unordered_map > m_Sessions; std::map > m_PendingOutgoingSessions; }; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 85543407..097c3984 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -136,7 +136,7 @@ namespace transport Transports::Transports (): m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_CheckReserved(true), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr), - m_SSUServer (nullptr), m_NTCP2Server (nullptr), + m_SSUServer (nullptr), m_SSU2Server (nullptr), m_NTCP2Server (nullptr), m_X25519KeysPairSupplier (15), // 15 pre-generated keys m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0), m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth(0), @@ -304,7 +304,14 @@ namespace transport delete m_SSUServer; m_SSUServer = nullptr; } - + + if (m_SSU2Server) + { + m_SSU2Server->Stop (); + delete m_SSU2Server; + m_SSU2Server = nullptr; + } + if (m_NTCP2Server) { m_NTCP2Server->Stop (); diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 44790e6a..2a8dce15 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -22,6 +22,7 @@ #include #include "TransportSession.h" #include "SSU.h" +#include "SSU2.h" #include "NTCP2.h" #include "RouterInfo.h" #include "I2NPProtocol.h" @@ -159,6 +160,7 @@ namespace transport boost::asio::deadline_timer * m_PeerCleanupTimer, * m_PeerTestTimer; SSUServer * m_SSUServer; + SSU2Server * m_SSU2Server; NTCP2Server * m_NTCP2Server; mutable std::mutex m_PeersMutex; std::unordered_map m_Peers;