mirror of
https://github.com/oxen-io/lokinet.git
synced 2024-10-31 09:20:21 +00:00
af6caf776a
* Config file API/comment improvements API improvements: ================= Make the config API use position-independent tag parameters (Required, Default{123}, MultiValue) rather than a sequence of bools with overloads. For example, instead of: conf.defineOption<int>("a", "b", false, true, 123, [] { ... }); you now write: conf.defineOption<int>("a", "b", MultiValue, Default{123}, [] { ... }); The tags are: - Required - MultiValue - Default{value} plus new abilities (see below): - Hidden - RelayOnly - ClientOnly - Comment{"line1", "line2", "line3"} Made option definition more powerful: ===================================== - `Hidden` allows you to define an option that won't show up in the generated config file if it isn't set. - `RelayOnly`/`ClientOnly` sets up an option that is only accepted and only shows up for relay or client configs. (If neither is specified the option shows up in both modes). - `Comment{...}` lets the option comments be specified as part of the defineOption. Comment improvements ==================== - Rewrote comments for various options to expand on details. - Inlined all the comments with the option definitions. - Several options that were missing comments got comments added. - Made various options for deprecated and or internal options hidden by default so that they don't show up in a default config file. - show the section comment (but not option comments) *after* the [section] tag instead of before it as it makes more sense that way (particularly for the [bind] section which has a new long comment to describe how it works). Disable profiling by default ============================ We had this weird state where we use and store profiling by default but never *load* it when starting up. This commit makes us just not use profiling at all unless explicitly enabled. Other misc changes: =================== - change default worker threads to 0 (= num cpus) instead of 1, and fix it to allow 0. - Actually apply worker-threads option - fixed default data-dir value erroneously having quotes around it - reordered ifname/ifaddr/mapaddr (was previously mapaddr/ifaddr/ifname) as mapaddr is a sort of specialization of ifaddr and so makes more sense to come after it (particularly because it now references ifaddr in its help message). - removed peer-stats option (since we always require it for relays and never use it for clients) - removed router profiles filename option (this doesn't need to be configurable) - removed defunct `service-node-seed` option - Change default logging output file to "" (which means stdout), and also made "-" work for stdout. * Router hive compilation fixes * Comments for SNApp SRV settings in ini file * Add extra blank line after section comments * Better deprecated option handling Allow {client,relay}-only options in {relay,client} configs to be specified as implicitly deprecated options: they warn, and don't set anything. Add an explicit `Deprecated` tag and move deprecated option handling into definition.cpp. * Move backwards compat options into section definitions Keep the "addBackwardsCompatibleConfigOptions" only for options in sections that no longer exist. * Fix INI parsing issues & C++17-ify - don't allow inline comments because it seems they aren't allowed in ini formats in general, and is going to cause problems if there is a comment character in a value (e.g. an exit auth string). Additionally it was breaking on a line such as: # some comment; see? because it was treating only `; see?` as the comment and then producing an error message about the rest of the line being invalid. - make section parsing stricter: the `[` and `]` have to be at the beginning at end of the line now (after stripping whitespace). - Move whitespace stripping to the top since everything in here does it. - chop off string_view suffix/prefix rather than maintaining position values - fix potential infinite loop/segfault when given a line such as `]foo[` * Make config parsing failure fatal Load() LogError's and returns false on failure, so we weren't aborting on config file errors. * Formatting: allow `{}` for empty functions/structs Instead of using two lines when empty: { } * Make default dns bind 127.0.0.1 on non-Linux * Don't show empty section; fix tests We can conceivably have sections that only make sense for clients or relays, and so want to completely omit that section if we have no options for the type of config being generated. Also fixes missing empty lines between tests. Co-authored-by: Thomas Winget <tewinget@gmail.com>
556 lines
12 KiB
C++
556 lines
12 KiB
C++
#ifndef LLARP_ROUTER_HPP
|
|
#define LLARP_ROUTER_HPP
|
|
|
|
#include <router/abstractrouter.hpp>
|
|
|
|
#include <bootstrap.hpp>
|
|
#include <config/config.hpp>
|
|
#include <config/key_manager.hpp>
|
|
#include <constants/link_layer.hpp>
|
|
#include <crypto/types.hpp>
|
|
#include <ev/ev.h>
|
|
#include <exit/context.hpp>
|
|
#include <handlers/tun.hpp>
|
|
#include <link/link_manager.hpp>
|
|
#include <link/server.hpp>
|
|
#include <messages/link_message_parser.hpp>
|
|
#include <nodedb.hpp>
|
|
#include <path/path_context.hpp>
|
|
#include <peerstats/peer_db.hpp>
|
|
#include <profiling.hpp>
|
|
#include <router_contact.hpp>
|
|
#include <router/outbound_message_handler.hpp>
|
|
#include <router/outbound_session_maker.hpp>
|
|
#include <router/rc_gossiper.hpp>
|
|
#include <router/rc_lookup_handler.hpp>
|
|
#include <router/route_poker.hpp>
|
|
#include <routing/handler.hpp>
|
|
#include <routing/message_parser.hpp>
|
|
#include <rpc/lokid_rpc_client.hpp>
|
|
#include <rpc/rpc_server.hpp>
|
|
#include <service/context.hpp>
|
|
#include <stdexcept>
|
|
#include <util/buffer.hpp>
|
|
#include <util/fs.hpp>
|
|
#include <util/mem.hpp>
|
|
#include <util/status.hpp>
|
|
#include <util/str.hpp>
|
|
#include <util/thread/logic.hpp>
|
|
#include <util/time.hpp>
|
|
|
|
#include <functional>
|
|
#include <list>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <set>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include <lokimq/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;
|
|
|
|
LMQ_ptr
|
|
lmq() const override
|
|
{
|
|
return m_lmq;
|
|
}
|
|
|
|
std::shared_ptr<rpc::LokidRpcClient>
|
|
RpcClient() const override
|
|
{
|
|
return m_lokidRpcClient;
|
|
}
|
|
|
|
std::shared_ptr<Logic>
|
|
logic() const override
|
|
{
|
|
return _logic;
|
|
}
|
|
|
|
llarp_dht_context*
|
|
dht() const override
|
|
{
|
|
return _dht;
|
|
}
|
|
|
|
util::StatusObject
|
|
ExtractStatus() const override;
|
|
|
|
llarp_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
|
|
SetRouterWhitelist(const std::vector<RouterID> routers) override;
|
|
|
|
exit::Context&
|
|
exitContext() override
|
|
{
|
|
return _exitContext;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
llarp_ev_loop_ptr
|
|
netloop() const override
|
|
{
|
|
return _netloop;
|
|
}
|
|
|
|
void
|
|
QueueWork(std::function<void(void)> func) override;
|
|
|
|
void
|
|
QueueDiskIO(std::function<void(void)> func) override;
|
|
|
|
IpAddress _ourAddress;
|
|
|
|
llarp_ev_loop_ptr _netloop;
|
|
std::shared_ptr<Logic> _logic;
|
|
path::PathContext paths;
|
|
exit::Context _exitContext;
|
|
SecretKey _identity;
|
|
SecretKey _encryption;
|
|
llarp_dht_context* _dht = nullptr;
|
|
llarp_nodedb* _nodedb;
|
|
llarp_time_t _startedAt;
|
|
const lokimq::TaggedThreadID m_DiskThread;
|
|
|
|
llarp_time_t
|
|
Uptime() const override;
|
|
|
|
bool
|
|
Sign(Signature& sig, const llarp_buffer_t& buf) const override;
|
|
|
|
uint16_t m_OutboundPort = 0;
|
|
/// 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;
|
|
|
|
uint32_t ticker_job_id = 0;
|
|
|
|
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;
|
|
|
|
bool
|
|
ExitEnabled() const
|
|
{
|
|
return false; // FIXME - have to fix the FIXME because FIXME
|
|
throw std::runtime_error("FIXME: this needs to be derived from config");
|
|
/*
|
|
// TODO: use equal_range ?
|
|
auto itr = netConfig.find("exit");
|
|
if (itr == netConfig.end())
|
|
return false;
|
|
return IsTrueValue(itr->second.c_str());
|
|
*/
|
|
}
|
|
|
|
RoutePoker&
|
|
routePoker() override
|
|
{
|
|
return m_RoutePoker;
|
|
}
|
|
|
|
RoutePoker m_RoutePoker;
|
|
|
|
void
|
|
PumpLL() override;
|
|
|
|
NetworkConfig networkConfig;
|
|
DnsConfig dnsConfig;
|
|
|
|
const lokimq::address DefaultRPCBindAddr = lokimq::address::tcp("127.0.0.1", 1190);
|
|
bool enableRPCServer = false;
|
|
lokimq::address rpcBindAddr = DefaultRPCBindAddr;
|
|
std::unique_ptr<rpc::RpcServer> m_RPCServer;
|
|
|
|
const llarp_time_t _randomStartDelay;
|
|
|
|
std::shared_ptr<rpc::LokidRpcClient> m_lokidRpcClient;
|
|
|
|
lokimq::address lokidRPCAddr;
|
|
|
|
Profiling _routerProfiling;
|
|
std::string routerProfilesFile = "profiles.dat";
|
|
|
|
OutboundMessageHandler _outboundMessageHandler;
|
|
OutboundSessionMaker _outboundSessionMaker;
|
|
LinkManager _linkManager;
|
|
RCLookupHandler _rcLookupHandler;
|
|
RCGossiper _rcGossiper;
|
|
|
|
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;
|
|
}
|
|
|
|
void
|
|
GossipRCIfNeeded(const RouterContact rc) override;
|
|
|
|
explicit Router(llarp_ev_loop_ptr __netloop, std::shared_ptr<Logic> logic);
|
|
|
|
virtual ~Router() override;
|
|
|
|
bool
|
|
HandleRecvLinkMessageBuffer(ILinkSession* from, const llarp_buffer_t& msg) override;
|
|
|
|
bool
|
|
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;
|
|
|
|
void
|
|
Close();
|
|
|
|
bool
|
|
Configure(std::shared_ptr<Config> conf, bool isRouter, llarp_nodedb* nodedb = nullptr) override;
|
|
|
|
bool
|
|
StartRpcServer() 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
|
|
ConnectionToRouterAllowed(const RouterID& router) const override;
|
|
|
|
void
|
|
HandleSaveRC() const;
|
|
|
|
bool
|
|
SaveRC();
|
|
|
|
/// return true if we are a client with an exit configured
|
|
bool
|
|
HasClientExit() const;
|
|
|
|
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();
|
|
}
|
|
|
|
/// schedule ticker to call i ms from now
|
|
void
|
|
ScheduleTicker(llarp_time_t i = 1s);
|
|
|
|
/// 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
|
|
handle_router_ticker();
|
|
|
|
void
|
|
AfterStopLinks();
|
|
|
|
void
|
|
AfterStopIssued();
|
|
|
|
std::shared_ptr<Config> m_Config;
|
|
|
|
std::shared_ptr<Config>
|
|
GetConfig() const override
|
|
{
|
|
return m_Config;
|
|
}
|
|
|
|
private:
|
|
std::atomic<bool> _stopping;
|
|
std::atomic<bool> _running;
|
|
|
|
bool m_isServiceNode = false;
|
|
|
|
llarp_time_t m_LastStatsReport = 0s;
|
|
|
|
std::shared_ptr<llarp::KeyManager> m_keyManager;
|
|
std::shared_ptr<PeerDb> m_peerDb;
|
|
|
|
uint32_t path_build_count = 0;
|
|
|
|
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);
|
|
|
|
protected:
|
|
virtual void
|
|
HandleRouterEvent(tooling::RouterEventPtr event) const override;
|
|
|
|
virtual bool
|
|
disableGossipingRC_TestingOnly()
|
|
{
|
|
return false;
|
|
};
|
|
};
|
|
|
|
} // namespace llarp
|
|
|
|
#endif
|