diff --git a/include/llarp.hpp b/include/llarp.hpp index 762bf38b1..4c07e764e 100644 --- a/include/llarp.hpp +++ b/include/llarp.hpp @@ -90,6 +90,14 @@ namespace llarp bool CallSafe(std::function f); + /// Creates a router. Can be overridden to allow a different class of router + /// to be created instead. Defaults to llarp::Router. + virtual std::unique_ptr + makeRouter( + std::shared_ptr worker, + llarp_ev_loop_ptr __netloop, + std::shared_ptr logic); + #ifdef LOKINET_HIVE void InjectHive(tooling::RouterHive* hive); diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index c072080b1..5cdd64b84 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -227,7 +227,11 @@ if(TESTNET) endif() if(WITH_HIVE) - target_sources(liblokinet PRIVATE tooling/router_hive.cpp) + target_sources(liblokinet PRIVATE + tooling/router_hive.cpp + tooling/hive_router.cpp + tooling/hive_context.cpp + ) endif() target_link_libraries(liblokinet PUBLIC cxxopts lokinet-platform lokinet-util lokinet-cryptography) diff --git a/llarp/context.cpp b/llarp/context.cpp index 7daa00818..7925e7836 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -90,7 +90,7 @@ namespace llarp crypto = std::make_unique(); cryptoManager = std::make_unique(crypto.get()); - router = std::make_unique(mainloop, logic); + router = makeRouter(worker, mainloop, logic); nodedb = std::make_unique( nodedb_dir, [r = router.get()](auto call) { r->QueueDiskIO(std::move(call)); }); @@ -105,6 +105,15 @@ namespace llarp throw std::runtime_error("Config::Setup() failed to load database"); } + std::unique_ptr + Context::makeRouter( + std::shared_ptr worker, + llarp_ev_loop_ptr netloop, + std::shared_ptr logic) + { + return std::make_unique(worker, netloop, logic); + } + int Context::Run(const RuntimeOptions& opts) { diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index e49f0329c..8d49d8ddf 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -49,7 +49,7 @@ namespace llarp { - struct Router final : public AbstractRouter + struct Router : public AbstractRouter { llarp_time_t _lastPump = 0s; bool ready; @@ -318,7 +318,7 @@ namespace llarp explicit Router(llarp_ev_loop_ptr __netloop, std::shared_ptr logic); - ~Router() override; + virtual ~Router() override; bool HandleRecvLinkMessageBuffer(ILinkSession* from, const llarp_buffer_t& msg) override; diff --git a/llarp/tooling/hive_context.cpp b/llarp/tooling/hive_context.cpp new file mode 100644 index 000000000..94b9ef770 --- /dev/null +++ b/llarp/tooling/hive_context.cpp @@ -0,0 +1,16 @@ +#include + +#include + +namespace tooling +{ + std::unique_ptr + HiveContext::makeRouter( + std::shared_ptr worker, + llarp_ev_loop_ptr netloop, + std::shared_ptr logic) + { + return std::make_unique(worker, netloop, logic); + } + +} // namespace tooling diff --git a/llarp/tooling/hive_context.hpp b/llarp/tooling/hive_context.hpp new file mode 100644 index 000000000..8851b3835 --- /dev/null +++ b/llarp/tooling/hive_context.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace tooling +{ + /// HiveContext is a subclass of llarp::Context which allows RouterHive to + /// perform custom behavior which might be undesirable in production code. + struct HiveContext : public llarp::Context + { + std::unique_ptr + makeRouter( + std::shared_ptr worker, + llarp_ev_loop_ptr netloop, + std::shared_ptr logic) override; + }; + +} // namespace tooling diff --git a/llarp/tooling/hive_router.cpp b/llarp/tooling/hive_router.cpp new file mode 100644 index 000000000..55bae5cf8 --- /dev/null +++ b/llarp/tooling/hive_router.cpp @@ -0,0 +1,31 @@ +#include + +namespace tooling +{ + HiveRouter::HiveRouter( + std::shared_ptr worker, + llarp_ev_loop_ptr netloop, + std::shared_ptr logic) + : Router(worker, netloop, logic) + { + } + + bool + HiveRouter::disableGossipingRC_TestingOnly() + { + return m_disableGossiping; + } + + void + HiveRouter::disableGossiping() + { + m_disableGossiping = false; + } + + void + HiveRouter::enableGossiping() + { + m_disableGossiping = true; + } + +} // namespace tooling diff --git a/llarp/tooling/hive_router.hpp b/llarp/tooling/hive_router.hpp new file mode 100644 index 000000000..743588550 --- /dev/null +++ b/llarp/tooling/hive_router.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +namespace tooling +{ + /// HiveRouter is a subclass of Router which overrides specific behavior in + /// order to perform testing-related functions. It exists largely to prevent + /// this behavior (which may often be "dangerous") from leaking into release + /// code. + struct HiveRouter : public llarp::Router + { + HiveRouter( + std::shared_ptr worker, + llarp_ev_loop_ptr netloop, + std::shared_ptr logic); + + virtual ~HiveRouter() = default; + + /// Override logic to prevent base Router class from gossiping its RC. + virtual bool + disableGossipingRC_TestingOnly() override; + + void + disableGossiping(); + + void + enableGossiping(); + + protected: + bool m_disableGossiping = false; + }; + +} // namespace tooling diff --git a/llarp/tooling/router_hive.hpp b/llarp/tooling/router_hive.hpp index fb9a35384..924a0554e 100644 --- a/llarp/tooling/router_hive.hpp +++ b/llarp/tooling/router_hive.hpp @@ -21,6 +21,8 @@ namespace llarp namespace tooling { + struct HiveRouter; // Hive's version of Router + struct RouterHive { using Context_ptr = std::shared_ptr; diff --git a/pybind/llarp/router.cpp b/pybind/llarp/router.cpp index 7531c27c5..d6d74e40d 100644 --- a/pybind/llarp/router.cpp +++ b/pybind/llarp/router.cpp @@ -1,6 +1,7 @@ #include "common.hpp" #include "router/abstractrouter.hpp" +#include "tooling/hive_router.hpp" namespace llarp { @@ -12,4 +13,16 @@ namespace llarp .def("Stop", &AbstractRouter::Stop) .def("peerDb", &AbstractRouter::peerDb); } + } // namespace llarp + +namespace tooling +{ + void + HiveRouter_Init(py::module& mod) + { + py::class_(mod, "HiveRouter") + .def("disableGossiping", &HiveRouter::disableGossiping) + .def("enableGossiping", &HiveRouter::enableGossiping); + } +} // namespace tooling