2019-12-03 17:58:53 +00:00
|
|
|
#include <memory>
|
2019-01-14 21:46:07 +00:00
|
|
|
#include <router/router.hpp>
|
2019-01-10 19:41:51 +00:00
|
|
|
|
2019-07-02 21:28:28 +00:00
|
|
|
#include <config/config.hpp>
|
2019-09-01 12:10:49 +00:00
|
|
|
#include <constants/proto.hpp>
|
2020-04-02 15:48:20 +00:00
|
|
|
#include <constants/files.hpp>
|
2019-01-26 15:40:58 +00:00
|
|
|
#include <crypto/crypto_libsodium.hpp>
|
2019-09-01 12:10:49 +00:00
|
|
|
#include <crypto/crypto.hpp>
|
2019-01-11 00:12:43 +00:00
|
|
|
#include <dht/context.hpp>
|
2019-01-19 18:16:40 +00:00
|
|
|
#include <dht/node.hpp>
|
2019-03-29 15:17:49 +00:00
|
|
|
#include <iwp/iwp.hpp>
|
2018-12-12 01:32:10 +00:00
|
|
|
#include <link/server.hpp>
|
2019-01-14 21:46:07 +00:00
|
|
|
#include <messages/link_message.hpp>
|
2019-01-11 01:42:02 +00:00
|
|
|
#include <net/net.hpp>
|
2020-04-24 17:10:05 +00:00
|
|
|
#include <stdexcept>
|
2019-01-10 19:41:51 +00:00
|
|
|
#include <util/buffer.hpp>
|
2019-09-01 12:10:49 +00:00
|
|
|
#include <util/logging/file_logger.hpp>
|
|
|
|
#include <util/logging/json_logger.hpp>
|
|
|
|
#include <util/logging/logger_syslog.hpp>
|
|
|
|
#include <util/logging/logger.hpp>
|
2019-09-01 12:38:03 +00:00
|
|
|
#include <util/meta/memfn.hpp>
|
2019-01-10 19:41:51 +00:00
|
|
|
#include <util/str.hpp>
|
2019-09-05 17:39:09 +00:00
|
|
|
#include <ev/ev.hpp>
|
2020-06-11 19:02:34 +00:00
|
|
|
#include <tooling/peer_stats_event.hpp>
|
2017-11-28 14:05:31 +00:00
|
|
|
|
2020-02-27 20:17:37 +00:00
|
|
|
#include "tooling/router_event.hpp"
|
2020-05-27 21:00:09 +00:00
|
|
|
#include "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
|
|
|
|
|
2020-05-19 18:53:03 +00:00
|
|
|
#include <lokimq/lokimq.h>
|
|
|
|
|
2020-02-25 17:05:13 +00:00
|
|
|
static constexpr std::chrono::milliseconds ROUTER_TICK_INTERVAL = 1s;
|
2018-05-20 17:45:47 +00:00
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
namespace llarp
|
|
|
|
{
|
2020-06-11 11:44:02 +00:00
|
|
|
Router::Router(llarp_ev_loop_ptr __netloop, std::shared_ptr<Logic> l)
|
2018-12-10 16:26:46 +00:00
|
|
|
: ready(false)
|
2020-05-19 18:53:03 +00:00
|
|
|
, m_lmq(std::make_shared<lokimq::LokiMQ>())
|
2019-07-30 23:42:13 +00:00
|
|
|
, _netloop(std::move(__netloop))
|
|
|
|
, _logic(std::move(l))
|
2018-12-10 16:26:46 +00:00
|
|
|
, paths(this)
|
2019-02-11 19:45:42 +00:00
|
|
|
, _exitContext(this)
|
2019-01-29 02:16:31 +00:00
|
|
|
, _dht(llarp_dht_context_new(this))
|
2020-06-11 11:44:02 +00:00
|
|
|
, m_DiskThread(m_lmq->add_tagged_thread("disk"))
|
2018-12-10 16:26:46 +00:00
|
|
|
, inbound_link_msg_parser(this)
|
2019-02-22 16:21:05 +00:00
|
|
|
, _hiddenServiceContext(this)
|
2020-05-23 19:36:25 +00:00
|
|
|
, m_RPCServer(new rpc::RpcServer(m_lmq, this))
|
2020-03-03 19:56:33 +00:00
|
|
|
#ifdef LOKINET_HIVE
|
2020-04-07 18:38:56 +00:00
|
|
|
, _randomStartDelay(std::chrono::milliseconds((llarp::randint() % 1250) + 2000))
|
2020-03-03 19:56:33 +00:00
|
|
|
#else
|
2020-02-05 16:16:46 +00:00
|
|
|
, _randomStartDelay(std::chrono::seconds((llarp::randint() % 30) + 10))
|
2020-03-03 19:56:33 +00:00
|
|
|
#endif
|
2020-05-20 11:41:42 +00:00
|
|
|
, m_lokidRpcClient(std::make_shared<rpc::LokidRpcClient>(m_lmq, this))
|
2018-06-20 17:45:44 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
m_keyManager = std::make_shared<KeyManager>();
|
2019-12-03 17:58:53 +00:00
|
|
|
|
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();
|
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
|
|
|
|
2019-02-11 17:14:43 +00:00
|
|
|
util::StatusObject
|
|
|
|
Router::ExtractStatus() const
|
2019-02-08 19:43:25 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (_running)
|
2019-10-04 09:10:55 +00:00
|
|
|
{
|
2020-05-27 21:00:09 +00:00
|
|
|
util::StatusObject peerStatsObj = nullptr;
|
|
|
|
if (m_peerDb)
|
|
|
|
peerStatsObj = m_peerDb->ExtractStatus();
|
|
|
|
|
2020-06-25 21:59:42 +00:00
|
|
|
return util::StatusObject{{"running", true},
|
|
|
|
{"numNodesKnown", _nodedb->num_loaded()},
|
|
|
|
{"dht", _dht->impl->ExtractStatus()},
|
|
|
|
{"services", _hiddenServiceContext.ExtractStatus()},
|
|
|
|
{"exit", _exitContext.ExtractStatus()},
|
|
|
|
{"links", _linkManager.ExtractStatus()},
|
|
|
|
{"outboundMessages", _outboundMessageHandler.ExtractStatus()},
|
|
|
|
{"peerStats", peerStatsObj}};
|
2019-10-04 09:10:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-10-04 19:43:30 +00:00
|
|
|
return util::StatusObject{{"running", false}};
|
2019-10-04 09:10:55 +00:00
|
|
|
}
|
2019-02-08 19:43:25 +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
|
|
|
}
|
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);
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
auto pick_router = [&](auto& collection) -> bool {
|
2019-05-14 14:36:18 +00:00
|
|
|
const auto sz = collection.size();
|
2020-04-07 18:38:56 +00:00
|
|
|
auto itr = collection.begin();
|
|
|
|
if (sz == 0)
|
2019-05-09 12:31:10 +00:00
|
|
|
return false;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (sz > 1)
|
2019-05-09 12:31:10 +00:00
|
|
|
std::advance(itr, randint() % sz);
|
|
|
|
router = itr->first;
|
|
|
|
return true;
|
2019-05-14 14:36:18 +00:00
|
|
|
};
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2020-05-12 19:42:35 +00:00
|
|
|
std::shared_lock l{nodedb()->access};
|
2019-05-14 14:36:18 +00:00
|
|
|
return pick_router(nodedb()->entries);
|
2018-12-13 00:03:19 +00:00
|
|
|
}
|
|
|
|
|
2019-04-30 16:07:17 +00:00
|
|
|
void
|
|
|
|
Router::PumpLL()
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (_stopping.load())
|
2019-09-16 16:12:05 +00:00
|
|
|
return;
|
2019-09-16 10:21:12 +00:00
|
|
|
paths.PumpDownstream();
|
2019-11-04 18:25:05 +00:00
|
|
|
paths.PumpUpstream();
|
2019-10-25 21:13:11 +00:00
|
|
|
_outboundMessageHandler.Tick();
|
2019-06-26 21:39:29 +00:00
|
|
|
_linkManager.PumpLinks();
|
2019-04-30 16:07:17 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
bool
|
2020-04-07 18:38:56 +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();
|
|
|
|
LogWarn("Obtained lokid identity keys");
|
|
|
|
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
|
2020-08-27 12:43:53 +00:00
|
|
|
Router::Configure(std::shared_ptr<Config> c, bool isRouter, llarp_nodedb* nodedb)
|
2018-12-10 16:26:46 +00:00
|
|
|
{
|
2020-08-27 12:43:53 +00:00
|
|
|
m_Config = c;
|
|
|
|
auto& conf = *m_Config;
|
2020-07-06 19:13:01 +00:00
|
|
|
whitelistRouters = conf.lokid.whitelistRouters;
|
|
|
|
if (whitelistRouters)
|
|
|
|
lokidRPCAddr = lokimq::address(conf.lokid.lokidRPCAddr);
|
|
|
|
|
|
|
|
enableRPCServer = conf.api.m_enableRPCServer;
|
|
|
|
if (enableRPCServer)
|
|
|
|
rpcBindAddr = lokimq::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");
|
|
|
|
|
|
|
|
m_lmq->start();
|
|
|
|
|
2020-06-11 11:44:02 +00:00
|
|
|
_nodedb = nodedb;
|
|
|
|
|
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
|
2020-07-06 19:13:01 +00:00
|
|
|
if (not m_keyManager->initialize(conf, true, isRouter))
|
|
|
|
throw std::runtime_error("KeyManager failed to initialize");
|
|
|
|
if (!FromConfig(conf))
|
|
|
|
throw std::runtime_error("FromConfig() failed");
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!InitOutboundLinks())
|
2020-04-24 17:10:05 +00:00
|
|
|
throw std::runtime_error("InitOutboundLinks() failed");
|
|
|
|
|
|
|
|
if (not EnsureIdentity())
|
|
|
|
throw std::runtime_error("EnsureIdentity() failed");
|
2019-11-26 19:42:41 +00:00
|
|
|
|
2020-04-24 17:10:05 +00:00
|
|
|
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;
|
|
|
|
}
|
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
|
|
|
|
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");
|
2019-06-02 21:17:05 +00:00
|
|
|
llarp_ev_loop_stop(_netloop);
|
2020-02-28 01:23:36 +00:00
|
|
|
_running.store(false);
|
2018-12-10 16:26:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-11-23 04:47:08 +00:00
|
|
|
Router::handle_router_ticker()
|
2018-11-28 15:18:18 +00:00
|
|
|
{
|
2019-11-23 04:47:08 +00:00
|
|
|
ticker_job_id = 0;
|
2020-02-24 19:40:45 +00:00
|
|
|
Tick();
|
|
|
|
ScheduleTicker(ROUTER_TICK_INTERVAL);
|
2018-11-28 15:18:18 +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);
|
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
bool
|
2020-04-07 18:38:56 +00:00
|
|
|
Router::ConnectionToRouterAllowed(const RouterID& router) const
|
2018-11-28 14:58:38 +00:00
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
return _rcLookupHandler.RemoteIsAllowed(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-02 21:28:28 +00:00
|
|
|
// IWP config
|
2020-07-06 19:13:01 +00:00
|
|
|
m_OutboundPort = conf.links.m_OutboundLink.port;
|
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;
|
|
|
|
|
2020-07-06 19:13:01 +00:00
|
|
|
_ourAddress = conf.router.m_publicAddress;
|
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
|
|
|
usingSNSeed = conf.lokid.usingSNSeed;
|
|
|
|
whitelistRouters = conf.lokid.whitelistRouters;
|
|
|
|
lokidRPCAddr = lokimq::address(conf.lokid.lokidRPCAddr);
|
2019-07-12 17:21:29 +00:00
|
|
|
|
2020-06-04 18:38:35 +00:00
|
|
|
if (usingSNSeed)
|
2020-07-06 19:13:01 +00:00
|
|
|
ident_keyfile = conf.lokid.ident_keyfile;
|
2020-06-04 18:38:35 +00:00
|
|
|
|
2020-08-14 15:36:08 +00:00
|
|
|
m_isServiceNode = conf.router.m_isRelay;
|
2019-02-11 14:43:48 +00:00
|
|
|
|
2020-07-06 19:13:01 +00:00
|
|
|
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?
|
2020-04-07 18:38:56 +00:00
|
|
|
std::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");
|
2020-04-27 15:24:05 +00:00
|
|
|
|
|
|
|
// try as a RouterID and as a PubKey, convert to RouterID if needed
|
2019-07-02 21:28:28 +00:00
|
|
|
llarp::RouterID snode;
|
|
|
|
llarp::PubKey pk;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (pk.FromString(val))
|
2020-04-27 15:24:05 +00:00
|
|
|
strictConnectPubkeys.emplace(pk);
|
2020-04-07 18:38:56 +00:00
|
|
|
else if (snode.FromString(val))
|
2020-04-27 15:24:05 +00:00
|
|
|
strictConnectPubkeys.insert(snode);
|
2019-02-11 14:43:48 +00:00
|
|
|
else
|
2020-04-27 15:24:05 +00:00
|
|
|
throw std::invalid_argument(stringify("invalid key for strict-connect: ", val));
|
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(
|
2020-07-06 19:13:01 +00:00
|
|
|
configRouters.end(), conf.bootstrap.routers.begin(), conf.bootstrap.routers.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
|
2020-04-07 23:52:14 +00:00
|
|
|
if (configRouters.size() == 0 and not m_isServiceNode)
|
2020-04-02 15:13:39 +00:00
|
|
|
{
|
|
|
|
// TODO: use constant
|
2020-07-06 19:13:01 +00:00
|
|
|
fs::path defaultBootstrapFile = conf.router.m_dataDir / "bootstrap.signed";
|
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-07-06 19:13:01 +00:00
|
|
|
else if (not conf.bootstrap.skipBootstrap)
|
2020-04-02 15:13:39 +00:00
|
|
|
{
|
|
|
|
LogError("No bootstrap files specified in config file, and the default");
|
|
|
|
LogError("bootstrap file ", defaultBootstrapFile, " does not exist.");
|
2020-04-29 20:19:48 +00:00
|
|
|
LogError("Please provide a bootstrap file (e.g. run 'lokinet-bootstrap)'");
|
2020-04-02 15:13:39 +00:00
|
|
|
throw std::runtime_error("No bootstrap files available.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2019-12-06 17:32:46 +00:00
|
|
|
bool isListFile = false;
|
2019-02-11 14:43:48 +00:00
|
|
|
{
|
2020-04-02 15:12:45 +00:00
|
|
|
std::ifstream inf(router.c_str(), std::ios::binary);
|
2020-04-07 20:41:11 +00:00
|
|
|
if (inf.is_open())
|
2019-12-06 17:32:46 +00:00
|
|
|
{
|
|
|
|
const char ch = inf.get();
|
2020-04-07 18:38:56 +00:00
|
|
|
isListFile = ch == 'l';
|
2019-12-06 17:32:46 +00:00
|
|
|
}
|
2019-02-11 14:43:48 +00:00
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
if (isListFile)
|
2019-02-11 14:43:48 +00:00
|
|
|
{
|
2020-05-27 03:42:01 +00:00
|
|
|
if (not BDecodeReadFile(router, b_list))
|
2019-12-06 17:32:46 +00:00
|
|
|
{
|
2020-04-24 17:10:05 +00:00
|
|
|
throw std::runtime_error(stringify("failed to read bootstrap list file '", router, "'"));
|
2019-12-06 17:32:46 +00:00
|
|
|
}
|
2019-02-11 14:43:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-06 17:32:46 +00:00
|
|
|
RouterContact rc;
|
2020-05-27 03:42:01 +00:00
|
|
|
if (not rc.Read(router))
|
2019-02-11 14:43:48 +00:00
|
|
|
{
|
2020-04-24 17:10:05 +00:00
|
|
|
throw std::runtime_error(
|
|
|
|
stringify("failed to decode bootstrap RC, file='", router, "' rc=", rc));
|
2019-02-11 14:43:48 +00:00
|
|
|
}
|
2019-12-06 17:32:46 +00:00
|
|
|
b_list.insert(rc);
|
2019-02-11 14:43:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (auto& rc : b_list)
|
2019-12-06 17:32:46 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (not rc.Verify(Now()))
|
2019-12-06 17:32:46 +00:00
|
|
|
{
|
|
|
|
LogWarn("ignoring invalid RC: ", RouterID(rc.pubkey));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
bootstrapRCList.emplace(std::move(rc));
|
|
|
|
}
|
|
|
|
|
|
|
|
LogInfo("Loaded ", bootstrapRCList.size(), " bootstrap routers");
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
// Init components after relevant config settings loaded
|
|
|
|
_outboundMessageHandler.Init(&_linkManager, _logic);
|
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,
|
|
|
|
_logic,
|
|
|
|
_nodedb,
|
|
|
|
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,
|
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);
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
// create inbound links, if we are a service node
|
2020-07-06 19:13:01 +00:00
|
|
|
for (const LinksConfig::LinkInfo& serverConfig : conf.links.m_InboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-03-30 21:33:36 +00:00
|
|
|
auto server = iwp::NewInboundLink(
|
2020-04-07 20:41:11 +00:00
|
|
|
m_keyManager,
|
|
|
|
util::memFn(&AbstractRouter::rc, this),
|
2019-06-26 21:39:29 +00:00
|
|
|
util::memFn(&AbstractRouter::HandleRecvLinkMessageBuffer, this),
|
2019-08-07 16:33:29 +00:00
|
|
|
util::memFn(&AbstractRouter::Sign, this),
|
2020-06-08 20:03:03 +00:00
|
|
|
util::memFn(&Router::ConnectionEstablished, this),
|
2019-06-26 21:39:29 +00:00
|
|
|
util::memFn(&AbstractRouter::CheckRenegotiateValid, this),
|
2020-06-08 20:03:03 +00:00
|
|
|
util::memFn(&Router::ConnectionTimedOut, this),
|
2019-11-04 18:49:08 +00:00
|
|
|
util::memFn(&AbstractRouter::SessionClosed, this),
|
2020-06-11 11:44:02 +00:00
|
|
|
util::memFn(&AbstractRouter::PumpLL, this),
|
|
|
|
util::memFn(&AbstractRouter::QueueWork, this));
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2020-03-19 22:20:45 +00:00
|
|
|
const std::string& key = serverConfig.interface;
|
|
|
|
int af = serverConfig.addressFamily;
|
|
|
|
uint16_t port = serverConfig.port;
|
2020-04-07 20:41:11 +00:00
|
|
|
if (!server->Configure(netloop(), key, af, port))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-24 17:10:05 +00:00
|
|
|
throw std::runtime_error(stringify("failed to bind inbound link on ", key, " port ", port));
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
_linkManager.AddLink(std::move(server), true);
|
|
|
|
}
|
|
|
|
|
2020-08-21 15:07:37 +00:00
|
|
|
if (conf.links.m_InboundLinks.empty() and m_isServiceNode)
|
|
|
|
{
|
|
|
|
throw std::runtime_error("service node enabled but have no inbound links");
|
|
|
|
}
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
// Network config
|
2020-07-06 19:13:01 +00:00
|
|
|
if (conf.network.m_enableProfiling.has_value() and not*conf.network.m_enableProfiling)
|
2018-12-19 17:48:29 +00:00
|
|
|
{
|
2020-05-20 19:46:08 +00:00
|
|
|
routerProfiling().Disable();
|
|
|
|
LogWarn("router profiling explicitly disabled");
|
2018-12-19 17:48:29 +00:00
|
|
|
}
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2020-07-06 19:13:01 +00:00
|
|
|
if (!conf.network.m_routerProfilesFile.empty())
|
2018-12-19 16:17:41 +00:00
|
|
|
{
|
2020-07-06 19:13:01 +00:00
|
|
|
routerProfilesFile = conf.network.m_routerProfilesFile;
|
2019-06-26 21:39:29 +00:00
|
|
|
routerProfiling().Load(routerProfilesFile.c_str());
|
|
|
|
llarp::LogInfo("setting profiles to ", routerProfilesFile);
|
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
|
|
|
|
2020-05-26 17:03:21 +00:00
|
|
|
// peer stats
|
2020-07-06 19:13:01 +00:00
|
|
|
if (conf.router.m_enablePeerStats)
|
2020-05-26 17:03:21 +00:00
|
|
|
{
|
|
|
|
LogInfo("Initializing peerdb...");
|
2020-05-27 01:57:27 +00:00
|
|
|
m_peerDb = std::make_shared<PeerDb>();
|
2020-07-06 19:13:01 +00:00
|
|
|
m_peerDb->configure(conf.router);
|
2020-05-26 17:03:21 +00:00
|
|
|
}
|
2020-08-28 11:35:10 +00:00
|
|
|
else if (IsServiceNode())
|
2020-06-05 16:16:00 +00:00
|
|
|
{
|
2020-08-28 11:26:50 +00:00
|
|
|
throw std::runtime_error("peer stats must be enabled when running as relay");
|
2020-06-05 16:16:00 +00:00
|
|
|
}
|
2020-05-26 17:03:21 +00:00
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
// Logging config
|
2020-04-02 17:45:33 +00:00
|
|
|
LogContext::Instance().Initialize(
|
2020-07-06 19:13:01 +00:00
|
|
|
conf.logging.m_logLevel,
|
|
|
|
conf.logging.m_logType,
|
|
|
|
conf.logging.m_logFile,
|
|
|
|
conf.router.m_nickname,
|
2020-06-11 11:44:02 +00:00
|
|
|
util::memFn(&AbstractRouter::QueueDiskIO, this));
|
2018-12-19 17:48:29 +00:00
|
|
|
|
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();
|
|
|
|
LogInfo(nodedb()->num_loaded(), " RCs loaded");
|
|
|
|
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-05-15 12:38:04 +00:00
|
|
|
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();
|
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
|
|
|
{
|
|
|
|
std::stringstream ss;
|
2020-02-26 20:16:57 +00:00
|
|
|
ss << "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
|
|
|
{
|
|
|
|
ss << " snode | known/svc/clients: " << nodedb()->num_loaded() << "/"
|
2020-04-07 18:38:56 +00:00
|
|
|
<< NumberOfConnectedRouters() << "/" << NumberOfConnectedClients() << " | "
|
|
|
|
<< pathContext().CurrentTransitPaths() << " active paths";
|
2020-02-25 22:32:57 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ss << " client | known/connected: " << nodedb()->num_loaded() << "/"
|
|
|
|
<< NumberOfConnectedRouters() << " | path success: ";
|
2020-04-07 18:38:56 +00:00
|
|
|
hiddenServiceContext().ForEachService([&ss](const auto& name, const auto& ep) {
|
|
|
|
ss << " [" << name << " " << std::setprecision(4)
|
|
|
|
<< (100.0 * ep->CurrentBuildStats().SuccessRatio()) << "%]";
|
|
|
|
return true;
|
|
|
|
});
|
2020-02-25 22:32:57 +00:00
|
|
|
}
|
|
|
|
const auto status = ss.str();
|
|
|
|
::sd_notify(0, status.c_str());
|
|
|
|
}
|
2019-12-07 19:21:26 +00:00
|
|
|
#endif
|
|
|
|
|
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
|
|
|
|
|
|
|
const bool isSvcNode = IsServiceNode();
|
|
|
|
|
2020-06-04 21:02:05 +00:00
|
|
|
if (_rc.ExpiresSoon(now, std::chrono::milliseconds(randint() % 10000))
|
|
|
|
|| (now - _rc.last_updated) > rcRegenInterval)
|
2018-12-19 17:48:29 +00:00
|
|
|
{
|
2020-06-04 21:02:05 +00:00
|
|
|
LogInfo("regenerating RC");
|
|
|
|
if (!UpdateOurRC(false))
|
|
|
|
LogError("Failed to update our RC");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GossipRCIfNeeded(_rc);
|
2020-01-30 17:23:16 +00:00
|
|
|
}
|
2020-03-09 15:04:28 +00:00
|
|
|
const bool gotWhitelist = _rcLookupHandler.HaveReceivedWhitelist();
|
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))
|
2020-03-08 12:09:48 +00:00
|
|
|
return false;
|
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())
|
2020-03-08 12:09:48 +00:00
|
|
|
return true;
|
2020-03-08 12:12:23 +00:00
|
|
|
// clients have a notion of a whilelist
|
|
|
|
// 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)
|
2020-03-08 12:09:48 +00:00
|
|
|
return false;
|
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)
|
2020-03-09 15:04:28 +00:00
|
|
|
return false;
|
|
|
|
// 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
|
2020-03-08 12:09:48 +00:00
|
|
|
return not _rcLookupHandler.RemoteIsAllowed(rc.pubkey);
|
|
|
|
});
|
2019-02-25 12:46:40 +00:00
|
|
|
|
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();
|
2020-04-07 18:38:56 +00:00
|
|
|
if (timepoint_now >= m_NextExploreAt)
|
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;
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (connected < connectToNum)
|
2019-09-03 15:56:56 +00:00
|
|
|
{
|
|
|
|
size_t dlt = connectToNum - connected;
|
2019-04-25 11:00:18 +00:00
|
|
|
LogInfo("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
|
2020-04-07 18:38:56 +00:00
|
|
|
if (routerProfiling().ShouldSave(now))
|
2019-03-25 15:41:37 +00:00
|
|
|
{
|
2020-06-11 11:44:02 +00:00
|
|
|
QueueDiskIO([&]() { routerProfiling().Save(routerProfilesFile.c_str()); });
|
2019-03-25 15:41:37 +00:00
|
|
|
}
|
2020-01-14 17:01:41 +00:00
|
|
|
// save nodedb
|
2020-04-07 18:38:56 +00:00
|
|
|
if (nodedb()->ShouldSaveToDisk(now))
|
2020-01-14 17:01:41 +00:00
|
|
|
{
|
|
|
|
nodedb()->AsyncFlushToDisk();
|
|
|
|
}
|
2020-05-26 17:03:21 +00:00
|
|
|
|
2020-06-04 16:00:30 +00:00
|
|
|
if (m_peerDb)
|
|
|
|
{
|
|
|
|
// TODO: throttle this?
|
|
|
|
// TODO: need to capture session stats when session terminates / is removed from link manager
|
|
|
|
_linkManager.updatePeerDb(m_peerDb);
|
|
|
|
|
|
|
|
if (m_peerDb->shouldFlush(now))
|
|
|
|
{
|
|
|
|
LogWarn("Queing database flush...");
|
2020-07-02 16:36:12 +00:00
|
|
|
QueueDiskIO([this]() { m_peerDb->flushDatabase(); });
|
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
|
2020-02-24 19:40:45 +00:00
|
|
|
Router::ScheduleTicker(llarp_time_t interval)
|
2018-06-06 12:46:26 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
ticker_job_id = _logic->call_later(interval, std::bind(&Router::handle_router_ticker, this));
|
2018-06-06 12:46:26 +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");
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2020-05-19 18:53:03 +00:00
|
|
|
Router::SetRouterWhitelist(const std::vector<RouterID> routers)
|
2019-02-15 22:19:19 +00:00
|
|
|
{
|
2019-06-26 21:39:29 +00:00
|
|
|
_rcLookupHandler.SetRouterWhitelist(routers);
|
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
|
|
|
{
|
2020-05-21 14:09:45 +00:00
|
|
|
m_RPCServer->AsyncServeRPC(rpcBindAddr);
|
|
|
|
LogInfo("Bound RPC server to ", rpcBindAddr);
|
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;
|
|
|
|
|
2019-02-11 19:45:42 +00:00
|
|
|
routerProfiling().Load(routerProfilesFile.c_str());
|
2018-10-12 12:05:03 +00:00
|
|
|
|
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
|
|
|
{
|
2020-01-25 17:21:28 +00:00
|
|
|
_rc.routerVersion = RouterVersion(llarp::VERSION, LLARP_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))
|
|
|
|
{
|
|
|
|
// override ip and port
|
|
|
|
if (not _ourAddress.isEmpty())
|
2019-04-08 18:21:01 +00:00
|
|
|
{
|
2020-06-04 21:02:05 +00:00
|
|
|
ai.fromIpAddress(_ourAddress);
|
2019-04-08 18:21:01 +00:00
|
|
|
}
|
2020-06-04 21:02:05 +00:00
|
|
|
if (RouterContact::BlockBogons && IsBogon(ai.ip))
|
|
|
|
return;
|
|
|
|
LogInfo("adding address: ", ai);
|
|
|
|
_rc.addrs.push_back(ai);
|
|
|
|
}
|
|
|
|
});
|
2018-12-10 16:26:46 +00:00
|
|
|
|
2020-08-19 19:10:11 +00:00
|
|
|
if (ExitEnabled() and IsServiceNode())
|
|
|
|
{
|
|
|
|
LogError("exit mode not supported while service node");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
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());
|
2020-06-11 11:44:02 +00:00
|
|
|
if (!_linkManager.StartLinks(_logic))
|
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
|
|
|
{
|
|
|
|
ssize_t loaded = _nodedb->LoadAll();
|
|
|
|
llarp::LogInfo("loaded ", loaded, " RCs");
|
2020-04-07 18:38:56 +00:00
|
|
|
if (loaded < 0)
|
2020-01-14 20:12:47 +00:00
|
|
|
{
|
|
|
|
// shouldn't be possible
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (this->nodedb()->Insert(rc))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
LogInfo("added bootstrap node ", RouterID(rc.pubkey));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LogError("Failed to add bootstrap node ", RouterID(rc.pubkey));
|
|
|
|
}
|
|
|
|
_dht->impl->Nodes()->PutNode(rc);
|
|
|
|
}
|
|
|
|
|
2019-10-04 09:10:55 +00:00
|
|
|
LogInfo("have ", _nodedb->num_loaded(), " routers");
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2019-09-16 16:12:05 +00:00
|
|
|
_netloop->add_ticker(std::bind(&Router::PumpLL, this));
|
2019-10-07 10:08:47 +00:00
|
|
|
|
2020-02-24 19:40:45 +00:00
|
|
|
ScheduleTicker(ROUTER_TICK_INTERVAL);
|
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
|
2019-12-09 13:08:30 +00:00
|
|
|
LogContext::Instance().DropToRuntimeLevel();
|
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();
|
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();
|
|
|
|
nodedb()->AsyncFlushToDisk();
|
2020-02-24 19:40:45 +00:00
|
|
|
_logic->call_later(200ms, std::bind(&Router::AfterStopLinks, this));
|
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);
|
|
|
|
LogContext::Instance().RevertRuntimeLevel();
|
|
|
|
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);
|
2019-12-09 13:08:30 +00:00
|
|
|
LogContext::Instance().RevertRuntimeLevel();
|
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();
|
2020-02-24 19:40:45 +00:00
|
|
|
_logic->call_later(200ms, std::bind(&Router::AfterStopIssued, this));
|
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());
|
2020-04-28 14:22:04 +00:00
|
|
|
_exitContext.AddExitEndpoint("default-connectivity", networkConfig, dnsConfig);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!_rcLookupHandler.RemoteIsAllowed(rc.pubkey))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
_outboundSessionMaker.CreateSessionTo(rc, nullptr);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:46 +00:00
|
|
|
bool
|
2019-01-05 13:45:05 +00:00
|
|
|
Router::InitOutboundLinks()
|
2018-06-18 22:03:50 +00:00
|
|
|
{
|
2020-03-30 21:33:36 +00:00
|
|
|
auto link = iwp::NewOutboundLink(
|
2020-04-07 18:38:56 +00:00
|
|
|
m_keyManager,
|
|
|
|
util::memFn(&AbstractRouter::rc, this),
|
|
|
|
util::memFn(&AbstractRouter::HandleRecvLinkMessageBuffer, this),
|
|
|
|
util::memFn(&AbstractRouter::Sign, this),
|
2020-06-08 20:03:03 +00:00
|
|
|
util::memFn(&Router::ConnectionEstablished, this),
|
2020-04-07 18:38:56 +00:00
|
|
|
util::memFn(&AbstractRouter::CheckRenegotiateValid, this),
|
2020-06-08 20:03:03 +00:00
|
|
|
util::memFn(&Router::ConnectionTimedOut, this),
|
2020-04-07 18:38:56 +00:00
|
|
|
util::memFn(&AbstractRouter::SessionClosed, this),
|
2020-06-11 11:44:02 +00:00
|
|
|
util::memFn(&AbstractRouter::PumpLL, this),
|
|
|
|
util::memFn(&AbstractRouter::QueueWork, this));
|
2020-04-07 18:38:56 +00:00
|
|
|
|
2020-04-07 20:41:11 +00:00
|
|
|
if (!link)
|
2020-04-24 17:10:05 +00:00
|
|
|
throw std::runtime_error("NewOutboundLink() failed to provide a link");
|
2018-05-21 12:43:32 +00:00
|
|
|
|
2019-08-07 16:33:29 +00:00
|
|
|
const auto afs = {AF_INET, AF_INET6};
|
2018-06-28 11:29:10 +00:00
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto af : afs)
|
2018-12-10 16:26:46 +00:00
|
|
|
{
|
2020-04-29 20:19:48 +00:00
|
|
|
if (not link->Configure(netloop(), "*", af, m_OutboundPort))
|
2019-01-05 13:48:00 +00:00
|
|
|
continue;
|
2020-04-29 20:19:48 +00:00
|
|
|
|
2019-08-07 16:33:29 +00:00
|
|
|
_linkManager.AddLink(std::move(link), false);
|
|
|
|
return true;
|
2018-06-21 12:52:45 +00:00
|
|
|
}
|
2020-04-24 17:10:05 +00:00
|
|
|
throw std::runtime_error(
|
|
|
|
stringify("Failed to init AF_INET and AF_INET6 on port ", m_OutboundPort));
|
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
|