2021-03-09 23:24:35 +01:00
|
|
|
#include "router_hive.hpp"
|
2020-02-26 21:12:14 +01:00
|
|
|
|
2021-03-09 23:24:35 +01:00
|
|
|
#include <llarp.hpp>
|
|
|
|
#include <llarp/util/str.hpp>
|
|
|
|
#include <llarp/router/abstractrouter.hpp>
|
2020-02-27 02:18:38 +01:00
|
|
|
|
2020-02-26 23:05:04 +01:00
|
|
|
#include <chrono>
|
2020-03-04 06:57:07 +01:00
|
|
|
#include <algorithm>
|
2020-10-28 23:26:43 +01:00
|
|
|
#include <csignal>
|
2020-02-26 23:05:04 +01:00
|
|
|
|
2020-02-28 05:01:14 +01:00
|
|
|
using namespace std::chrono_literals;
|
|
|
|
|
2020-02-26 21:12:14 +01:00
|
|
|
namespace tooling
|
|
|
|
{
|
2020-02-26 23:05:04 +01:00
|
|
|
void
|
2021-03-23 20:00:46 +01:00
|
|
|
RouterHive::AddRouter(const std::shared_ptr<llarp::Config>& config, bool isSNode)
|
2020-02-26 23:05:04 +01:00
|
|
|
{
|
2021-03-23 20:00:46 +01:00
|
|
|
auto& container = (isSNode ? relays : clients);
|
2020-07-01 21:46:52 +02:00
|
|
|
|
|
|
|
llarp::RuntimeOptions opts;
|
2021-03-23 20:00:46 +01:00
|
|
|
opts.isSNode = isSNode;
|
2020-06-15 20:53:17 +02:00
|
|
|
|
2020-07-01 21:46:52 +02:00
|
|
|
Context_ptr context = std::make_shared<HiveContext>(this);
|
2021-02-02 19:16:34 +01:00
|
|
|
context->Configure(config);
|
2020-07-01 21:46:52 +02:00
|
|
|
context->Setup(opts);
|
2020-06-30 17:45:26 +02:00
|
|
|
|
|
|
|
auto routerId = llarp::RouterID(context->router->pubkey());
|
|
|
|
container[routerId] = context;
|
2022-07-19 20:22:38 +02:00
|
|
|
fmt::print("Generated router with ID {}\n", routerId);
|
2020-02-26 23:05:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-07 20:38:56 +02:00
|
|
|
RouterHive::AddRelay(const std::shared_ptr<llarp::Config>& config)
|
2020-03-02 23:10:01 +01:00
|
|
|
{
|
2020-06-15 20:53:17 +02:00
|
|
|
AddRouter(config, true);
|
2020-03-02 23:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-07 20:38:56 +02:00
|
|
|
RouterHive::AddClient(const std::shared_ptr<llarp::Config>& config)
|
2020-02-26 23:05:04 +01:00
|
|
|
{
|
2020-06-15 20:53:17 +02:00
|
|
|
AddRouter(config, false);
|
2020-03-02 23:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-06-15 20:53:17 +02:00
|
|
|
RouterHive::StartRouters(bool isRelay)
|
2020-03-02 23:10:01 +01:00
|
|
|
{
|
2020-06-15 20:53:17 +02:00
|
|
|
auto& container = (isRelay ? relays : clients);
|
|
|
|
|
2022-07-19 20:22:38 +02:00
|
|
|
for (const auto& [routerId, ctx] : container)
|
2020-02-26 23:05:04 +01:00
|
|
|
{
|
2022-07-19 20:22:38 +02:00
|
|
|
routerMainThreads.emplace_back([ctx = ctx, isRelay = isRelay]() {
|
2020-06-30 17:45:26 +02:00
|
|
|
ctx->Run(llarp::RuntimeOptions{false, false, isRelay});
|
2020-02-28 19:44:27 +01:00
|
|
|
});
|
2020-03-04 01:28:23 +01:00
|
|
|
std::this_thread::sleep_for(2ms);
|
2020-02-26 23:05:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-02 23:10:01 +01:00
|
|
|
void
|
|
|
|
RouterHive::StartRelays()
|
|
|
|
{
|
2020-06-15 20:53:17 +02:00
|
|
|
StartRouters(true);
|
2020-03-02 23:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RouterHive::StartClients()
|
|
|
|
{
|
2020-06-15 20:53:17 +02:00
|
|
|
StartRouters(false);
|
2020-03-02 23:10:01 +01:00
|
|
|
}
|
|
|
|
|
2020-02-26 23:05:04 +01:00
|
|
|
void
|
|
|
|
RouterHive::StopRouters()
|
|
|
|
{
|
2020-02-29 23:53:54 +01:00
|
|
|
llarp::LogInfo("Signalling all routers to stop");
|
2021-03-02 08:02:59 +01:00
|
|
|
for (auto& [routerId, ctx] : relays)
|
2020-03-02 23:10:01 +01:00
|
|
|
{
|
2021-03-02 23:49:25 +01:00
|
|
|
ctx->loop->call([ctx = ctx]() { ctx->HandleSignal(SIGINT); });
|
2020-03-02 23:10:01 +01:00
|
|
|
}
|
2021-03-02 08:02:59 +01:00
|
|
|
for (auto& [routerId, ctx] : clients)
|
2020-02-26 23:05:04 +01:00
|
|
|
{
|
2021-03-02 23:49:25 +01:00
|
|
|
ctx->loop->call([ctx = ctx]() { ctx->HandleSignal(SIGINT); });
|
2020-02-26 23:05:04 +01:00
|
|
|
}
|
|
|
|
|
2020-02-29 23:53:54 +01:00
|
|
|
llarp::LogInfo("Waiting on routers to be stopped");
|
2020-06-15 20:53:17 +02:00
|
|
|
for (auto [routerId, ctx] : relays)
|
2020-03-02 23:10:01 +01:00
|
|
|
{
|
2020-06-30 17:45:26 +02:00
|
|
|
while (ctx->IsUp())
|
2020-03-02 23:10:01 +01:00
|
|
|
{
|
|
|
|
std::this_thread::sleep_for(10ms);
|
|
|
|
}
|
|
|
|
}
|
2020-06-15 20:53:17 +02:00
|
|
|
for (auto [routerId, ctx] : clients)
|
2020-02-26 23:05:04 +01:00
|
|
|
{
|
2020-06-30 17:45:26 +02:00
|
|
|
while (ctx->IsUp())
|
2020-02-26 23:05:04 +01:00
|
|
|
{
|
|
|
|
std::this_thread::sleep_for(10ms);
|
|
|
|
}
|
|
|
|
}
|
2020-02-28 02:23:36 +01:00
|
|
|
|
2020-02-29 23:53:54 +01:00
|
|
|
llarp::LogInfo("Joining all router threads");
|
2020-04-07 20:38:56 +02:00
|
|
|
for (auto& thread : routerMainThreads)
|
2020-02-28 02:23:36 +01:00
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
while (not thread.joinable())
|
2020-02-28 02:23:36 +01:00
|
|
|
{
|
|
|
|
std::this_thread::sleep_for(500ms);
|
|
|
|
}
|
|
|
|
thread.join();
|
|
|
|
}
|
2020-02-29 00:24:16 +01:00
|
|
|
|
2020-02-29 23:53:54 +01:00
|
|
|
llarp::LogInfo("RouterHive::StopRouters finished");
|
2020-02-26 23:05:04 +01:00
|
|
|
}
|
|
|
|
|
2020-02-26 21:12:14 +01:00
|
|
|
void
|
2020-02-27 22:16:46 +01:00
|
|
|
RouterHive::NotifyEvent(RouterEventPtr event)
|
2020-02-26 21:12:14 +01:00
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
std::lock_guard<std::mutex> guard{eventQueueMutex};
|
2020-02-26 21:12:14 +01:00
|
|
|
|
2020-03-03 01:42:06 +01:00
|
|
|
eventQueue.push_back(std::move(event));
|
2020-02-26 21:12:14 +01:00
|
|
|
}
|
|
|
|
|
2020-02-28 03:19:47 +01:00
|
|
|
RouterEventPtr
|
|
|
|
RouterHive::GetNextEvent()
|
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
std::lock_guard<std::mutex> guard{eventQueueMutex};
|
2020-02-29 23:53:54 +01:00
|
|
|
|
2020-04-07 20:38:56 +02:00
|
|
|
if (not eventQueue.empty())
|
2020-02-28 05:01:14 +01:00
|
|
|
{
|
2020-02-29 23:53:54 +01:00
|
|
|
auto ptr = std::move(eventQueue.front());
|
2020-03-03 01:42:06 +01:00
|
|
|
eventQueue.pop_front();
|
2020-02-29 23:53:54 +01:00
|
|
|
return ptr;
|
2020-02-28 05:01:14 +01:00
|
|
|
}
|
|
|
|
return nullptr;
|
2020-02-28 03:19:47 +01:00
|
|
|
}
|
|
|
|
|
2020-04-07 20:38:56 +02:00
|
|
|
std::deque<RouterEventPtr>
|
2020-03-03 01:42:06 +01:00
|
|
|
RouterHive::GetAllEvents()
|
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
std::lock_guard<std::mutex> guard{eventQueueMutex};
|
2020-03-03 01:42:06 +01:00
|
|
|
|
2020-04-07 20:38:56 +02:00
|
|
|
std::deque<RouterEventPtr> events;
|
|
|
|
if (not eventQueue.empty())
|
2020-03-03 01:42:06 +01:00
|
|
|
{
|
|
|
|
eventQueue.swap(events);
|
|
|
|
}
|
|
|
|
return events;
|
|
|
|
}
|
|
|
|
|
2020-02-28 17:29:15 +01:00
|
|
|
void
|
2020-06-30 17:45:26 +02:00
|
|
|
RouterHive::VisitRouter(Context_ptr ctx, std::function<void(Context_ptr)> visit)
|
2020-03-02 23:10:01 +01:00
|
|
|
{
|
2021-03-02 08:02:59 +01:00
|
|
|
// TODO: this should be called from each router's appropriate Loop, e.g.:
|
2021-03-02 23:49:25 +01:00
|
|
|
// ctx->loop->call([visit, ctx]() { visit(ctx); });
|
2020-07-07 02:11:15 +02:00
|
|
|
// however, this causes visit calls to be deferred
|
|
|
|
visit(ctx);
|
2020-03-02 23:10:01 +01:00
|
|
|
}
|
|
|
|
|
2020-07-01 21:46:52 +02:00
|
|
|
HiveRouter*
|
2020-06-24 22:07:15 +02:00
|
|
|
RouterHive::GetRelay(const llarp::RouterID& id, bool needMutexLock)
|
2020-06-17 23:42:22 +02:00
|
|
|
{
|
2020-06-25 23:59:42 +02:00
|
|
|
auto guard =
|
|
|
|
needMutexLock ? std::make_optional<std::lock_guard<std::mutex>>(routerMutex) : std::nullopt;
|
2020-06-24 22:07:15 +02:00
|
|
|
|
2020-06-17 23:42:22 +02:00
|
|
|
auto itr = relays.find(id);
|
|
|
|
if (itr == relays.end())
|
|
|
|
return nullptr;
|
|
|
|
|
2020-06-30 17:45:26 +02:00
|
|
|
auto ctx = itr->second;
|
2020-07-01 21:46:52 +02:00
|
|
|
return ctx->getRouterAsHiveRouter();
|
2020-06-17 23:42:22 +02:00
|
|
|
}
|
|
|
|
|
2020-04-07 20:38:56 +02:00
|
|
|
std::vector<size_t>
|
2020-03-04 06:57:07 +01:00
|
|
|
RouterHive::RelayConnectedRelays()
|
|
|
|
{
|
2021-03-02 08:02:59 +01:00
|
|
|
std::lock_guard guard{routerMutex};
|
2020-04-07 20:38:56 +02:00
|
|
|
std::vector<size_t> results;
|
2020-03-04 06:57:07 +01:00
|
|
|
results.resize(relays.size());
|
|
|
|
std::mutex results_lock;
|
|
|
|
|
2020-04-07 20:38:56 +02:00
|
|
|
size_t i = 0;
|
2020-03-04 06:57:07 +01:00
|
|
|
size_t done_count = 0;
|
2021-03-02 08:02:59 +01:00
|
|
|
for (auto& [routerId, ctx] : relays)
|
2020-03-04 06:57:07 +01:00
|
|
|
{
|
2021-03-02 23:49:25 +01:00
|
|
|
ctx->loop->call([&, i, ctx = ctx]() {
|
2020-06-30 17:45:26 +02:00
|
|
|
size_t count = ctx->router->NumberOfConnectedRouters();
|
2021-03-02 08:02:59 +01:00
|
|
|
std::lock_guard guard{results_lock};
|
2020-03-04 06:57:07 +01:00
|
|
|
results[i] = count;
|
|
|
|
done_count++;
|
|
|
|
});
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
2020-04-07 20:38:56 +02:00
|
|
|
while (true)
|
2020-03-04 06:57:07 +01:00
|
|
|
{
|
|
|
|
size_t read_done_count = 0;
|
|
|
|
{
|
2021-03-02 08:02:59 +01:00
|
|
|
std::lock_guard guard{results_lock};
|
2020-03-04 06:57:07 +01:00
|
|
|
read_done_count = done_count;
|
|
|
|
}
|
2020-04-07 20:38:56 +02:00
|
|
|
if (read_done_count == relays.size())
|
2020-03-04 06:57:07 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
std::this_thread::sleep_for(100ms);
|
|
|
|
}
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
2020-04-24 19:10:05 +02:00
|
|
|
// TODO: DRY -- this smells a lot like RelayConnectedRelays()
|
2020-04-07 20:38:56 +02:00
|
|
|
std::vector<llarp::RouterContact>
|
2020-03-04 06:57:07 +01:00
|
|
|
RouterHive::GetRelayRCs()
|
|
|
|
{
|
2020-06-24 22:07:15 +02:00
|
|
|
std::lock_guard<std::mutex> guard{routerMutex};
|
2020-04-07 20:38:56 +02:00
|
|
|
std::vector<llarp::RouterContact> results;
|
2020-03-04 06:57:07 +01:00
|
|
|
results.resize(relays.size());
|
|
|
|
|
2020-04-07 20:38:56 +02:00
|
|
|
size_t i = 0;
|
2020-06-15 20:53:17 +02:00
|
|
|
for (auto [routerId, ctx] : relays)
|
2020-03-04 06:57:07 +01:00
|
|
|
{
|
2020-06-30 17:45:26 +02:00
|
|
|
results[i] = ctx->router->rc();
|
2020-03-04 06:57:07 +01:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
2020-06-17 23:42:22 +02:00
|
|
|
void
|
2020-07-01 21:46:52 +02:00
|
|
|
RouterHive::ForEachRelay(std::function<void(Context_ptr)> visit)
|
2020-06-17 23:42:22 +02:00
|
|
|
{
|
|
|
|
for (auto [routerId, ctx] : relays)
|
|
|
|
{
|
|
|
|
VisitRouter(ctx, visit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-07-01 21:46:52 +02:00
|
|
|
RouterHive::ForEachClient(std::function<void(Context_ptr)> visit)
|
2020-06-17 23:42:22 +02:00
|
|
|
{
|
|
|
|
for (auto [routerId, ctx] : clients)
|
|
|
|
{
|
|
|
|
VisitRouter(ctx, visit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// safely visit every router context
|
|
|
|
void
|
2020-07-01 21:46:52 +02:00
|
|
|
RouterHive::ForEachRouter(std::function<void(Context_ptr)> visit)
|
2020-06-17 23:42:22 +02:00
|
|
|
{
|
2020-07-01 21:46:52 +02:00
|
|
|
ForEachRelay(visit);
|
|
|
|
ForEachClient(visit);
|
2020-06-17 23:42:22 +02:00
|
|
|
}
|
|
|
|
|
2020-03-07 02:20:11 +01:00
|
|
|
} // namespace tooling
|