Skip to content

Commit dea8ad2

Browse files
author
jeff
committed
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
1 parent a294c81 commit dea8ad2

File tree

7 files changed

+144
-26
lines changed

7 files changed

+144
-26
lines changed

llarp/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ add_library(lokinet-config
145145
# lokinet-consensus is for deriving and tracking network consensus state for both service nodes and clients
146146
add_library(lokinet-consensus
147147
STATIC
148+
consensus/edge_selector.cpp
148149
consensus/reachability_testing.cpp
149150
)
150151

llarp/consensus/edge_selector.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#include "edge_selector.hpp"
2+
3+
#include <llarp/router/abstractrouter.hpp>
4+
#include <llarp/crypto/crypto.hpp>
5+
#include <llarp/nodedb.hpp>
6+
#include <llarp/profiling.hpp>
7+
8+
namespace llarp::consensus
9+
{
10+
11+
EdgeSelector::EdgeSelector(AbstractRouter& r) : _router{r}
12+
{}
13+
14+
std::optional<RouterContact>
15+
EdgeSelector::select_path_edge(const std::unordered_set<RouterID>& connected_now) const
16+
{
17+
auto conf = _router.GetConfig();
18+
auto nodedb = _router.nodedb();
19+
20+
const auto& _keys = conf->network.m_strictConnect;
21+
// no strict hops. select a random good snode.
22+
if (_keys.empty())
23+
{
24+
return nodedb->GetRandom([&connected_now, this](const auto& rc) {
25+
return connected_now.count(rc.pubkey) == 0
26+
and not _router.routerProfiling().IsBadForConnect(rc.pubkey)
27+
and not _router.IsBootstrapNode(rc.pubkey);
28+
});
29+
}
30+
31+
// select random from strict connections.
32+
std::vector<RouterID> keys{_keys.begin(), _keys.end()};
33+
34+
std::shuffle(keys.begin(), keys.end(), llarp::CSRNG{});
35+
36+
for (const auto& pk : keys)
37+
{
38+
if (_router.routerProfiling().IsBadForConnect(pk))
39+
continue;
40+
if (connected_now.count(pk))
41+
continue;
42+
if (auto maybe = nodedb->Get(pk))
43+
return maybe;
44+
}
45+
return std::nullopt;
46+
}
47+
48+
std::optional<RouterContact>
49+
EdgeSelector::select_bootstrap(const std::unordered_set<RouterID>& connected_now) const
50+
{
51+
auto conf = _router.GetConfig();
52+
auto nodedb = _router.nodedb();
53+
if (const auto& _keys = conf->network.m_strictConnect; not _keys.empty())
54+
{
55+
// try bootstrapping off strict connections first if we have any.
56+
std::vector<RouterID> keys{_keys.begin(), _keys.end()};
57+
std::shuffle(keys.begin(), keys.end(), llarp::CSRNG{});
58+
for (const auto& pk : keys)
59+
{
60+
if (connected_now.count(pk))
61+
continue;
62+
if (auto maybe = nodedb->Get(pk))
63+
return maybe;
64+
}
65+
}
66+
// if we cant use a strict connection we'll just use one of our bootstrap nodes.
67+
return nodedb->GetRandom([&connected_now, this](const auto& rc) {
68+
return connected_now.count(rc.pubkey) == 0 and _router.IsBootstrapNode(rc.pubkey);
69+
});
70+
}
71+
} // namespace llarp::consensus

llarp/consensus/edge_selector.hpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#pragma once
2+
3+
#include <optional>
4+
#include <unordered_set>
5+
#include <llarp/router_id.hpp>
6+
7+
namespace llarp
8+
{
9+
struct AbstractRouter;
10+
struct RouterContact;
11+
} // namespace llarp
12+
13+
namespace llarp::consensus
14+
{
15+
/// when we want to connect to and edge when we are a client, an instance of EdgeSelector acts as
16+
/// a stateless selection algorith for router contacts for each attempt at connecting out we make.
17+
class EdgeSelector
18+
{
19+
AbstractRouter& _router;
20+
21+
public:
22+
explicit EdgeSelector(AbstractRouter& router);
23+
24+
/// select a candidate for connecting out to the network when we need more connections to do a
25+
/// path build. pass in an unordered set of the snode pubkeys we are currently connected to.
26+
std::optional<RouterContact>
27+
select_path_edge(const std::unordered_set<RouterID>& connected_now = {}) const;
28+
29+
/// get a router contact of a bootstrap snode to bootstrap with if we are in need of
30+
/// bootstrapping more peers. pass in an unodereed set of bootstrap router pubkeys we are
31+
/// currently connected to.
32+
std::optional<RouterContact>
33+
select_bootstrap(const std::unordered_set<RouterID>& connected_now = {}) const;
34+
};
35+
} // namespace llarp::consensus

llarp/router/abstractrouter.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ namespace llarp
4545
struct I_RCLookupHandler;
4646
struct RoutePoker;
4747

48+
namespace consensus
49+
{
50+
class EdgeSelector;
51+
}
52+
4853
namespace dns
4954
{
5055
class I_SystemSettings;
@@ -130,6 +135,9 @@ namespace llarp
130135
virtual const RouterContact&
131136
rc() const = 0;
132137

138+
virtual const consensus::EdgeSelector&
139+
edge_selector() const = 0;
140+
133141
/// modify our rc
134142
/// modify returns nullopt if unmodified otherwise it returns the new rc to be sigend and
135143
/// published out

llarp/router/outbound_session_maker.cpp

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <llarp/util/thread/threading.hpp>
1212
#include <llarp/util/status.hpp>
1313
#include <llarp/crypto/crypto.hpp>
14+
#include <llarp/consensus/edge_selector.hpp>
1415
#include <utility>
1516

1617
#include <llarp/rpc/lokid_rpc_client.hpp>
@@ -139,30 +140,23 @@ namespace llarp
139140
OutboundSessionMaker::ConnectToRandomRouters(int numDesired)
140141
{
141142
int remainingDesired = numDesired;
142-
std::set<RouterID> exclude;
143+
std::unordered_set<RouterID> exclude;
144+
for (const auto& item : pendingSessions)
145+
exclude.emplace(item.first);
146+
_linkManager->ForEachPeer([&exclude](auto* session) {
147+
if (session and session->IsEstablished())
148+
exclude.emplace(session->GetPubKey());
149+
});
143150
do
144151
{
145-
auto filter = [exclude](const auto& rc) -> bool { return exclude.count(rc.pubkey) == 0; };
146-
147-
RouterContact other;
148-
if (const auto maybe = _nodedb->GetRandom(filter))
149-
{
150-
other = *maybe;
151-
}
152-
else
152+
auto maybe_rc = _router->edge_selector().select_path_edge(exclude);
153+
if (not maybe_rc)
153154
break;
154155

155-
exclude.insert(other.pubkey);
156-
if (not _rcLookup->SessionIsAllowed(other.pubkey))
157-
{
158-
continue;
159-
}
160-
if (not(_linkManager->HasSessionTo(other.pubkey) || HavePendingSessionTo(other.pubkey)))
161-
{
162-
CreateSessionTo(other, nullptr);
163-
--remainingDesired;
164-
}
165-
156+
const auto& rc = *maybe_rc;
157+
exclude.insert(rc.pubkey);
158+
CreateSessionTo(rc, nullptr);
159+
--remainingDesired;
166160
} while (remainingDesired > 0);
167161
LogDebug(
168162
"connecting to ", numDesired - remainingDesired, " out of ", numDesired, " random routers");

llarp/router/router.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ namespace llarp
5050
Router::Router(EventLoop_ptr loop, std::shared_ptr<vpn::Platform> vpnPlatform)
5151
: ready{false}
5252
, m_lmq{std::make_shared<oxenmq::OxenMQ>()}
53+
, _edge_selector{*this}
5354
, _loop{std::move(loop)}
5455
, _vpnPlatform{std::move(vpnPlatform)}
5556
, paths{this}
@@ -869,6 +870,12 @@ namespace llarp
869870
m_LastStatsReport = now;
870871
}
871872

873+
const consensus::EdgeSelector&
874+
Router::edge_selector() const
875+
{
876+
return _edge_selector;
877+
}
878+
872879
std::string
873880
Router::status_line()
874881
{
@@ -1059,12 +1066,8 @@ namespace llarp
10591066
_rcLookupHandler.ExploreNetwork();
10601067
m_NextExploreAt = timepoint_now + std::chrono::seconds(interval);
10611068
}
1062-
size_t connectToNum = _outboundSessionMaker.minConnectedRouters;
1063-
const auto strictConnect = _rcLookupHandler.NumberOfStrictConnectRouters();
1064-
if (strictConnect > 0 && connectToNum > strictConnect)
1065-
{
1066-
connectToNum = strictConnect;
1067-
}
1069+
1070+
size_t connectToNum = _outboundSessionMaker.maxConnectedRouters;
10681071

10691072
if (isSvcNode and now >= m_NextDecommissionWarn)
10701073
{

llarp/router/router.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "abstractrouter.hpp"
44

55
#include <llarp/bootstrap.hpp>
6+
#include <llarp/consensus/edge_selector.hpp>
67
#include <llarp/config/config.hpp>
78
#include <llarp/config/key_manager.hpp>
89
#include <llarp/constants/link_layer.hpp>
@@ -79,6 +80,8 @@ namespace llarp
7980

8081
std::shared_ptr<EventLoopWakeup> m_Pump;
8182

83+
consensus::EdgeSelector _edge_selector;
84+
8285
path::BuildLimiter&
8386
pathBuildLimiter() override
8487
{
@@ -148,6 +151,9 @@ namespace llarp
148151
const std::vector<RouterID>& greylist,
149152
const std::vector<RouterID>& unfunded) override;
150153

154+
const consensus::EdgeSelector&
155+
edge_selector() const override;
156+
151157
std::unordered_set<RouterID>
152158
GetRouterWhitelist() const override
153159
{

0 commit comments

Comments
 (0)