From 5aebefe73f55112d4dea2ee23bcd39662aed1054 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 1 May 2022 10:33:25 -0400 Subject: [PATCH] connect through introducer --- libi2pd/SSU2.cpp | 73 ++++++++++++++++++++++++++++++++++++++++++------ libi2pd/SSU2.h | 14 ++++++++-- 2 files changed, 77 insertions(+), 10 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 919faf16..9310a172 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -28,7 +28,7 @@ namespace transport } SSU2Session::SSU2Session (SSU2Server& server, std::shared_ptr in_RemoteRouter, - std::shared_ptr addr, bool peerTest): + std::shared_ptr addr): TransportSession (in_RemoteRouter, SSU2_CONNECT_TIMEOUT), m_Server (server), m_Address (addr), m_DestConnID (0), m_SourceConnID (0), m_State (eSSU2SessionStateUnknown), m_SendPacketNum (0), m_ReceivePacketNum (0), @@ -52,6 +52,7 @@ namespace transport SSU2Session::~SSU2Session () { + Terminate (); } void SSU2Session::Connect () @@ -135,6 +136,7 @@ namespace transport m_SessionConfirmedFragment1.reset (nullptr); SetTerminationTimeout (SSU2_TERMINATION_TIMEOUT); transports.PeerConnected (shared_from_this ()); + if (m_OnEstablished) m_OnEstablished (); } void SSU2Session::Done () @@ -1810,19 +1812,74 @@ namespace transport { if (router && address) { - if (address->UsesIntroducer ()) return false; // not implemented yet - GetService ().post ( - [this, router, address]() - { - auto session = std::make_shared (*this, router, address); - session->Connect (); - }); + if (address->UsesIntroducer ()) + GetService ().post (std::bind (&SSU2Server::ConnectThroughIntroducer, this, router, address)); + else + GetService ().post ( + [this, router, address]() + { + auto session = std::make_shared (*this, router, address); + session->Connect (); + }); } else return false; return true; } + void SSU2Server::ConnectThroughIntroducer (std::shared_ptr router, + std::shared_ptr address) + { + auto session = std::make_shared (*this, router, address); + session->SetState (eSSU2SessionStateIntroduced); + // try to find existing session first + for (auto& it: address->ssu->introducers) + { + auto it1 = m_SessionsByRouterHash.find (it.iKey); + if (it1 != m_SessionsByRouterHash.end ()) + { + it1->second->Introduce (session, it.iTag); + return; + } + } + // we have to start a new session to an introducer + std::shared_ptr r; + uint32_t relayTag = 0; + for (auto& it: address->ssu->introducers) + { + r = i2p::data::netdb.FindRouter (it.iKey); + if (r) + { + relayTag = it.iTag; + if (relayTag) break; + } + } + if (r) + { + if (relayTag) + { + // introducer and tag found connect to it through SSU2 + auto addr = address->IsV6 () ? r->GetSSU2V6Address () : r->GetSSU2V4Address (); + if (addr) + { + auto s = std::make_shared (*this, r, addr); + s->SetOnEstablished ( + [session, s, relayTag]() + { + s->Introduce (session, relayTag); + }); + s->Connect (); + } + } + } + else + { + // introducers not found, try to request them + for (auto& it: address->ssu->introducers) + i2p::data::netdb.RequestDestination (it.iKey); + } + } + void SSU2Server::ScheduleTermination () { m_TerminationTimer.expires_from_now (boost::posix_time::seconds(SSU2_TERMINATION_CHECK_TIMEOUT)); diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index ea83b608..a7988054 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -10,6 +10,7 @@ #define SSU2_H__ #include +#include #include #include #include @@ -130,15 +131,18 @@ namespace transport uint8_t payload[SSU2_MAX_PAYLOAD_SIZE]; size_t payloadSize; }; + + typedef std::function OnEstablished; public: SSU2Session (SSU2Server& server, std::shared_ptr in_RemoteRouter = nullptr, - std::shared_ptr addr = nullptr, bool peerTest = false); + std::shared_ptr addr = nullptr); ~SSU2Session (); void SetRemoteEndpoint (const boost::asio::ip::udp::endpoint& ep) { m_RemoteEndpoint = ep; }; const boost::asio::ip::udp::endpoint& GetRemoteEndpoint () const { return m_RemoteEndpoint; }; + void SetOnEstablished (OnEstablished e) { m_OnEstablished = e; }; void Connect (); bool Introduce (std::shared_ptr session, uint32_t relayTag); @@ -151,6 +155,8 @@ namespace transport void Resend (uint64_t ts); bool IsEstablished () const { return m_State == eSSU2SessionStateEstablished; }; uint64_t GetConnID () const { return m_SourceConnID; }; + SSU2SessionState GetState () const { return m_State; }; + void SetState (SSU2SessionState state) { m_State = state; }; void ProcessFirstIncomingMessage (uint64_t connID, uint8_t * buf, size_t len); bool ProcessSessionCreated (uint8_t * buf, size_t len); @@ -222,7 +228,8 @@ namespace transport i2p::I2NPMessagesHandler m_Handler; bool m_IsDataReceived; size_t m_WindowSize; - uint32_t m_RelayTag; + uint32_t m_RelayTag; // between Bob and Charlie + OnEstablished m_OnEstablished; // callback from Established }; class SSU2Server: private i2p::util::RunnableServiceWithWork @@ -290,6 +297,9 @@ namespace transport void ScheduleResend (); void HandleResendTimer (const boost::system::error_code& ecode); + + void ConnectThroughIntroducer (std::shared_ptr router, + std::shared_ptr address); private: