Merge pull request #1557 from jagerman/uvw-overhaul

libuv -> uvw overhaul
pull/1568/head
Jeff 3 years ago committed by GitHub
commit 76ee6734db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,2 +1,2 @@
HeaderFilterRegex: 'llarp/.*'
Checks: 'readability-else-after-return,clang-analyzer-core-*,modernize-*'
Checks: 'readability-else-after-return,clang-analyzer-core-*,modernize-*,-modernize-use-trailing-return-type,-modernize-use-nodiscard,bugprone-*'

4
.gitignore vendored

@ -5,7 +5,7 @@
*.o
*.so
build/
/build*/
**/__pycache__/**
llarpd
@ -18,6 +18,8 @@ CMakeFiles
CMakeCache.txt
.ninja_log
.ninja_deps
/.cache/
/compile_commands.json
callgrind.*
.gdb_history

3
.gitmodules vendored

@ -26,3 +26,6 @@
[submodule "external/oxen-mq"]
path = external/oxen-mq
url = https://github.com/oxen-io/oxen-mq
[submodule "external/uvw"]
path = external/uvw
url = https://github.com/jagerman/uvw.git

@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.10) # bionic's cmake version
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Has to be set before `project()`, and ignored on non-macos:
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.12 CACHE STRING "macOS deployment target (Apple clang only)")
@ -162,7 +164,7 @@ endif()
option(FORCE_OXENMQ_SUBMODULE "force using oxenmq submodule" OFF)
if(NOT FORCE_OXENMQ_SUBMODULE)
pkg_check_modules(OXENMQ liboxenmq>=1.2.2)
pkg_check_modules(OXENMQ liboxenmq>=1.2.4)
endif()
if(OXENMQ_FOUND)
add_library(oxenmq INTERFACE)
@ -210,11 +212,10 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
endif()
if (NOT MSVC_VERSION)
add_compile_options(-Wall -Wextra -Wno-unknown-pragmas)
# vla are evil
add_compile_options(-Wvla)
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fpermissive>)
add_compile_options(-Wno-unused-function -Wno-deprecated-declarations -Wno-unknown-pragmas)
add_compile_options(-Wall -Wextra -Wno-unknown-pragmas)
# vla are evil
add_compile_options(-Werror=vla)
add_compile_options(-Wno-unused-function -Wno-deprecated-declarations)
endif()
include(cmake/coverage.cmake)
@ -315,6 +316,7 @@ if(SUBMODULE_CHECK)
check_submodule(external/pybind11)
check_submodule(external/sqlite_orm)
check_submodule(external/oxen-mq)
check_submodule(external/uvw)
endif()
endif()

@ -9,6 +9,7 @@ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
if(NOT MSVC_VERSION)
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wno-bad-function-cast>)
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wno-cast-function-type>)
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fpermissive>)
# unlike unix where you get a *single* compiler ID string in .comment
# GNU ld sees fit to merge *all* the .ident sections in object files
# to .r[o]data section one after the other!

@ -6,7 +6,6 @@
#include <util/logging/logger.hpp>
#include <util/logging/ostream_logger.hpp>
#include <util/str.hpp>
#include <util/thread/logic.hpp>
#ifdef _WIN32
#include <dbghelp.h>
@ -69,7 +68,7 @@ void
handle_signal(int sig)
{
if (ctx)
LogicCall(ctx->logic, std::bind(&llarp::Context::HandleSignal, ctx.get(), sig));
ctx->loop->call([sig] { ctx->HandleSignal(sig); });
else
std::cerr << "Received signal " << sig << ", but have no context yet. Ignoring!" << std::endl;
}

1
external/uvw vendored

@ -0,0 +1 @@
Subproject commit 51724bcef0effa361710677a10cb6d7fd58c4616

@ -16,14 +16,13 @@ namespace llarp
class Platform;
}
class Logic;
class EventLoop;
struct Config;
struct RouterContact;
struct Config;
struct Crypto;
struct CryptoManager;
struct AbstractRouter;
struct EventLoop;
class NodeDB;
namespace thread
@ -43,9 +42,8 @@ namespace llarp
std::shared_ptr<Crypto> crypto = nullptr;
std::shared_ptr<CryptoManager> cryptoManager = nullptr;
std::shared_ptr<AbstractRouter> router = nullptr;
std::shared_ptr<Logic> logic = nullptr;
std::shared_ptr<EventLoop> loop = nullptr;
std::shared_ptr<NodeDB> nodedb = nullptr;
std::shared_ptr<EventLoop> mainloop;
std::string nodedb_dir;
virtual ~Context() = default;
@ -93,7 +91,7 @@ namespace llarp
/// Creates a router. Can be overridden to allow a different class of router
/// to be created instead. Defaults to llarp::Router.
virtual std::shared_ptr<AbstractRouter>
makeRouter(std::shared_ptr<EventLoop> __netloop, std::shared_ptr<Logic> logic);
makeRouter(const std::shared_ptr<EventLoop>& loop);
/// create the vpn platform for use in creating network interfaces
virtual std::shared_ptr<llarp::vpn::Platform>

@ -19,7 +19,6 @@ add_library(lokinet-util
util/mem.cpp
util/printer.cpp
util/str.cpp
util/thread/logic.cpp
util/thread/queue_manager.cpp
util/thread/threading.cpp
util/time.cpp
@ -47,6 +46,10 @@ if(ANDROID)
target_link_libraries(lokinet-util PUBLIC log)
endif()
add_library(uvw INTERFACE)
target_include_directories(uvw INTERFACE ${PROJECT_SOURCE_DIR}/external/uvw/src)
target_link_libraries(uvw INTERFACE libuv)
add_library(lokinet-platform
# for networking
ev/ev.cpp
@ -63,7 +66,7 @@ add_library(lokinet-platform
vpn/platform.cpp
)
target_link_libraries(lokinet-platform PUBLIC lokinet-cryptography lokinet-util Threads::Threads base_libs libuv)
target_link_libraries(lokinet-platform PUBLIC lokinet-cryptography lokinet-util Threads::Threads base_libs uvw)
if (ANDROID)
@ -81,7 +84,6 @@ endif()
if (WIN32)
target_sources(lokinet-platform PRIVATE
ev/ev_libuv.cpp
win32/win32_inet.c
win32/win32_intrnl.c)

@ -1,11 +1,13 @@
#include <llarp.hpp>
#include <constants/version.hpp>
#include <constants/evloop.hpp>
#include <config/config.hpp>
#include <crypto/crypto_libsodium.hpp>
#include <dht/context.hpp>
#include <ev/ev.hpp>
#include <ev/vpnio.hpp>
#include <memory>
#include <nodedb.hpp>
#include <router/router.hpp>
#include <service/context.hpp>
@ -24,7 +26,10 @@ namespace llarp
bool
Context::CallSafe(std::function<void(void)> f)
{
return logic && LogicCall(logic, f);
if (!loop)
return false;
loop->call(std::move(f));
return true;
}
void
@ -35,8 +40,6 @@ namespace llarp
config = std::move(conf);
logic = std::make_shared<Logic>();
nodedb_dir = fs::path{config->router.m_dataDir / nodedb_dirname}.string();
}
@ -61,19 +64,16 @@ namespace llarp
llarp::LogInfo(llarp::VERSION_FULL, " ", llarp::RELEASE_MOTTO);
llarp::LogInfo("starting up");
if (mainloop == nullptr)
if (!loop)
{
auto jobQueueSize = std::max(event_loop_queue_size, config->router.m_JobQueueSize);
mainloop = llarp_make_ev_loop(jobQueueSize);
loop = EventLoop::create(jobQueueSize);
}
logic->set_event_loop(mainloop.get());
mainloop->set_logic(logic);
crypto = std::make_shared<sodium::CryptoLibSodium>();
cryptoManager = std::make_shared<CryptoManager>(crypto.get());
router = makeRouter(mainloop, logic);
router = makeRouter(loop);
nodedb = std::make_shared<NodeDB>(
nodedb_dir, [r = router.get()](auto call) { r->QueueDiskIO(std::move(call)); });
@ -83,9 +83,10 @@ namespace llarp
}
std::shared_ptr<AbstractRouter>
Context::makeRouter(std::shared_ptr<EventLoop> netloop, std::shared_ptr<Logic> logic)
Context::makeRouter(const EventLoop_ptr& loop)
{
return std::make_shared<Router>(netloop, logic, makeVPNPlatform());
return std::static_pointer_cast<AbstractRouter>(
std::make_shared<Router>(loop, makeVPNPlatform()));
}
std::shared_ptr<vpn::Platform>
@ -116,7 +117,7 @@ namespace llarp
// run net io thread
llarp::LogInfo("running mainloop");
llarp_ev_loop_run_single_process(mainloop, logic);
loop->run();
if (closeWaiter)
{
closeWaiter->set_value();
@ -187,8 +188,8 @@ namespace llarp
llarp::LogDebug("free router");
router.reset();
llarp::LogDebug("free logic");
logic.reset();
llarp::LogDebug("free loop");
loop.reset();
}
#if defined(ANDROID)

@ -17,7 +17,6 @@
#include <path/path_context.hpp>
#include <router/abstractrouter.hpp>
#include <routing/dht_message.hpp>
#include <util/thread/logic.hpp>
#include <nodedb.hpp>
#include <profiling.hpp>
#include <router/i_rc_lookup_handler.hpp>
@ -161,7 +160,7 @@ namespace llarp
GetIntroSetByLocation(const Key_t& location) const override;
void
handle_cleaner_timer(uint64_t interval);
handle_cleaner_timer();
/// explore dht for new routers
void
@ -202,15 +201,13 @@ namespace llarp
void
PutRCNodeAsync(const RCNode& val) override
{
auto func = std::bind(&Bucket<RCNode>::PutNode, Nodes(), val);
LogicCall(router->logic(), func);
router->loop()->call([nodes = Nodes(), val] { nodes->PutNode(val); });
}
void
DelRCNodeAsync(const Key_t& val) override
{
auto func = std::bind(&Bucket<RCNode>::DelNode, Nodes(), val);
LogicCall(router->logic(), func);
router->loop()->call([nodes = Nodes(), val] { nodes->DelNode(val); });
}
const Key_t&
@ -289,8 +286,7 @@ namespace llarp
ExploreNetworkVia(const Key_t& peer) override;
private:
void
ScheduleCleanupTimer();
std::shared_ptr<int> _timer_keepalive;
void
CleanupTX();
@ -333,7 +329,7 @@ namespace llarp
}
void
Context::handle_cleaner_timer(__attribute__((unused)) uint64_t interval)
Context::handle_cleaner_timer()
{
// clean up transactions
CleanupTX();
@ -354,7 +350,6 @@ namespace llarp
++itr;
}
}
ScheduleCleanupTimer();
}
void
@ -458,14 +453,8 @@ namespace llarp
_services = std::make_unique<Bucket<ISNode>>(ourKey, llarp::randint);
llarp::LogDebug("initialize dht with key ", ourKey);
// start cleanup timer
ScheduleCleanupTimer();
}
void
Context::ScheduleCleanupTimer()
{
router->logic()->call_later(
1s, std::bind(&llarp::dht::Context::handle_cleaner_timer, this, 1000));
_timer_keepalive = std::make_shared<int>(0);
router->loop()->call_every(1s, _timer_keepalive, [this] { handle_cleaner_timer(); });
}
void

@ -17,7 +17,7 @@ namespace llarp
uint64_t relayOrder,
const Key_t& addr,
AbstractContext* ctx,
__attribute__((unused)) const Key_t& askpeer)
[[maybe_unused]] const Key_t& askpeer)
: ServiceAddressLookup(TXOwner{ctx->OurKey(), txid}, addr, ctx, relayOrder, nullptr)
, localPath(pathid)
{}

@ -19,7 +19,7 @@ namespace llarp
uint64_t relayOrder,
const Key_t& addr,
AbstractContext* ctx,
__attribute__((unused)) const Key_t& askpeer);
[[maybe_unused]] const Key_t& askpeer);
void
SendReply() override;

@ -63,7 +63,7 @@ namespace llarp
bool
RelayedGotIntroMessage::HandleMessage(
llarp_dht_context* ctx,
__attribute__((unused)) std::vector<std::unique_ptr<IMessage>>& replies) const
[[maybe_unused]] std::vector<std::unique_ptr<IMessage>>& replies) const
{
// TODO: implement me better?
auto pathset = ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID);

@ -82,7 +82,7 @@ namespace llarp
bool
GotRouterMessage::HandleMessage(
llarp_dht_context* ctx,
__attribute__((unused)) std::vector<std::unique_ptr<IMessage>>& replies) const
[[maybe_unused]] std::vector<std::unique_ptr<IMessage>>& replies) const
{
auto& dht = *ctx->impl;
if (relayed)

@ -122,6 +122,16 @@ namespace llarp
return true;
}
OwnedBuffer
Message::ToBuffer() const
{
std::array<byte_t, 1500> tmp;
llarp_buffer_t buf{tmp};
if (not Encode(&buf))
throw std::runtime_error("cannot encode dns message");
return OwnedBuffer::copy_used(buf);
}
void Message::AddServFail(RR_TTL_t)
{
if (questions.size())

@ -83,6 +83,10 @@ namespace llarp
bool
Decode(llarp_buffer_t* buf) override;
// Wrapper around Encode that encodes into a new buffer and returns it
[[nodiscard]] OwnedBuffer
ToBuffer() const;
std::ostream&
print(std::ostream& stream, int level, int spaces) const;

@ -1,34 +1,21 @@
#include <dns/server.hpp>
#include <dns/dns.hpp>
#include <crypto/crypto.hpp>
#include <util/thread/logic.hpp>
#include <array>
#include <utility>
#include <ev/udp_handle.hpp>
namespace llarp::dns
{
static std::vector<byte_t>
MessageToBuffer(Message msg)
{
std::array<byte_t, 1500> tmp = {{0}};
llarp_buffer_t buf{tmp};
if (not msg.Encode(&buf))
throw std::runtime_error("cannot encode dns message");
std::vector<byte_t> pkt;
pkt.resize(buf.cur - buf.base);
std::copy_n(tmp.data(), pkt.size(), pkt.data());
return pkt;
}
PacketHandler::PacketHandler(Logic_ptr logic, IQueryHandler* h)
: m_QueryHandler{h}, m_Logic{logic}
PacketHandler::PacketHandler(EventLoop_ptr loop, IQueryHandler* h)
: m_QueryHandler{h}, m_Loop{std::move(loop)}
{}
Proxy::Proxy(llarp_ev_loop_ptr loop, Logic_ptr logic, IQueryHandler* h)
: PacketHandler{logic, h}, m_Loop(std::move(loop))
Proxy::Proxy(EventLoop_ptr loop, IQueryHandler* h)
: PacketHandler{loop, h}, m_Loop(std::move(loop))
{
m_Server.user = this;
m_Server.tick = nullptr;
m_Server.recvfrom = &HandleUDP;
m_Server = m_Loop->make_udp(
[this](UDPHandle&, SockAddr a, OwnedBuffer buf) { HandlePacket(a, a, buf); });
}
void
@ -43,23 +30,7 @@ namespace llarp::dns
{
if (not PacketHandler::Start(addr, std::move(resolvers)))
return false;
return (llarp_ev_add_udp(m_Loop, &m_Server, addr) == 0);
}
static Proxy::Buffer_t
CopyBuffer(const llarp_buffer_t& buf)
{
std::vector<byte_t> msgbuf(buf.sz);
std::copy_n(buf.base, buf.sz, msgbuf.data());
return msgbuf;
}
void
Proxy::HandleUDP(llarp_udp_io* u, const SockAddr& from, ManagedBuffer buf)
{
Buffer_t msgbuf = CopyBuffer(buf.underlying);
auto self = static_cast<Proxy*>(u->user);
self->HandlePacket(from, from, std::move(msgbuf));
return m_Server->listen(addr);
}
void
@ -81,25 +52,19 @@ namespace llarp::dns
bool
PacketHandler::SetupUnboundResolver(std::vector<IpAddress> resolvers)
{
auto failFunc = [self = weak_from_this()](SockAddr from, SockAddr to, Message msg) {
auto this_ptr = self.lock();
if (this_ptr)
{
this_ptr->SendServerMessageBufferTo(from, to, MessageToBuffer(std::move(msg)));
}
auto failFunc = [self = weak_from_this()](
const SockAddr& from, const SockAddr& to, Message msg) {
if (auto this_ptr = self.lock())
this_ptr->SendServerMessageBufferTo(from, to, msg.ToBuffer());
};
auto replyFunc = [self = weak_from_this()](
SockAddr from, SockAddr to, std::vector<byte_t> buf) {
auto this_ptr = self.lock();
if (this_ptr)
{
this_ptr->SendServerMessageBufferTo(from, to, std::move(buf));
}
auto replyFunc = [self = weak_from_this()](auto&&... args) {
if (auto this_ptr = self.lock())
this_ptr->SendServerMessageBufferTo(std::forward<decltype(args)>(args)...);
};
m_UnboundResolver =
std::make_shared<UnboundResolver>(m_Logic, std::move(replyFunc), std::move(failFunc));
std::make_shared<UnboundResolver>(m_Loop, std::move(replyFunc), std::move(failFunc));
if (not m_UnboundResolver->Init())
{
llarp::LogError("Failed to initialize upstream DNS resolver.");
@ -121,26 +86,24 @@ namespace llarp::dns
}
void
Proxy::SendServerMessageBufferTo(SockAddr, SockAddr to, Buffer_t buf)
Proxy::SendServerMessageBufferTo(const SockAddr&, const SockAddr& to, llarp_buffer_t buf)
{
if (llarp_ev_udp_sendto(&m_Server, to, buf) < 0)
if (!m_Server->send(to, buf))
llarp::LogError("dns reply failed");
}
bool
PacketHandler::ShouldHandlePacket(SockAddr to, SockAddr from, Buffer_t buf) const
PacketHandler::ShouldHandlePacket(
const SockAddr& to, [[maybe_unused]] const SockAddr& from, llarp_buffer_t buf) const
{
(void)from;
MessageHeader hdr;
llarp_buffer_t pkt{buf};
if (not hdr.Decode(&pkt))
if (not hdr.Decode(&buf))
{
return false;
}
Message msg{hdr};
if (not msg.Decode(&pkt))
if (not msg.Decode(&buf))
{
return false;
}
@ -156,18 +119,17 @@ namespace llarp::dns
}
void
PacketHandler::HandlePacket(SockAddr resolver, SockAddr from, Buffer_t buf)
PacketHandler::HandlePacket(const SockAddr& resolver, const SockAddr& from, llarp_buffer_t buf)
{
MessageHeader hdr;
llarp_buffer_t pkt{buf};
if (not hdr.Decode(&pkt))
if (not hdr.Decode(&buf))
{
llarp::LogWarn("failed to parse dns header from ", from);
return;
}
Message msg(hdr);
if (not msg.Decode(&pkt))
if (not msg.Decode(&buf))
{
llarp::LogWarn("failed to parse dns message from ", from);
return;
@ -186,7 +148,7 @@ namespace llarp::dns
// yea it is, let's turn off DoH because god is dead.
msg.AddNXReply();
// press F to pay respects
SendServerMessageBufferTo(resolver, from, MessageToBuffer(std::move(msg)));
SendServerMessageBufferTo(resolver, from, msg.ToBuffer());
return;
}
}
@ -194,7 +156,7 @@ namespace llarp::dns
if (m_QueryHandler && m_QueryHandler->ShouldHookDNSMessage(msg))
{
auto reply = [self = shared_from_this(), to = from, resolver](dns::Message msg) {
self->SendServerMessageBufferTo(resolver, to, MessageToBuffer(std::move(msg)));
self->SendServerMessageBufferTo(resolver, to, msg.ToBuffer());
};
if (!m_QueryHandler->HandleHookedDNSMessage(std::move(msg), reply))
{
@ -206,7 +168,7 @@ namespace llarp::dns
// no upstream resolvers
// let's serv fail it
msg.AddServFail();
SendServerMessageBufferTo(resolver, from, MessageToBuffer(std::move(msg)));
SendServerMessageBufferTo(resolver, from, msg.ToBuffer());
}
else
{

@ -2,9 +2,8 @@
#define LLARP_DNS_SERVER_HPP
#include <dns/message.hpp>
#include <ev/ev.h>
#include <ev/ev.hpp>
#include <net/net.hpp>
#include <util/thread/logic.hpp>
#include <dns/unbound_resolver.hpp>
#include <unordered_map>
@ -14,8 +13,9 @@ namespace llarp
namespace dns
{
/// handler of dns query hooking
struct IQueryHandler
class IQueryHandler
{
public:
virtual ~IQueryHandler() = default;
/// return true if we should hook this message
@ -27,12 +27,11 @@ namespace llarp
HandleHookedDNSMessage(Message query, std::function<void(Message)> sendReply) = 0;
};
struct PacketHandler : public std::enable_shared_from_this<PacketHandler>
// Base class for DNS lookups
class PacketHandler : public std::enable_shared_from_this<PacketHandler>
{
using Logic_ptr = std::shared_ptr<Logic>;
using Buffer_t = std::vector<uint8_t>;
explicit PacketHandler(Logic_ptr logic, IQueryHandler* handler);
public:
explicit PacketHandler(EventLoop_ptr loop, IQueryHandler* handler);
virtual ~PacketHandler() = default;
@ -46,18 +45,18 @@ namespace llarp
Restart();
void
HandlePacket(SockAddr resolver, SockAddr from, Buffer_t buf);
HandlePacket(const SockAddr& resolver, const SockAddr& from, llarp_buffer_t buf);
bool
ShouldHandlePacket(SockAddr to, SockAddr from, Buffer_t buf) const;
ShouldHandlePacket(const SockAddr& to, const SockAddr& from, llarp_buffer_t buf) const;
protected:
virtual void
SendServerMessageBufferTo(SockAddr from, SockAddr to, Buffer_t buf) = 0;
SendServerMessageBufferTo(const SockAddr& from, const SockAddr& to, llarp_buffer_t buf) = 0;
private:
void
HandleUpstreamFailure(SockAddr from, SockAddr to, Message msg);
HandleUpstreamFailure(const SockAddr& from, const SockAddr& to, Message msg);
bool
SetupUnboundResolver(std::vector<IpAddress> resolvers);
@ -65,30 +64,26 @@ namespace llarp
IQueryHandler* const m_QueryHandler;
std::set<IpAddress> m_Resolvers;
std::shared_ptr<UnboundResolver> m_UnboundResolver;
Logic_ptr m_Logic;
EventLoop_ptr m_Loop;
};
struct Proxy : public PacketHandler
// Proxying DNS handler that listens on a UDP port for proper DNS requests.
class Proxy : public PacketHandler
{
using Logic_ptr = std::shared_ptr<Logic>;
explicit Proxy(llarp_ev_loop_ptr loop, Logic_ptr logic, IQueryHandler* handler);
public:
explicit Proxy(EventLoop_ptr loop, IQueryHandler* handler);
bool
Start(SockAddr localaddr, std::vector<IpAddress> resolvers) override;
using Buffer_t = std::vector<uint8_t>;
protected:
void
SendServerMessageBufferTo(SockAddr from, SockAddr to, Buffer_t buf) override;
private:
static void
HandleUDP(llarp_udp_io*, const SockAddr&, ManagedBuffer);
SendServerMessageBufferTo(
const SockAddr& from, const SockAddr& to, llarp_buffer_t buf) override;
private:
llarp_udp_io m_Server;
llarp_ev_loop_ptr m_Loop;
std::shared_ptr<UDPHandle> m_Server;
EventLoop_ptr m_Loop;
};
} // namespace dns
} // namespace llarp

@ -35,16 +35,11 @@ namespace llarp::dns
unboundContext = nullptr;
}
UnboundResolver::UnboundResolver(
std::shared_ptr<Logic> logic, ReplyFunction reply, FailFunction fail)
UnboundResolver::UnboundResolver(EventLoop_ptr loop, ReplyFunction reply, FailFunction fail)
: unboundContext(nullptr)
, started(false)
, replyFunc([logic, reply](auto res, auto source, auto buf) {
LogicCall(logic, [source, buf, reply, res]() { reply(res, source, buf); });
})
, failFunc([logic, fail](auto res, auto source, auto message) {
LogicCall(logic, [source, message, res, fail]() { fail(res, source, message); });
})
, replyFunc(loop->make_caller(std::move(reply)))
, failFunc(loop->make_caller(std::move(fail)))
{}
// static callback
@ -65,8 +60,8 @@ namespace llarp::dns
ub_resolve_free(result);
return;
}
std::vector<byte_t> pkt(result->answer_len);
std::copy_n(static_cast<byte_t*>(result->answer_packet), pkt.size(), pkt.data());
OwnedBuffer pkt{(size_t)result->answer_len};
std::memcpy(pkt.buf.get(), result->answer_packet, pkt.sz);
llarp_buffer_t buf(pkt);
MessageHeader hdr;

@ -7,7 +7,6 @@
#include <queue>
#include <ev/ev.hpp>
#include <util/thread/logic.hpp>
#include <dns/message.hpp>
@ -18,8 +17,9 @@
namespace llarp::dns
{
using ReplyFunction =
std::function<void(SockAddr resolver, SockAddr source, std::vector<byte_t> buf)>;
using FailFunction = std::function<void(SockAddr resolver, SockAddr source, Message msg)>;
std::function<void(const SockAddr& resolver, const SockAddr& source, OwnedBuffer buf)>;
using FailFunction =
std::function<void(const SockAddr& resolver, const SockAddr& source, Message msg)>;
class UnboundResolver : public std::enable_shared_from_this<UnboundResolver>
{
@ -36,7 +36,7 @@ namespace llarp::dns
Reset();
public:
UnboundResolver(std::shared_ptr<Logic> logic, ReplyFunction replyFunc, FailFunction failFunc);
UnboundResolver(EventLoop_ptr loop, ReplyFunction replyFunc, FailFunction failFunc);
static void
Callback(void* data, int err, ub_result* result);

@ -1,7 +1,6 @@
#include <ev/ev.h>
#include <ev/ev.hpp>
#include <util/mem.hpp>
#include <util/str.hpp>
#include <util/thread/logic.hpp>
#include <cstddef>
#include <cstring>
@ -10,64 +9,11 @@
// We libuv now
#include <ev/ev_libuv.hpp>
llarp_ev_loop_ptr
llarp_make_ev_loop(size_t queueLength)
namespace llarp
{
llarp_ev_loop_ptr r = std::make_shared<libuv::Loop>(queueLength);
r->init();
r->update_time();
return r;
}
void
llarp_ev_loop_run_single_process(llarp_ev_loop_ptr ev, std::shared_ptr<llarp::Logic> logic)
{
if (ev == nullptr or logic == nullptr)
return;
ev->run();
logic->clear_event_loop();
ev->stopped();
}
int
llarp_ev_add_udp(const llarp_ev_loop_ptr& ev, struct llarp_udp_io* udp, const llarp::SockAddr& src)
{
if (ev == nullptr or udp == nullptr)
EventLoop_ptr
EventLoop::create(size_t queueLength)
{
llarp::LogError("Attempting llarp_ev_add_udp() with null event loop or udp io struct.");
return -1;
return std::make_shared<llarp::uv::Loop>(queueLength);
}
udp->parent = ev.get();
if (ev->udp_listen(udp, src))
return 0;
llarp::LogError("llarp_ev_add_udp() call to udp_listen failed.");
return -1;
}
int
llarp_ev_close_udp(struct llarp_udp_io* udp)
{
if (udp->parent->udp_close(udp))
return 0;
return -1;
}
llarp_time_t
llarp_ev_loop_time_now_ms(const llarp_ev_loop_ptr& loop)
{
if (loop)
return loop->time_now();
return llarp::time_now_ms();
}
void
llarp_ev_loop_stop(const llarp_ev_loop_ptr& loop)
{
loop->stop();
}
int
llarp_ev_udp_sendto(struct llarp_udp_io* udp, const llarp::SockAddr& to, const llarp_buffer_t& buf)
{
return udp->sendto(udp, to, buf.base, buf.sz);
}
} // namespace llarp

@ -1,88 +0,0 @@
#ifndef LLARP_EV_H
#define LLARP_EV_H
#include <net/ip_address.hpp>
#include <util/buffer.hpp>
#include <util/time.hpp>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#else
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#include <net/net_if.hpp>
#include <memory>
#include <cstdint>
#include <cstdlib>
#include <constants/evloop.hpp>
/**
* ev.h
*
* event handler (cross platform high performance event system for IO)
*/
#define EV_TICK_INTERVAL 10
namespace llarp
{
class Logic;
struct EventLoop;
} // namespace llarp
using llarp_ev_loop_ptr = std::shared_ptr<llarp::EventLoop>;
/// make an event loop using our baked in event loop on Windows
/// make an event loop using libuv otherwise.
/// @param queue_size how big the logic job queue is
llarp_ev_loop_ptr
llarp_make_ev_loop(std::size_t queue_size = llarp::event_loop_queue_size);
// run mainloop
void
llarp_ev_loop_run_single_process(llarp_ev_loop_ptr ev, std::shared_ptr<llarp::Logic> logic);
/// get the current time on the event loop
llarp_time_t
llarp_ev_loop_time_now_ms(const llarp_ev_loop_ptr& ev);
/// stop event loop and wait for it to complete all jobs
void
llarp_ev_loop_stop(const llarp_ev_loop_ptr& ev);
/// UDP handling configuration
struct llarp_udp_io
{
/// set after added
int fd;
void* user;
void* impl;
llarp::EventLoop* parent;
/// called every event loop tick after reads
void (*tick)(struct llarp_udp_io*);
void (*recvfrom)(struct llarp_udp_io*, const llarp::SockAddr& source, ManagedBuffer);
/// set by parent
int (*sendto)(struct llarp_udp_io*, const llarp::SockAddr&, const byte_t*, size_t);
};
/// add UDP handler
int
llarp_ev_add_udp(const llarp_ev_loop_ptr& ev, struct llarp_udp_io* udp, const llarp::SockAddr& src);
/// send a UDP packet
int
llarp_ev_udp_sendto(struct llarp_udp_io* udp, const llarp::SockAddr& to, const llarp_buffer_t& pkt);
/// close UDP handler
int
llarp_ev_close_udp(struct llarp_udp_io* udp);
#endif

