2019-12-03 17:58:53 +00:00
|
|
|
#include <memory>
|
2021-03-09 22:24:35 +00:00
|
|
|
#include "router.hpp"
|
2019-01-10 19:41:51 +00:00
|
|
|
|
2021-03-09 22:24:35 +00:00
|
|
|
#include <llarp/config/config.hpp>
|
|
|
|
#include <llarp/constants/proto.hpp>
|
|
|
|
#include <llarp/constants/files.hpp>
|
2022-01-27 16:11:57 +00:00
|
|
|
#include <llarp/constants/time.hpp>
|
2021-03-09 22:24:35 +00:00
|
|
|
#include <llarp/crypto/crypto_libsodium.hpp>
|
|
|
|
#include <llarp/crypto/crypto.hpp>
|
|
|
|
#include <llarp/dht/context.hpp>
|
|
|
|
#include <llarp/dht/node.hpp>
|
|
|
|
#include <llarp/iwp/iwp.hpp>
|
|
|
|
#include <llarp/link/server.hpp>
|
|
|
|
#include <llarp/messages/link_message.hpp>
|
|
|
|
#include <llarp/net/net.hpp>
|
2020-04-24 17:10:05 +00:00
|
|
|
#include <stdexcept>
|
2021-03-09 22:24:35 +00:00
|
|
|
#include <llarp/util/buffer.hpp>
|
2022-07-16 00:41:14 +00:00
|
|
|
#include <llarp/util/logging.hpp>
|
2021-03-09 22:24:35 +00:00
|
|
|
#include <llarp/util/meta/memfn.hpp>
|
|
|
|
#include <llarp/util/str.hpp>
|
|
|
|
#include <llarp/ev/ev.hpp>
|
|
|
|
#include <llarp/tooling/peer_stats_event.hpp>
|
2017-11-28 14:05:31 +00:00
|
|
|
|
2021-03-09 22:24:35 +00:00
|
|
|
#include <llarp/tooling/router_event.hpp>
|
|
|
|
#include <llarp/util/status.hpp>
|
2020-02-27 20:17:37 +00:00
|
|
|
|
2018-05-20 17:45:47 +00:00
|
|
|
#include <fstream>
|
2018-10-09 01:38:25 +00:00
|
|
|
#include <cstdlib>
|
2019-01-02 17:41:13 +00:00
|
|
|
#include <iterator>
|
2019-07-08 15:26:06 +00:00
|
|
|
#include <unordered_map>
|
2019-09-01 12:10:49 +00:00
|
|
|
#include <utility>
|
2019-11-26 21:58:20 +00:00
|
|
|
#if defined(ANDROID) || defined(IOS)
|
2018-11-08 12:31:50 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
2019-11-23 04:47:08 +00:00
|
|
|
|
2020-02-25 22:32:57 +00:00
|
|
|
#if defined(WITH_SYSTEMD)
|
|
|
|
#include <systemd/sd-daemon.h>
|
|
|
|
#endif
|
|
|
|
|
2022-07-09 15:05:52 +00:00
|
|
|
#include <llarp/constants/platform.hpp>
|
|
|
|
|
2021-02-02 14:35:40 +00:00
|
|
|
#include <oxenmq/oxenmq.h>
|
2020-05-19 18:53:03 +00:00
|
|
|
|
2021-06-02 19:37:43 +00:00
|
|
|
static constexpr std::chrono::milliseconds ROUTER_TICK_INTERVAL = 250ms;
|
2018-05-20 17:45:47 +00:00
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
namespace llarp
|
|
|
|
{
|
2022-07-26 14:26:35 +00:00
|
|
|
static auto logcat = log::Cat("router");
|
|
|
|
|
2021-03-02 15:23:38 +00:00
|
|
|
Router::Router(EventLoop_ptr loop, std::shared_ptr<vpn::Platform> vpnPlatform)
|
2022-07-28 16:07:38 +00:00
|
|
|
: ready{false}
|
|
|
|
, m_lmq{std::make_shared<oxenmq::OxenMQ>()}
|
|
|
|
, _loop{std::move(loop)}
|
|
|
|
, _vpnPlatform{std::move(vpnPlatform)}
|
|
|
|
, paths{this}
|
|
|
|
, _exitContext{this}
|
|
|
|
, _dht{llarp_dht_context_new(this)}
|
|
|
|
, m_DiskThread{m_lmq->add_tagged_thread("disk")}
|
|
|
|
, inbound_link_msg_parser{this}
|
|
|
|
, _hiddenServiceContext{this}
|
|
|
|
, m_RoutePoker{std::make_shared<RoutePoker>()}
|
2022-09-28 16:37:19 +00:00
|
|
|
, m_RPCServer{nullptr}
|
2022-07-28 16:07:38 +00:00
|
|
|
, _randomStartDelay{
|
|
|
|
platform::is_simulation ? std::chrono::milliseconds{(llarp::randint() % 1250) + 2000}
|
|
|
|
: 0s}
|
2018-06-20 17:45:44 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
m_keyManager = std::make_shared<KeyManager>();
|
2020-10-02 09:51:52 +00:00
|
|
|
// for lokid, so we don't close the connection when syncing the whitelist
|
|
|
|
m_lmq->MAX_MSG_SIZE = -1;
|
2018-12-24 16:09:05 +00:00
|
|
|
_stopping.store(false);
|
|
|
|
_running.store(false);
|
2020-04-07 18:38:56 +00:00
|
|
|
_lastTick = llarp::time_now_ms();
|
2020-01-18 20:47:36 +00:00
|
|
|
m_NextExploreAt = Clock_t::now();
|
2021-11-15 22:23:42 +00:00
|
|
|
m_Pump = _loop->make_waker([this]() { PumpLL(); });
|
2018-06-20 17:45:44 +00:00
|
|
|
}
|
2018-09-18 20:56:22 +00:00
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
Router::~Router()
|
2018-09-19 13:27:15 +00:00
|
|
|
{
|
2019-01-29 02:16:31 +00:00
|
|
|
llarp_dht_context_free(_dht);
|
2018-09-19 13:27:15 +00:00
|
|
|
}
|
2018-12-10 16:26:46 +00:00
|
|
|
|
2021-11-09 17:44:35 +00:00
|
|
|
void
|
2021-11-12 13:51:39 +00:00
|
|
|
Router::PumpLL()
|
2021-11-09 17:44:35 +00:00
|
|
|
{
|
|
|
|
llarp::LogTrace("Router::PumpLL() start");
|
|
|
|
if (_stopping.load())
|
|
|
|
return;
|
2021-11-15 22:23:42 +00:00
|
|
|
paths.PumpDownstream();
|
|
|
|
paths.PumpUpstream();
|
2021-11-14 15:03:33 +00:00
|
|
|
_hiddenServiceContext.Pump();
|
2021-11-11 14:17:48 +00:00
|
|
|
_outboundMessageHandler.Pump();
|
2021-11-09 17:44:35 +00:00
|
|
|
_linkManager.PumpLinks();
|
|
|
|
llarp::LogTrace("Router::PumpLL() end");
|
|
|
|
}
|
|
|
|
|
2019-02-11 17:14:43 +00:00
|
|
|
util::StatusObject
|
|
|
|
Router::ExtractStatus() const
|
2019-02-08 19:43:25 +00:00
|
|
|
{
|
2022-02-23 14:21:38 +00:00
|
|
|
if (not _running)
|
|
|
|
util::StatusObject{{"running", false}};
|
|
|
|
|
|
|
|
return util::StatusObject{
|
|
|
|
{"running", true},
|
|
|
|
{"numNodesKnown", _nodedb->NumLoaded()},
|
|
|
|
{"dht", _dht->impl->ExtractStatus()},
|
|
|
|
{"services", _hiddenServiceContext.ExtractStatus()},
|
|
|
|
{"exit", _exitContext.ExtractStatus()},
|
|
|
|
{"links", _linkManager.ExtractStatus()},
|
|
|
|
{"outboundMessages", _outboundMessageHandler.ExtractStatus()}};
|
2019-02-08 19:43:25 +00:00
|
|
|
}
|
|
|
|
|
2021-10-13 11:20:36 +00:00
|
|
|
util::StatusObject
|
|
|
|
Router::ExtractSummaryStatus() const
|
|
|
|
{
|
|
|
|
if (!_running)
|
|
|
|
return util::StatusObject{{"running", false}};
|
|
|
|
|
|
|
|
auto services = _hiddenServiceContext.ExtractStatus();
|
2022-02-23 03:21:47 +00:00
|
|
|
|
2021-10-13 11:20:36 +00:00
|
|
|
auto link_types = _linkManager.ExtractStatus();
|
|
|
|
|
|
|
|
uint64_t tx_rate = 0;
|
|
|
|
uint64_t rx_rate = 0;
|
|
|
|
uint64_t peers = 0;
|
|
|
|
for (const auto& links : link_types)
|
|
|
|
{
|
|
|
|
for (const auto& link : links)
|
|
|
|
{
|
|
|
|
if (link.empty())
|
|
|
|
continue;
|
|
|
|
for (const auto& peer : link["sessions"]["established"])
|
|
|
|
{
|
|
|
|
tx_rate += peer["tx"].get<uint64_t>();
|
|
|
|
rx_rate += peer["rx"].get<uint64_t>();
|
|
|
|
peers++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute all stats on all path builders on the default endpoint
|
|
|
|
// Merge snodeSessions, remoteSessions and default into a single array
|
|
|
|
std::vector<nlohmann::json> builders;
|
2022-02-15 05:29:37 +00:00
|
|
|
|
2022-02-23 14:21:38 +00:00
|
|
|
if (services.is_object())
|
|
|
|
{
|
|
|
|
const auto& serviceDefault = services.at("default");
|
|
|
|
builders.push_back(serviceDefault);
|
2022-02-15 05:29:37 +00:00
|
|
|
|
2022-02-23 14:21:38 +00:00
|
|
|
auto snode_sessions = serviceDefault.at("snodeSessions");
|
|
|
|
for (const auto& session : snode_sessions)
|
|
|
|
builders.push_back(session);
|
2021-10-13 11:20:36 +00:00
|
|
|
|
2022-02-23 14:21:38 +00:00
|
|
|
auto remote_sessions = serviceDefault.at("remoteSessions");
|
|
|
|
for (const auto& session : remote_sessions)
|
|
|
|
builders.push_back(session);
|
|
|
|
}
|
2021-10-13 11:20:36 +00:00
|
|
|
|
|
|
|
// Iterate over all items on this array to build the global pathStats
|
2022-02-15 05:29:37 +00:00
|
|
|
uint64_t pathsCount = 0;
|
2021-10-13 11:20:36 +00:00
|
|
|
uint64_t success = 0;
|
|
|
|
uint64_t attempts = 0;
|
|
|
|
for (const auto& builder : builders)
|
|
|
|
{
|
|
|
|
if (builder.is_null())
|
|
|
|
continue;
|
2022-02-15 05:29:37 +00:00
|
|
|
|
|
|
|
const auto& paths = builder.at("paths");
|
|
|
|
if (paths.is_array())
|
|
|
|
{
|
|
|
|
for (const auto& [key, value] : paths.items())
|
|
|
|
{
|
|
|
|
if (value.is_object() && value.at("status").is_string()
|
|
|
|
&& value.at("status") == "established")
|
|
|
|
pathsCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto& buildStats = builder.at("buildStats");
|
|
|
|
if (buildStats.is_null())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
success += buildStats.at("success").get<uint64_t>();
|
|
|
|
attempts += buildStats.at("attempts").get<uint64_t>();
|
2021-10-13 11:20:36 +00:00
|
|
|
}
|
|
|
|
double ratio = static_cast<double>(success) / (attempts + 1);
|
|
|
|
|
2022-02-23 14:21:38 +00:00
|
|
|
util::StatusObject stats{
|
2021-10-13 11:20:36 +00:00
|
|
|
{"running", true},
|
2022-02-20 23:31:44 +00:00
|
|
|
{"version", llarp::VERSION_FULL},
|
|
|
|
{"uptime", to_json(Uptime())},
|
2022-02-15 05:29:37 +00:00
|
|
|
{"numPathsBuilt", pathsCount},
|
2021-10-13 11:20:36 +00:00
|
|
|
{"numPeersConnected", peers},
|
|
|
|
{"numRoutersKnown", _nodedb->NumLoaded()},
|
|
|
|
{"ratio", ratio},
|
|
|
|
{"txRate", tx_rate},
|
|
|
|
{"rxRate", rx_rate},
|
|
|
|
};
|
2022-02-23 14:21:38 +00:00
|
|
|
|
|
|
|
if (services.is_object())
|
|
|
|
{
|
|
|
|
stats["authCodes"] = services["default"]["authCodes"];
|
|
|
|
stats["exitMap"] = services["default"]["exitMap"];
|
|
|
|
stats["lokiAddress"] = services["default"]["identity"];
|
|
|
|
}
|
|
|
|
return stats;
|
2021-10-13 11:20:36 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
bool
|
2020-04-07 18:38:56 +00:00
|
|
|
Router::HandleRecvLinkMessageBuffer(ILinkSession* session, const llarp_buffer_t& buf)
|
2018-09-18 20:56:22 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (_stopping)
|
2018-12-24 16:09:05 +00:00
|
|
|
return true;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!session)
|
2018-12-10 16:26:46 +00:00
|
|
|
{
|
2019-02-11 19:45:42 +00:00
|
|
|
LogWarn("no link session");
|
2018-12-10 16:26:46 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return inbound_link_msg_parser.ProcessFrom(session, buf);
|
2018-10-07 15:29:36 +00:00
|
|
|
}
|
2022-07-28 16:07:38 +00:00
|
|
|
void
|
|
|
|
Router::Freeze()
|
|
|
|
{
|
|
|
|
if (IsServiceNode())
|
|
|
|
return;
|
|
|
|
linkManager().ForEachPeer([](auto peer) {
|
|
|
|
if (peer)
|
|
|
|
peer->Close();
|
|
|
|
});
|
|
|
|
}
|
2018-12-10 16:26:46 +00:00
|
|
|
|
2021-02-05 21:48:57 +00:00
|
|
|
void
|
|
|
|
Router::Thaw()
|
|
|
|
{
|
2022-07-28 16:07:38 +00:00
|
|
|
if (IsServiceNode())
|
|
|
|
return;
|
2021-02-08 11:35:24 +00:00
|
|
|
// get pubkeys we are connected to
|
|
|
|
std::unordered_set<RouterID> peerPubkeys;
|
|
|
|
linkManager().ForEachPeer([&peerPubkeys](auto peer) {
|
|
|
|
if (not peer)
|
|
|
|
return;
|
|
|
|
peerPubkeys.emplace(peer->GetPubKey());
|
|
|
|
});
|
|
|
|
// close our sessions to them on link layer
|
|
|
|
linkManager().ForEachOutboundLink([peerPubkeys](const auto& link) {
|
|
|
|
for (const auto& remote : peerPubkeys)
|
|
|
|
link->CloseSessionTo(remote);
|
|
|
|
});
|
|
|
|
// thaw endpoints
|
2021-02-05 21:48:57 +00:00
|
|
|
hiddenServiceContext().ForEachService([](const auto& name, const auto& ep) -> bool {
|
|
|
|
LogInfo(name, " thawing...");
|
|
|
|
ep->Thaw();
|
|
|
|
return true;
|
|
|
|
});
|
2021-02-08 12:44:01 +00:00
|
|
|
LogInfo("We are ready to go bruh... probably");
|
2021-02-05 21:48:57 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
Router::PersistSessionUntil(const RouterID& remote, llarp_time_t until)
|
2018-10-07 15:29:36 +00:00
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
_linkManager.PersistSessionUntil(remote, until);
|
2018-06-01 14:08:54 +00:00
|
|
|
}
|
2018-06-26 10:08:51 +00:00
|
|
|
|
2020-01-30 17:23:16 +00:00
|
|
|
void
|
|
|
|
Router::GossipRCIfNeeded(const RouterContact rc)
|
|
|
|
{
|
2020-06-25 17:46:31 +00:00
|
|
|
if (disableGossipingRC_TestingOnly())
|
2020-06-24 20:49:35 +00:00
|
|
|
return;
|
|
|
|
|
2020-01-30 17:23:16 +00:00
|
|
|
/// if we are not a service node forget about gossip
|
2020-04-07 18:38:56 +00:00
|
|
|
if (not IsServiceNode())
|
2020-01-30 17:23:16 +00:00
|
|
|
return;
|
|
|
|
/// wait for random uptime
|
2020-04-07 18:38:56 +00:00
|
|
|
if (std::chrono::milliseconds{Uptime()} < _randomStartDelay)
|
2020-01-30 17:23:16 +00:00
|
|
|
return;
|
|
|
|
_rcGossiper.GossipRC(rc);
|
|
|
|
}
|
|
|
|
|
2018-12-13 00:03:19 +00:00
|
|
|
bool
|
2020-04-07 18:38:56 +00:00
|
|
|
Router::GetRandomGoodRouter(RouterID& router)
|
2018-12-13 00:03:19 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (whitelistRouters)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
return _rcLookupHandler.GetRandomWhitelistRouter(router);
|
|
|
|
}
|
|
|
|
|
2021-02-03 21:38:31 +00:00
|
|
|
if (const auto maybe = nodedb()->GetRandom([](const auto&) -> bool { return true; }))
|
2021-02-02 14:35:40 +00:00
|
|
|
{
|
|
|
|
router = maybe->pubkey;
|
2019-05-09 12:31:10 +00:00
|
|
|
return true;
|
2021-02-02 14:35:40 +00:00
|
|
|
}
|
|
|
|
return false;
|
2018-12-13 00:03:19 +00:00
|
|
|
}
|
|
|
|
|
2019-04-30 16:07:17 +00:00
|
|
|
void
|
2021-11-12 13:51:39 +00:00
|
|
|
Router::TriggerPump()
|
2019-04-30 16:07:17 +00:00
|
|
|
{
|
2021-11-09 16:20:53 +00:00
|
|
|
m_Pump->Trigger();
|
2019-04-30 16:07:17 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
bool
|
2021-04-12 11:39:07 +00:00
|
|
|
Router::SendToOrQueue(const RouterID& remote, const ILinkMessage& msg, SendStatusHandler handler)
|
2018-06-14 15:10:31 +00:00
|
|
|
{
|
2019-06-04 18:31:17 +00:00
|
|
|
return _outboundMessageHandler.QueueMessage(remote, msg, handler);
|
2018-10-25 18:18:12 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
Router::ForEachPeer(std::function<void(const ILinkSession*, bool)> visit, bool randomize) const
|
2018-05-22 15:54:19 +00:00
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
_linkManager.ForEachPeer(visit, randomize);
|
2018-05-22 15:54:19 +00:00
|
|
|
}
|
2018-12-10 16:26:46 +00:00
|
|
|
|
2018-12-19 16:17:41 +00:00
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
Router::ForEachPeer(std::function<void(ILinkSession*)> visit)
|
2018-12-19 16:17:41 +00:00
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
_linkManager.ForEachPeer(visit);
|
2018-12-19 16:17:41 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
void
|
|
|
|
Router::try_connect(fs::path rcfile)
|
2018-05-16 18:13:18 +00:00
|
|
|
{
|
2019-02-11 19:45:42 +00:00
|
|
|
RouterContact remote;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!remote.Read(rcfile.string().c_str()))
|
2018-07-25 01:24:37 +00:00
|
|
|
{
|
2019-02-11 19:45:42 +00:00
|
|
|
LogError("failure to decode or verify of remote RC");
|
2018-12-10 16:26:46 +00:00
|
|
|
return;
|
2018-07-25 01:24:37 +00:00
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
if (remote.Verify(Now()))
|
2018-05-22 15:54:19 +00:00
|
|
|
{
|
2019-02-11 19:45:42 +00:00
|
|
|
LogDebug("verified signature");
|
2019-06-26 21:39:29 +00:00
|
|
|
_outboundSessionMaker.CreateSessionTo(remote, nullptr);
|
2018-05-22 15:54:19 +00:00
|
|
|
}
|
2018-12-10 16:26:46 +00:00
|
|
|
else
|
2019-02-11 19:45:42 +00:00
|
|
|
LogError(rcfile, " contains invalid RC");
|
2018-05-16 18:13:18 +00:00
|
|
|
}
|
2018-05-20 17:45:47 +00:00
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
bool
|
|
|
|
Router::EnsureIdentity()
|
|
|
|
{
|
2020-05-20 11:41:42 +00:00
|
|
|
_encryption = m_keyManager->encryptionKey;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (whitelistRouters)
|
2019-11-26 21:58:20 +00:00
|
|
|
{
|
|
|
|
#if defined(ANDROID) || defined(IOS)
|
|
|
|
LogError("running a service node on mobile device is not possible.");
|
|
|
|
return false;
|
2019-11-26 22:11:13 +00:00
|
|
|
#else
|
|
|
|
#if defined(_WIN32)
|
|
|
|
LogError("running a service node on windows is not possible.");
|
|
|
|
return false;
|
|
|
|
#endif
|
2019-11-26 21:58:20 +00:00
|
|
|
#endif
|
2020-07-23 16:54:39 +00:00
|
|
|
constexpr int maxTries = 5;
|
|
|
|
int numTries = 0;
|
|
|
|
while (numTries < maxTries)
|
|
|
|
{
|
|
|
|
numTries++;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
_identity = RpcClient()->ObtainIdentityKey();
|
2022-06-16 00:23:15 +00:00
|
|
|
const RouterID pk{pubkey()};
|
|
|
|
LogWarn("Obtained lokid identity key: ", pk);
|
2020-07-23 16:54:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
catch (const std::exception& e)
|
|
|
|
{
|
|
|
|
LogWarn(
|
|
|
|
"Failed attempt ",
|
|
|
|
numTries,
|
|
|
|
" of ",
|
|
|
|
maxTries,
|
|
|
|
" to get lokid identity keys because: ",
|
|
|
|
e.what());
|
|
|
|
|
|
|
|
if (numTries == maxTries)
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
2020-05-20 11:41:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_identity = m_keyManager->identityKey;
|
2019-11-26 21:58:20 +00:00
|
|
|
}
|
2019-12-03 19:32:19 +00:00
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (_identity.IsZero())
|
2019-12-03 19:32:19 +00:00
|
|
|
return false;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (_encryption.IsZero())
|
2019-11-26 19:42:41 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
2018-12-10 16:26:46 +00:00
|
|
|
}
|
2018-01-29 14:27:24 +00:00
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
bool
|
2021-03-23 19:00:46 +00:00
|
|
|
Router::Configure(std::shared_ptr<Config> c, bool isSNode, std::shared_ptr<NodeDB> nodedb)
|
2018-12-10 16:26:46 +00:00
|
|
|
{
|
2021-03-02 02:06:20 +00:00
|
|
|
m_Config = std::move(c);
|
2020-08-27 12:43:53 +00:00
|
|
|
auto& conf = *m_Config;
|
2020-07-06 19:13:01 +00:00
|
|
|
whitelistRouters = conf.lokid.whitelistRouters;
|
|
|
|
if (whitelistRouters)
|
2021-06-06 12:32:23 +00:00
|
|
|
{
|
2021-02-03 18:12:21 +00:00
|
|
|
lokidRPCAddr = oxenmq::address(conf.lokid.lokidRPCAddr);
|
2021-06-06 12:32:23 +00:00
|
|
|
m_lokidRpcClient = std::make_shared<rpc::LokidRpcClient>(m_lmq, weak_from_this());
|
|
|
|
}
|
2020-07-06 19:13:01 +00:00
|
|
|
|
|
|
|
enableRPCServer = conf.api.m_enableRPCServer;
|
|
|
|
if (enableRPCServer)
|
2021-02-03 18:12:21 +00:00
|
|
|
rpcBindAddr = oxenmq::address(conf.api.m_rpcBindAddr);
|
2020-07-02 18:25:16 +00:00
|
|
|
|
2020-05-20 11:41:42 +00:00
|
|
|
if (not StartRpcServer())
|
|
|
|
throw std::runtime_error("Failed to start rpc server");
|
|
|
|
|
Config file improvements (#1397)
* 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>
2020-10-07 22:22:58 +00:00
|
|
|
if (conf.router.m_workerThreads > 0)
|
|
|
|
m_lmq->set_general_threads(conf.router.m_workerThreads);
|
|
|
|
|
2020-05-20 11:41:42 +00:00
|
|
|
m_lmq->start();
|
|
|
|
|
2021-03-02 02:06:20 +00:00
|
|
|
_nodedb = std::move(nodedb);
|
2020-06-11 11:44:02 +00:00
|
|
|
|
2020-10-06 13:44:51 +00:00
|
|
|
m_isServiceNode = conf.router.m_isRelay;
|
|
|
|
|
2020-05-20 11:41:42 +00:00
|
|
|
if (whitelistRouters)
|
|
|
|
{
|
2020-06-11 18:26:02 +00:00
|
|
|
m_lokidRpcClient->ConnectAsync(lokidRPCAddr);
|
2020-05-20 11:41:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// fetch keys
|
2021-03-23 19:00:46 +00:00
|
|
|
if (not m_keyManager->initialize(conf, true, isSNode))
|
2020-07-06 19:13:01 +00:00
|
|
|
throw std::runtime_error("KeyManager failed to initialize");
|
|
|
|
if (!FromConfig(conf))
|
|
|
|
throw std::runtime_error("FromConfig() failed");
|
|
|
|
|
2020-04-24 17:10:05 +00:00
|
|
|
if (not EnsureIdentity())
|
|
|
|
throw std::runtime_error("EnsureIdentity() failed");
|
|
|
|
return true;
|
2018-12-10 16:26:46 +00:00
|
|
|
}
|
2018-11-21 14:10:02 +00:00
|
|
|
|
2019-03-25 15:41:37 +00:00
|
|
|
/// called in disk worker thread
|
2019-05-18 18:46:49 +00:00
|
|
|
void
|
|
|
|
Router::HandleSaveRC() const
|
2019-03-25 15:41:37 +00:00
|
|
|
{
|
2019-05-18 18:46:49 +00:00
|
|
|
std::string fname = our_rc_file.string();
|
|
|
|
_rc.Write(fname.c_str());
|
2019-03-25 15:41:37 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
bool
|
|
|
|
Router::SaveRC()
|
2018-08-18 14:01:21 +00:00
|
|
|
{
|
2019-02-11 19:45:42 +00:00
|
|
|
LogDebug("verify RC signature");
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!_rc.Verify(Now()))
|
2018-12-10 16:26:46 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
Dump<MAX_RC_SIZE>(rc());
|
2019-02-11 19:45:42 +00:00
|
|
|
LogError("RC is invalid, not saving");
|
2018-12-10 16:26:46 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-03-06 01:04:39 +00:00
|
|
|
if (m_isServiceNode)
|
|
|
|
_nodedb->Put(_rc);
|
2020-06-30 16:02:29 +00:00
|
|
|
QueueDiskIO([&]() { HandleSaveRC(); });
|
2019-03-25 15:41:37 +00:00
|
|
|
return true;
|
2018-06-20 12:34:48 +00:00
|
|
|
}
|
2018-05-29 13:40:26 +00:00
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
bool
|
|
|
|
Router::IsServiceNode() const
|
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
return m_isServiceNode;
|
2018-12-10 16:26:46 +00:00
|
|
|
}
|
2018-05-30 20:56:47 +00:00
|
|
|
|
2022-09-28 14:15:45 +00:00
|
|
|
bool
|
|
|
|
Router::TooFewPeers() const
|
|
|
|
{
|
|
|
|
constexpr int KnownPeerWarningThreshold = 5;
|
|
|
|
return nodedb()->NumLoaded() < KnownPeerWarningThreshold;
|
|
|
|
}
|
|
|
|
|
2022-10-14 23:55:21 +00:00
|
|
|
std::optional<std::string>
|
|
|
|
Router::OxendErrorState() const
|
2022-09-28 14:15:45 +00:00
|
|
|
{
|
2022-10-14 23:55:21 +00:00
|
|
|
// If we're in the white or gray list then we *should* be establishing connections to other
|
|
|
|
// routers, so if we have almost no peers then something is almost certainly wrong.
|
|
|
|
if (LooksFunded() and TooFewPeers())
|
|
|
|
return "too few peer connections; lokinet is not adequately connected to the network";
|
|
|
|
return std::nullopt;
|
2022-09-28 14:15:45 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
void
|
|
|
|
Router::Close()
|
2018-05-26 18:31:45 +00:00
|
|
|
{
|
2020-08-21 19:09:13 +00:00
|
|
|
if (_onDown)
|
|
|
|
_onDown();
|
2019-02-11 19:45:42 +00:00
|
|
|
LogInfo("closing router");
|
2021-03-02 07:02:59 +00:00
|
|
|
_loop->stop();
|
2020-02-28 01:23:36 +00:00
|
|
|
_running.store(false);
|
2018-12-10 16:26:46 +00:00
|
|
|
}
|
|
|
|
|
2018-12-27 14:32:37 +00:00
|
|
|
bool
|
2020-04-07 18:38:56 +00:00
|
|
|
Router::ParseRoutingMessageBuffer(
|
|
|
|
const llarp_buffer_t& buf, routing::IMessageHandler* h, const PathID_t& rxid)
|
2018-12-27 14:32:37 +00:00
|
|
|
{
|
|
|
|
return inbound_routing_msg_parser.ParseMessageBuffer(buf, h, rxid, this);
|
|
|
|
}
|
|
|
|
|
2021-05-11 13:10:16 +00:00
|
|
|
bool
|
2021-06-07 20:35:06 +00:00
|
|
|
Router::LooksDecommissioned() const
|
2021-05-11 13:10:16 +00:00
|
|
|
{
|
|
|
|
return IsServiceNode() and whitelistRouters and _rcLookupHandler.HaveReceivedWhitelist()
|
2021-06-07 14:57:33 +00:00
|
|
|
and _rcLookupHandler.IsGreylisted(pubkey());
|
2021-05-11 13:10:16 +00:00
|
|
|
}
|
|
|
|
|
2022-05-03 17:37:57 +00:00
|
|
|
bool
|
2022-10-14 23:55:21 +00:00
|
|
|
Router::LooksFunded() const
|
2022-05-03 17:37:57 +00:00
|
|
|
{
|
|
|
|
return IsServiceNode() and whitelistRouters and _rcLookupHandler.HaveReceivedWhitelist()
|
2022-10-14 23:55:21 +00:00
|
|
|
and _rcLookupHandler.SessionIsAllowed(pubkey());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Router::LooksRegistered() const
|
|
|
|
{
|
|
|
|
return IsServiceNode() and whitelistRouters and _rcLookupHandler.HaveReceivedWhitelist()
|
|
|
|
and _rcLookupHandler.IsRegistered(pubkey());
|
2022-05-03 17:37:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Router::ShouldTestOtherRouters() const
|
|
|
|
{
|
|
|
|
if (not IsServiceNode())
|
|
|
|
return false;
|
|
|
|
if (not whitelistRouters)
|
|
|
|
return true;
|
|
|
|
if (not _rcLookupHandler.HaveReceivedWhitelist())
|
|
|
|
return false;
|
2022-05-03 20:05:22 +00:00
|
|
|
return _rcLookupHandler.SessionIsAllowed(pubkey());
|
2022-05-03 17:37:57 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
bool
|
2021-06-07 14:57:33 +00:00
|
|
|
Router::SessionToRouterAllowed(const RouterID& router) const
|
|
|
|
{
|
|
|
|
return _rcLookupHandler.SessionIsAllowed(router);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Router::PathToRouterAllowed(const RouterID& router) const
|
2018-11-28 14:58:38 +00:00
|
|
|
{
|
2021-06-07 20:35:06 +00:00
|
|
|
if (LooksDecommissioned())
|
2021-05-11 13:10:16 +00:00
|
|
|
{
|
2021-06-07 20:35:06 +00:00
|
|
|
// we are decom'd don't allow any paths outbound at all
|
2021-05-11 13:10:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
2021-06-07 14:57:33 +00:00
|
|
|
return _rcLookupHandler.PathIsAllowed(router);
|
2019-05-09 15:36:39 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
size_t
|
|
|
|
Router::NumberOfConnectedRouters() const
|
2018-09-14 13:43:42 +00:00
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
return _linkManager.NumberOfConnectedRouters();
|
2019-05-09 15:36:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
Router::NumberOfConnectedClients() const
|
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
return _linkManager.NumberOfConnectedClients();
|
2018-09-14 13:43:42 +00:00
|
|
|
}
|
2018-06-19 17:11:24 +00:00
|
|
|
|
2018-12-19 16:17:41 +00:00
|
|
|
bool
|
|
|
|
Router::UpdateOurRC(bool rotateKeys)
|
|
|
|
{
|
2019-02-11 19:45:42 +00:00
|
|
|
SecretKey nextOnionKey;
|
|
|
|
RouterContact nextRC = _rc;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (rotateKeys)
|
2018-12-19 16:17:41 +00:00
|
|
|
{
|
2019-05-28 19:45:08 +00:00
|
|
|
CryptoManager::instance()->encryption_keygen(nextOnionKey);
|
2019-01-29 13:20:27 +00:00
|
|
|
std::string f = encryption_keyfile.string();
|
2019-03-25 15:41:37 +00:00
|
|
|
// TODO: use disk worker
|
2020-04-07 18:38:56 +00:00
|
|
|
if (nextOnionKey.SaveToFile(f.c_str()))
|
2019-01-29 13:20:27 +00:00
|
|
|
{
|
2019-02-11 19:45:42 +00:00
|
|
|
nextRC.enckey = seckey_topublic(nextOnionKey);
|
2020-04-07 18:38:56 +00:00
|
|
|
_encryption = nextOnionKey;
|
2019-01-29 13:20:27 +00:00
|
|
|
}
|
2018-12-19 16:17:41 +00:00
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!nextRC.Sign(identity()))
|
2018-12-19 16:17:41 +00:00
|
|
|
return false;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!nextRC.Verify(time_now_ms(), false))
|
2019-08-28 11:38:32 +00:00
|
|
|
return false;
|
|
|
|
_rc = std::move(nextRC);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (rotateKeys)
|
2020-01-21 17:31:48 +00:00
|
|
|
{
|
|
|
|
// propagate RC by renegotiating sessions
|
2020-04-07 18:38:56 +00:00
|
|
|
ForEachPeer([](ILinkSession* s) {
|
|
|
|
if (s->RenegotiateSession())
|
2020-01-21 17:31:48 +00:00
|
|
|
LogInfo("renegotiated session");
|
|
|
|
else
|
|
|
|
LogWarn("failed to renegotiate session");
|
|
|
|
});
|
|
|
|
}
|
2020-06-04 21:02:05 +00:00
|
|
|
if (IsServiceNode())
|
|
|
|
return SaveRC();
|
|
|
|
else
|
|
|
|
return true;
|
2019-03-25 15:41:37 +00:00
|
|
|
}
|
2018-12-19 16:17:41 +00:00
|
|
|
|
2019-07-12 17:21:29 +00:00
|
|
|
bool
|
2020-07-06 19:13:01 +00:00
|
|
|
Router::FromConfig(const Config& conf)
|
2019-02-11 14:43:48 +00:00
|
|
|
{
|
2019-07-07 11:29:44 +00:00
|
|
|
// Set netid before anything else
|
2020-07-06 19:13:01 +00:00
|
|
|
if (!conf.router.m_netId.empty() && strcmp(conf.router.m_netId.c_str(), llarp::DEFAULT_NETID))
|
2019-02-11 14:43:48 +00:00
|
|
|
{
|
2020-07-06 19:13:01 +00:00
|
|
|
const auto& netid = conf.router.m_netId;
|
2020-04-07 20:41:11 +00:00
|
|
|
llarp::LogWarn(
|
|
|
|
"!!!! you have manually set netid to be '",
|
|
|
|
netid,
|
|
|
|
"' which does not equal '",
|
|
|
|
llarp::DEFAULT_NETID,
|
|
|
|
"' you will run as a different network, good luck "
|
|
|
|
"and don't forget: something something MUH traffic "
|
|
|
|
"shape correlation !!!!");
|
|
|
|
NetID::DefaultValue() = NetID(reinterpret_cast<const byte_t*>(netid.c_str()));
|
2019-07-07 11:29:44 +00:00
|
|
|
// reset netid in our rc
|
|
|
|
_rc.netID = llarp::NetID();
|
2019-02-11 14:43:48 +00:00
|
|
|
}
|
2019-07-07 11:29:44 +00:00
|
|
|
|
2019-07-12 17:21:29 +00:00
|
|
|
// Router config
|
2020-07-06 19:13:01 +00:00
|
|
|
_rc.SetNick(conf.router.m_nickname);
|
|
|
|
_outboundSessionMaker.maxConnectedRouters = conf.router.m_maxConnectedRouters;
|
|
|
|
_outboundSessionMaker.minConnectedRouters = conf.router.m_minConnectedRouters;
|
2020-06-04 18:38:35 +00:00
|
|
|
|
|
|
|
encryption_keyfile = m_keyManager->m_encKeyPath;
|
|
|
|
our_rc_file = m_keyManager->m_rcPath;
|
|
|
|
transport_keyfile = m_keyManager->m_transportKeyPath;
|
|
|
|
ident_keyfile = m_keyManager->m_idKeyPath;
|
|
|
|
|
2022-07-09 15:05:52 +00:00
|
|
|
if (auto maybe_ip = conf.links.PublicAddress)
|
|
|
|
_ourAddress = var::visit([](auto&& ip) { return SockAddr{ip}; }, *maybe_ip);
|
|
|
|
else if (auto maybe_ip = conf.router.PublicIP)
|
|
|
|
_ourAddress = var::visit([](auto&& ip) { return SockAddr{ip}; }, *maybe_ip);
|
|
|
|
|
|
|
|
if (_ourAddress)
|
|
|
|
{
|
|
|
|
if (auto maybe_port = conf.links.PublicPort)
|
|
|
|
_ourAddress->setPort(*maybe_port);
|
|
|
|
else if (auto maybe_port = conf.router.PublicPort)
|
|
|
|
_ourAddress->setPort(*maybe_port);
|
|
|
|
else
|
|
|
|
throw std::runtime_error{"public ip provided without public port"};
|
|
|
|
}
|
2020-03-27 22:15:26 +00:00
|
|
|
|
2020-07-06 19:13:01 +00:00
|
|
|
RouterContact::BlockBogons = conf.router.m_blockBogons;
|
2019-08-26 23:29:17 +00:00
|
|
|
|
2019-07-12 17:21:29 +00:00
|
|
|
// Lokid Config
|
2020-07-06 19:13:01 +00:00
|
|
|
whitelistRouters = conf.lokid.whitelistRouters;
|
2021-02-03 18:12:21 +00:00
|
|
|
lokidRPCAddr = oxenmq::address(conf.lokid.lokidRPCAddr);
|
2019-07-12 17:21:29 +00:00
|
|
|
|
Config file improvements (#1397)
* 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>
2020-10-07 22:22:58 +00:00
|
|
|
m_isServiceNode = conf.router.m_isRelay;
|
2020-06-04 18:38:35 +00:00
|
|
|
|
2020-10-30 23:32:00 +00:00
|
|
|
auto& networkConfig = conf.network;
|
2020-05-04 16:33:44 +00:00
|
|
|
|
2020-04-27 15:24:05 +00:00
|
|
|
/// build a set of strictConnectPubkeys (
|
|
|
|
/// TODO: make this consistent with config -- do we support multiple strict connections
|
|
|
|
// or not?
|
2021-02-02 14:35:40 +00:00
|
|
|
std::unordered_set<RouterID> strictConnectPubkeys;
|
2020-04-27 15:24:05 +00:00
|
|
|
if (not networkConfig.m_strictConnect.empty())
|
2019-02-11 14:43:48 +00:00
|
|
|
{
|
2020-04-27 15:24:05 +00:00
|
|
|
const auto& val = networkConfig.m_strictConnect;
|
2020-04-07 20:41:11 +00:00
|
|
|
if (IsServiceNode())
|
2020-04-24 17:10:05 +00:00
|
|
|
throw std::runtime_error("cannot use strict-connect option as service node");
|
2021-04-12 11:39:07 +00:00
|
|
|
strictConnectPubkeys.insert(val.begin(), val.end());
|
2019-02-11 14:43:48 +00:00
|
|
|
}
|
2019-07-02 21:28:28 +00:00
|
|
|
|
2020-07-06 19:13:01 +00:00
|
|
|
std::vector<fs::path> configRouters = conf.connect.routers;
|
2020-04-07 20:41:11 +00:00
|
|
|
configRouters.insert(
|
2021-04-02 15:10:37 +00:00
|
|
|
configRouters.end(), conf.bootstrap.files.begin(), conf.bootstrap.files.end());
|
2020-04-02 15:13:39 +00:00
|
|
|
|
|
|
|
// if our conf had no bootstrap files specified, try the default location of
|
|
|
|
// <DATA_DIR>/bootstrap.signed. If this isn't present, leave a useful error message
|
2022-10-04 19:19:42 +00:00
|
|
|
// TODO: use constant
|
|
|
|
fs::path defaultBootstrapFile = conf.router.m_dataDir / "bootstrap.signed";
|
2021-04-02 15:10:37 +00:00
|
|
|
if (configRouters.empty() and conf.bootstrap.routers.empty())
|
2020-04-02 15:13:39 +00:00
|
|
|
{
|
|
|
|
if (fs::exists(defaultBootstrapFile))
|
2020-06-08 12:42:10 +00:00
|
|
|
{
|
2020-04-02 15:13:39 +00:00
|
|
|
configRouters.push_back(defaultBootstrapFile);
|
2020-06-08 12:42:10 +00:00
|
|
|
}
|
2020-04-02 15:13:39 +00:00
|
|
|
}
|
|
|
|
|
2019-12-06 17:32:46 +00:00
|
|
|
BootstrapList b_list;
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& router : configRouters)
|
2019-02-11 14:43:48 +00:00
|
|
|
{
|
2022-09-27 17:00:27 +00:00
|
|
|
b_list.AddFromFile(router);
|
2019-02-11 14:43:48 +00:00
|
|
|
}
|
|
|
|
|
2021-04-02 15:10:37 +00:00
|
|
|
for (const auto& rc : conf.bootstrap.routers)
|
|
|
|
{
|
|
|
|
b_list.emplace(rc);
|
|
|
|
}
|
|
|
|
|
2022-09-27 17:00:27 +00:00
|
|
|
// in case someone has an old bootstrap file and is trying to use a bootstrap
|
|
|
|
// that no longer exists
|
|
|
|
for (auto rc_itr = b_list.begin(); rc_itr != b_list.end();)
|
2019-12-06 17:32:46 +00:00
|
|
|
{
|
2022-09-27 17:00:27 +00:00
|
|
|
if (rc_itr->IsObsoleteBootstrap())
|
|
|
|
b_list.erase(rc_itr);
|
|
|
|
else
|
|
|
|
rc_itr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto verifyRCs = [&]() {
|
|
|
|
for (auto& rc : b_list)
|
2019-12-06 17:32:46 +00:00
|
|
|
{
|
2022-09-27 17:00:27 +00:00
|
|
|
if (rc.IsObsoleteBootstrap())
|
|
|
|
{
|
2022-10-04 19:19:42 +00:00
|
|
|
log::warning(logcat, "ignoring obsolete boostrap RC: {}", RouterID(rc.pubkey));
|
2022-09-27 17:00:27 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (not rc.Verify(Now()))
|
|
|
|
{
|
|
|
|
log::warning(logcat, "ignoring invalid RC: {}", RouterID(rc.pubkey));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
bootstrapRCList.emplace(std::move(rc));
|
2019-12-06 17:32:46 +00:00
|
|
|
}
|
2022-09-27 17:00:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
verifyRCs();
|
|
|
|
|
2021-04-02 15:10:37 +00:00
|
|
|
if (bootstrapRCList.empty() and not conf.bootstrap.seednode)
|
|
|
|
{
|
2022-10-04 19:19:42 +00:00
|
|
|
auto fallbacks = llarp::load_bootstrap_fallbacks();
|
|
|
|
if (auto itr = fallbacks.find(_rc.netID.ToString()); itr != fallbacks.end())
|
2022-09-27 17:00:27 +00:00
|
|
|
{
|
2022-10-04 19:19:42 +00:00
|
|
|
b_list = itr->second;
|
2022-09-27 17:00:27 +00:00
|
|
|
|
|
|
|
verifyRCs();
|
|
|
|
}
|
2022-10-04 19:19:42 +00:00
|
|
|
if (bootstrapRCList.empty()
|
|
|
|
and not conf.bootstrap.seednode) // empty after trying fallback, if set
|
|
|
|
{
|
|
|
|
log::error(
|
|
|
|
logcat,
|
|
|
|
"No bootstrap routers were loaded. The default bootstrap file {} does not exist, and "
|
|
|
|
"loading fallback bootstrap RCs failed.",
|
|
|
|
defaultBootstrapFile);
|
|
|
|
throw std::runtime_error("No bootstrap nodes available.");
|
|
|
|
}
|
2021-04-02 15:10:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (conf.bootstrap.seednode)
|
|
|
|
LogInfo("we are a seed node");
|
|
|
|
else
|
|
|
|
LogInfo("Loaded ", bootstrapRCList.size(), " bootstrap routers");
|
2019-12-06 17:32:46 +00:00
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
// Init components after relevant config settings loaded
|
2021-11-09 23:46:09 +00:00
|
|
|
_outboundMessageHandler.Init(this);
|
2020-04-07 18:38:56 +00:00
|
|
|
_outboundSessionMaker.Init(
|
2020-06-15 17:37:57 +00:00
|
|
|
this,
|
2020-06-11 11:44:02 +00:00
|
|
|
&_linkManager,
|
|
|
|
&_rcLookupHandler,
|
|
|
|
&_routerProfiling,
|
2021-03-02 07:02:59 +00:00
|
|
|
_loop,
|
2020-06-11 11:44:02 +00:00
|
|
|
util::memFn(&AbstractRouter::QueueWork, this));
|
2019-06-26 21:39:29 +00:00
|
|
|
_linkManager.Init(&_outboundSessionMaker);
|
2020-04-07 18:38:56 +00:00
|
|
|
_rcLookupHandler.Init(
|
|
|
|
_dht,
|
|
|
|
_nodedb,
|
2021-03-02 07:02:59 +00:00
|
|
|
_loop,
|
2020-06-11 11:44:02 +00:00
|
|
|
util::memFn(&AbstractRouter::QueueWork, this),
|
2020-04-07 18:38:56 +00:00
|
|
|
&_linkManager,
|
|
|
|
&_hiddenServiceContext,
|
|
|
|
strictConnectPubkeys,
|
|
|
|
bootstrapRCList,
|
|
|
|
whitelistRouters,
|
|
|
|
m_isServiceNode);
|
|
|
|
|
2022-07-09 15:05:52 +00:00
|
|
|
// inbound links
|
|
|
|
InitInboundLinks();
|
|
|
|
// outbound links
|
|
|
|
InitOutboundLinks();
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2020-11-03 15:54:55 +00:00
|
|
|
// profiling
|
|
|
|
_profilesFile = conf.router.m_dataDir / "profiles.dat";
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
// Network config
|
Config file improvements (#1397)
* 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>
2020-10-07 22:22:58 +00:00
|
|
|
if (conf.network.m_enableProfiling.value_or(false))
|
2018-12-19 17:48:29 +00:00
|
|
|
{
|
2020-11-03 15:54:55 +00:00
|
|
|
LogInfo("router profiling enabled");
|
|
|
|
if (not fs::exists(_profilesFile))
|
|
|
|
{
|
|
|
|
LogInfo("no profiles file at ", _profilesFile, " skipping");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LogInfo("loading router profiles from ", _profilesFile);
|
|
|
|
routerProfiling().Load(_profilesFile);
|
|
|
|
}
|
2018-12-19 17:48:29 +00:00
|
|
|
}
|
Config file improvements (#1397)
* 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>
2020-10-07 22:22:58 +00:00
|
|
|
else
|
2018-12-19 16:17:41 +00:00
|
|
|
{
|
Config file improvements (#1397)
* 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>
2020-10-07 22:22:58 +00:00
|
|
|
routerProfiling().Disable();
|
|
|
|
LogInfo("router profiling disabled");
|
2018-12-19 16:17:41 +00:00
|
|
|
}
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
// API config
|
2020-05-04 16:58:46 +00:00
|
|
|
if (not IsServiceNode())
|
|
|
|
{
|
2020-07-06 19:13:01 +00:00
|
|
|
hiddenServiceContext().AddEndpoint(conf);
|
2020-05-04 16:58:46 +00:00
|
|
|
}
|
2019-06-26 21:39:29 +00:00
|
|
|
|
|
|
|
// Logging config
|
2022-07-16 00:41:14 +00:00
|
|
|
|
|
|
|
// Backwards compat: before 0.9.10 we used `type=file` with `file=|-|stdout` for print mode
|
|
|
|
auto log_type = conf.logging.m_logType;
|
|
|
|
if (log_type == log::Type::File
|
|
|
|
&& (conf.logging.m_logFile == "stdout" || conf.logging.m_logFile == "-"
|
|
|
|
|| conf.logging.m_logFile.empty()))
|
|
|
|
log_type = log::Type::Print;
|
|
|
|
|
2022-07-18 15:59:13 +00:00
|
|
|
if (log::get_level_default() != log::Level::off)
|
|
|
|
log::reset_level(conf.logging.m_logLevel);
|
2022-07-21 18:02:23 +00:00
|
|
|
log::clear_sinks();
|
2022-07-16 00:41:14 +00:00
|
|
|
log::add_sink(log_type, conf.logging.m_logFile);
|
2018-12-19 17:48:29 +00:00
|
|
|
|
2022-09-28 16:37:19 +00:00
|
|
|
// re-add rpc log sink if rpc enabled, else free it
|
|
|
|
if (enableRPCServer and llarp::logRingBuffer)
|
|
|
|
log::add_sink(llarp::logRingBuffer, llarp::log::DEFAULT_PATTERN_MONO);
|
|
|
|
else
|
|
|
|
llarp::logRingBuffer = nullptr;
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
return true;
|
2019-06-10 12:47:21 +00:00
|
|
|
}
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
bool
|
|
|
|
Router::CheckRenegotiateValid(RouterContact newrc, RouterContact oldrc)
|
2019-03-31 15:09:59 +00:00
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
return _rcLookupHandler.CheckRenegotiateValid(newrc, oldrc);
|
2019-03-31 15:09:59 +00:00
|
|
|
}
|
|
|
|
|
2019-04-03 19:05:44 +00:00
|
|
|
bool
|
2019-05-09 15:36:39 +00:00
|
|
|
Router::IsBootstrapNode(const RouterID r) const
|
2019-04-03 19:05:44 +00:00
|
|
|
{
|
2019-05-09 15:36:39 +00:00
|
|
|
return std::count_if(
|
2020-04-07 18:38:56 +00:00
|
|
|
bootstrapRCList.begin(),
|
|
|
|
bootstrapRCList.end(),
|
|
|
|
[r](const RouterContact& rc) -> bool { return rc.pubkey == r; })
|
2019-05-09 15:36:39 +00:00
|
|
|
> 0;
|
2019-04-03 19:05:44 +00:00
|
|
|
}
|
2019-04-05 14:58:22 +00:00
|
|
|
|
2019-07-15 16:56:09 +00:00
|
|
|
bool
|
|
|
|
Router::ShouldReportStats(llarp_time_t now) const
|
|
|
|
{
|
2020-02-24 19:40:45 +00:00
|
|
|
static constexpr auto ReportStatsInterval = 1h;
|
2019-07-15 16:56:09 +00:00
|
|
|
return now - m_LastStatsReport > ReportStatsInterval;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Router::ReportStats()
|
|
|
|
{
|
|
|
|
const auto now = Now();
|
2021-02-02 14:35:40 +00:00
|
|
|
LogInfo(nodedb()->NumLoaded(), " RCs loaded");
|
2019-07-15 16:56:09 +00:00
|
|
|
LogInfo(bootstrapRCList.size(), " bootstrap peers");
|
|
|
|
LogInfo(NumberOfConnectedRouters(), " router connections");
|
2020-04-07 18:38:56 +00:00
|
|
|
if (IsServiceNode())
|
2019-07-15 16:56:09 +00:00
|
|
|
{
|
|
|
|
LogInfo(NumberOfConnectedClients(), " client connections");
|
2020-02-25 17:05:13 +00:00
|
|
|
LogInfo(_rc.Age(now), " since we last updated our RC");
|
|
|
|
LogInfo(_rc.TimeUntilExpires(now), " until our RC expires");
|
2019-07-15 16:56:09 +00:00
|
|
|
}
|
2020-10-09 15:40:04 +00:00
|
|
|
if (m_LastStatsReport > 0s)
|
|
|
|
LogInfo(now - m_LastStatsReport, " last reported stats");
|
2019-07-15 16:56:09 +00:00
|
|
|
m_LastStatsReport = now;
|
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
void
|
|
|
|
Router::Tick()
|
2018-06-19 17:11:24 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (_stopping)
|
2019-04-23 18:29:42 +00:00
|
|
|
return;
|
2019-02-11 19:45:42 +00:00
|
|
|
// LogDebug("tick router");
|
2019-11-05 16:58:53 +00:00
|
|
|
const auto now = Now();
|
2022-01-27 15:59:04 +00:00
|
|
|
if (const auto delta = now - _lastTick; _lastTick != 0s and delta > TimeskipDetectedDuration)
|
|
|
|
{
|
|
|
|
// we detected a time skip into the futre, thaw the network
|
|
|
|
LogWarn("Timeskip of ", delta, " detected. Resetting network state");
|
|
|
|
Thaw();
|
|
|
|
}
|
2018-12-19 17:48:29 +00:00
|
|
|
|
2019-12-07 19:21:26 +00:00
|
|
|
#if defined(WITH_SYSTEMD)
|
2020-02-25 22:32:57 +00:00
|
|
|
{
|
2022-07-16 00:41:14 +00:00
|
|
|
std::string status;
|
|
|
|
auto out = std::back_inserter(status);
|
|
|
|
out = fmt::format_to(out, "WATCHDOG=1\nSTATUS=v{}", llarp::VERSION_STR);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (IsServiceNode())
|
2020-02-25 22:32:57 +00:00
|
|
|
{
|
2022-07-16 00:41:14 +00:00
|
|
|
out = fmt::format_to(
|
|
|
|
out,
|
|
|
|
" snode | known/svc/clients: {}/{}/{}",
|
|
|
|
nodedb()->NumLoaded(),
|
|
|
|
NumberOfConnectedRouters(),
|
|
|
|
NumberOfConnectedClients());
|
|
|
|
out = fmt::format_to(
|
|
|
|
out,
|
|
|
|
" | {} active paths | block {} ",
|
|
|
|
pathContext().CurrentTransitPaths(),
|
|
|
|
(m_lokidRpcClient ? m_lokidRpcClient->BlockHeight() : 0));
|
|
|
|
out = fmt::format_to(
|
|
|
|
out,
|
|
|
|
" | gossip: (next/last) {} / ",
|
|
|
|
time_delta<std::chrono::seconds>{_rcGossiper.NextGossipAt()});
|
2022-05-04 14:37:35 +00:00
|
|
|
if (auto maybe = _rcGossiper.LastGossipAt())
|
2022-07-16 00:41:14 +00:00
|
|
|
out = fmt::format_to(out, "{}", time_delta<std::chrono::seconds>{*maybe});
|
2022-05-04 14:37:35 +00:00
|
|
|
else
|
2022-07-16 00:41:14 +00:00
|
|
|
out = fmt::format_to(out, "never");
|
2020-02-25 22:32:57 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-07-16 00:41:14 +00:00
|
|
|
out = fmt::format_to(
|
|
|
|
out,
|
|
|
|
" client | known/connected: {}/{}",
|
|
|
|
nodedb()->NumLoaded(),
|
|
|
|
NumberOfConnectedRouters());
|
|
|
|
|
2022-01-13 21:24:08 +00:00
|
|
|
if (auto ep = hiddenServiceContext().GetDefault())
|
|
|
|
{
|
2022-07-16 00:41:14 +00:00
|
|
|
out = fmt::format_to(
|
|
|
|
out,
|
|
|
|
" | paths/endpoints {}/{}",
|
|
|
|
pathContext().CurrentOwnedPaths(),
|
|
|
|
ep->UniqueEndpoints());
|
|
|
|
|
|
|
|
if (auto success_rate = ep->CurrentBuildStats().SuccessRatio(); success_rate < 0.5)
|
2022-01-13 21:24:08 +00:00
|
|
|
{
|
2022-07-16 00:41:14 +00:00
|
|
|
out = fmt::format_to(
|
|
|
|
out, " [ !!! Low Build Success Rate ({:.1f}%) !!! ]", (100.0 * success_rate));
|
2022-01-13 21:24:08 +00:00
|
|
|
}
|
|
|
|
};
|
2020-02-25 22:32:57 +00:00
|
|
|
}
|
|
|
|
::sd_notify(0, status.c_str());
|
|
|
|
}
|
2019-12-07 19:21:26 +00:00
|
|
|
#endif
|
|
|
|
|
2021-05-05 12:21:39 +00:00
|
|
|
m_PathBuildLimiter.Decay(now);
|
|
|
|
|
2019-03-04 17:03:18 +00:00
|
|
|
routerProfiling().Tick();
|
2019-06-10 12:47:21 +00:00
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (ShouldReportStats(now))
|
2019-07-15 16:56:09 +00:00
|
|
|
{
|
|
|
|
ReportStats();
|
|
|
|
}
|
|
|
|
|
2020-02-24 19:40:45 +00:00
|
|
|
_rcGossiper.Decay(now);
|
2020-01-30 17:23:16 +00:00
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
_rcLookupHandler.PeriodicUpdate(now);
|
2019-07-15 16:56:09 +00:00
|
|
|
|
2021-05-11 13:10:16 +00:00
|
|
|
const bool gotWhitelist = _rcLookupHandler.HaveReceivedWhitelist();
|
2019-07-15 16:56:09 +00:00
|
|
|
const bool isSvcNode = IsServiceNode();
|
2021-06-07 20:35:06 +00:00
|
|
|
const bool decom = LooksDecommissioned();
|
2022-05-03 20:05:22 +00:00
|
|
|
bool shouldGossip = isSvcNode and whitelistRouters and gotWhitelist
|
|
|
|
and _rcLookupHandler.SessionIsAllowed(pubkey());
|
2019-07-15 16:56:09 +00:00
|
|
|
|
2022-05-03 20:05:22 +00:00
|
|
|
if (isSvcNode
|
|
|
|
and (_rc.ExpiresSoon(now, std::chrono::milliseconds(randint() % 10000)) or (now - _rc.last_updated) > rcRegenInterval))
|
2018-12-19 17:48:29 +00:00
|
|
|
{
|
2020-06-04 21:02:05 +00:00
|
|
|
LogInfo("regenerating RC");
|
2022-05-03 20:05:22 +00:00
|
|
|
if (UpdateOurRC())
|
|
|
|
{
|
|
|
|
// our rc changed so we should gossip it
|
|
|
|
shouldGossip = true;
|
|
|
|
// remove our replay entry so it goes out
|
|
|
|
_rcGossiper.Forget(pubkey());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
LogError("failed to update our RC");
|
2020-06-04 21:02:05 +00:00
|
|
|
}
|
2022-05-03 20:05:22 +00:00
|
|
|
if (shouldGossip)
|
2020-06-04 21:02:05 +00:00
|
|
|
{
|
2021-06-07 20:15:17 +00:00
|
|
|
// if we have the whitelist enabled, we have fetched the list and we are in either
|
|
|
|
// the white or grey list, we want to gossip our RC
|
2020-06-04 21:02:05 +00:00
|
|
|
GossipRCIfNeeded(_rc);
|
2020-01-30 17:23:16 +00:00
|
|
|
}
|
2020-03-08 12:09:48 +00:00
|
|
|
// remove RCs for nodes that are no longer allowed by network policy
|
2020-04-07 18:38:56 +00:00
|
|
|
nodedb()->RemoveIf([&](const RouterContact& rc) -> bool {
|
2020-03-09 15:08:56 +00:00
|
|
|
// don't purge bootstrap nodes from nodedb
|
2020-04-07 18:38:56 +00:00
|
|
|
if (IsBootstrapNode(rc.pubkey))
|
2022-07-26 14:26:35 +00:00
|
|
|
{
|
2022-10-14 23:37:19 +00:00
|
|
|
log::trace(logcat, "Not removing {}: is bootstrap node", rc.pubkey);
|
2020-03-08 12:09:48 +00:00
|
|
|
return false;
|
2022-07-26 14:26:35 +00:00
|
|
|
}
|
2020-03-09 15:04:28 +00:00
|
|
|
// if for some reason we stored an RC that isn't a valid router
|
|
|
|
// purge this entry
|
2020-04-07 18:38:56 +00:00
|
|
|
if (not rc.IsPublicRouter())
|
2022-07-26 14:26:35 +00:00
|
|
|
{
|
|
|
|
log::debug(logcat, "Removing {}: not a valid router", rc.pubkey);
|
2020-03-08 12:09:48 +00:00
|
|
|
return true;
|
2022-07-26 14:26:35 +00:00
|
|
|
}
|
2022-07-18 17:11:57 +00:00
|
|
|
/// clear out a fully expired RC
|
|
|
|
if (rc.IsExpired(now))
|
2022-07-26 14:26:35 +00:00
|
|
|
{
|
|
|
|
log::debug(logcat, "Removing {}: RC is expired", rc.pubkey);
|
2022-07-18 17:11:57 +00:00
|
|
|
return true;
|
2022-07-26 14:26:35 +00:00
|
|
|
}
|
2022-07-26 14:26:07 +00:00
|
|
|
// clients have no notion of a whilelist
|
2020-03-08 12:12:23 +00:00
|
|
|
// we short circuit logic here so we dont remove
|
|
|
|
// routers that are not whitelisted for first hops
|
2020-04-07 18:38:56 +00:00
|
|
|
if (not isSvcNode)
|
2022-07-26 14:26:35 +00:00
|
|
|
{
|
|
|
|
log::trace(logcat, "Not removing {}: we are a client and it looks fine", rc.pubkey);
|
2020-03-08 12:09:48 +00:00
|
|
|
return false;
|
2022-07-26 14:26:35 +00:00
|
|
|
}
|
|
|
|
|
2020-03-09 15:04:28 +00:00
|
|
|
// if we have a whitelist enabled and we don't
|
|
|
|
// have the whitelist yet don't remove the entry
|
2020-04-07 18:38:56 +00:00
|
|
|
if (whitelistRouters and not gotWhitelist)
|
2022-07-26 14:26:35 +00:00
|
|
|
{
|
|
|
|
log::debug(logcat, "Skipping check on {}: don't have whitelist yet", rc.pubkey);
|
2020-03-09 15:04:28 +00:00
|
|
|
return false;
|
2022-07-26 14:26:35 +00:00
|
|
|
}
|
2020-03-09 15:04:28 +00:00
|
|
|
// if we have no whitelist enabled or we have
|
|
|
|
// the whitelist enabled and we got the whitelist
|
|
|
|
// check against the whitelist and remove if it's not
|
2020-03-09 15:05:40 +00:00
|
|
|
// in the whitelist OR if there is no whitelist don't remove
|
2022-08-07 01:22:06 +00:00
|
|
|
if (gotWhitelist and not _rcLookupHandler.SessionIsAllowed(rc.pubkey))
|
2022-07-26 14:26:35 +00:00
|
|
|
{
|
|
|
|
log::debug(logcat, "Removing {}: not a valid router", rc.pubkey);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2020-03-08 12:09:48 +00:00
|
|
|
});
|
2019-02-25 12:46:40 +00:00
|
|
|
|
2020-11-10 14:24:58 +00:00
|
|
|
// find all deregistered relays
|
2021-03-09 18:39:40 +00:00
|
|
|
std::unordered_set<PubKey> closePeers;
|
2020-11-10 14:24:58 +00:00
|
|
|
|
|
|
|
_linkManager.ForEachPeer([&](auto session) {
|
|
|
|
if (whitelistRouters and not gotWhitelist)
|
|
|
|
return;
|
|
|
|
if (not session)
|
|
|
|
return;
|
|
|
|
const auto pk = session->GetPubKey();
|
2021-06-07 14:57:33 +00:00
|
|
|
if (session->IsRelay() and not _rcLookupHandler.SessionIsAllowed(pk))
|
2020-11-10 14:24:58 +00:00
|
|
|
{
|
|
|
|
closePeers.emplace(pk);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// mark peers as de-registered
|
|
|
|
for (auto& peer : closePeers)
|
|
|
|
_linkManager.DeregisterPeer(std::move(peer));
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
_linkManager.CheckPersistingSessions(now);
|
2018-12-10 16:26:46 +00:00
|
|
|
|
2019-12-03 17:03:19 +00:00
|
|
|
size_t connected = NumberOfConnectedRouters();
|
2020-04-07 18:38:56 +00:00
|
|
|
if (not isSvcNode)
|
2019-12-03 17:03:19 +00:00
|
|
|
{
|
|
|
|
connected += _linkManager.NumberOfPendingConnections();
|
|
|
|
}
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
const int interval = isSvcNode ? 5 : 2;
|
2020-01-18 20:46:22 +00:00
|
|
|
const auto timepoint_now = Clock_t::now();
|
2021-06-07 20:35:06 +00:00
|
|
|
if (timepoint_now >= m_NextExploreAt and not decom)
|
2020-01-18 20:46:22 +00:00
|
|
|
{
|
2020-01-18 20:55:50 +00:00
|
|
|
_rcLookupHandler.ExploreNetwork();
|
2020-01-18 20:46:22 +00:00
|
|
|
m_NextExploreAt = timepoint_now + std::chrono::seconds(interval);
|
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
size_t connectToNum = _outboundSessionMaker.minConnectedRouters;
|
2019-09-03 15:56:56 +00:00
|
|
|
const auto strictConnect = _rcLookupHandler.NumberOfStrictConnectRouters();
|
2020-04-07 18:38:56 +00:00
|
|
|
if (strictConnect > 0 && connectToNum > strictConnect)
|
2018-12-18 17:37:59 +00:00
|
|
|
{
|
2019-09-03 15:56:56 +00:00
|
|
|
connectToNum = strictConnect;
|
|
|
|
}
|
|
|
|
|
2022-10-17 12:33:50 +00:00
|
|
|
if (isSvcNode and now >= m_NextDecommissionWarn)
|
2021-05-11 13:10:16 +00:00
|
|
|
{
|
2022-09-27 13:36:38 +00:00
|
|
|
constexpr auto DecommissionWarnInterval = 5min;
|
2022-10-14 23:55:21 +00:00
|
|
|
if (auto registered = LooksRegistered(), funded = LooksFunded();
|
|
|
|
not(registered and funded and not decom))
|
2022-09-27 17:00:27 +00:00
|
|
|
{
|
2022-10-14 23:55:21 +00:00
|
|
|
// complain about being deregistered/decommed/unfunded
|
|
|
|
log::error(
|
|
|
|
logcat,
|
|
|
|
"We are running as a service node but we seem to be {}",
|
|
|
|
not registered ? "deregistered"
|
|
|
|
: decom ? "decommissioned"
|
|
|
|
: "not fully staked");
|
2022-09-27 17:00:27 +00:00
|
|
|
m_NextDecommissionWarn = now + DecommissionWarnInterval;
|
|
|
|
}
|
2022-10-17 12:33:50 +00:00
|
|
|
else if (TooFewPeers())
|
2022-09-27 17:00:27 +00:00
|
|
|
{
|
2022-09-28 14:15:45 +00:00
|
|
|
log::error(
|
|
|
|
logcat,
|
|
|
|
"We appear to be an active service node, but have only {} known peers.",
|
|
|
|
nodedb()->NumLoaded());
|
2022-09-27 17:00:27 +00:00
|
|
|
m_NextDecommissionWarn = now + DecommissionWarnInterval;
|
|
|
|
}
|
2021-05-11 13:10:16 +00:00
|
|
|
}
|
2022-04-28 22:28:55 +00:00
|
|
|
|
2022-10-17 23:05:30 +00:00
|
|
|
// if we need more sessions to routers and we are not a service node kicked from the network or
|
|
|
|
// we are a client we shall connect out to others
|
2022-10-17 12:33:50 +00:00
|
|
|
if (connected < connectToNum and (LooksFunded() or not isSvcNode))
|
2019-09-03 15:56:56 +00:00
|
|
|
{
|
|
|
|
size_t dlt = connectToNum - connected;
|
2021-04-05 23:09:45 +00:00
|
|
|
LogDebug("connecting to ", dlt, " random routers to keep alive");
|
2019-12-09 15:17:02 +00:00
|
|
|
_outboundSessionMaker.ConnectToRandomRouters(dlt);
|
2018-08-14 21:17:18 +00:00
|
|
|
}
|
2019-03-25 12:52:32 +00:00
|
|
|
|
2019-11-05 16:58:53 +00:00
|
|
|
_hiddenServiceContext.Tick(now);
|
2019-02-11 19:45:42 +00:00
|
|
|
_exitContext.Tick(now);
|
2019-11-05 16:58:53 +00:00
|
|
|
|
2020-01-14 17:01:41 +00:00
|
|
|
// save profiles
|
2021-04-02 16:08:06 +00:00
|
|
|
if (routerProfiling().ShouldSave(now) and m_Config->network.m_saveProfiles)
|
2019-03-25 15:41:37 +00:00
|
|
|
{
|
2020-11-03 15:54:55 +00:00
|
|
|
QueueDiskIO([&]() { routerProfiling().Save(_profilesFile); });
|
2019-03-25 15:41:37 +00:00
|
|
|
}
|
2021-02-02 14:35:40 +00:00
|
|
|
|
|
|
|
_nodedb->Tick(now);
|
2020-05-26 17:03:21 +00:00
|
|
|
|
2020-06-04 16:00:30 +00:00
|
|
|
if (m_peerDb)
|
|
|
|
{
|
|
|
|
// TODO: throttle this?
|
2022-05-03 17:37:57 +00:00
|
|
|
// TODO: need to capture session stats when session terminates / is removed from link
|
|
|
|
// manager
|
2020-06-04 16:00:30 +00:00
|
|
|
_linkManager.updatePeerDb(m_peerDb);
|
|
|
|
|
|
|
|
if (m_peerDb->shouldFlush(now))
|
|
|
|
{
|
2020-09-23 18:44:39 +00:00
|
|
|
LogDebug("Queing database flush...");
|
2021-05-11 13:10:16 +00:00
|
|
|
QueueDiskIO([this]() {
|
|
|
|
try
|
|
|
|
{
|
|
|
|
m_peerDb->flushDatabase();
|
|
|
|
}
|
|
|
|
catch (std::exception& ex)
|
|
|
|
{
|
|
|
|
LogError("Could not flush peer stats database: ", ex.what());
|
|
|
|
}
|
|
|
|
});
|
2020-06-04 16:00:30 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-26 17:03:21 +00:00
|
|
|
|
2019-09-10 14:16:32 +00:00
|
|
|
// get connected peers
|
2020-04-07 18:38:56 +00:00
|
|
|
std::set<dht::Key_t> peersWeHave;
|
|
|
|
_linkManager.ForEachPeer([&peersWeHave](ILinkSession* s) {
|
|
|
|
if (!s->IsEstablished())
|
2019-09-10 14:16:32 +00:00
|
|
|
return;
|
|
|
|
peersWeHave.emplace(s->GetPubKey());
|
|
|
|
});
|
|
|
|
// remove any nodes we don't have connections to
|
2020-04-07 18:38:56 +00:00
|
|
|
_dht->impl->Nodes()->RemoveIf(
|
|
|
|
[&peersWeHave](const dht::Key_t& k) -> bool { return peersWeHave.count(k) == 0; });
|
2019-11-05 16:58:53 +00:00
|
|
|
// expire paths
|
|
|
|
paths.ExpirePaths(now);
|
2019-12-07 19:58:19 +00:00
|
|
|
// update tick timestamp
|
|
|
|
_lastTick = llarp::time_now_ms();
|
|
|
|
}
|
2018-08-22 16:19:51 +00:00
|
|
|
|
2018-12-17 20:46:08 +00:00
|
|
|
bool
|
2020-04-07 18:38:56 +00:00
|
|
|
Router::Sign(Signature& sig, const llarp_buffer_t& buf) const
|
2018-12-17 20:46:08 +00:00
|
|
|
{
|
2019-05-28 19:45:08 +00:00
|
|
|
return CryptoManager::instance()->sign(sig, identity(), buf);
|
2018-12-17 20:46:08 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
void
|
2019-02-11 19:45:42 +00:00
|
|
|
Router::SessionClosed(RouterID remote)
|
2018-06-20 12:34:48 +00:00
|
|
|
{
|
2019-02-25 12:46:40 +00:00
|
|
|
dht::Key_t k(remote);
|
|
|
|
dht()->impl->Nodes()->DelNode(k);
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2019-02-11 19:45:42 +00:00
|
|
|
LogInfo("Session to ", remote, " fully closed");
|
2020-09-01 21:22:22 +00:00
|
|
|
if (IsServiceNode())
|
|
|
|
return;
|
2021-02-02 14:35:40 +00:00
|
|
|
if (const auto maybe = nodedb()->Get(remote); maybe.has_value())
|
|
|
|
{
|
|
|
|
for (const auto& addr : maybe->addrs)
|
2022-07-28 16:07:38 +00:00
|
|
|
m_RoutePoker->DelRoute(addr.IPv4());
|
2021-02-02 14:35:40 +00:00
|
|
|
}
|
2018-06-20 12:34:48 +00:00
|
|
|
}
|
2018-12-10 16:26:46 +00:00
|
|
|
|
2020-06-08 20:03:03 +00:00
|
|
|
void
|
|
|
|
Router::ConnectionTimedOut(ILinkSession* session)
|
|
|
|
{
|
|
|
|
if (m_peerDb)
|
|
|
|
{
|
|
|
|
RouterID id{session->GetPubKey()};
|
|
|
|
// TODO: make sure this is a public router (on whitelist)?
|
|
|
|
m_peerDb->modifyPeerStats(id, [&](PeerStats& stats) { stats.numConnectionTimeouts++; });
|
|
|
|
}
|
|
|
|
_outboundSessionMaker.OnConnectTimeout(session);
|
|
|
|
}
|
|
|
|
|
2021-04-06 12:25:46 +00:00
|
|
|
void
|
|
|
|
Router::ModifyOurRC(std::function<std::optional<RouterContact>(RouterContact)> modify)
|
|
|
|
{
|
|
|
|
if (auto maybe = modify(rc()))
|
|
|
|
{
|
|
|
|
_rc = *maybe;
|
|
|
|
UpdateOurRC();
|
|
|
|
_rcGossiper.GossipRC(rc());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-08 20:03:03 +00:00
|
|
|
bool
|
2020-06-11 19:02:34 +00:00
|
|
|
Router::ConnectionEstablished(ILinkSession* session, bool inbound)
|
2020-06-08 20:03:03 +00:00
|
|
|
{
|
2020-06-11 19:02:34 +00:00
|
|
|
RouterID id{session->GetPubKey()};
|
2020-06-08 20:03:03 +00:00
|
|
|
if (m_peerDb)
|
|
|
|
{
|
|
|
|
// TODO: make sure this is a public router (on whitelist)?
|
|
|
|
m_peerDb->modifyPeerStats(id, [&](PeerStats& stats) { stats.numConnectionSuccesses++; });
|
|
|
|
}
|
2020-06-11 19:02:34 +00:00
|
|
|
NotifyRouterEvent<tooling::LinkSessionEstablishedEvent>(pubkey(), id, inbound);
|
2020-06-08 20:03:03 +00:00
|
|
|
return _outboundSessionMaker.OnSessionEstablished(session);
|
|
|
|
}
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
bool
|
2020-04-07 18:38:56 +00:00
|
|
|
Router::GetRandomConnectedRouter(RouterContact& result) const
|
2018-06-06 12:46:26 +00:00
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
return _linkManager.GetRandomConnectedRouter(result);
|
2018-06-06 12:46:26 +00:00
|
|
|
}
|
2018-05-30 20:56:47 +00:00
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
Router::HandleDHTLookupForExplore(RouterID /*remote*/, const std::vector<RouterContact>& results)
|
2018-07-03 13:33:37 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& rc : results)
|
2018-12-10 16:26:46 +00:00
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
_rcLookupHandler.CheckRC(rc);
|
2018-12-10 16:26:46 +00:00
|
|
|
}
|
2018-06-01 14:08:54 +00:00
|
|
|
}
|
2018-06-13 12:58:51 +00:00
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
// TODO: refactor callers and remove this function
|
2018-12-10 16:26:46 +00:00
|
|
|
void
|
2019-06-26 21:39:29 +00:00
|
|
|
Router::LookupRouter(RouterID remote, RouterLookupHandler resultHandler)
|
2018-10-09 12:06:30 +00:00
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
_rcLookupHandler.GetRC(
|
|
|
|
remote,
|
2020-04-07 18:38:56 +00:00
|
|
|
[=](const RouterID& id, const RouterContact* const rc, const RCRequestResult result) {
|
2019-06-26 21:39:29 +00:00
|
|
|
(void)id;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (resultHandler)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
std::vector<RouterContact> routers;
|
|
|
|
if (result == RCRequestResult::Success && rc != nullptr)
|
2019-07-26 12:10:04 +00:00
|
|
|
{
|
|
|
|
routers.push_back(*rc);
|
|
|
|
}
|
2019-06-26 21:39:29 +00:00
|
|
|
resultHandler(routers);
|
|
|
|
}
|
|
|
|
});
|
2018-12-10 16:26:46 +00:00
|
|
|
}
|
|
|
|
|
2019-02-15 22:19:19 +00:00
|
|
|
void
|
2021-06-07 14:57:33 +00:00
|
|
|
Router::SetRouterWhitelist(
|
2022-10-14 23:55:21 +00:00
|
|
|
const std::vector<RouterID>& whitelist,
|
|
|
|
const std::vector<RouterID>& greylist,
|
|
|
|
const std::vector<RouterID>& unfundedlist)
|
2019-02-15 22:19:19 +00:00
|
|
|
{
|
2022-10-14 23:55:21 +00:00
|
|
|
_rcLookupHandler.SetRouterWhitelist(whitelist, greylist, unfundedlist);
|
2019-02-15 22:19:19 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
bool
|
2020-05-20 11:41:42 +00:00
|
|
|
Router::StartRpcServer()
|
2018-12-10 16:26:46 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (enableRPCServer)
|
2018-10-09 12:06:30 +00:00
|
|
|
{
|
2022-09-28 16:37:19 +00:00
|
|
|
m_RPCServer.reset(new rpc::RpcServer{m_lmq, this});
|
2020-05-21 14:09:45 +00:00
|
|
|
m_RPCServer->AsyncServeRPC(rpcBindAddr);
|
2022-07-16 00:41:14 +00:00
|
|
|
LogInfo("Bound RPC server to ", rpcBindAddr.full_address());
|
2018-10-09 12:06:30 +00:00
|
|
|
}
|
2019-10-04 09:10:55 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Router::Run()
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (_running || _stopping)
|
2019-10-04 09:10:55 +00:00
|
|
|
return false;
|
|
|
|
|
2020-06-04 21:02:05 +00:00
|
|
|
// set public signing key
|
|
|
|
_rc.pubkey = seckey_topublic(identity());
|
|
|
|
// set router version if service node
|
2020-04-07 18:38:56 +00:00
|
|
|
if (IsServiceNode())
|
2020-01-25 16:28:07 +00:00
|
|
|
{
|
2022-05-26 15:59:44 +00:00
|
|
|
_rc.routerVersion = RouterVersion(llarp::VERSION, llarp::constants::proto_version);
|
2020-06-04 21:02:05 +00:00
|
|
|
}
|
2019-04-08 18:21:01 +00:00
|
|
|
|
2020-06-04 21:02:05 +00:00
|
|
|
_linkManager.ForEachInboundLink([&](LinkLayer_ptr link) {
|
|
|
|
AddressInfo ai;
|
|
|
|
if (link->GetOurAddressInfo(ai))
|
|
|
|
{
|
2022-07-09 15:05:52 +00:00
|
|
|
// override ip and port as needed
|
2021-02-22 15:01:05 +00:00
|
|
|
if (_ourAddress)
|
2019-04-08 18:21:01 +00:00
|
|
|
{
|
2022-07-09 15:05:52 +00:00
|
|
|
if (not Net().IsBogon(ai.ip))
|
|
|
|
throw std::runtime_error{"cannot override public ip, it is already set"};
|
2021-02-22 15:01:05 +00:00
|
|
|
ai.fromSockAddr(*_ourAddress);
|
2019-04-08 18:21:01 +00:00
|
|
|
}
|
2022-07-28 16:07:38 +00:00
|
|
|
if (RouterContact::BlockBogons && Net().IsBogon(ai.ip))
|
2022-07-09 15:05:52 +00:00
|
|
|
throw std::runtime_error{var::visit(
|
|
|
|
[](auto&& ip) {
|
|
|
|
return "cannot use " + ip.ToString()
|
|
|
|
+ " as a public ip as it is in a non routable ip range";
|
|
|
|
},
|
|
|
|
ai.IP())};
|
2020-06-04 21:02:05 +00:00
|
|
|
LogInfo("adding address: ", ai);
|
|
|
|
_rc.addrs.push_back(ai);
|
|
|
|
}
|
|
|
|
});
|
2018-12-10 16:26:46 +00:00
|
|
|
|
2020-08-14 15:36:08 +00:00
|
|
|
if (IsServiceNode() and not _rc.IsPublicRouter())
|
|
|
|
{
|
|
|
|
LogError("we are configured as relay but have no reachable addresses");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-06-04 21:02:05 +00:00
|
|
|
// set public encryption key
|
|
|
|
_rc.enckey = seckey_topublic(encryption());
|
2019-04-08 18:21:01 +00:00
|
|
|
|
2020-06-04 21:02:05 +00:00
|
|
|
LogInfo("Signing rc...");
|
|
|
|
if (!_rc.Sign(identity()))
|
|
|
|
{
|
|
|
|
LogError("failed to sign rc");
|
|
|
|
return false;
|
|
|
|
}
|
2018-05-22 15:54:19 +00:00
|
|
|
|
2020-06-04 21:02:05 +00:00
|
|
|
if (IsServiceNode())
|
|
|
|
{
|
2020-06-04 16:57:29 +00:00
|
|
|
if (!SaveRC())
|
|
|
|
{
|
|
|
|
LogError("failed to save RC");
|
|
|
|
return false;
|
|
|
|
}
|
2020-06-04 21:02:05 +00:00
|
|
|
}
|
|
|
|
_outboundSessionMaker.SetOurRouter(pubkey());
|
2021-03-02 22:27:35 +00:00
|
|
|
if (!_linkManager.StartLinks())
|
2020-06-04 21:02:05 +00:00
|
|
|
{
|
|
|
|
LogWarn("One or more links failed to start.");
|
|
|
|
return false;
|
|
|
|
}
|
2018-05-22 15:54:19 +00:00
|
|
|
|
2020-06-04 21:02:05 +00:00
|
|
|
if (IsServiceNode())
|
|
|
|
{
|
2018-12-10 16:26:46 +00:00
|
|
|
// initialize as service node
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!InitServiceNode())
|
2018-12-10 16:26:46 +00:00
|
|
|
{
|
2019-02-11 19:45:42 +00:00
|
|
|
LogError("Failed to initialize service node");
|
2018-12-10 16:26:46 +00:00
|
|
|
return false;
|
|
|
|
}
|
2020-01-30 22:10:56 +00:00
|
|
|
const RouterID us = pubkey();
|
2019-02-11 19:45:42 +00:00
|
|
|
LogInfo("initalized service node: ", us);
|
2020-01-30 22:10:56 +00:00
|
|
|
// init gossiper here
|
2020-03-04 00:50:20 +00:00
|
|
|
_rcGossiper.Init(&_linkManager, us, this);
|
2019-05-06 14:21:47 +00:00
|
|
|
// relays do not use profiling
|
|
|
|
routerProfiling().Disable();
|
2018-11-12 16:43:40 +00:00
|
|
|
}
|
2018-12-10 16:26:46 +00:00
|
|
|
else
|
2018-09-18 20:56:22 +00:00
|
|
|
{
|
2018-12-10 16:26:46 +00:00
|
|
|
// we are a client
|
|
|
|
// regenerate keys and resign rc before everything else
|
2019-05-28 19:45:08 +00:00
|
|
|
CryptoManager::instance()->identity_keygen(_identity);
|
|
|
|
CryptoManager::instance()->encryption_keygen(_encryption);
|
2020-06-04 21:02:05 +00:00
|
|
|
_rc.pubkey = seckey_topublic(identity());
|
|
|
|
_rc.enckey = seckey_topublic(encryption());
|
|
|
|
if (!_rc.Sign(identity()))
|
|
|
|
{
|
|
|
|
LogError("failed to regenerate keys and sign RC");
|
|
|
|
return false;
|
|
|
|
}
|
2018-09-18 20:56:22 +00:00
|
|
|
}
|
2018-12-10 16:26:46 +00:00
|
|
|
|
2019-02-11 19:45:42 +00:00
|
|
|
LogInfo("starting hidden service context...");
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!hiddenServiceContext().StartAll())
|
2018-10-03 11:01:42 +00:00
|
|
|
{
|
2019-02-11 19:45:42 +00:00
|
|
|
LogError("Failed to start hidden service context");
|
2018-11-26 22:46:22 +00:00
|
|
|
return false;
|
2018-10-03 11:01:42 +00:00
|
|
|
}
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2020-01-14 20:12:47 +00:00
|
|
|
{
|
2021-02-02 14:35:40 +00:00
|
|
|
LogInfo("Loading nodedb from disk...");
|
|
|
|
_nodedb->LoadFromDisk();
|
2020-01-14 20:12:47 +00:00
|
|
|
}
|
|
|
|
|
2019-01-29 02:16:31 +00:00
|
|
|
llarp_dht_context_start(dht(), pubkey());
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& rc : bootstrapRCList)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2021-02-02 14:35:40 +00:00
|
|
|
nodedb()->Put(rc);
|
2019-06-26 21:39:29 +00:00
|
|
|
_dht->impl->Nodes()->PutNode(rc);
|
2021-02-02 14:35:40 +00:00
|
|
|
LogInfo("added bootstrap node ", RouterID{rc.pubkey});
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
2021-02-02 14:35:40 +00:00
|
|
|
LogInfo("have ", _nodedb->NumLoaded(), " routers");
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2021-03-02 07:02:59 +00:00
|
|
|
_loop->call_every(ROUTER_TICK_INTERVAL, weak_from_this(), [this] { Tick(); });
|
2022-07-28 16:07:38 +00:00
|
|
|
m_RoutePoker->Start(this);
|
2018-12-24 16:09:05 +00:00
|
|
|
_running.store(true);
|
2019-04-22 12:25:25 +00:00
|
|
|
_startedAt = Now();
|
2019-12-07 19:21:26 +00:00
|
|
|
#if defined(WITH_SYSTEMD)
|
|
|
|
::sd_notify(0, "READY=1");
|
|
|
|
#endif
|
2021-06-04 20:46:51 +00:00
|
|
|
if (whitelistRouters)
|
|
|
|
{
|
|
|
|
// do service node testing if we are in service node whitelist mode
|
2021-06-08 09:45:21 +00:00
|
|
|
_loop->call_every(consensus::REACHABILITY_TESTING_TIMER_INTERVAL, weak_from_this(), [this] {
|
|
|
|
// dont run tests if we are not running or we are stopping
|
|
|
|
if (not _running)
|
|
|
|
return;
|
2022-05-03 17:37:57 +00:00
|
|
|
// dont run tests if we think we should not test other routers
|
2022-05-03 20:05:22 +00:00
|
|
|
// this occurs when we are deregistered or do not have the service node list
|
2022-05-03 17:37:57 +00:00
|
|
|
// yet when we expect to have one.
|
|
|
|
if (not ShouldTestOtherRouters())
|
2021-06-08 09:45:21 +00:00
|
|
|
return;
|
2021-06-08 14:47:27 +00:00
|
|
|
auto tests = m_routerTesting.get_failing();
|
2021-06-08 09:45:21 +00:00
|
|
|
if (auto maybe = m_routerTesting.next_random(this))
|
|
|
|
{
|
|
|
|
tests.emplace_back(*maybe, 0);
|
|
|
|
}
|
|
|
|
for (const auto& [router, fails] : tests)
|
|
|
|
{
|
2021-06-08 14:47:27 +00:00
|
|
|
if (not SessionToRouterAllowed(router))
|
|
|
|
{
|
|
|
|
LogDebug(
|
|
|
|
router,
|
|
|
|
" is no longer a registered service node so we remove it from the testing list");
|
|
|
|
m_routerTesting.remove_node_from_failing(router);
|
|
|
|
continue;
|
|
|
|
}
|
2021-06-08 09:45:21 +00:00
|
|
|
LogDebug("Establishing session to ", router, " for SN testing");
|
|
|
|
// try to make a session to this random router
|
|
|
|
// this will do a dht lookup if needed
|
|
|
|
_outboundSessionMaker.CreateSessionTo(
|
|
|
|
router, [previous_fails = fails, this](const auto& router, const auto result) {
|
|
|
|
auto rpc = RpcClient();
|
|
|
|
|
|
|
|
if (result != SessionResult::Establish)
|
|
|
|
{
|
|
|
|
// failed connection mark it as so
|
|
|
|
m_routerTesting.add_failing_node(router, previous_fails);
|
|
|
|
LogInfo(
|
|
|
|
"FAILED SN connection test to ",
|
|
|
|
router,
|
|
|
|
" (",
|
|
|
|
previous_fails + 1,
|
2021-07-01 16:10:26 +00:00
|
|
|
" consecutive failures) result=",
|
|
|
|
result);
|
2021-06-08 09:45:21 +00:00
|
|
|
}
|
|
|
|
else
|
2021-06-08 14:47:27 +00:00
|
|
|
{
|
|
|
|
m_routerTesting.remove_node_from_failing(router);
|
|
|
|
if (previous_fails > 0)
|
|
|
|
{
|
|
|
|
LogInfo(
|
|
|
|
"Successful SN connection test to ",
|
|
|
|
router,
|
|
|
|
" after ",
|
|
|
|
previous_fails,
|
|
|
|
" failures");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LogDebug("Successful SN connection test to ", router);
|
|
|
|
}
|
|
|
|
}
|
2021-06-08 09:45:21 +00:00
|
|
|
if (rpc)
|
|
|
|
{
|
|
|
|
// inform as needed
|
|
|
|
rpc->InformConnection(router, result == SessionResult::Establish);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2021-06-04 20:46:51 +00:00
|
|
|
}
|
2018-12-24 16:09:05 +00:00
|
|
|
return _running;
|
|
|
|
}
|
|
|
|
|
2019-10-09 13:08:38 +00:00
|
|
|
bool
|
|
|
|
Router::IsRunning() const
|
|
|
|
{
|
|
|
|
return _running;
|
|
|
|
}
|
|
|
|
|
2019-04-22 12:25:25 +00:00
|
|
|
llarp_time_t
|
|
|
|
Router::Uptime() const
|
|
|
|
{
|
|
|
|
const llarp_time_t _now = Now();
|
2020-04-07 18:38:56 +00:00
|
|
|
if (_startedAt > 0s && _now > _startedAt)
|
2019-04-22 12:25:25 +00:00
|
|
|
return _now - _startedAt;
|
2020-02-24 19:40:45 +00:00
|
|
|
return 0s;
|
2019-04-22 12:25:25 +00:00
|
|
|
}
|
|
|
|
|
2019-11-23 04:47:08 +00:00
|
|
|
void
|
|
|
|
Router::AfterStopLinks()
|
2018-12-24 16:09:05 +00:00
|
|
|
{
|
2019-11-23 04:47:08 +00:00
|
|
|
Close();
|
2020-10-06 13:44:51 +00:00
|
|
|
m_lmq.reset();
|
2018-12-24 16:09:05 +00:00
|
|
|
}
|
|
|
|
|
2019-11-23 04:47:08 +00:00
|
|
|
void
|
|
|
|
Router::AfterStopIssued()
|
2018-12-24 16:09:05 +00:00
|
|
|
{
|
2019-11-23 04:47:08 +00:00
|
|
|
StopLinks();
|
2021-02-02 14:35:40 +00:00
|
|
|
nodedb()->SaveToDisk();
|
2021-03-02 07:02:59 +00:00
|
|
|
_loop->call_later(200ms, [this] { AfterStopLinks(); });
|
2018-12-24 16:09:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Router::StopLinks()
|
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
_linkManager.Stop();
|
2018-06-10 14:05:48 +00:00
|
|
|
}
|
|
|
|
|
2020-06-16 11:28:20 +00:00
|
|
|
void
|
|
|
|
Router::Die()
|
|
|
|
{
|
|
|
|
if (!_running)
|
|
|
|
return;
|
|
|
|
if (_stopping)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_stopping.store(true);
|
2022-07-18 15:59:13 +00:00
|
|
|
if (log::get_level_default() != log::Level::off)
|
|
|
|
log::reset_level(log::Level::info);
|
2020-06-16 11:28:20 +00:00
|
|
|
LogWarn("stopping router hard");
|
|
|
|
#if defined(WITH_SYSTEMD)
|
|
|
|
sd_notify(0, "STOPPING=1\nSTATUS=Shutting down HARD");
|
|
|
|
#endif
|
|
|
|
hiddenServiceContext().StopAll();
|
|
|
|
_exitContext.Stop();
|
|
|
|
StopLinks();
|
|
|
|
Close();
|
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
void
|
|
|
|
Router::Stop()
|
2018-11-26 13:29:45 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!_running)
|
2018-12-24 16:09:05 +00:00
|
|
|
return;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (_stopping)
|
2018-12-24 16:09:05 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
_stopping.store(true);
|
2022-07-18 15:59:13 +00:00
|
|
|
if (log::get_level_default() != log::Level::off)
|
|
|
|
log::reset_level(log::Level::info);
|
2019-02-11 19:45:42 +00:00
|
|
|
LogInfo("stopping router");
|
2020-02-25 22:32:57 +00:00
|
|
|
#if defined(WITH_SYSTEMD)
|
|
|
|
sd_notify(0, "STOPPING=1\nSTATUS=Shutting down");
|
|
|
|
#endif
|
2019-02-22 16:21:05 +00:00
|
|
|
hiddenServiceContext().StopAll();
|
2019-02-11 19:45:42 +00:00
|
|
|
_exitContext.Stop();
|
2019-09-16 10:21:12 +00:00
|
|
|
paths.PumpUpstream();
|
2019-06-26 21:39:29 +00:00
|
|
|
_linkManager.PumpLinks();
|
2021-03-02 07:02:59 +00:00
|
|
|
_loop->call_later(200ms, [this] { AfterStopIssued(); });
|
2018-11-26 13:29:45 +00:00
|
|
|
}
|
2018-08-02 23:30:34 +00:00
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
bool
|
2020-04-07 18:38:56 +00:00
|
|
|
Router::HasSessionTo(const RouterID& remote) const
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
return _linkManager.HasSessionTo(remote);
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
2020-02-20 21:37:39 +00:00
|
|
|
std::string
|
|
|
|
Router::ShortName() const
|
|
|
|
{
|
|
|
|
return RouterID(pubkey()).ToString().substr(0, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
2020-02-20 21:57:48 +00:00
|
|
|
Router::NextPathBuildNumber()
|
2020-02-20 21:37:39 +00:00
|
|
|
{
|
|
|
|
return path_build_count++;
|
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
void
|
2019-12-03 17:03:19 +00:00
|
|
|
Router::ConnectToRandomRouters(int _want)
|
2018-12-10 16:26:46 +00:00
|
|
|
{
|
2019-12-03 17:03:19 +00:00
|
|
|
const size_t want = _want;
|
2020-04-07 18:38:56 +00:00
|
|
|
auto connected = NumberOfConnectedRouters();
|
|
|
|
if (not IsServiceNode())
|
2019-12-03 17:03:19 +00:00
|
|
|
{
|
|
|
|
connected += _linkManager.NumberOfPendingConnections();
|
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
if (connected >= want)
|
2019-12-03 17:03:19 +00:00
|
|
|
return;
|
2019-12-09 15:17:02 +00:00
|
|
|
_outboundSessionMaker.ConnectToRandomRouters(want);
|
2018-06-07 16:22:49 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
bool
|
|
|
|
Router::InitServiceNode()
|
2018-11-26 13:29:45 +00:00
|
|
|
{
|
2019-02-11 19:45:42 +00:00
|
|
|
LogInfo("accepting transit traffic");
|
2018-12-10 16:26:46 +00:00
|
|
|
paths.AllowTransit();
|
2019-01-29 02:16:31 +00:00
|
|
|
llarp_dht_allow_transit(dht());
|
2021-03-26 20:45:19 +00:00
|
|
|
_exitContext.AddExitEndpoint("default", m_Config->network, m_Config->dns);
|
2020-04-28 14:22:04 +00:00
|
|
|
return true;
|
2018-11-26 13:29:45 +00:00
|
|
|
}
|
2018-06-14 17:35:12 +00:00
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
bool
|
|
|
|
Router::TryConnectAsync(RouterContact rc, uint16_t tries)
|
|
|
|
{
|
|
|
|
(void)tries;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (rc.pubkey == pubkey())
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-06-07 14:57:33 +00:00
|
|
|
if (not _rcLookupHandler.SessionIsAllowed(rc.pubkey))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
_outboundSessionMaker.CreateSessionTo(rc, nullptr);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-10-06 13:44:51 +00:00
|
|
|
void
|
|
|
|
Router::QueueWork(std::function<void(void)> func)
|
|
|
|
{
|
2021-11-09 17:21:07 +00:00
|
|
|
m_lmq->job(std::move(func));
|
2020-10-06 13:44:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Router::QueueDiskIO(std::function<void(void)> func)
|
|
|
|
{
|
|
|
|
m_lmq->job(std::move(func), m_DiskThread);
|
|
|
|
}
|
|
|
|
|
2020-09-24 00:28:38 +00:00
|
|
|
bool
|
|
|
|
Router::HasClientExit() const
|
2020-09-01 21:22:22 +00:00
|
|
|
{
|
2020-09-24 00:28:38 +00:00
|
|
|
if (IsServiceNode())
|
|
|
|
return false;
|
2020-09-01 21:22:22 +00:00
|
|
|
const auto ep = hiddenServiceContext().GetDefault();
|
2020-09-24 00:28:38 +00:00
|
|
|
return ep and ep->HasExit();
|
2020-09-01 21:22:22 +00:00
|
|
|
}
|
|
|
|
|
2022-05-20 17:10:04 +00:00
|
|
|
std::optional<std::variant<nuint32_t, nuint128_t>>
|
|
|
|
Router::OurPublicIP() const
|
|
|
|
{
|
|
|
|
if (_ourAddress)
|
|
|
|
return _ourAddress->getIP();
|
|
|
|
std::optional<std::variant<nuint32_t, nuint128_t>> found;
|
|
|
|
_linkManager.ForEachInboundLink([&found](const auto& link) {
|
|
|
|
if (found)
|
|
|
|
return;
|
|
|
|
AddressInfo ai;
|
|
|
|
if (link->GetOurAddressInfo(ai))
|
|
|
|
found = ai.IP();
|
|
|
|
});
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
2022-07-09 15:05:52 +00:00
|
|
|
void
|
|
|
|
Router::InitInboundLinks()
|
2018-06-18 22:03:50 +00:00
|
|
|
{
|
2022-07-09 15:05:52 +00:00
|
|
|
auto addrs = m_Config->links.InboundListenAddrs;
|
|
|
|
if (m_isServiceNode and addrs.empty())
|
|
|
|
{
|
|
|
|
LogInfo("Inferring Public Address");
|
|
|
|
|
|
|
|
auto maybe_port = m_Config->links.PublicPort;
|
|
|
|
if (m_Config->router.PublicPort and not maybe_port)
|
|
|
|
maybe_port = m_Config->router.PublicPort;
|
|
|
|
if (not maybe_port)
|
|
|
|
maybe_port = net::port_t::from_host(constants::DefaultInboundIWPPort);
|
2020-04-07 18:38:56 +00:00
|
|
|
|
2022-07-09 15:05:52 +00:00
|
|
|
if (auto maybe_addr = Net().MaybeInferPublicAddr(*maybe_port))
|
|
|
|
{
|
|
|
|
LogInfo("Public Address looks to be ", *maybe_addr);
|
|
|
|
addrs.emplace_back(std::move(*maybe_addr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (m_isServiceNode and addrs.empty())
|
|
|
|
throw std::runtime_error{"we are a service node and we have no inbound links configured"};
|
2018-05-21 12:43:32 +00:00
|
|
|
|
2022-07-09 15:05:52 +00:00
|
|
|
// create inbound links, if we are a service node
|
|
|
|
for (auto bind_addr : addrs)
|
2018-12-10 16:26:46 +00:00
|
|
|
{
|
2022-07-09 15:05:52 +00:00
|
|
|
if (bind_addr.getPort() == 0)
|
|
|
|
throw std::invalid_argument{"inbound link cannot use port 0"};
|
|
|
|
|
|
|
|
if (Net().IsWildcardAddress(bind_addr.getIP()))
|
|
|
|
{
|
|
|
|
if (auto maybe_ip = OurPublicIP())
|
|
|
|
bind_addr.setIP(*maybe_ip);
|
|
|
|
else
|
|
|
|
throw std::runtime_error{"no public ip provided for inbound socket"};
|
|
|
|
}
|
|
|
|
|
|
|
|
auto server = iwp::NewInboundLink(
|
|
|
|
m_keyManager,
|
|
|
|
loop(),
|
|
|
|
util::memFn(&AbstractRouter::rc, this),
|
|
|
|
util::memFn(&AbstractRouter::HandleRecvLinkMessageBuffer, this),
|
|
|
|
util::memFn(&AbstractRouter::Sign, this),
|
|
|
|
nullptr,
|
|
|
|
util::memFn(&Router::ConnectionEstablished, this),
|
|
|
|
util::memFn(&AbstractRouter::CheckRenegotiateValid, this),
|
|
|
|
util::memFn(&Router::ConnectionTimedOut, this),
|
|
|
|
util::memFn(&AbstractRouter::SessionClosed, this),
|
|
|
|
util::memFn(&AbstractRouter::TriggerPump, this),
|
|
|
|
util::memFn(&AbstractRouter::QueueWork, this));
|
|
|
|
|
|
|
|
server->Bind(this, bind_addr);
|
|
|
|
_linkManager.AddLink(std::move(server), true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Router::InitOutboundLinks()
|
|
|
|
{
|
|
|
|
auto addrs = m_Config->links.OutboundLinks;
|
|
|
|
if (addrs.empty())
|
|
|
|
addrs.emplace_back(Net().Wildcard());
|
|
|
|
|
2022-07-21 20:47:27 +00:00
|
|
|
for (auto& bind_addr : addrs)
|
2022-07-09 15:05:52 +00:00
|
|
|
{
|
|
|
|
auto link = iwp::NewOutboundLink(
|
|
|
|
m_keyManager,
|
|
|
|
loop(),
|
|
|
|
util::memFn(&AbstractRouter::rc, this),
|
|
|
|
util::memFn(&AbstractRouter::HandleRecvLinkMessageBuffer, this),
|
|
|
|
util::memFn(&AbstractRouter::Sign, this),
|
|
|
|
[this](llarp::RouterContact rc) {
|
|
|
|
if (IsServiceNode())
|
|
|
|
return;
|
2022-07-28 16:07:38 +00:00
|
|
|
for (const auto& addr : rc.addrs)
|
|
|
|
m_RoutePoker->AddRoute(addr.IPv4());
|
2022-07-09 15:05:52 +00:00
|
|
|
},
|
|
|
|
util::memFn(&Router::ConnectionEstablished, this),
|
|
|
|
util::memFn(&AbstractRouter::CheckRenegotiateValid, this),
|
|
|
|
util::memFn(&Router::ConnectionTimedOut, this),
|
|
|
|
util::memFn(&AbstractRouter::SessionClosed, this),
|
|
|
|
util::memFn(&AbstractRouter::TriggerPump, this),
|
|
|
|
util::memFn(&AbstractRouter::QueueWork, this));
|
|
|
|
|
|
|
|
const auto& net = Net();
|
|
|
|
|
2022-07-21 20:47:27 +00:00
|
|
|
// If outbound is set to wildcard and we have just one inbound, then bind to the inbound IP;
|
|
|
|
// if you have more than one inbound you have to be explicit about your outbound.
|
|
|
|
if (net.IsWildcardAddress(bind_addr.getIP()))
|
|
|
|
{
|
|
|
|
bool multiple = false;
|
|
|
|
_linkManager.ForEachInboundLink([&bind_addr, &multiple](const auto& link) {
|
|
|
|
if (multiple)
|
|
|
|
throw std::runtime_error{
|
|
|
|
"outbound= IP address must be specified when using multiple inbound= addresses"};
|
|
|
|
multiple = true;
|
|
|
|
bind_addr.setIP(link->LocalSocketAddr().getIP());
|
|
|
|
});
|
|
|
|
}
|
2022-07-09 15:05:52 +00:00
|
|
|
|
|
|
|
link->Bind(this, bind_addr);
|
|
|
|
|
|
|
|
if constexpr (llarp::platform::is_android)
|
|
|
|
m_OutboundUDPSocket = link->GetUDPFD().value_or(-1);
|
2020-04-29 20:19:48 +00:00
|
|
|
|
2019-08-07 16:33:29 +00:00
|
|
|
_linkManager.AddLink(std::move(link), false);
|
2018-06-21 12:52:45 +00:00
|
|
|
}
|
2022-07-09 15:05:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const llarp::net::Platform&
|
|
|
|
Router::Net() const
|
|
|
|
{
|
|
|
|
return *llarp::net::Platform::Default_ptr();
|
2018-06-21 12:52:45 +00:00
|
|
|
}
|
2018-06-21 13:33:42 +00:00
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
Router::MessageSent(const RouterID& remote, SendStatus status)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (status == SendStatus::Success)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2019-07-25 18:31:53 +00:00
|
|
|
LogDebug("Message successfully sent to ", remote);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-09-09 11:36:21 +00:00
|
|
|
LogDebug("Message failed sending to ", remote);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
}
|
2020-07-01 19:46:52 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
Router::HandleRouterEvent(tooling::RouterEventPtr event) const
|
|
|
|
{
|
|
|
|
LogDebug(event->ToString());
|
|
|
|
}
|
|
|
|
|
2018-02-01 13:21:00 +00:00
|
|
|
} // namespace llarp
|