Merge remote-tracking branch 'github/master' into iwp-multi-ack

pull/830/head
Jeff Becker 5 years ago
commit 3c0245f8b3
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -28,6 +28,7 @@ option(WITH_SHARED "build shared library")
option(WITH_COVERAGE "generate coverage data")
option(USE_SHELLHOOKS "enable shell hooks on compile time (dangerous)" OFF)
option(WARNINGS_AS_ERRORS "treat all warnings as errors. turn off for development, on for release" OFF)
option(TRACY_ROOT "include tracy profiler source")
include(cmake/target_link_libraries_system.cmake)
include(cmake/add_import_library.cmake)
@ -209,6 +210,11 @@ add_definitions("-DGIT_REV=\"${GIT_VERSION_REAL}\"")
set(EXE lokinet)
set(EXE_SRC daemon/main.cpp)
if(TRACY_ROOT)
include_directories(${TRACY_ROOT})
add_definitions(-DTRACY_ENABLE)
list(APPEND EXE_SRC ${TRACY_ROOT}/TracyClient.cpp)
endif()
# HeapAlloc(2) on Windows was significantly revamped in 2009
# but the old algorithm isn't too bad either
@ -237,6 +243,9 @@ else()
endif()
set(LIBS ${MALLOC_LIB} ${FS_LIB} ${LIBUV_LIBRARY})
if(TRACY_ROOT)
list(APPEND LIBS -ldl)
endif()
add_subdirectory(crypto)
add_subdirectory(libutp)
@ -254,6 +263,7 @@ else()
target_link_libraries(${ABYSS_EXE} PUBLIC ${ABYSS_LIB} ${STATIC_LIB} ws2_32)
endif(NOT WIN32)
# Why does abyss not inherit the existing include folders?
target_include_directories(${ABYSS_LIB} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/${ABYSS}/include" llarp vendor/nlohmann/include include crypto/include)
target_include_directories(${ABYSS_EXE} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/${ABYSS}/include" llarp vendor/nlohmann/include include crypto/include)
@ -276,7 +286,11 @@ if(SHADOW)
else()
if(NOT WIN32)
add_executable(${EXE} ${EXE_SRC})
add_executable(lokinet-rcutil daemon/rcutil.cpp)
if(TRACY_ROOT)
add_executable(lokinet-rcutil daemon/rcutil.cpp ${TRACY_ROOT}/TracyClient.cpp)
else()
add_executable(lokinet-rcutil daemon/rcutil.cpp)
endif()
elseif(NOT MSVC_VERSION)
add_executable(${EXE} ${EXE_SRC} llarp/win32/version.rc)
add_executable(lokinet-rcutil daemon/rcutil.cpp llarp/win32/version.rc)

@ -80,6 +80,8 @@ COVERAGE ?= OFF
COVERAGE_OUTDIR ?= "$(TMPDIR)/lokinet-coverage"
# enable ASAN
ASAN ?= OFF
# tracy profiler
TRACY_ROOT ?=
# cmake generator type
CMAKE_GEN ?= Unix Makefiles
@ -104,7 +106,7 @@ ANALYZE_CONFIG_CMD = $(shell gecho -n "cd '$(BUILD_ROOT)' && " ; gecho -n "$(SCA
COVERAGE_CONFIG_CMD = $(shell gecho -n "cd '$(BUILD_ROOT)' && " ; gecho -n "cmake -G'$(CMAKE_GEN)' -DCMAKE_CROSSCOMPILING=$(CROSS) -DSTATIC_LINK_RUNTIME=$(STATIC_LINK) -DUSE_NETNS=$(NETNS) -DUSE_AVX2=$(AVX2) -DNON_PC_TARGET=$(NON_PC_TARGET) -DWITH_SHARED=$(SHARED_LIB) -DWITH_COVERAGE=yes -DCMAKE_EXPORT_COMPILE_COMMANDS=ON '$(REPO)'")
else
CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "cmake -G'$(CMAKE_GEN)' -DCMAKE_CROSSCOMPILING=$(CROSS) -DSTATIC_LINK_RUNTIME=$(STATIC_LINK) -DUSE_SHELLHOOKS=$(SHELL_HOOKS) -DUSE_NETNS=$(NETNS) -DUSE_AVX2=$(AVX2) -DNON_PC_TARGET=$(NON_PC_TARGET) -DWITH_SHARED=$(SHARED_LIB) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON '$(REPO)'")
CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "cmake -G'$(CMAKE_GEN)' -DCMAKE_CROSSCOMPILING=$(CROSS) -DSTATIC_LINK_RUNTIME=$(STATIC_LINK) -DUSE_SHELLHOOKS=$(SHELL_HOOKS) -DUSE_NETNS=$(NETNS) -DUSE_AVX2=$(AVX2) -DNON_PC_TARGET=$(NON_PC_TARGET) -DWITH_SHARED=$(SHARED_LIB) -DTRACY_ROOT=$(TRACY_ROOT) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON '$(REPO)'")
CONFIG_CMD_WINDOWS = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "cmake -G'$(CMAKE_GEN)' -DCMAKE_CROSSCOMPILING=ON -DSTATIC_LINK_RUNTIME=$(STATIC_LINK) -DUSE_SHELLHOOKS=$(SHELL_HOOKS) -DUSE_NETNS=$(NETNS) -DUSE_AVX2=$(AVX2) -DNON_PC_TARGET=$(NON_PC_TARGET) -DWITH_SHARED=$(SHARED_LIB) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON '$(REPO)'")
ANALYZE_CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "$(SCAN_BUILD) cmake -G'$(CMAKE_GEN)' -DCMAKE_CROSSCOMPILING=$(CROSS) -DSTATIC_LINK_RUNTIME=$(STATIC_LINK) -DUSE_NETNS=$(NETNS) -DUSE_AVX2=$(AVX2) -DNON_PC_TARGET=$(NON_PC_TARGET) -DWITH_SHARED=$(SHARED_LIB) -DASAN=$(ASAN) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON '$(REPO)'")