@ -1,18 +1,10 @@
#ifndef LLARP_EV_HPP
#define LLARP_EV_HPP
#include <net/ip_address.hpp>
#include <net/ip_packet.hpp>
#include <ev/ev.h>
#include <util/buffer.hpp>
#include <util/codel.hpp>
#include <util/time.hpp>
#include <util/thread/threading.hpp>
// writev
#ifndef _WIN32
#include <sys/uio.h>
#include <unistd.h>
#endif
#include <constants/evloop.hpp>
#include <algorithm>
#include <deque>
@ -20,97 +12,166 @@
#include <future>
#include <utility>
#ifdef _WIN32
// From the preview SDK, should take a look at that
// periodically in case its definition changes
#define UNIX_PATH_MAX 108
typedef struct sockaddr_un
{
ADDRESS_FAMILY sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
} SOCKADDR_UN, *PSOCKADDR_UN;
#else
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || (__APPLE__ && __MACH__)
#include <sys/event.h>
#endif
#include <sys/un.h>
#endif
struct llarp_ev_pkt_pipe;
#ifndef MAX_WRITE_QUEUE_SIZE
#define MAX_WRITE_QUEUE_SIZE (1024UL)
#endif
#ifndef EV_READ_BUF_SZ
#define EV_READ_BUF_SZ (4 * 1024UL)
#endif
#ifndef EV_WRITE_BUF_SZ
#define EV_WRITE_BUF_SZ (4 * 1024UL)
#endif
namespace llarp
{
struct SockAddr;
struct UDPHandle;
namespace vpn
{
class NetworkInterface;
}
/// distinct event loop waker uper
class EventLoopWakeup
namespace net
{
protected:
std::function<void()> callback;
struct IPPacket;
}
/// distinct event loop waker upper; used to idempotently schedule a task on the next event loop
///
/// Created via EventLoop::make_waker(...).
class EventLoopWakeup
{
public:
EventLoopWakeup(std::function<void()> cb) : callback{cb}
{}
/// Destructor: remove the task from the event loop task. (Note that destruction here only
/// initiates removal of the task from the underlying event loop: it is *possible* for the
/// callback to fire again if already triggered depending on the underlying implementation).
virtual ~EventLoopWakeup() = default;
/// async wakeup and call callback once
/// trigger this task to run on the next event loop iteration; does nothing if already
/// triggered.
virtual void
Wakeup() = 0;
Trigger() = 0;
};
/// holds a repeated task on the event loop; the task is removed on destruction
class EventLoopRepeater
{
public:
// Destructor: if the task has been started then it is removed from the event loop. Note
// that it is possible for a task to fire *after* destruction of this container;
// destruction only initiates removal of the periodic task.
virtual ~EventLoopRepeater() = default;
/// end operation
// Starts the repeater to call `task` every `every` period.
virtual void
End() = 0;
start(llarp_time_t every, std::function<void()> task) = 0;
};
// this (nearly!) abstract base class
// is overriden for each platform
struct EventLoop
class EventLoop
{
virtual bool
init() = 0;
virtual int
public:
// Runs the event loop. This does not return until sometime after `stop()` is called (and so
// typically you want to run this in its own thread).
virtual void
run() = 0;
virtual bool
running() const = 0;
virtual void
update_time()
{}
virtual llarp_time_t
time_now() const
{
return llarp::time_now_ms();
}
// Triggers an event loop wakeup; use when something has been done that requires the event loop
// to wake up (e.g. adding to queues). This is called implicitly by call() and call_soon().
// Idempotent and thread-safe.
virtual void
stopped(){};
wakeup() = 0;
// Calls a function/lambda/etc. If invoked from within the event loop itself this calls the
// given lambda immediately; otherwise it passes it to `call_soon()` to be queued to run at the
// next event loop iteration.
template <typename Callable>
void
call(Callable&& f)
{
if (inEventLoop())
{
f();
wakeup();
}
else
call_soon(std::forward<Callable>(f));
}
virtual uint32_t
call_after_delay(llarp_time_t delay_ms, std::function<void(void)> callback) = 0;
// Queues a function to be called on the next event loop cycle and triggers it to be called as
// soon as possible; can be called from any thread. Note that, unlike `call()`, this queues the
// job even if called from the event loop thread itself and so you *usually* want to use
// `call()` instead.
virtual void
call_soon(std::function<void(void)> f) = 0;
// Adds a timer to the event loop to invoke the given callback after a delay.
virtual void
cancel_delayed_call(uint32_t call_id) = 0;
call_later(llarp_time_t delay_ms, std::function<void(void)> callback) = 0;
// Created a repeated timer that fires ever `repeat` time unit. Lifetime of the event
// is tied to `owner`: callbacks will be invoked so long as `owner` remains alive, but
// the first time it repeats after `owner` has been destroyed the internal timer object will
// be destroyed and no more callbacks will be invoked.
//
// Intended to be used as:
//
// loop->call_every(100ms, weak_from_this(), [this] { some_func(); });
//
// Alternative, when shared_from_this isn't available for a type, you can use a local member
// shared_ptr (or even create a simple one, for more fine-grained control) to tie the lifetime:
//
// m_keepalive = std::make_shared<int>(42);
// loop->call_every(100ms, m_keepalive, [this] { some_func(); });
//
template <typename Callable> // Templated so that the compiler can inline the call
void
call_every(llarp_time_t repeat, std::weak_ptr<void> owner, Callable f)
{
auto repeater = make_repeater();
auto& r = *repeater; // reference *before* we pass ownership into the lambda below
r.start(
repeat,
[repeater = std::move(repeater), owner = std::move(owner), f = std::move(f)]() mutable {
if (auto ptr = owner.lock())
f();
else
repeater.reset(); // Trigger timer removal on tied object destruction (we should be
// the only thing holding the repeater; ideally it would be a
// unique_ptr, but std::function says nuh-uh).
});
}
// Wraps a lambda with a lambda that triggers it to be called via loop->call()
// when invoked. E.g.:
//
// auto x = loop->make_caller([] (int a) { std::cerr << a; });
// x(42);
// x(99);
//
// will schedule two calls of the inner lambda (with different arguments) in the event loop.
// Arguments are forwarded to the inner lambda (allowing moving arguments into it).
template <typename Callable>
auto
make_caller(Callable f)
{
return [this, f = std::move(f)](auto&&... args) {
if (inEventLoop())
return f(std::forward<decltype(args)>(args)...);
// This shared pointer in a pain in the ass but needed because this lambda is going into a
// std::function that only accepts copyable lambdas. I *want* to simply capture:
// args=std::make_tuple(std::forward<decltype(args)>(args)...) but that fails if any given
// arguments aren't copyable (because of std::function). Dammit.
auto args_tuple_ptr = std::make_shared<std::tuple<std::decay_t<decltype(args)>...>>(
std::forward<decltype(args)>(args)...);
call_soon([f, args = std::move(args_tuple_ptr)]() mutable {
// Moving away the tuple args here is okay because this lambda will only be invoked once
std::apply(f, std::move(*args));
});
};
}
virtual bool
add_network_interface(
@ -123,33 +184,40 @@ namespace llarp
virtual void
stop() = 0;
virtual bool
udp_listen(llarp_udp_io* l, const llarp::SockAddr& src) = 0;
virtual bool
udp_close(llarp_udp_io* l) = 0;
/// give this event loop a logic thread for calling
virtual void set_logic(std::shared_ptr<llarp::Logic>) = 0;
virtual ~EventLoop() = default;
virtual void
call_soon(std::function<void(void)> f) = 0;
using UDPReceiveFunc = std::function<void(UDPHandle&, SockAddr src, llarp::OwnedBuffer buf)>;
// Constructs a UDP socket that can be used for sending and/or receiving
virtual std::shared_ptr<UDPHandle>
make_udp(UDPReceiveFunc on_recv) = 0;
/// set the function that is called once per cycle the flush all the queues
virtual void
set_pump_function(std::function<void(void)> pumpll) = 0;
virtual void
register_poll_fd_readable(int fd, std::function<void(void)> callback) = 0;
/// Make a thread-safe event loop waker (an "async" in libuv terminology) on this event loop;
/// you can call `->Trigger()` on the returned shared pointer to fire the callback at the next
/// available event loop iteration. (Multiple Trigger calls invoked before the call is actually
/// made are coalesced into one call).
virtual std::shared_ptr<EventLoopWakeup>
make_waker(std::function<void()> callback) = 0;
virtual void
deregister_poll_fd_readable(int fd) = 0;
// Initializes a new repeated task object. Note that the task is not actually added to the event
// loop until you call start() on the returned object. Typically invoked via call_every.
virtual std::shared_ptr<EventLoopRepeater>
make_repeater() = 0;
// Constructs and initializes a new default (libuv) event loop
static std::shared_ptr<EventLoop>
create(size_t queueLength = event_loop_queue_size);
/// make an event loop waker on this event loop
virtual EventLoopWakeup*
make_event_loop_waker(std::function<void()> callback) = 0;
// Returns true if called from within the event loop thread, false otherwise.
virtual bool
inEventLoop() const = 0;
};
using EventLoop_ptr = std::shared_ptr<EventLoop>;
} // namespace llarp
#endif

@ -1,322 +1,91 @@
#include <ev/ev_libuv.hpp>
#include <ev/vpn.hpp>
#include <util/thread/logic.hpp>
#include <memory>
#include <thread>
#include <type_traits>
#include <util/thread/queue.hpp>
#include <cstring>
#include "ev/ev.hpp"
namespace libuv
{
#define LoopCall(h, ...) \
{ \
auto __f = __VA_ARGS__; \
__f(); \
}
#include <uvw.hpp>
struct glue
{
virtual ~glue() = default;
virtual void
Close() = 0;
};
class UVWakeup final : public llarp::EventLoopWakeup, public glue
namespace llarp::uv
{
class UVWakeup final : public EventLoopWakeup
{
uv_async_t m_Impl;
const int m_Idx;
static void
OnWake(uv_async_t* self)
{
static_cast<UVWakeup*>(self->data)->callback();
}
std::shared_ptr<uvw::AsyncHandle> async;
public:
UVWakeup(uv_loop_t* loop, std::function<void()> hook, int idx)
: llarp::EventLoopWakeup{hook}, m_Idx{idx}
UVWakeup(uvw::Loop& loop, std::function<void()> callback)
: async{loop.resource<uvw::AsyncHandle>()}
{
uv_async_init(loop, &m_Impl, OnWake);
m_Impl.data = this;
async->on<uvw::AsyncEvent>([f = std::move(callback)](auto&, auto&) { f(); });
}
~UVWakeup() = default;
void
Close() override
Trigger() override
{
uv_close((uv_handle_t*)&m_Impl, [](uv_handle_t* h) {
auto loop = static_cast<libuv::Loop*>(h->loop->data);
loop->delete_waker(static_cast<UVWakeup*>(h->data)->m_Idx);
});
async->send();
}
void
End() override
~UVWakeup() override
{
Close();
}
void
Wakeup() override
{
uv_async_send(&m_Impl);
async->close();
}
};
struct ticker_glue : public glue
class UVRepeater final : public EventLoopRepeater
{
std::function<void(void)> func;
ticker_glue(uv_loop_t* loop, std::function<void(void)> tick) : func(tick)
{
m_Ticker.data = this;
uv_check_init(loop, &m_Ticker);
}
std::shared_ptr<uvw::TimerHandle> timer;
static void
OnTick(uv_check_t* t)
{
llarp::LogTrace("ticker_glue::OnTick() start");
ticker_glue* ticker = static_cast<ticker_glue*>(t->data);
ticker->func();
// Loop* loop = static_cast<Loop*>(t->loop->data);
// loop->FlushLogic();
llarp::LogTrace("ticker_glue::OnTick() end");
}
public:
UVRepeater(uvw::Loop& loop) : timer{loop.resource<uvw::TimerHandle>()}
{}
bool
Start()
void
start(llarp_time_t every, std::function<void()> task) override
{
return uv_check_start(&m_Ticker, &OnTick) != -1;
timer->start(every, every);
timer->on<uvw::TimerEvent>([task = std::move(task)](auto&, auto&) { task(); });
}
void
Close() override
~UVRepeater() override
{
uv_check_stop(&m_Ticker);
uv_close((uv_handle_t*)&m_Ticker, [](auto h) {
ticker_glue* self = (ticker_glue*)h->data;
h->data = nullptr;
delete self;
});
timer->stop();
}
uv_check_t m_Ticker;
};
struct udp_glue : public glue
struct UDPHandle final : llarp::UDPHandle
{
uv_udp_t m_Handle;
uv_check_t m_Ticker;
llarp_udp_io* const m_UDP;
llarp::SockAddr m_Addr;
std::vector<char> m_Buffer;
udp_glue(uv_loop_t* loop, llarp_udp_io* udp, const llarp::SockAddr& src)
: m_UDP(udp), m_Addr(src)
{
m_Handle.data = this;
m_Ticker.data = this;
uv_udp_init(loop, &m_Handle);
uv_check_init(loop, &m_Ticker);
}
static void
Alloc(uv_handle_t* h, size_t suggested_size, uv_buf_t* buf)
{
udp_glue* self = static_cast<udp_glue*>(h->data);
if (self->m_Buffer.empty())
self->m_Buffer.resize(suggested_size);
buf->base = self->m_Buffer.data();
buf->len = self->m_Buffer.size();
}
/// callback for libuv
static void
OnRecv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const sockaddr* addr, unsigned)
{
udp_glue* glue = static_cast<udp_glue*>(handle->data);
if (addr)
glue->RecvFrom(nread, buf, llarp::SockAddr(*addr));
}
UDPHandle(uvw::Loop& loop, ReceiveFunc rf);
void
RecvFrom(ssize_t sz, const uv_buf_t* buf, const llarp::SockAddr& fromaddr)
{
if (sz > 0 && m_UDP)
{
const size_t pktsz = sz;
if (m_UDP->recvfrom)
{
const llarp_buffer_t pkt((const byte_t*)buf->base, pktsz);
m_UDP->recvfrom(m_UDP, fromaddr, ManagedBuffer{pkt});
}
}
}
static void
OnTick(uv_check_t* t)
{
llarp::LogTrace("udp_glue::OnTick() start");
udp_glue* udp = static_cast<udp_glue*>(t->data);
udp->Tick();
llarp::LogTrace("udp_glue::OnTick() end");
}
void
Tick()
{
if (m_UDP && m_UDP->tick)
m_UDP->tick(m_UDP);
}
static int
SendTo(llarp_udp_io* udp, const llarp::SockAddr& to, const byte_t* ptr, size_t sz)
{
auto* self = static_cast<udp_glue*>(udp->impl);
if (self == nullptr)
return -1;
const auto buf = uv_buf_init((char*)ptr, sz);
return uv_udp_try_send(
&self->m_Handle, &buf, 1, (const sockaddr*)static_cast<const sockaddr_in*>(to));
}
bool
listen(const SockAddr& addr) override;
bool
Bind()
{
auto ret =
uv_udp_bind(&m_Handle, (const sockaddr*)static_cast<const sockaddr_in*>(m_Addr), 0);
if (ret)
{
llarp::LogError("failed to bind to ", m_Addr, " ", uv_strerror(ret));
return false;
}
if (uv_udp_recv_start(&m_Handle, &Alloc, &OnRecv))
{
llarp::LogError("failed to start recving packets via ", m_Addr);
return false;
}
if (uv_check_start(&m_Ticker, &OnTick))
{
llarp::LogError("failed to start ticker");
return false;
}
#if defined(_WIN32) || defined(_WIN64)
#else
if (uv_fileno((const uv_handle_t*)&m_Handle, &m_UDP->fd))
return false;
#endif
m_UDP->sendto = &SendTo;
m_UDP->impl = this;
return true;
}
send(const SockAddr& dest, const llarp_buffer_t& buf) override;
static void
OnClosed(uv_handle_t* h)
std::optional<int>
file_descriptor() override
{
auto* glue = static_cast<udp_glue*>(h->data);
if (glue)
{
h->data = nullptr;
delete glue;
}
#ifndef _WIN32
if (int fd = handle->fd(); fd >= 0)
return fd;
#endif
return std::nullopt;
}
void
Close() override
{
m_UDP->impl = nullptr;
uv_check_stop(&m_Ticker);
uv_close((uv_handle_t*)&m_Handle, &OnClosed);
}
};
close() override;
struct tun_glue : public glue
{
uv_poll_t m_Handle;
uv_check_t m_Ticker;
std::shared_ptr<llarp::vpn::NetworkInterface> m_NetIf;
std::function<void(llarp::net::IPPacket)> m_Handler;
tun_glue(
std::shared_ptr<llarp::vpn::NetworkInterface> netif,
std::function<void(llarp::net::IPPacket)> handler)
: m_NetIf{std::move(netif)}, m_Handler{std::move(handler)}
{
m_Handle.data = this;
m_Ticker.data = this;
}
static void
OnTick(uv_check_t* h)
{
auto self = static_cast<tun_glue*>(h->data);
while (self->m_NetIf->HasNextPacket())
self->Read();
}
static void
OnPoll(uv_poll_t* h, int, int events)
{
if (events & UV_READABLE)
{
static_cast<tun_glue*>(h->data)->Read();
}
}
void
Read()
{
auto pkt = m_NetIf->ReadNextPacket();
LogDebug("got packet ", pkt.sz);
if (m_Handler)
m_Handler(std::move(pkt));
}
~UDPHandle() override;
static void
OnClosed(uv_handle_t* h)
{
auto* self = static_cast<tun_glue*>(h->data);
if (self)
{
h->data = nullptr;
delete self;
}
}
private:
std::shared_ptr<uvw::UDPHandle> handle;
void
Close() override
{
uv_check_stop(&m_Ticker);
#ifndef _WIN32
uv_close((uv_handle_t*)&m_Handle, &OnClosed);
#endif
}
bool
Init(uv_loop_t* loop)
{
if (uv_check_init(loop, &m_Ticker) == -1)
{
return false;
}
if (uv_check_start(&m_Ticker, &OnTick) == -1)
{
return false;
}
#ifndef _WIN32
if (uv_poll_init(loop, &m_Handle, m_NetIf->PollFD()) == -1)
{
llarp::LogError("failed to initialize polling on ", m_NetIf->IfName());
return false;
}
if (uv_poll_start(&m_Handle, UV_READABLE, &OnPoll))
{
llarp::LogError("failed to start polling on ", m_NetIf->IfName());
return false;
}
#endif
return true;
}
reset_handle(uvw::Loop& loop);
};
void
@ -331,63 +100,36 @@ namespace libuv
llarp::LogTrace("Loop::FlushLogic() end");
}
static void
OnAsyncWake(uv_async_t* async_handle)
void
Loop::tick_event_loop()
{
llarp::LogTrace("OnAsyncWake, ticking event loop.");
Loop* loop = static_cast<Loop*>(async_handle->data);
loop->update_time();
loop->process_timer_queue();
loop->process_cancel_queue();
loop->FlushLogic();
loop->PumpLL();
llarp::LogTrace("ticking event loop.");
FlushLogic();
PumpLL();
auto& log = llarp::LogContext::Instance();
if (log.logStream)
log.logStream->Tick(loop->time_now());
log.logStream->Tick(time_now());
}
constexpr size_t TimerQueueSize = 20;
Loop::Loop(size_t queue_size)
: llarp::EventLoop{}
, PumpLL{[]() {}}
, m_LogicCalls{queue_size}
, m_timerQueue{TimerQueueSize}
, m_timerCancelQueue{TimerQueueSize}
{}
bool
Loop::init()
Loop::Loop(size_t queue_size) : llarp::EventLoop{}, PumpLL{[] {}}, m_LogicCalls{queue_size}
{
if (uv_loop_init(&m_Impl) == -1)
return false;
if (!(m_Impl = uvw::Loop::create()))
throw std::runtime_error{"Failed to construct libuv loop"};
#ifdef LOKINET_DEBUG
last_time = 0;
loop_run_count = 0;
#endif
m_Impl.data = this;
#if defined(_WIN32) || defined(_WIN64)
#else
uv_loop_configure(&m_Impl, UV_LOOP_BLOCK_SIGNAL, SIGPIPE);
#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
m_TickTimer = new uv_timer_t;
m_TickTimer->data = this;
if (uv_timer_init(&m_Impl, m_TickTimer) == -1)
return false;
m_Run.store(true);
m_nextID.store(0);
m_WakeUp.data = this;
uv_async_init(&m_Impl, &m_WakeUp, &OnAsyncWake);
return true;
}
void
Loop::update_time()
{
llarp::EventLoop::update_time();
uv_update_time(&m_Impl);
if (!(m_WakeUp = m_Impl->resource<uvw::AsyncHandle>()))
throw std::runtime_error{"Failed to create libuv async"};
m_WakeUp->on<uvw::AsyncEvent>([this](const auto&, auto&) { tick_event_loop(); });
}
bool
@ -396,18 +138,21 @@ namespace libuv
return m_Run.load();
}
static void
OnTickTimeout(uv_timer_t* timer)
void
Loop::run()
{
uv_stop(timer->loop);
llarp::LogTrace("Loop::run_loop()");
m_EventLoopThreadID = std::this_thread::get_id();
m_Impl->run();
m_Impl->close();
m_Impl.reset();
llarp::LogInfo("we have stopped");
}
int
Loop::run()
void
Loop::wakeup()
{
llarp::LogTrace("Loop::run()");
m_EventLoopThreadID = std::this_thread::get_id();
return uv_run(&m_Impl, UV_RUN_DEFAULT);
m_WakeUp->send();
}
void
@ -416,97 +161,46 @@ namespace libuv
PumpLL = std::move(pump);
}
struct TimerData
std::shared_ptr<llarp::UDPHandle>
Loop::make_udp(UDPReceiveFunc on_recv)
{
Loop* loop;
uint64_t job_id;
};
void
CloseUVTimer(uv_timer_t* timer)
{
// have to delete timer handle this way because libuv.
uv_timer_stop(timer);
uv_close((uv_handle_t*)timer, [](uv_handle_t* handle) { delete (uv_timer_t*)handle; });
return std::static_pointer_cast<llarp::UDPHandle>(
std::make_shared<llarp::uv::UDPHandle>(*m_Impl, std::move(on_recv)));
}
static void
OnUVTimer(uv_timer_t* timer)
setup_oneshot_timer(uvw::Loop& loop, llarp_time_t delay, std::function<void()> callback)
{
TimerData* timer_data = static_cast<TimerData*>(timer->data);
Loop* loop = timer_data->loop;
loop->do_timer_job(timer_data->job_id);
delete timer_data;
CloseUVTimer(timer);
auto timer = loop.resource<uvw::TimerHandle>();
timer->on<uvw::TimerEvent>([f = std::move(callback)](const auto&, auto& timer) {
f();
timer.stop();
timer.close();
});
timer->start(delay, 0ms);
}
uint32_t
Loop::call_after_delay(llarp_time_t delay_ms, std::function<void(void)> callback)
void
Loop::call_later(llarp_time_t delay_ms, std::function<void(void)> callback)
{
llarp::LogTrace("Loop::call_after_delay()");
#ifdef TESTNET_SPEED
delay_ms *= TESTNET_SPEED;
#endif
PendingTimer timer;
timer.delay_ms = delay_ms;
timer.callback = callback;
timer.job_id = m_nextID++;
uint64_t job_id = timer.job_id;
m_timerQueue.pushBack(std::move(timer));
uv_async_send(&m_WakeUp);
return job_id;
}
void
Loop::cancel_delayed_call(uint32_t job_id)
{
m_timerCancelQueue.pushBack(job_id);
uv_async_send(&m_WakeUp);
}
void
Loop::process_timer_queue()
{
while (not m_timerQueue.empty())
{
PendingTimer job = m_timerQueue.popFront();
uint64_t job_id = job.job_id;
m_pendingCalls.emplace(job_id, std::move(job.callback));
TimerData* timer_data = new TimerData;
timer_data->loop = this;
timer_data->job_id = job_id;
uv_timer_t* newTimer = new uv_timer_t;
newTimer->data = (void*)timer_data;
uv_timer_init(&m_Impl, newTimer);
uv_timer_start(newTimer, &OnUVTimer, job.delay_ms.count(), 0);
}
}
void
Loop::process_cancel_queue()
{
while (not m_timerCancelQueue.empty())
{
uint64_t job_id = m_timerCancelQueue.popFront();
m_pendingCalls.erase(job_id);
}
}
void
Loop::do_timer_job(uint64_t job_id)
{
auto itr = m_pendingCalls.find(job_id);
if (itr != m_pendingCalls.end())
{
if (itr->second)
itr->second();
m_pendingCalls.erase(itr->first);
if (inEventLoop())
setup_oneshot_timer(*m_Impl, delay_ms, std::move(callback));
else
{
call_soon([this, f = std::move(callback), target_time = time_now() + delay_ms] {
// Recalculate delay because it may have taken some time to get ourselves into the logic
// thread
auto updated_delay = target_time - time_now();
if (updated_delay <= 0ms)
f(); // Timer already expired!
else
setup_oneshot_timer(*m_Impl, updated_delay, std::move(f));
});
}
}
@ -515,62 +209,28 @@ namespace libuv
{
if (m_Run)
{
llarp::LogInfo("stopping event loop");
CloseAll();
uv_stop(&m_Impl);
}
m_Run.store(false);
}
if (not inEventLoop())
return call_soon([this] { stop(); });
void
Loop::CloseAll()
{
llarp::LogInfo("Closing all handles");
uv_walk(
&m_Impl,
[](uv_handle_t* h, void*) {
if (uv_is_closing(h))
return;
if (h->data && uv_is_active(h) && h->type != UV_TIMER && h->type != UV_POLL)
{
auto glue = reinterpret_cast<libuv::glue*>(h->data);
if (glue)
glue->Close();
}
},
nullptr);
}
void
Loop::stopped()
{
llarp::LogInfo("we have stopped");
}
llarp::LogInfo("stopping event loop");
m_Impl->walk([](auto&& handle) {
if constexpr (!std::is_pointer_v<std::remove_reference_t<decltype(handle)>>)
handle.close();
});
llarp::LogDebug("Closed all handles, stopping the loop");
m_Impl->stop();
bool
Loop::udp_listen(llarp_udp_io* udp, const llarp::SockAddr& src)
{
auto* impl = new udp_glue(&m_Impl, udp, src);
udp->impl = impl;
if (impl->Bind())
{
return true;
m_Run.store(false);
}
llarp::LogError("Loop::udp_listen failed to bind");
delete impl;
return false;
}
bool
Loop::add_ticker(std::function<void(void)> func)
{
auto* ticker = new ticker_glue(&m_Impl, func);
if (ticker->Start())
{
return true;
}
delete ticker;
return false;
auto check = m_Impl->resource<uvw::CheckHandle>();
check->on<uvw::CheckEvent>([f = std::move(func)](auto&, auto&) { f(); });
check->start();
return true;
}
bool
@ -578,23 +238,32 @@ namespace libuv
std::shared_ptr<llarp::vpn::NetworkInterface> netif,
std::function<void(llarp::net::IPPacket)> handler)
{
auto* glue = new tun_glue(netif, handler);
// call to Init gives ownership of glue to event loop
if (glue->Init(&m_Impl))
return true;
delete glue;
return false;
}
bool
Loop::udp_close(llarp_udp_io* udp)
{
if (udp == nullptr)
return false;
auto* glue = static_cast<udp_glue*>(udp->impl);
if (glue == nullptr)
#ifndef _WIN32
using event_t = uvw::PollEvent;
auto handle = m_Impl->resource<uvw::PollHandle>(netif->PollFD());
#else
using event_t = uvw::CheckEvent;
auto handle = m_Impl->resource<uvw::CheckHandle>();
#endif
if (!handle)
return false;
glue->Close();
handle->on<event_t>([netif = std::move(netif), handler = std::move(handler)](
const event_t&, [[maybe_unused]] auto& handle) {
for (auto pkt = netif->ReadNextPacket(); pkt.sz > 0; pkt = netif->ReadNextPacket())
{
LogDebug("got packet ", pkt.sz);
if (handler)
handler(std::move(pkt));
}
});
#ifndef _WIN32
handle->start(uvw::PollHandle::Event::READABLE);
#else
handle->start();
#endif
return true;
}
@ -604,80 +273,96 @@ namespace libuv
if (not m_EventLoopThreadID.has_value())
{
m_LogicCalls.tryPushBack(f);
uv_async_send(&m_WakeUp);
m_WakeUp->send();
return;
}
const auto inEventLoop = *m_EventLoopThreadID == std::this_thread::get_id();
if (inEventLoop and m_LogicCalls.full())
if (inEventLoop() and m_LogicCalls.full())
{
FlushLogic();
}
m_LogicCalls.pushBack(f);
uv_async_send(&m_WakeUp);
m_WakeUp->send();
}
// Sets `handle` to a new uvw UDP handle, first initiating a close and then disowning the handle
// if already set, allocating the resource, and setting the receive event on it.
void
OnUVPollFDReadable(uv_poll_t* handle, int status, [[maybe_unused]] int events)
UDPHandle::reset_handle(uvw::Loop& loop)
{
if (handle)
handle->close();
handle = loop.resource<uvw::UDPHandle>();
handle->on<uvw::UDPDataEvent>([this](auto& event, auto& /*handle*/) {
on_recv(
*this,
SockAddr{event.sender.ip, static_cast<uint16_t>(event.sender.port)},
OwnedBuffer{std::move(event.data), event.length});
});
}
llarp::uv::UDPHandle::UDPHandle(uvw::Loop& loop, ReceiveFunc rf) : llarp::UDPHandle{std::move(rf)}
{
if (status < 0)
return; // probably fd was closed
reset_handle(loop);
}
auto func = static_cast<libuv::Loop::Callback*>(handle->data);
bool
UDPHandle::listen(const SockAddr& addr)
{
if (handle->active())
reset_handle(handle->loop());
bool good = true;
auto err = handle->on<uvw::ErrorEvent>([&](auto& event, auto&) {
llarp::LogError("failed to bind and start receiving on ", addr, ": ", event.what());
good = false;
});
handle->bind(*static_cast<const sockaddr*>(addr));
if (good)
handle->recv();
handle->erase(err);
return good;
}
(*func)();
bool
UDPHandle::send(const SockAddr& to, const llarp_buffer_t& buf)
{
return handle->trySend(
*static_cast<const sockaddr*>(to),
const_cast<char*>(reinterpret_cast<const char*>(buf.base)),
buf.sz)
>= 0;
}
void
Loop::register_poll_fd_readable(int fd, Callback callback)
UDPHandle::close()
{
if (m_Polls.count(fd))
{
llarp::LogError(
"Attempting to create event loop poll on fd ",
fd,
", but an event loop poll for that fd already exists.");
return;
}
// new a copy as the one passed in here will go out of scope
auto function_ptr = new Callback(callback);
auto& new_poll = m_Polls[fd];
uv_poll_init(&m_Impl, &new_poll, fd);
new_poll.data = (void*)function_ptr;
uv_poll_start(&new_poll, UV_READABLE, &OnUVPollFDReadable);
handle->close();
handle.reset();
}
void
Loop::deregister_poll_fd_readable(int fd)
UDPHandle::~UDPHandle()
{
auto itr = m_Polls.find(fd);
close();
}
if (itr != m_Polls.end())
{
uv_poll_stop(&(itr->second));
auto func = static_cast<Callback*>(itr->second.data);
delete func;
m_Polls.erase(itr);
}
std::shared_ptr<llarp::EventLoopWakeup>
Loop::make_waker(std::function<void()> callback)
{
return std::static_pointer_cast<llarp::EventLoopWakeup>(
std::make_shared<UVWakeup>(*m_Impl, std::move(callback)));
}
llarp::EventLoopWakeup*
Loop::make_event_loop_waker(std::function<void()> callback)
std::shared_ptr<EventLoopRepeater>
Loop::make_repeater()
{
auto wake_idx = m_NumWakers++;
auto wake = new UVWakeup{&m_Impl, callback, wake_idx};
m_Wakers[wake_idx] = wake;
return wake;
return std::static_pointer_cast<EventLoopRepeater>(std::make_shared<UVRepeater>(*m_Impl));
}
void
Loop::delete_waker(int idx)
bool
Loop::inEventLoop() const
{
delete m_Wakers[idx];
m_Wakers.erase(idx);
return m_EventLoopThreadID and *m_EventLoopThreadID == std::this_thread::get_id();
}
} // namespace libuv
} // namespace llarp::uv

