mirror of
https://github.com/oxen-io/lokinet
synced 2023-12-14 06:53:00 +01:00
make lokinet client with strict-connect option provided explicitly connect out to snodes provided.
* create new component for selecting edge snodes as client (llarp::consensus::EdgeSelector) * require llarp::AbstractRouter own a llarp::consensus::EdgeSelector * make outbound_session_maker.cpp use llarp::consensus::EdgeSelector owned by llarp::AbstractRouter
This commit is contained in:
parent
a294c81f0d
commit
dea8ad2244
7 changed files with 144 additions and 26 deletions
|
@ -145,6 +145,7 @@ add_library(lokinet-config
|
|||
# lokinet-consensus is for deriving and tracking network consensus state for both service nodes and clients
|
||||
add_library(lokinet-consensus
|
||||
STATIC
|
||||
consensus/edge_selector.cpp
|
||||
consensus/reachability_testing.cpp
|
||||
)
|
||||
|
||||
|
|
71
llarp/consensus/edge_selector.cpp
Normal file
71
llarp/consensus/edge_selector.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
#include "edge_selector.hpp"
|
||||
|
||||
#include <llarp/router/abstractrouter.hpp>
|
||||
#include <llarp/crypto/crypto.hpp>
|
||||
#include <llarp/nodedb.hpp>
|
||||
#include <llarp/profiling.hpp>
|
||||
|
||||
namespace llarp::consensus
|
||||
{
|
||||
|
||||
EdgeSelector::EdgeSelector(AbstractRouter& r) : _router{r}
|
||||
{}
|
||||
|
||||
std::optional<RouterContact>
|
||||
EdgeSelector::select_path_edge(const std::unordered_set<RouterID>& connected_now) const
|
||||
{
|
||||
auto conf = _router.GetConfig();
|
||||
auto nodedb = _router.nodedb();
|
||||
|
||||
const auto& _keys = conf->network.m_strictConnect;
|
||||
// no strict hops. select a random good snode.
|
||||
if (_keys.empty())
|
||||
{
|
||||
return nodedb->GetRandom([&connected_now, this](const auto& rc) {
|
||||
return connected_now.count(rc.pubkey) == 0
|
||||
and not _router.routerProfiling().IsBadForConnect(rc.pubkey)
|
||||
and not _router.IsBootstrapNode(rc.pubkey);
|
||||
});
|
||||
}
|
||||
|
||||
// select random from strict connections.
|
||||
std::vector<RouterID> keys{_keys.begin(), _keys.end()};
|
||||
|
||||
std::shuffle(keys.begin(), keys.end(), llarp::CSRNG{});
|
||||
|
||||
for (const auto& pk : keys)
|
||||
{
|
||||
if (_router.routerProfiling().IsBadForConnect(pk))
|
||||
continue;
|
||||
if (connected_now.count(pk))
|
||||
continue;
|
||||
if (auto maybe = nodedb->Get(pk))
|
||||
return maybe;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<RouterContact>
|
||||
EdgeSelector::select_bootstrap(const std::unordered_set<RouterID>& connected_now) const
|
||||
{
|
||||
auto conf = _router.GetConfig();
|
||||
auto nodedb = _router.nodedb();
|
||||
if (const auto& _keys = conf->network.m_strictConnect; not _keys.empty())
|
||||
{
|
||||
// try bootstrapping off strict connections first if we have any.
|
||||
std::vector<RouterID> keys{_keys.begin(), _keys.end()};
|
||||
std::shuffle(keys.begin(), keys.end(), llarp::CSRNG{});
|
||||
for (const auto& pk : keys)
|
||||
{
|
||||
if (connected_now.count(pk))
|
||||
continue;
|
||||
if (auto maybe = nodedb->Get(pk))
|
||||
return maybe;
|
||||
}
|
||||
}
|
||||
// if we cant use a strict connection we'll just use one of our bootstrap nodes.
|
||||
return nodedb->GetRandom([&connected_now, this](const auto& rc) {
|
||||
return connected_now.count(rc.pubkey) == 0 and _router.IsBootstrapNode(rc.pubkey);
|
||||
});
|
||||
}
|
||||
} // namespace llarp::consensus
|
35
llarp/consensus/edge_selector.hpp
Normal file
35
llarp/consensus/edge_selector.hpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <unordered_set>
|
||||
#include <llarp/router_id.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct AbstractRouter;
|
||||
struct RouterContact;
|
||||
} // namespace llarp
|
||||
|
||||
namespace llarp::consensus
|
||||
{
|
||||
/// when we want to connect to and edge when we are a client, an instance of EdgeSelector acts as
|
||||
/// a stateless selection algorith for router contacts for each attempt at connecting out we make.
|
||||
class EdgeSelector
|
||||
{
|
||||
AbstractRouter& _router;
|
||||
|
||||
public:
|
||||
explicit EdgeSelector(AbstractRouter& router);
|
||||
|
||||
/// select a candidate for connecting out to the network when we need more connections to do a
|
||||
/// path build. pass in an unordered set of the snode pubkeys we are currently connected to.
|
||||
std::optional<RouterContact>
|
||||
select_path_edge(const std::unordered_set<RouterID>& connected_now = {}) const;
|
||||
|
||||
/// get a router contact of a bootstrap snode to bootstrap with if we are in need of
|
||||
/// bootstrapping more peers. pass in an unodereed set of bootstrap router pubkeys we are
|
||||
/// currently connected to.
|
||||
std::optional<RouterContact>
|
||||
select_bootstrap(const std::unordered_set<RouterID>& connected_now = {}) const;
|
||||
};
|
||||
} // namespace llarp::consensus
|
|
@ -45,6 +45,11 @@ namespace llarp
|
|||
struct I_RCLookupHandler;
|
||||
struct RoutePoker;
|
||||
|
||||
namespace consensus
|
||||
{
|
||||
class EdgeSelector;
|
||||
}
|
||||
|
||||
namespace dns
|
||||
{
|
||||
class I_SystemSettings;
|
||||
|
@ -130,6 +135,9 @@ namespace llarp
|
|||
virtual const RouterContact&
|
||||
rc() const = 0;
|
||||
|
||||
virtual const consensus::EdgeSelector&
|
||||
edge_selector() const = 0;
|
||||
|
||||
/// modify our rc
|
||||
/// modify returns nullopt if unmodified otherwise it returns the new rc to be sigend and
|
||||
/// published out
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <llarp/util/thread/threading.hpp>
|
||||
#include <llarp/util/status.hpp>
|
||||
#include <llarp/crypto/crypto.hpp>
|
||||
#include <llarp/consensus/edge_selector.hpp>
|
||||
#include <utility>
|
||||
|
||||
#include <llarp/rpc/lokid_rpc_client.hpp>
|
||||
|
@ -139,30 +140,23 @@ namespace llarp
|
|||
OutboundSessionMaker::ConnectToRandomRouters(int numDesired)
|
||||
{
|
||||
int remainingDesired = numDesired;
|
||||
std::set<RouterID> exclude;
|
||||
std::unordered_set<RouterID> exclude;
|
||||
for (const auto& item : pendingSessions)
|
||||
exclude.emplace(item.first);
|
||||
_linkManager->ForEachPeer([&exclude](auto* session) {
|
||||
if (session and session->IsEstablished())
|
||||
exclude.emplace(session->GetPubKey());
|
||||
});
|
||||
do
|
||||
{
|
||||
auto filter = [exclude](const auto& rc) -> bool { return exclude.count(rc.pubkey) == 0; };
|
||||
|
||||
RouterContact other;
|
||||
if (const auto maybe = _nodedb->GetRandom(filter))
|
||||
{
|
||||
other = *maybe;
|
||||
}
|
||||
else
|
||||
auto maybe_rc = _router->edge_selector().select_path_edge(exclude);
|
||||
if (not maybe_rc)
|
||||
break;
|
||||
|
||||
exclude.insert(other.pubkey);
|
||||
if (not _rcLookup->SessionIsAllowed(other.pubkey))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (not(_linkManager->HasSessionTo(other.pubkey) || HavePendingSessionTo(other.pubkey)))
|
||||
{
|
||||
CreateSessionTo(other, nullptr);
|
||||
--remainingDesired;
|
||||
}
|
||||
|
||||
const auto& rc = *maybe_rc;
|
||||
exclude.insert(rc.pubkey);
|
||||
CreateSessionTo(rc, nullptr);
|
||||
--remainingDesired;
|
||||
} while (remainingDesired > 0);
|
||||
LogDebug(
|
||||
"connecting to ", numDesired - remainingDesired, " out of ", numDesired, " random routers");
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace llarp
|
|||
Router::Router(EventLoop_ptr loop, std::shared_ptr<vpn::Platform> vpnPlatform)
|
||||
: ready{false}
|
||||
, m_lmq{std::make_shared<oxenmq::OxenMQ>()}
|
||||
, _edge_selector{*this}
|
||||
, _loop{std::move(loop)}
|
||||
, _vpnPlatform{std::move(vpnPlatform)}
|
||||
, paths{this}
|
||||
|
@ -869,6 +870,12 @@ namespace llarp
|
|||
m_LastStatsReport = now;
|
||||
}
|
||||
|
||||
const consensus::EdgeSelector&
|
||||
Router::edge_selector() const
|
||||
{
|
||||
return _edge_selector;
|
||||
}
|
||||
|
||||
std::string
|
||||
Router::status_line()
|
||||
{
|
||||
|
@ -1059,12 +1066,8 @@ namespace llarp
|
|||
_rcLookupHandler.ExploreNetwork();
|
||||
m_NextExploreAt = timepoint_now + std::chrono::seconds(interval);
|
||||
}
|
||||
size_t connectToNum = _outboundSessionMaker.minConnectedRouters;
|
||||
const auto strictConnect = _rcLookupHandler.NumberOfStrictConnectRouters();
|
||||
if (strictConnect > 0 && connectToNum > strictConnect)
|
||||
{
|
||||
connectToNum = strictConnect;
|
||||
}
|
||||
|
||||
size_t connectToNum = _outboundSessionMaker.maxConnectedRouters;
|
||||
|
||||
if (isSvcNode and now >= m_NextDecommissionWarn)
|
||||
{
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "abstractrouter.hpp"
|
||||
|
||||
#include <llarp/bootstrap.hpp>
|
||||
#include <llarp/consensus/edge_selector.hpp>
|
||||
#include <llarp/config/config.hpp>
|
||||
#include <llarp/config/key_manager.hpp>
|
||||
#include <llarp/constants/link_layer.hpp>
|
||||
|
@ -79,6 +80,8 @@ namespace llarp
|
|||
|
||||
std::shared_ptr<EventLoopWakeup> m_Pump;
|
||||
|
||||
consensus::EdgeSelector _edge_selector;
|
||||
|
||||
path::BuildLimiter&
|
||||
pathBuildLimiter() override
|
||||
{
|
||||
|
@ -148,6 +151,9 @@ namespace llarp
|
|||
const std::vector<RouterID>& greylist,
|
||||
const std::vector<RouterID>& unfunded) override;
|
||||
|
||||
const consensus::EdgeSelector&
|
||||
edge_selector() const override;
|
||||
|
||||
std::unordered_set<RouterID>
|
||||
GetRouterWhitelist() const override
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue