diff --git a/llarp/path/pathbuilder.hpp b/llarp/path/pathbuilder.hpp index 2114ae2c4..a01198974 100644 --- a/llarp/path/pathbuilder.hpp +++ b/llarp/path/pathbuilder.hpp @@ -110,7 +110,7 @@ namespace llarp llarp_time_t Now() const override; - void + virtual void Tick(llarp_time_t now) override; void diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 796d9e536..943dfe4e4 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -470,6 +470,7 @@ namespace llarp if (itr == Sessions().end()) return false; si = itr->second.remote; + si.UpdateAddr(); return true; } @@ -1100,13 +1101,14 @@ namespace llarp bool Endpoint::HandleDataMessage( - path::Path_ptr, const PathID_t from, std::shared_ptr msg) + path::Path_ptr p, const PathID_t from, std::shared_ptr msg) { PutSenderFor(msg->tag, msg->sender, true); Introduction intro = msg->introReply; if (HasInboundConvo(msg->sender.Addr())) { intro.pathID = from; + intro.router = p->Endpoint(); } PutReplyIntroFor(msg->tag, intro); ConvoTagRX(msg->tag); diff --git a/llarp/service/intro.hpp b/llarp/service/intro.hpp index 093c1035b..507d0ffc9 100644 --- a/llarp/service/intro.hpp +++ b/llarp/service/intro.hpp @@ -13,7 +13,7 @@ namespace llarp { struct Introduction { - PubKey router; + RouterID router; PathID_t pathID; llarp_time_t latency = 0s; llarp_time_t expiresAt = 0s; diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index 98f6cd28c..e2ac2cb6e 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -54,7 +54,7 @@ namespace llarp return true; } - constexpr auto OutboundContextNumPaths = 2; + constexpr auto OutboundContextNumPaths = 4; OutboundContext::OutboundContext(const IntroSet& introset, Endpoint* parent) : path::Builder{parent->Router(), OutboundContextNumPaths, parent->numHops} @@ -64,12 +64,17 @@ namespace llarp , currentIntroSet{introset} { + assert(not introset.intros.empty()); updatingIntroSet = false; - for (const auto& intro : introset.intros) + + // pick random first intro + auto it = introset.intros.begin(); + if (introset.intros.size() > 1) { - if (m_NextIntro.latency == 0s or m_NextIntro.latency > intro.latency) - m_NextIntro = intro; + CSRNG rng{}; + it += std::uniform_int_distribution{0, introset.intros.size() - 1}(rng); } + m_NextIntro = *it; currentConvoTag.Randomize(); lastShift = Now(); // add send and connect timeouts to the parent endpoints path alignment timeout @@ -333,6 +338,7 @@ namespace llarp Encrypted<64> tmp; tmp.Randomize(); SendPacketToRemote(tmp, ProtocolType::Control); + m_LastKeepAliveAt = Now(); } bool @@ -348,7 +354,10 @@ namespace llarp // expunge SharedSecret discardme; if (not m_DataHandler->GetCachedSessionKeyFor(currentConvoTag, discardme)) + { + LogError(Name(), " no cached key after sending intro, we are in a fugged state, oh no"); return true; + } } if (m_GotInboundTraffic and m_LastInboundTraffic + sendTimeout <= now) @@ -404,21 +413,33 @@ namespace llarp m_ReadyHooks.clear(); } - if (m_LastInboundTraffic > 0s and lastGoodSend > 0s - and now >= sendTimeout + m_LastInboundTraffic) - return true; - const auto timeout = std::max(lastGoodSend, m_LastInboundTraffic); if (lastGoodSend > 0s and now >= timeout + (sendTimeout / 2)) { // send a keep alive to keep this session alive KeepAlive(); if (markedBad) + { + LogWarn(Name(), " keepalive timeout hit"); return true; + } + } + + // check for half open state where we can send but we get nothing back + if (m_LastInboundTraffic == 0s and now - createdAt > connectTimeout) + { + LogWarn(Name(), " half open state, we can send but we got nothing back"); + return true; } // if we are dead return true so we are removed - return timeout > 0s ? (now >= timeout && now - timeout > sendTimeout) - : (now >= createdAt && now - createdAt > connectTimeout); + const bool removeIt = timeout > 0s ? (now >= timeout && now - timeout > sendTimeout) + : (now >= createdAt && now - createdAt > connectTimeout); + if (removeIt) + { + LogInfo(Name(), " session is stale"); + return true; + } + return false; } void @@ -584,6 +605,25 @@ namespace llarp } } + bool + OutboundContext::ShouldKeepAlive(llarp_time_t now) const + { + const auto SendKeepAliveInterval = sendTimeout / 2; + if (not m_GotInboundTraffic) + return false; + if (m_LastInboundTraffic == 0s) + return false; + return (now - m_LastKeepAliveAt) >= SendKeepAliveInterval; + } + + void + OutboundContext::Tick(llarp_time_t now) + { + path::Builder::Tick(now); + if (ShouldKeepAlive(now)) + KeepAlive(); + } + bool OutboundContext::HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrame& frame) { diff --git a/llarp/service/outbound_context.hpp b/llarp/service/outbound_context.hpp index 8e27500e6..b005bcd19 100644 --- a/llarp/service/outbound_context.hpp +++ b/llarp/service/outbound_context.hpp @@ -23,6 +23,9 @@ namespace llarp ~OutboundContext() override; + void + Tick(llarp_time_t now) override; + util::StatusObject ExtractStatus() const; @@ -129,6 +132,9 @@ namespace llarp void KeepAlive(); + bool + ShouldKeepAlive(llarp_time_t now) const; + const IntroSet& GetCurrentIntroSet() const { @@ -170,6 +176,7 @@ namespace llarp bool sentIntro = false; std::vector> m_ReadyHooks; llarp_time_t m_LastIntrosetUpdateAt = 0s; + llarp_time_t m_LastKeepAliveAt = 0s; }; } // namespace service diff --git a/llarp/service/sendcontext.hpp b/llarp/service/sendcontext.hpp index dee9cb4eb..cc0ab4a69 100644 --- a/llarp/service/sendcontext.hpp +++ b/llarp/service/sendcontext.hpp @@ -45,7 +45,7 @@ namespace llarp llarp_time_t lastGoodSend = 0s; const llarp_time_t createdAt; llarp_time_t sendTimeout = path::build_timeout; - llarp_time_t connectTimeout = path::build_timeout; + llarp_time_t connectTimeout = path::build_timeout * 2; llarp_time_t shiftTimeout = (path::build_timeout * 5) / 2; llarp_time_t estimatedRTT = 0s; bool markedBad = false;