From 2188b443e943456f431cdd74ef6d8b62627b212b Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 2 Apr 2021 12:08:06 -0400 Subject: [PATCH] more liblokinet api stuff * add lokinet_wait_for_ready to wait until we have published introsets and such * optionally expose ports in lnproxy * dont save profiles by default --- contrib/py/lnproxy/lnproxy/__main__.py | 35 +++++++++++++++++----- include/lokinet.h | 6 ++++ llarp/config/config.cpp | 9 ++++++ llarp/config/config.hpp | 1 + llarp/lokinet_shared.cpp | 41 +++++++++++++++++++++----- llarp/router/router.cpp | 2 +- 6 files changed, 79 insertions(+), 15 deletions(-) diff --git a/contrib/py/lnproxy/lnproxy/__main__.py b/contrib/py/lnproxy/lnproxy/__main__.py index 81e42c01c..d55f47bfe 100644 --- a/contrib/py/lnproxy/lnproxy/__main__.py +++ b/contrib/py/lnproxy/lnproxy/__main__.py @@ -39,7 +39,7 @@ class Context: wrapper around liblokinet """ - def __init__(self): + def __init__(self, debug=False): self._ln = ctypes.CDLL(find_library("lokinet")) self._c = ctypes.CDLL(find_library("c")) self._ln.lokinet_context_new.restype = ctypes.POINTER(LNContext) @@ -49,6 +49,7 @@ class Context: self._ln.lokinet_outbound_stream.argtypes = (ctypes.POINTER(ResultStruct), ctypes.c_char_p, ctypes.c_char_p, ctypes.POINTER(LNContext)) self._ctx = self._ln.lokinet_context_new() self._addrmap = dict() + self._debug = debug def free(self, ptr): self._c.free(ptr) @@ -58,6 +59,9 @@ class Context: ptrlen = ctypes.c_size_t(len(data)) return self.ln_call("lokinet_add_bootstrap_rc", ptr, ptrlen) + def wait_for_ready(self, ms): + return self.ln_call("lokinet_wait_for_ready", ms) == 0 + def addr(self): return self._ln.lokinet_address(self._ctx).decode('ascii') @@ -66,9 +70,15 @@ class Context: def ln_call(self, funcname, *args): args += (self._ctx,) - print("call {}{}".format(funcname, args)) + if self._debug: + print("call {}{}".format(funcname, args)) return self._ln[funcname](*args) + def expose(self, port): + port = int(port) + print("exposing loopback port: {}".format(port)) + return self.ln_call("lokinet_inbound_stream", port) + def start(self): return self.ln_call("lokinet_context_start") @@ -145,8 +155,10 @@ class Handler(BaseHandler): ctx.putAddr(host, result) sock = socket.socket() - sock.connect(ctx.getAddr(host)) - if not sock: + try: + sock.connect(ctx.getAddr(host)) + except: + self.delAddr(host) self.send_error(504) return @@ -177,6 +189,7 @@ from argparse import ArgumentParser as AP ap = AP() ap.add_argument("--ip", type=str, help="ip to bind to", default="127.0.0.1") ap.add_argument("--port", type=int, help="port to bind to", default=3000) +ap.add_argument("--expose", type=int, help="expose a port to loopback") ap.add_argument("--bootstrap", type=str, help="bootstrap file", default="bootstrap.signed") if bootstrapFromURL: ap.add_argument("--bootstrap-url", type=str, help="bootstrap from remote url", default="https://seed.lokinet.org/lokinet.signed") @@ -203,11 +216,19 @@ if ctx.start() != 0: ctx.stop() sys.exit(-1) -id = ctx.expose(80) -print("we are {}".format(ctx.addr())) +id = None + try: + while not ctx.wait_for_ready(1000): + print("waiting for lokinet...") + lokiaddr = ctx.addr() + print("we are {}".format(lokiaddr)) + if args.expose: + id = ctx.expose(args.expose) + print("exposed {}:{}".format(lokiaddr, args.expose)) print("serving on {}:{}".format(*addr)) server.serve_forever() finally: - ctx.ln_call("lokinet_close_stream", id) + if id is not None: + ctx.ln_call("lokinet_close_stream", id) ctx.stop() diff --git a/include/lokinet.h b/include/lokinet.h index 0c1b6933e..b8aceab04 100644 --- a/include/lokinet.h +++ b/include/lokinet.h @@ -32,6 +32,12 @@ extern "C" int lokinet_context_start(struct lokinet_context*); + /// wait at most N milliseconds for lokinet to build paths and get ready + /// return 0 if we are ready + /// return nonzero if we are not ready + int + lokinet_wait_for_ready(int N, struct lokinet_context*); + /// stop all operations on this lokinet context void lokinet_context_stop(struct lokinet_context*); diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 8ffae4ba0..ba932c4c1 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -259,6 +259,7 @@ namespace llarp (void)params; static constexpr Default ProfilingValueDefault{true}; + static constexpr Default SaveProfilesDefault{true}; static constexpr Default ReachableDefault{true}; static constexpr Default HopsDefault{4}; static constexpr Default PathsDefault{6}; @@ -267,6 +268,13 @@ namespace llarp conf.defineOption( "network", "type", Default{"tun"}, Hidden, AssignmentAcceptor(m_endpointType)); + conf.defineOption( + "network", + "save-profiles", + SaveProfilesDefault, + Hidden, + AssignmentAcceptor(m_saveProfiles)); + conf.defineOption( "network", "profiling", @@ -1361,6 +1369,7 @@ namespace llarp config->logging.m_logLevel = eLogNone; config->api.m_enableRPCServer = false; config->network.m_endpointType = "null"; + config->network.m_saveProfiles = false; config->bootstrap.files.clear(); return config; } diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index e9dcc2bb5..96d0420a1 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -93,6 +93,7 @@ namespace llarp struct NetworkConfig { std::optional m_enableProfiling; + bool m_saveProfiles; std::string m_strictConnect; std::string m_ifname; IPRange m_ifaddr; diff --git a/llarp/lokinet_shared.cpp b/llarp/lokinet_shared.cpp index ab6edc029..814c751e9 100644 --- a/llarp/lokinet_shared.cpp +++ b/llarp/lokinet_shared.cpp @@ -51,6 +51,12 @@ struct lokinet_context return std::unique_lock{m_access}; } + [[nodiscard]] auto + endpoint() const + { + return impl->router->hiddenServiceContext().GetEndpointByName("default"); + } + std::unordered_map streams; void @@ -138,7 +144,7 @@ extern "C" if (not ctx) return nullptr; auto lock = ctx->acquire(); - auto ep = ctx->impl->router->hiddenServiceContext().GetEndpointByName("default"); + auto ep = ctx->endpoint(); const auto addr = ep->GetIdentity().pub.Addr(); const auto addrStr = addr.ToString(); return strdup(addrStr.c_str()); @@ -203,11 +209,32 @@ extern "C" { if (ctx->impl->IsStopping()) return -1; - std::this_thread::sleep_for(5ms); + std::this_thread::sleep_for(50ms); } return 0; } + int + lokinet_wait_for_ready(int ms, struct lokinet_context* ctx) + { + if (ctx == nullptr) + return -1; + auto lock = ctx->acquire(); + auto ep = ctx->endpoint(); + int iterations = ms / 10; + if (iterations <= 0) + { + ms = 10; + iterations = 1; + } + while (not ep->IsReady() and iterations > 0) + { + std::this_thread::sleep_for(std::chrono::milliseconds{ms / 10}); + iterations--; + } + return ep->IsReady() ? 0 : -1; + } + void lokinet_context_stop(struct lokinet_context* ctx) { @@ -286,7 +313,7 @@ extern "C" remoteport, endpoint, localAddr]() { - auto ep = router->hiddenServiceContext().GetEndpointByName(endpoint); + auto ep = ctx->endpoint(); if (ep == nullptr) { stream_error(result, ENOTSUP); @@ -375,8 +402,8 @@ extern "C" return -1; } - ctx->impl->CallSafe([router = ctx->impl->router, acceptFilter, user, &promise]() { - auto ep = router->hiddenServiceContext().GetEndpointByName("default"); + ctx->impl->CallSafe([ctx, acceptFilter, user, &promise]() { + auto ep = ctx->endpoint(); auto* quic = ep->GetQUICTunnel(); auto id = quic->listen( [acceptFilter, user](auto remoteAddr, auto port) -> std::optional { @@ -417,8 +444,8 @@ extern "C" { std::promise promise; bool inbound = ctx->streams.at(stream_id); - ctx->impl->CallSafe([stream_id, inbound, router = ctx->impl->router, &promise]() { - auto ep = router->hiddenServiceContext().GetEndpointByName("default"); + ctx->impl->CallSafe([stream_id, inbound, ctx, &promise]() { + auto ep = ctx->endpoint(); auto* quic = ep->GetQUICTunnel(); try { diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 3f5844a69..822dbf3ba 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -876,7 +876,7 @@ namespace llarp _exitContext.Tick(now); // save profiles - if (routerProfiling().ShouldSave(now)) + if (routerProfiling().ShouldSave(now) and m_Config->network.m_saveProfiles) { QueueDiskIO([&]() { routerProfiling().Save(_profilesFile); }); }