@ -1,74 +1,49 @@
#ifndef LLARP_EV_LIBUV_HPP
#define LLARP_EV_LIBUV_HPP
#include <ev/ev.hpp>
#include <uv.h>
#include <vector>
#include <functional>
#include <util/thread/logic.hpp>
#include "udp_handle.hpp"
#include <util/thread/queue.hpp>
#include <util/meta/memfn.hpp>
#include <uvw/loop.h>
#include <uvw/async.h>
#include <uvw/poll.h>
#include <uvw/udp.h>
#include <functional>
#include <map>
#include <vector>
namespace libuv
namespace llarp::uv
{
class UVWakeup;
class UVRepeater;
struct Loop final : public llarp::EventLoop
class Loop final : public llarp::EventLoop
{
typedef std::function<void(void)> Callback;
struct PendingTimer
{
uint64_t job_id;
llarp_time_t delay_ms;
Callback callback;
};
public:
using Callback = std::function<void()>;
Loop(size_t queue_size);
bool
init() override;
int
void
run() override;
bool
running() const override;
void
update_time() override;
uint32_t
call_after_delay(llarp_time_t delay_ms, std::function<void(void)> callback) override;
void
cancel_delayed_call(uint32_t job_id) override;
void
process_timer_queue();
wakeup() override;
void
process_cancel_queue();
call_later(llarp_time_t delay_ms, std::function<void(void)> callback) override;
void
do_timer_job(uint64_t job_id);
tick_event_loop();
void
stop() override;
void
stopped() override;
void
CloseAll();
bool
udp_listen(llarp_udp_io* l, const llarp::SockAddr& src) override;
bool
udp_close(llarp_udp_io* l) override;
bool
add_ticker(std::function<void(void)> ticker) override;
@ -77,42 +52,32 @@ namespace libuv
std::shared_ptr<llarp::vpn::NetworkInterface> netif,
std::function<void(llarp::net::IPPacket)> handler) override;
void
set_logic(std::shared_ptr<llarp::Logic> l) override
{
m_Logic = l;
m_Logic->SetQueuer(llarp::util::memFn(&Loop::call_soon, this));
}
std::shared_ptr<llarp::Logic> m_Logic;
void
call_soon(std::function<void(void)> f) override;
void
register_poll_fd_readable(int fd, Callback callback) override;
void
deregister_poll_fd_readable(int fd) override;
void
set_pump_function(std::function<void(void)> pumpll) override;
llarp::EventLoopWakeup*
make_event_loop_waker(std::function<void()> callback) override;
std::shared_ptr<llarp::EventLoopWakeup>
make_waker(std::function<void()> callback) override;
void
delete_waker(int idx);
std::shared_ptr<EventLoopRepeater>
make_repeater() override;
std::shared_ptr<llarp::UDPHandle>
make_udp(UDPReceiveFunc on_recv) override;
void
FlushLogic();
std::function<void(void)> PumpLL;
bool
inEventLoop() const override;
private:
uv_loop_t m_Impl;
uv_timer_t* m_TickTimer;
uv_async_t m_WakeUp;
std::shared_ptr<uvw::Loop> m_Impl;
std::shared_ptr<uvw::AsyncHandle> m_WakeUp;
std::atomic<bool> m_Run;
using AtomicQueue_t = llarp::thread::Queue<std::function<void(void)>>;
AtomicQueue_t m_LogicCalls;
@ -125,16 +90,11 @@ namespace libuv
std::map<uint32_t, Callback> m_pendingCalls;
std::unordered_map<int, uv_poll_t> m_Polls;
std::unordered_map<int, std::shared_ptr<uvw::PollHandle>> m_Polls;
llarp::thread::Queue<PendingTimer> m_timerQueue;
llarp::thread::Queue<uint32_t> m_timerCancelQueue;
std::optional<std::thread::id> m_EventLoopThreadID;
int m_NumWakers;
std::unordered_map<int, UVWakeup*> m_Wakers;
};
} // namespace libuv
} // namespace llarp::uv
#endif

