diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 5896db314..10558892c 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -150,6 +150,7 @@ add_library(liblokinet iwp/message_buffer.cpp iwp/session.cpp link/link_manager.cpp + link/session.cpp link/server.cpp messages/dht_immediate.cpp messages/link_intro.cpp diff --git a/llarp/link/i_link_manager.hpp b/llarp/link/i_link_manager.hpp index 52b16c33a..c1614c870 100644 --- a/llarp/link/i_link_manager.hpp +++ b/llarp/link/i_link_manager.hpp @@ -7,6 +7,7 @@ #include #include +#include struct llarp_buffer_t; @@ -38,6 +39,12 @@ namespace llarp virtual bool HasSessionTo(const RouterID& remote) const = 0; + /// return true if the session with this pubkey is a client + /// return false if the session with this pubkey is a router + /// return std::nullopt we have no session with this pubkey + virtual std::optional + SessionIsClient(RouterID remote) const = 0; + virtual void PumpLinks() = 0; @@ -63,6 +70,11 @@ namespace llarp virtual void ForEachInboundLink(std::function visit) const = 0; + /// close all connections to this peer + /// remove all link layer commits + virtual void + DeregisterPeer(RouterID remote) = 0; + virtual size_t NumberOfConnectedRouters() const = 0; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 447b7d9d7..736d6fce1 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -60,6 +60,38 @@ namespace llarp return GetLinkWithSessionTo(remote) != nullptr; } + std::optional + LinkManager::SessionIsClient(RouterID remote) const + { + for (const auto& link : inboundLinks) + { + const auto session = link->FindSessionByPubkey(remote); + if (session) + return not session->IsRelay(); + } + for (const auto& link : outboundLinks) + { + if (link->HasSessionTo(remote)) + return false; + } + return std::nullopt; + } + + void + LinkManager::DeregisterPeer(RouterID remote) + { + m_PersistingSessions.erase(remote); + for (const auto& link : inboundLinks) + { + link->CloseSessionTo(remote); + } + for (const auto& link : outboundLinks) + { + link->CloseSessionTo(remote); + } + LogInfo(remote, " has been de-registered"); + } + void LinkManager::PumpLinks() { diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index ddd546854..89ff52e08 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -34,6 +34,12 @@ namespace llarp bool HasSessionTo(const RouterID& remote) const override; + std::optional + SessionIsClient(RouterID remote) const override; + + void + DeregisterPeer(RouterID remote) override; + void PumpLinks() override; diff --git a/llarp/link/server.cpp b/llarp/link/server.cpp index d41b42c2d..28e7be49e 100644 --- a/llarp/link/server.cpp +++ b/llarp/link/server.cpp @@ -48,6 +48,16 @@ namespace llarp return m_AuthedLinks.find(id) != m_AuthedLinks.end(); } + std::shared_ptr + ILinkLayer::FindSessionByPubkey(RouterID id) + { + Lock_t l(m_AuthedLinksMutex); + auto itr = m_AuthedLinks.find(id); + if (itr == m_AuthedLinks.end()) + return nullptr; + return itr->second; + } + void ILinkLayer::ForEachSession(std::function visit, bool randomize) const { diff --git a/llarp/link/server.hpp b/llarp/link/server.hpp index 3d30dc21b..19503df01 100644 --- a/llarp/link/server.hpp +++ b/llarp/link/server.hpp @@ -121,6 +121,10 @@ namespace llarp virtual std::shared_ptr NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) = 0; + /// fetch a session by the identity pubkey it claims + std::shared_ptr + FindSessionByPubkey(RouterID pk); + virtual void Pump(); diff --git a/llarp/link/session.cpp b/llarp/link/session.cpp new file mode 100644 index 000000000..b7014966c --- /dev/null +++ b/llarp/link/session.cpp @@ -0,0 +1,11 @@ +#include + +namespace llarp +{ + bool + ILinkSession::IsRelay() const + { + return GetRemoteRC().IsPublicRouter(); + } + +} // namespace llarp diff --git a/llarp/link/session.hpp b/llarp/link/session.hpp index efb6f1dd5..73cf6cff5 100644 --- a/llarp/link/session.hpp +++ b/llarp/link/session.hpp @@ -102,6 +102,10 @@ namespace llarp virtual RouterContact GetRemoteRC() const = 0; + /// is this session a session to a relay? + bool + IsRelay() const; + /// handle a valid LIM std::function GotLIM; diff --git a/llarp/router/outbound_message_handler.cpp b/llarp/router/outbound_message_handler.cpp index 431de0cb6..7b926ae88 100644 --- a/llarp/router/outbound_message_handler.cpp +++ b/llarp/router/outbound_message_handler.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -22,6 +23,12 @@ namespace llarp OutboundMessageHandler::QueueMessage( const RouterID& remote, const ILinkMessage* msg, SendStatusHandler callback) { + if (not _linkManager->SessionIsClient(remote) and not _lookupHandler->RemoteIsAllowed(remote)) + { + DoCallback(callback, SendStatus::InvalidRouter); + return true; + } + const uint16_t priority = msg->Priority(); std::array linkmsg_buffer; llarp_buffer_t buf(linkmsg_buffer); @@ -105,9 +112,11 @@ namespace llarp } void - OutboundMessageHandler::Init(ILinkManager* linkManager, std::shared_ptr logic) + OutboundMessageHandler::Init( + ILinkManager* linkManager, I_RCLookupHandler* lookupHandler, std::shared_ptr logic) { _linkManager = linkManager; + _lookupHandler = lookupHandler; _logic = logic; outboundMessageQueues.emplace(zeroID, MessageQueue()); diff --git a/llarp/router/outbound_message_handler.hpp b/llarp/router/outbound_message_handler.hpp index 44f53e69f..44f1a8c76 100644 --- a/llarp/router/outbound_message_handler.hpp +++ b/llarp/router/outbound_message_handler.hpp @@ -18,6 +18,7 @@ struct llarp_buffer_t; namespace llarp { struct ILinkManager; + struct I_RCLookupHandler; class Logic; enum class SessionResult; @@ -42,7 +43,7 @@ namespace llarp ExtractStatus() const override; void - Init(ILinkManager* linkManager, std::shared_ptr logic); + Init(ILinkManager* linkManager, I_RCLookupHandler* lookupHandler, std::shared_ptr logic); private: using Message = std::pair, SendStatusHandler>; @@ -137,6 +138,7 @@ namespace llarp std::queue roundRobinOrder; ILinkManager* _linkManager; + I_RCLookupHandler* _lookupHandler; std::shared_ptr _logic; util::ContentionKiller m_Killer; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index cbf256628..f0ee0999c 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -551,7 +551,7 @@ namespace llarp LogInfo("Loaded ", bootstrapRCList.size(), " bootstrap routers"); // Init components after relevant config settings loaded - _outboundMessageHandler.Init(&_linkManager, _logic); + _outboundMessageHandler.Init(&_linkManager, &_rcLookupHandler, _logic); _outboundSessionMaker.Init( this, &_linkManager, @@ -784,6 +784,25 @@ namespace llarp return not _rcLookupHandler.RemoteIsAllowed(rc.pubkey); }); + // find all deregistered relays + std::unordered_set closePeers; + + _linkManager.ForEachPeer([&](auto session) { + if (whitelistRouters and not gotWhitelist) + return; + if (not session) + return; + const auto pk = session->GetPubKey(); + if (session->IsRelay() and not _rcLookupHandler.RemoteIsAllowed(pk)) + { + closePeers.emplace(pk); + } + }); + + // mark peers as de-registered + for (auto& peer : closePeers) + _linkManager.DeregisterPeer(std::move(peer)); + _linkManager.CheckPersistingSessions(now); if (HasClientExit())