From ea0ed9e844c99b980f64224fbc037a2f33ee70ec Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 20 Jul 2022 21:55:48 -0400 Subject: [PATCH] update SSU2 introducers if Firewalled --- libi2pd/RouterInfo.cpp | 2 +- libi2pd/SSU2.cpp | 91 ++++++++++++++++++++++++++++++++++++++++- libi2pd/SSU2.h | 14 +++++-- libi2pd/SSU2Session.cpp | 6 +++ 4 files changed, 108 insertions(+), 5 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 4bb0fb05..4dae397e 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1321,7 +1321,7 @@ namespace data size_t len = address.IsSSU2 () ? 32 : 16; WriteString (address.i.ToBase64 (len), properties); properties << ';'; } - if (address.transportStyle == eTransportSSU || (address.IsSSU2 () && isPublished)) + if (address.transportStyle == eTransportSSU || address.IsSSU2 ()) { // write introducers if any if (address.ssu && !address.ssu->introducers.empty()) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index e667b337..52a38244 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -21,7 +21,9 @@ namespace transport RunnableServiceWithWork ("SSU2"), m_ReceiveService ("SSU2r"), m_SocketV4 (m_ReceiveService.GetService ()), m_SocketV6 (m_ReceiveService.GetService ()), m_AddressV4 (boost::asio::ip::address_v4()), m_AddressV6 (boost::asio::ip::address_v6()), - m_TerminationTimer (GetService ()), m_ResendTimer (GetService ()) + m_TerminationTimer (GetService ()), m_ResendTimer (GetService ()), + m_IntroducersUpdateTimer (GetService ()), m_IntroducersUpdateTimerV6 (GetService ()), + m_IsPublished (true) { } @@ -30,6 +32,7 @@ namespace transport if (!IsRunning ()) { StartIOService (); + i2p::config::GetOption ("ssu2.published", m_IsPublished); bool found = false; auto& addresses = i2p::context.GetRouterInfo ().GetAddresses (); for (const auto& address: addresses) @@ -59,6 +62,7 @@ namespace transport { Receive (m_SocketV4); }); + ScheduleIntroducersUpdateTimer (); // wait for 30 seconds and decide if we need introducers } if (address->IsV6 ()) { @@ -69,6 +73,7 @@ namespace transport { Receive (m_SocketV6); }); + ScheduleIntroducersUpdateTimerV6 (); // wait for 30 seconds and decide if we need introducers } } else @@ -827,6 +832,90 @@ namespace transport } } } + } + + void SSU2Server::ScheduleIntroducersUpdateTimer () + { + if (m_IsPublished) + { + m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL)); + m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, + this, std::placeholders::_1, true)); + } + } + + void SSU2Server::RescheduleIntroducersUpdateTimer () + { + if (m_IsPublished) + { + m_IntroducersUpdateTimer.cancel (); + m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2)); + m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, + this, std::placeholders::_1, true)); + } + } + + void SSU2Server::ScheduleIntroducersUpdateTimerV6 () + { + if (m_IsPublished) + { + m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL)); + m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, + this, std::placeholders::_1, false)); + } + } + + void SSU2Server::RescheduleIntroducersUpdateTimerV6 () + { + if (m_IsPublished) + { + m_IntroducersUpdateTimerV6.cancel (); + m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2)); + m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, + this, std::placeholders::_1, false)); + } + } + + void SSU2Server::HandleIntroducersUpdateTimer (const boost::system::error_code& ecode, bool v4) + { + if (ecode != boost::asio::error::operation_aborted) + { + // timeout expired + if (v4) + { + if (i2p::context.GetStatus () == eRouterStatusTesting) + { + // we still don't know if we need introducers + ScheduleIntroducersUpdateTimer (); + return; + } + if (i2p::context.GetStatus () != eRouterStatusFirewalled) + { + // we don't need introducers + m_Introducers.clear (); + return; + } + UpdateIntroducers (true); + ScheduleIntroducersUpdateTimer (); + } + else + { + if (i2p::context.GetStatusV6 () == eRouterStatusTesting) + { + // we still don't know if we need introducers + ScheduleIntroducersUpdateTimerV6 (); + return; + } + if (i2p::context.GetStatusV6 () != eRouterStatusFirewalled) + { + // we don't need introducers + m_IntroducersV6.clear (); + return; + } + UpdateIntroducers (false); + ScheduleIntroducersUpdateTimerV6 (); + } + } } } } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index b9d59d68..5e0bba6b 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -23,6 +23,7 @@ namespace transport const size_t SSU2_MAX_NUM_INTRODUCERS = 3; const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes + const int SSU2_KEEP_ALIVE_INTERVAL = 30; // 30 seconds class SSU2Server: private i2p::util::RunnableServiceWithWork { @@ -82,7 +83,9 @@ namespace transport uint64_t GetIncomingToken (const boost::asio::ip::udp::endpoint& ep); std::pair NewIncomingToken (const boost::asio::ip::udp::endpoint& ep); - + void RescheduleIntroducersUpdateTimer (); + void RescheduleIntroducersUpdateTimerV6 (); + private: boost::asio::ip::udp::socket& OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint); @@ -103,7 +106,10 @@ namespace transport std::list > FindIntroducers (int maxNumIntroducers, bool v4, const std::set& excluded) const; void UpdateIntroducers (bool v4); - + void ScheduleIntroducersUpdateTimer (); + void HandleIntroducersUpdateTimer (const boost::system::error_code& ecode, bool v4); + void ScheduleIntroducersUpdateTimerV6 (); + private: ReceiveService m_ReceiveService; @@ -116,8 +122,10 @@ namespace transport std::map > m_Relays; // we are introducer, relay tag -> session std::list > m_Introducers, m_IntroducersV6; // introducers we are connected to i2p::util::MemoryPoolMt m_PacketsPool; - boost::asio::deadline_timer m_TerminationTimer, m_ResendTimer; + boost::asio::deadline_timer m_TerminationTimer, m_ResendTimer, + m_IntroducersUpdateTimer, m_IntroducersUpdateTimerV6; std::shared_ptr m_LastSession; + bool m_IsPublished; // if we maintain introducers public: diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index fb5dd1e6..4890a61d 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1831,7 +1831,13 @@ namespace transport else { if (GetRouterStatus () == eRouterStatusTesting) + { SetRouterStatus (eRouterStatusFirewalled); + if (m_Address->IsV4 ()) + m_Server.RescheduleIntroducersUpdateTimer (); + else + m_Server.RescheduleIntroducersUpdateTimerV6 (); + } } } else