@ -0,0 +1,49 @@
#include "ev.hpp"
#include "../util/buffer.hpp"
namespace llarp
{
// Base type for UDP handling; constructed via EventLoop::make_udp().
struct UDPHandle
{
using ReceiveFunc = EventLoop::UDPReceiveFunc;
// Starts listening for incoming UDP packets on the given address. Returns true on success,
// false if the address could not be bound. If you send without calling this first then the
// socket will bind to a random high port on 0.0.0.0 (the "all addresses" address).
virtual bool
listen(const SockAddr& addr) = 0;
// Sends a packet to the given recipient, immediately. Returns true if the send succeeded,
// false it could not be performed (either because of error, or because it would have blocked).
// If listen hasn't been called then a random IP/port will be used.
virtual bool
send(const SockAddr& dest, const llarp_buffer_t& buf) = 0;
// Closes the listening UDP socket (if opened); this is typically called (automatically) during
// destruction. Does nothing if the UDP socket is already closed.
virtual void
close() = 0;
// Returns the file descriptor of the socket, if available. This generally exists only after
// listen() has been called, and never exists on Windows.
virtual std::optional<int>
file_descriptor()
{
return std::nullopt;
}
// Base class destructor
virtual ~UDPHandle() = default;
protected:
explicit UDPHandle(ReceiveFunc on_recv) : on_recv{std::move(on_recv)}
{
// It makes no sense at all to use this with a null receive function:
assert(this->on_recv);
}
// Callback to invoke when data is received
ReceiveFunc on_recv;
};
} // namespace llarp

@ -49,15 +49,10 @@ namespace llarp::vpn
virtual std::string
IfName() const = 0;
/// read next ip packet
/// blocks until ready
/// read next ip packet, return an empty packet if there are none ready.
virtual net::IPPacket
ReadNextPacket() = 0;
/// return true if we have another packet to read
virtual bool
HasNextPacket() = 0;
/// write a packet to the interface
/// returns false if we dropped it
virtual bool

@ -1,7 +1,6 @@
#include <ev/vpnio.hpp>
#include <llarp.hpp>
#include <router/abstractrouter.hpp>
#include <util/thread/logic.hpp>
void
llarp_vpn_io_impl::AsyncClose()

@ -13,12 +13,12 @@ namespace llarp
{
namespace handlers
{
ExitEndpoint::ExitEndpoint(const std::string& name, AbstractRouter* r)
ExitEndpoint::ExitEndpoint(std::string name, AbstractRouter* r)
: m_Router(r)
, m_Resolver(std::make_shared<dns::Proxy>(r->netloop(), r->logic(), this))
, m_Name(name)
, m_Resolver(std::make_shared<dns::Proxy>(r->loop(), this))
, m_Name(std::move(name))
, m_LocalResolverAddr("127.0.0.1", 53)
, m_InetToNetwork(name + "_exit_rx", r->netloop(), r->netloop())
, m_InetToNetwork(name + "_exit_rx", r->loop(), r->loop())
{
m_ShouldInitTun = true;
@ -312,15 +312,14 @@ namespace llarp
llarp::LogError("Could not create interface");
return false;
}
auto loop = GetRouter()->netloop();
if (not loop->add_network_interface(
m_NetIf, [&](net::IPPacket pkt) { OnInetPacket(std::move(pkt)); }))
if (not GetRouter()->loop()->add_network_interface(
m_NetIf, [this](net::IPPacket pkt) { OnInetPacket(std::move(pkt)); }))
{
llarp::LogWarn("Could not create tunnel for exit endpoint");
return false;
}
loop->add_ticker([&]() { Flush(); });
GetRouter()->loop()->add_ticker([this] { Flush(); });
llarp::LogInfo("Trying to start resolver ", m_LocalResolverAddr.toString());
return m_Resolver->Start(m_LocalResolverAddr.createSockAddr(), m_UpstreamResolvers);

@ -13,7 +13,7 @@ namespace llarp
{
struct ExitEndpoint : public dns::IQueryHandler
{
ExitEndpoint(const std::string& name, AbstractRouter* r);
ExitEndpoint(std::string name, AbstractRouter* r);
~ExitEndpoint() override;
void

@ -18,7 +18,6 @@
#include <service/outbound_context.hpp>
#include <service/name.hpp>
#include <util/meta/memfn.hpp>
#include <util/thread/logic.hpp>
#include <nodedb.hpp>
#include <rpc/endpoint_rpc.hpp>
@ -31,34 +30,33 @@ namespace llarp
{
namespace handlers
{
bool
TunEndpoint::ShouldFlushNow(llarp_time_t now) const
{
static constexpr auto FlushInterval = 25ms;
return now >= m_LastFlushAt + FlushInterval;
}
constexpr size_t udp_header_size = 8;
struct DnsHandler : public dns::PacketHandler
// Intercepts DNS IP packets going to an IP on the tun interface; this is currently used on
// Android where binding to a DNS port (i.e. via llarp::dns::Proxy) isn't possible because of OS
// restrictions, but a tun interface *is* available.
class DnsInterceptor : public dns::PacketHandler
{
public:
TunEndpoint* const m_Endpoint;
explicit DnsHandler(AbstractRouter* router, TunEndpoint* ep)
: dns::PacketHandler{router->logic(), ep}, m_Endpoint{ep} {};
explicit DnsInterceptor(AbstractRouter* router, TunEndpoint* ep)
: dns::PacketHandler{router->loop(), ep}, m_Endpoint{ep} {};
void
SendServerMessageBufferTo(SockAddr from, SockAddr to, std::vector<byte_t> buf) override
SendServerMessageBufferTo(
const SockAddr& from, const SockAddr& to, llarp_buffer_t buf) override
{
net::IPPacket pkt;
if (buf.size() + 28 > sizeof(pkt.buf))
if (buf.sz + 28 > sizeof(pkt.buf))
return;
auto* hdr = pkt.Header();
pkt.buf[1] = 0;
hdr->version = 4;
hdr->ihl = 5;
hdr->tot_len = htons(buf.size() + 28);
hdr->tot_len = htons(buf.sz + 28);
hdr->protocol = 0x11; // udp
hdr->ttl = 64;
hdr->frag_off = htons(0b0100000000000000);
@ -72,11 +70,11 @@ namespace llarp
ptr += 2;
htobe16buf(ptr, to.getPort());
ptr += 2;
htobe16buf(ptr, buf.size() + udp_header_size);
htobe16buf(ptr, buf.sz + udp_header_size);
ptr += 2;
htobe16buf(ptr, uint16_t{0}); // checksum
ptr += 2;
std::copy_n(buf.data(), buf.size(), ptr);
std::copy_n(buf.base, buf.sz, ptr);
/// queue ip packet write
const IpAddress remoteIP{from};
@ -84,7 +82,7 @@ namespace llarp
hdr->check = 0;
hdr->check = net::ipchksum(pkt.buf, 20);
pkt.sz = 28 + buf.size();
pkt.sz = 28 + buf.sz;
m_Endpoint->HandleWriteIPPacket(
pkt.ConstBuffer(), net::ExpandV4(remoteIP.toIP()), net::ExpandV4(localIP.toIP()), 0);
}
@ -92,12 +90,12 @@ namespace llarp
TunEndpoint::TunEndpoint(AbstractRouter* r, service::Context* parent)
: service::Endpoint(r, parent)
, m_UserToNetworkPktQueue("endpoint_sendq", r->netloop(), r->netloop())
, m_UserToNetworkPktQueue("endpoint_sendq", r->loop(), r->loop())
{
m_PacketRouter.reset(
new vpn::PacketRouter{[&](net::IPPacket pkt) { HandleGotUserPacket(std::move(pkt)); }});
#if ANDROID
m_Resolver = std::make_shared<DnsHandler>(r, this);
#ifdef ANDROID
m_Resolver = std::make_shared<DnsInterceptor>(r, this);
m_PacketRouter->AddUDPHandler(huint16_t{53}, [&](net::IPPacket pkt) {
const size_t ip_header_size = (pkt.Header()->ihl * 4);
@ -107,16 +105,15 @@ namespace llarp
const SockAddr raddr{src.n, *reinterpret_cast<const uint16_t*>(ptr)};
const SockAddr laddr{dst.n, *reinterpret_cast<const uint16_t*>(ptr + 2)};
std::vector<byte_t> buf;
buf.resize(pkt.sz - (udp_header_size + ip_header_size));
std::copy_n(ptr + udp_header_size, buf.size(), buf.data());
OwnedBuffer buf{pkt.sz - (udp_header_size + ip_header_size)};
std::copy_n(ptr + udp_header_size, buf.sz, buf.buf.get());
if (m_Resolver->ShouldHandlePacket(laddr, raddr, buf))
m_Resolver->HandlePacket(laddr, raddr, std::move(buf));
m_Resolver->HandlePacket(laddr, raddr, buf);
else
HandleGotUserPacket(std::move(pkt));
});
#else
m_Resolver = std::make_shared<dns::Proxy>(r->netloop(), r->logic(), this);
m_Resolver = std::make_shared<dns::Proxy>(r->loop(), this);
#endif
}
@ -833,9 +830,9 @@ namespace llarp
m_IfName = m_NetIf->IfName();
LogInfo(Name(), " got network interface ", m_IfName);
auto netloop = Router()->netloop();
if (not netloop->add_network_interface(
m_NetIf, [&](net::IPPacket pkt) { m_PacketRouter->HandleIPPacket(std::move(pkt)); }))
if (not Router()->loop()->add_network_interface(m_NetIf, [this](net::IPPacket pkt) {
m_PacketRouter->HandleIPPacket(std::move(pkt));
}))
{
LogError(Name(), " failed to add network interface");
return false;
@ -848,7 +845,7 @@ namespace llarp
LogInfo(Name(), " has ipv6 address ", m_OurIPv6);
}
netloop->add_ticker([&]() { Flush(); });
Router()->loop()->add_ticker([this] { Flush(); });
if (m_OnUp)
{

@ -158,10 +158,6 @@ namespace llarp
ResetInternalState() override;
protected:
bool
ShouldFlushNow(llarp_time_t now) const;
llarp_time_t m_LastFlushAt = 0s;
using PacketQueue_t = llarp::util::CoDelQueue<
net::IPPacket,
net::IPPacket::GetTime,

@ -22,17 +22,12 @@ namespace llarp::iwp
bool allowInbound)
: ILinkLayer(
keyManager, getrc, h, sign, before, est, reneg, timeout, closed, pumpDone, worker)
, m_Wakeup{ev->make_event_loop_waker([self = this]() { self->HandleWakeupPlaintext(); })}
, m_Wakeup{ev->make_waker([this]() { HandleWakeupPlaintext(); })}
, m_PlaintextRecv{1024}
, permitInbound{allowInbound}
{}
LinkLayer::~LinkLayer()
{
m_Wakeup->End();
}
const char*
LinkLayer::Name() const
{
@ -111,7 +106,7 @@ namespace llarp::iwp
void
LinkLayer::WakeupPlaintext()
{
m_Wakeup->Wakeup();
m_Wakeup->Trigger();
}
void

@ -33,8 +33,6 @@ namespace llarp::iwp
WorkerFunc_t dowork,
bool permitInbound);
~LinkLayer() override;
std::shared_ptr<ILinkSession>
NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) override;
@ -63,7 +61,7 @@ namespace llarp::iwp
void
HandleWakeupPlaintext();
EventLoopWakeup* const m_Wakeup;
const std::shared_ptr<EventLoopWakeup> m_Wakeup;
std::unordered_map<SockAddr, std::weak_ptr<Session>, SockAddr::Hash> m_PlaintextRecv;
std::unordered_map<SockAddr, RouterID, SockAddr::Hash> m_AuthedAddrs;
const bool permitInbound;

@ -2,7 +2,6 @@
#define LLARP_I_LINK_MANAGER_HPP
#include <link/server.hpp>
#include <util/thread/logic.hpp>
#include <util/types.hpp>
#include <peerstats/peer_db.hpp>
@ -13,8 +12,6 @@ struct llarp_buffer_t;
namespace llarp
{
using Logic_ptr = std::shared_ptr<Logic>;
struct RouterContact;
struct ILinkSession;
struct IOutboundSessionMaker;
@ -52,7 +49,7 @@ namespace llarp
AddLink(LinkLayer_ptr link, bool inbound = false) = 0;
virtual bool
StartLinks(Logic_ptr logic) = 0;
StartLinks() = 0;
virtual void
Stop() = 0;

@ -121,12 +121,12 @@ namespace llarp
}
bool
LinkManager::StartLinks(Logic_ptr logic)
LinkManager::StartLinks()
{
LogInfo("starting ", outboundLinks.size(), " outbound links");
for (const auto& link : outboundLinks)
{
if (!link->Start(logic))
if (!link->Start())
{
LogWarn("outbound link '", link->Name(), "' failed to start");
return false;
@ -139,7 +139,7 @@ namespace llarp
LogInfo("starting ", inboundLinks.size(), " inbound links");
for (const auto& link : inboundLinks)
{
if (!link->Start(logic))
if (!link->Start())
{
LogWarn("Link ", link->Name(), " failed to start");
return false;

@ -47,7 +47,7 @@ namespace llarp
AddLink(LinkLayer_ptr link, bool inbound = false) override;
bool
StartLinks(Logic_ptr logic) override;
StartLinks() override;
void
Stop() override;

@ -1,5 +1,6 @@
#include <link/server.hpp>
#include <ev/ev.hpp>
#include <ev/udp_handle.hpp>
#include <crypto/crypto.hpp>
#include <config/key_manager.hpp>
#include <memory>
@ -125,18 +126,17 @@ namespace llarp
}
bool
ILinkLayer::Configure(llarp_ev_loop_ptr loop, const std::string& ifname, int af, uint16_t port)
ILinkLayer::Configure(EventLoop_ptr loop, const std::string& ifname, int af, uint16_t port)
{
m_Loop = loop;
m_udp.user = this;
m_udp.recvfrom = [](llarp_udp_io* udp, const llarp::SockAddr& from, ManagedBuffer pktbuf) {
ILinkSession::Packet_t pkt;
auto& buf = pktbuf.underlying;
pkt.resize(buf.sz);
std::copy_n(buf.base, buf.sz, pkt.data());
static_cast<ILinkLayer*>(udp->user)->RecvFrom(from, std::move(pkt));
};
m_udp.tick = &ILinkLayer::udp_tick;
m_Loop = std::move(loop);
m_udp = m_Loop->make_udp(
[this]([[maybe_unused]] UDPHandle& udp, const SockAddr& from, llarp_buffer_t buf) {
ILinkSession::Packet_t pkt;
pkt.resize(buf.sz);
std::copy_n(buf.base, buf.sz, pkt.data());
RecvFrom(from, std::move(pkt));
});
if (ifname == "*")
{
if (!AllInterfaces(af, m_ourAddr))
@ -162,7 +162,11 @@ namespace llarp
}
}
m_ourAddr.setPort(port);
return llarp_ev_add_udp(m_Loop, &m_udp, m_ourAddr) != -1;
if (not m_udp->listen(m_ourAddr))
return false;
m_Loop->add_ticker([this] { Pump(); });
return true;
}
void
@ -335,35 +339,29 @@ namespace llarp
}
bool
ILinkLayer::Start(std::shared_ptr<Logic> l)
ILinkLayer::Start()
{
m_Logic = l;
ScheduleTick(LINK_LAYER_TICK_INTERVAL);
// Tie the lifetime of this repeater to this arbitrary shared_ptr:
m_repeater_keepalive = std::make_shared<int>(0);
m_Loop->call_every(LINK_LAYER_TICK_INTERVAL, m_repeater_keepalive, [this] { Tick(Now()); });
return true;
}
void
ILinkLayer::Tick(llarp_time_t now)
ILinkLayer::Tick(const llarp_time_t now)
{
{
Lock_t l(m_AuthedLinksMutex);
auto itr = m_AuthedLinks.begin();
while (itr != m_AuthedLinks.end())
{
itr->second->Tick(now);
++itr;
}
for (const auto& [routerid, link] : m_AuthedLinks)
link->Tick(now);
}
{
Lock_t l(m_PendingMutex);
auto itr = m_Pending.begin();
while (itr != m_Pending.end())
{
itr->second->Tick(now);
++itr;
}
for (const auto& [addr, link] : m_Pending)
link->Tick(now);
}
{
// decay recently closed list
auto itr = m_RecentlyClosed.begin();
@ -380,25 +378,16 @@ namespace llarp
void
ILinkLayer::Stop()
{
if (m_Logic && tick_id)
m_Logic->remove_call(tick_id);
m_repeater_keepalive.reset(); // make the repeater kill itself
{
Lock_t l(m_AuthedLinksMutex);
auto itr = m_AuthedLinks.begin();
while (itr != m_AuthedLinks.end())
{
itr->second->Close();
++itr;
}
for (const auto& [router, link] : m_AuthedLinks)
link->Close();
}
{
Lock_t l(m_PendingMutex);
auto itr = m_Pending.begin();
while (itr != m_Pending.end())
{
itr->second->Close();
++itr;
}
for (const auto& [addr, link] : m_Pending)
link->Close();
}
}
@ -411,9 +400,8 @@ namespace llarp
Lock_t l(m_AuthedLinksMutex);
RouterID r = remote;
llarp::LogInfo("Closing all to ", r);
auto range = m_AuthedLinks.equal_range(r);
auto itr = range.first;
while (itr != range.second)
auto [itr, end] = m_AuthedLinks.equal_range(r);
while (itr != end)
{
itr->second->Close();
m_RecentlyClosed.emplace(itr->second->GetRemoteEndpoint(), now + CloseGraceWindow);
@ -427,19 +415,22 @@ namespace llarp
ILinkLayer::KeepAliveSessionTo(const RouterID& remote)
{
Lock_t l(m_AuthedLinksMutex);
auto range = m_AuthedLinks.equal_range(remote);
auto itr = range.first;
while (itr != range.second)
for (auto [itr, end] = m_AuthedLinks.equal_range(remote); itr != end; ++itr)
{
if (itr->second->ShouldPing())
{
LogDebug("keepalive to ", remote);
itr->second->SendKeepAlive();
}
++itr;
}
}
void
ILinkLayer::SendTo_LL(const SockAddr& to, const llarp_buffer_t& pkt)
{
m_udp->send(to, pkt);
}
bool
ILinkLayer::SendTo(
const RouterID& remote, const llarp_buffer_t& buf, ILinkSession::CompletionHandler completed)
@ -447,20 +438,16 @@ namespace llarp
std::shared_ptr<ILinkSession> s;
{
Lock_t l(m_AuthedLinksMutex);
auto range = m_AuthedLinks.equal_range(remote);
auto itr = range.first;
// pick lowest backlog session
size_t min = std::numeric_limits<size_t>::max();
while (itr != range.second)
for (auto [itr, end] = m_AuthedLinks.equal_range(remote); itr != end; ++itr)
{
const auto backlog = itr->second->SendQueueBacklog();
if (backlog < min)
if (const auto backlog = itr->second->SendQueueBacklog(); backlog < min)
{
s = itr->second;
min = backlog;
}
++itr;
}
}
ILinkSession::Message_t pkt(buf.sz);
@ -502,25 +489,10 @@ namespace llarp
return true;
}
void
ILinkLayer::OnTick()
{
auto now = Now();
Tick(now);
ScheduleTick(LINK_LAYER_TICK_INTERVAL);
}
void
ILinkLayer::ScheduleTick(llarp_time_t interval)
{
tick_id = m_Logic->call_later(interval, std::bind(&ILinkLayer::OnTick, this));
}
void
ILinkLayer::udp_tick(llarp_udp_io* udp)
std::optional<int>
ILinkLayer::GetUDPFD() const
{
ILinkLayer* link = static_cast<ILinkLayer*>(udp->user);
link->Pump();
return m_udp->file_descriptor();
}
} // namespace llarp

@ -2,12 +2,11 @@
#define LLARP_LINK_SERVER_HPP
#include <crypto/types.hpp>
#include <ev/ev.h>
#include <ev/ev.hpp>
#include <link/session.hpp>
#include <net/sock_addr.hpp>
#include <router_contact.hpp>
#include <util/status.hpp>
#include <util/thread/logic.hpp>
#include <util/thread/threading.hpp>
#include <config/key_manager.hpp>
@ -93,7 +92,7 @@ namespace llarp
llarp_time_t
Now() const
{
return llarp_ev_loop_time_now_ms(m_Loop);
return m_Loop->time_now();
}
bool
@ -106,17 +105,11 @@ namespace llarp
void
ForEachSession(std::function<void(ILinkSession*)> visit) EXCLUDES(m_AuthedLinksMutex);
static void
udp_tick(llarp_udp_io* udp);
void
SendTo_LL(const SockAddr& to, const llarp_buffer_t& pkt)
{
llarp_ev_udp_sendto(&m_udp, to, pkt);
}
SendTo_LL(const SockAddr& to, const llarp_buffer_t& pkt);
virtual bool
Configure(llarp_ev_loop_ptr loop, const std::string& ifname, int af, uint16_t port);
Configure(EventLoop_ptr loop, const std::string& ifname, int af, uint16_t port);
virtual std::shared_ptr<ILinkSession>
NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) = 0;
@ -138,7 +131,7 @@ namespace llarp
TryEstablishTo(RouterContact rc);
bool
Start(std::shared_ptr<llarp::Logic> l);
Start();
virtual void
Stop();
@ -211,12 +204,6 @@ namespace llarp
std::shared_ptr<KeyManager> keyManager;
WorkerFunc_t QueueWork;
std::shared_ptr<Logic>
logic()
{
return m_Logic;
}
bool
operator<(const ILinkLayer& other) const
{
@ -235,20 +222,11 @@ namespace llarp
return m_Pending.size();
}
int
GetUDPSocket() const
{
return m_udp.fd;
}
// Returns the file description of the UDP server, if available.
std::optional<int>
GetUDPFD() const;
private:
void
OnTick();
void
ScheduleTick(llarp_time_t interval);
uint32_t tick_id;
const SecretKey& m_RouterEncSecret;
protected:
@ -262,10 +240,9 @@ namespace llarp
bool
PutSession(const std::shared_ptr<ILinkSession>& s);
std::shared_ptr<llarp::Logic> m_Logic = nullptr;
llarp_ev_loop_ptr m_Loop;
EventLoop_ptr m_Loop;
SockAddr m_ourAddr;
llarp_udp_io m_udp;
std::shared_ptr<llarp::UDPHandle> m_udp;
SecretKey m_SecretKey;
using AuthedLinks =
@ -278,6 +255,9 @@ namespace llarp
Pending m_Pending GUARDED_BY(m_PendingMutex);
std::unordered_map<SockAddr, llarp_time_t, SockAddr::Hash> m_RecentlyClosed;
private:
std::shared_ptr<int> m_repeater_keepalive;
};
using LinkLayer_ptr = std::shared_ptr<ILinkLayer>;

@ -12,7 +12,6 @@
#include <util/buffer.hpp>
#include <util/logging/logger.hpp>
#include <util/meta/memfn.hpp>
#include <util/thread/logic.hpp>
#include <tooling/path_event.hpp>
#include <functional>
@ -238,10 +237,9 @@ namespace llarp
break;
}
auto func =
std::bind(&LR_StatusMessage::CreateAndSend, router, pathid, nextHop, pathKey, status);
router->QueueWork(func);
router->QueueWork([router, pathid, nextHop, pathKey, status] {
LR_StatusMessage::CreateAndSend(router, pathid, nextHop, pathKey, status);
});
}
/// this is done from logic thread
@ -438,7 +436,7 @@ namespace llarp
// we are the farthest hop
llarp::LogDebug("We are the farthest hop for ", info);
// send a LRSM down the path
LogicCall(self->context->logic(), [=]() {
self->context->loop()->call([self] {
SendPathConfirm(self);
self->decrypter = nullptr;
});
@ -447,7 +445,7 @@ namespace llarp
{
// forward upstream
// we are still in the worker thread so post job to logic
LogicCall(self->context->logic(), [=]() {
self->context->loop()->call([self] {
SendLRCM(self);
self->decrypter = nullptr;
});

@ -9,7 +9,6 @@
#include <util/buffer.hpp>
#include <util/logging/logger.hpp>
#include <util/meta/memfn.hpp>
#include <util/thread/logic.hpp>
#include <tooling/path_event.hpp>
#include <functional>
@ -224,8 +223,8 @@ namespace llarp
LR_StatusMessage::QueueSendMessage(
AbstractRouter* router, const RouterID nextHop, std::shared_ptr<LR_StatusMessage> msg)
{
auto func = std::bind(&LR_StatusMessage::SendMessage, router, nextHop, msg);
LogicCall(router->logic(), func);
router->loop()->call(
[router, nextHop, msg = std::move(msg)] { SendMessage(router, nextHop, msg); });
}
void

@ -1,7 +1,7 @@
#ifndef LLARP_IP_HPP
#define LLARP_IP_HPP
#include <ev/ev.h>
#include <ev/ev.hpp>
#include <net/net.hpp>
#include <util/buffer.hpp>
#include <util/time.hpp>
@ -109,8 +109,6 @@ struct ipv6_header
#include <service/protocol_type.hpp>
#include <utility>
struct llarp_ev_loop;
namespace llarp
{
namespace net
@ -143,25 +141,25 @@ namespace llarp
struct PutTime
{
llarp_ev_loop_ptr loop;
PutTime(llarp_ev_loop_ptr evloop) : loop(std::move(evloop))
EventLoop_ptr loop;
PutTime(EventLoop_ptr evloop) : loop(std::move(evloop))
{}
void
operator()(IPPacket& pkt) const
{
pkt.timestamp = llarp_ev_loop_time_now_ms(loop);
pkt.timestamp = loop->time_now();
}
};
struct GetNow
{
llarp_ev_loop_ptr loop;
GetNow(llarp_ev_loop_ptr evloop) : loop(std::move(evloop))
EventLoop_ptr loop;
GetNow(EventLoop_ptr evloop) : loop(std::move(evloop))
{}
llarp_time_t
operator()() const
{
return llarp_ev_loop_time_now_ms(loop);
return loop->time_now();
}
};

@ -19,7 +19,7 @@
#include <util/logging/logger.hpp>
#include <util/str.hpp>
#if ANDROID
#ifdef ANDROID
#include <android/ifaddrs.h>
#else
#ifndef _WIN32

@ -23,7 +23,9 @@ namespace llarp
SockAddr::init()
{
llarp::Zero(&m_addr, sizeof(m_addr));
m_addr.sin6_family = AF_INET6;
llarp::Zero(&m_addr4, sizeof(m_addr4));
m_addr4.sin_family = AF_INET;
}
void
@ -167,7 +169,8 @@ namespace llarp
SockAddr::operator const sockaddr*() const
{
return (sockaddr*)&m_addr;
return ipv6_is_mapped_ipv4(m_addr.sin6_addr) ? reinterpret_cast<const sockaddr*>(&m_addr4)
: reinterpret_cast<const sockaddr*>(&m_addr);
}
SockAddr::operator const sockaddr_in*() const
@ -264,10 +267,9 @@ namespace llarp
if (isEmpty())
return "";
const uint8_t* ip6 = m_addr.sin6_addr.s6_addr;
std::string str;
if (ip6[10] == 0xff and ip6[11] == 0xff)
if (ipv6_is_mapped_ipv4(m_addr.sin6_addr))
{
// handle IPv4 mapped addrs
constexpr auto MaxIPv4PlusPortStringSize = 22;
@ -309,8 +311,6 @@ namespace llarp
void
SockAddr::setIPv4(uint32_t ip)
{
m_addr.sin6_family = AF_INET;
uint8_t* ip6 = m_addr.sin6_addr.s6_addr;
llarp::Zero(ip6, sizeof(m_addr.sin6_addr.s6_addr));
@ -318,15 +318,12 @@ namespace llarp
std::memcpy(ip6 + 12, &ip, 4);
m_addr4.sin_addr.s_addr = ip;
m_addr4.sin_family = AF_INET;
m_empty = false;
}
void
SockAddr::setIPv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{
m_addr.sin6_family = AF_INET;
uint8_t* ip6 = m_addr.sin6_addr.s6_addr;
llarp::Zero(ip6, sizeof(m_addr.sin6_addr.s6_addr));
@ -338,7 +335,6 @@ namespace llarp
ip6[15] = d;
const auto ip = ipaddr_ipv4_bits(a, b, c, d);
m_addr4.sin_addr.s_addr = htonl(ip.h);
m_addr4.sin_family = AF_INET;
m_empty = false;
}

@ -7,7 +7,6 @@
#include <util/fs.hpp>
#include <util/logging/logger.hpp>
#include <util/mem.hpp>
#include <util/thread/logic.hpp>
#include <util/str.hpp>
#include <dht/kademlia.hpp>

@ -20,8 +20,6 @@
namespace llarp
{
class Logic;
class NodeDB
{
struct Entry

@ -1,4 +1,5 @@
#include <path/ihophandler.hpp>
#include <router/abstractrouter.hpp>
namespace llarp
{
@ -6,7 +7,7 @@ namespace llarp
{
// handle data in upstream direction
bool
IHopHandler::HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter*)
IHopHandler::HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter* r)
{
if (not m_UpstreamReplayFilter.Insert(Y))
return false;
@ -17,12 +18,13 @@ namespace llarp
pkt.first.resize(X.sz);
std::copy_n(X.base, X.sz, pkt.first.begin());
pkt.second = Y;
r->loop()->wakeup();
return true;
}
// handle data in downstream direction
bool
IHopHandler::HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter*)
IHopHandler::HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter* r)
{
if (not m_DownstreamReplayFilter.Insert(Y))
return false;
@ -33,6 +35,7 @@ namespace llarp
pkt.first.resize(X.sz);
std::copy_n(X.base, X.sz, pkt.first.begin());
pkt.second = Y;
r->loop()->wakeup();
return true;
}

@ -14,7 +14,6 @@
#include <routing/transfer_traffic_message.hpp>
#include <util/buffer.hpp>
#include <util/endian.hpp>
#include <util/thread/logic.hpp>
#include <tooling/path_event.hpp>
#include <deque>
@ -174,8 +173,7 @@ namespace llarp
if ((currentStatus & LR_StatusRecord::SUCCESS) == LR_StatusRecord::SUCCESS)
{
llarp::LogDebug("LR_Status message processed, path build successful");
auto self = shared_from_this();
LogicCall(r->logic(), [=]() { self->HandlePathConfirmMessage(r); });
r->loop()->call([r, self = shared_from_this()] { self->HandlePathConfirmMessage(r); });
}
else
{
@ -231,8 +229,8 @@ namespace llarp
{
llarp::LogDebug("Path build failed for an unspecified reason");
}
auto self = shared_from_this();
LogicCall(r->logic(), [=]() { self->EnterState(ePathFailed, r->Now()); });
r->loop()->call(
[r, self = shared_from_this()]() { self->EnterState(ePathFailed, r->Now()); });
}
// TODO: meaningful return value?
@ -439,7 +437,7 @@ namespace llarp
msg.pathid = TXID();
++idx;
}
LogicCall(r->logic(), [self = shared_from_this(), data = std::move(sendmsgs), r]() {
r->loop()->call([self = shared_from_this(), data = std::move(sendmsgs), r]() mutable {
self->HandleAllUpstream(std::move(data), r);
});
}
@ -509,7 +507,7 @@ namespace llarp
sendMsgs[idx].X = buf;
++idx;
}
LogicCall(r->logic(), [self = shared_from_this(), msgs = std::move(sendMsgs), r]() {
r->loop()->call([self = shared_from_this(), msgs = std::move(sendMsgs), r]() mutable {
self->HandleAllDownstream(std::move(msgs), r);
});
}

@ -28,7 +28,6 @@
namespace llarp
{
class Logic;
struct AbstractRouter;
struct LR_CommitMessage;

@ -42,10 +42,10 @@ namespace llarp
#endif
}
std::shared_ptr<Logic>
PathContext::logic()
const EventLoop_ptr&
PathContext::loop()
{
return m_Router->logic();
return m_Router->loop();
}
const SecretKey&

@ -18,7 +18,6 @@
namespace llarp
{
class Logic;
struct AbstractRouter;
struct LR_CommitMessage;
struct RelayDownstreamMessage;
@ -147,8 +146,8 @@ namespace llarp
}
};
std::shared_ptr<Logic>
logic();
const EventLoop_ptr&
loop();
AbstractRouter*
Router();

@ -7,7 +7,6 @@
#include <profiling.hpp>
#include <router/abstractrouter.hpp>
#include <util/buffer.hpp>
#include <util/thread/logic.hpp>
#include <tooling/path_event.hpp>
#include <functional>
@ -28,7 +27,7 @@ namespace llarp
size_t idx = 0;
AbstractRouter* router = nullptr;
WorkerFunc_t work;
std::shared_ptr<Logic> logic;
EventLoop_ptr loop;
LR_CommitMessage LRCM;
void
@ -97,21 +96,21 @@ namespace llarp
{
// farthest hop
// TODO: encrypt junk frames because our public keys are not eligator
LogicCall(logic, std::bind(result, shared_from_this()));
loop->call([self = shared_from_this()] { self->result(self); });
}
else
{
// next hop
work(std::bind(&AsyncPathKeyExchangeContext::GenerateNextKey, shared_from_this()));
work([self = shared_from_this()] { self->GenerateNextKey(); });
}
}
/// Generate all keys asynchronously and call handler when done
void
AsyncGenerateKeys(Path_t p, std::shared_ptr<Logic> l, WorkerFunc_t worker, Handler func)
AsyncGenerateKeys(Path_t p, EventLoop_ptr l, WorkerFunc_t worker, Handler func)
{
path = p;
logic = l;
loop = std::move(l);
result = func;
work = worker;
@ -119,7 +118,7 @@ namespace llarp
{
LRCM.frames[i].Randomize();
}
work(std::bind(&AsyncPathKeyExchangeContext::GenerateNextKey, shared_from_this()));
work([self = shared_from_this()] { self->GenerateNextKey(); });
}
};
@ -393,7 +392,7 @@ namespace llarp
path->SetBuildResultHook([self](Path_ptr p) { self->HandlePathBuilt(p); });
ctx->AsyncGenerateKeys(
path,
m_router->logic(),
m_router->loop(),
[r = m_router](auto func) { r->QueueWork(std::move(func)); },
&PathBuilderKeysGenerated);
}

@ -189,7 +189,7 @@ namespace llarp
/// return true if we should publish a new hidden service descriptor
virtual bool
ShouldPublishDescriptors(__attribute__((unused)) llarp_time_t now) const
ShouldPublishDescriptors([[maybe_unused]] llarp_time_t now) const
{
return false;
}

@ -121,13 +121,10 @@ namespace llarp
{
auto flushIt = [self = shared_from_this(), r]() {
std::vector<RelayDownstreamMessage> msgs;
do
while (auto maybe = self->m_DownstreamGather.tryPopFront())
{
auto maybe = self->m_DownstreamGather.tryPopFront();
if (not maybe)
break;
msgs.emplace_back(*maybe);
} while (true);
msgs.push_back(*maybe);
}
self->HandleAllDownstream(std::move(msgs), r);
};
for (auto& ev : *msgs)
@ -147,12 +144,12 @@ namespace llarp
info.downstream);
if (m_DownstreamGather.full())
{
LogicCall(r->logic(), flushIt);
r->loop()->call(flushIt);
}
if (m_DownstreamGather.enabled())
m_DownstreamGather.pushBack(msg);
}
LogicCall(r->logic(), flushIt);
r->loop()->call(flushIt);
}
void
@ -160,13 +157,10 @@ namespace llarp
{
auto flushIt = [self = shared_from_this(), r]() {
std::vector<RelayUpstreamMessage> msgs;
do
while (auto maybe = self->m_UpstreamGather.tryPopFront())
{
auto maybe = self->m_UpstreamGather.tryPopFront();
if (not maybe)
break;
msgs.emplace_back(*maybe);
} while (true);
msgs.push_back(*maybe);
}
self->HandleAllUpstream(std::move(msgs), r);
};
for (auto& ev : *msgs)
@ -179,12 +173,12 @@ namespace llarp
msg.X = buf;
if (m_UpstreamGather.full())
{
LogicCall(r->logic(), flushIt);
r->loop()->call(flushIt);
}
if (m_UpstreamGather.enabled())
m_UpstreamGather.pushBack(msg);
}
LogicCall(r->logic(), flushIt);
r->loop()->call(flushIt);
}
void
@ -207,6 +201,7 @@ namespace llarp
other->FlushDownstream(r);
}
m_FlushOthers.clear();
r->loop()->wakeup();
}
else
{
@ -221,8 +216,8 @@ namespace llarp
info.upstream);
r->SendToOrQueue(info.upstream, &msg);
}
r->linkManager().PumpLinks();
}
r->linkManager().PumpLinks();
}
void
@ -285,8 +280,8 @@ namespace llarp
bool
TransitHop::HandlePathConfirmMessage(
__attribute__((unused)) const llarp::routing::PathConfirmMessage& msg,
__attribute__((unused)) AbstractRouter* r)
[[maybe_unused]] const llarp::routing::PathConfirmMessage& msg,
[[maybe_unused]] AbstractRouter* r)
{
llarp::LogWarn("unwarranted path confirm message on ", info);
return false;
@ -294,8 +289,8 @@ namespace llarp
bool
TransitHop::HandleDataDiscardMessage(
__attribute__((unused)) const llarp::routing::DataDiscardMessage& msg,
__attribute__((unused)) AbstractRouter* r)
[[maybe_unused]] const llarp::routing::DataDiscardMessage& msg,
[[maybe_unused]] AbstractRouter* r)
{
llarp::LogWarn("unwarranted path data discard message on ", info);
return false;
@ -488,8 +483,7 @@ namespace llarp
void
TransitHop::QueueDestroySelf(AbstractRouter* r)
{
auto func = std::bind(&TransitHop::SetSelfDestruct, shared_from_this());
LogicCall(r->logic(), func);
r->loop()->call([self = shared_from_this()] { self->SetSelfDestruct(); });
}
} // namespace path
} // namespace llarp

