Merge branch 'dev' into private-keys-backup-support

pull/921/head
Stephen Shelton 5 years ago committed by GitHub
commit 93b8832026
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -188,6 +188,10 @@ set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)
if(NOT IOS AND NOT ANDROID AND NOT WIN32)
find_package(CURL REQUIRED)
endif()
include(cmake/static_link_runtime.cmake)
include(cmake/static_link.cmake)

@ -16,7 +16,7 @@ BUILD_TYPE ?= Debug
PYTHON ?= python
PYTHON3 ?= python3
FORMAT ?= clang-format
FORMAT ?= clang-format-8
SETCAP ?= which setcap && setcap cap_net_admin,cap_net_bind_service=+eip

@ -1,6 +1,7 @@
#include <config/config.hpp> // for ensure_config
#include <constants/version.hpp>
#include <llarp.h>
#include <util/lokinet_init.h>
#include <util/fs.hpp>
#include <util/logging/logger.hpp>
#include <util/logging/ostream_logger.hpp>
@ -83,6 +84,11 @@ run_main_context(std::string conffname, llarp_main_runtime_opts opts)
int
main(int argc, char *argv[])
{
auto result = Lokinet_INIT();
if(result)
{
return result;
}
llarp_main_runtime_opts opts;
const char *singleThreadVar = getenv("LLARP_SHADOW");
if(singleThreadVar && std::string(singleThreadVar) == "1")

@ -39,7 +39,7 @@ struct DemoCall : public abyss::http::IRPCClientHandler
bool HandleResponse(abyss::http::RPC_Response) override
{
llarp::LogInfo("response get");
m_Logic->queue_func([=]() { m_Callback(); });
LogicCall(m_Logic, m_Callback);
return true;
}

@ -26,6 +26,7 @@ set(LIB_UTIL_SRC
util/logging/ostream_logger.cpp
util/logging/syslog_logger.cpp
util/logging/win32_logger.cpp
util/lokinet_init.c
util/mem.cpp
util/meta/memfn_traits.cpp
util/meta/memfn.cpp
@ -83,7 +84,6 @@ set(LIB_PLATFORM_SRC
net/ip.cpp
net/net.cpp
net/net_addr.cpp
net/net_inaddr.cpp
net/net_int.cpp
# for android shim
${ANDROID_PLATFORM_SRC}
@ -254,7 +254,8 @@ if(TESTNET)
endif()
add_library(${STATIC_LIB} STATIC ${LIB_SRC})
target_link_libraries(${STATIC_LIB} PUBLIC cxxopts ${ABYSS_LIB} ${PLATFORM_LIB} ${UTIL_LIB} ${CRYPTOGRAPHY_LIB} ${FS_LIB})
target_include_directories(${STATIC_LIB} PUBLIC ${CURL_INCLUDE_DIRS})
target_link_libraries(${STATIC_LIB} PUBLIC cxxopts ${ABYSS_LIB} ${PLATFORM_LIB} ${UTIL_LIB} ${CRYPTOGRAPHY_LIB} ${FS_LIB} ${CURL_LIBRARIES})
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_include_directories(${PLATFORM_LIB} SYSTEM PUBLIC /usr/local/include)

@ -11,6 +11,7 @@
#include <util/mem.hpp>
#include <util/meta/memfn.hpp>
#include <util/str.hpp>
#include <util/lokinet_init.h>
#include <absl/strings/strip.h>
@ -51,6 +52,15 @@ namespace llarp
void
RouterConfig::fromSection(string_view key, string_view val)
{
if(key == "job-queue-size")
{
auto sval = svtoi(val);
if(sval >= 1024)
{
m_JobQueueSize = sval;
LogInfo("Set job queue size to ", m_JobQueueSize);
}
}
if(key == "default-protocol")
{
m_DefaultLinkProto = tostr(val);
@ -459,6 +469,8 @@ namespace llarp
bool
Config::parse(const ConfigParser &parser)
{
if(Lokinet_INIT())
return false;
router = find_section< RouterConfig >(parser, "router");
network = find_section< NetworkConfig >(parser, "network");
connect = find_section< ConnectConfig >(parser, "connect");
@ -500,6 +512,8 @@ extern "C" bool
llarp_ensure_config(const char *fname, const char *basedir, bool overwrite,
bool asRouter)
{
if(Lokinet_INIT())
return false;
std::error_code ec;
if(fs::exists(fname, ec) && !overwrite)
{

@ -121,10 +121,13 @@ namespace llarp
int m_workerThreads = 1;
int m_numNetThreads = 1;
size_t m_JobQueueSize = size_t{1024 * 8};
std::string m_DefaultLinkProto = "iwp";
public:
// clang-format off
size_t jobQueueSize() const { return fromEnv(m_JobQueueSize, "JOB_QUEUE_SIZE"); }
size_t minConnectedRouters() const { return fromEnv(m_minConnectedRouters, "MIN_CONNECTED_ROUTERS"); }
size_t maxConnectedRouters() const { return fromEnv(m_maxConnectedRouters, "MAX_CONNECTED_ROUTERS"); }
std::string encryptionKeyfile() const { return fromEnv(m_encryptionKeyfile, "ENCRYPTION_KEYFILE"); }

@ -39,7 +39,7 @@ namespace llarp
bool
Context::CallSafe(std::function< void(void) > f)
{
return logic && logic->queue_func(std::move(f));
return logic && LogicCall(logic, f);
}
void
@ -51,7 +51,6 @@ namespace llarp
bool
Context::Configure()
{
logic = std::make_shared< Logic >();
// llarp::LogInfo("loading config at ", configfile);
if(configfile.size())
{
@ -73,6 +72,10 @@ namespace llarp
threads = 1;
worker = std::make_shared< llarp::thread::ThreadPool >(threads, 1024,
"llarp-worker");
auto jobQueueSize = config->router.jobQueueSize();
if(jobQueueSize < 1024)
jobQueueSize = 1024;
logic = std::make_shared< Logic >(jobQueueSize);
nodedb_dir = config->netdb.nodedbDir();
@ -482,7 +485,7 @@ extern "C"
void
llarp_main_signal(struct llarp_main *ptr, int sig)
{
ptr->ctx->logic->queue_func(
LogicCall(ptr->ctx->logic,
std::bind(&llarp::Context::HandleSignal, ptr->ctx.get(), sig));
}

@ -87,6 +87,9 @@ namespace llarp
/// post quantum encrypt (buffer, sharedkey_dst, pub)
virtual bool
pqe_encrypt(PQCipherBlock &, SharedSecret &, const PQPubKey &) = 0;
virtual bool
check_identity_privkey(const SecretKey &) = 0;
};
inline Crypto::~Crypto() = default;

@ -214,6 +214,19 @@ namespace llarp
(void)sk_pk;
}
bool
CryptoLibSodium::check_identity_privkey(const llarp::SecretKey &keys)
{
AlignedBuffer< crypto_sign_SEEDBYTES > seed;
llarp::PubKey pk;
llarp::SecretKey sk;
if(crypto_sign_ed25519_sk_to_seed(seed.data(), keys.data()) == -1)
return false;
if(crypto_sign_seed_keypair(pk.data(), sk.data(), seed.data()) == -1)
return false;
return keys.toPublic() == pk && sk == keys;
}
void
CryptoLibSodium::encryption_keygen(llarp::SecretKey &keys)
{

@ -79,6 +79,9 @@ namespace llarp
/// post quantum encrypt (buffer, sharedkey_dst, pub)
bool
pqe_encrypt(PQCipherBlock &, SharedSecret &, const PQPubKey &) override;
bool
check_identity_privkey(const SecretKey &) override;
};
} // namespace sodium

@ -180,6 +180,12 @@ namespace llarp
std::copy_n(secret.begin(), SharedSecret::SIZE, block.begin());
return true;
}
bool
check_identity_privkey(const SecretKey &) override
{
return true;
}
};
} // namespace llarp

@ -58,20 +58,17 @@ namespace llarp
using User_ptr = std::shared_ptr< User >;
using DecryptHandler = std::function< void(llarp_buffer_t*, User_ptr) >;
static void
Decrypt(void* user)
void
Decrypt(User_ptr user)
{
auto* ctx = static_cast< AsyncFrameDecrypter< User >* >(user);
if(ctx->target.DecryptInPlace(ctx->seckey))
if(target.DecryptInPlace(seckey))
{
auto buf = ctx->target.Buffer();
auto buf = target.Buffer();
buf->cur = buf->base + EncryptedFrameOverheadSize;
ctx->result(buf, ctx->user);
result(buf, user);
}
else
ctx->result(nullptr, ctx->user);
ctx->user = nullptr;
result(nullptr, user);
}
AsyncFrameDecrypter(const SecretKey& secretkey, DecryptHandler h)
@ -80,7 +77,6 @@ namespace llarp
}
DecryptHandler result;
User_ptr user;
const SecretKey& seckey;
EncryptedFrame target;
@ -89,8 +85,8 @@ namespace llarp
const EncryptedFrame& frame, User_ptr u)
{
target = frame;
user = u;
worker->addJob(std::bind(&Decrypt, this));
worker->addJob(
[self = this, user = std::move(u)]() { self->Decrypt(user); });
}
};
} // namespace llarp

@ -199,14 +199,14 @@ namespace llarp
PutRCNodeAsync(const RCNode& val) override
{
auto func = std::bind(&Bucket< RCNode >::PutNode, Nodes(), val);
router->logic()->queue_func(func);
LogicCall(router->logic(), func);
}
void
DelRCNodeAsync(const Key_t& val) override
{
auto func = std::bind(&Bucket< RCNode >::DelNode, Nodes(), val);
router->logic()->queue_func(func);
LogicCall(router->logic(), func);
}
const Key_t&

@ -39,10 +39,10 @@ namespace llarp
m_Resolvers = resolvers;
const llarp::Addr any("0.0.0.0", 0);
auto self = shared_from_this();
m_ClientLogic->queue_func([=]() {
LogicCall(m_ClientLogic, [=]() {
llarp_ev_add_udp(self->m_ClientLoop.get(), &self->m_Client, any);
});
m_ServerLogic->queue_func([=]() {
LogicCall(m_ServerLogic, [=]() {
llarp_ev_add_udp(self->m_ServerLoop.get(), &self->m_Server, addr);
});
return true;
@ -65,8 +65,9 @@ namespace llarp
auto self = static_cast< Proxy* >(u->user)->shared_from_this();
// yes we use the server loop here because if the server loop is not the
// client loop we'll crash again
self->m_ServerLogic->queue_func(
[self, addr, msgbuf]() { self->HandlePktServer(addr, msgbuf); });
LogicCall(self->m_ServerLogic, [self, addr, msgbuf]() {
self->HandlePktServer(addr, msgbuf);
});
}
void
@ -76,8 +77,9 @@ namespace llarp
const llarp::Addr addr(*from);
Buffer_t msgbuf = CopyBuffer(buf.underlying);
auto self = static_cast< Proxy* >(u->user)->shared_from_this();
self->m_ServerLogic->queue_func(
[self, addr, msgbuf]() { self->HandlePktClient(addr, msgbuf); });
LogicCall(self->m_ServerLogic, [self, addr, msgbuf]() {
self->HandlePktClient(addr, msgbuf);
});
}
llarp::Addr
@ -100,7 +102,7 @@ namespace llarp
Proxy::SendServerMessageTo(llarp::Addr to, Message msg)
{
auto self = shared_from_this();
m_ServerLogic->queue_func([to, msg, self]() {
LogicCall(m_ServerLogic, [to, msg, self]() {
std::array< byte_t, 1500 > tmp = {{0}};
llarp_buffer_t buf(tmp);
if(msg.Encode(&buf))
@ -118,7 +120,7 @@ namespace llarp
Proxy::SendClientMessageTo(llarp::Addr to, Message msg)
{
auto self = shared_from_this();
m_ClientLogic->queue_func([to, msg, self]() {
LogicCall(m_ClientLogic, [to, msg, self]() {
std::array< byte_t, 1500 > tmp = {{0}};
llarp_buffer_t buf(tmp);
if(msg.Encode(&buf))
@ -151,7 +153,7 @@ namespace llarp
const Addr requester = itr->second;
auto self = shared_from_this();
m_ServerLogic->queue_func([=]() {
LogicCall(m_ServerLogic, [=]() {
// forward reply to requester via server
const llarp_buffer_t tmpbuf(buf);
llarp_ev_udp_sendto(&self->m_Server, requester, tmpbuf);
@ -222,7 +224,7 @@ namespace llarp
// new forwarded query
tx.from = PickRandomResolver();
m_Forwarded[tx] = from;
m_ClientLogic->queue_func([=] {
LogicCall(m_ClientLogic, [=] {
// do query
const llarp_buffer_t tmpbuf(buf);
llarp_ev_udp_sendto(&self->m_Client, tx.from, tmpbuf);
@ -232,7 +234,7 @@ namespace llarp
{
// send the query again because it's probably FEC from the requester
const auto resolver = itr->first.from;
m_ClientLogic->queue_func([=] {
LogicCall(m_ClientLogic, [=] {
// send it
const llarp_buffer_t tmpbuf(buf);
llarp_ev_udp_sendto(&self->m_Client, resolver, tmpbuf);

@ -40,7 +40,7 @@ typedef SSIZE_T ssize_t;
* event handler (cross platform high performance event system for IO)
*/
#define EV_TICK_INTERVAL 100
#define EV_TICK_INTERVAL 10
// forward declare
struct llarp_threadpool;

@ -7,13 +7,8 @@
namespace libuv
{
/// call a function in logic thread via a handle
template < typename Handle, typename Func >
void
Call(Handle* h, Func&& f)
{
static_cast< Loop* >(h->loop->data)->Call(f);
}
#define LoopCall(h, ...) \
LogicCall(static_cast< Loop* >((h)->loop->data)->m_Logic, __VA_ARGS__)
struct glue
{
@ -110,7 +105,7 @@ namespace libuv
OnOutboundConnect(uv_connect_t* c, int status)
{
conn_glue* self = static_cast< conn_glue* >(c->data);
Call(self->Stream(),
LoopCall(self->Stream(),
std::bind(&conn_glue::HandleConnectResult, self, status));
c->data = nullptr;
}
@ -145,7 +140,7 @@ namespace libuv
if(nread >= 0)
{
auto* conn = static_cast< conn_glue* >(stream->data);
Call(stream, std::bind(&conn_glue::Read, conn, buf->base, nread));
LoopCall(stream, std::bind(&conn_glue::Read, conn, buf->base, nread));
return;
}
else if(nread < 0)
@ -262,7 +257,7 @@ namespace libuv
OnClosed(uv_handle_t* h)
{
conn_glue* conn = static_cast< conn_glue* >(h->data);
Call(h, std::bind(&conn_glue::HandleClosed, conn));
LoopCall(h, std::bind(&conn_glue::HandleClosed, conn));
}
static void
@ -329,7 +324,7 @@ namespace libuv
if(status == 0)
{
conn_glue* conn = static_cast< conn_glue* >(stream->data);
Call(stream, std::bind(&conn_glue::Accept, conn));
LoopCall(stream, std::bind(&conn_glue::Accept, conn));
}
else
{
@ -347,7 +342,7 @@ namespace libuv
OnTick(uv_check_t* t)
{
conn_glue* conn = static_cast< conn_glue* >(t->data);
Call(t, std::bind(&conn_glue::Tick, conn));
LoopCall(t, std::bind(&conn_glue::Tick, conn));
}
void
@ -416,7 +411,7 @@ namespace libuv
OnTick(uv_check_t* t)
{
ticker_glue* ticker = static_cast< ticker_glue* >(t->data);
Call(&ticker->m_Ticker, [ticker]() { ticker->func(); });
LoopCall(t, ticker->func);
}
bool
@ -429,8 +424,11 @@ namespace libuv
Close() override
{
uv_check_stop(&m_Ticker);
m_Ticker.data = nullptr;
delete this;
uv_close((uv_handle_t*)&m_Ticker, [](auto h) {
ticker_glue* self = (ticker_glue*)h->data;
h->data = nullptr;
delete self;
});
}
uv_check_t m_Ticker;
@ -586,7 +584,7 @@ namespace libuv
void
Tick()
{
Call(&m_Handle, std::bind(&llarp_ev_pkt_pipe::tick, m_Pipe));
LoopCall(&m_Handle, std::bind(&llarp_ev_pkt_pipe::tick, m_Pipe));
}
static void
@ -626,7 +624,7 @@ namespace libuv
OnTick(uv_check_t* h)
{
pipe_glue* pipe = static_cast< pipe_glue* >(h->data);
Call(h, std::bind(&pipe_glue::Tick, pipe));
LoopCall(h, std::bind(&pipe_glue::Tick, pipe));
}
bool
@ -668,7 +666,7 @@ namespace libuv
OnTick(uv_check_t* timer)
{
tun_glue* tun = static_cast< tun_glue* >(timer->data);
Call(timer, std::bind(&tun_glue::Tick, tun));
tun->Tick();
}
static void
@ -687,7 +685,7 @@ namespace libuv
if(sz > 0)
{
llarp::LogDebug("tun read ", sz);
llarp_buffer_t pkt(m_Buffer, sz);
const llarp_buffer_t pkt(m_Buffer, sz);
if(m_Tun && m_Tun->recvpkt)
m_Tun->recvpkt(m_Tun, pkt);
}
@ -716,9 +714,14 @@ namespace libuv
void
Close() override
{
if(m_Tun->impl == nullptr)
return;
m_Tun->impl = nullptr;
uv_check_stop(&m_Ticker);
uv_close((uv_handle_t*)&m_Handle, &OnClosed);
uv_close((uv_handle_t*)&m_Ticker, [](uv_handle_t* h) {
tun_glue* glue = static_cast< tun_glue* >(h->data);
uv_close((uv_handle_t*)&glue->m_Handle, &OnClosed);
});
}
bool
@ -760,6 +763,9 @@ namespace libuv
" has invalid fd: ", m_Device->tun_fd);
return false;
}
tuntap_set_nonblocking(m_Device, 1);
if(uv_poll_init(loop, &m_Handle, m_Device->tun_fd) == -1)
{
llarp::LogError("failed to start polling on ", m_Tun->ifname);
@ -788,6 +794,12 @@ namespace libuv
{
if(uv_loop_init(&m_Impl) == -1)
return false;
#ifdef LOKINET_DEBUG
last_time = 0;
loop_run_count = 0;
#endif
m_Impl.data = this;
uv_loop_configure(&m_Impl, UV_LOOP_BLOCK_SIGNAL, SIGPIPE);
m_TickTimer.data = this;
@ -829,18 +841,35 @@ namespace libuv
int
Loop::tick(int ms)
{
if(m_Run)
{
#ifdef LOKINET_DEBUG
if((uv_now(&m_Impl) - last_time) > 1000)
{
llarp::LogInfo("UV EVENT LOOP TICKS LAST SECOND: ", loop_run_count,
", LOGIC THREAD JOBS: ", m_Logic->numPendingJobs());
loop_run_count = 0;
last_time = uv_now(&m_Impl);
}
loop_run_count++;
#endif
uv_timer_start(&m_TickTimer, &OnTickTimeout, ms, 0);
uv_run(&m_Impl, UV_RUN_ONCE);
}
return 0;
}
void
Loop::stop()
{
uv_stop(&m_Impl);
if(m_Run)
{
llarp::LogInfo("stopping event loop");
m_Run.store(false);
CloseAll();
// uv_stop(&m_Impl);
}
m_Run.store(false);
}
void

@ -92,19 +92,17 @@ namespace libuv
m_Logic = l;
}
/// call function in logic thread
template < typename F >
void
Call(F f)
{
m_Logic->queue_func(f);
}
std::shared_ptr< llarp::Logic > m_Logic;
private:
uv_loop_t m_Impl;
uv_timer_t m_TickTimer;
std::atomic< bool > m_Run;
std::shared_ptr< llarp::Logic > m_Logic;
#ifdef LOKINET_DEBUG
uint64_t last_time;
uint64_t loop_run_count;
#endif
};
} // namespace libuv

@ -144,7 +144,7 @@ tun_ev_loop(void* unused)
while(true)
{
alert =
GetQueuedCompletionStatus(tun_event_queue, &size, &listener, &ovl, 100);
GetQueuedCompletionStatus(tun_event_queue, &size, &listener, &ovl, EV_TICK_INTERVAL);
if(!alert)
{
@ -727,7 +727,7 @@ llarp_win32_loop::tick_listeners()
{
llarp_ev_loop::tick_listeners();
for(auto& func : m_Tickers)
m_Logic->queue_func([func]() { func(); });
LogicCall(m_Logic, func);
}
bool

@ -16,14 +16,20 @@ namespace llarp
static void
ExitHandlerRecvPkt(llarp_tun_io *tun, const llarp_buffer_t &buf)
{
static_cast< ExitEndpoint * >(tun->user)->OnInetPacket(buf);
std::vector< byte_t > pkt;
pkt.resize(buf.sz);
std::copy_n(buf.base, buf.sz, pkt.data());
auto self = static_cast< ExitEndpoint * >(tun->user);
LogicCall(self->GetRouter()->logic(), [self, pktbuf = std::move(pkt)]() {
self->OnInetPacket(std::move(pktbuf));
});
}
static void
ExitHandlerFlush(llarp_tun_io *tun)
{
auto *ep = static_cast< ExitEndpoint * >(tun->user);
ep->GetRouter()->logic()->queue_func(std::bind(&ExitEndpoint::Flush, ep));
LogicCall(ep->GetRouter()->logic(), std::bind(&ExitEndpoint::Flush, ep));
}
ExitEndpoint::ExitEndpoint(const std::string &name, AbstractRouter *r)
@ -457,10 +463,13 @@ namespace llarp
}
void
ExitEndpoint::OnInetPacket(const llarp_buffer_t &buf)
ExitEndpoint::OnInetPacket(std::vector< byte_t > buf)
{
const llarp_buffer_t buffer(buf);
m_InetToNetwork.EmplaceIf(
[b = ManagedBuffer(buf)](Pkt_t &pkt) -> bool { return pkt.Load(b); });
[b = ManagedBuffer(buffer)](Pkt_t &pkt) -> bool {
return pkt.Load(b);
});
}
bool

@ -57,7 +57,7 @@ namespace llarp
/// handle ip packet from outside
void
OnInetPacket(const llarp_buffer_t& buf);
OnInetPacket(std::vector< byte_t > buf);
AbstractRouter*
GetRouter();

@ -32,11 +32,23 @@ namespace llarp
m_NetworkToUserPktQueue.Process(send);
}
static void
tunifTick(llarp_tun_io *tun)
bool
TunEndpoint::ShouldFlushNow(llarp_time_t now) const
{
static constexpr llarp_time_t FlushInterval = 25;
return now >= m_LastFlushAt + FlushInterval;
}
void
TunEndpoint::tunifTick(llarp_tun_io *tun)
{
auto *self = static_cast< TunEndpoint * >(tun->user);
self->Flush();
const auto now = self->Now();
if(self->ShouldFlushNow(now))
{
self->m_LastFlushAt = now;
LogicCall(self->m_router->logic(), [self]() { self->Flush(); });
}
}
TunEndpoint::TunEndpoint(const std::string &nickname, AbstractRouter *r,
@ -308,13 +320,20 @@ namespace llarp
void
TunEndpoint::Flush()
{
auto self = shared_from_this();
FlushSend();
RouterLogic()->queue_func([=] {
static const auto func = [](auto self) {
self->FlushSend();
self->m_ExitMap.ForEachValue(
[](const auto &exit) { exit->FlushUpstream(); });
self->Pump(self->Now());
});
};
if(NetworkIsIsolated())
{
LogicCall(RouterLogic(), std::bind(func, shared_from_this()));
}
else
{
func(this);
}
}
static bool
@ -329,6 +348,32 @@ namespace llarp
return msg.questions[0].IsName("localhost.loki");
}
template <>
bool
TunEndpoint::FindAddrForIP(service::Address &addr, huint128_t ip)
{
auto itr = m_IPToAddr.find(ip);
if(itr != m_IPToAddr.end() and not m_SNodes[itr->second])
{
addr = service::Address(itr->second.as_array());
return true;
}
return false;
}
template <>
bool
TunEndpoint::FindAddrForIP(RouterID &addr, huint128_t ip)
{
auto itr = m_IPToAddr.find(ip);
if(itr != m_IPToAddr.end() and m_SNodes[itr->second])
{
addr = RouterID(itr->second.as_array());
return true;
}
return false;
}
bool
TunEndpoint::HandleHookedDNSMessage(
dns::Message &&msg, std::function< void(dns::Message) > reply)
@ -472,18 +517,17 @@ namespace llarp
reply(msg);
return true;
}
llarp::service::Address addr(
ObtainAddrForIP< llarp::service::Address >(ip, true));
if(!addr.IsZero())
RouterID snodeAddr;
if(FindAddrForIP(snodeAddr, ip))
{
msg.AddAReply(addr.ToString(".snode"));
msg.AddAReply(snodeAddr.ToString());
reply(msg);
return true;
}
addr = ObtainAddrForIP< llarp::service::Address >(ip, false);
if(!addr.IsZero())
service::Address lokiAddr;
if(FindAddrForIP(lokiAddr, ip))
{
msg.AddAReply(addr.ToString(".loki"));
msg.AddAReply(lokiAddr.ToString());
reply(msg);
return true;
}
@ -701,7 +745,13 @@ namespace llarp
llarp::LogInfo(Name(), " allocated up to ", m_MaxIP, " on range ",
m_OurRange);
MapAddress(m_Identity.pub.Addr(), m_OurIP, IsSNode());
const service::Address ourAddr = m_Identity.pub.Addr();
if(not MapAddress(ourAddr, GetIfAddr(), false))
{
return false;
}
if(m_OnUp)
{
m_OnUp->NotifyAsync(NotifyParams());
@ -710,7 +760,8 @@ namespace llarp
{
vpnif->injected(vpnif, true);
}
return true;
return HasAddress(ourAddr);
}
std::unordered_map< std::string, std::string >
@ -749,13 +800,11 @@ namespace llarp
void
TunEndpoint::Tick(llarp_time_t now)
{
EndpointLogic()->queue_func([&]() {
m_ExitMap.ForEachValue([&](const auto &exit) {
this->EnsureRouterIsKnown(exit->Endpoint());
exit->Tick(now);
});
Endpoint::Tick(now);
});
}
bool
@ -974,16 +1023,23 @@ namespace llarp
{
// called in the isolated network thread
auto *self = static_cast< TunEndpoint * >(tun->user);
auto sendpkt = [self, tun](net::IPPacket &pkt) -> bool {
auto _pkts = std::move(self->m_TunPkts);
self->m_TunPkts = std::vector< net::IPPacket >();
LogicCall(self->EndpointLogic(), [tun, self, pkts = std::move(_pkts)]() {
for(auto &pkt : pkts)
{
self->m_UserToNetworkPktQueue.Emplace(pkt);
}
self->FlushToUser([self, tun](net::IPPacket &pkt) -> bool {
if(!llarp_ev_tun_async_write(tun, pkt.Buffer()))
{
llarp::LogWarn(self->Name(), " packet dropped");
return true;
}
return false;
};
self->EndpointLogic()->queue_func(std::bind(
&TunEndpoint::FlushToUser, self->shared_from_this(), sendpkt));
});
});
}
void
@ -991,9 +1047,10 @@ namespace llarp
{
// called for every packet read from user in isolated network thread
auto *self = static_cast< TunEndpoint * >(tun->user);
const ManagedBuffer pkt(b);
self->m_UserToNetworkPktQueue.EmplaceIf(
[&pkt](net::IPPacket &p) -> bool { return p.Load(pkt); });
net::IPPacket pkt;
if(not pkt.Load(b))
return;
self->m_TunPkts.emplace_back(pkt);
}
TunEndpoint::~TunEndpoint() = default;

@ -56,6 +56,9 @@ namespace llarp
void
TickTun(llarp_time_t now);
static void
tunifTick(llarp_tun_io*);
bool
MapAddress(const service::Address& remote, huint128_t ip, bool SNode);
@ -145,22 +148,24 @@ namespace llarp
handleTickTun(void* u);
/// get a key for ip address
template < typename Addr >
Addr
template < typename Addr_t >
Addr_t
ObtainAddrForIP(huint128_t ip, bool isSNode)
{
Addr_t addr;
auto itr = m_IPToAddr.find(ip);
if(itr == m_IPToAddr.end() || m_SNodes[itr->second] != isSNode)
if(itr != m_IPToAddr.end() and m_SNodes[itr->second] == isSNode)
{
// not found
Addr addr;
addr.Zero();
return addr;
addr = Addr_t(itr->second);
}
// found
return Addr{itr->second};
return addr;
}
template < typename Addr_t >
bool
FindAddrForIP(Addr_t& addr, huint128_t ip);
bool
HasAddress(const AlignedBuffer< 32 >& addr) const
{
@ -179,9 +184,16 @@ namespace llarp
ResetInternalState() override;
protected:
bool
ShouldFlushNow(llarp_time_t now) const;
llarp_time_t m_LastFlushAt = 0;
using PacketQueue_t = llarp::util::CoDelQueue<
net::IPPacket, net::IPPacket::GetTime, net::IPPacket::PutTime,
net::IPPacket::CompareOrder, net::IPPacket::GetNow >;
/// queue packet for send on net thread from user
std::vector< net::IPPacket > m_TunPkts;
/// queue for sending packets over the network from us
PacketQueue_t m_UserToNetworkPktQueue;
/// queue for sending packets to user from network
@ -308,6 +320,7 @@ namespace llarp
void
FlushToUser(std::function< bool(net::IPPacket&) > sendfunc);
};
} // namespace handlers
} // namespace llarp

@ -22,34 +22,6 @@ namespace llarp
LinkLayer::~LinkLayer() = default;
void
LinkLayer::Pump()
{
std::unordered_set< RouterID, RouterID::Hash > sessions;
{
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
auto itr = m_AuthedLinks.begin();
while(itr != m_AuthedLinks.end())
{
const RouterID r{itr->first};
sessions.emplace(r);
++itr;
}
}
ILinkLayer::Pump();
{
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
for(const auto& pk : sessions)
{
if(m_AuthedLinks.count(pk) == 0)
{
// all sessions were removed
SessionClosed(pk);
}
}
}
}
const char*
LinkLayer::Name() const
{

@ -29,6 +29,7 @@ namespace llarp
NewOutboundSession(const RouterContact &rc,
const AddressInfo &ai) override;
void
Pump() override;

@ -28,14 +28,15 @@ namespace llarp
return pkt;
}
Session::Session(LinkLayer* p, RouterContact rc, AddressInfo ai)
Session::Session(LinkLayer* p, const RouterContact& rc,
const AddressInfo& ai)
: m_State{State::Initial}
, m_Inbound{false}
, m_Parent{p}
, m_Parent(p)
, m_CreatedAt{p->Now()}
, m_RemoteAddr{ai}
, m_ChosenAI{std::move(ai)}
, m_RemoteRC{std::move(rc)}
, m_RemoteAddr(ai)
, m_ChosenAI(ai)
, m_RemoteRC(rc)
{
token.Zero();
GotLIM = util::memFn(&Session::GotOutboundLIM, this);
@ -43,12 +44,12 @@ namespace llarp
llarp_buffer_t(rc.pubkey));
}
Session::Session(LinkLayer* p, Addr from)
Session::Session(LinkLayer* p, const Addr& from)
: m_State{State::Initial}
, m_Inbound{true}
, m_Parent{p}
, m_Parent(p)
, m_CreatedAt{p->Now()}
, m_RemoteAddr{from}
, m_RemoteAddr(from)
{
token.Randomize();
GotLIM = util::memFn(&Session::GotInboundLIM, this);
@ -57,9 +58,10 @@ namespace llarp
}
void
Session::Send_LL(const llarp_buffer_t& pkt)
Session::Send_LL(const byte_t* buf, size_t sz)
{
LogDebug("send ", pkt.sz, " to ", m_RemoteAddr);
LogDebug("send ", sz, " to ", m_RemoteAddr);
const llarp_buffer_t pkt(buf, sz);
m_Parent->SendTo_LL(m_RemoteAddr, pkt);
m_LastTX = time_now_ms();
}
@ -144,8 +146,10 @@ namespace llarp
Session::EncryptWorker(CryptoQueue_ptr msgs)
{
LogDebug("encrypt worker ", msgs->size(), " messages");
for(auto& pkt : *msgs)
auto itr = msgs->begin();
while(itr != msgs->end())
{
Packet_t pkt = std::move(*itr);
llarp_buffer_t pktbuf(pkt);
const TunnelNonce nonce_ptr{pkt.data() + HMACSIZE};
pktbuf.base += PacketOverhead;
@ -155,10 +159,8 @@ namespace llarp
pktbuf.base = pkt.data() + HMACSIZE;
pktbuf.sz = pkt.size() - HMACSIZE;
CryptoManager::instance()->hmac(pkt.data(), pktbuf, m_SessionKey);
pktbuf.base = pkt.data();
pktbuf.cur = pkt.data();
pktbuf.sz = pkt.size();
Send_LL(pktbuf);
Send_LL(pkt.data(), pkt.size());
++itr;
}
}
@ -361,6 +363,7 @@ namespace llarp
{
TunnelNonce N;
N.Randomize();
{
ILinkSession::Packet_t req(Introduction::SIZE + PacketOverhead);
const auto pk = m_Parent->GetOurRC().pubkey;
const auto e_pk = m_Parent->RouterEncryptionSecret().toPublic();
@ -374,11 +377,13 @@ namespace llarp
llarp_buffer_t signbuf(req.data() + PacketOverhead,
Introduction::SIZE - Signature::SIZE);
m_Parent->Sign(Z, signbuf);
std::copy_n(
Z.data(), Z.size(),
req.data() + PacketOverhead + (Introduction::SIZE - Signature::SIZE));
CryptoManager::instance()->randbytes(req.data() + HMACSIZE, TUNNONCESIZE);
std::copy_n(Z.data(), Z.size(),
req.data() + PacketOverhead
+ (Introduction::SIZE - Signature::SIZE));
CryptoManager::instance()->randbytes(req.data() + HMACSIZE,
TUNNONCESIZE);
EncryptAndSend(std::move(req));
}
m_State = State::Introduction;
if(not CryptoManager::instance()->transport_dh_client(
m_SessionKey, m_ChosenAI.pubkey,
@ -557,7 +562,8 @@ namespace llarp
recvMsgs->emplace_back(std::move(pkt));
}
LogDebug("decrypted ", recvMsgs->size(), " packets from ", m_RemoteAddr);
m_Parent->logic()->queue_func(
LogicCall(
m_Parent->logic(),
std::bind(&Session::HandlePlaintext, shared_from_this(), recvMsgs));
}

@ -39,9 +39,10 @@ namespace llarp
static constexpr std::size_t MaxACKSInMACK = 1024 / sizeof(uint64_t);
/// outbound session
Session(LinkLayer* parent, RouterContact rc, AddressInfo ai);
Session(LinkLayer* parent, const RouterContact& rc,
const AddressInfo& ai);
/// inbound session
Session(LinkLayer* parent, Addr from);
Session(LinkLayer* parent, const Addr& from);
~Session() = default;
@ -62,7 +63,7 @@ namespace llarp
CompletionHandler resultHandler) override;
void
Send_LL(const llarp_buffer_t& pkt);
Send_LL(const byte_t* buf, size_t sz);
void EncryptAndSend(ILinkSession::Packet_t);

@ -5,6 +5,7 @@
#include <memory>
#include <util/fs.hpp>
#include <utility>
#include <unordered_set>
namespace llarp
{
@ -128,6 +129,8 @@ namespace llarp
void
ILinkLayer::Pump()
{
std::unordered_set< RouterID, RouterID::Hash > closedSessions;
std::vector< std::shared_ptr< ILinkSession > > closedPending;
auto _now = Now();
{
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
@ -144,6 +147,7 @@ namespace llarp
llarp::LogInfo("session to ", RouterID(itr->second->GetPubKey()),
" timed out");
itr->second->Close();
closedSessions.emplace(itr->first);
itr = m_AuthedLinks.erase(itr);
}
}
@ -163,15 +167,25 @@ namespace llarp
{
LogInfo("pending session at ", itr->first, " timed out");
// defer call so we can acquire mutexes later
auto self = itr->second->BorrowSelf();
m_Logic->queue_func([&, self]() {
this->HandleTimeout(self.get());
self->Close();
});
closedPending.emplace_back(std::move(itr->second));
itr = m_Pending.erase(itr);
}
}
}
{
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
for(const auto& r : closedSessions)
{
if(m_AuthedLinks.count(r) == 0)
{
SessionClosed(r);
}
}
}
for(const auto& pending : closedPending)
{
HandleTimeout(pending.get());
}
}
bool
@ -444,7 +458,7 @@ namespace llarp
auto logic = link->logic();
if(logic == nullptr)
return;
logic->queue_func([pkts, link]() {
LogicCall(logic, [pkts, link]() {
auto itr = pkts->begin();
while(itr != pkts->end())
{

@ -410,7 +410,7 @@ namespace llarp
// we are the farthest hop
llarp::LogDebug("We are the farthest hop for ", info);
// send a LRSM down the path
self->context->logic()->queue_func([=]() {
LogicCall(self->context->logic(), [=]() {
SendPathConfirm(self);
self->decrypter = nullptr;
});
@ -419,7 +419,7 @@ namespace llarp
{
// forward upstream
// we are still in the worker thread so post job to logic
self->context->logic()->queue_func([=]() {
LogicCall(self->context->logic(), [=]() {
SendLRCM(self);
self->decrypter = nullptr;
});

@ -222,7 +222,7 @@ namespace llarp
std::shared_ptr< LR_StatusMessage > msg)
{
auto func = std::bind(&LR_StatusMessage::SendMessage, router, nextHop, msg);
router->pathContext().logic()->queue_func(func);
LogicCall(router->logic(), func);
}
void

@ -23,7 +23,7 @@ namespace llarp
uint16_t rank;
std::string dialect;
llarp::PubKey pubkey;
struct in6_addr ip;
in6_addr ip = {0};
uint16_t port;
uint64_t version = LLARP_PROTO_VERSION;

@ -18,8 +18,8 @@ namespace llarp
{
struct ExitInfo
{
struct in6_addr address;
struct in6_addr netmask;
in6_addr address = {0};
in6_addr netmask = {0};
PubKey pubkey;
uint64_t version = LLARP_PROTO_VERSION;

@ -87,7 +87,7 @@ namespace llarp
bool
IPPacket::Load(const llarp_buffer_t &pkt)
{
if(pkt.sz > sizeof(buf))
if(pkt.sz > sizeof(buf) or pkt.sz == 0)
return false;
sz = pkt.sz;
std::copy_n(pkt.base, sz, buf);

@ -1078,7 +1078,7 @@ namespace llarp
{
char buf[INET6_ADDRSTRLEN + 1] = {0};
std::string str;
in6_addr inaddr;
in6_addr inaddr = {0};
size_t numset = 0;
absl::uint128 bits = netmask_bits.h;
while(bits)

@ -191,6 +191,5 @@ namespace llarp
} // namespace llarp
#include <net/net_addr.hpp>
#include <net/net_inaddr.hpp>
#endif

@ -16,7 +16,13 @@
namespace llarp
{
Addr::Addr() = default;
Addr::Addr()
{
llarp::Zero(&_addr4, sizeof(_addr4));
_addr4.sin_family = AF_INET;
llarp::Zero(&_addr, sizeof(_addr));
_addr.sin6_family = AF_INET6;
}
Addr::~Addr() = default;
void
@ -53,18 +59,18 @@ namespace llarp
return (const in_addr*)&_addr.sin6_addr.s6_addr[12];
}
Addr::Addr(string_view str)
Addr::Addr(string_view str) : Addr()
{
this->from_char_array(str);
}
Addr::Addr(string_view str, const uint16_t p_port)
Addr::Addr(string_view str, const uint16_t p_port) : Addr()
{
this->from_char_array(str);
this->port(p_port);
}
Addr::Addr(string_view addr_str, string_view port_str)
Addr::Addr(string_view addr_str, string_view port_str) : Addr()
{
this->from_char_array(string_view_string(addr_str).c_str());
this->port(std::strtoul(string_view_string(port_str).c_str(), nullptr, 10));
@ -174,18 +180,20 @@ namespace llarp
Addr::Addr(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four)
: Addr()
{
this->from_4int(one, two, three, four);
}
Addr::Addr(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four, const uint16_t p_port)
: Addr()
{
this->from_4int(one, two, three, four);
this->port(p_port);
}
Addr::Addr(const AddressInfo& other)
Addr::Addr(const AddressInfo& other) : Addr()
{
memcpy(addr6(), other.ip.s6_addr, 16);
_addr.sin6_port = htons(other.port);
@ -200,7 +208,7 @@ namespace llarp
_addr.sin6_family = AF_INET6;
}
Addr::Addr(const sockaddr_in& other)
Addr::Addr(const sockaddr_in& other) : Addr()
{
Zero(&_addr, sizeof(sockaddr_in6));
_addr.sin6_family = AF_INET;
@ -217,7 +225,7 @@ namespace llarp
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
}
Addr::Addr(const sockaddr_in6& other)
Addr::Addr(const sockaddr_in6& other) : Addr()
{
memcpy(addr6(), other.sin6_addr.s6_addr, 16);
_addr.sin6_port = htons(other.sin6_port);
@ -236,7 +244,7 @@ namespace llarp
_addr.sin6_family = AF_INET6;
}
Addr::Addr(const sockaddr& other)
Addr::Addr(const sockaddr& other) : Addr()
{
Zero(&_addr, sizeof(sockaddr_in6));
_addr.sin6_family = other.sa_family;

@ -16,7 +16,7 @@ namespace llarp
{
// network order
sockaddr_in6 _addr;
sockaddr_in _addr4; // why do we even have this? favor cpu over memory
sockaddr_in _addr4;
~Addr();
Addr();

@ -1,228 +0,0 @@
#include <net/net_inaddr.hpp>
std::ostream&
operator<<(std::ostream& out, const llarp::inAddr& a)
{
char tmp[128] = {0};
if(a.isIPv6Mode())
{
out << "[";
}
if(inet_ntop(a.isIPv4Mode() ? AF_INET : AF_INET6, (void*)&a._addr, tmp,
sizeof(tmp)))
{
out << tmp;
if(a.isIPv6Mode())
out << "]";
}
return out;
}
namespace llarp
{
void
inAddr::reset()
{
llarp::Zero(&this->_addr, sizeof(in6_addr));
}
bool
inAddr::from_char_array(const char* str)
{
this->reset();
// maybe refactor the family detection out
struct addrinfo hint, *res = nullptr;
int ret;
memset(&hint, '\0', sizeof hint);
hint.ai_family = PF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
ret = getaddrinfo(str, nullptr, &hint, &res);
if(ret)
{
llarp::LogError("failed to determine address family: ", str);
return false;
}
if(res->ai_family != AF_INET && res->ai_family != AF_INET6)
{
llarp::LogError("Address family not supported yet", str);
return false;
}
// convert detected-family (ipv4 or ipv6) str to in6_addr
/*
if (res->ai_family == AF_INET)
{
freeaddrinfo(res);
// get IPv4
struct in_addr addr; // basically a uint32_t network order
if(inet_aton(str, &addr) == 0)
{
llarp::LogError("failed to parse ", str);
return false;
}
nuint32_t result;
result.n = addr.s_addr;
this->fromN32(result);
return true;
}
*/
ret = inet_pton(res->ai_family, str, &this->_addr);
// inet_pton won't set SIIT
// this->hexDebug();
freeaddrinfo(res);
if(ret <= 0)
{
if(ret == 0)
{
llarp::LogWarn("Not in presentation format");
return false;
}
llarp::LogWarn("inet_pton failure");
return false;
}
return true;
}
void
inAddr::fromSIIT()
{
if(ipv6_is_siit(this->_addr))
{
this->_addr.s6_addr[0] = this->_addr.s6_addr[12];
this->_addr.s6_addr[1] = this->_addr.s6_addr[13];
this->_addr.s6_addr[2] = this->_addr.s6_addr[14];
this->_addr.s6_addr[3] = this->_addr.s6_addr[15];
this->setIPv4Mode();
}
}
void
inAddr::toSIIT()
{
if(!ipv6_is_siit(this->_addr))
{
this->_addr.s6_addr[10] = 0xff;
this->_addr.s6_addr[11] = 0xff;
this->_addr.s6_addr[12] = this->_addr.s6_addr[0];
this->_addr.s6_addr[13] = this->_addr.s6_addr[1];
this->_addr.s6_addr[14] = this->_addr.s6_addr[2];
this->_addr.s6_addr[15] = this->_addr.s6_addr[3];
llarp::Zero(&this->_addr, sizeof(in6_addr) - 6);
}
}
inline bool
inAddr::isIPv6Mode() const
{
return !this->isIPv4Mode();
}
bool
inAddr::isIPv4Mode() const
{
return ipv6_is_siit(this->_addr)
|| (this->_addr.s6_addr[4] == 0 && this->_addr.s6_addr[5] == 0
&& this->_addr.s6_addr[6] == 0 && this->_addr.s6_addr[7] == 0
&& this->_addr.s6_addr[8] == 0 && this->_addr.s6_addr[9] == 0
&& this->_addr.s6_addr[10] == 0 && this->_addr.s6_addr[11] == 0
&& this->_addr.s6_addr[12] == 0 && this->_addr.s6_addr[13] == 0
&& this->_addr.s6_addr[14] == 0 && this->_addr.s6_addr[15] == 0);
}
void
inAddr::setIPv4Mode()
{
// keep first 4
// llarp::Zero(&this->_addr + 4, sizeof(in6_addr) - 4);
this->_addr.s6_addr[4] = 0;
this->_addr.s6_addr[5] = 0;
this->_addr.s6_addr[6] = 0;
this->_addr.s6_addr[7] = 0;
this->_addr.s6_addr[8] = 0;
this->_addr.s6_addr[9] = 0;
this->_addr.s6_addr[10] = 0;
this->_addr.s6_addr[11] = 0;
this->_addr.s6_addr[12] = 0;
this->_addr.s6_addr[13] = 0;
this->_addr.s6_addr[14] = 0;
this->_addr.s6_addr[15] = 0;
}
void
inAddr::hexDebug()
{
char hex_buffer[16 * 3 + 1];
hex_buffer[16 * 3] = 0;
for(unsigned int j = 0; j < 16; j++)
sprintf(&hex_buffer[3 * j], "%02X ", this->_addr.s6_addr[j]);
printf("in6_addr: [%s]\n", hex_buffer);
}
//
// IPv4 specific functions
//
in_addr
inAddr::toIAddr()
{
in_addr res;
res.s_addr = toN32().n;
return res;
}
void
inAddr::from4int(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four)
{
this->reset();
this->setIPv4Mode();
// Network byte order
this->_addr.s6_addr[0] = one;
this->_addr.s6_addr[1] = two;
this->_addr.s6_addr[2] = three;
this->_addr.s6_addr[3] = four;
}
void
inAddr::fromN32(nuint32_t in)
{
this->reset();
this->setIPv4Mode();
memcpy(&this->_addr, &in.n, sizeof(uint32_t));
}
void
inAddr::fromH32(huint32_t in)
{
this->fromN32(xhtonl(in));
}
nuint32_t
inAddr::toN32()
{
nuint32_t result;
result.n = 0; // return 0 for IPv6
if(this->isIPv4Mode())
{
memcpy(&result.n, &this->_addr, sizeof(uint32_t));
}
return result;
}
huint32_t
inAddr::toH32()
{
return xntohl(this->toN32());
}
//
// IPv6 specific functions
//
} // namespace llarp

@ -1,81 +0,0 @@
#ifndef LLARP_NET_INADDR_HPP
#define LLARP_NET_INADDR_HPP
#include <net/net.hpp>
namespace llarp
{
/// IPv4 or IPv6 holder
struct inAddr
{
// unsigned char s6_addr[16];
struct in6_addr _addr; // store in network order
/// zero out
void
reset();
/// from char*
bool
from_char_array(const char* str);
/// convert from SIIT to IPv4 Mode
void
fromSIIT();
/// convert from IPv4 Mode to SIIT
void
toSIIT();
/// not IPv4 Mode (an actual IPv6 address)
inline bool
isIPv6Mode() const;
/// IPv4 mode (not SIIT)
bool
isIPv4Mode() const;
/// clear out bytes 5-15 (Last 12 bytes)
/// This is how inet_pton works with IPv4 addresses
void
setIPv4Mode();
/// make debugging/testing easier
void
hexDebug();
//
// IPv4 specific functions
//
/// make ipv4 in_addr struct
in_addr
toIAddr();
/// set an IPv4 addr
void
from4int(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four);
/// set from an net-order uint32_t
void
fromN32(nuint32_t in);
/// set from an host-order uint32_t
void
fromH32(huint32_t in);
/// output as net-order uint32_t
nuint32_t
toN32();
/// output as host-order uint32_t
huint32_t
toH32();
//
// IPv6 specific functions
//
// coming soon
};
} // namespace llarp
#endif

@ -122,7 +122,7 @@ llarp_nodedb::InsertAsync(llarp::RouterContact rc,
this->Insert(rc);
if(logic && completionHandler)
{
logic->queue_func([completionHandler] { completionHandler(); });
LogicCall(logic, completionHandler);
}
});
}

@ -155,7 +155,7 @@ namespace llarp
{
llarp::LogDebug("LR_Status message processed, path build successful");
auto self = shared_from_this();
r->logic()->queue_func([=]() { self->HandlePathConfirmMessage(r); });
LogicCall(r->logic(), [=]() { self->HandlePathConfirmMessage(r); });
}
else
{
@ -206,7 +206,7 @@ namespace llarp
llarp::LogDebug("Path build failed for an unspecified reason");
}
auto self = shared_from_this();
r->logic()->queue_func(
LogicCall(r->logic(),
[=]() { self->EnterState(ePathFailed, r->Now()); });
}
@ -411,9 +411,9 @@ namespace llarp
msg.pathid = TXID();
++idx;
}
r->logic()->queue_func(std::bind(&Path::HandleAllUpstream,
shared_from_this(), std::move(sendmsgs),
r));
LogicCall(r->logic(),
std::bind(&Path::HandleAllUpstream, shared_from_this(),
std::move(sendmsgs), r));
}
void
@ -482,9 +482,9 @@ namespace llarp
sendMsgs[idx].X = buf;
++idx;
}
r->logic()->queue_func(std::bind(&Path::HandleAllDownstream,
shared_from_this(), std::move(sendMsgs),
r));
LogicCall(r->logic(),
std::bind(&Path::HandleAllDownstream, shared_from_this(),
std::move(sendMsgs), r));
}
void

@ -239,10 +239,10 @@ namespace llarp
return m_Router;
}
HopHandler_ptr
TransitHop_ptr
PathContext::GetPathForTransfer(const PathID_t& id)
{
RouterID us(OurRouterID());
const RouterID us(OurRouterID());
auto& map = m_TransitPaths;
{
SyncTransitMap_t::Lock_t lock(&map.first);

@ -67,7 +67,7 @@ namespace llarp
bool
TransitHopPreviousIsRouter(const PathID_t& path, const RouterID& r);
HopHandler_ptr
TransitHop_ptr
GetPathForTransfer(const PathID_t& topath);
HopHandler_ptr

@ -98,7 +98,7 @@ namespace llarp
{
// farthest hop
// TODO: encrypt junk frames because our public keys are not eligator
logic->queue_func(std::bind(result, shared_from_this()));
LogicCall(logic, std::bind(result, shared_from_this()));
}
else
{

@ -32,7 +32,13 @@ namespace llarp
return stream;
}
TransitHop::TransitHop() = default;
TransitHop::TransitHop() : m_UpstreamGather(128), m_DownstreamGather(128)
{
m_UpstreamGather.enable();
m_DownstreamGather.enable();
m_UpstreamWorkCounter = 0;
m_DownstreamWorkCounter = 0;
}
bool
TransitHop::Expired(llarp_time_t now) const
@ -118,43 +124,73 @@ namespace llarp
void
TransitHop::DownstreamWork(TrafficQueue_ptr msgs, AbstractRouter* r)
{
std::vector< RelayDownstreamMessage > sendmsgs(msgs->size());
size_t idx = 0;
m_DownstreamWorkCounter++;
auto flushIt = [self = shared_from_this(), r]() {
std::vector< RelayDownstreamMessage > msgs;
do
{
auto maybe = self->m_DownstreamGather.tryPopFront();
if(not maybe.has_value())
break;
msgs.emplace_back(maybe.value());
} while(true);
self->HandleAllDownstream(std::move(msgs), r);
};
for(auto& ev : *msgs)
{
RelayDownstreamMessage msg;
const llarp_buffer_t buf(ev.first);
auto& msg = sendmsgs[idx];
msg.pathid = info.rxID;
msg.Y = ev.second ^ nonceXOR;
CryptoManager::instance()->xchacha20(buf, pathKey, ev.second);
msg.X = buf;
llarp::LogDebug("relay ", msg.X.size(), " bytes downstream from ",
info.upstream, " to ", info.downstream);
++idx;
if(m_DownstreamGather.full())
{
LogicCall(r->logic(), flushIt);
}
if(m_DownstreamGather.enabled())
m_DownstreamGather.pushBack(msg);
}
r->logic()->queue_func(std::bind(&TransitHop::HandleAllDownstream,
shared_from_this(), std::move(sendmsgs),
r));
m_DownstreamWorkCounter--;
if(m_DownstreamWorkCounter == 0)
LogicCall(r->logic(), flushIt);
}
void
TransitHop::UpstreamWork(TrafficQueue_ptr msgs, AbstractRouter* r)
{
std::vector< RelayUpstreamMessage > sendmsgs(msgs->size());
size_t idx = 0;
m_UpstreamWorkCounter++;
auto flushIt = [self = shared_from_this(), r]() {
std::vector< RelayUpstreamMessage > msgs;
do
{
auto maybe = self->m_UpstreamGather.tryPopFront();
if(not maybe.has_value())
break;
msgs.emplace_back(maybe.value());
} while(true);
self->HandleAllUpstream(std::move(msgs), r);
};
for(auto& ev : *msgs)
{
const llarp_buffer_t buf(ev.first);
auto& msg = sendmsgs[idx];
RelayUpstreamMessage msg;
CryptoManager::instance()->xchacha20(buf, pathKey, ev.second);
msg.pathid = info.txID;
msg.Y = ev.second ^ nonceXOR;
msg.X = buf;
++idx;
if(m_UpstreamGather.full())
{
LogicCall(r->logic(), flushIt);
}
if(m_UpstreamGather.enabled())
m_UpstreamGather.pushBack(msg);
}
r->logic()->queue_func(std::bind(&TransitHop::HandleAllUpstream,
shared_from_this(), std::move(sendmsgs),
r));
m_UpstreamWorkCounter--;
if(m_UpstreamWorkCounter == 0)
LogicCall(r->logic(), flushIt);
}
void
@ -173,6 +209,11 @@ namespace llarp
m_LastActivity = r->Now();
}
FlushDownstream(r);
for(const auto& other : m_FlushOthers)
{
other->FlushUpstream(r);
}
m_FlushOthers.clear();
}
else
{
@ -183,7 +224,7 @@ namespace llarp
r->SendToOrQueue(info.upstream, &msg);
}
}
r->linkManager().PumpLinks();
r->PumpLL();
}
void
@ -196,7 +237,7 @@ namespace llarp
info.upstream, " to ", info.downstream);
r->SendToOrQueue(info.downstream, &msg);
}
r->linkManager().PumpLinks();
r->PumpLL();
}
void
@ -410,7 +451,10 @@ namespace llarp
buf.cur = buf.base;
// send
if(path->HandleDownstream(buf, msg.Y, r))
{
m_FlushOthers.emplace(path);
return true;
}
return SendRoutingMessage(discarded, r);
}
@ -421,10 +465,16 @@ namespace llarp
printer.printAttribute("TransitHop", info);
printer.printAttribute("started", started);
printer.printAttribute("lifetime", lifetime);
return stream;
}
void
TransitHop::Stop()
{
m_UpstreamGather.disable();
m_DownstreamGather.disable();
}
void
TransitHop::SetSelfDestruct()
{
@ -435,7 +485,7 @@ namespace llarp
TransitHop::QueueDestroySelf(AbstractRouter* r)
{
auto func = std::bind(&TransitHop::SetSelfDestruct, shared_from_this());
r->logic()->queue_func(func);
LogicCall(r->logic(), func);
}
} // namespace path
} // namespace llarp

@ -6,6 +6,7 @@
#include <path/path_types.hpp>
#include <routing/handler.hpp>
#include <router_id.hpp>
#include <util/compare_ptr.hpp>
namespace llarp
{
@ -94,8 +95,17 @@ namespace llarp
llarp_proto_version_t version;
llarp_time_t m_LastActivity = 0;
void
Stop();
bool destroy = false;
bool
operator<(const TransitHop& other) const
{
return info < other.info;
}
bool
IsEndpoint(const RouterID& us) const
{
@ -222,6 +232,14 @@ namespace llarp
void
QueueDestroySelf(AbstractRouter* r);
std::set< std::shared_ptr< TransitHop >,
ComparePtr< std::shared_ptr< TransitHop > > >
m_FlushOthers;
thread::Queue< RelayUpstreamMessage > m_UpstreamGather;
thread::Queue< RelayDownstreamMessage > m_DownstreamGather;
std::atomic< uint32_t > m_UpstreamWorkCounter;
std::atomic< uint32_t > m_DownstreamWorkCounter;
};
inline std::ostream&

@ -71,15 +71,18 @@ namespace llarp
void
OutboundMessageHandler::Tick()
{
ProcessOutboundQueue();
RemoveEmptyPathQueues();
SendRoundRobin();
m_Killer.TryAccess([self = this]() {
self->ProcessOutboundQueue();
self->RemoveEmptyPathQueues();
self->SendRoundRobin();
});
}
void
OutboundMessageHandler::QueueRemoveEmptyPath(const PathID_t &pathid)
{
removedPaths.pushBack(pathid);
m_Killer.TryAccess(
[self = this, pathid]() { self->removedPaths.pushBack(pathid); });
}
// TODO: this
@ -164,8 +167,8 @@ namespace llarp
{
if(callback)
{
auto func = std::bind(callback, status);
_logic->queue_func(func);
auto f = std::bind(callback, status);
LogicCall(_logic, [self = this, f]() { self->m_Killer.TryAccess(f); });
}
}
@ -265,7 +268,9 @@ namespace llarp
void
OutboundMessageHandler::RemoveEmptyPathQueues()
{
removedSomePaths = (not removedPaths.empty());
removedSomePaths = false;
if(removedPaths.empty())
return;
while(not removedPaths.empty())
{
@ -275,6 +280,7 @@ namespace llarp
outboundMessageQueues.erase(itr);
}
}
removedSomePaths = true;
}
void
@ -282,7 +288,7 @@ namespace llarp
{
// send non-routing messages first priority
auto &non_routing_mq = outboundMessageQueues[zeroID];
while(!non_routing_mq.empty())
while(not non_routing_mq.empty())
{
MessageQueueEntry entry = std::move(non_routing_mq.front());
non_routing_mq.pop();

@ -123,6 +123,8 @@ namespace llarp
ILinkManager *_linkManager;
std::shared_ptr< Logic > _logic;
util::ContentionKiller m_Killer;
// paths cannot have pathid "0", so it can be used as the "pathid"
// for non-traffic (control) messages, so they can be prioritized.
static const PathID_t zeroID;

@ -123,11 +123,6 @@ namespace llarp
int remainingDesired = numDesired;
_nodedb->visit([&](const RouterContact &other) -> bool {
// check if we really remainingDesired to
if(other.ExpiresSoon(now, 30000)) // TODO: make delta configurable
{
return remainingDesired > 0;
}
if(!_rcLookup->RemoteIsAllowed(other.pubkey))
{
return remainingDesired > 0;
@ -219,7 +214,7 @@ namespace llarp
if(ShouldConnectTo(router))
{
auto fn = std::bind(&OutboundSessionMaker::DoEstablish, this, router);
_logic->queue_func(fn);
LogicCall(_logic, fn);
}
}
@ -326,7 +321,7 @@ namespace llarp
for(const auto &callback : movedCallbacks)
{
auto func = std::bind(callback, router, type);
_logic->queue_func(func);
LogicCall(_logic, func);
}
{

@ -29,8 +29,13 @@
#include <iterator>
#include <unordered_map>
#include <utility>
#if defined(RPI) || defined(ANDROID)
#if defined(ANDROID) || defined(IOS)
#include <unistd.h>
#else
#if defined(_WIN32)
#else
#include <curl/curl.h>
#endif
#endif
bool
@ -143,9 +148,17 @@ namespace llarp
void
Router::PumpLL()
{
static constexpr size_t PumpJobThreshhold = 50;
static constexpr llarp_time_t PumpInterval = 25;
const auto now = Now();
if(_stopping.load())
return;
if(_logic->numPendingJobs() >= PumpJobThreshhold
&& _lastPump + PumpInterval >= now)
{
return;
}
_lastPump = now;
paths.PumpDownstream();
paths.PumpUpstream();
@ -197,6 +210,14 @@ namespace llarp
LogError(rcfile, " contains invalid RC");
}
static size_t
RecvIdentKey(char *ptr, size_t, size_t nmemb, void *userdata)
{
for(size_t idx = 0; idx < nmemb; idx++)
static_cast< std::vector< char > * >(userdata)->push_back(ptr[idx]);
return nmemb;
}
bool
Router::EnsureIdentity()
{
@ -207,10 +228,120 @@ namespace llarp
if (_identity.IsZero())
return false;
if (_encryption.IsZero())
return false;
if(whitelistRouters)
{
#if defined(ANDROID) || defined(IOS)
LogError("running a service node on mobile device is not possible.");
return false;
#else
#if defined(_WIN32)
LogError("running a service node on windows is not possible.");
return false;
#else
CURL *curl = curl_easy_init();
if(curl)
{
bool ret = false;
std::stringstream ss;
ss << "http://" << lokidRPCAddr << "/json_rpc";
const auto url = ss.str();
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY);
const auto auth = lokidRPCUser + ":" + lokidRPCPassword;
curl_easy_setopt(curl, CURLOPT_USERPWD, auth.c_str());
curl_slist *list = nullptr;
list = curl_slist_append(list, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
nlohmann::json request = {{"id", "0"},
{"jsonrpc", "2.0"},
{"method", "get_service_node_privkey"}};
const auto data = request.dump();
std::vector< char > resp;
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data.size());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &RecvIdentKey);
do
{
resp.clear();
LogInfo("Getting Identity Keys from lokid...");
if(curl_easy_perform(curl) == CURLE_OK)
{
try
{
auto j = nlohmann::json::parse(resp);
if(not j.is_object())
continue;
const auto itr = j.find("result");
if(itr == j.end())
continue;
if(not itr->is_object())
continue;
const auto k =
(*itr)["service_node_ed25519_privkey"].get< std::string >();
if(k.size() != (_identity.size() * 2))
{
if(k.empty())
{
LogError("lokid gave no identity key");
}
else
{
LogError("lokid gave invalid identity key");
}
return false;
}
if(not HexDecode(k.c_str(), _identity.data(), _identity.size()))
continue;
if(CryptoManager::instance()->check_identity_privkey(_identity))
{
ret = true;
}
else
{
LogError("lokid gave bogus identity key");
}
}
catch(nlohmann::json::exception &ex)
{
LogError("Bad response from lokid: ", ex.what());
}
}
else
{
LogError("failed to get identity keys");
}
if(ret)
{
LogInfo("Got Identity Keys from lokid: ", RouterID(pubkey()));
break;
}
else
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
} while(true);
curl_easy_cleanup(curl);
curl_slist_free_all(list);
return ret;
}
else
{
LogError("failed to init curl");
return false;
}
#endif
#endif
}
return llarp_findOrCreateIdentity(ident_keyfile, _identity);
}
if(usingSNSeed)
{
LogError("FIXME: load identity key from SNode seed");
@ -287,7 +418,7 @@ namespace llarp
return;
auto *self = static_cast< Router * >(user);
self->ticker_job_id = 0;
self->logic()->queue_func(std::bind(&Router::Tick, self));
LogicCall(self->logic(), std::bind(&Router::Tick, self));
self->ScheduleTicker(orig);
}

@ -54,6 +54,7 @@ namespace llarp
{
struct Router final : public AbstractRouter
{
llarp_time_t _lastPump = 0;
bool ready;
// transient iwp encryption key
fs::path transport_keyfile = "transport.key";

@ -53,6 +53,48 @@ namespace llarp
PopulateReqHeaders(abyss::http::Headers_t& hdr) override;
};
struct LokiPingHandler final : public CallerHandler
{
~LokiPingHandler() override = default;
LokiPingHandler(::abyss::http::ConnImpl* impl, CallerImpl* parent)
: CallerHandler(impl, parent)
{
}
bool
HandleJSONResult(const nlohmann::json& result) override
{
if(not result.is_object())
{
LogError("invalid result from lokid ping, not an object");
return false;
}
const auto itr = result.find("status");
if(itr == result.end())
{
LogError("invalid result from lokid ping, no result");
return false;
}
if(not itr->is_string())
{
LogError("invalid result from lokid ping, status not an string");
return false;
}
const auto status = itr->get< std::string >();
if(status != "OK")
{
LogError("lokid ping failed: '", status, "'");
return false;
}
LogInfo("lokid ping: '", status, "'");
return true;
}
void
HandleError() override
{
LogError("Failed to ping lokid");
}
};
struct GetServiceNodeListHandler final : public CallerHandler
{
using PubkeyList_t = std::vector< RouterID >;
@ -120,7 +162,9 @@ namespace llarp
{
AbstractRouter* router;
llarp_time_t m_NextKeyUpdate = 0;
llarp_time_t m_NextPing = 0;
const llarp_time_t KeyUpdateInterval = 5000;
const llarp_time_t PingInterval = 60 * 5 * 1000;
using PubkeyList_t = GetServiceNodeListHandler::PubkeyList_t;
CallerImpl(AbstractRouter* r) : ::abyss::http::JSONRPC(), router(r)
@ -130,11 +174,18 @@ namespace llarp
void
Tick(llarp_time_t now)
{
if(not router->IsRunning())
return;
if(now >= m_NextKeyUpdate)
{
AsyncUpdatePubkeyList();
m_NextKeyUpdate = now + KeyUpdateInterval;
}
if(now >= m_NextPing)
{
AsyncLokiPing();
m_NextPing = now + PingInterval;
}
Flush();
}
@ -145,6 +196,20 @@ namespace llarp
password = passwd;
}
void
AsyncLokiPing()
{
LogInfo("Pinging Lokid");
static nlohmann::json::number_unsigned_t major(atoi(LLARP_VERSION_MAJ));
static nlohmann::json::number_unsigned_t minor(atoi(LLARP_VERSION_MIN));
static nlohmann::json::number_unsigned_t patch(
atoi(LLARP_VERSION_PATCH));
nlohmann::json params = {
{"version", nlohmann::json::array({major, minor, patch})}};
QueueRPC("lokinet_ping", std::move(params),
util::memFn(&CallerImpl::NewLokinetPingConn, this));
}
void
AsyncUpdatePubkeyList()
{
@ -162,6 +227,12 @@ namespace llarp
return RunAsync(router->netloop(), remote);
}
abyss::http::IRPCClientHandler*
NewLokinetPingConn(abyss::http::ConnImpl* impl)
{
return new LokiPingHandler(impl, this);
}
abyss::http::IRPCClientHandler*
NewAsyncUpdatePubkeyListConn(abyss::http::ConnImpl* impl)
{

@ -17,7 +17,6 @@ namespace llarp
: logic(std::move(l))
, m_remote(std::move(r))
, m_LocalIdentity(localident)
, frame(std::make_shared< ProtocolFrame >())
, introPubKey(introsetPubKey)
, remoteIntro(remote)
, handler(h)
@ -27,31 +26,33 @@ namespace llarp
}
void
AsyncKeyExchange::Result(std::shared_ptr< AsyncKeyExchange > self)
AsyncKeyExchange::Result(std::shared_ptr< AsyncKeyExchange > self,
std::shared_ptr< ProtocolFrame > frame)
{
// put values
self->handler->PutSenderFor(self->msg.tag, self->m_remote, false);
self->handler->PutCachedSessionKeyFor(self->msg.tag, self->sharedKey);
self->handler->PutIntroFor(self->msg.tag, self->remoteIntro);
self->handler->PutReplyIntroFor(self->msg.tag, self->msg.introReply);
self->hook(self->frame);
self->hook(frame);
}
void
AsyncKeyExchange::Encrypt(std::shared_ptr< AsyncKeyExchange > self)
AsyncKeyExchange::Encrypt(std::shared_ptr< AsyncKeyExchange > self,
std::shared_ptr< ProtocolFrame > frame)
{
// derive ntru session key component
SharedSecret K;
auto crypto = CryptoManager::instance();
crypto->pqe_encrypt(self->frame->C, K, self->introPubKey);
crypto->pqe_encrypt(frame->C, K, self->introPubKey);
// randomize Nonce
self->frame->N.Randomize();
frame->N.Randomize();
// compure post handshake session key
// PKE (A, B, N)
SharedSecret sharedSecret;
path_dh_func dh_client = util::memFn(&Crypto::dh_client, crypto);
if(!self->m_LocalIdentity.KeyExchange(dh_client, sharedSecret,
self->m_remote, self->frame->N))
self->m_remote, frame->N))
{
LogError("failed to derive x25519 shared key component");
}
@ -68,8 +69,9 @@ namespace llarp
// set version
self->msg.version = LLARP_PROTO_VERSION;
// encrypt and sign
if(self->frame->EncryptAndSign(self->msg, K, self->m_LocalIdentity))
self->logic->queue_func(std::bind(&AsyncKeyExchange::Result, self));
if(frame->EncryptAndSign(self->msg, K, self->m_LocalIdentity))
LogicCall(self->logic,
std::bind(&AsyncKeyExchange::Result, self, frame));
else
{
LogError("failed to encrypt and sign");

@ -19,7 +19,6 @@ namespace llarp
ServiceInfo m_remote;
const Identity& m_LocalIdentity;
ProtocolMessage msg;
std::shared_ptr< ProtocolFrame > frame;
Introduction intro;
const PQPubKey introPubKey;
Introduction remoteIntro;
@ -34,11 +33,13 @@ namespace llarp
const ConvoTag& t, ProtocolType proto);
static void
Result(std::shared_ptr< AsyncKeyExchange > user);
Result(std::shared_ptr< AsyncKeyExchange > user,
std::shared_ptr< ProtocolFrame > frame);
/// given protocol message make protocol frame
static void
Encrypt(std::shared_ptr< AsyncKeyExchange > user);
Encrypt(std::shared_ptr< AsyncKeyExchange > user,
std::shared_ptr< ProtocolFrame > frame);
};
} // namespace service

@ -29,12 +29,15 @@ namespace llarp
{
Endpoint::Endpoint(const std::string& name, AbstractRouter* r,
Context* parent)
: path::Builder(r, 3, path::default_len), context(parent)
: path::Builder(r, 3, path::default_len)
, context(parent)
, m_RecvQueue(128)
{
m_state = std::make_unique< EndpointState >();
m_state->m_Router = r;
m_state->m_Name = name;
m_state->m_Tag.Zero();
m_RecvQueue.enable();
}
bool
@ -805,6 +808,30 @@ namespace llarp
return {{"LOKINET_ADDR", m_Identity.pub.Addr().ToString()}};
}
void
Endpoint::FlushRecvData()
{
do
{
auto maybe = m_RecvQueue.tryPopFront();
if(not maybe.has_value())
return;
auto ev = std::move(maybe.value());
ProtocolMessage::ProcessAsync(ev.fromPath, ev.pathid, ev.msg);
} while(true);
}
void
Endpoint::QueueRecvData(RecvDataEvent ev)
{
if(m_RecvQueue.full() || m_RecvQueue.empty())
{
auto self = this;
LogicCall(m_router->logic(), [self]() { self->FlushRecvData(); });
}
m_RecvQueue.pushBack(std::move(ev));
}
bool
Endpoint::HandleDataMessage(path::Path_ptr path, const PathID_t from,
std::shared_ptr< ProtocolMessage > msg)
@ -1046,20 +1073,31 @@ namespace llarp
{
const auto& sessions = m_state->m_SNodeSessions;
auto& queue = m_state->m_InboundTrafficQueue;
EndpointLogic()->queue_func([&]() {
auto epPump = [&]() {
FlushRecvData();
// send downstream packets to user for snode
for(const auto& item : sessions)
item.second.first->FlushDownstream();
// send downstream traffic to user for hidden service
util::Lock lock(&m_state->m_InboundTrafficQueueMutex);
while(queue.size())
while(not queue.empty())
{
const auto& msg = queue.top();
const llarp_buffer_t buf(msg->payload);
HandleInboundPacket(msg->tag, buf, msg->proto);
queue.pop();
}
});
};
if(NetworkIsIsolated())
{
LogicCall(EndpointLogic(), epPump);
}
else
{
epPump();
}
auto router = Router();
// TODO: locking on this container
@ -1068,6 +1106,7 @@ namespace llarp
// TODO: locking on this container
for(const auto& item : sessions)
item.second.first->FlushUpstream();
{
util::Lock lock(&m_state->m_SendQueueMutex);
// send outbound traffic
for(const auto& item : m_state->m_SendQueue)
@ -1076,6 +1115,7 @@ namespace llarp
MarkConvoTagActive(item.first->T.T);
}
m_state->m_SendQueue.clear();
}
router->PumpLL();
}
@ -1096,6 +1136,8 @@ namespace llarp
Endpoint::SendToServiceOrQueue(const service::Address& remote,
const llarp_buffer_t& data, ProtocolType t)
{
if(data.sz == 0)
return false;
// inbound converstation
const auto now = Now();

@ -78,6 +78,9 @@ namespace llarp
bool
IsReady() const;
void
QueueRecvData(RecvDataEvent ev) override;
/// return true if our introset has expired intros
bool
IntrosetIsStale() const;
@ -436,6 +439,9 @@ namespace llarp
hooks::Backend_ptr m_OnReady;
private:
void
FlushRecvData();
friend struct EndpointUtil;
// clang-format off
@ -448,6 +454,7 @@ namespace llarp
// clang-format on
std::unique_ptr< EndpointState > m_state;
thread::Queue< RecvDataEvent > m_RecvQueue;
};
using Endpoint_ptr = std::shared_ptr< Endpoint >;

@ -14,6 +14,14 @@ namespace llarp
namespace service
{
using ConvoTag = AlignedBuffer< 16 >;
struct ProtocolMessage;
struct RecvDataEvent
{
path::Path_ptr fromPath;
PathID_t pathid;
std::shared_ptr< ProtocolMessage > msg;
};
struct ProtocolMessage;
struct IDataHandler
@ -63,6 +71,9 @@ namespace llarp
virtual bool
HasInboundConvo(const Address& addr) const = 0;
virtual void
QueueRecvData(RecvDataEvent ev) = 0;
};
} // namespace service
} // namespace llarp

@ -26,7 +26,7 @@ namespace llarp
if(!msg)
return false;
endpoint = path->Endpoint();
r->logic()->queue_func([=]() { path->SendRoutingMessage(*msg, r); });
LogicCall(r->logic(), [=]() { path->SendRoutingMessage(*msg, r); });
return true;
}
} // namespace service

@ -62,7 +62,6 @@ namespace llarp
if(intro.expiresAt > m_NextIntro.expiresAt)
m_NextIntro = intro;
}
currentConvoTag.Randomize();
}
OutboundContext::~OutboundContext() = default;
@ -176,6 +175,8 @@ namespace llarp
OutboundContext::AsyncGenIntro(const llarp_buffer_t& payload,
ProtocolType t)
{
if(not currentConvoTag.IsZero())
return;
if(remoteIntro.router.IsZero())
SwapIntros();
@ -193,6 +194,8 @@ namespace llarp
return;
}
}
currentConvoTag.Randomize();
auto frame = std::make_shared< ProtocolFrame >();
auto ex = std::make_shared< AsyncKeyExchange >(
m_Endpoint->RouterLogic(), remoteIdent, m_Endpoint->GetIdentity(),
currentIntroSet.K, remoteIntro, m_DataHandler, currentConvoTag, t);
@ -202,9 +205,9 @@ namespace llarp
ex->msg.PutBuffer(payload);
ex->msg.introReply = path->intro;
ex->frame->F = ex->msg.introReply.pathID;
frame->F = ex->msg.introReply.pathID;
m_Endpoint->CryptoWorker()->addJob(
std::bind(&AsyncKeyExchange::Encrypt, ex));
std::bind(&AsyncKeyExchange::Encrypt, ex, frame));
}
std::string

@ -343,7 +343,7 @@ namespace llarp
std::shared_ptr< ProtocolMessage > msg = std::move(self->msg);
path::Path_ptr path = std::move(self->path);
const PathID_t from = self->frame.F;
self->logic->queue_func(
LogicCall(self->logic,
[=]() { ProtocolMessage::ProcessAsync(path, from, msg); });
delete self;
}
@ -364,6 +364,13 @@ namespace llarp
return *this;
}
struct AsyncDecrypt
{
ServiceInfo si;
SharedSecret shared;
ProtocolFrame frame;
};
bool
ProtocolFrame::AsyncDecryptAndVerify(
std::shared_ptr< Logic > logic, path::Path_ptr recvPath,
@ -371,6 +378,7 @@ namespace llarp
const Identity& localIdent, IDataHandler* handler) const
{
auto msg = std::make_shared< ProtocolMessage >();
msg->handler = handler;
if(T.IsZero())
{
LogInfo("Got protocol frame with new convo");
@ -380,38 +388,44 @@ namespace llarp
dh->path = recvPath;
return worker->addJob(std::bind(&AsyncFrameDecrypt::Work, dh));
}
SharedSecret shared;
if(!handler->GetCachedSessionKeyFor(T, shared))
auto v = new AsyncDecrypt();
if(!handler->GetCachedSessionKeyFor(T, v->shared))
{
LogError("No cached session for T=", T);
delete v;
return false;
}
ServiceInfo si;
if(!handler->GetSenderFor(T, si))
if(!handler->GetSenderFor(T, v->si))
{
LogError("No sender for T=", T);
delete v;
return false;
}
if(!Verify(si))
v->frame = *this;
return worker->addJob(
[v, msg = std::move(msg), recvPath = std::move(recvPath)]() {
if(not v->frame.Verify(v->si))
{
LogError("Signature failure from ", si.Addr());
return false;
LogError("Signature failure from ", v->si.Addr());
delete v;
return;
}
if(!DecryptPayloadInto(shared, *msg))
if(not v->frame.DecryptPayloadInto(v->shared, *msg))
{
LogError("failed to decrypt message");
return false;
}
if(T != msg->tag && !msg->tag.IsZero())
{
LogError("convotag missmatch: ", T, " != ", msg->tag);
return false;
delete v;
return;
}
msg->handler = handler;
const PathID_t fromPath = F;
logic->queue_func(
[=]() { ProtocolMessage::ProcessAsync(recvPath, fromPath, msg); });
return true;
RecvDataEvent ev;
ev.fromPath = std::move(recvPath);
ev.pathid = v->frame.F;
ev.msg = std::move(msg);
msg->handler->QueueRecvData(std::move(ev));
delete v;
});
}
bool

@ -95,15 +95,12 @@ namespace llarp
m->PutBuffer(payload);
auto self = this;
m_Endpoint->CryptoWorker()->addJob([f, m, shared, path, self]() {
if(!f->EncryptAndSign(*m, shared, self->m_Endpoint->GetIdentity()))
if(not f->EncryptAndSign(*m, shared, self->m_Endpoint->GetIdentity()))
{
LogError(self->m_Endpoint->Name(), " failed to sign message");
return;
}
self->m_Endpoint->RouterLogic()->queue_func([self, f, path]() {
self->Send(f, path);
self->FlushUpstream();
});
});
}
@ -111,7 +108,7 @@ namespace llarp
SendContext::AsyncEncryptAndSendTo(const llarp_buffer_t& data,
ProtocolType protocol)
{
if(lastGoodSend)
if(lastGoodSend != 0)
{
EncryptAndSendTo(data, protocol);
}

@ -14,9 +14,10 @@ namespace llarp
switch(lvl)
{
case eLogNone:
break;
case eLogDebug:
ss << "[DBG] ";
return;
case eLogTrace:
ss << "[TRC] ";
break case eLogDebug : ss << "[DBG] ";
break;
case eLogInfo:
ss << "[NFO] ";
@ -49,6 +50,9 @@ namespace llarp
str += tag;
switch(lvl)
{
case eLogTrace:
__android_log_write(ANDROID_LOG_TRACE, str.c_str(), msg.c_str());
return;
case eLogDebug:
__android_log_write(ANDROID_LOG_DEBUG, str.c_str(), msg.c_str());
return;

@ -5,28 +5,46 @@
namespace llarp
{
namespace
void
FileLogStream::Flush(Lines_t *lines, FILE *const f)
{
static void
Flush(std::deque< std::string > lines, FILE *const f)
bool wrote_stuff = false;
do
{
for(const auto &line : lines)
fprintf(f, "%s\n", line.c_str());
auto maybe_line = lines->tryPopFront();
if(not maybe_line.has_value())
break;
const auto &line = maybe_line.value();
if(fprintf(f, "%s\n", line.c_str()) >= 0)
wrote_stuff = true;
} while(true);
if(wrote_stuff)
fflush(f);
}
} // namespace
// namespace
FileLogStream::FileLogStream(std::shared_ptr< thread::ThreadPool > disk,
FILE *f, llarp_time_t flushInterval,
bool closeFile)
: m_Disk(std::move(disk))
: m_Lines(1024 * 8)
, m_Disk(std::move(disk))
, m_File(f)
, m_FlushInterval(flushInterval)
, m_Close(closeFile)
{
m_Lines.enable();
}
FileLogStream::~FileLogStream()
{
m_Lines.disable();
do
{
auto line = m_Lines.tryPopFront();
if(not line.has_value())
break;
} while(true);
fflush(m_File);
if(m_Close)
fclose(m_File);
@ -35,6 +53,8 @@ namespace llarp
bool
FileLogStream::ShouldFlush(llarp_time_t now) const
{
if(m_Lines.full())
return true;
if(m_LastFlush >= now)
return false;
const auto dlt = now - m_LastFlush;
@ -54,7 +74,15 @@ namespace llarp
void
FileLogStream::Print(LogLevel, const char *, const std::string &msg)
{
m_Lines.emplace_back(msg);
m_Lines.pushBack(msg);
}
void
FileLogStream::AppendLog(LogLevel lvl, const char *fname, int lineno,
const std::string &nodename, const std::string msg)
{
ILogStream::AppendLog(lvl, fname, lineno, nodename, msg);
Tick(llarp::time_now_ms());
}
void
@ -68,9 +96,8 @@ namespace llarp
FileLogStream::FlushLinesToDisk(llarp_time_t now)
{
FILE *const f = m_File;
std::deque< std::string > lines(m_Lines);
m_Disk->addJob([=]() { Flush(lines, f); });
m_Lines.clear();
auto lines = &m_Lines;
m_Disk->addJob([f, lines]() { Flush(lines, f); });
m_LastFlush = now;
}
} // namespace llarp

@ -4,6 +4,7 @@
#include <util/logging/logstream.hpp>
#include <util/thread/thread_pool.hpp>
#include <util/thread/queue.hpp>
#include <util/time.hpp>
#include <deque>
@ -29,14 +30,21 @@ namespace llarp
Tick(llarp_time_t now) override;
void
PostLog(std::stringstream&) const override
{
}
PostLog(std::stringstream&) const override{};
void
AppendLog(LogLevel lvl, const char* fname, int lineno,
const std::string& nodename, const std::string msg) override;
using Lines_t = thread::Queue< std::string >;
protected:
std::deque< std::string > m_Lines;
Lines_t m_Lines;
private:
static void
Flush(Lines_t* const, FILE* const);
bool
ShouldFlush(llarp_time_t now) const;

@ -14,7 +14,7 @@ namespace llarp
obj["line"] = lineno;
obj["level"] = LogLevelToString(lvl);
obj["message"] = msg;
m_Lines.emplace_back(obj.dump());
m_Lines.pushBack(obj.dump());
}
} // namespace llarp

@ -236,15 +236,29 @@ namespace llarp
*/
} // namespace llarp
#define LogTrace(...) _Log(llarp::eLogTrace, LOG_TAG, __LINE__, __VA_ARGS__)
#define LogDebug(...) _Log(llarp::eLogDebug, LOG_TAG, __LINE__, __VA_ARGS__)
#define LogInfo(...) _Log(llarp::eLogInfo, LOG_TAG, __LINE__, __VA_ARGS__)
#define LogWarn(...) _Log(llarp::eLogWarn, LOG_TAG, __LINE__, __VA_ARGS__)
#define LogError(...) _Log(llarp::eLogError, LOG_TAG, __LINE__, __VA_ARGS__)
#define LogTraceTag(tag, ...) _Log(llarp::eLogTrace, tag, __LINE__, __VA_ARGS__)
#define LogDebugTag(tag, ...) _Log(llarp::eLogDebug, tag, __LINE__, __VA_ARGS__)
#define LogInfoTag(tag, ...) _Log(llarp::eLogInfo, tag, __LINE__, __VA_ARGS__)
#define LogWarnTag(tag, ...) _Log(llarp::eLogWarn, tag, __LINE__, __VA_ARGS__)
#define LogErrorTag(tag, ...) _Log(llarp::eLogError, tag, __LINE__, __VA_ARGS__)
#define LogTraceExplicit(tag, line, ...) \
_Log(llarp::eLogTrace, tag, line, __VA_ARGS__)
#define LogDebugExplicit(tag, line, ...) \
_Log(llarp::eLogDebug, tag, line, __VA_ARGS__)
#define LogInfoExplicit(tag, line, ...) \
_Log(llarp::eLogInfo, tag, line __VA_ARGS__)
#define LogWarnExplicit(tag, line, ...) \
_Log(llarp::eLogWarn, tag, line, __VA_ARGS__)
#define LogErrorExplicit(tag, line, ...) \
_Log(llarp::eLogError, tag, line, __VA_ARGS__)
#ifndef LOG_TAG
#define LOG_TAG "default"
#endif

@ -7,6 +7,8 @@ namespace llarp
{
switch(lvl)
{
case eLogTrace:
return "TRC";
case eLogDebug:
return "DBG";
case eLogInfo:

@ -7,6 +7,7 @@ namespace llarp
// probably will need to move out of llarp namespace for c api
enum LogLevel
{
eLogTrace,
eLogDebug,
eLogInfo,
eLogWarn,

@ -18,7 +18,8 @@ namespace llarp
switch(lvl)
{
case eLogNone:
break;
return;
case eLogTrace:
case eLogDebug:
ss << (char)27 << "[0m";
break;

@ -23,6 +23,7 @@ namespace llarp
{
case eLogNone:
return;
case eLogTrace:
case eLogDebug:
::syslog(LOG_DEBUG, "%s", msg.c_str());
return;

@ -34,6 +34,8 @@ namespace llarp
{
case eLogNone:
break;
case eLogTrace:
ss << "[TRC] ";
case eLogDebug:
ss << "[DBG] ";
break;

@ -0,0 +1,35 @@
#include <util/lokinet_init.h>
#if defined(_WIN32)
#include <windows.h>
#include <winuser.h>
#include <stdio.h>
int
Lokinet_INIT(void)
{
static const char *(CDECL * pwine_get_version)(void);
HMODULE hntdll = GetModuleHandle("ntdll.dll");
if(hntdll)
{
pwine_get_version = (void *)GetProcAddress(hntdll, "wine_get_version");
if(pwine_get_version)
{
static const char *text =
"dont run lokinet in wine like wtf man we support linux and pretty "
"much every flavour of BSD, and even some flavours of unix system "
"5.x.\nThis Program Will now crash lmao.";
static const char *title = "srsly fam wtf";
MessageBoxA(NULL, text, title, MB_ICONHAND);
abort();
}
}
return 0;
}
#else
int
Lokinet_INIT(void)
{
return 0;
}
#endif

@ -0,0 +1,24 @@
#ifndef LLARP_UTIL_LOKINET_INIT_H
#define LLARP_UTIL_LOKINET_INIT_H
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef Lokinet_INIT
#if defined(_WIN32)
#define Lokinet_INIT \
DieInCaseSomehowThisGetsRunInWineButLikeWTFThatShouldNotHappenButJustInCaseHandleItWithAPopupOrSomeShit
#else
#define Lokinet_INIT _lokinet_non_shit_platform_INIT
#endif
#endif
int
Lokinet_INIT(void);
#ifdef __cplusplus
}
#endif
#endif

@ -2,6 +2,7 @@
#include <util/thread/timer.hpp>
#include <util/logging/logger.hpp>
#include <util/mem.h>
#include <util/metrics/metrics.hpp>
#include <future>
@ -13,8 +14,8 @@ namespace llarp
llarp_timer_tick_all_async(m_Timer, m_Thread, now);
}
Logic::Logic()
: m_Thread(llarp_init_threadpool(1, "llarp-logic"))
Logic::Logic(size_t sz)
: m_Thread(llarp_init_threadpool(1, "llarp-logic", sz))
, m_Timer(llarp_init_timer())
{
llarp_threadpool_start(m_Thread);
@ -36,10 +37,17 @@ namespace llarp
llarp_free_timer(m_Timer);
}
size_t
Logic::numPendingJobs() const
{
return m_Thread->pendingJobs();
}
bool
Logic::queue_job(struct llarp_thread_job job)
{
return job.user && job.work && queue_func(std::bind(job.work, job.user));
return job.user && job.work
&& LogicCall(this, std::bind(job.work, job.user));
}
void
@ -47,28 +55,61 @@ namespace llarp
{
llarp::LogDebug("logic thread stop");
// stop all timers from happening in the future
queue_func(std::bind(&llarp_timer_stop, m_Timer));
LogicCall(this, std::bind(&llarp_timer_stop, m_Timer));
// stop all operations on threadpool
llarp_threadpool_stop(m_Thread);
}
bool
Logic::queue_func(std::function< void(void) > f)
Logic::_traceLogicCall(std::function< void(void) > func, const char* tag,
int line)
{
if(m_Thread->LooksFull(5))
{
LogWarn(
"holy crap, we are trying to queue a job onto the logic thread but "
"it looks full");
#define TAG (tag ? tag : LOG_TAG)
#define LINE (line ? line : __LINE__)
// wrap the function so that we ensure that it's always calling stuff one at
// a time
#if defined(LOKINET_DEBUG)
#define METRIC(action) \
metrics::integerTick("logic", action, 1, "tag", TAG, "line", \
std::to_string(LINE))
#else
#define METRIC(action) \
do \
{ \
} while(false)
#endif
METRIC("queue");
auto f = [self = this, func, tag, line]() {
#if defined(LOKINET_DEBUG)
metrics::TimerGuard g("logic",
std::string(TAG) + ":" + std::to_string(LINE));
#endif
self->m_Killer.TryAccess(func);
};
if(can_flush())
{
// we are calling in the logic thread and our queue looks full
// defer call to a later time so we don't die like a little bitch
call_later(m_Thread->GuessJobLatency() / 2, f);
METRIC("fired");
f();
return true;
}
if(m_Thread->LooksFull(5))
{
LogErrorExplicit(TAG, LINE, "holy crap, we are trying to queue a job "
"onto the logic thread but it looks full");
METRIC("full");
std::abort();
}
auto ret = llarp_threadpool_queue_job(m_Thread, f);
if(not ret)
{
METRIC("dropped");
}
return llarp_threadpool_queue_job(m_Thread, f);
return ret;
#undef TAG
#undef LINE
#undef METRIC
}
void

@ -11,7 +11,7 @@ namespace llarp
class Logic
{
public:
Logic();
Logic(size_t queueLength = size_t{1024 * 8});
~Logic();
@ -27,7 +27,8 @@ namespace llarp
queue_job(struct llarp_thread_job job);
bool
queue_func(std::function< void(void) > func);
_traceLogicCall(std::function< void(void) > func, const char* filename,
int lineo);
uint32_t
call_later(const llarp_timeout_job& job);
@ -41,6 +42,9 @@ namespace llarp
void
remove_call(uint32_t id);
size_t
numPendingJobs() const;
bool
can_flush() const;
@ -49,7 +53,19 @@ namespace llarp
llarp_threadpool* const m_Thread;
llarp_timer_context* const m_Timer;
absl::optional< ID_t > m_ID;
util::ContentionKiller m_Killer;
};
} // namespace llarp
#ifndef LogicCall
#if defined(LOKINET_DEBUG)
#ifdef LOG_TAG
#define LogicCall(l, ...) l->_traceLogicCall(__VA_ARGS__, LOG_TAG, __LINE__)
#else
#define LogicCall(l, ...) l->_traceLogicCall(__VA_ARGS__, __FILE__, __LINE__)
#endif
#else
#define LogicCall(l, ...) l->_traceLogicCall(__VA_ARGS__, 0, 0)
#endif
#endif
#endif

@ -156,6 +156,21 @@ namespace llarp
return ::getpid();
#endif
}
// type for detecting contention on a resource
struct ContentionKiller
{
template < typename F >
void
TryAccess(F visit) const
{
NullLock lock(&__access);
visit();
}
private:
mutable NullMutex __access;
};
} // namespace util
} // namespace llarp

@ -8,11 +8,11 @@
#include <queue>
struct llarp_threadpool *
llarp_init_threadpool(int workers, const char *name)
llarp_init_threadpool(int workers, const char *name, size_t queueLength)
{
if(workers <= 0)
workers = 1;
return new llarp_threadpool(workers, name);
return new llarp_threadpool(workers, name, queueLength);
}
void

@ -19,7 +19,7 @@ struct llarp_threadpool
std::unique_ptr< llarp::thread::ThreadPool > impl;
llarp_threadpool(int workers, llarp::string_view name,
size_t queueLength = size_t{1024})
size_t queueLength = size_t{1024 * 8})
: impl(std::make_unique< llarp::thread::ThreadPool >(
workers, std::max(queueLength, size_t{32}), name))
{
@ -48,7 +48,7 @@ struct llarp_threadpool
#endif
struct llarp_threadpool *
llarp_init_threadpool(int workers, const char *name);
llarp_init_threadpool(int workers, const char *name, size_t queueLength);
void
llarp_free_threadpool(struct llarp_threadpool **tp);

@ -45,12 +45,6 @@ namespace llarp
{
static_cast< timer* >(user)->exec();
}
bool
operator<(const timer& other) const
{
return (started + timeout) < (other.started + other.timeout);
}
};
} // namespace llarp
@ -59,7 +53,6 @@ struct llarp_timer_context
llarp::util::Mutex timersMutex; // protects timers
std::unordered_map< uint32_t, std::unique_ptr< llarp::timer > > timers
GUARDED_BY(timersMutex);
std::priority_queue< std::unique_ptr< llarp::timer > > calling;
llarp::util::Mutex tickerMutex;
std::unique_ptr< llarp::util::Condition > ticker;
absl::Duration nextTickLen = absl::Milliseconds(100);
@ -230,14 +223,15 @@ llarp_timer_tick_all(struct llarp_timer_context* t)
{
if(!t->run())
return;
const auto now = llarp::time_now_ms();
t->m_Now = now;
std::list< std::unique_ptr< llarp::timer > > hit;
{
llarp::util::Lock lock(&t->timersMutex);
auto itr = t->timers.begin();
while(itr != t->timers.end())
{
if(t->m_Now - itr->second->started >= itr->second->timeout
if(now - itr->second->started >= itr->second->timeout
|| itr->second->canceled)
{
// timer hit
@ -253,14 +247,14 @@ llarp_timer_tick_all(struct llarp_timer_context* t)
while(not hit.empty())
{
const auto& h = hit.front();
h->called_at = t->m_Now;
h->called_at = now;
h->exec();
hit.pop_front();
}
// reindex next tick info
{
llarp::util::Lock lock(&t->timersMutex);
t->m_Now = llarp::time_now_ms();
t->m_Now = now;
t->m_NextRequiredTickAt = std::numeric_limits< llarp_time_t >::max();
for(const auto& item : t->timers)
{

@ -71,12 +71,13 @@ Build requirements:
* gcovr (if generating test coverage with gcc)
* libuv >= 1.27.0
* libsodium (A patch that removes `undocumented system call` from the Win32 build is in `llarp/win32`.)
* libcurl
### Linux
build:
$ sudo apt install build-essential cmake git libcap-dev curl libuv1-dev libsodium-dev
$ sudo apt install build-essential cmake git libcap-dev curl libuv1-dev libsodium-dev libcurl-dev
$ git clone https://github.com/loki-project/loki-network
$ cd loki-network
$ make

@ -18,7 +18,6 @@ list(APPEND TEST_SRC
exit/test_llarp_exit_context.cpp
link/test_llarp_link.cpp
llarp_test.cpp
net/test_llarp_net_inaddr.cpp
net/test_llarp_net.cpp
routing/llarp_routing_transfer_traffic.cpp
routing/test_llarp_routing_obtainexitmessage.cpp

@ -69,6 +69,8 @@ namespace llarp
MOCK_METHOD3(pqe_encrypt,
bool(PQCipherBlock &, SharedSecret &, const PQPubKey &));
MOCK_METHOD1(check_identity_privkey, bool(const SecretKey&));
};
} // namespace test
} // namespace llarp

@ -127,7 +127,7 @@ struct LinkLayerTest : public test::LlarpTest< llarp::sodium::CryptoLibSodium >
Context Bob;
bool success = false;
const bool shouldDebug = true;
const bool shouldDebug = false;
llarp_ev_loop_ptr netLoop;
std::shared_ptr< Logic > m_logic;
@ -144,7 +144,7 @@ struct LinkLayerTest : public test::LlarpTest< llarp::sodium::CryptoLibSodium >
{
oldLevel = llarp::LogContext::Instance().minLevel;
if(shouldDebug)
llarp::SetLogLevel(eLogDebug);
llarp::SetLogLevel(eLogTrace);
oldRCLifetime = RouterContact::Lifetime;
RouterContact::BlockBogons = false;
RouterContact::Lifetime = 500;
@ -288,7 +288,7 @@ TEST_F(LinkLayerTest, TestIWP)
ASSERT_TRUE(Alice.Start(m_logic, netLoop, AlicePort));
ASSERT_TRUE(Bob.Start(m_logic, netLoop, BobPort));
m_logic->queue_func([&]() { ASSERT_TRUE(Alice.link->TryEstablishTo(Bob.GetRC())); });
LogicCall(m_logic, [&]() { ASSERT_TRUE(Alice.link->TryEstablishTo(Bob.GetRC())); });
RunMainloop();
ASSERT_TRUE(Alice.IsGucci());

@ -1,7 +1,6 @@
#include <gtest/gtest.h>
#include <net/net.hpp>
#include <net/net_inaddr.hpp>
#include <net/net_int.hpp>
#include <net/ip.hpp>

@ -1,106 +0,0 @@
#include <gtest/gtest.h>
#include <net/net_inaddr.hpp>
struct TestNetInAddr : public ::testing::Test
{
};
TEST_F(TestNetInAddr, TestinAddrFrom4Int)
{
llarp::inAddr test;
test.from4int(127, 0, 0, 1);
char str[INET6_ADDRSTRLEN];
if(inet_ntop(AF_INET, &test._addr, str, INET6_ADDRSTRLEN) == NULL)
{
ASSERT_TRUE(false);
}
ASSERT_TRUE(strcmp("127.0.0.1", str) == 0);
}
TEST_F(TestNetInAddr, TestinAddrFromStr)
{
llarp::inAddr test;
test.from_char_array("127.0.0.1");
char str[INET6_ADDRSTRLEN];
if(inet_ntop(AF_INET, &test._addr, str, INET6_ADDRSTRLEN) == NULL)
{
ASSERT_TRUE(false);
}
ASSERT_TRUE(strcmp("127.0.0.1", str) == 0);
}
TEST_F(TestNetInAddr, TestinAddrReset)
{
llarp::inAddr test;
test.from_char_array("127.0.0.1");
test.reset();
char str[INET6_ADDRSTRLEN];
if(inet_ntop(AF_INET, &test._addr, str, INET6_ADDRSTRLEN) == NULL)
{
ASSERT_TRUE(false);
}
ASSERT_TRUE(strcmp("0.0.0.0", str) == 0);
}
TEST_F(TestNetInAddr, TestinAddrModeSet)
{
llarp::inAddr test;
test.from_char_array("127.0.0.1");
// test.hexDebug();
ASSERT_TRUE(test.isIPv4Mode());
// corrupt it
test._addr.s6_addr[10] = 0xfe;
test._addr.s6_addr[11] = 0xfe;
test.setIPv4Mode();
// test.hexDebug();
ASSERT_TRUE(test.isIPv4Mode());
}
TEST_F(TestNetInAddr, TestinAddrSIIT)
{
llarp::inAddr test;
test.from_char_array("127.0.0.1");
test.toSIIT();
// test.hexDebug();
ASSERT_TRUE(llarp::ipv6_is_siit(test._addr));
test.fromSIIT();
// test.hexDebug();
ASSERT_TRUE(!llarp::ipv6_is_siit(test._addr));
}
TEST_F(TestNetInAddr, TestinAddrN32)
{
llarp::inAddr test;
test.from_char_array("127.0.0.1");
llarp::nuint32_t netOrder = test.toN32();
llarp::inAddr test2;
test2.fromN32(netOrder);
char str[INET6_ADDRSTRLEN];
if(inet_ntop(AF_INET, &test2._addr, str, INET6_ADDRSTRLEN) == NULL)
{
ASSERT_TRUE(false);
}
// printf("[%s]\n", str);
ASSERT_TRUE(strcmp("127.0.0.1", str) == 0);
}
TEST_F(TestNetInAddr, TestinAddrH32)
{
llarp::inAddr test;
test.from_char_array("127.0.0.1");
llarp::huint32_t netOrder = test.toH32();
llarp::inAddr test2;
test2.fromH32(netOrder);
char str[INET6_ADDRSTRLEN];
if(inet_ntop(AF_INET, &test2._addr, str, INET6_ADDRSTRLEN) == NULL)
{
ASSERT_TRUE(false);
}
// printf("[%s]\n", str);
ASSERT_TRUE(strcmp("127.0.0.1", str) == 0);
}

@ -10,11 +10,11 @@ using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("LokiNET")]
[assembly: AssemblyDescription("LokiNET end-user UI")]
[assembly: AssemblyTitle("Lokinet for Windows")]
[assembly: AssemblyDescription("Lokinet end-user UI")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Loki Project")]
[assembly: AssemblyProduct("LokiNET Launcher")]
[assembly: AssemblyProduct("Lokinet Launcher")]
[assembly: AssemblyCopyright("Copyright ©2018-2019 Loki Project. All rights reserved. See LICENSE for more details.")]
[assembly: AssemblyTrademark("Loki, Loki Project, LokiNET are ™ & ©2018-2019 Loki Foundation")]
[assembly: AssemblyCulture("")]
@ -37,10 +37,10 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.5.2")]
[assembly: AssemblyFileVersion("0.5.2")]
[assembly: AssemblyVersion("0.6.0")]
[assembly: AssemblyFileVersion("0.6.0")]
#if DEBUG
[assembly: AssemblyInformationalVersion("0.5.2-dev-{chash:8}")]
[assembly: AssemblyInformationalVersion("0.6.0-dev-{chash:8}")]
#else
[assembly: AssemblyInformationalVersion("0.5.2 (RELEASE_CODENAME)")]
[assembly: AssemblyInformationalVersion("0.6.0 (RELEASE_CODENAME)")]
#endif

@ -67,7 +67,7 @@
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.button1_Click_1);
//
// bootstrap
// dlgBootstrap
//
this.AcceptButton = this.btnDownload;
resources.ApplyResources(this, "$this");
@ -82,7 +82,7 @@
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "bootstrap";
this.Name = "dlgBootstrap";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.ResumeLayout(false);

@ -159,6 +159,9 @@
<data name="uriBox.TabIndex" type="System.Int32, mscorlib">
<value>1</value>
</data>
<data name="uriBox.Text" xml:space="preserve">
<value>https://seed.lokinet.org/bootstrap.signed</value>
</data>
<data name="&gt;&gt;uriBox.Name" xml:space="preserve">
<value>uriBox</value>
</data>
@ -268,7 +271,7 @@
<value>bootstrap from web...</value>
</data>
<data name="&gt;&gt;$this.Name" xml:space="preserve">
<value>bootstrap</value>
<value>dlgBootstrap</value>
</data>
<data name="&gt;&gt;$this.Type" xml:space="preserve">
<value>System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

Loading…
Cancel
Save