diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e22f4530..341054289 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/Makefile b/Makefile index e2ab5cd34..a37be1e0b 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/daemon/main.cpp b/daemon/main.cpp index 1e7124731..9ad3cfab7 100644 --- a/daemon/main.cpp +++ b/daemon/main.cpp @@ -1,6 +1,7 @@ #include // for ensure_config #include #include +#include #include #include #include @@ -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") diff --git a/libabyss/main.cpp b/libabyss/main.cpp index 626ffb719..274a6968d 100644 --- a/libabyss/main.cpp +++ b/libabyss/main.cpp @@ -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; } diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 00b663856..324d6beef 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -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) diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 0ba2b968b..2bd89ef87 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -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) { diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 83d059df0..51dca57e3 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -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"); } diff --git a/llarp/context.cpp b/llarp/context.cpp index 7f88b6107..3e1c825e3 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -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,8 +485,8 @@ extern "C" void llarp_main_signal(struct llarp_main *ptr, int sig) { - ptr->ctx->logic->queue_func( - std::bind(&llarp::Context::HandleSignal, ptr->ctx.get(), sig)); + LogicCall(ptr->ctx->logic, + std::bind(&llarp::Context::HandleSignal, ptr->ctx.get(), sig)); } int diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index f97bdbfc7..432bd4782 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -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; diff --git a/llarp/crypto/crypto_libsodium.cpp b/llarp/crypto/crypto_libsodium.cpp index 72378d182..1507312cf 100644 --- a/llarp/crypto/crypto_libsodium.cpp +++ b/llarp/crypto/crypto_libsodium.cpp @@ -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) { diff --git a/llarp/crypto/crypto_libsodium.hpp b/llarp/crypto/crypto_libsodium.hpp index 422747335..75ded5c32 100644 --- a/llarp/crypto/crypto_libsodium.hpp +++ b/llarp/crypto/crypto_libsodium.hpp @@ -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 diff --git a/llarp/crypto/crypto_noop.hpp b/llarp/crypto/crypto_noop.hpp index 177515258..9a91e673d 100644 --- a/llarp/crypto/crypto_noop.hpp +++ b/llarp/crypto/crypto_noop.hpp @@ -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 diff --git a/llarp/crypto/encrypted_frame.hpp b/llarp/crypto/encrypted_frame.hpp index e1fccab5e..0beb62736 100644 --- a/llarp/crypto/encrypted_frame.hpp +++ b/llarp/crypto/encrypted_frame.hpp @@ -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 diff --git a/llarp/dht/context.cpp b/llarp/dht/context.cpp index d729543e9..1f95b0120 100644 --- a/llarp/dht/context.cpp +++ b/llarp/dht/context.cpp @@ -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& diff --git a/llarp/dns/server.cpp b/llarp/dns/server.cpp index dfb0d5834..75373282b 100644 --- a/llarp/dns/server.cpp +++ b/llarp/dns/server.cpp @@ -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); diff --git a/llarp/ev/ev.h b/llarp/ev/ev.h index f7365decf..22dc5443b 100644 --- a/llarp/ev/ev.h +++ b/llarp/ev/ev.h @@ -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; diff --git a/llarp/ev/ev_libuv.cpp b/llarp/ev/ev_libuv.cpp index b003e76bb..aa9c0f0ee 100644 --- a/llarp/ev/ev_libuv.cpp +++ b/llarp/ev/ev_libuv.cpp @@ -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,8 +105,8 @@ namespace libuv OnOutboundConnect(uv_connect_t* c, int status) { conn_glue* self = static_cast< conn_glue* >(c->data); - Call(self->Stream(), - std::bind(&conn_glue::HandleConnectResult, self, status)); + 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) { - uv_timer_start(&m_TickTimer, &OnTickTimeout, ms, 0); - uv_run(&m_Impl, UV_RUN_ONCE); + 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); - llarp::LogInfo("stopping event loop"); + if(m_Run) + { + llarp::LogInfo("stopping event loop"); + CloseAll(); + // uv_stop(&m_Impl); + } m_Run.store(false); - CloseAll(); } void @@ -945,4 +974,4 @@ bool llarp_ev_udp_recvmany(struct llarp_udp_io* u, struct llarp_pkt_list* pkts) { return static_cast< libuv::udp_glue* >(u->impl)->RecvMany(pkts); -} \ No newline at end of file +} diff --git a/llarp/ev/ev_libuv.hpp b/llarp/ev/ev_libuv.hpp index d5c86845b..01ca795c9 100644 --- a/llarp/ev/ev_libuv.hpp +++ b/llarp/ev/ev_libuv.hpp @@ -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 diff --git a/llarp/ev/ev_win32.cpp b/llarp/ev/ev_win32.cpp index b15d29169..18fa91c44 100644 --- a/llarp/ev/ev_win32.cpp +++ b/llarp/ev/ev_win32.cpp @@ -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 diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 5b207056f..7c5c490d6 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -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 diff --git a/llarp/handlers/exit.hpp b/llarp/handlers/exit.hpp index 21a499160..170535fa5 100644 --- a/llarp/handlers/exit.hpp +++ b/llarp/handlers/exit.hpp @@ -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(); diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 837093bfd..8baf61ff6 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -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 { - auto *self = static_cast< TunEndpoint * >(tun->user); - self->Flush(); + 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); + 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); + m_ExitMap.ForEachValue([&](const auto &exit) { + this->EnsureRouterIsKnown(exit->Endpoint()); + exit->Tick(now); }); + Endpoint::Tick(now); } bool @@ -973,17 +1022,24 @@ namespace llarp TunEndpoint::tunifBeforeWrite(llarp_tun_io *tun) { // called in the isolated network thread - auto *self = static_cast< TunEndpoint * >(tun->user); - auto sendpkt = [self, tun](net::IPPacket &pkt) -> bool { - if(!llarp_ev_tun_async_write(tun, pkt.Buffer())) + auto *self = static_cast< TunEndpoint * >(tun->user); + 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) { - llarp::LogWarn(self->Name(), " packet dropped"); - return true; + self->m_UserToNetworkPktQueue.Emplace(pkt); } - return false; - }; - self->EndpointLogic()->queue_func(std::bind( - &TunEndpoint::FlushToUser, self->shared_from_this(), sendpkt)); + 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; + }); + }); } 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; diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index fc48ec547..2203cbf2f 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -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: - using PacketQueue_t = llarp::util::CoDelQueue< + 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 diff --git a/llarp/iwp/linklayer.cpp b/llarp/iwp/linklayer.cpp index 6ffbc5269..4cc1aefa6 100644 --- a/llarp/iwp/linklayer.cpp +++ b/llarp/iwp/linklayer.cpp @@ -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 { diff --git a/llarp/iwp/linklayer.hpp b/llarp/iwp/linklayer.hpp index d6b1e742b..399bbc5ad 100644 --- a/llarp/iwp/linklayer.hpp +++ b/llarp/iwp/linklayer.hpp @@ -29,6 +29,7 @@ namespace llarp NewOutboundSession(const RouterContact &rc, const AddressInfo &ai) override; + void Pump() override; diff --git a/llarp/iwp/session.cpp b/llarp/iwp/session.cpp index 41cbf7c94..7641bad92 100644 --- a/llarp/iwp/session.cpp +++ b/llarp/iwp/session.cpp @@ -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,24 +363,27 @@ 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(); - auto itr = req.data() + PacketOverhead; - std::copy_n(pk.data(), pk.size(), itr); - itr += pk.size(); - std::copy_n(e_pk.data(), e_pk.size(), itr); - itr += e_pk.size(); - std::copy_n(N.data(), N.size(), itr); - Signature Z; - 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); - EncryptAndSend(std::move(req)); + { + ILinkSession::Packet_t req(Introduction::SIZE + PacketOverhead); + const auto pk = m_Parent->GetOurRC().pubkey; + const auto e_pk = m_Parent->RouterEncryptionSecret().toPublic(); + auto itr = req.data() + PacketOverhead; + std::copy_n(pk.data(), pk.size(), itr); + itr += pk.size(); + std::copy_n(e_pk.data(), e_pk.size(), itr); + itr += e_pk.size(); + std::copy_n(N.data(), N.size(), itr); + Signature Z; + 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); + 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)); } diff --git a/llarp/iwp/session.hpp b/llarp/iwp/session.hpp index 7e19d43d5..67b4ef0bf 100644 --- a/llarp/iwp/session.hpp +++ b/llarp/iwp/session.hpp @@ -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); diff --git a/llarp/link/server.cpp b/llarp/link/server.cpp index 96c35f98a..7ade923ae 100644 --- a/llarp/link/server.cpp +++ b/llarp/link/server.cpp @@ -5,6 +5,7 @@ #include #include #include +#include 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()) { diff --git a/llarp/messages/relay_commit.cpp b/llarp/messages/relay_commit.cpp index 7862f6f7a..7d0630fee 100644 --- a/llarp/messages/relay_commit.cpp +++ b/llarp/messages/relay_commit.cpp @@ -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; }); diff --git a/llarp/messages/relay_status.cpp b/llarp/messages/relay_status.cpp index 5e3cea935..46f4d38ac 100644 --- a/llarp/messages/relay_status.cpp +++ b/llarp/messages/relay_status.cpp @@ -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 diff --git a/llarp/net/address_info.hpp b/llarp/net/address_info.hpp index 7bbeaf1b3..b528439e3 100644 --- a/llarp/net/address_info.hpp +++ b/llarp/net/address_info.hpp @@ -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; diff --git a/llarp/net/exit_info.hpp b/llarp/net/exit_info.hpp index c1fe6f678..9a69d88ff 100644 --- a/llarp/net/exit_info.hpp +++ b/llarp/net/exit_info.hpp @@ -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; diff --git a/llarp/net/ip.cpp b/llarp/net/ip.cpp index 8dba138d2..64eb0490b 100644 --- a/llarp/net/ip.cpp +++ b/llarp/net/ip.cpp @@ -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); diff --git a/llarp/net/net.cpp b/llarp/net/net.cpp index f737980d7..a00d6d452 100644 --- a/llarp/net/net.cpp +++ b/llarp/net/net.cpp @@ -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) diff --git a/llarp/net/net.hpp b/llarp/net/net.hpp index b1b4e6d80..d11934f89 100644 --- a/llarp/net/net.hpp +++ b/llarp/net/net.hpp @@ -191,6 +191,5 @@ namespace llarp } // namespace llarp #include -#include #endif diff --git a/llarp/net/net_addr.cpp b/llarp/net/net_addr.cpp index bed44a9c6..6145c6cfd 100644 --- a/llarp/net/net_addr.cpp +++ b/llarp/net/net_addr.cpp @@ -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; diff --git a/llarp/net/net_addr.hpp b/llarp/net/net_addr.hpp index 75e137b87..62e6ff150 100644 --- a/llarp/net/net_addr.hpp +++ b/llarp/net/net_addr.hpp @@ -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(); diff --git a/llarp/net/net_inaddr.cpp b/llarp/net/net_inaddr.cpp deleted file mode 100644 index 1617bf3a3..000000000 --- a/llarp/net/net_inaddr.cpp +++ /dev/null @@ -1,228 +0,0 @@ -#include - -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 diff --git a/llarp/net/net_inaddr.hpp b/llarp/net/net_inaddr.hpp deleted file mode 100644 index 23155e391..000000000 --- a/llarp/net/net_inaddr.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef LLARP_NET_INADDR_HPP -#define LLARP_NET_INADDR_HPP - -#include - -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 diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 6c4b51fbf..c9b7d7f4e 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -122,7 +122,7 @@ llarp_nodedb::InsertAsync(llarp::RouterContact rc, this->Insert(rc); if(logic && completionHandler) { - logic->queue_func([completionHandler] { completionHandler(); }); + LogicCall(logic, completionHandler); } }); } diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index bcee180dc..be2fa17ce 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -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,8 +206,8 @@ namespace llarp llarp::LogDebug("Path build failed for an unspecified reason"); } auto self = shared_from_this(); - r->logic()->queue_func( - [=]() { self->EnterState(ePathFailed, r->Now()); }); + LogicCall(r->logic(), + [=]() { self->EnterState(ePathFailed, r->Now()); }); } // TODO: meaningful return value? @@ -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 diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index e41de0e4b..addf663cd 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -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); diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 8b7c48179..6b5b27ceb 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -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 diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index b30dbbc96..07be157dc 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -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 { diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index c3c2e9d03..07a164b39 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -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 diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index 008ec7841..fb7ecde58 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -6,6 +6,7 @@ #include #include #include +#include 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& diff --git a/llarp/router/outbound_message_handler.cpp b/llarp/router/outbound_message_handler.cpp index 0774f974b..825532aa1 100644 --- a/llarp/router/outbound_message_handler.cpp +++ b/llarp/router/outbound_message_handler.cpp @@ -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(); diff --git a/llarp/router/outbound_message_handler.hpp b/llarp/router/outbound_message_handler.hpp index af18bc9d6..9db745efd 100644 --- a/llarp/router/outbound_message_handler.hpp +++ b/llarp/router/outbound_message_handler.hpp @@ -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; diff --git a/llarp/router/outbound_session_maker.cpp b/llarp/router/outbound_session_maker.cpp index f3418171b..8c6ed024b 100644 --- a/llarp/router/outbound_session_maker.cpp +++ b/llarp/router/outbound_session_maker.cpp @@ -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); } { diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 8017d5d81..b0a034ded 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -29,8 +29,13 @@ #include #include #include -#if defined(RPI) || defined(ANDROID) +#if defined(ANDROID) || defined(IOS) #include +#else +#if defined(_WIN32) +#else +#include +#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); } diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index e81554d5b..1fc8e59bd 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -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"; diff --git a/llarp/rpc/rpc.cpp b/llarp/rpc/rpc.cpp index f25487545..690d1906e 100644 --- a/llarp/rpc/rpc.cpp +++ b/llarp/rpc/rpc.cpp @@ -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) { diff --git a/llarp/service/async_key_exchange.cpp b/llarp/service/async_key_exchange.cpp index b948520bf..ed45ff256 100644 --- a/llarp/service/async_key_exchange.cpp +++ b/llarp/service/async_key_exchange.cpp @@ -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"); diff --git a/llarp/service/async_key_exchange.hpp b/llarp/service/async_key_exchange.hpp index b43ffd279..854047300 100644 --- a/llarp/service/async_key_exchange.hpp +++ b/llarp/service/async_key_exchange.hpp @@ -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 diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 617dcdc4d..1f9d3e306 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -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,14 +1106,16 @@ 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) { - item.second->SendRoutingMessage(*item.first, router); - MarkConvoTagActive(item.first->T.T); + util::Lock lock(&m_state->m_SendQueueMutex); + // send outbound traffic + for(const auto& item : m_state->m_SendQueue) + { + item.second->SendRoutingMessage(*item.first, router); + MarkConvoTagActive(item.first->T.T); + } + m_state->m_SendQueue.clear(); } - 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(); diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index 0dd858cc7..359fd8498 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -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 >; diff --git a/llarp/service/handler.hpp b/llarp/service/handler.hpp index 3c20aea47..9fabb6b95 100644 --- a/llarp/service/handler.hpp +++ b/llarp/service/handler.hpp @@ -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 diff --git a/llarp/service/lookup.cpp b/llarp/service/lookup.cpp index 90dbcfe84..6ffbebd71 100644 --- a/llarp/service/lookup.cpp +++ b/llarp/service/lookup.cpp @@ -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 diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index 510678d7b..cdc4214e6 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -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,7 +194,9 @@ namespace llarp return; } } - auto ex = std::make_shared< AsyncKeyExchange >( + 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 diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index 878c247a8..a74e80b85 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -343,8 +343,8 @@ 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( - [=]() { ProtocolMessage::ProcessAsync(path, from, msg); }); + LogicCall(self->logic, + [=]() { ProtocolMessage::ProcessAsync(path, from, msg); }); delete self; } }; @@ -364,13 +364,21 @@ namespace llarp return *this; } + struct AsyncDecrypt + { + ServiceInfo si; + SharedSecret shared; + ProtocolFrame frame; + }; + bool ProtocolFrame::AsyncDecryptAndVerify( std::shared_ptr< Logic > logic, path::Path_ptr recvPath, const std::shared_ptr< llarp::thread::ThreadPool >& worker, const Identity& localIdent, IDataHandler* handler) const { - auto msg = std::make_shared< ProtocolMessage >(); + 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)) - { - LogError("Signature failure from ", si.Addr()); - return false; - } - if(!DecryptPayloadInto(shared, *msg)) - { - LogError("failed to decrypt message"); - return false; - } - if(T != msg->tag && !msg->tag.IsZero()) - { - LogError("convotag missmatch: ", T, " != ", msg->tag); - return false; - } - msg->handler = handler; - const PathID_t fromPath = F; - logic->queue_func( - [=]() { ProtocolMessage::ProcessAsync(recvPath, fromPath, msg); }); - return true; + 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 ", v->si.Addr()); + delete v; + return; + } + if(not v->frame.DecryptPayloadInto(v->shared, *msg)) + { + LogError("failed to decrypt message"); + delete v; + return; + } + 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 diff --git a/llarp/service/sendcontext.cpp b/llarp/service/sendcontext.cpp index d4c9dc8a5..e47e1382a 100644 --- a/llarp/service/sendcontext.cpp +++ b/llarp/service/sendcontext.cpp @@ -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(); - }); + self->Send(f, path); }); } @@ -111,7 +108,7 @@ namespace llarp SendContext::AsyncEncryptAndSendTo(const llarp_buffer_t& data, ProtocolType protocol) { - if(lastGoodSend) + if(lastGoodSend != 0) { EncryptAndSendTo(data, protocol); } diff --git a/llarp/util/logging/android_logger.cpp b/llarp/util/logging/android_logger.cpp index 439a99036..2757cb746 100644 --- a/llarp/util/logging/android_logger.cpp +++ b/llarp/util/logging/android_logger.cpp @@ -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; diff --git a/llarp/util/logging/file_logger.cpp b/llarp/util/logging/file_logger.cpp index b02d9c2a3..7e055b27d 100644 --- a/llarp/util/logging/file_logger.cpp +++ b/llarp/util/logging/file_logger.cpp @@ -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 diff --git a/llarp/util/logging/file_logger.hpp b/llarp/util/logging/file_logger.hpp index c8db68689..117869295 100644 --- a/llarp/util/logging/file_logger.hpp +++ b/llarp/util/logging/file_logger.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -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; diff --git a/llarp/util/logging/json_logger.cpp b/llarp/util/logging/json_logger.cpp index 71ed8bd99..8acb416b7 100644 --- a/llarp/util/logging/json_logger.cpp +++ b/llarp/util/logging/json_logger.cpp @@ -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 diff --git a/llarp/util/logging/logger.hpp b/llarp/util/logging/logger.hpp index 300cc8684..206c8a000 100644 --- a/llarp/util/logging/logger.hpp +++ b/llarp/util/logging/logger.hpp @@ -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 diff --git a/llarp/util/logging/loglevel.cpp b/llarp/util/logging/loglevel.cpp index e01acaa8a..e2d972627 100644 --- a/llarp/util/logging/loglevel.cpp +++ b/llarp/util/logging/loglevel.cpp @@ -7,6 +7,8 @@ namespace llarp { switch(lvl) { + case eLogTrace: + return "TRC"; case eLogDebug: return "DBG"; case eLogInfo: diff --git a/llarp/util/logging/loglevel.hpp b/llarp/util/logging/loglevel.hpp index 4b9063fed..3bf7a7918 100644 --- a/llarp/util/logging/loglevel.hpp +++ b/llarp/util/logging/loglevel.hpp @@ -7,6 +7,7 @@ namespace llarp // probably will need to move out of llarp namespace for c api enum LogLevel { + eLogTrace, eLogDebug, eLogInfo, eLogWarn, diff --git a/llarp/util/logging/ostream_logger.cpp b/llarp/util/logging/ostream_logger.cpp index 233b99ed4..ba3b3d19e 100644 --- a/llarp/util/logging/ostream_logger.cpp +++ b/llarp/util/logging/ostream_logger.cpp @@ -18,7 +18,8 @@ namespace llarp switch(lvl) { case eLogNone: - break; + return; + case eLogTrace: case eLogDebug: ss << (char)27 << "[0m"; break; diff --git a/llarp/util/logging/syslog_logger.cpp b/llarp/util/logging/syslog_logger.cpp index 7ce3b533f..c9ff0c45b 100644 --- a/llarp/util/logging/syslog_logger.cpp +++ b/llarp/util/logging/syslog_logger.cpp @@ -23,6 +23,7 @@ namespace llarp { case eLogNone: return; + case eLogTrace: case eLogDebug: ::syslog(LOG_DEBUG, "%s", msg.c_str()); return; diff --git a/llarp/util/logging/win32_logger.cpp b/llarp/util/logging/win32_logger.cpp index 65e359804..e5e7eecac 100644 --- a/llarp/util/logging/win32_logger.cpp +++ b/llarp/util/logging/win32_logger.cpp @@ -34,6 +34,8 @@ namespace llarp { case eLogNone: break; + case eLogTrace: + ss << "[TRC] "; case eLogDebug: ss << "[DBG] "; break; diff --git a/llarp/util/lokinet_init.c b/llarp/util/lokinet_init.c new file mode 100644 index 000000000..34be28086 --- /dev/null +++ b/llarp/util/lokinet_init.c @@ -0,0 +1,35 @@ +#include +#if defined(_WIN32) +#include +#include +#include + +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 diff --git a/llarp/util/lokinet_init.h b/llarp/util/lokinet_init.h new file mode 100644 index 000000000..d63cdba2a --- /dev/null +++ b/llarp/util/lokinet_init.h @@ -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 \ No newline at end of file diff --git a/llarp/util/thread/logic.cpp b/llarp/util/thread/logic.cpp index d3fd3bad9..55da1ec1a 100644 --- a/llarp/util/thread/logic.cpp +++ b/llarp/util/thread/logic.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include @@ -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) { +#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()) + { + METRIC("fired"); + f(); + return true; + } if(m_Thread->LooksFull(5)) { - LogWarn( - "holy crap, we are trying to queue a job onto the logic thread but " - "it looks full"); - 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); - return true; - } + 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 diff --git a/llarp/util/thread/logic.hpp b/llarp/util/thread/logic.hpp index bd8dbcb61..721922d6f 100644 --- a/llarp/util/thread/logic.hpp +++ b/llarp/util/thread/logic.hpp @@ -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 diff --git a/llarp/util/thread/threading.hpp b/llarp/util/thread/threading.hpp index 960acc917..6e2ef8da2 100644 --- a/llarp/util/thread/threading.hpp +++ b/llarp/util/thread/threading.hpp @@ -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 diff --git a/llarp/util/thread/threadpool.cpp b/llarp/util/thread/threadpool.cpp index 715271cec..ead887723 100644 --- a/llarp/util/thread/threadpool.cpp +++ b/llarp/util/thread/threadpool.cpp @@ -8,11 +8,11 @@ #include 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 diff --git a/llarp/util/thread/threadpool.h b/llarp/util/thread/threadpool.h index 43936222f..bc180a11f 100644 --- a/llarp/util/thread/threadpool.h +++ b/llarp/util/thread/threadpool.h @@ -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); diff --git a/llarp/util/thread/timer.cpp b/llarp/util/thread/timer.cpp index ebf4e6d12..bcd4cb1ce 100644 --- a/llarp/util/thread/timer.cpp +++ b/llarp/util/thread/timer.cpp @@ -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) { diff --git a/readme.md b/readme.md index 82f8816db..54c0bdf1a 100644 --- a/readme.md +++ b/readme.md @@ -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 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b7feec249..37ebcec9f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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 diff --git a/test/crypto/mock_crypto.hpp b/test/crypto/mock_crypto.hpp index be0151528..dee621502 100644 --- a/test/crypto/mock_crypto.hpp +++ b/test/crypto/mock_crypto.hpp @@ -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 diff --git a/test/link/test_llarp_link.cpp b/test/link/test_llarp_link.cpp index ab4c9d181..f329fe2f9 100644 --- a/test/link/test_llarp_link.cpp +++ b/test/link/test_llarp_link.cpp @@ -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()); diff --git a/test/net/test_llarp_net.cpp b/test/net/test_llarp_net.cpp index 564ae524c..44472d60a 100644 --- a/test/net/test_llarp_net.cpp +++ b/test/net/test_llarp_net.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include diff --git a/test/net/test_llarp_net_inaddr.cpp b/test/net/test_llarp_net_inaddr.cpp deleted file mode 100644 index 43c7387e5..000000000 --- a/test/net/test_llarp_net_inaddr.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include - -#include - -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); -} diff --git a/ui-win32/Properties/AssemblyInfo.cs b/ui-win32/Properties/AssemblyInfo.cs index d09b6bde3..0d4c77e78 100644 --- a/ui-win32/Properties/AssemblyInfo.cs +++ b/ui-win32/Properties/AssemblyInfo.cs @@ -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 \ No newline at end of file diff --git a/ui-win32/dlgBootstrap.Designer.cs b/ui-win32/dlgBootstrap.Designer.cs index fffb1caf9..af6f80780 100644 --- a/ui-win32/dlgBootstrap.Designer.cs +++ b/ui-win32/dlgBootstrap.Designer.cs @@ -28,66 +28,66 @@ /// private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(dlgBootstrap)); - this.label1 = new System.Windows.Forms.Label(); - this.uriBox = new System.Windows.Forms.TextBox(); - this.label2 = new System.Windows.Forms.Label(); - this.btnDownload = new System.Windows.Forms.Button(); - this.btnCancel = new System.Windows.Forms.Button(); - this.SuspendLayout(); - // - // label1 - // - resources.ApplyResources(this.label1, "label1"); - this.label1.Name = "label1"; - // - // uriBox - // - resources.ApplyResources(this.uriBox, "uriBox"); - this.uriBox.Name = "uriBox"; - // - // label2 - // - resources.ApplyResources(this.label2, "label2"); - this.label2.Name = "label2"; - // - // btnDownload - // - resources.ApplyResources(this.btnDownload, "btnDownload"); - this.btnDownload.DialogResult = System.Windows.Forms.DialogResult.OK; - this.btnDownload.Name = "btnDownload"; - this.btnDownload.UseVisualStyleBackColor = true; - this.btnDownload.Click += new System.EventHandler(this.button1_Click); - // - // btnCancel - // - resources.ApplyResources(this.btnCancel, "btnCancel"); - this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.btnCancel.Name = "btnCancel"; - this.btnCancel.UseVisualStyleBackColor = true; - this.btnCancel.Click += new System.EventHandler(this.button1_Click_1); - // - // bootstrap - // - this.AcceptButton = this.btnDownload; - resources.ApplyResources(this, "$this"); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.CancelButton = this.btnCancel; - this.ControlBox = false; - this.Controls.Add(this.btnCancel); - this.Controls.Add(this.btnDownload); - this.Controls.Add(this.label2); - this.Controls.Add(this.uriBox); - this.Controls.Add(this.label1); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "bootstrap"; - this.ShowIcon = false; - this.ShowInTaskbar = false; - this.ResumeLayout(false); - this.PerformLayout(); - + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(dlgBootstrap)); + this.label1 = new System.Windows.Forms.Label(); + this.uriBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.btnDownload = new System.Windows.Forms.Button(); + this.btnCancel = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // uriBox + // + resources.ApplyResources(this.uriBox, "uriBox"); + this.uriBox.Name = "uriBox"; + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // btnDownload + // + resources.ApplyResources(this.btnDownload, "btnDownload"); + this.btnDownload.DialogResult = System.Windows.Forms.DialogResult.OK; + this.btnDownload.Name = "btnDownload"; + this.btnDownload.UseVisualStyleBackColor = true; + this.btnDownload.Click += new System.EventHandler(this.button1_Click); + // + // btnCancel + // + resources.ApplyResources(this.btnCancel, "btnCancel"); + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Name = "btnCancel"; + this.btnCancel.UseVisualStyleBackColor = true; + this.btnCancel.Click += new System.EventHandler(this.button1_Click_1); + // + // dlgBootstrap + // + this.AcceptButton = this.btnDownload; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.btnCancel; + this.ControlBox = false; + this.Controls.Add(this.btnCancel); + this.Controls.Add(this.btnDownload); + this.Controls.Add(this.label2); + this.Controls.Add(this.uriBox); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "dlgBootstrap"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.ResumeLayout(false); + this.PerformLayout(); + } #endregion diff --git a/ui-win32/dlgBootstrap.resx b/ui-win32/dlgBootstrap.resx index a686f5f4e..eab9d99c3 100644 --- a/ui-win32/dlgBootstrap.resx +++ b/ui-win32/dlgBootstrap.resx @@ -1,276 +1,279 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - True - - - - 13, 13 - - - 196, 13 - - - 0 - - - Enter a URI to a node to bootstrap from: - - - label1 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 4 - - - - Left, Right - - - 12, 29 - - - 520, 20 - - - 1 - - - uriBox - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 3 - - - True - - - 12, 52 - - - 347, 13 - - - 2 - - - This file is automatically saved as $APPDATA\.lokinet\bootstrap.signed. - - - label2 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 2 - - - Bottom - - - 196, 75 - - - 75, 23 - - - 3 - - - OK - - - btnDownload - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 1 - - - Bottom - - - 278, 75 - - - 75, 23 - - - 4 - - - Cancel - - - btnCancel - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 0 - - - True - - - 6, 13 - - - 548, 111 - - - CenterParent - - - bootstrap from web... - - - bootstrap - - - System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + + 13, 13 + + + 196, 13 + + + 0 + + + Enter a URI to a node to bootstrap from: + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + + Left, Right + + + 12, 29 + + + 520, 20 + + + 1 + + + https://seed.lokinet.org/bootstrap.signed + + + uriBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + True + + + 12, 52 + + + 347, 13 + + + 2 + + + This file is automatically saved as $APPDATA\.lokinet\bootstrap.signed. + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + Bottom + + + 196, 75 + + + 75, 23 + + + 3 + + + OK + + + btnDownload + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Bottom + + + 278, 75 + + + 75, 23 + + + 4 + + + Cancel + + + btnCancel + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 6, 13 + + + 548, 111 + + + CenterParent + + + bootstrap from web... + + + dlgBootstrap + + + System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file