mirror of
https://github.com/oxen-io/lokinet.git
synced 2024-10-31 09:20:21 +00:00
4103908a8d
the win32 and sd_notify components provided a disjointed set of similar high level functionality so we consolidate these duplicate code paths into one that has the same lifecycle regardless of platform to reduce complexity of this feature. this new component is responsible for reporting state changes to the system layer and optionally propagating state change to lokinet requested by the system layer (used by windows service).
610 lines
13 KiB
C++
610 lines
13 KiB
C++
#pragma once
|
|
|
|
#include "abstractrouter.hpp"
|
|
|
|
#include <llarp/bootstrap.hpp>
|
|
#include <llarp/config/config.hpp>
|
|
#include <llarp/config/key_manager.hpp>
|
|
#include <llarp/constants/link_layer.hpp>
|
|
#include <llarp/crypto/types.hpp>
|
|
#include <llarp/ev/ev.hpp>
|
|
#include <llarp/exit/context.hpp>
|
|
#include <llarp/handlers/tun.hpp>
|
|
#include <llarp/link/link_manager.hpp>
|
|
#include <llarp/link/server.hpp>
|
|
#include <llarp/messages/link_message_parser.hpp>
|
|
#include <llarp/nodedb.hpp>
|
|
#include <llarp/path/path_context.hpp>
|
|
#include <llarp/peerstats/peer_db.hpp>
|
|
#include <llarp/profiling.hpp>
|
|
#include <llarp/router_contact.hpp>
|
|
#include "outbound_message_handler.hpp"
|
|
#include "outbound_session_maker.hpp"
|
|
#include "rc_gossiper.hpp"
|
|
#include "rc_lookup_handler.hpp"
|
|
#include "route_poker.hpp"
|
|
#include <llarp/routing/handler.hpp>
|
|
#include <llarp/routing/message_parser.hpp>
|
|
#include <llarp/rpc/lokid_rpc_client.hpp>
|
|
#include <llarp/rpc/rpc_server.hpp>
|
|
#include <llarp/service/context.hpp>
|
|
#include <stdexcept>
|
|
#include <llarp/util/buffer.hpp>
|
|
#include <llarp/util/fs.hpp>
|
|
#include <llarp/util/mem.hpp>
|
|
#include <llarp/util/status.hpp>
|
|
#include <llarp/util/str.hpp>
|
|
#include <llarp/util/time.hpp>
|
|
#include <llarp/util/service_manager.hpp>
|
|
|
|
#include <functional>
|
|
#include <list>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <set>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include <oxenmq/address.h>
|
|
|
|
namespace llarp
|
|
{
|
|
struct Router : public AbstractRouter
|
|
{
|
|
llarp_time_t _lastPump = 0s;
|
|
bool ready;
|
|
// transient iwp encryption key
|
|
fs::path transport_keyfile;
|
|
|
|
// long term identity key
|
|
fs::path ident_keyfile;
|
|
|
|
fs::path encryption_keyfile;
|
|
|
|
// path to write our self signed rc to
|
|
fs::path our_rc_file;
|
|
|
|
// use file based logging?
|
|
bool m_UseFileLogging = false;
|
|
|
|
// our router contact
|
|
RouterContact _rc;
|
|
|
|
/// should we obey the service node whitelist?
|
|
bool whitelistRouters = false;
|
|
|
|
LMQ_ptr m_lmq;
|
|
|
|
path::BuildLimiter m_PathBuildLimiter;
|
|
|
|
std::shared_ptr<EventLoopWakeup> m_Pump;
|
|
|
|
path::BuildLimiter&
|
|
pathBuildLimiter() override
|
|
{
|
|
return m_PathBuildLimiter;
|
|
}
|
|
|
|
const llarp::net::Platform&
|
|
Net() const override;
|
|
|
|
const LMQ_ptr&
|
|
lmq() const override
|
|
{
|
|
return m_lmq;
|
|
}
|
|
|
|
const std::shared_ptr<rpc::LokidRpcClient>&
|
|
RpcClient() const override
|
|
{
|
|
return m_lokidRpcClient;
|
|
}
|
|
|
|
llarp_dht_context*
|
|
dht() const override
|
|
{
|
|
return _dht;
|
|
}
|
|
|
|
std::optional<std::variant<nuint32_t, nuint128_t>>
|
|
OurPublicIP() const override;
|
|
|
|
util::StatusObject
|
|
ExtractStatus() const override;
|
|
|
|
util::StatusObject
|
|
ExtractSummaryStatus() const override;
|
|
|
|
const std::shared_ptr<NodeDB>&
|
|
nodedb() const override
|
|
{
|
|
return _nodedb;
|
|
}
|
|
|
|
const path::PathContext&
|
|
pathContext() const override
|
|
{
|
|
return paths;
|
|
}
|
|
|
|
path::PathContext&
|
|
pathContext() override
|
|
{
|
|
return paths;
|
|
}
|
|
|
|
const RouterContact&
|
|
rc() const override
|
|
{
|
|
return _rc;
|
|
}
|
|
|
|
void
|
|
ModifyOurRC(std::function<std::optional<RouterContact>(RouterContact)> modify) override;
|
|
|
|
void
|
|
SetRouterWhitelist(
|
|
const std::vector<RouterID>& whitelist,
|
|
const std::vector<RouterID>& greylist,
|
|
const std::vector<RouterID>& unfunded) override;
|
|
|
|
std::unordered_set<RouterID>
|
|
GetRouterWhitelist() const override
|
|
{
|
|
return _rcLookupHandler.Whitelist();
|
|
}
|
|
|
|
exit::Context&
|
|
exitContext() override
|
|
{
|
|
return _exitContext;
|
|
}
|
|
|
|
const std::shared_ptr<KeyManager>&
|
|
keyManager() const override
|
|
{
|
|
return m_keyManager;
|
|
}
|
|
|
|
const SecretKey&
|
|
identity() const override
|
|
{
|
|
return _identity;
|
|
}
|
|
|
|
const SecretKey&
|
|
encryption() const override
|
|
{
|
|
return _encryption;
|
|
}
|
|
|
|
Profiling&
|
|
routerProfiling() override
|
|
{
|
|
return _routerProfiling;
|
|
}
|
|
|
|
const EventLoop_ptr&
|
|
loop() const override
|
|
{
|
|
return _loop;
|
|
}
|
|
|
|
vpn::Platform*
|
|
GetVPNPlatform() const override
|
|
{
|
|
return _vpnPlatform.get();
|
|
}
|
|
|
|
void
|
|
QueueWork(std::function<void(void)> func) override;
|
|
|
|
void
|
|
QueueDiskIO(std::function<void(void)> func) override;
|
|
|
|
/// return true if we look like we are a decommissioned service node
|
|
bool
|
|
LooksDecommissioned() const;
|
|
|
|
/// return true if we look like we are a registered, fully-staked service node (either active or
|
|
/// decommissioned). This condition determines when we are allowed to (and attempt to) connect
|
|
/// to other peers when running as a service node.
|
|
bool
|
|
LooksFunded() const;
|
|
|
|
/// return true if we a registered service node; not that this only requires a partial stake,
|
|
/// and does not imply that this service node is *active* or fully funded.
|
|
bool
|
|
LooksRegistered() const;
|
|
|
|
/// return true if we look like we are allowed and able to test other routers
|
|
bool
|
|
ShouldTestOtherRouters() const;
|
|
|
|
std::optional<SockAddr> _ourAddress;
|
|
|
|
EventLoop_ptr _loop;
|
|
std::shared_ptr<vpn::Platform> _vpnPlatform;
|
|
path::PathContext paths;
|
|
exit::Context _exitContext;
|
|
SecretKey _identity;
|
|
SecretKey _encryption;
|
|
llarp_dht_context* _dht = nullptr;
|
|
std::shared_ptr<NodeDB> _nodedb;
|
|
llarp_time_t _startedAt;
|
|
const oxenmq::TaggedThreadID m_DiskThread;
|
|
|
|
llarp_time_t
|
|
Uptime() const override;
|
|
|
|
bool
|
|
Sign(Signature& sig, const llarp_buffer_t& buf) const override;
|
|
|
|
/// how often do we resign our RC? milliseconds.
|
|
// TODO: make configurable
|
|
llarp_time_t rcRegenInterval = 1h;
|
|
|
|
// should we be sending padded messages every interval?
|
|
bool sendPadding = false;
|
|
|
|
LinkMessageParser inbound_link_msg_parser;
|
|
routing::InboundMessageParser inbound_routing_msg_parser;
|
|
|
|
service::Context _hiddenServiceContext;
|
|
|
|
service::Context&
|
|
hiddenServiceContext() override
|
|
{
|
|
return _hiddenServiceContext;
|
|
}
|
|
|
|
const service::Context&
|
|
hiddenServiceContext() const override
|
|
{
|
|
return _hiddenServiceContext;
|
|
}
|
|
|
|
llarp_time_t _lastTick = 0s;
|
|
|
|
std::function<void(void)> _onDown;
|
|
|
|
void
|
|
SetDownHook(std::function<void(void)> hook) override
|
|
{
|
|
_onDown = hook;
|
|
}
|
|
|
|
bool
|
|
LooksAlive() const override
|
|
{
|
|
const llarp_time_t now = Now();
|
|
return now <= _lastTick || (now - _lastTick) <= llarp_time_t{30000};
|
|
}
|
|
|
|
/// bootstrap RCs
|
|
BootstrapList bootstrapRCList;
|
|
|
|
const std::shared_ptr<RoutePoker>&
|
|
routePoker() const override
|
|
{
|
|
return m_RoutePoker;
|
|
}
|
|
|
|
std::shared_ptr<RoutePoker> m_RoutePoker;
|
|
|
|
void
|
|
TriggerPump() override;
|
|
|
|
void
|
|
PumpLL();
|
|
|
|
const oxenmq::address DefaultRPCBindAddr = oxenmq::address::tcp("127.0.0.1", 1190);
|
|
bool enableRPCServer = false;
|
|
oxenmq::address rpcBindAddr = DefaultRPCBindAddr;
|
|
std::unique_ptr<rpc::RpcServer> m_RPCServer;
|
|
|
|
const llarp_time_t _randomStartDelay;
|
|
|
|
std::shared_ptr<rpc::LokidRpcClient> m_lokidRpcClient;
|
|
|
|
oxenmq::address lokidRPCAddr;
|
|
Profiling _routerProfiling;
|
|
fs::path _profilesFile;
|
|
OutboundMessageHandler _outboundMessageHandler;
|
|
OutboundSessionMaker _outboundSessionMaker;
|
|
LinkManager _linkManager;
|
|
RCLookupHandler _rcLookupHandler;
|
|
RCGossiper _rcGossiper;
|
|
|
|
std::string
|
|
status_line() override;
|
|
|
|
using Clock_t = std::chrono::steady_clock;
|
|
using TimePoint_t = Clock_t::time_point;
|
|
|
|
TimePoint_t m_NextExploreAt;
|
|
|
|
IOutboundMessageHandler&
|
|
outboundMessageHandler() override
|
|
{
|
|
return _outboundMessageHandler;
|
|
}
|
|
|
|
IOutboundSessionMaker&
|
|
outboundSessionMaker() override
|
|
{
|
|
return _outboundSessionMaker;
|
|
}
|
|
|
|
ILinkManager&
|
|
linkManager() override
|
|
{
|
|
return _linkManager;
|
|
}
|
|
|
|
I_RCLookupHandler&
|
|
rcLookupHandler() override
|
|
{
|
|
return _rcLookupHandler;
|
|
}
|
|
|
|
std::shared_ptr<PeerDb>
|
|
peerDb() override
|
|
{
|
|
return m_peerDb;
|
|
}
|
|
|
|
inline int
|
|
OutboundUDPSocket() const override
|
|
{
|
|
return m_OutboundUDPSocket;
|
|
}
|
|
|
|
void
|
|
GossipRCIfNeeded(const RouterContact rc) override;
|
|
|
|
explicit Router(EventLoop_ptr loop, std::shared_ptr<vpn::Platform> vpnPlatform);
|
|
|
|
~Router() override;
|
|
|
|
bool
|
|
HandleRecvLinkMessageBuffer(ILinkSession* from, const llarp_buffer_t& msg) override;
|
|
|
|
void
|
|
InitInboundLinks();
|
|
|
|
void
|
|
InitOutboundLinks();
|
|
|
|
bool
|
|
GetRandomGoodRouter(RouterID& r) override;
|
|
|
|
/// initialize us as a service node
|
|
/// return true on success
|
|
bool
|
|
InitServiceNode();
|
|
|
|
bool
|
|
IsRunning() const override;
|
|
|
|
/// return true if we are running in service node mode
|
|
bool
|
|
IsServiceNode() const override;
|
|
|
|
std::optional<std::string>
|
|
OxendErrorState() const override;
|
|
|
|
void
|
|
Close();
|
|
|
|
bool
|
|
Configure(std::shared_ptr<Config> conf, bool isSNode, std::shared_ptr<NodeDB> nodedb) override;
|
|
|
|
bool
|
|
StartRpcServer() override;
|
|
|
|
void
|
|
Freeze() override;
|
|
|
|
void
|
|
Thaw() override;
|
|
|
|
bool
|
|
Run() override;
|
|
|
|
/// stop running the router logic gracefully
|
|
void
|
|
Stop() override;
|
|
|
|
/// non graceful stop router
|
|
void
|
|
Die() override;
|
|
|
|
/// close all sessions and shutdown all links
|
|
void
|
|
StopLinks();
|
|
|
|
void
|
|
PersistSessionUntil(const RouterID& remote, llarp_time_t until) override;
|
|
|
|
bool
|
|
EnsureIdentity();
|
|
|
|
bool
|
|
EnsureEncryptionKey();
|
|
|
|
bool
|
|
SessionToRouterAllowed(const RouterID& router) const override;
|
|
bool
|
|
PathToRouterAllowed(const RouterID& router) const override;
|
|
|
|
void
|
|
HandleSaveRC() const;
|
|
|
|
bool
|
|
SaveRC();
|
|
|
|
/// return true if we are a client with an exit configured
|
|
bool
|
|
HasClientExit() const override;
|
|
|
|
const byte_t*
|
|
pubkey() const override
|
|
{
|
|
return seckey_topublic(_identity);
|
|
}
|
|
|
|
void
|
|
try_connect(fs::path rcfile);
|
|
|
|
bool
|
|
TryConnectAsync(RouterContact rc, uint16_t tries) override;
|
|
|
|
/// send to remote router or queue for sending
|
|
/// returns false on overflow
|
|
/// returns true on successful queue
|
|
/// NOT threadsafe
|
|
/// MUST be called in the logic thread
|
|
bool
|
|
SendToOrQueue(
|
|
const RouterID& remote, const ILinkMessage& msg, SendStatusHandler handler) override;
|
|
|
|
void
|
|
ForEachPeer(std::function<void(const ILinkSession*, bool)> visit, bool randomize = false)
|
|
const override;
|
|
|
|
void
|
|
ForEachPeer(std::function<void(ILinkSession*)> visit);
|
|
|
|
bool IsBootstrapNode(RouterID) const override;
|
|
|
|
/// check if newRc matches oldRC and update local rc for this remote contact
|
|
/// if valid
|
|
/// returns true on valid and updated
|
|
/// returns false otherwise
|
|
bool
|
|
CheckRenegotiateValid(RouterContact newRc, RouterContact oldRC) override;
|
|
|
|
/// called by link when a remote session has no more sessions open
|
|
void
|
|
SessionClosed(RouterID remote) override;
|
|
|
|
/// called by link when an unestablished connection times out
|
|
void
|
|
ConnectionTimedOut(ILinkSession* session);
|
|
|
|
/// called by link when session is fully established
|
|
bool
|
|
ConnectionEstablished(ILinkSession* session, bool inbound);
|
|
|
|
/// call internal router ticker
|
|
void
|
|
Tick();
|
|
|
|
llarp_time_t
|
|
Now() const override
|
|
{
|
|
return llarp::time_now_ms();
|
|
}
|
|
|
|
/// parse a routing message in a buffer and handle it with a handler if
|
|
/// successful parsing return true on parse and handle success otherwise
|
|
/// return false
|
|
bool
|
|
ParseRoutingMessageBuffer(
|
|
const llarp_buffer_t& buf, routing::IMessageHandler* h, const PathID_t& rxid) override;
|
|
|
|
void
|
|
ConnectToRandomRouters(int N) override;
|
|
|
|
/// count the number of unique service nodes connected via pubkey
|
|
size_t
|
|
NumberOfConnectedRouters() const override;
|
|
|
|
/// count the number of unique clients connected by pubkey
|
|
size_t
|
|
NumberOfConnectedClients() const override;
|
|
|
|
bool
|
|
GetRandomConnectedRouter(RouterContact& result) const override;
|
|
|
|
void
|
|
HandleDHTLookupForExplore(RouterID remote, const std::vector<RouterContact>& results) override;
|
|
|
|
void
|
|
LookupRouter(RouterID remote, RouterLookupHandler resultHandler) override;
|
|
|
|
bool
|
|
HasSessionTo(const RouterID& remote) const override;
|
|
|
|
std::string
|
|
ShortName() const override;
|
|
|
|
uint32_t
|
|
NextPathBuildNumber() override;
|
|
|
|
void
|
|
AfterStopLinks();
|
|
|
|
void
|
|
AfterStopIssued();
|
|
|
|
std::shared_ptr<Config> m_Config;
|
|
|
|
std::shared_ptr<Config>
|
|
GetConfig() const override
|
|
{
|
|
return m_Config;
|
|
}
|
|
|
|
int m_OutboundUDPSocket = -1;
|
|
|
|
private:
|
|
std::atomic<bool> _stopping;
|
|
std::atomic<bool> _running;
|
|
|
|
bool m_isServiceNode = false;
|
|
|
|
// Delay warning about being decommed/dereged until we've had enough time to sync up with oxend
|
|
static constexpr auto DECOMM_WARNING_STARTUP_DELAY = 15s;
|
|
|
|
llarp_time_t m_LastStatsReport = 0s;
|
|
llarp_time_t m_NextDecommissionWarn = time_now_ms() + DECOMM_WARNING_STARTUP_DELAY;
|
|
std::shared_ptr<llarp::KeyManager> m_keyManager;
|
|
std::shared_ptr<PeerDb> m_peerDb;
|
|
|
|
uint32_t path_build_count = 0;
|
|
|
|
consensus::reachability_testing m_routerTesting;
|
|
|
|
bool
|
|
ShouldReportStats(llarp_time_t now) const;
|
|
|
|
void
|
|
ReportStats();
|
|
|
|
bool
|
|
UpdateOurRC(bool rotateKeys = false);
|
|
|
|
bool
|
|
FromConfig(const Config& conf);
|
|
|
|
void
|
|
MessageSent(const RouterID& remote, SendStatus status);
|
|
|
|
bool
|
|
TooFewPeers() const;
|
|
|
|
protected:
|
|
virtual void
|
|
HandleRouterEvent(tooling::RouterEventPtr event) const override;
|
|
|
|
virtual bool
|
|
disableGossipingRC_TestingOnly()
|
|
{
|
|
return false;
|
|
};
|
|
};
|
|
|
|
} // namespace llarp
|