@ -27,7 +27,9 @@ void
handle_signal(int sig)
{
if(ctx)
{
llarp_main_signal(ctx, sig);
}
}
#ifdef _WIN32

@ -433,7 +433,8 @@ extern "C"
void
llarp_main_signal(struct llarp_main *ptr, int sig)
{
ptr->ctx->HandleSignal(sig);
ptr->ctx->logic->queue_func(
std::bind(&llarp::Context::HandleSignal, ptr->ctx.get(), sig));
}
int

@ -5,6 +5,7 @@
#include <path/path_context.hpp>
#include <router/abstractrouter.hpp>
#include <util/str.hpp>
#include <util/bits.hpp>
#include <cassert>
@ -547,6 +548,11 @@ namespace llarp
}
if(k == "ifaddr")
{
if(!m_OurRange.FromString(v))
{
LogError(Name(), " has invalid address range: ", v);
return false;
}
auto pos = v.find("/");
if(pos == std::string::npos)
{
@ -558,26 +564,9 @@ namespace llarp
// string, or just a plain char array?
strncpy(m_Tun.ifaddr, host_str.c_str(), sizeof(m_Tun.ifaddr) - 1);
m_Tun.netmask = std::atoi(nmask_str.c_str());
huint32_t ip;
if(ip.FromString(host_str))
{
m_IfAddr = net::IPPacket::ExpandV4(ip);
m_OurRange.netmask_bits = netmask_ipv6_bits(m_Tun.netmask + 96);
}
else if(m_IfAddr.FromString(host_str))
{
m_UseV6 = true;
m_OurRange.netmask_bits = netmask_ipv6_bits(m_Tun.netmask);
}
else
{
LogError(Name(), " invalid ifaddr: ", v);
return false;
}
m_OurRange.addr = m_IfAddr;
m_NextAddr = m_IfAddr;
m_HigestAddr = m_IfAddr | (~m_OurRange.netmask_bits);
m_IfAddr = m_OurRange.addr;
m_NextAddr = m_IfAddr;
m_HigestAddr = m_OurRange.HighestAddr();
LogInfo(Name(), " set ifaddr range to ", m_Tun.ifaddr, "/",
m_Tun.netmask, " lo=", m_IfAddr, " hi=", m_HigestAddr);
}

@ -18,6 +18,8 @@
#include <util/str.hpp>
#include <absl/strings/ascii.h>
namespace llarp
{
namespace handlers
@ -143,18 +145,39 @@ namespace llarp
// the keyfile
if(k == "exit-node")
{
IPRange exitRange;
llarp::RouterID exitRouter;
if(!(exitRouter.FromString(v)
|| HexDecode(v.c_str(), exitRouter.begin(), exitRouter.size())))
std::string routerStr;
const auto pos = v.find(",");
if(pos != std::string::npos)
{
auto range_str = v.substr(1 + pos);
if(!exitRange.FromString(range_str))
{
LogError("bad exit range: '", range_str, "'");
return false;
}
routerStr = v.substr(0, pos);
}
else
{
llarp::LogError(Name(), " bad exit router key: ", v);
routerStr = v;
}
absl::StripAsciiWhitespace(&routerStr);
if(!(exitRouter.FromString(routerStr)
|| HexDecode(routerStr.c_str(), exitRouter.begin(),
exitRouter.size())))
{
llarp::LogError(Name(), " bad exit router key: ", routerStr);
return false;
}
m_Exit = std::make_shared< llarp::exit::ExitSession >(
auto exit = std::make_shared< llarp::exit::ExitSession >(
exitRouter,
util::memFn(&TunEndpoint::QueueInboundPacketForExit, this),
m_router, numPaths, numHops, ShouldBundleRC());
llarp::LogInfo(Name(), " using exit at ", exitRouter);
m_ExitMap.Insert(exitRange, exit);
llarp::LogInfo(Name(), " using exit at ", exitRouter, " for ",
exitRange);
}
if(k == "local-dns")
{
@ -288,13 +311,11 @@ namespace llarp
{
auto self = shared_from_this();
FlushSend();
if(m_Exit)
{
RouterLogic()->queue_func([=] {
self->m_Exit->FlushUpstream();
self->Router()->PumpLL();
});
}
RouterLogic()->queue_func([=] {
self->m_ExitMap.ForEachValue(
[](const auto &exit) { exit->FlushUpstream(); });
self->Router()->PumpLL();
});
RouterLogic()->queue_func([=]() {
self->Pump(self->Now());
self->Router()->PumpLL();
@ -487,8 +508,8 @@ namespace llarp
TunEndpoint::ResetInternalState()
{
service::Endpoint::ResetInternalState();
if(m_Exit)
m_Exit->ResetInternalState();
m_ExitMap.ForEachValue(
[](const auto &exit) { exit->ResetInternalState(); });
}
bool
@ -550,11 +571,11 @@ namespace llarp
llarp::LogWarn("Couldn't start endpoint");
return false;
}
if(m_Exit)
{
for(const auto &snode : SnodeBlacklist())
m_Exit->BlacklistSnode(snode);
}
const auto blacklist = SnodeBlacklist();
m_ExitMap.ForEachValue([blacklist](const auto &exit) {
for(const auto &snode : blacklist)
exit->BlacklistSnode(snode);
});
return SetupNetworking();
}
@ -639,7 +660,7 @@ namespace llarp
m_NextIP = m_OurIP;
m_OurRange.addr = m_OurIP;
m_MaxIP = m_OurIP | (~m_OurRange.netmask_bits);
m_MaxIP = m_OurRange.HighestAddr();
llarp::LogInfo(Name(), " set ", tunif.ifname, " to have address ",
m_OurIP);
llarp::LogInfo(Name(), " allocated up to ", m_MaxIP, " on range ",
@ -690,19 +711,17 @@ namespace llarp
{
// call tun code in endpoint logic in case of network isolation
// EndpointLogic()->queue_job({this, handleTickTun});
if(m_Exit)
{
EnsureRouterIsKnown(m_Exit->Endpoint());
m_Exit->Tick(now);
}
m_ExitMap.ForEachValue([&](const auto &exit) {
EnsureRouterIsKnown(exit->Endpoint());
exit->Tick(now);
});
Endpoint::Tick(now);
}
bool
TunEndpoint::Stop()
{
if(m_Exit)
m_Exit->Stop();
m_ExitMap.ForEachValue([](const auto &exit) { exit->Stop(); });
return llarp::service::Endpoint::Stop();
}
@ -721,22 +740,26 @@ namespace llarp
auto itr = m_IPToAddr.find(dst);
if(itr == m_IPToAddr.end())
{
if(m_Exit && pkt.IsV4() && !llarp::IsIPv4Bogon(pkt.dstv4()))
const auto exits = m_ExitMap.FindAll(dst);
if(exits.empty())
{
pkt.UpdateIPv4Address({0}, xhtonl(pkt.dstv4()));
m_Exit->QueueUpstreamTraffic(std::move(pkt),
llarp::routing::ExitPadSize);
llarp::LogWarn(Name(), " has no exit mapped for ", dst);
return;
}
else if(m_Exit && pkt.IsV6())
for(const auto &exit : exits)
{
pkt.UpdateIPv6Address({0}, pkt.dstv6());
m_Exit->QueueUpstreamTraffic(std::move(pkt),
if(pkt.IsV4() && !llarp::IsIPv4Bogon(pkt.dstv4()))
{
pkt.UpdateIPv4Address({0}, xhtonl(pkt.dstv4()));
exit->QueueUpstreamTraffic(std::move(pkt),
llarp::routing::ExitPadSize);
}
else
{
llarp::LogWarn(Name(), " has no endpoint for ", dst);
llarp::DumpBuffer(pkt.ConstBuffer());
}
else if(pkt.IsV6())
{
pkt.UpdateIPv6Address({0}, pkt.dstv6());
exit->QueueUpstreamTraffic(std::move(pkt),
llarp::routing::ExitPadSize);
}
}
return;
}
@ -913,10 +936,8 @@ namespace llarp
// flush user to network
self->FlushSend();
// flush exit traffic queues if it's there
if(self->m_Exit)
{
self->m_Exit->FlushDownstream();
}
self->m_ExitMap.ForEachValue(
[](const auto &exit) { exit->FlushDownstream(); });
// flush network to user
self->m_NetworkToUserPktQueue.Process([tun](net::IPPacket &pkt) {
if(!llarp_ev_tun_async_write(tun, pkt.Buffer()))

@ -24,7 +24,7 @@ namespace llarp
{
std::set< RouterID > sessions;
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
auto itr = m_AuthedLinks.begin();
while(itr != m_AuthedLinks.end())
{
@ -34,7 +34,7 @@ namespace llarp
}
ILinkLayer::Pump();
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
for(const auto& pk : sessions)
{
if(m_AuthedLinks.count(pk) == 0)
@ -79,7 +79,7 @@ namespace llarp
auto itr = m_AuthedAddrs.find(from);
if(itr == m_AuthedAddrs.end())
{
util::Lock lock(&m_PendingMutex);
// ACQUIRE_LOCK(Lock_t lock , m_PendingMutex);
if(m_Pending.count(from) == 0)
{
if(not permitInbound)

@ -691,18 +691,16 @@ namespace llarp
auto itr = m_RXMsgs.find(rxid);
if(itr == m_RXMsgs.end())
{
if(m_ReplayFilter.find(rxid) != m_ReplayFilter.end())
if(m_ReplayFilter.find(rxid) == m_ReplayFilter.end())
{
// don't nack if we already got it
return;
LogDebug("no rxid=", rxid, " for ", m_RemoteAddr);
std::vector< byte_t > nack = {
LLARP_PROTO_VERSION, Command::eNACK, 0, 0, 0, 0, 0, 0, 0, 0};
htobe64buf(nack.data() + 2, rxid);
AddRandomPadding(nack);
const llarp_buffer_t nackbuf(nack);
EncryptAndSend(nackbuf);
}
LogDebug("no rxid=", rxid, " for ", m_RemoteAddr);
std::vector< byte_t > nack = {
LLARP_PROTO_VERSION, Command::eNACK, 0, 0, 0, 0, 0, 0, 0, 0};
htobe64buf(nack.data() + 2, rxid);
AddRandomPadding(nack);
const llarp_buffer_t nackbuf(nack);
EncryptAndSend(nackbuf);
return;
}

@ -17,13 +17,13 @@ namespace llarp
public std::enable_shared_from_this< Session >
{
/// Time how long we try delivery for
static constexpr llarp_time_t DeliveryTimeout = 5000;
/// How long to keep a replay window for
static constexpr llarp_time_t ReplayWindow = (DeliveryTimeout * 3) / 2;
static constexpr llarp_time_t DeliveryTimeout = 2000;
/// Time how long we wait to recieve a message
static constexpr llarp_time_t RecievalTimeout = (DeliveryTimeout * 8) / 5;
/// How long to keep a replay window for
static constexpr llarp_time_t ReplayWindow = (RecievalTimeout * 3) / 2;
/// How often to acks RX messages
static constexpr llarp_time_t ACKResendInterval = 500;
static constexpr llarp_time_t ACKResendInterval = 250;
/// How often to retransmit TX fragments
static constexpr llarp_time_t TXFlushInterval =
(ACKResendInterval * 3) / 2;

@ -29,7 +29,7 @@ namespace llarp
bool
ILinkLayer::HasSessionTo(const RouterID& id)
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
return m_AuthedLinks.find(id) != m_AuthedLinks.end();
}
@ -39,7 +39,7 @@ namespace llarp
{
std::vector< std::shared_ptr< ILinkSession > > sessions;
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
if(m_AuthedLinks.size() == 0)
return;
const size_t sz = randint() % m_AuthedLinks.size();
@ -75,7 +75,7 @@ namespace llarp
{
std::shared_ptr< ILinkSession > session;
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
auto itr = m_AuthedLinks.find(pk);
if(itr == m_AuthedLinks.end())
return false;
@ -89,7 +89,7 @@ namespace llarp
{
std::vector< std::shared_ptr< ILinkSession > > sessions;
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
auto itr = m_AuthedLinks.begin();
while(itr != m_AuthedLinks.end())
{
@ -125,7 +125,7 @@ namespace llarp
{
auto _now = Now();
{
Lock lock(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
auto itr = m_AuthedLinks.begin();
while(itr != m_AuthedLinks.end())
{
@ -144,7 +144,7 @@ namespace llarp
}
}
{
Lock lock(&m_PendingMutex);
ACQUIRE_LOCK(Lock_t l, m_PendingMutex);
auto itr = m_Pending.begin();
while(itr != m_Pending.end())
@ -172,8 +172,8 @@ namespace llarp
bool
ILinkLayer::MapAddr(const RouterID& pk, ILinkSession* s)
{
Lock l_authed(&m_AuthedLinksMutex);
Lock l_pending(&m_PendingMutex);
ACQUIRE_LOCK(Lock_t l_authed, m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l_pending, m_PendingMutex);
llarp::Addr addr = s->GetRemoteEndpoint();
auto itr = m_Pending.find(addr);
if(itr != m_Pending.end())
@ -213,7 +213,7 @@ namespace llarp
std::vector< util::StatusObject > pending, established;
{
Lock l(&m_PendingMutex);
ACQUIRE_LOCK(Lock_t l, m_PendingMutex);
std::transform(m_Pending.cbegin(), m_Pending.cend(),
std::back_inserter(pending),
[](const auto& item) -> util::StatusObject {
@ -221,7 +221,7 @@ namespace llarp
});
}
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
std::transform(m_AuthedLinks.cbegin(), m_AuthedLinks.cend(),
std::back_inserter(established),
[](const auto& item) -> util::StatusObject {
@ -241,7 +241,7 @@ namespace llarp
ILinkLayer::TryEstablishTo(RouterContact rc)
{
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
if(m_AuthedLinks.count(rc.pubkey) >= MaxSessionsPerKey)
return false;
}
@ -250,7 +250,7 @@ namespace llarp
return false;
const llarp::Addr addr(to);
{
Lock l(&m_PendingMutex);
ACQUIRE_LOCK(Lock_t l, m_PendingMutex);
if(m_Pending.count(addr) >= MaxSessionsPerKey)
return false;
}
@ -277,7 +277,7 @@ namespace llarp
ILinkLayer::Tick(llarp_time_t now)
{
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
auto itr = m_AuthedLinks.begin();
while(itr != m_AuthedLinks.end())
{
@ -287,7 +287,7 @@ namespace llarp
}
{
Lock l(&m_PendingMutex);
ACQUIRE_LOCK(Lock_t l, m_PendingMutex);
auto itr = m_Pending.begin();
while(itr != m_Pending.end())
{
@ -303,7 +303,7 @@ namespace llarp
if(m_Logic && tick_id)
m_Logic->remove_call(tick_id);
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
auto itr = m_AuthedLinks.begin();
while(itr != m_AuthedLinks.end())
{
@ -312,7 +312,7 @@ namespace llarp
}
}
{
Lock l(&m_PendingMutex);
ACQUIRE_LOCK(Lock_t l, m_PendingMutex);
auto itr = m_Pending.begin();
while(itr != m_Pending.end())
{
@ -325,7 +325,7 @@ namespace llarp
void
ILinkLayer::CloseSessionTo(const RouterID& remote)
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
RouterID r = remote;
llarp::LogInfo("Closing all to ", r);
auto range = m_AuthedLinks.equal_range(r);
@ -340,7 +340,7 @@ namespace llarp
void
ILinkLayer::KeepAliveSessionTo(const RouterID& remote)
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
auto range = m_AuthedLinks.equal_range(remote);
auto itr = range.first;
while(itr != range.second)
@ -357,7 +357,7 @@ namespace llarp
{
ILinkSession* s = nullptr;
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
auto range = m_AuthedLinks.equal_range(remote);
auto itr = range.first;
// pick lowest backlog session
@ -433,7 +433,7 @@ namespace llarp
ILinkLayer::PutSession(const std::shared_ptr< ILinkSession >& s)
{
static constexpr size_t MaxSessionsPerEndpoint = 5;
Lock lock(&m_PendingMutex);
ACQUIRE_LOCK(Lock_t lock, m_PendingMutex);
llarp::Addr addr = s->GetRemoteEndpoint();
if(m_Pending.count(addr) >= MaxSessionsPerEndpoint)
return false;

@ -238,9 +238,13 @@ namespace llarp
const SecretKey& m_RouterEncSecret;
protected:
using Lock = util::Lock;
using Mutex = util::Mutex;
#ifdef TRACY_ENABLE
using Lock_t = std::lock_guard< LockableBase(std::mutex) >;
using Mutex_t = std::mutex;
#else
using Lock_t = util::NullLock;
using Mutex_t = util::NullMutex;
#endif
bool
PutSession(const std::shared_ptr< ILinkSession >& s);
@ -257,10 +261,11 @@ namespace llarp
using Pending =
std::unordered_multimap< llarp::Addr, std::shared_ptr< ILinkSession >,
llarp::Addr::Hash >;
mutable Mutex m_AuthedLinksMutex ACQUIRED_BEFORE(m_PendingMutex);
mutable DECLARE_LOCK(Mutex_t, m_AuthedLinksMutex,
ACQUIRED_BEFORE(m_PendingMutex));
AuthedLinks m_AuthedLinks GUARDED_BY(m_AuthedLinksMutex);
mutable Mutex m_PendingMutex ACQUIRED_AFTER(m_AuthedLinksMutex);
mutable DECLARE_LOCK(Mutex_t, m_PendingMutex,
ACQUIRED_AFTER(m_AuthedLinksMutex));
Pending m_Pending GUARDED_BY(m_PendingMutex);
};

@ -238,6 +238,15 @@ namespace llarp
static void
SendLRCM(std::shared_ptr< LRCMFrameDecrypt > self)
{
if(self->context->HasTransitHop(self->hop->info))
{
llarp::LogError("duplicate transit hop", self->hop->info);
OnForwardLRCMResult(self->context->Router(), self->hop->info.rxID,
self->hop->info.downstream, self->hop->pathKey,
SendStatus::Congestion);
self->hop = nullptr;
return;
}
if(!self->context->Router()->ConnectionToRouterAllowed(
self->hop->info.upstream))
{
@ -287,15 +296,21 @@ namespace llarp
static void
SendPathConfirm(std::shared_ptr< LRCMFrameDecrypt > self)
{
// persist session to downstream until path expiration
self->context->Router()->PersistSessionUntil(
self->hop->info.downstream, self->hop->ExpireTime() + 10000);
// put hop
self->context->PutTransitHop(self->hop);
// send path confirmation
// TODO: other status flags?
uint64_t status = LR_StatusRecord::SUCCESS;
if(self->context->HasTransitHop(self->hop->info))
{
status = LR_StatusRecord::FAIL_DUPLICATE_HOP;
}
else
{
// persist session to downstream until path expiration
self->context->Router()->PersistSessionUntil(
self->hop->info.downstream, self->hop->ExpireTime() + 10000);
// put hop
self->context->PutTransitHop(self->hop);
}
if(!LR_StatusMessage::CreateAndSend(
self->context->Router(), self->hop->info.rxID,
@ -332,12 +347,7 @@ namespace llarp
info.txID = self->record.txid;
info.rxID = self->record.rxid;
info.upstream = self->record.nextHop;
if(self->context->HasTransitHop(info))
{
llarp::LogError("duplicate transit hop ", info);
self->decrypter = nullptr;
return;
}
// generate path key as we are in a worker thread
auto crypto = CryptoManager::instance();
if(!crypto->dh_server(self->hop->pathKey, self->record.commkey,
@ -387,7 +397,7 @@ namespace llarp
{
// we are the farthest hop
llarp::LogDebug("We are the farthest hop for ", info);
// send a LRAM down the path
// send a LRSM down the path
self->context->logic()->queue_func([=]() {
SendPathConfirm(self);
self->decrypter = nullptr;

@ -23,7 +23,7 @@ namespace llarp
struct LR_StatusRecord
{
static constexpr uint64_t SUCCESS = 1;
static constexpr uint64_t SUCCESS = 1 << 0;
static constexpr uint64_t FAIL_TIMEOUT = 1 << 1;
static constexpr uint64_t FAIL_CONGESTION = 1 << 2;
static constexpr uint64_t FAIL_DEST_UNKNOWN = 1 << 3;
@ -31,6 +31,7 @@ namespace llarp
static constexpr uint64_t FAIL_MALFORMED_RECORD = 1 << 5;
static constexpr uint64_t FAIL_DEST_INVALID = 1 << 6;
static constexpr uint64_t FAIL_CANNOT_CONNECT = 1 << 7;
static constexpr uint64_t FAIL_DUPLICATE_HOP = 1 << 8;
uint64_t status = 0;
uint64_t version = 0;

@ -0,0 +1,89 @@
#ifndef LLARP_NET_IP_RANGE_MAP_HPP
#define LLARP_NET_IP_RANGE_MAP_HPP
#include <net/ip.hpp>
namespace llarp
{
namespace net
{
/// a container that maps an ip range to a value that allows you to lookup
/// key by range hit
/// TODO: do some kind of magic shit to ensure near constant time for
/// lookups
template < typename Value_t >
struct IPRangeMap
{
using Range_t = IPRange;
using IP_t = Range_t::Addr_t;
using Entry_t = std::pair< Range_t, Value_t >;
using Container_t = std::forward_list< Entry_t >;
/// get a set of all values
std::set< Value_t >
Values() const
{
std::set< Value_t > all;
for(const auto &entry : m_Entries)
all.insert(entry.second);
return all;
}
void
ForEachValue(std::function< void(const Value_t &) > functor) const
{
for(const auto &entry : m_Entries)
functor(entry.second);
}
/// convert all values into type T
template < typename T, typename Transformer >
std::set< T >
TransformValues(Transformer transform) const
{
std::set< T > transformed;
for(const auto &entry : m_Entries)
{
T val = transform(entry.second);
transformed.insert(std::move(val));
}
return transformed;
}
/// return a set of all values who's range contains this IP
std::set< Value_t >
FindAll(const IP_t &addr) const
{
std::set< Value_t > found;
for(const auto &entry : m_Entries)
{
if(entry.first.Contains(addr))
found.insert(entry.second);
}
return found;
}
struct CompareEntry
{
bool
operator()(const Entry_t &left, const Entry_t &right) const
{
return left.first < right.first;
}
};
void
Insert(const Range_t &addr, const Value_t &val)
{
m_Entries.emplace_front(addr, val);
m_Entries.sort(CompareEntry{});
}
private:
Container_t m_Entries;
};
} // namespace net
} // namespace llarp
#endif

@ -987,6 +987,52 @@ namespace llarp
return Contains(net::IPPacket::ExpandV4(ip));
}
bool
IPRange::FromString(std::string str)
{
const auto colinpos = str.find(":");
const auto slashpos = str.find("/");
std::string bitsstr;
if(slashpos != std::string::npos)
{
bitsstr = str.substr(slashpos + 1);
str = str.substr(0, slashpos);
}
if(colinpos == std::string::npos)
{
huint32_t ip;
if(!ip.FromString(str))
return false;
addr = net::IPPacket::ExpandV4(ip);
if(!bitsstr.empty())
{
auto bits = atoi(bitsstr.c_str());
if(bits < 0 || bits > 32)
return false;
netmask_bits = netmask_ipv6_bits(96 + bits);
}
else
netmask_bits = netmask_ipv6_bits(128);
}
else
{
if(!addr.FromString(str))
return false;
if(!bitsstr.empty())
{
auto bits = atoi(bitsstr.c_str());
if(bits < 0 || bits > 128)
return false;
netmask_bits = netmask_ipv6_bits(bits);
}
else
{
netmask_bits = netmask_ipv6_bits(128);
}
}
return true;
}
std::string
IPRange::ToString() const
{

@ -59,12 +59,13 @@ namespace llarp
{
struct IPRange
{
huint128_t addr;
huint128_t netmask_bits;
using Addr_t = huint128_t;
huint128_t addr = {0};
huint128_t netmask_bits = {0};
/// return true if ip is contained in this ip range
bool
Contains(const huint128_t& ip) const
Contains(const Addr_t& ip) const
{
return (addr & netmask_bits) == (ip & netmask_bits);
}
@ -78,8 +79,28 @@ namespace llarp
return out << a.ToString();
}
/// get the highest address on this range
huint128_t
HighestAddr() const
{
return (addr & netmask_bits)
+ (huint128_t{1} << (128 - bits::count_bits_128(netmask_bits.h)))
- huint128_t{1};
}
bool
operator<(const IPRange& other) const
{
return (this->addr & this->netmask_bits)
< (other.addr & other.netmask_bits)
|| this->netmask_bits < other.netmask_bits;
}
std::string
ToString() const;
bool
FromString(std::string str);
};
huint128_t

@ -40,6 +40,18 @@ namespace llarp
return huint_t{UInt_t{h | x.h}};
}
constexpr huint_t
operator-(huint_t x) const
{
return huint_t{UInt_t{h - x.h}};
}
constexpr huint_t
operator+(huint_t x) const
{
return huint_t{UInt_t{h + x.h}};
}
constexpr huint_t
operator^(huint_t x) const
{

@ -83,12 +83,12 @@ namespace llarp
return true;
}
template < typename Map_t, typename Key_t, typename CheckValue_t,
typename GetFunc_t >
template < typename Lock_t, typename Map_t, typename Key_t,
typename CheckValue_t, typename GetFunc_t >
HopHandler_ptr
MapGet(Map_t& map, const Key_t& k, CheckValue_t check, GetFunc_t get)
{
util::Lock lock(&map.first);
Lock_t lock(&map.first);
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second; ++i)
{
@ -98,11 +98,12 @@ namespace llarp
return nullptr;
}
template < typename Map_t, typename Key_t, typename CheckValue_t >
template < typename Lock_t, typename Map_t, typename Key_t,
typename CheckValue_t >
bool
MapHas(Map_t& map, const Key_t& k, CheckValue_t check)
{
util::Lock lock(&map.first);
Lock_t lock(&map.first);
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second; ++i)
{
@ -112,28 +113,30 @@ namespace llarp
return false;
}
template < typename Map_t, typename Key_t, typename Value_t >
template < typename Lock_t, typename Map_t, typename Key_t,
typename Value_t >
void
MapPut(Map_t& map, const Key_t& k, const Value_t& v)
{
util::Lock lock(&map.first);
Lock_t lock(&map.first);
map.second.emplace(k, v);
}
template < typename Map_t, typename Visit_t >
template < typename Lock_t, typename Map_t, typename Visit_t >
void
MapIter(Map_t& map, Visit_t v)
{
util::Lock lock(map.first);
Lock_t lock(map.first);
for(const auto& item : map.second)
v(item);
}
template < typename Map_t, typename Key_t, typename Check_t >
template < typename Lock_t, typename Map_t, typename Key_t,
typename Check_t >
void
MapDel(Map_t& map, const Key_t& k, Check_t check)
{
util::Lock lock(map.first);
Lock_t lock(map.first);
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second;)
{
@ -148,23 +151,24 @@ namespace llarp
PathContext::AddOwnPath(PathSet_ptr set, Path_ptr path)
{
set->AddPath(path);
MapPut(m_OurPaths, path->TXID(), set);
MapPut(m_OurPaths, path->RXID(), set);
MapPut< SyncOwnedPathsMap_t::Lock_t >(m_OurPaths, path->TXID(), set);
MapPut< SyncOwnedPathsMap_t::Lock_t >(m_OurPaths, path->RXID(), set);
}
bool
PathContext::HasTransitHop(const TransitHopInfo& info)
{
return MapHas(m_TransitPaths, info.txID,
[info](const std::shared_ptr< TransitHop >& hop) -> bool {
return info == hop->info;
});
return MapHas< SyncTransitMap_t::Lock_t >(
m_TransitPaths, info.txID,
[info](const std::shared_ptr< TransitHop >& hop) -> bool {
return info == hop->info;
});
}
HopHandler_ptr
PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id)
{
auto own = MapGet(
auto own = MapGet< SyncOwnedPathsMap_t::Lock_t >(
m_OurPaths, id,
[](const PathSet_ptr) -> bool {
// TODO: is this right?
@ -176,7 +180,7 @@ namespace llarp
if(own)
return own;
return MapGet(
return MapGet< SyncTransitMap_t::Lock_t >(
m_TransitPaths, id,
[remote](const std::shared_ptr< TransitHop >& hop) -> bool {
return hop->info.upstream == remote;
@ -190,7 +194,7 @@ namespace llarp
PathContext::TransitHopPreviousIsRouter(const PathID_t& path,
const RouterID& otherRouter)
{
util::Lock lock(&m_TransitPaths.first);
SyncTransitMap_t::Lock_t lock(&m_TransitPaths.first);
auto itr = m_TransitPaths.second.find(path);
if(itr == m_TransitPaths.second.end())
return false;
@ -200,7 +204,7 @@ namespace llarp
HopHandler_ptr
PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id)
{
return MapGet(
return MapGet< SyncTransitMap_t::Lock_t >(
m_TransitPaths, id,
[remote](const std::shared_ptr< TransitHop >& hop) -> bool {
return hop->info.downstream == remote;
@ -214,7 +218,7 @@ namespace llarp
PathContext::GetLocalPathSet(const PathID_t& id)
{
auto& map = m_OurPaths;
util::Lock lock(&map.first);
SyncOwnedPathsMap_t::Lock_t lock(&map.first);
auto itr = map.second.find(id);
if(itr != map.second.end())
{
@ -241,7 +245,7 @@ namespace llarp
RouterID us(OurRouterID());
auto& map = m_TransitPaths;
{
util::Lock lock(&map.first);
SyncTransitMap_t::Lock_t lock(&map.first);
auto range = map.second.equal_range(id);
for(auto i = range.first; i != range.second; ++i)
{
@ -262,15 +266,15 @@ namespace llarp
void
PathContext::PutTransitHop(std::shared_ptr< TransitHop > hop)
{
MapPut(m_TransitPaths, hop->info.txID, hop);
MapPut(m_TransitPaths, hop->info.rxID, hop);
MapPut< SyncTransitMap_t::Lock_t >(m_TransitPaths, hop->info.txID, hop);
MapPut< SyncTransitMap_t::Lock_t >(m_TransitPaths, hop->info.rxID, hop);
}
void
PathContext::ExpirePaths(llarp_time_t now)
{
{
util::Lock lock(&m_TransitPaths.first);
SyncTransitMap_t::Lock_t lock(&m_TransitPaths.first);
auto& map = m_TransitPaths.second;
auto itr = map.begin();
while(itr != map.end())
@ -284,7 +288,7 @@ namespace llarp
}
}
{
util::Lock lock(&m_OurPaths.first);
SyncOwnedPathsMap_t::Lock_t lock(&m_OurPaths.first);
auto& map = m_OurPaths.second;
for(auto& item : map)
{
@ -306,7 +310,7 @@ namespace llarp
const RouterID us(OurRouterID());
auto& map = m_TransitPaths;
{
util::Lock lock(&map.first);
SyncTransitMap_t::Lock_t lock(&map.first);
auto range = map.second.equal_range(id);
for(auto i = range.first; i != range.second; ++i)
{
@ -320,7 +324,7 @@ namespace llarp
void
PathContext::RemovePathSet(PathSet_ptr set)
{
util::Lock lock(&m_OurPaths.first);
SyncOwnedPathsMap_t::Lock_t lock(&m_OurPaths.first);
auto& map = m_OurPaths.second;
auto itr = map.begin();
while(itr != map.end())

@ -105,14 +105,17 @@ namespace llarp
struct SyncTransitMap_t
{
util::Mutex first; // protects second
using Mutex_t = util::NullMutex;
using Lock_t = util::NullLock;
Mutex_t first; // protects second
TransitHopsMap_t second GUARDED_BY(first);
void
ForEach(std::function< void(const TransitHop_ptr&) > visit)
LOCKS_EXCLUDED(first)
{
util::Lock lock(&first);
Lock_t lock(&first);
for(const auto& item : second)
visit(item.second);
}
@ -123,13 +126,15 @@ namespace llarp
struct SyncOwnedPathsMap_t
{
util::Mutex first; // protects second
using Mutex_t = util::Mutex;
using Lock_t = util::Lock;
Mutex_t first; // protects second
OwnedPathsMap_t second GUARDED_BY(first);
void
ForEach(std::function< void(const PathSet_ptr&) > visit)
{
util::Lock lock(&first);
Lock_t lock(&first);
for(const auto& item : second)
visit(item.second);
}

@ -214,7 +214,8 @@ namespace llarp
if(s && s->IsEstablished() && isOutbound && !got)
{
const RouterContact rc = s->GetRemoteRC();
if(got || exclude.count(rc.pubkey))
if(got || exclude.count(rc.pubkey)
|| m_router->IsBootstrapNode(rc.pubkey))
return;
cur = rc;
got = true;

@ -56,6 +56,9 @@ namespace llarp
virtual void
ExploreNetwork() = 0;
virtual size_t
NumberOfStrictConnectRouters() const = 0;
};
} // namespace llarp

@ -149,6 +149,12 @@ namespace llarp
return true;
}
size_t
RCLookupHandler::NumberOfStrictConnectRouters() const
{
return _strictConnectPubkeys.size();
}
bool
RCLookupHandler::GetRandomWhitelistRouter(RouterID &router) const
{

@ -64,6 +64,9 @@ namespace llarp
void
ExploreNetwork() override;
size_t
NumberOfStrictConnectRouters() const override;
void
Init(llarp_dht_context *dht, llarp_nodedb *nodedb,
std::shared_ptr< llarp::thread::ThreadPool > threadpool,

@ -701,9 +701,16 @@ namespace llarp
_rcLookupHandler.ExploreNetwork();
}
if(connected < _outboundSessionMaker.minConnectedRouters)
size_t connectToNum = _outboundSessionMaker.minConnectedRouters;
const auto strictConnect = _rcLookupHandler.NumberOfStrictConnectRouters();
if(strictConnect > 0 && connectToNum > strictConnect)
{
size_t dlt = _outboundSessionMaker.minConnectedRouters - connected;
connectToNum = strictConnect;
}
if(connected < connectToNum)
{
size_t dlt = connectToNum - connected;
LogInfo("connecting to ", dlt, " random routers to keep alive");
_outboundSessionMaker.ConnectToRandomRouters(dlt, now);
}

@ -628,9 +628,24 @@ namespace llarp
std::set< RouterID > exclude = prev;
for(const auto& snode : SnodeBlacklist())
exclude.insert(snode);
if(hop == 0)
{
const auto exits = GetExitRouters();
// exclude exit node as first hop in any paths
exclude.insert(exits.begin(), exits.end());
}
return path::Builder::SelectHop(db, exclude, cur, hop, roles);
}
std::set< RouterID >
Endpoint::GetExitRouters() const
{
return m_ExitMap.TransformValues< RouterID >(
[](const exit::BaseSession_ptr& ptr) -> RouterID {
return ptr->Endpoint();
});
}
bool
Endpoint::ShouldBundleRC() const
{

@ -4,6 +4,7 @@
#include <dht/messages/gotrouter.hpp>
#include <ev/ev.h>
#include <exit/session.hpp>
#include <net/ip_range_map.hpp>
#include <net/net.hpp>
#include <path/path.hpp>
#include <path/pathbuilder.hpp>
@ -145,6 +146,10 @@ namespace llarp
std::string
Name() const override;
/// get a set of all the routers we use as exit node
std::set< RouterID >
GetExitRouters() const;
bool
ShouldPublishDescriptors(llarp_time_t now) const override;
@ -417,7 +422,7 @@ namespace llarp
protected:
IDataHandler* m_DataHandler = nullptr;
Identity m_Identity;
std::shared_ptr< exit::BaseSession > m_Exit;
net::IPRangeMap< exit::BaseSession_ptr > m_ExitMap;
hooks::Backend_ptr m_OnUp;
hooks::Backend_ptr m_OnDown;
hooks::Backend_ptr m_OnReady;

@ -301,6 +301,12 @@ namespace llarp
exclude.insert(m_NextIntro.router);
for(const auto& snode : m_Endpoint->SnodeBlacklist())
exclude.insert(snode);
if(hop == 0)
{
// exclude any exits as our first hop
const auto exits = m_Endpoint->GetExitRouters();
exclude.insert(exits.begin(), exits.end());
}
if(hop == numHops - 1)
{
m_Endpoint->EnsureRouterIsKnown(m_NextIntro.router);

@ -23,6 +23,13 @@ namespace llarp
return std::bitset< std::numeric_limits< Int_t >::digits >(i).count();
}
constexpr std::size_t
count_bits_128(const absl::uint128& i)
{
return count_bits(absl::Uint128High64(i))
+ count_bits(absl::Uint128Low64(i));
}
template < typename InputIt >
constexpr std::size_t
__count_array_bits(InputIt begin, InputIt end)

@ -3,8 +3,12 @@
#include <absl/synchronization/barrier.h>
#include <absl/synchronization/mutex.h>
#include <absl/types/optional.h>
#include <absl/time/time.h>
#include <iostream>
#include <thread>
#if defined(WIN32) && !defined(__GNUC__)
#include <process.h>
using pid_t = int;
@ -13,6 +17,22 @@ using pid_t = int;
#include <unistd.h>
#endif
#ifdef TRACY_ENABLE
#include "Tracy.hpp"
#define DECLARE_LOCK(type, var, ...) TracyLockable(type, var)
#define ACQUIRE_LOCK(lock, mtx) lock(mtx)
#else
#define DECLARE_LOCK(type, var, ...) type var __VA_ARGS__
#define ACQUIRE_LOCK(lock, mtx) lock(&mtx)
#endif
#ifdef YOLO_DISABLE_LOCKING
#warning \
"!!! locking disabled !!! This may cause hella crashes, please mind the gap."
#undef ACQUIRE_LOCK
#define ACQUIRE_LOCK(lock, mtx)
#endif
namespace llarp
{
namespace util
@ -20,6 +40,29 @@ namespace llarp
/// a mutex that does nothing
struct LOCKABLE NullMutex
{
#ifdef LOKINET_DEBUG
mutable absl::optional< std::thread::id > m_id;
void
lock() const
{
if(!m_id)
{
m_id.emplace(std::this_thread::get_id());
}
else if(m_id.value() != std::this_thread::get_id())
{
std::cerr << "NullMutex " << this << " was locked by "
<< std::this_thread::get_id()
<< " and was previously locked by " << m_id.value() << "\n";
std::abort();
}
}
#else
void
lock() const
{
}
#endif
};
/// a lock that does nothing
@ -28,6 +71,7 @@ namespace llarp
NullLock(ABSL_ATTRIBUTE_UNUSED const NullMutex* mtx)
EXCLUSIVE_LOCK_FUNCTION(mtx)
{
mtx->lock();
}
~NullLock() UNLOCK_FUNCTION()
@ -36,8 +80,9 @@ namespace llarp
}
};
using Mutex = absl::Mutex;
using Lock = absl::MutexLock;
using Mutex = absl::Mutex;
using Lock = absl::MutexLock;
using ReleasableLock = absl::ReleasableMutexLock;
using Condition = absl::CondVar;

@ -206,7 +206,7 @@ namespace llarp
utp_issue_deferred_acks(_utp_ctx);
std::set< RouterID > sessions;
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
auto itr = m_AuthedLinks.begin();
while(itr != m_AuthedLinks.end())
{
@ -216,7 +216,7 @@ namespace llarp
}
ILinkLayer::Pump();
{
Lock l(&m_AuthedLinksMutex);
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
for(const auto& pk : sessions)
{
if(m_AuthedLinks.count(pk) == 0)

Loading…
Cancel
Save