@ -8,7 +8,7 @@
#include <util/status.hpp>
#include <router/i_outbound_message_handler.hpp>
#include <vector>
#include <ev/ev.h>
#include <ev/ev.hpp>
#include <functional>
#include <router_contact.hpp>
#include <tooling/router_event.hpp>
@ -29,7 +29,6 @@ namespace oxenmq
namespace llarp
{
class NodeDB;
class Logic;
struct Config;
struct RouterID;
struct ILinkMessage;
@ -81,7 +80,7 @@ namespace llarp
using LMQ_ptr = std::shared_ptr<oxenmq::OxenMQ>;
struct AbstractRouter
struct AbstractRouter : public std::enable_shared_from_this<AbstractRouter>
{
#ifdef LOKINET_HIVE
tooling::RouterHive* hive = nullptr;
@ -92,22 +91,19 @@ namespace llarp
virtual bool
HandleRecvLinkMessageBuffer(ILinkSession* from, const llarp_buffer_t& msg) = 0;
virtual LMQ_ptr
virtual const LMQ_ptr&
lmq() const = 0;
virtual vpn::Platform*
GetVPNPlatform() const = 0;
virtual std::shared_ptr<rpc::LokidRpcClient>
virtual const std::shared_ptr<rpc::LokidRpcClient>&
RpcClient() const = 0;
virtual std::shared_ptr<Logic>
logic() const = 0;
virtual llarp_dht_context*
dht() const = 0;
virtual std::shared_ptr<NodeDB>
virtual const std::shared_ptr<NodeDB>&
nodedb() const = 0;
virtual const path::PathContext&
@ -122,7 +118,7 @@ namespace llarp
virtual exit::Context&
exitContext() = 0;
virtual std::shared_ptr<KeyManager>
virtual const std::shared_ptr<KeyManager>&
keyManager() const = 0;
virtual const SecretKey&
@ -134,8 +130,8 @@ namespace llarp
virtual Profiling&
routerProfiling() = 0;
virtual llarp_ev_loop_ptr
netloop() const = 0;
virtual const EventLoop_ptr&
loop() const = 0;
/// call function in crypto worker
virtual void QueueWork(std::function<void(void)>) = 0;

@ -113,11 +113,11 @@ namespace llarp
void
OutboundMessageHandler::Init(
ILinkManager* linkManager, I_RCLookupHandler* lookupHandler, std::shared_ptr<Logic> logic)
ILinkManager* linkManager, I_RCLookupHandler* lookupHandler, EventLoop_ptr loop)
{
_linkManager = linkManager;
_lookupHandler = lookupHandler;
_logic = logic;
_loop = std::move(loop);
outboundMessageQueues.emplace(zeroID, MessageQueue());
}
@ -183,10 +183,7 @@ namespace llarp
OutboundMessageHandler::DoCallback(SendStatusHandler callback, SendStatus status)
{
if (callback)
{
auto f = std::bind(callback, status);
LogicCall(_logic, [self = this, f]() { self->m_Killer.TryAccess(f); });
}
_loop->call([f = std::move(callback), status] { f(status); });
}
void

@ -3,7 +3,7 @@
#include <router/i_outbound_message_handler.hpp>
#include <util/thread/logic.hpp>
#include <ev/ev.hpp>
#include <util/thread/queue.hpp>
#include <path/path_types.hpp>
#include <router_id.hpp>
@ -19,7 +19,6 @@ namespace llarp
{
struct ILinkManager;
struct I_RCLookupHandler;
class Logic;
enum class SessionResult;
struct OutboundMessageHandler final : public IOutboundMessageHandler
@ -43,7 +42,7 @@ namespace llarp
ExtractStatus() const override;
void
Init(ILinkManager* linkManager, I_RCLookupHandler* lookupHandler, std::shared_ptr<Logic> logic);
Init(ILinkManager* linkManager, I_RCLookupHandler* lookupHandler, EventLoop_ptr loop);
private:
using Message = std::pair<std::vector<byte_t>, SendStatusHandler>;
@ -139,7 +138,7 @@ namespace llarp
ILinkManager* _linkManager;
I_RCLookupHandler* _lookupHandler;
std::shared_ptr<Logic> _logic;
EventLoop_ptr _loop;
util::ContentionKiller m_Killer;

@ -8,7 +8,6 @@
#include <router/i_rc_lookup_handler.hpp>
#include <link/i_link_manager.hpp>
#include <util/meta/memfn.hpp>
#include <util/thread/logic.hpp>
#include <util/thread/threading.hpp>
#include <util/status.hpp>
#include <crypto/crypto.hpp>
@ -163,16 +162,16 @@ namespace llarp
ILinkManager* linkManager,
I_RCLookupHandler* rcLookup,
Profiling* profiler,
std::shared_ptr<Logic> logic,
EventLoop_ptr loop,
WorkerFunc_t dowork)
{
_router = router;
_linkManager = linkManager;
_rcLookup = rcLookup;
_logic = logic;
_loop = std::move(loop);
_nodedb = router->nodedb();
_profiler = profiler;
work = dowork;
work = std::move(dowork);
}
void
@ -226,8 +225,7 @@ namespace llarp
}
if (ShouldConnectTo(router))
{
auto fn = std::bind(&OutboundSessionMaker::DoEstablish, this, router);
LogicCall(_logic, fn);
_loop->call([this, router] { DoEstablish(router); });
}
}
@ -348,8 +346,7 @@ namespace llarp
for (const auto& callback : movedCallbacks)
{
auto func = std::bind(callback, router, type);
LogicCall(_logic, func);
_loop->call([callback, router, type] { return callback(router, type); });
}
{

@ -4,7 +4,6 @@
#include <router/i_outbound_session_maker.hpp>
#include <router/i_rc_lookup_handler.hpp>
#include <util/thread/logic.hpp>
#include <util/thread/threading.hpp>
#include <profiling.hpp>
@ -60,7 +59,7 @@ namespace llarp
ILinkManager* linkManager,
I_RCLookupHandler* rcLookup,
Profiling* profiler,
std::shared_ptr<Logic> logic,
EventLoop_ptr loop,
WorkerFunc_t work);
void
@ -113,7 +112,7 @@ namespace llarp
I_RCLookupHandler* _rcLookup = nullptr;
Profiling* _profiler = nullptr;
std::shared_ptr<NodeDB> _nodedb;
std::shared_ptr<Logic> _logic;
EventLoop_ptr _loop;
WorkerFunc_t work;
RouterID us;
};

@ -156,8 +156,7 @@ namespace llarp
if (rc.IsPublicRouter())
{
LogDebug("Adding or updating RC for ", RouterID(rc.pubkey), " to nodedb and dht.");
const RouterContact copy{rc};
LogicCall(_logic, [copy, n = _nodedb]() { n->PutIfNewer(copy); });
_loop->call([rc, n = _nodedb] { n->PutIfNewer(rc); });
_dht->impl->PutRCNodeAsync(rc);
}
@ -301,7 +300,7 @@ namespace llarp
RCLookupHandler::Init(
llarp_dht_context* dht,
std::shared_ptr<NodeDB> nodedb,
std::shared_ptr<Logic> logic,
EventLoop_ptr loop,
WorkerFunc_t dowork,
ILinkManager* linkManager,
service::Context* hiddenServiceContext,
@ -311,9 +310,9 @@ namespace llarp
bool isServiceNode_arg)
{
_dht = dht;
_nodedb = nodedb;
_logic = logic;
_work = dowork;
_nodedb = std::move(nodedb);
_loop = std::move(loop);
_work = std::move(dowork);
_hiddenServiceContext = hiddenServiceContext;
_strictConnectPubkeys = strictConnectPubkeys;
_bootstrapRCList = bootstrapRCList;

@ -16,7 +16,7 @@ struct llarp_dht_context;
namespace llarp
{
class NodeDB;
class Logic;
class EventLoop;
namespace service
{
@ -76,7 +76,7 @@ namespace llarp
Init(
llarp_dht_context* dht,
std::shared_ptr<NodeDB> nodedb,
std::shared_ptr<Logic> logic,
std::shared_ptr<EventLoop> loop,
WorkerFunc_t dowork,
ILinkManager* linkManager,
service::Context* hiddenServiceContext,
@ -103,7 +103,7 @@ namespace llarp
llarp_dht_context* _dht = nullptr;
std::shared_ptr<NodeDB> _nodedb;
std::shared_ptr<Logic> _logic;
std::shared_ptr<EventLoop> _loop;
WorkerFunc_t _work = nullptr;
service::Context* _hiddenServiceContext = nullptr;
ILinkManager* _linkManager = nullptr;

@ -46,14 +46,10 @@ static constexpr std::chrono::milliseconds ROUTER_TICK_INTERVAL = 1s;
namespace llarp
{
Router::Router(
llarp_ev_loop_ptr __netloop,
std::shared_ptr<Logic> l,
std::shared_ptr<vpn::Platform> vpnPlatform)
Router::Router(EventLoop_ptr loop, std::shared_ptr<vpn::Platform> vpnPlatform)
: ready(false)
, m_lmq(std::make_shared<oxenmq::OxenMQ>())
, _netloop(std::move(__netloop))
, _logic(std::move(l))
, _loop(std::move(loop))
, _vpnPlatform(std::move(vpnPlatform))
, paths(this)
, _exitContext(this)
@ -289,7 +285,7 @@ namespace llarp
bool
Router::Configure(std::shared_ptr<Config> c, bool isRouter, std::shared_ptr<NodeDB> nodedb)
{
m_Config = c;
m_Config = std::move(c);
auto& conf = *m_Config;
whitelistRouters = conf.lokid.whitelistRouters;
if (whitelistRouters)
@ -307,7 +303,7 @@ namespace llarp
m_lmq->start();
_nodedb = nodedb;
_nodedb = std::move(nodedb);
m_isServiceNode = conf.router.m_isRelay;
@ -366,18 +362,10 @@ namespace llarp
if (_onDown)
_onDown();
LogInfo("closing router");
llarp_ev_loop_stop(_netloop);
_loop->stop();
_running.store(false);
}
void
Router::handle_router_ticker()
{
ticker_job_id = 0;
Tick();
ScheduleTicker(ROUTER_TICK_INTERVAL);
}
bool
Router::ParseRoutingMessageBuffer(
const llarp_buffer_t& buf, routing::IMessageHandler* h, const PathID_t& rxid)
@ -573,19 +561,19 @@ namespace llarp
LogInfo("Loaded ", bootstrapRCList.size(), " bootstrap routers");
// Init components after relevant config settings loaded
_outboundMessageHandler.Init(&_linkManager, &_rcLookupHandler, _logic);
_outboundMessageHandler.Init(&_linkManager, &_rcLookupHandler, _loop);
_outboundSessionMaker.Init(
this,
&_linkManager,
&_rcLookupHandler,
&_routerProfiling,
_logic,
_loop,
util::memFn(&AbstractRouter::QueueWork, this));
_linkManager.Init(&_outboundSessionMaker);
_rcLookupHandler.Init(
_dht,
_nodedb,
_logic,
_loop,
util::memFn(&AbstractRouter::QueueWork, this),
&_linkManager,
&_hiddenServiceContext,
@ -613,7 +601,7 @@ namespace llarp
{
auto server = iwp::NewInboundLink(
m_keyManager,
netloop(),
loop(),
util::memFn(&AbstractRouter::rc, this),
util::memFn(&AbstractRouter::HandleRecvLinkMessageBuffer, this),
util::memFn(&AbstractRouter::Sign, this),
@ -628,7 +616,7 @@ namespace llarp
const std::string& key = serverConfig.interface;
int af = serverConfig.addressFamily;
uint16_t port = serverConfig.port;
if (!server->Configure(netloop(), key, af, port))
if (!server->Configure(loop(), key, af, port))
{
throw std::runtime_error(stringify("failed to bind inbound link on ", key, " port ", port));
}
@ -914,12 +902,6 @@ namespace llarp
return CryptoManager::instance()->sign(sig, identity(), buf);
}
void
Router::ScheduleTicker(llarp_time_t interval)
{
ticker_job_id = _logic->call_later(interval, std::bind(&Router::handle_router_ticker, this));
}
void
Router::SessionClosed(RouterID remote)
{
@ -1075,7 +1057,7 @@ namespace llarp
}
}
_outboundSessionMaker.SetOurRouter(pubkey());
if (!_linkManager.StartLinks(_logic))
if (!_linkManager.StartLinks())
{
LogWarn("One or more links failed to start.");
return false;
@ -1136,11 +1118,11 @@ namespace llarp
#ifdef _WIN32
// windows uses proactor event loop so we need to constantly pump
_netloop->add_ticker(std::bind(&Router::PumpLL, this));
_loop->add_ticker([this] { PumpLL(); });
#else
_netloop->set_pump_function(std::bind(&Router::PumpLL, this));
_loop->set_pump_function([this] { PumpLL(); });
#endif
ScheduleTicker(ROUTER_TICK_INTERVAL);
_loop->call_every(ROUTER_TICK_INTERVAL, weak_from_this(), [this] { Tick(); });
_running.store(true);
_startedAt = Now();
#if defined(WITH_SYSTEMD)
@ -1177,7 +1159,7 @@ namespace llarp
{
StopLinks();
nodedb()->SaveToDisk();
_logic->call_later(200ms, std::bind(&Router::AfterStopLinks, this));
_loop->call_later(200ms, [this] { AfterStopLinks(); });
}
void
@ -1224,7 +1206,7 @@ namespace llarp
_exitContext.Stop();
paths.PumpUpstream();
_linkManager.PumpLinks();
_logic->call_later(200ms, std::bind(&Router::AfterStopIssued, this));
_loop->call_later(200ms, [this] { AfterStopIssued(); });
}
bool
@ -1315,7 +1297,7 @@ namespace llarp
{
auto link = iwp::NewOutboundLink(
m_keyManager,
netloop(),
loop(),
util::memFn(&AbstractRouter::rc, this),
util::memFn(&AbstractRouter::HandleRecvLinkMessageBuffer, this),
util::memFn(&AbstractRouter::Sign, this),
@ -1338,15 +1320,13 @@ namespace llarp
if (!link)
throw std::runtime_error("NewOutboundLink() failed to provide a link");
const auto afs = {AF_INET, AF_INET6};
for (const auto af : afs)
for (const auto af : {AF_INET, AF_INET6})
{
if (not link->Configure(netloop(), "*", af, m_OutboundPort))
if (not link->Configure(loop(), "*", af, m_OutboundPort))
continue;
#if defined(ANDROID)
m_OutboundUDPSocket = link->GetUDPSocket();
m_OutboundUDPSocket = link->GetUDPFD().value_or(-1);
#endif
_linkManager.AddLink(std::move(link), false);
return true;

@ -8,7 +8,7 @@
#include <config/key_manager.hpp>
#include <constants/link_layer.hpp>
#include <crypto/types.hpp>
#include <ev/ev.h>
#include <ev/ev.hpp>
#include <exit/context.hpp>
#include <handlers/tun.hpp>
#include <link/link_manager.hpp>
@ -35,7 +35,6 @@
#include <util/mem.hpp>
#include <util/status.hpp>
#include <util/str.hpp>
#include <util/thread/logic.hpp>
#include <util/time.hpp>
#include <functional>
@ -76,24 +75,18 @@ namespace llarp
LMQ_ptr m_lmq;
LMQ_ptr
const LMQ_ptr&
lmq() const override
{
return m_lmq;
}
std::shared_ptr<rpc::LokidRpcClient>
const std::shared_ptr<rpc::LokidRpcClient>&
RpcClient() const override
{
return m_lokidRpcClient;
}
std::shared_ptr<Logic>
logic() const override
{
return _logic;
}
llarp_dht_context*
dht() const override
{
@ -103,7 +96,7 @@ namespace llarp
util::StatusObject
ExtractStatus() const override;
std::shared_ptr<NodeDB>
const std::shared_ptr<NodeDB>&
nodedb() const override
{
return _nodedb;
@ -136,7 +129,7 @@ namespace llarp
return _exitContext;
}
std::shared_ptr<KeyManager>
const std::shared_ptr<KeyManager>&
keyManager() const override
{
return m_keyManager;
@ -160,10 +153,10 @@ namespace llarp
return _routerProfiling;
}
llarp_ev_loop_ptr
netloop() const override
const EventLoop_ptr&
loop() const override
{
return _netloop;
return _loop;
}
vpn::Platform*
@ -180,8 +173,7 @@ namespace llarp
std::optional<SockAddr> _ourAddress;
llarp_ev_loop_ptr _netloop;
std::shared_ptr<Logic> _logic;
EventLoop_ptr _loop;
std::shared_ptr<vpn::Platform> _vpnPlatform;
path::PathContext paths;
exit::Context _exitContext;
@ -206,8 +198,6 @@ namespace llarp
// should we be sending padded messages every interval?
bool sendPadding = false;
uint32_t ticker_job_id = 0;
LinkMessageParser inbound_link_msg_parser;
routing::InboundMessageParser inbound_routing_msg_parser;
@ -326,12 +316,9 @@ namespace llarp
void
GossipRCIfNeeded(const RouterContact rc) override;
explicit Router(
llarp_ev_loop_ptr __netloop,
std::shared_ptr<Logic> logic,
std::shared_ptr<vpn::Platform> vpnPlatform);
explicit Router(EventLoop_ptr loop, std::shared_ptr<vpn::Platform> vpnPlatform);
virtual ~Router() override;
~Router() override;
bool
HandleRecvLinkMessageBuffer(ILinkSession* from, const llarp_buffer_t& msg) override;
@ -462,10 +449,6 @@ namespace llarp
return llarp::time_now_ms();
}
/// schedule ticker to call i ms from now
void
ScheduleTicker(llarp_time_t i = 1s);
/// parse a routing message in a buffer and handle it with a handler if
/// successful parsing return true on parse and handle success otherwise
/// return false
@ -502,9 +485,6 @@ namespace llarp
uint32_t
NextPathBuildNumber() override;
void
handle_router_ticker();
void
AfterStopLinks();

@ -29,7 +29,7 @@ namespace llarp::rpc
},
[self = shared_from_this()](oxenmq::ConnectionID, std::string_view fail) {
LogWarn("failed to connect to endpoint auth server: ", fail);
self->m_Endpoint->RouterLogic()->call_later(1s, [self]() { self->Start(); });
self->m_Endpoint->Loop()->call_later(1s, [self] { self->Start(); });
});
}
@ -47,30 +47,28 @@ namespace llarp::rpc
service::ConvoTag tag = msg->tag;
m_PendingAuths.insert(tag);
const auto from = msg->sender.Addr();
auto reply =
[self = this, tag, logic = m_Endpoint->RouterLogic(), hook](service::AuthResult result) {
logic->Call([self, hook, result, tag]() {
self->m_PendingAuths.erase(tag);
hook(result);
});
};
auto reply = m_Endpoint->Loop()->make_caller([this, tag, hook](service::AuthResult result) {
m_PendingAuths.erase(tag);
hook(result);
});
if (m_AuthWhitelist.count(from))
{
// explicitly whitelisted source
reply({service::AuthResultCode::eAuthAccepted, "explicitly whitelisted"});
reply(service::AuthResult{service::AuthResultCode::eAuthAccepted, "explicitly whitelisted"});
return;
}
if (not m_Conn.has_value())
{
// we don't have a connection to the backend so it's failed
reply({service::AuthResultCode::eAuthFailed, "remote has no connection to auth backend"});
reply(service::AuthResult{service::AuthResultCode::eAuthFailed,
"remote has no connection to auth backend"});
return;
}
if (msg->proto != llarp::service::eProtocolAuth)
{
// not an auth message, reject
reply({service::AuthResultCode::eAuthRejected, "protocol error"});
reply(service::AuthResult{service::AuthResultCode::eAuthRejected, "protocol error"});
return;
}
@ -81,7 +79,8 @@ namespace llarp::rpc
m_LMQ->request(
*m_Conn,
m_AuthMethod,
[self = shared_from_this(), reply](bool success, std::vector<std::string> data) {
[self = shared_from_this(), reply = std::move(reply)](
bool success, std::vector<std::string> data) {
service::AuthResult result{service::AuthResultCode::eAuthFailed, "no reason given"};
if (success and not data.empty())
{

@ -8,7 +8,6 @@
#include <nlohmann/json.hpp>
#include <util/time.hpp>
#include <util/thread/logic.hpp>
namespace llarp
{
@ -57,7 +56,7 @@ namespace llarp
[self = shared_from_this()](oxenmq::ConnectionID) { self->Connected(); },
[self = shared_from_this(), url](oxenmq::ConnectionID, std::string_view f) {
llarp::LogWarn("Failed to connect to lokid: ", f);
LogicCall(self->m_Router->logic(), [self, url]() { self->ConnectAsync(url); });
self->m_Router->loop()->call([self, url]() { self->ConnectAsync(url); });
});
}
@ -170,7 +169,7 @@ namespace llarp
return;
}
// inform router about the new list
LogicCall(m_Router->logic(), [r = m_Router, nodeList = std::move(nodeList)]() mutable {
m_Router->loop()->call([r = m_Router, nodeList = std::move(nodeList)]() mutable {
r->SetRouterWhitelist(std::move(nodeList));
});
}
@ -252,7 +251,8 @@ namespace llarp
LogError("failed to parse response from lns lookup: ", ex.what());
}
}
LogicCall(r->logic(), [resultHandler, maybe]() { resultHandler(maybe); });
r->loop()->call(
[resultHandler, maybe = std::move(maybe)]() { resultHandler(std::move(maybe)); });
},
req.dump());
}

@ -1,6 +1,5 @@
#include "rpc_server.hpp"
#include <router/route_poker.hpp>
#include <util/thread/logic.hpp>
#include <constants/version.hpp>
#include <nlohmann/json.hpp>
#include <net/ip_range.hpp>
@ -106,7 +105,7 @@ namespace llarp::rpc
.add_request_command(
"status",
[&](oxenmq::Message& msg) {
LogicCall(m_Router->logic(), [defer = msg.send_later(), r = m_Router]() {
m_Router->loop()->call([defer = msg.send_later(), r = m_Router]() {
std::string data;
if (r->IsRunning())
{
@ -158,7 +157,7 @@ namespace llarp::rpc
reply(CreateJSONError("no action taken"));
return;
}
LogicCall(r->logic(), [r, endpoint, kills, reply]() {
r->loop()->call([r, endpoint, kills, reply]() {
auto ep = r->hiddenServiceContext().GetEndpointByName(endpoint);
if (ep == nullptr)
{
@ -236,94 +235,93 @@ namespace llarp::rpc
{
endpoint = endpoint_itr->get<std::string>();
}
LogicCall(
r->logic(), [map, exit, lnsExit, range, token, endpoint, r, reply]() mutable {
auto ep = r->hiddenServiceContext().GetEndpointByName(endpoint);
if (ep == nullptr)
r->loop()->call([map, exit, lnsExit, range, token, endpoint, r, reply]() mutable {
auto ep = r->hiddenServiceContext().GetEndpointByName(endpoint);
if (ep == nullptr)
{
reply(CreateJSONError("no endpoint with name " + endpoint));
return;
}
if (map and (exit.has_value() or lnsExit.has_value()))
{
auto mapExit = [=](service::Address addr) mutable {
ep->MapExitRange(range, addr);
bool shouldSendAuth = false;
if (token.has_value())
{
reply(CreateJSONError("no endpoint with name " + endpoint));
return;
shouldSendAuth = true;
ep->SetAuthInfoForEndpoint(*exit, service::AuthInfo{*token});
}
if (map and (exit.has_value() or lnsExit.has_value()))
{
auto mapExit = [=](service::Address addr) mutable {
ep->MapExitRange(range, addr);
bool shouldSendAuth = false;
if (token.has_value())
{
shouldSendAuth = true;
ep->SetAuthInfoForEndpoint(*exit, service::AuthInfo{*token});
}
ep->EnsurePathToService(
addr,
[reply, r, shouldSendAuth](auto, service::OutboundContext* ctx) {
if (ctx == nullptr)
{
reply(CreateJSONError("could not find exit"));
return;
}
auto onGoodResult = [r, reply](std::string reason) {
r->routePoker().Enable();
r->routePoker().Up();
reply(CreateJSONResponse(reason));
};
if (not shouldSendAuth)
{
onGoodResult("OK");
return;
}
ctx->AsyncSendAuth(
[onGoodResult, reply](service::AuthResult result) {
if (result.code != service::AuthResultCode::eAuthAccepted)
{
reply(CreateJSONError(result.reason));
return;
}
onGoodResult(result.reason);
});
},
5s);
};
if (exit.has_value())
{
mapExit(*exit);
}
else if (lnsExit.has_value())
{
ep->LookupNameAsync(*lnsExit, [reply, mapExit](auto maybe) mutable {
if (not maybe.has_value())
ep->EnsurePathToService(
addr,
[reply, r, shouldSendAuth](auto, service::OutboundContext* ctx) {
if (ctx == nullptr)
{
reply(CreateJSONError("we could not find an exit with that name"));
reply(CreateJSONError("could not find exit"));
return;
}
if (maybe->IsZero())
auto onGoodResult = [r, reply](std::string reason) {
r->routePoker().Enable();
r->routePoker().Up();
reply(CreateJSONResponse(reason));
};
if (not shouldSendAuth)
{
reply(CreateJSONError("lokinet exit does not exist"));
onGoodResult("OK");
return;
}
mapExit(*maybe);
});
ctx->AsyncSendAuth([onGoodResult, reply](service::AuthResult result) {
// TODO: refactor this code. We are 5 lambdas deep here!
if (result.code != service::AuthResultCode::eAuthAccepted)
{
reply(CreateJSONError(result.reason));
return;
}
onGoodResult(result.reason);
});
},
5s);
};
if (exit.has_value())
{
mapExit(*exit);
}
else if (lnsExit.has_value())
{
ep->LookupNameAsync(*lnsExit, [reply, mapExit](auto maybe) mutable {
if (not maybe.has_value())
{
reply(CreateJSONError("we could not find an exit with that name"));
return;
}
else
if (maybe->IsZero())
{
reply(
CreateJSONError("WTF inconsistent request, no exit address or lns "
"name provided?"));
reply(CreateJSONError("lokinet exit does not exist"));
return;
}
return;
}
else if (map and not exit.has_value())
{
reply(CreateJSONError("no exit address provided"));
return;
}
else if (not map)
{
r->routePoker().Down();
ep->UnmapExitRange(range);
}
reply(CreateJSONResponse("OK"));
});
mapExit(*maybe);
});
}
else
{
reply(
CreateJSONError("WTF inconsistent request, no exit address or lns "
"name provided?"));
}
return;
}
else if (map and not exit.has_value())
{
reply(CreateJSONError("no exit address provided"));
return;
}
else if (not map)
{
r->routePoker().Down();
ep->UnmapExitRange(range);
}
reply(CreateJSONResponse("OK"));
});
});
})
.add_request_command("config", [&](oxenmq::Message& msg) {

@ -3,7 +3,6 @@
#include <crypto/crypto.hpp>
#include <crypto/types.hpp>
#include <util/meta/memfn.hpp>
#include <util/thread/logic.hpp>
#include <utility>
namespace llarp
@ -11,7 +10,7 @@ namespace llarp
namespace service
{
AsyncKeyExchange::AsyncKeyExchange(
std::shared_ptr<Logic> l,
EventLoop_ptr l,
ServiceInfo r,
const Identity& localident,
const PQPubKey& introsetPubKey,
@ -19,7 +18,7 @@ namespace llarp
IDataHandler* h,
const ConvoTag& t,
ProtocolType proto)
: logic(std::move(l))
: loop(std::move(l))
, m_remote(std::move(r))
, m_LocalIdentity(localident)
, introPubKey(introsetPubKey)
@ -74,7 +73,7 @@ namespace llarp
self->msg.version = LLARP_PROTO_VERSION;
// encrypt and sign
if (frame->EncryptAndSign(self->msg, K, self->m_LocalIdentity))
LogicCall(self->logic, std::bind(&AsyncKeyExchange::Result, self, frame));
self->loop->call([self, frame] { AsyncKeyExchange::Result(self, frame); });
else
{
LogError("failed to encrypt and sign");

@ -7,13 +7,11 @@
namespace llarp
{
class Logic;
namespace service
{
struct AsyncKeyExchange : public std::enable_shared_from_this<AsyncKeyExchange>
{
std::shared_ptr<Logic> logic;
EventLoop_ptr loop;
SharedSecret sharedKey;
ServiceInfo m_remote;
const Identity& m_LocalIdentity;
@ -26,7 +24,7 @@ namespace llarp
ConvoTag tag;
AsyncKeyExchange(
std::shared_ptr<Logic> l,
EventLoop_ptr l,
ServiceInfo r,
const Identity& localident,
const PQPubKey& introsetPubKey,

@ -21,7 +21,6 @@
#include <service/hidden_service_address_lookup.hpp>
#include <service/outbound_context.hpp>
#include <service/protocol.hpp>
#include <util/thread/logic.hpp>
#include <util/str.hpp>
#include <util/buffer.hpp>
#include <util/meta/memfn.hpp>
@ -76,21 +75,6 @@ namespace llarp
return m_state->Configure(conf);
}
llarp_ev_loop_ptr
Endpoint::EndpointNetLoop()
{
if (m_state->m_IsolatedNetLoop)
return m_state->m_IsolatedNetLoop;
return Router()->netloop();
}
bool
Endpoint::NetworkIsIsolated() const
{
return m_state->m_IsolatedLogic.get() != nullptr && m_state->m_IsolatedNetLoop != nullptr;
}
bool
Endpoint::HasPendingPathToService(const Address& addr) const
{
@ -652,20 +636,6 @@ namespace llarp
m_OnReady = nullptr;
}
void
Endpoint::IsolatedNetworkMainLoop()
{
m_state->m_IsolatedNetLoop = llarp_make_ev_loop();
m_state->m_IsolatedLogic = std::make_shared<llarp::Logic>();
if (SetupNetworking())
llarp_ev_loop_run_single_process(m_state->m_IsolatedNetLoop, m_state->m_IsolatedLogic);
else
{
m_state->m_IsolatedNetLoop.reset();
m_state->m_IsolatedLogic.reset();
}
}
std::optional<std::vector<RouterContact>>
Endpoint::GetHopsForBuild()
{
@ -748,13 +718,13 @@ namespace llarp
{
if (not msg->foundRCs.empty())
{
for (auto rc : msg->foundRCs)
for (auto& rc : msg->foundRCs)
{
Router()->QueueWork([rc = std::move(rc), logic = Router()->logic(), self = this, msg]() {
Router()->QueueWork([this, rc, msg]() mutable {
bool valid = rc.Verify(llarp::time_now_ms());
LogicCall(logic, [self, valid, rc = std::move(rc), msg]() {
self->Router()->nodedb()->PutIfNewer(rc);
self->HandleVerifyGotRouter(msg, rc.pubkey, valid);
Router()->loop()->call([this, valid, rc = std::move(rc), msg] {
Router()->nodedb()->PutIfNewer(rc);
HandleVerifyGotRouter(msg, rc.pubkey, valid);
});
});
}
@ -949,8 +919,7 @@ namespace llarp
{
if (m_RecvQueue.full() || m_RecvQueue.empty())
{
auto self = this;
LogicCall(m_router->logic(), [self]() { self->FlushRecvData(); });
m_router->loop()->call([this] { FlushRecvData(); });
}
m_RecvQueue.pushBack(std::move(ev));
}
@ -1019,7 +988,7 @@ namespace llarp
}
else
{
RouterLogic()->Call([hook]() { hook({AuthResultCode::eAuthAccepted, "OK"}); });
Router()->loop()->call([h = std::move(hook)] { h({AuthResultCode::eAuthAccepted, "OK"}); });
}
}
@ -1099,7 +1068,7 @@ namespace llarp
RemoveConvoTag(frame.T);
return true;
}
if (not frame.AsyncDecryptAndVerify(EndpointLogic(), p, m_Identity, this))
if (not frame.AsyncDecryptAndVerify(Router()->loop(), p, m_Identity, this))
{
// send reset convo tag message
ProtocolFrame f;
@ -1342,14 +1311,7 @@ namespace llarp
}
};
if (NetworkIsIsolated())
{
LogicCall(EndpointLogic(), epPump);
}
else
{
epPump();
}
epPump();
auto router = Router();
// TODO: locking on this container
for (const auto& item : m_state->m_RemoteSessions)
@ -1537,24 +1499,18 @@ namespace llarp
|| NumInStatus(path::ePathEstablished) < path::min_intro_paths;
}
std::shared_ptr<Logic>
Endpoint::RouterLogic()
{
return Router()->logic();
}
std::shared_ptr<Logic>
Endpoint::EndpointLogic()
{
return m_state->m_IsolatedLogic ? m_state->m_IsolatedLogic : Router()->logic();
}
AbstractRouter*
Endpoint::Router()
{
return m_state->m_Router;
}
const EventLoop_ptr&
Endpoint::Loop()
{
return Router()->loop();
}
void
Endpoint::BlacklistSNode(const RouterID snode)
{

@ -2,7 +2,7 @@
#define LLARP_SERVICE_ENDPOINT_HPP
#include <llarp.h>
#include <dht/messages/gotrouter.hpp>
#include <ev/ev.h>
#include <ev/ev.hpp>
#include <exit/session.hpp>
#include <net/ip_range_map.hpp>
#include <net/net.hpp>
@ -18,7 +18,6 @@
#include <service/lookup.hpp>
#include <hook/ihook.hpp>
#include <util/compare_ptr.hpp>
#include <util/thread/logic.hpp>
#include <service/endpoint_types.hpp>
#include <service/auth.hpp>
@ -136,20 +135,10 @@ namespace llarp
void
ResetInternalState() override;
/// router's logic
/// loop (via router)
/// use when sending any data on a path
std::shared_ptr<Logic>
RouterLogic();
/// endpoint's logic
/// use when writing any data to local network interfaces
std::shared_ptr<Logic>
EndpointLogic();
/// borrow endpoint's net loop for sending data to user on local network
/// interface
llarp_ev_loop_ptr
EndpointNetLoop();
const EventLoop_ptr&
Loop();
AbstractRouter*
Router();
@ -423,22 +412,6 @@ namespace llarp
void
PrefetchServicesByTag(const Tag& tag);
/// spawn a new process that contains a network isolated process
/// return true if we set up isolation and the event loop is up
/// otherwise return false
virtual bool
SpawnIsolatedNetwork()
{
return false;
}
bool
NetworkIsIsolated() const;
/// this runs in the isolated network process
void
IsolatedNetworkMainLoop();
private:
void
HandleVerifyGotRouter(dht::GotRouterMessage_constptr msg, RouterID id, bool valid);

@ -19,25 +19,8 @@
namespace llarp
{
struct EventLoop;
}
using llarp_ev_loop_ptr = std::shared_ptr<llarp::EventLoop>;
namespace llarp
{
// clang-format off
namespace exit { struct BaseSession; }
namespace path { struct Path; using Path_ptr = std::shared_ptr< Path >; }
namespace routing { struct PathTransferMessage; }
// clang-format on
namespace service
{
struct IServiceLookup;
struct OutboundContext;
struct Endpoint;
struct EndpointState
{
hooks::Backend_ptr m_OnUp;
@ -47,8 +30,6 @@ namespace llarp
std::set<RouterID> m_SnodeBlacklist;
AbstractRouter* m_Router;
std::shared_ptr<Logic> m_IsolatedLogic = nullptr;
llarp_ev_loop_ptr m_IsolatedNetLoop = nullptr;
std::string m_Keyfile;
std::string m_Name;
std::string m_NetNS;

@ -3,7 +3,6 @@
#include <path/path.hpp>
#include <util/time.hpp>
#include <router/abstractrouter.hpp>
#include <util/thread/logic.hpp>
#include <utility>
namespace llarp
@ -25,8 +24,8 @@ namespace llarp
auto msg = BuildRequestMessage();
if (!msg)
return false;
endpoint = path->Endpoint();
LogicCall(r->logic(), [=]() { path->SendRoutingMessage(*msg, r); });
r->loop()->call(
[path = std::move(path), msg = std::move(msg), r] { path->SendRoutingMessage(*msg, r); });
return true;
}
} // namespace service

@ -202,7 +202,7 @@ namespace llarp
currentConvoTag.Randomize();
auto frame = std::make_shared<ProtocolFrame>();
auto ex = std::make_shared<AsyncKeyExchange>(
m_Endpoint->RouterLogic(),
m_Endpoint->Loop(),
remoteIdent,
m_Endpoint->GetIdentity(),
currentIntroSet.K,
@ -211,12 +211,14 @@ namespace llarp
currentConvoTag,
t);
ex->hook = std::bind(&OutboundContext::Send, shared_from_this(), std::placeholders::_1, path);
ex->hook = [self = shared_from_this(), path](auto frame) {
self->Send(std::move(frame), path);
};
ex->msg.PutBuffer(payload);
ex->msg.introReply = path->intro;
frame->F = ex->msg.introReply.pathID;
m_Endpoint->Router()->QueueWork(std::bind(&AsyncKeyExchange::Encrypt, ex, frame));
m_Endpoint->Router()->QueueWork([ex, frame] { return AsyncKeyExchange::Encrypt(ex, frame); });
}
std::string
@ -581,7 +583,7 @@ namespace llarp
};
}
const auto& ident = m_Endpoint->GetIdentity();
if (not frame.AsyncDecryptAndVerify(m_Endpoint->EndpointLogic(), p, ident, m_Endpoint, hook))
if (not frame.AsyncDecryptAndVerify(m_Endpoint->Loop(), p, ident, m_Endpoint, hook))
{
// send reset convo tag message
ProtocolFrame f;

@ -4,7 +4,6 @@
#include <util/buffer.hpp>
#include <util/mem.hpp>
#include <util/meta/memfn.hpp>
#include <util/thread/logic.hpp>
#include <service/endpoint.hpp>
#include <router/abstractrouter.hpp>
#include <utility>
@ -271,7 +270,7 @@ namespace llarp
struct AsyncFrameDecrypt
{
path::Path_ptr path;
std::shared_ptr<Logic> logic;
EventLoop_ptr loop;
std::shared_ptr<ProtocolMessage> msg;
const Identity& m_LocalIdentity;
Endpoint* handler;
@ -279,13 +278,13 @@ namespace llarp
const Introduction fromIntro;
AsyncFrameDecrypt(
std::shared_ptr<Logic> l,
EventLoop_ptr l,
const Identity& localIdent,
Endpoint* h,
std::shared_ptr<ProtocolMessage> m,
const ProtocolFrame& f,
const Introduction& recvIntro)
: logic(std::move(l))
: loop(std::move(l))
, msg(std::move(m))
, m_LocalIdentity(localIdent)
, handler(h)
@ -403,7 +402,7 @@ namespace llarp
bool
ProtocolFrame::AsyncDecryptAndVerify(
std::shared_ptr<Logic> logic,
EventLoop_ptr loop,
path::Path_ptr recvPath,
const Identity& localIdent,
Endpoint* handler,
@ -416,9 +415,9 @@ namespace llarp
LogInfo("Got protocol frame with new convo");
// we need to dh
auto dh = std::make_shared<AsyncFrameDecrypt>(
logic, localIdent, handler, msg, *this, recvPath->intro);
loop, localIdent, handler, msg, *this, recvPath->intro);
dh->path = recvPath;
handler->Router()->QueueWork(std::bind(&AsyncFrameDecrypt::Work, dh));
handler->Router()->QueueWork([dh = std::move(dh)] { return AsyncFrameDecrypt::Work(dh); });
return true;
}
@ -436,10 +435,10 @@ namespace llarp
return false;
}
v->frame = *this;
auto callback = [logic, hook](std::shared_ptr<ProtocolMessage> msg) {
auto callback = [loop, hook](std::shared_ptr<ProtocolMessage> msg) {
if (hook)
{
LogicCall(logic, [msg, hook]() { hook(msg); });
loop->call([msg, hook]() { hook(msg); });
}
};
handler->Router()->QueueWork(

@ -20,8 +20,6 @@ struct llarp_threadpool;
namespace llarp
{
class Logic;
namespace path
{
/// forward declare
@ -127,7 +125,7 @@ namespace llarp
bool
AsyncDecryptAndVerify(
std::shared_ptr<Logic> logic,
EventLoop_ptr loop,
path::Path_ptr fromPath,
const Identity& localIdent,
Endpoint* handler,

@ -3,7 +3,6 @@
#include <router/abstractrouter.hpp>
#include <routing/path_transfer_message.hpp>
#include <service/endpoint.hpp>
#include <util/thread/logic.hpp>
#include <utility>
#include <unordered_set>
@ -29,7 +28,7 @@ namespace llarp
{
if (m_SendQueue.empty() or m_SendQueue.full())
{
LogicCall(m_Endpoint->RouterLogic(), [self = this]() { self->FlushUpstream(); });
m_Endpoint->Loop()->call([this] { FlushUpstream(); });
}
m_SendQueue.pushBack(std::make_pair(
std::make_shared<const routing::PathTransferMessage>(*msg, remoteIntro.pathID), path));
@ -97,14 +96,13 @@ namespace llarp
m->sender = m_Endpoint->GetIdentity().pub;
m->tag = f->T;
m->PutBuffer(payload);
auto self = this;
m_Endpoint->Router()->QueueWork([f, m, shared, path, self]() {
if (not f->EncryptAndSign(*m, shared, self->m_Endpoint->GetIdentity()))
m_Endpoint->Router()->QueueWork([f, m, shared, path, this] {
if (not f->EncryptAndSign(*m, shared, m_Endpoint->GetIdentity()))
{
LogError(self->m_Endpoint->Name(), " failed to sign message");
LogError(m_Endpoint->Name(), " failed to sign message");
return;
}
self->Send(f, path);
Send(f, path);
});
}

@ -1,6 +1,6 @@
#pragma once
#include <crypto/crypto_libsodium.hpp>
#include <ev/ev.h>
#include <ev/ev.hpp>
namespace llarp
{
@ -15,7 +15,7 @@ namespace llarp
Simulation();
llarp::CryptoManager m_CryptoManager;
llarp_ev_loop_ptr m_NetLoop;
EventLoop_ptr m_NetLoop;
std::unordered_map<std::string, Node_ptr> m_Nodes;

@ -8,9 +8,9 @@ namespace tooling
{}
std::shared_ptr<llarp::AbstractRouter>
HiveContext::makeRouter(llarp_ev_loop_ptr netloop, std::shared_ptr<llarp::Logic> logic)
HiveContext::makeRouter(const llarp::EventLoop_ptr& loop)
{
return std::make_shared<HiveRouter>(netloop, logic, makeVPNPlatform(), m_hive);
return std::make_shared<HiveRouter>(loop, makeVPNPlatform(), m_hive);
}
HiveRouter*

@ -12,7 +12,7 @@ namespace tooling
HiveContext(RouterHive* hive);
std::shared_ptr<llarp::AbstractRouter>
makeRouter(llarp_ev_loop_ptr netloop, std::shared_ptr<llarp::Logic> logic) override;
makeRouter(const llarp::EventLoop_ptr& loop) override;
/// Get this context's router as a HiveRouter.
///

@ -5,11 +5,8 @@
namespace tooling
{
HiveRouter::HiveRouter(
llarp_ev_loop_ptr netloop,
std::shared_ptr<llarp::Logic> logic,
std::shared_ptr<llarp::vpn::Platform> plat,
RouterHive* hive)
: Router(netloop, logic, plat), m_hive(hive)
llarp::EventLoop_ptr loop, std::shared_ptr<llarp::vpn::Platform> plat, RouterHive* hive)
: Router(loop, plat), m_hive(hive)
{}
bool

@ -11,8 +11,7 @@ namespace tooling
struct HiveRouter : public llarp::Router
{
explicit HiveRouter(
llarp_ev_loop_ptr netloop,
std::shared_ptr<llarp::Logic> logic,
llarp::EventLoop_ptr loop,
std::shared_ptr<llarp::vpn::Platform> vpnPlatform,
RouterHive* hive);

@ -2,7 +2,6 @@
#include "llarp.h"
#include "llarp.hpp"
#include "util/thread/logic.hpp"
#include "util/str.hpp"
#include "router/abstractrouter.hpp"
@ -73,13 +72,13 @@ namespace tooling
RouterHive::StopRouters()
{
llarp::LogInfo("Signalling all routers to stop");
for (auto [routerId, ctx] : relays)
for (auto& [routerId, ctx] : relays)
{
LogicCall(ctx->logic, [ctx]() { ctx->HandleSignal(SIGINT); });
ctx->loop->call([ctx = ctx]() { ctx->HandleSignal(SIGINT); });
}
for (auto [routerId, ctx] : clients)
for (auto& [routerId, ctx] : clients)
{
LogicCall(ctx->logic, [ctx]() { ctx->HandleSignal(SIGINT); });
ctx->loop->call([ctx = ctx]() { ctx->HandleSignal(SIGINT); });
}
llarp::LogInfo("Waiting on routers to be stopped");
@ -149,8 +148,8 @@ namespace tooling
void
RouterHive::VisitRouter(Context_ptr ctx, std::function<void(Context_ptr)> visit)
{
// TODO: this should be called from each router's appropriate Logic thread, e.g.:
// LogicCall(ctx->logic, [visit, ctx]() { visit(ctx); });
// TODO: this should be called from each router's appropriate Loop, e.g.:
// ctx->loop->call([visit, ctx]() { visit(ctx); });
// however, this causes visit calls to be deferred
visit(ctx);
}
@ -172,18 +171,18 @@ namespace tooling
std::vector<size_t>
RouterHive::RelayConnectedRelays()
{
std::lock_guard<std::mutex> guard{routerMutex};
std::lock_guard guard{routerMutex};
std::vector<size_t> results;
results.resize(relays.size());
std::mutex results_lock;
size_t i = 0;
size_t done_count = 0;
for (auto [routerId, ctx] : relays)
for (auto& [routerId, ctx] : relays)
{
LogicCall(ctx->logic, [&, i, ctx]() {
ctx->loop->call([&, i, ctx = ctx]() {
size_t count = ctx->router->NumberOfConnectedRouters();
std::lock_guard<std::mutex> guard{results_lock};
std::lock_guard guard{results_lock};
results[i] = count;
done_count++;
});
@ -194,7 +193,7 @@ namespace tooling
{
size_t read_done_count = 0;
{
std::lock_guard<std::mutex> guard{results_lock};
std::lock_guard guard{results_lock};
read_done_count = done_count;
}
if (read_done_count == relays.size())

@ -124,7 +124,7 @@ namespace llarp
operator^(const AlignedBuffer& other) const
{
AlignedBuffer<sz> ret;
std::transform(begin(), end(), other.begin(), ret.begin(), std::bit_xor<byte_t>());
std::transform(begin(), end(), other.begin(), ret.begin(), std::bit_xor<>());
return ret;
}

@ -94,8 +94,9 @@ llarp_buffer_t::read_uint64(uint64_t& i)
}
size_t
llarp_buffer_t::read_until(char delim, byte_t* result, size_t resultsize)
llarp_buffer_t::read_until(char c_delim, byte_t* result, size_t resultsize)
{
const auto delim = static_cast<byte_t>(c_delim);
size_t read = 0;
// do the bound check first, to avoid over running
@ -115,8 +116,9 @@ llarp_buffer_t::read_until(char delim, byte_t* result, size_t resultsize)
}
bool
operator==(const llarp_buffer_t& buff, const char* str)
operator==(const llarp_buffer_t& buff, const char* c_str)
{
const auto* str = reinterpret_cast<const byte_t*>(c_str);
ManagedBuffer copy{buff};
while (*str && copy.underlying.cur != (copy.underlying.base + copy.underlying.sz))
{
@ -127,3 +129,23 @@ operator==(const llarp_buffer_t& buff, const char* str)
}
return *str == 0;
}
namespace llarp
{
OwnedBuffer
OwnedBuffer::copy_from(const llarp_buffer_t& b)
{
auto buf = std::make_unique<byte_t[]>(b.sz);
std::copy(b.begin(), b.end(), buf.get());
return {std::move(buf), b.sz};
}
OwnedBuffer
OwnedBuffer::copy_used(const llarp_buffer_t& b)
{
auto buf = std::make_unique<byte_t[]>(b.cur - b.base);
std::copy(b.base, b.cur, buf.get());
return {std::move(buf), b.sz};
}
} // namespace llarp

@ -1,6 +1,7 @@
#ifndef LLARP_BUFFER_HPP
#define LLARP_BUFFER_HPP
#include <type_traits>
#include <util/common.hpp>
#include <util/mem.h>
#include <util/types.hpp>
@ -13,11 +14,16 @@
#include <cstring>
#include <utility>
#include <algorithm>
#include <memory>
/**
* buffer.h
*
* generic memory buffer
*
* TODO: replace usage of these with std::span (via a backport until we move to C++20). That's a
* fairly big job, though, as llarp_buffer_t is currently used a bit differently (i.e. maintains
* both start and current position, plus has some value reading/writing methods).
*/
/**
@ -83,34 +89,44 @@ struct llarp_buffer_t
llarp_buffer_t(const ManagedBuffer&) = delete;
llarp_buffer_t(ManagedBuffer&&) = delete;
template <typename T>
llarp_buffer_t(T* buf, size_t _sz) : base(reinterpret_cast<byte_t*>(buf)), cur(base), sz(_sz)
/// Construct referencing some 1-byte, trivially copyable (e.g. char, unsigned char, byte_t)
/// pointer type and a buffer size.
template <
typename T,
typename = std::enable_if_t<sizeof(T) == 1 and std::is_trivially_copyable_v<T>>>
llarp_buffer_t(T* buf, size_t _sz)
: base(reinterpret_cast<byte_t*>(const_cast<std::remove_const_t<T>*>(buf)))
, cur(base)
, sz(_sz)
{}
template <typename T>
llarp_buffer_t(const T* buf, size_t _sz)
: base(reinterpret_cast<byte_t*>(const_cast<T*>(buf))), cur(base), sz(_sz)
/// initialize llarp_buffer_t from containers supporting .data() and .size()
template <
typename T,
typename = std::void_t<decltype(std::declval<T>().data() + std::declval<T>().size())>>
llarp_buffer_t(T&& t) : llarp_buffer_t{t.data(), t.size()}
{}
/** initialize llarp_buffer_t from container */
template <typename T>
llarp_buffer_t(T& t) : base(t.data()), cur(t.data()), sz(t.size())
byte_t*
begin()
{
// use data over the first element to "enforce" the container used has
// contiguous memory. (Note this isn't required by the standard, but a
// reasonable test on most standard library implementations).
return base;
}
byte_t*
begin() const
{
return base;
}
byte_t*
end()
{
return base + sz;
}
byte_t*
end() const
{
return base + sz;
}
template <typename T>
llarp_buffer_t(const T& t) : llarp_buffer_t(t.data(), t.size())
{}
// clang-format off
byte_t * begin() { return base; }
byte_t * begin() const { return base; }
byte_t * end() { return base + sz; }
byte_t * end() const { return base + sz; }
// clang-format on
size_t
size_left() const;
@ -211,4 +227,49 @@ struct ManagedBuffer
}
};
namespace llarp
{
// Wrapper around a std::unique_ptr<byte_t[]> that owns its own memory and is also implicitly
// convertible to a llarp_buffer_t.
struct OwnedBuffer
{
std::unique_ptr<byte_t[]> buf;
size_t sz;
template <typename T, typename = std::enable_if_t<sizeof(T) == 1>>
OwnedBuffer(std::unique_ptr<T[]> buf, size_t sz)
: buf{reinterpret_cast<byte_t*>(buf.release())}, sz{sz}
{}
// Create a new, uninitialized owned buffer of the given size.
explicit OwnedBuffer(size_t sz) : OwnedBuffer{std::make_unique<byte_t[]>(sz), sz}
{}
OwnedBuffer(const OwnedBuffer&) = delete;
OwnedBuffer&
operator=(const OwnedBuffer&) = delete;
OwnedBuffer(OwnedBuffer&&) = default;
OwnedBuffer&
operator=(OwnedBuffer&&) = delete;
// Implicit conversion so that this OwnedBuffer can be passed to anything taking a
// llarp_buffer_t
operator llarp_buffer_t()
{
return {buf.get(), sz};
}
// Creates an owned buffer by copying from a llarp_buffer_t. (Can also be used to copy from
// another OwnedBuffer via the implicit conversion operator above).
static OwnedBuffer
copy_from(const llarp_buffer_t& b);
// Creates an owned buffer by copying the used portion of a llarp_buffer_t (i.e. from base to
// cur), for when a llarp_buffer_t is used in write mode.
static OwnedBuffer
copy_used(const llarp_buffer_t& b);
};
} // namespace llarp
#endif

@ -1,71 +0,0 @@
#include <util/thread/logic.hpp>
#include <util/logging/logger.hpp>
#include <util/mem.h>
#include <future>
namespace llarp
{
void
Logic::stop()
{
llarp::LogDebug("logic thread stop");
}
void
Logic::Call(std::function<void(void)> func)
{
m_Queue(std::move(func));
}
void
Logic::SetQueuer(std::function<void(std::function<void(void)>)> q)
{
m_Queue = std::move(q);
}
uint32_t
Logic::call_later(llarp_time_t timeout, std::function<void(void)> func)
{
auto loop = m_Loop;
if (loop != nullptr)
{
return loop->call_after_delay(timeout, func);
}
return 0;
}
void
Logic::cancel_call(uint32_t id)
{
auto loop = m_Loop;
if (loop != nullptr)
{
loop->cancel_delayed_call(id);
}
}
void
Logic::remove_call(uint32_t id)
{
auto loop = m_Loop;
if (loop != nullptr)
{
loop->cancel_delayed_call(id);
}
}
void
Logic::set_event_loop(EventLoop* loop)
{
m_Loop = loop;
SetQueuer([loop](std::function<void(void)> work) { loop->call_soon(work); });
}
void
Logic::clear_event_loop()
{
m_Loop = nullptr;
}
} // namespace llarp

@ -1,52 +0,0 @@
#ifndef LLARP_LOGIC_HPP
#define LLARP_LOGIC_HPP
#include <ev/ev.hpp>
#include <util/mem.h>
namespace llarp
{
class Logic
{
public:
/// stop all operation and wait for that to die
void
stop();
void
Call(std::function<void(void)> func);
uint32_t
call_later(llarp_time_t later, std::function<void(void)> func);
void
cancel_call(uint32_t id);
void
remove_call(uint32_t id);
void
SetQueuer(std::function<void(std::function<void(void)>)> q);
void
set_event_loop(EventLoop* loop);
void
clear_event_loop();
private:
EventLoop* m_Loop = nullptr;
std::function<void(std::function<void(void)>)> m_Queue;
};
} // namespace llarp
/// this used to be a macro
template <typename Logic_ptr, typename Func_t>
static bool
LogicCall(const Logic_ptr& logic, Func_t func)
{
logic->Call(std::move(func));
return true;
}
#endif

@ -53,12 +53,6 @@ namespace llarp::vpn
return sz == static_cast<ssize_t>(pkt.sz);
}
bool
HasNextPacket() override
{
return false;
}
std::string
IfName() const override
{

@ -122,25 +122,21 @@ namespace llarp::vpn
return m_FD;
}
bool
HasNextPacket() override
{
return false;
}
net::IPPacket
ReadNextPacket() override
{
constexpr int uintsize = sizeof(unsigned int);
net::IPPacket pkt{};
unsigned int pktinfo = 0;
const struct iovec vecs[2] = {{.iov_base = &pktinfo, .iov_len = sizeof(unsigned int)},
const struct iovec vecs[2] = {{.iov_base = &pktinfo, .iov_len = uintsize},
{.iov_base = pkt.buf, .iov_len = sizeof(pkt.buf)}};
int n = readv(m_FD, vecs, 2);
if (n >= (int)(sizeof(unsigned int)))
{
n -= sizeof(unsigned int);
pkt.sz = n;
}
int sz = readv(m_FD, vecs, 2);
if (sz >= uintsize)
pkt.sz = sz - uintsize;
else if (sz >= 0 || errno == EAGAIN || errno == EWOULDBLOCK)
pkt.sz = 0;
else
throw std::error_code{errno, std::system_category()};
return pkt;
}

@ -6,6 +6,7 @@
#include <sys/types.h>
#include <fcntl.h>
#include <vpn/common.hpp>
#include <linux/if.h>
#include <linux/if_tun.h>
namespace llarp::vpn
@ -68,7 +69,7 @@ namespace llarp::vpn
control6.ioctl(SIOCSIFADDR, &ifr6);
}
}
ifr.ifr_flags = flags | IFF_UP | IFF_NO_PI;
ifr.ifr_flags = static_cast<short>(flags | IFF_UP | IFF_NO_PI);
control.ioctl(SIOCSIFFLAGS, &ifr);
}
@ -91,6 +92,10 @@ namespace llarp::vpn
const auto sz = read(m_fd, pkt.buf, sizeof(pkt.buf));
if (sz >= 0)
pkt.sz = std::min(sz, ssize_t{sizeof(pkt.buf)});
else if (errno == EAGAIN || errno == EWOULDBLOCK)
pkt.sz = 0;
else
throw std::error_code{errno, std::system_category()};
return pkt;
}
@ -103,12 +108,6 @@ namespace llarp::vpn
return sz == static_cast<ssize_t>(pkt.sz);
}
bool
HasNextPacket() override
{
return false;
}
std::string
IfName() const override
{

@ -117,7 +117,7 @@ namespace llarp::vpn
return deviceid;
}
class Win32Interface : public NetworkInterface
class Win32Interface final : public NetworkInterface
{
std::atomic<bool> m_Run;
HANDLE m_Device, m_IOCP;
@ -345,12 +345,6 @@ namespace llarp::vpn
return -1;
}
bool
HasNextPacket() override
{
return not m_ReadQueue.empty();
}
std::string
IfName() const override
{
@ -376,8 +370,11 @@ namespace llarp::vpn
}
net::IPPacket
ReadNextPacket()
ReadNextPacket() override
{
if (m_ReadQueue.empty())
return net::IPPacket{};
return m_ReadQueue.popFront();
}

@ -76,7 +76,7 @@ namespace llarp
void
SendPacket(service::Address remote, std::vector<byte_t> pkt, service::ProtocolType proto)
{
LogicCall(m_router->logic(), [remote, pkt, proto, self = shared_from_this()]() {
m_router->loop()->call([remote, pkt, proto, self = shared_from_this()]() {
self->SendToServiceOrQueue(remote, llarp_buffer_t(pkt), proto);
});
}

@ -8,7 +8,7 @@ namespace llarp
void
AbstractRouter_Init(py::module& mod)
{
py::class_<AbstractRouter>(mod, "AbstractRouter")
py::class_<AbstractRouter, std::shared_ptr<AbstractRouter>>(mod, "AbstractRouter")
.def("rc", &AbstractRouter::rc)
.def("Stop", &AbstractRouter::Stop)
.def("peerDb", &AbstractRouter::peerDb);
@ -21,7 +21,7 @@ namespace tooling
void
HiveRouter_Init(py::module& mod)
{
py::class_<HiveRouter, llarp::AbstractRouter>(mod, "HiveRouter")
py::class_<HiveRouter, llarp::AbstractRouter, std::shared_ptr<HiveRouter>>(mod, "HiveRouter")
.def("disableGossiping", &HiveRouter::disableGossiping)
.def("enableGossiping", &HiveRouter::enableGossiping);
}

@ -11,6 +11,7 @@
#include <util/time.hpp>
#include <net/net_if.hpp>
#include "ev/ev.hpp"
#undef LOG_TAG
#define LOG_TAG __FILE__
@ -19,16 +20,14 @@ namespace iwp = llarp::iwp;
namespace util = llarp::util;
/// make an iwp link
template <bool inbound, typename... Args_t>
template <bool inbound, typename... Args>
static llarp::LinkLayer_ptr
make_link(Args_t... args)
make_link(Args&&... args)
{
if (inbound)
return iwp::NewInboundLink(args...);
else
return iwp::NewOutboundLink(args...);
return iwp::NewInboundLink(std::forward<Args>(args)...);
return iwp::NewOutboundLink(std::forward<Args>(args)...);
}
using Logic_ptr = std::shared_ptr<llarp::Logic>;
/// a single iwp link with associated keys and members to make unit tests work
struct IWPLinkContext
@ -38,11 +37,11 @@ struct IWPLinkContext
llarp::LinkLayer_ptr link;
std::shared_ptr<llarp::KeyManager> keyManager;
llarp::LinkMessageParser m_Parser;
llarp_ev_loop_ptr m_Loop;
llarp::EventLoop_ptr m_Loop;
/// is the test done on this context ?
bool gucci = false;
IWPLinkContext(std::string_view addr, llarp_ev_loop_ptr loop)
IWPLinkContext(std::string_view addr, llarp::EventLoop_ptr loop)
: localAddr{std::move(addr)}
, keyManager{std::make_shared<llarp::KeyManager>()}
, m_Parser{nullptr}
@ -104,7 +103,7 @@ struct IWPLinkContext
},
// timeout handler
[&](llarp::ILinkSession*) {
llarp_ev_loop_stop(m_Loop);
m_Loop->stop();
FAIL("session timeout");
},
// session closed handler
@ -118,7 +117,7 @@ struct IWPLinkContext
if (inbound)
{
// only add address info on the recipiant's rc
// only add address info on the recipient's rc
rc.addrs.emplace_back();
REQUIRE(link->GetOurAddressInfo(rc.addrs.back()));
}
@ -134,7 +133,7 @@ using Context_ptr = std::shared_ptr<IWPLinkContext>;
/// call take 2 parameters, test and a timeout
///
/// test is a callable that takes 5 arguments:
/// 0) std::function<Logic_ptr(void)> that starts the iwp links and gives a logic to call with
/// 0) std::function<EventLoop_ptr(void)> that starts the iwp links and gives an event loop to call with
/// 1) std::function<void(void)> that ends the unit test if we are done
/// 2) std::function<void(void)> that ends the unit test right now as a success
/// 3) client iwp link context (shared_ptr)
@ -149,9 +148,7 @@ RunIWPTest(Func_t test, Duration_t timeout = 10s)
// shut up logs
llarp::LogSilencer shutup;
// set up event loop
auto logic = std::make_shared<llarp::Logic>();
auto loop = llarp_make_ev_loop();
loop->set_logic(logic);
auto loop = llarp::EventLoop::create();
llarp::LogContext::Instance().Initialize(
llarp::eLogDebug, llarp::LogType::File, "stdout", "unit test", [loop](auto work) {
@ -169,36 +166,35 @@ RunIWPTest(Func_t test, Duration_t timeout = 10s)
// set up client
auto initiator = std::make_shared<IWPLinkContext>("127.0.0.1:3001", loop);
// set up server
auto recipiant = std::make_shared<IWPLinkContext>("127.0.0.1:3002", loop);
auto recipient = std::make_shared<IWPLinkContext>("127.0.0.1:3002", loop);
// function for ending unit test on success
auto endIfDone = [initiator, recipiant, loop, logic]() {
if (initiator->gucci and recipiant->gucci)
auto endIfDone = [initiator, recipient, loop]() {
if (initiator->gucci and recipient->gucci)
{
LogicCall(logic, [loop]() { llarp_ev_loop_stop(loop); });
loop->stop();
}
};
// function to start test and give logic to unit test
auto start = [initiator, recipiant, logic]() {
REQUIRE(initiator->link->Start(logic));
REQUIRE(recipiant->link->Start(logic));
return logic;
// function to start test and give loop to unit test
auto start = [initiator, recipient, loop]() {
REQUIRE(initiator->link->Start());
REQUIRE(recipient->link->Start());
return loop;
};
// function to end test immediately
auto endTest = [logic, loop]() { LogicCall(logic, [loop]() { llarp_ev_loop_stop(loop); }); };
auto endTest = [loop] { loop->stop(); };
loop->call_after_delay(
std::chrono::duration_cast<llarp_time_t>(timeout), []() { FAIL("test timeout"); });
test(start, endIfDone, endTest, initiator, recipiant);
llarp_ev_loop_run_single_process(loop, logic);
loop->call_later(timeout, [] { FAIL("test timeout"); });
test(start, endIfDone, endTest, initiator, recipient);
loop->run();
llarp::RouterContact::BlockBogons = oldBlockBogons;
}
/// ensure clients can connect to relays
TEST_CASE("IWP handshake", "[iwp]")
{
RunIWPTest([](std::function<Logic_ptr(void)> start,
RunIWPTest([](std::function<llarp::EventLoop_ptr(void)> start,
std::function<void(void)> endIfDone,
[[maybe_unused]] std::function<void(void)> endTestNow,
Context_ptr alice,
@ -209,23 +205,23 @@ TEST_CASE("IWP handshake", "[iwp]")
alice->gucci = true;
endIfDone();
});
// set up recipiant
// set up recipient
bob->InitLink<true>([=](auto remote) {
REQUIRE(remote->GetRemoteRC() == alice->rc);
bob->gucci = true;
endIfDone();
});
// start unit test
auto logic = start();
auto loop = start();
// try establishing a session
LogicCall(logic, [link = alice->link, rc = bob->rc]() { REQUIRE(link->TryEstablishTo(rc)); });
loop->call([link = alice->link, rc = bob->rc]() { REQUIRE(link->TryEstablishTo(rc)); });
});
}
/// ensure relays cannot connect to clients
TEST_CASE("IWP handshake reverse", "[iwp]")
{
RunIWPTest([](std::function<Logic_ptr(void)> start,
RunIWPTest([](std::function<llarp::EventLoop_ptr(void)> start,
[[maybe_unused]] std::function<void(void)> endIfDone,
std::function<void(void)> endTestNow,
Context_ptr alice,
@ -233,9 +229,9 @@ TEST_CASE("IWP handshake reverse", "[iwp]")
alice->InitLink<false>([](auto) {});
bob->InitLink<true>([](auto) {});
// start unit test
auto logic = start();
auto loop = start();
// try establishing a session in the wrong direction
LogicCall(logic, [logic, link = bob->link, rc = alice->rc, endTestNow]() {
loop->call([link = bob->link, rc = alice->rc, endTestNow] {
REQUIRE(not link->TryEstablishTo(rc));
endTestNow();
});
@ -247,7 +243,7 @@ TEST_CASE("IWP send messages", "[iwp]")
{
int aliceNumSent = 0;
int bobNumSent = 0;
RunIWPTest([&aliceNumSent, &bobNumSent](std::function<Logic_ptr(void)> start,
RunIWPTest([&aliceNumSent, &bobNumSent](std::function<llarp::EventLoop_ptr(void)> start,
std::function<void(void)> endIfDone,
std::function<void(void)> endTestNow,
Context_ptr alice,
@ -307,9 +303,9 @@ TEST_CASE("IWP send messages", "[iwp]")
}
});
// start unit test
auto logic = start();
auto loop = start();
// try establishing a session from alice to bob
LogicCall(logic, [logic, link = alice->link, rc = bob->rc, endTestNow]() {
loop->call([link = alice->link, rc = bob->rc, endTestNow]() {
REQUIRE(link->TryEstablishTo(rc));
});
});

@ -5,6 +5,7 @@
#include <catch2/catch.hpp>
#include "peerstats/types.hpp"
#include "router_contact.hpp"
#include "util/logging/logger.hpp"
#include "util/time.hpp"
TEST_CASE("Test PeerDb PeerStats memory storage", "[PeerDb]")
@ -40,6 +41,7 @@ TEST_CASE("Test PeerDb flush before load", "[PeerDb]")
TEST_CASE("Test PeerDb load twice", "[PeerDb]")
{
llarp::LogSilencer shutup;
llarp::PeerDb db;
CHECK_NOTHROW(db.loadDatabase(std::nullopt));
CHECK_THROWS_WITH(db.loadDatabase(std::nullopt), "Reloading database not supported");
@ -47,6 +49,7 @@ TEST_CASE("Test PeerDb load twice", "[PeerDb]")
TEST_CASE("Test PeerDb nukes stats on load", "[PeerDb]")
{
llarp::LogSilencer shutup;
const llarp::RouterID id = llarp::test::makeBuf<llarp::RouterID>(0x01);
llarp::PeerDb db;
@ -64,6 +67,7 @@ TEST_CASE("Test PeerDb nukes stats on load", "[PeerDb]")
TEST_CASE("Test PeerDb file-backed database reloads properly", "[PeerDb]")
{
llarp::LogSilencer shutup;
const std::string filename = "/tmp/peerdb_test_tmp2.db.sqlite";
const llarp::RouterID id = llarp::test::makeBuf<llarp::RouterID>(0x02);
@ -93,6 +97,7 @@ TEST_CASE("Test PeerDb file-backed database reloads properly", "[PeerDb]")
TEST_CASE("Test PeerDb modifyPeerStats", "[PeerDb]")
{
llarp::LogSilencer shutup;
const llarp::RouterID id = llarp::test::makeBuf<llarp::RouterID>(0xF2);
int numTimesCalled = 0;
@ -117,6 +122,7 @@ TEST_CASE("Test PeerDb modifyPeerStats", "[PeerDb]")
TEST_CASE("Test PeerDb handleGossipedRC", "[PeerDb]")
{
llarp::LogSilencer shutup;
const llarp::RouterID id = llarp::test::makeBuf<llarp::RouterID>(0xCA);
auto rcLifetime = llarp::RouterContact::Lifetime;
@ -156,6 +162,7 @@ TEST_CASE("Test PeerDb handleGossipedRC", "[PeerDb]")
TEST_CASE("Test PeerDb handleGossipedRC expiry calcs", "[PeerDb]")
{
llarp::LogSilencer shutup;
const llarp::RouterID id = llarp::test::makeBuf<llarp::RouterID>(0xF9);
// see comments in peer_db.cpp above PeerDb::handleGossipedRC() for some context around these

@ -203,6 +203,7 @@ TEST_CASE("Test signing with derived key", "[crypto]")
TEST_CASE("Test sign and encrypt introset", "[crypto]")
{
llarp::LogSilencer shutup;
CryptoManager manager(new sodium::CryptoLibSodium());
service::Identity ident;

Loading…
Cancel
Save