mirror of
https://github.com/oxen-io/lokinet
synced 2023-12-14 06:53:00 +01:00
Merge branch 'dev' into private-keys-backup-support
This commit is contained in:
commit
93b8832026
88 changed files with 1424 additions and 1138 deletions
|
@ -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)
|
||||
|
||||
|
|
2
Makefile
2
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
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <config/config.hpp> // for ensure_config
|
||||
#include <constants/version.hpp>
|
||||
#include <llarp.h>
|
||||
#include <util/lokinet_init.h>
|
||||
#include <util/fs.hpp>
|
||||
#include <util/logging/logger.hpp>
|
||||
#include <util/logging/ostream_logger.hpp>
|
||||
|
@ -83,6 +84,11 @@ run_main_context(std::string conffname, llarp_main_runtime_opts opts)
|
|||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
auto result = Lokinet_INIT();
|
||||
if(result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
llarp_main_runtime_opts opts;
|
||||
const char *singleThreadVar = getenv("LLARP_SHADOW");
|
||||
if(singleThreadVar && std::string(singleThreadVar) == "1")
|
||||
|
|
|
@ -39,7 +39,7 @@ struct DemoCall : public abyss::http::IRPCClientHandler
|
|||
bool HandleResponse(abyss::http::RPC_Response) override
|
||||
{
|
||||
llarp::LogInfo("response get");
|
||||
m_Logic->queue_func([=]() { m_Callback(); });
|
||||
LogicCall(m_Logic, m_Callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ set(LIB_UTIL_SRC
|
|||
util/logging/ostream_logger.cpp
|
||||
util/logging/syslog_logger.cpp
|
||||
util/logging/win32_logger.cpp
|
||||
util/lokinet_init.c
|
||||
util/mem.cpp
|
||||
util/meta/memfn_traits.cpp
|
||||
util/meta/memfn.cpp
|
||||
|
@ -83,7 +84,6 @@ set(LIB_PLATFORM_SRC
|
|||
net/ip.cpp
|
||||
net/net.cpp
|
||||
net/net_addr.cpp
|
||||
net/net_inaddr.cpp
|
||||
net/net_int.cpp
|
||||
# for android shim
|
||||
${ANDROID_PLATFORM_SRC}
|
||||
|
@ -254,7 +254,8 @@ if(TESTNET)
|
|||
endif()
|
||||
|
||||
add_library(${STATIC_LIB} STATIC ${LIB_SRC})
|
||||
target_link_libraries(${STATIC_LIB} PUBLIC cxxopts ${ABYSS_LIB} ${PLATFORM_LIB} ${UTIL_LIB} ${CRYPTOGRAPHY_LIB} ${FS_LIB})
|
||||
target_include_directories(${STATIC_LIB} PUBLIC ${CURL_INCLUDE_DIRS})
|
||||
target_link_libraries(${STATIC_LIB} PUBLIC cxxopts ${ABYSS_LIB} ${PLATFORM_LIB} ${UTIL_LIB} ${CRYPTOGRAPHY_LIB} ${FS_LIB} ${CURL_LIBRARIES})
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
target_include_directories(${PLATFORM_LIB} SYSTEM PUBLIC /usr/local/include)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <util/mem.hpp>
|
||||
#include <util/meta/memfn.hpp>
|
||||
#include <util/str.hpp>
|
||||
#include <util/lokinet_init.h>
|
||||
|
||||
#include <absl/strings/strip.h>
|
||||
|
||||
|
@ -51,6 +52,15 @@ namespace llarp
|
|||
void
|
||||
RouterConfig::fromSection(string_view key, string_view val)
|
||||
{
|
||||
if(key == "job-queue-size")
|
||||
{
|
||||
auto sval = svtoi(val);
|
||||
if(sval >= 1024)
|
||||
{
|
||||
m_JobQueueSize = sval;
|
||||
LogInfo("Set job queue size to ", m_JobQueueSize);
|
||||
}
|
||||
}
|
||||
if(key == "default-protocol")
|
||||
{
|
||||
m_DefaultLinkProto = tostr(val);
|
||||
|
@ -459,6 +469,8 @@ namespace llarp
|
|||
bool
|
||||
Config::parse(const ConfigParser &parser)
|
||||
{
|
||||
if(Lokinet_INIT())
|
||||
return false;
|
||||
router = find_section< RouterConfig >(parser, "router");
|
||||
network = find_section< NetworkConfig >(parser, "network");
|
||||
connect = find_section< ConnectConfig >(parser, "connect");
|
||||
|
@ -500,6 +512,8 @@ extern "C" bool
|
|||
llarp_ensure_config(const char *fname, const char *basedir, bool overwrite,
|
||||
bool asRouter)
|
||||
{
|
||||
if(Lokinet_INIT())
|
||||
return false;
|
||||
std::error_code ec;
|
||||
if(fs::exists(fname, ec) && !overwrite)
|
||||
{
|
||||
|
|
|
@ -121,10 +121,13 @@ namespace llarp
|
|||
int m_workerThreads = 1;
|
||||
int m_numNetThreads = 1;
|
||||
|
||||
size_t m_JobQueueSize = size_t{1024 * 8};
|
||||
|
||||
std::string m_DefaultLinkProto = "iwp";
|
||||
|
||||
public:
|
||||
// clang-format off
|
||||
size_t jobQueueSize() const { return fromEnv(m_JobQueueSize, "JOB_QUEUE_SIZE"); }
|
||||
size_t minConnectedRouters() const { return fromEnv(m_minConnectedRouters, "MIN_CONNECTED_ROUTERS"); }
|
||||
size_t maxConnectedRouters() const { return fromEnv(m_maxConnectedRouters, "MAX_CONNECTED_ROUTERS"); }
|
||||
std::string encryptionKeyfile() const { return fromEnv(m_encryptionKeyfile, "ENCRYPTION_KEYFILE"); }
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace llarp
|
|||
bool
|
||||
Context::CallSafe(std::function< void(void) > f)
|
||||
{
|
||||
return logic && logic->queue_func(std::move(f));
|
||||
return logic && LogicCall(logic, f);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -51,7 +51,6 @@ namespace llarp
|
|||
bool
|
||||
Context::Configure()
|
||||
{
|
||||
logic = std::make_shared< Logic >();
|
||||
// llarp::LogInfo("loading config at ", configfile);
|
||||
if(configfile.size())
|
||||
{
|
||||
|
@ -73,6 +72,10 @@ namespace llarp
|
|||
threads = 1;
|
||||
worker = std::make_shared< llarp::thread::ThreadPool >(threads, 1024,
|
||||
"llarp-worker");
|
||||
auto jobQueueSize = config->router.jobQueueSize();
|
||||
if(jobQueueSize < 1024)
|
||||
jobQueueSize = 1024;
|
||||
logic = std::make_shared< Logic >(jobQueueSize);
|
||||
|
||||
nodedb_dir = config->netdb.nodedbDir();
|
||||
|
||||
|
@ -482,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
|
||||
|
|
|
@ -87,6 +87,9 @@ namespace llarp
|
|||
/// post quantum encrypt (buffer, sharedkey_dst, pub)
|
||||
virtual bool
|
||||
pqe_encrypt(PQCipherBlock &, SharedSecret &, const PQPubKey &) = 0;
|
||||
|
||||
virtual bool
|
||||
check_identity_privkey(const SecretKey &) = 0;
|
||||
};
|
||||
|
||||
inline Crypto::~Crypto() = default;
|
||||
|
|
|
@ -214,6 +214,19 @@ namespace llarp
|
|||
(void)sk_pk;
|
||||
}
|
||||
|
||||
bool
|
||||
CryptoLibSodium::check_identity_privkey(const llarp::SecretKey &keys)
|
||||
{
|
||||
AlignedBuffer< crypto_sign_SEEDBYTES > seed;
|
||||
llarp::PubKey pk;
|
||||
llarp::SecretKey sk;
|
||||
if(crypto_sign_ed25519_sk_to_seed(seed.data(), keys.data()) == -1)
|
||||
return false;
|
||||
if(crypto_sign_seed_keypair(pk.data(), sk.data(), seed.data()) == -1)
|
||||
return false;
|
||||
return keys.toPublic() == pk && sk == keys;
|
||||
}
|
||||
|
||||
void
|
||||
CryptoLibSodium::encryption_keygen(llarp::SecretKey &keys)
|
||||
{
|
||||
|
|
|
@ -79,6 +79,9 @@ namespace llarp
|
|||
/// post quantum encrypt (buffer, sharedkey_dst, pub)
|
||||
bool
|
||||
pqe_encrypt(PQCipherBlock &, SharedSecret &, const PQPubKey &) override;
|
||||
|
||||
bool
|
||||
check_identity_privkey(const SecretKey &) override;
|
||||
};
|
||||
} // namespace sodium
|
||||
|
||||
|
|
|
@ -180,6 +180,12 @@ namespace llarp
|
|||
std::copy_n(secret.begin(), SharedSecret::SIZE, block.begin());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
check_identity_privkey(const SecretKey &) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
|
|
|
@ -58,20 +58,17 @@ namespace llarp
|
|||
using User_ptr = std::shared_ptr< User >;
|
||||
using DecryptHandler = std::function< void(llarp_buffer_t*, User_ptr) >;
|
||||
|
||||
static void
|
||||
Decrypt(void* user)
|
||||
void
|
||||
Decrypt(User_ptr user)
|
||||
{
|
||||
auto* ctx = static_cast< AsyncFrameDecrypter< User >* >(user);
|
||||
|
||||
if(ctx->target.DecryptInPlace(ctx->seckey))
|
||||
if(target.DecryptInPlace(seckey))
|
||||
{
|
||||
auto buf = ctx->target.Buffer();
|
||||
auto buf = target.Buffer();
|
||||
buf->cur = buf->base + EncryptedFrameOverheadSize;
|
||||
ctx->result(buf, ctx->user);
|
||||
result(buf, user);
|
||||
}
|
||||
else
|
||||
ctx->result(nullptr, ctx->user);
|
||||
ctx->user = nullptr;
|
||||
result(nullptr, user);
|
||||
}
|
||||
|
||||
AsyncFrameDecrypter(const SecretKey& secretkey, DecryptHandler h)
|
||||
|
@ -80,7 +77,6 @@ namespace llarp
|
|||
}
|
||||
|
||||
DecryptHandler result;
|
||||
User_ptr user;
|
||||
const SecretKey& seckey;
|
||||
EncryptedFrame target;
|
||||
|
||||
|
@ -89,8 +85,8 @@ namespace llarp
|
|||
const EncryptedFrame& frame, User_ptr u)
|
||||
{
|
||||
target = frame;
|
||||
user = u;
|
||||
worker->addJob(std::bind(&Decrypt, this));
|
||||
worker->addJob(
|
||||
[self = this, user = std::move(u)]() { self->Decrypt(user); });
|
||||
}
|
||||
};
|
||||
} // namespace llarp
|
||||
|
|
|
@ -199,14 +199,14 @@ namespace llarp
|
|||
PutRCNodeAsync(const RCNode& val) override
|
||||
{
|
||||
auto func = std::bind(&Bucket< RCNode >::PutNode, Nodes(), val);
|
||||
router->logic()->queue_func(func);
|
||||
LogicCall(router->logic(), func);
|
||||
}
|
||||
|
||||
void
|
||||
DelRCNodeAsync(const Key_t& val) override
|
||||
{
|
||||
auto func = std::bind(&Bucket< RCNode >::DelNode, Nodes(), val);
|
||||
router->logic()->queue_func(func);
|
||||
LogicCall(router->logic(), func);
|
||||
}
|
||||
|
||||
const Key_t&
|
||||
|
|
|
@ -39,10 +39,10 @@ namespace llarp
|
|||
m_Resolvers = resolvers;
|
||||
const llarp::Addr any("0.0.0.0", 0);
|
||||
auto self = shared_from_this();
|
||||
m_ClientLogic->queue_func([=]() {
|
||||
LogicCall(m_ClientLogic, [=]() {
|
||||
llarp_ev_add_udp(self->m_ClientLoop.get(), &self->m_Client, any);
|
||||
});
|
||||
m_ServerLogic->queue_func([=]() {
|
||||
LogicCall(m_ServerLogic, [=]() {
|
||||
llarp_ev_add_udp(self->m_ServerLoop.get(), &self->m_Server, addr);
|
||||
});
|
||||
return true;
|
||||
|
@ -65,8 +65,9 @@ namespace llarp
|
|||
auto self = static_cast< Proxy* >(u->user)->shared_from_this();
|
||||
// yes we use the server loop here because if the server loop is not the
|
||||
// client loop we'll crash again
|
||||
self->m_ServerLogic->queue_func(
|
||||
[self, addr, msgbuf]() { self->HandlePktServer(addr, msgbuf); });
|
||||
LogicCall(self->m_ServerLogic, [self, addr, msgbuf]() {
|
||||
self->HandlePktServer(addr, msgbuf);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -76,8 +77,9 @@ namespace llarp
|
|||
const llarp::Addr addr(*from);
|
||||
Buffer_t msgbuf = CopyBuffer(buf.underlying);
|
||||
auto self = static_cast< Proxy* >(u->user)->shared_from_this();
|
||||
self->m_ServerLogic->queue_func(
|
||||
[self, addr, msgbuf]() { self->HandlePktClient(addr, msgbuf); });
|
||||
LogicCall(self->m_ServerLogic, [self, addr, msgbuf]() {
|
||||
self->HandlePktClient(addr, msgbuf);
|
||||
});
|
||||
}
|
||||
|
||||
llarp::Addr
|
||||
|
@ -100,7 +102,7 @@ namespace llarp
|
|||
Proxy::SendServerMessageTo(llarp::Addr to, Message msg)
|
||||
{
|
||||
auto self = shared_from_this();
|
||||
m_ServerLogic->queue_func([to, msg, self]() {
|
||||
LogicCall(m_ServerLogic, [to, msg, self]() {
|
||||
std::array< byte_t, 1500 > tmp = {{0}};
|
||||
llarp_buffer_t buf(tmp);
|
||||
if(msg.Encode(&buf))
|
||||
|
@ -118,7 +120,7 @@ namespace llarp
|
|||
Proxy::SendClientMessageTo(llarp::Addr to, Message msg)
|
||||
{
|
||||
auto self = shared_from_this();
|
||||
m_ClientLogic->queue_func([to, msg, self]() {
|
||||
LogicCall(m_ClientLogic, [to, msg, self]() {
|
||||
std::array< byte_t, 1500 > tmp = {{0}};
|
||||
llarp_buffer_t buf(tmp);
|
||||
if(msg.Encode(&buf))
|
||||
|
@ -151,7 +153,7 @@ namespace llarp
|
|||
|
||||
const Addr requester = itr->second;
|
||||
auto self = shared_from_this();
|
||||
m_ServerLogic->queue_func([=]() {
|
||||
LogicCall(m_ServerLogic, [=]() {
|
||||
// forward reply to requester via server
|
||||
const llarp_buffer_t tmpbuf(buf);
|
||||
llarp_ev_udp_sendto(&self->m_Server, requester, tmpbuf);
|
||||
|
@ -222,7 +224,7 @@ namespace llarp
|
|||
// new forwarded query
|
||||
tx.from = PickRandomResolver();
|
||||
m_Forwarded[tx] = from;
|
||||
m_ClientLogic->queue_func([=] {
|
||||
LogicCall(m_ClientLogic, [=] {
|
||||
// do query
|
||||
const llarp_buffer_t tmpbuf(buf);
|
||||
llarp_ev_udp_sendto(&self->m_Client, tx.from, tmpbuf);
|
||||
|
@ -232,7 +234,7 @@ namespace llarp
|
|||
{
|
||||
// send the query again because it's probably FEC from the requester
|
||||
const auto resolver = itr->first.from;
|
||||
m_ClientLogic->queue_func([=] {
|
||||
LogicCall(m_ClientLogic, [=] {
|
||||
// send it
|
||||
const llarp_buffer_t tmpbuf(buf);
|
||||
llarp_ev_udp_sendto(&self->m_Client, resolver, tmpbuf);
|
||||
|
|
|
@ -40,7 +40,7 @@ typedef SSIZE_T ssize_t;
|
|||
* event handler (cross platform high performance event system for IO)
|
||||
*/
|
||||
|
||||
#define EV_TICK_INTERVAL 100
|
||||
#define EV_TICK_INTERVAL 10
|
||||
|
||||
// forward declare
|
||||
struct llarp_threadpool;
|
||||
|
|
|
@ -7,13 +7,8 @@
|
|||
|
||||
namespace libuv
|
||||
{
|
||||
/// call a function in logic thread via a handle
|
||||
template < typename Handle, typename Func >
|
||||
void
|
||||
Call(Handle* h, Func&& f)
|
||||
{
|
||||
static_cast< Loop* >(h->loop->data)->Call(f);
|
||||
}
|
||||
#define LoopCall(h, ...) \
|
||||
LogicCall(static_cast< Loop* >((h)->loop->data)->m_Logic, __VA_ARGS__)
|
||||
|
||||
struct glue
|
||||
{
|
||||
|
@ -110,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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,19 +92,17 @@ namespace libuv
|
|||
m_Logic = l;
|
||||
}
|
||||
|
||||
/// call function in logic thread
|
||||
template < typename F >
|
||||
void
|
||||
Call(F f)
|
||||
{
|
||||
m_Logic->queue_func(f);
|
||||
}
|
||||
std::shared_ptr< llarp::Logic > m_Logic;
|
||||
|
||||
private:
|
||||
uv_loop_t m_Impl;
|
||||
uv_timer_t m_TickTimer;
|
||||
std::atomic< bool > m_Run;
|
||||
std::shared_ptr< llarp::Logic > m_Logic;
|
||||
|
||||
#ifdef LOKINET_DEBUG
|
||||
uint64_t last_time;
|
||||
uint64_t loop_run_count;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace libuv
|
||||
|
|
|
@ -144,7 +144,7 @@ tun_ev_loop(void* unused)
|
|||
while(true)
|
||||
{
|
||||
alert =
|
||||
GetQueuedCompletionStatus(tun_event_queue, &size, &listener, &ovl, 100);
|
||||
GetQueuedCompletionStatus(tun_event_queue, &size, &listener, &ovl, EV_TICK_INTERVAL);
|
||||
|
||||
if(!alert)
|
||||
{
|
||||
|
@ -727,7 +727,7 @@ llarp_win32_loop::tick_listeners()
|
|||
{
|
||||
llarp_ev_loop::tick_listeners();
|
||||
for(auto& func : m_Tickers)
|
||||
m_Logic->queue_func([func]() { func(); });
|
||||
LogicCall(m_Logic, func);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -16,14 +16,20 @@ namespace llarp
|
|||
static void
|
||||
ExitHandlerRecvPkt(llarp_tun_io *tun, const llarp_buffer_t &buf)
|
||||
{
|
||||
static_cast< ExitEndpoint * >(tun->user)->OnInetPacket(buf);
|
||||
std::vector< byte_t > pkt;
|
||||
pkt.resize(buf.sz);
|
||||
std::copy_n(buf.base, buf.sz, pkt.data());
|
||||
auto self = static_cast< ExitEndpoint * >(tun->user);
|
||||
LogicCall(self->GetRouter()->logic(), [self, pktbuf = std::move(pkt)]() {
|
||||
self->OnInetPacket(std::move(pktbuf));
|
||||
});
|
||||
}
|
||||
|
||||
static void
|
||||
ExitHandlerFlush(llarp_tun_io *tun)
|
||||
{
|
||||
auto *ep = static_cast< ExitEndpoint * >(tun->user);
|
||||
ep->GetRouter()->logic()->queue_func(std::bind(&ExitEndpoint::Flush, ep));
|
||||
LogicCall(ep->GetRouter()->logic(), std::bind(&ExitEndpoint::Flush, ep));
|
||||
}
|
||||
|
||||
ExitEndpoint::ExitEndpoint(const std::string &name, AbstractRouter *r)
|
||||
|
@ -457,10 +463,13 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
ExitEndpoint::OnInetPacket(const llarp_buffer_t &buf)
|
||||
ExitEndpoint::OnInetPacket(std::vector< byte_t > buf)
|
||||
{
|
||||
const llarp_buffer_t buffer(buf);
|
||||
m_InetToNetwork.EmplaceIf(
|
||||
[b = ManagedBuffer(buf)](Pkt_t &pkt) -> bool { return pkt.Load(b); });
|
||||
[b = ManagedBuffer(buffer)](Pkt_t &pkt) -> bool {
|
||||
return pkt.Load(b);
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace llarp
|
|||
|
||||
/// handle ip packet from outside
|
||||
void
|
||||
OnInetPacket(const llarp_buffer_t& buf);
|
||||
OnInetPacket(std::vector< byte_t > buf);
|
||||
|
||||
AbstractRouter*
|
||||
GetRouter();
|
||||
|
|
|
@ -32,11 +32,23 @@ namespace llarp
|
|||
m_NetworkToUserPktQueue.Process(send);
|
||||
}
|
||||
|
||||
static void
|
||||
tunifTick(llarp_tun_io *tun)
|
||||
bool
|
||||
TunEndpoint::ShouldFlushNow(llarp_time_t now) const
|
||||
{
|
||||
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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -22,34 +22,6 @@ namespace llarp
|
|||
|
||||
LinkLayer::~LinkLayer() = default;
|
||||
|
||||
void
|
||||
LinkLayer::Pump()
|
||||
{
|
||||
std::unordered_set< RouterID, RouterID::Hash > sessions;
|
||||
{
|
||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
||||
auto itr = m_AuthedLinks.begin();
|
||||
while(itr != m_AuthedLinks.end())
|
||||
{
|
||||
const RouterID r{itr->first};
|
||||
sessions.emplace(r);
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
ILinkLayer::Pump();
|
||||
{
|
||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
||||
for(const auto& pk : sessions)
|
||||
{
|
||||
if(m_AuthedLinks.count(pk) == 0)
|
||||
{
|
||||
// all sessions were removed
|
||||
SessionClosed(pk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
LinkLayer::Name() const
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace llarp
|
|||
NewOutboundSession(const RouterContact &rc,
|
||||
const AddressInfo &ai) override;
|
||||
|
||||
|
||||
void
|
||||
Pump() override;
|
||||
|
||||
|
|
|
@ -28,14 +28,15 @@ namespace llarp
|
|||
return pkt;
|
||||
}
|
||||
|
||||
Session::Session(LinkLayer* p, RouterContact rc, AddressInfo ai)
|
||||
Session::Session(LinkLayer* p, const RouterContact& rc,
|
||||
const AddressInfo& ai)
|
||||
: m_State{State::Initial}
|
||||
, m_Inbound{false}
|
||||
, m_Parent{p}
|
||||
, m_Parent(p)
|
||||
, m_CreatedAt{p->Now()}
|
||||
, m_RemoteAddr{ai}
|
||||
, m_ChosenAI{std::move(ai)}
|
||||
, m_RemoteRC{std::move(rc)}
|
||||
, m_RemoteAddr(ai)
|
||||
, m_ChosenAI(ai)
|
||||
, m_RemoteRC(rc)
|
||||
{
|
||||
token.Zero();
|
||||
GotLIM = util::memFn(&Session::GotOutboundLIM, this);
|
||||
|
@ -43,12 +44,12 @@ namespace llarp
|
|||
llarp_buffer_t(rc.pubkey));
|
||||
}
|
||||
|
||||
Session::Session(LinkLayer* p, Addr from)
|
||||
Session::Session(LinkLayer* p, const Addr& from)
|
||||
: m_State{State::Initial}
|
||||
, m_Inbound{true}
|
||||
, m_Parent{p}
|
||||
, m_Parent(p)
|
||||
, m_CreatedAt{p->Now()}
|
||||
, m_RemoteAddr{from}
|
||||
, m_RemoteAddr(from)
|
||||
{
|
||||
token.Randomize();
|
||||
GotLIM = util::memFn(&Session::GotInboundLIM, this);
|
||||
|
@ -57,9 +58,10 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
Session::Send_LL(const llarp_buffer_t& pkt)
|
||||
Session::Send_LL(const byte_t* buf, size_t sz)
|
||||
{
|
||||
LogDebug("send ", pkt.sz, " to ", m_RemoteAddr);
|
||||
LogDebug("send ", sz, " to ", m_RemoteAddr);
|
||||
const llarp_buffer_t pkt(buf, sz);
|
||||
m_Parent->SendTo_LL(m_RemoteAddr, pkt);
|
||||
m_LastTX = time_now_ms();
|
||||
}
|
||||
|
@ -144,8 +146,10 @@ namespace llarp
|
|||
Session::EncryptWorker(CryptoQueue_ptr msgs)
|
||||
{
|
||||
LogDebug("encrypt worker ", msgs->size(), " messages");
|
||||
for(auto& pkt : *msgs)
|
||||
auto itr = msgs->begin();
|
||||
while(itr != msgs->end())
|
||||
{
|
||||
Packet_t pkt = std::move(*itr);
|
||||
llarp_buffer_t pktbuf(pkt);
|
||||
const TunnelNonce nonce_ptr{pkt.data() + HMACSIZE};
|
||||
pktbuf.base += PacketOverhead;
|
||||
|
@ -155,10 +159,8 @@ namespace llarp
|
|||
pktbuf.base = pkt.data() + HMACSIZE;
|
||||
pktbuf.sz = pkt.size() - HMACSIZE;
|
||||
CryptoManager::instance()->hmac(pkt.data(), pktbuf, m_SessionKey);
|
||||
pktbuf.base = pkt.data();
|
||||
pktbuf.cur = pkt.data();
|
||||
pktbuf.sz = pkt.size();
|
||||
Send_LL(pktbuf);
|
||||
Send_LL(pkt.data(), pkt.size());
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -361,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));
|
||||
}
|
||||
|
||||
|
|
|
@ -39,9 +39,10 @@ namespace llarp
|
|||
static constexpr std::size_t MaxACKSInMACK = 1024 / sizeof(uint64_t);
|
||||
|
||||
/// outbound session
|
||||
Session(LinkLayer* parent, RouterContact rc, AddressInfo ai);
|
||||
Session(LinkLayer* parent, const RouterContact& rc,
|
||||
const AddressInfo& ai);
|
||||
/// inbound session
|
||||
Session(LinkLayer* parent, Addr from);
|
||||
Session(LinkLayer* parent, const Addr& from);
|
||||
|
||||
~Session() = default;
|
||||
|
||||
|
@ -62,7 +63,7 @@ namespace llarp
|
|||
CompletionHandler resultHandler) override;
|
||||
|
||||
void
|
||||
Send_LL(const llarp_buffer_t& pkt);
|
||||
Send_LL(const byte_t* buf, size_t sz);
|
||||
|
||||
void EncryptAndSend(ILinkSession::Packet_t);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <memory>
|
||||
#include <util/fs.hpp>
|
||||
#include <utility>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
@ -128,6 +129,8 @@ namespace llarp
|
|||
void
|
||||
ILinkLayer::Pump()
|
||||
{
|
||||
std::unordered_set< RouterID, RouterID::Hash > closedSessions;
|
||||
std::vector< std::shared_ptr< ILinkSession > > closedPending;
|
||||
auto _now = Now();
|
||||
{
|
||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
||||
|
@ -144,6 +147,7 @@ namespace llarp
|
|||
llarp::LogInfo("session to ", RouterID(itr->second->GetPubKey()),
|
||||
" timed out");
|
||||
itr->second->Close();
|
||||
closedSessions.emplace(itr->first);
|
||||
itr = m_AuthedLinks.erase(itr);
|
||||
}
|
||||
}
|
||||
|
@ -163,15 +167,25 @@ namespace llarp
|
|||
{
|
||||
LogInfo("pending session at ", itr->first, " timed out");
|
||||
// defer call so we can acquire mutexes later
|
||||
auto self = itr->second->BorrowSelf();
|
||||
m_Logic->queue_func([&, self]() {
|
||||
this->HandleTimeout(self.get());
|
||||
self->Close();
|
||||
});
|
||||
closedPending.emplace_back(std::move(itr->second));
|
||||
itr = m_Pending.erase(itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
||||
for(const auto& r : closedSessions)
|
||||
{
|
||||
if(m_AuthedLinks.count(r) == 0)
|
||||
{
|
||||
SessionClosed(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(const auto& pending : closedPending)
|
||||
{
|
||||
HandleTimeout(pending.get());
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -444,7 +458,7 @@ namespace llarp
|
|||
auto logic = link->logic();
|
||||
if(logic == nullptr)
|
||||
return;
|
||||
logic->queue_func([pkts, link]() {
|
||||
LogicCall(logic, [pkts, link]() {
|
||||
auto itr = pkts->begin();
|
||||
while(itr != pkts->end())
|
||||
{
|
||||
|
|
|
@ -410,7 +410,7 @@ namespace llarp
|
|||
// we are the farthest hop
|
||||
llarp::LogDebug("We are the farthest hop for ", info);
|
||||
// send a LRSM down the path
|
||||
self->context->logic()->queue_func([=]() {
|
||||
LogicCall(self->context->logic(), [=]() {
|
||||
SendPathConfirm(self);
|
||||
self->decrypter = nullptr;
|
||||
});
|
||||
|
@ -419,7 +419,7 @@ namespace llarp
|
|||
{
|
||||
// forward upstream
|
||||
// we are still in the worker thread so post job to logic
|
||||
self->context->logic()->queue_func([=]() {
|
||||
LogicCall(self->context->logic(), [=]() {
|
||||
SendLRCM(self);
|
||||
self->decrypter = nullptr;
|
||||
});
|
||||
|
|
|
@ -222,7 +222,7 @@ namespace llarp
|
|||
std::shared_ptr< LR_StatusMessage > msg)
|
||||
{
|
||||
auto func = std::bind(&LR_StatusMessage::SendMessage, router, nextHop, msg);
|
||||
router->pathContext().logic()->queue_func(func);
|
||||
LogicCall(router->logic(), func);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace llarp
|
|||
uint16_t rank;
|
||||
std::string dialect;
|
||||
llarp::PubKey pubkey;
|
||||
struct in6_addr ip;
|
||||
in6_addr ip = {0};
|
||||
uint16_t port;
|
||||
uint64_t version = LLARP_PROTO_VERSION;
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ namespace llarp
|
|||
{
|
||||
struct ExitInfo
|
||||
{
|
||||
struct in6_addr address;
|
||||
struct in6_addr netmask;
|
||||
in6_addr address = {0};
|
||||
in6_addr netmask = {0};
|
||||
PubKey pubkey;
|
||||
uint64_t version = LLARP_PROTO_VERSION;
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace llarp
|
|||
bool
|
||||
IPPacket::Load(const llarp_buffer_t &pkt)
|
||||
{
|
||||
if(pkt.sz > sizeof(buf))
|
||||
if(pkt.sz > sizeof(buf) or pkt.sz == 0)
|
||||
return false;
|
||||
sz = pkt.sz;
|
||||
std::copy_n(pkt.base, sz, buf);
|
||||
|
|
|
@ -1078,7 +1078,7 @@ namespace llarp
|
|||
{
|
||||
char buf[INET6_ADDRSTRLEN + 1] = {0};
|
||||
std::string str;
|
||||
in6_addr inaddr;
|
||||
in6_addr inaddr = {0};
|
||||
size_t numset = 0;
|
||||
absl::uint128 bits = netmask_bits.h;
|
||||
while(bits)
|
||||
|
|
|
@ -191,6 +191,5 @@ namespace llarp
|
|||
} // namespace llarp
|
||||
|
||||
#include <net/net_addr.hpp>
|
||||
#include <net/net_inaddr.hpp>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,7 +16,13 @@
|
|||
|
||||
namespace llarp
|
||||
{
|
||||
Addr::Addr() = default;
|
||||
Addr::Addr()
|
||||
{
|
||||
llarp::Zero(&_addr4, sizeof(_addr4));
|
||||
_addr4.sin_family = AF_INET;
|
||||
llarp::Zero(&_addr, sizeof(_addr));
|
||||
_addr.sin6_family = AF_INET6;
|
||||
}
|
||||
Addr::~Addr() = default;
|
||||
|
||||
void
|
||||
|
@ -53,18 +59,18 @@ namespace llarp
|
|||
return (const in_addr*)&_addr.sin6_addr.s6_addr[12];
|
||||
}
|
||||
|
||||
Addr::Addr(string_view str)
|
||||
Addr::Addr(string_view str) : Addr()
|
||||
{
|
||||
this->from_char_array(str);
|
||||
}
|
||||
|
||||
Addr::Addr(string_view str, const uint16_t p_port)
|
||||
Addr::Addr(string_view str, const uint16_t p_port) : Addr()
|
||||
{
|
||||
this->from_char_array(str);
|
||||
this->port(p_port);
|
||||
}
|
||||
|
||||
Addr::Addr(string_view addr_str, string_view port_str)
|
||||
Addr::Addr(string_view addr_str, string_view port_str) : Addr()
|
||||
{
|
||||
this->from_char_array(string_view_string(addr_str).c_str());
|
||||
this->port(std::strtoul(string_view_string(port_str).c_str(), nullptr, 10));
|
||||
|
@ -174,18 +180,20 @@ namespace llarp
|
|||
|
||||
Addr::Addr(const uint8_t one, const uint8_t two, const uint8_t three,
|
||||
const uint8_t four)
|
||||
: Addr()
|
||||
{
|
||||
this->from_4int(one, two, three, four);
|
||||
}
|
||||
|
||||
Addr::Addr(const uint8_t one, const uint8_t two, const uint8_t three,
|
||||
const uint8_t four, const uint16_t p_port)
|
||||
: Addr()
|
||||
{
|
||||
this->from_4int(one, two, three, four);
|
||||
this->port(p_port);
|
||||
}
|
||||
|
||||
Addr::Addr(const AddressInfo& other)
|
||||
Addr::Addr(const AddressInfo& other) : Addr()
|
||||
{
|
||||
memcpy(addr6(), other.ip.s6_addr, 16);
|
||||
_addr.sin6_port = htons(other.port);
|
||||
|
@ -200,7 +208,7 @@ namespace llarp
|
|||
_addr.sin6_family = AF_INET6;
|
||||
}
|
||||
|
||||
Addr::Addr(const sockaddr_in& other)
|
||||
Addr::Addr(const sockaddr_in& other) : Addr()
|
||||
{
|
||||
Zero(&_addr, sizeof(sockaddr_in6));
|
||||
_addr.sin6_family = AF_INET;
|
||||
|
@ -217,7 +225,7 @@ namespace llarp
|
|||
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
|
||||
}
|
||||
|
||||
Addr::Addr(const sockaddr_in6& other)
|
||||
Addr::Addr(const sockaddr_in6& other) : Addr()
|
||||
{
|
||||
memcpy(addr6(), other.sin6_addr.s6_addr, 16);
|
||||
_addr.sin6_port = htons(other.sin6_port);
|
||||
|
@ -236,7 +244,7 @@ namespace llarp
|
|||
_addr.sin6_family = AF_INET6;
|
||||
}
|
||||
|
||||
Addr::Addr(const sockaddr& other)
|
||||
Addr::Addr(const sockaddr& other) : Addr()
|
||||
{
|
||||
Zero(&_addr, sizeof(sockaddr_in6));
|
||||
_addr.sin6_family = other.sa_family;
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace llarp
|
|||
{
|
||||
// network order
|
||||
sockaddr_in6 _addr;
|
||||
sockaddr_in _addr4; // why do we even have this? favor cpu over memory
|
||||
sockaddr_in _addr4;
|
||||
~Addr();
|
||||
|
||||
Addr();
|
||||
|
|
|
@ -1,228 +0,0 @@
|
|||
#include <net/net_inaddr.hpp>
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& out, const llarp::inAddr& a)
|
||||
{
|
||||
char tmp[128] = {0};
|
||||
if(a.isIPv6Mode())
|
||||
{
|
||||
out << "[";
|
||||
}
|
||||
if(inet_ntop(a.isIPv4Mode() ? AF_INET : AF_INET6, (void*)&a._addr, tmp,
|
||||
sizeof(tmp)))
|
||||
{
|
||||
out << tmp;
|
||||
if(a.isIPv6Mode())
|
||||
out << "]";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
void
|
||||
inAddr::reset()
|
||||
{
|
||||
llarp::Zero(&this->_addr, sizeof(in6_addr));
|
||||
}
|
||||
|
||||
bool
|
||||
inAddr::from_char_array(const char* str)
|
||||
{
|
||||
this->reset();
|
||||
|
||||
// maybe refactor the family detection out
|
||||
struct addrinfo hint, *res = nullptr;
|
||||
int ret;
|
||||
|
||||
memset(&hint, '\0', sizeof hint);
|
||||
|
||||
hint.ai_family = PF_UNSPEC;
|
||||
hint.ai_flags = AI_NUMERICHOST;
|
||||
|
||||
ret = getaddrinfo(str, nullptr, &hint, &res);
|
||||
if(ret)
|
||||
{
|
||||
llarp::LogError("failed to determine address family: ", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(res->ai_family != AF_INET && res->ai_family != AF_INET6)
|
||||
{
|
||||
llarp::LogError("Address family not supported yet", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert detected-family (ipv4 or ipv6) str to in6_addr
|
||||
|
||||
/*
|
||||
if (res->ai_family == AF_INET)
|
||||
{
|
||||
freeaddrinfo(res);
|
||||
// get IPv4
|
||||
struct in_addr addr; // basically a uint32_t network order
|
||||
if(inet_aton(str, &addr) == 0)
|
||||
{
|
||||
llarp::LogError("failed to parse ", str);
|
||||
return false;
|
||||
}
|
||||
nuint32_t result;
|
||||
result.n = addr.s_addr;
|
||||
this->fromN32(result);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
ret = inet_pton(res->ai_family, str, &this->_addr);
|
||||
// inet_pton won't set SIIT
|
||||
// this->hexDebug();
|
||||
freeaddrinfo(res);
|
||||
if(ret <= 0)
|
||||
{
|
||||
if(ret == 0)
|
||||
{
|
||||
llarp::LogWarn("Not in presentation format");
|
||||
return false;
|
||||
}
|
||||
|
||||
llarp::LogWarn("inet_pton failure");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
inAddr::fromSIIT()
|
||||
{
|
||||
if(ipv6_is_siit(this->_addr))
|
||||
{
|
||||
this->_addr.s6_addr[0] = this->_addr.s6_addr[12];
|
||||
this->_addr.s6_addr[1] = this->_addr.s6_addr[13];
|
||||
this->_addr.s6_addr[2] = this->_addr.s6_addr[14];
|
||||
this->_addr.s6_addr[3] = this->_addr.s6_addr[15];
|
||||
this->setIPv4Mode();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
inAddr::toSIIT()
|
||||
{
|
||||
if(!ipv6_is_siit(this->_addr))
|
||||
{
|
||||
this->_addr.s6_addr[10] = 0xff;
|
||||
this->_addr.s6_addr[11] = 0xff;
|
||||
this->_addr.s6_addr[12] = this->_addr.s6_addr[0];
|
||||
this->_addr.s6_addr[13] = this->_addr.s6_addr[1];
|
||||
this->_addr.s6_addr[14] = this->_addr.s6_addr[2];
|
||||
this->_addr.s6_addr[15] = this->_addr.s6_addr[3];
|
||||
llarp::Zero(&this->_addr, sizeof(in6_addr) - 6);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
inAddr::isIPv6Mode() const
|
||||
{
|
||||
return !this->isIPv4Mode();
|
||||
}
|
||||
|
||||
bool
|
||||
inAddr::isIPv4Mode() const
|
||||
{
|
||||
return ipv6_is_siit(this->_addr)
|
||||
|| (this->_addr.s6_addr[4] == 0 && this->_addr.s6_addr[5] == 0
|
||||
&& this->_addr.s6_addr[6] == 0 && this->_addr.s6_addr[7] == 0
|
||||
&& this->_addr.s6_addr[8] == 0 && this->_addr.s6_addr[9] == 0
|
||||
&& this->_addr.s6_addr[10] == 0 && this->_addr.s6_addr[11] == 0
|
||||
&& this->_addr.s6_addr[12] == 0 && this->_addr.s6_addr[13] == 0
|
||||
&& this->_addr.s6_addr[14] == 0 && this->_addr.s6_addr[15] == 0);
|
||||
}
|
||||
|
||||
void
|
||||
inAddr::setIPv4Mode()
|
||||
{
|
||||
// keep first 4
|
||||
// llarp::Zero(&this->_addr + 4, sizeof(in6_addr) - 4);
|
||||
this->_addr.s6_addr[4] = 0;
|
||||
this->_addr.s6_addr[5] = 0;
|
||||
this->_addr.s6_addr[6] = 0;
|
||||
this->_addr.s6_addr[7] = 0;
|
||||
this->_addr.s6_addr[8] = 0;
|
||||
this->_addr.s6_addr[9] = 0;
|
||||
this->_addr.s6_addr[10] = 0;
|
||||
this->_addr.s6_addr[11] = 0;
|
||||
this->_addr.s6_addr[12] = 0;
|
||||
this->_addr.s6_addr[13] = 0;
|
||||
this->_addr.s6_addr[14] = 0;
|
||||
this->_addr.s6_addr[15] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
inAddr::hexDebug()
|
||||
{
|
||||
char hex_buffer[16 * 3 + 1];
|
||||
hex_buffer[16 * 3] = 0;
|
||||
for(unsigned int j = 0; j < 16; j++)
|
||||
sprintf(&hex_buffer[3 * j], "%02X ", this->_addr.s6_addr[j]);
|
||||
printf("in6_addr: [%s]\n", hex_buffer);
|
||||
}
|
||||
|
||||
//
|
||||
// IPv4 specific functions
|
||||
//
|
||||
|
||||
in_addr
|
||||
inAddr::toIAddr()
|
||||
{
|
||||
in_addr res;
|
||||
res.s_addr = toN32().n;
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
inAddr::from4int(const uint8_t one, const uint8_t two, const uint8_t three,
|
||||
const uint8_t four)
|
||||
{
|
||||
this->reset();
|
||||
this->setIPv4Mode();
|
||||
// Network byte order
|
||||
this->_addr.s6_addr[0] = one;
|
||||
this->_addr.s6_addr[1] = two;
|
||||
this->_addr.s6_addr[2] = three;
|
||||
this->_addr.s6_addr[3] = four;
|
||||
}
|
||||
|
||||
void
|
||||
inAddr::fromN32(nuint32_t in)
|
||||
{
|
||||
this->reset();
|
||||
this->setIPv4Mode();
|
||||
memcpy(&this->_addr, &in.n, sizeof(uint32_t));
|
||||
}
|
||||
void
|
||||
inAddr::fromH32(huint32_t in)
|
||||
{
|
||||
this->fromN32(xhtonl(in));
|
||||
}
|
||||
|
||||
nuint32_t
|
||||
inAddr::toN32()
|
||||
{
|
||||
nuint32_t result;
|
||||
result.n = 0; // return 0 for IPv6
|
||||
if(this->isIPv4Mode())
|
||||
{
|
||||
memcpy(&result.n, &this->_addr, sizeof(uint32_t));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
huint32_t
|
||||
inAddr::toH32()
|
||||
{
|
||||
return xntohl(this->toN32());
|
||||
}
|
||||
|
||||
//
|
||||
// IPv6 specific functions
|
||||
//
|
||||
|
||||
} // namespace llarp
|
|
@ -1,81 +0,0 @@
|
|||
#ifndef LLARP_NET_INADDR_HPP
|
||||
#define LLARP_NET_INADDR_HPP
|
||||
|
||||
#include <net/net.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
/// IPv4 or IPv6 holder
|
||||
struct inAddr
|
||||
{
|
||||
// unsigned char s6_addr[16];
|
||||
struct in6_addr _addr; // store in network order
|
||||
|
||||
/// zero out
|
||||
void
|
||||
reset();
|
||||
|
||||
/// from char*
|
||||
bool
|
||||
from_char_array(const char* str);
|
||||
|
||||
/// convert from SIIT to IPv4 Mode
|
||||
void
|
||||
fromSIIT();
|
||||
|
||||
/// convert from IPv4 Mode to SIIT
|
||||
void
|
||||
toSIIT();
|
||||
|
||||
/// not IPv4 Mode (an actual IPv6 address)
|
||||
inline bool
|
||||
isIPv6Mode() const;
|
||||
|
||||
/// IPv4 mode (not SIIT)
|
||||
bool
|
||||
isIPv4Mode() const;
|
||||
|
||||
/// clear out bytes 5-15 (Last 12 bytes)
|
||||
/// This is how inet_pton works with IPv4 addresses
|
||||
void
|
||||
setIPv4Mode();
|
||||
|
||||
/// make debugging/testing easier
|
||||
void
|
||||
hexDebug();
|
||||
|
||||
//
|
||||
// IPv4 specific functions
|
||||
//
|
||||
|
||||
/// make ipv4 in_addr struct
|
||||
in_addr
|
||||
toIAddr();
|
||||
|
||||
/// set an IPv4 addr
|
||||
void
|
||||
from4int(const uint8_t one, const uint8_t two, const uint8_t three,
|
||||
const uint8_t four);
|
||||
|
||||
/// set from an net-order uint32_t
|
||||
void
|
||||
fromN32(nuint32_t in);
|
||||
/// set from an host-order uint32_t
|
||||
void
|
||||
fromH32(huint32_t in);
|
||||
/// output as net-order uint32_t
|
||||
nuint32_t
|
||||
toN32();
|
||||
/// output as host-order uint32_t
|
||||
huint32_t
|
||||
toH32();
|
||||
|
||||
//
|
||||
// IPv6 specific functions
|
||||
//
|
||||
// coming soon
|
||||
};
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -122,7 +122,7 @@ llarp_nodedb::InsertAsync(llarp::RouterContact rc,
|
|||
this->Insert(rc);
|
||||
if(logic && completionHandler)
|
||||
{
|
||||
logic->queue_func([completionHandler] { completionHandler(); });
|
||||
LogicCall(logic, completionHandler);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ namespace llarp
|
|||
{
|
||||
llarp::LogDebug("LR_Status message processed, path build successful");
|
||||
auto self = shared_from_this();
|
||||
r->logic()->queue_func([=]() { self->HandlePathConfirmMessage(r); });
|
||||
LogicCall(r->logic(), [=]() { self->HandlePathConfirmMessage(r); });
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -206,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
|
||||
|
|
|
@ -239,10 +239,10 @@ namespace llarp
|
|||
return m_Router;
|
||||
}
|
||||
|
||||
HopHandler_ptr
|
||||
TransitHop_ptr
|
||||
PathContext::GetPathForTransfer(const PathID_t& id)
|
||||
{
|
||||
RouterID us(OurRouterID());
|
||||
const RouterID us(OurRouterID());
|
||||
auto& map = m_TransitPaths;
|
||||
{
|
||||
SyncTransitMap_t::Lock_t lock(&map.first);
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace llarp
|
|||
bool
|
||||
TransitHopPreviousIsRouter(const PathID_t& path, const RouterID& r);
|
||||
|
||||
HopHandler_ptr
|
||||
TransitHop_ptr
|
||||
GetPathForTransfer(const PathID_t& topath);
|
||||
|
||||
HopHandler_ptr
|
||||
|
|
|
@ -98,7 +98,7 @@ namespace llarp
|
|||
{
|
||||
// farthest hop
|
||||
// TODO: encrypt junk frames because our public keys are not eligator
|
||||
logic->queue_func(std::bind(result, shared_from_this()));
|
||||
LogicCall(logic, std::bind(result, shared_from_this()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -32,7 +32,13 @@ namespace llarp
|
|||
return stream;
|
||||
}
|
||||
|
||||
TransitHop::TransitHop() = default;
|
||||
TransitHop::TransitHop() : m_UpstreamGather(128), m_DownstreamGather(128)
|
||||
{
|
||||
m_UpstreamGather.enable();
|
||||
m_DownstreamGather.enable();
|
||||
m_UpstreamWorkCounter = 0;
|
||||
m_DownstreamWorkCounter = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
TransitHop::Expired(llarp_time_t now) const
|
||||
|
@ -118,43 +124,73 @@ namespace llarp
|
|||
void
|
||||
TransitHop::DownstreamWork(TrafficQueue_ptr msgs, AbstractRouter* r)
|
||||
{
|
||||
std::vector< RelayDownstreamMessage > sendmsgs(msgs->size());
|
||||
size_t idx = 0;
|
||||
m_DownstreamWorkCounter++;
|
||||
auto flushIt = [self = shared_from_this(), r]() {
|
||||
std::vector< RelayDownstreamMessage > msgs;
|
||||
do
|
||||
{
|
||||
auto maybe = self->m_DownstreamGather.tryPopFront();
|
||||
if(not maybe.has_value())
|
||||
break;
|
||||
msgs.emplace_back(maybe.value());
|
||||
} while(true);
|
||||
self->HandleAllDownstream(std::move(msgs), r);
|
||||
};
|
||||
for(auto& ev : *msgs)
|
||||
{
|
||||
RelayDownstreamMessage msg;
|
||||
const llarp_buffer_t buf(ev.first);
|
||||
auto& msg = sendmsgs[idx];
|
||||
msg.pathid = info.rxID;
|
||||
msg.Y = ev.second ^ nonceXOR;
|
||||
CryptoManager::instance()->xchacha20(buf, pathKey, ev.second);
|
||||
msg.X = buf;
|
||||
llarp::LogDebug("relay ", msg.X.size(), " bytes downstream from ",
|
||||
info.upstream, " to ", info.downstream);
|
||||
++idx;
|
||||
if(m_DownstreamGather.full())
|
||||
{
|
||||
LogicCall(r->logic(), flushIt);
|
||||
}
|
||||
if(m_DownstreamGather.enabled())
|
||||
m_DownstreamGather.pushBack(msg);
|
||||
}
|
||||
r->logic()->queue_func(std::bind(&TransitHop::HandleAllDownstream,
|
||||
shared_from_this(), std::move(sendmsgs),
|
||||
r));
|
||||
m_DownstreamWorkCounter--;
|
||||
if(m_DownstreamWorkCounter == 0)
|
||||
LogicCall(r->logic(), flushIt);
|
||||
}
|
||||
|
||||
void
|
||||
TransitHop::UpstreamWork(TrafficQueue_ptr msgs, AbstractRouter* r)
|
||||
{
|
||||
std::vector< RelayUpstreamMessage > sendmsgs(msgs->size());
|
||||
size_t idx = 0;
|
||||
m_UpstreamWorkCounter++;
|
||||
auto flushIt = [self = shared_from_this(), r]() {
|
||||
std::vector< RelayUpstreamMessage > msgs;
|
||||
do
|
||||
{
|
||||
auto maybe = self->m_UpstreamGather.tryPopFront();
|
||||
if(not maybe.has_value())
|
||||
break;
|
||||
msgs.emplace_back(maybe.value());
|
||||
} while(true);
|
||||
self->HandleAllUpstream(std::move(msgs), r);
|
||||
};
|
||||
for(auto& ev : *msgs)
|
||||
{
|
||||
const llarp_buffer_t buf(ev.first);
|
||||
auto& msg = sendmsgs[idx];
|
||||
RelayUpstreamMessage msg;
|
||||
CryptoManager::instance()->xchacha20(buf, pathKey, ev.second);
|
||||
msg.pathid = info.txID;
|
||||
msg.Y = ev.second ^ nonceXOR;
|
||||
msg.X = buf;
|
||||
++idx;
|
||||
if(m_UpstreamGather.full())
|
||||
{
|
||||
LogicCall(r->logic(), flushIt);
|
||||
}
|
||||
if(m_UpstreamGather.enabled())
|
||||
m_UpstreamGather.pushBack(msg);
|
||||
}
|
||||
r->logic()->queue_func(std::bind(&TransitHop::HandleAllUpstream,
|
||||
shared_from_this(), std::move(sendmsgs),
|
||||
r));
|
||||
m_UpstreamWorkCounter--;
|
||||
if(m_UpstreamWorkCounter == 0)
|
||||
LogicCall(r->logic(), flushIt);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -173,6 +209,11 @@ namespace llarp
|
|||
m_LastActivity = r->Now();
|
||||
}
|
||||
FlushDownstream(r);
|
||||
for(const auto& other : m_FlushOthers)
|
||||
{
|
||||
other->FlushUpstream(r);
|
||||
}
|
||||
m_FlushOthers.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -183,7 +224,7 @@ namespace llarp
|
|||
r->SendToOrQueue(info.upstream, &msg);
|
||||
}
|
||||
}
|
||||
r->linkManager().PumpLinks();
|
||||
r->PumpLL();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -196,7 +237,7 @@ namespace llarp
|
|||
info.upstream, " to ", info.downstream);
|
||||
r->SendToOrQueue(info.downstream, &msg);
|
||||
}
|
||||
r->linkManager().PumpLinks();
|
||||
r->PumpLL();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -410,7 +451,10 @@ namespace llarp
|
|||
buf.cur = buf.base;
|
||||
// send
|
||||
if(path->HandleDownstream(buf, msg.Y, r))
|
||||
{
|
||||
m_FlushOthers.emplace(path);
|
||||
return true;
|
||||
}
|
||||
return SendRoutingMessage(discarded, r);
|
||||
}
|
||||
|
||||
|
@ -421,10 +465,16 @@ namespace llarp
|
|||
printer.printAttribute("TransitHop", info);
|
||||
printer.printAttribute("started", started);
|
||||
printer.printAttribute("lifetime", lifetime);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void
|
||||
TransitHop::Stop()
|
||||
{
|
||||
m_UpstreamGather.disable();
|
||||
m_DownstreamGather.disable();
|
||||
}
|
||||
|
||||
void
|
||||
TransitHop::SetSelfDestruct()
|
||||
{
|
||||
|
@ -435,7 +485,7 @@ namespace llarp
|
|||
TransitHop::QueueDestroySelf(AbstractRouter* r)
|
||||
{
|
||||
auto func = std::bind(&TransitHop::SetSelfDestruct, shared_from_this());
|
||||
r->logic()->queue_func(func);
|
||||
LogicCall(r->logic(), func);
|
||||
}
|
||||
} // namespace path
|
||||
} // namespace llarp
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <path/path_types.hpp>
|
||||
#include <routing/handler.hpp>
|
||||
#include <router_id.hpp>
|
||||
#include <util/compare_ptr.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
@ -94,8 +95,17 @@ namespace llarp
|
|||
llarp_proto_version_t version;
|
||||
llarp_time_t m_LastActivity = 0;
|
||||
|
||||
void
|
||||
Stop();
|
||||
|
||||
bool destroy = false;
|
||||
|
||||
bool
|
||||
operator<(const TransitHop& other) const
|
||||
{
|
||||
return info < other.info;
|
||||
}
|
||||
|
||||
bool
|
||||
IsEndpoint(const RouterID& us) const
|
||||
{
|
||||
|
@ -222,6 +232,14 @@ namespace llarp
|
|||
|
||||
void
|
||||
QueueDestroySelf(AbstractRouter* r);
|
||||
|
||||
std::set< std::shared_ptr< TransitHop >,
|
||||
ComparePtr< std::shared_ptr< TransitHop > > >
|
||||
m_FlushOthers;
|
||||
thread::Queue< RelayUpstreamMessage > m_UpstreamGather;
|
||||
thread::Queue< RelayDownstreamMessage > m_DownstreamGather;
|
||||
std::atomic< uint32_t > m_UpstreamWorkCounter;
|
||||
std::atomic< uint32_t > m_DownstreamWorkCounter;
|
||||
};
|
||||
|
||||
inline std::ostream&
|
||||
|
|
|
@ -71,15 +71,18 @@ namespace llarp
|
|||
void
|
||||
OutboundMessageHandler::Tick()
|
||||
{
|
||||
ProcessOutboundQueue();
|
||||
RemoveEmptyPathQueues();
|
||||
SendRoundRobin();
|
||||
m_Killer.TryAccess([self = this]() {
|
||||
self->ProcessOutboundQueue();
|
||||
self->RemoveEmptyPathQueues();
|
||||
self->SendRoundRobin();
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
OutboundMessageHandler::QueueRemoveEmptyPath(const PathID_t &pathid)
|
||||
{
|
||||
removedPaths.pushBack(pathid);
|
||||
m_Killer.TryAccess(
|
||||
[self = this, pathid]() { self->removedPaths.pushBack(pathid); });
|
||||
}
|
||||
|
||||
// TODO: this
|
||||
|
@ -164,8 +167,8 @@ namespace llarp
|
|||
{
|
||||
if(callback)
|
||||
{
|
||||
auto func = std::bind(callback, status);
|
||||
_logic->queue_func(func);
|
||||
auto f = std::bind(callback, status);
|
||||
LogicCall(_logic, [self = this, f]() { self->m_Killer.TryAccess(f); });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,7 +268,9 @@ namespace llarp
|
|||
void
|
||||
OutboundMessageHandler::RemoveEmptyPathQueues()
|
||||
{
|
||||
removedSomePaths = (not removedPaths.empty());
|
||||
removedSomePaths = false;
|
||||
if(removedPaths.empty())
|
||||
return;
|
||||
|
||||
while(not removedPaths.empty())
|
||||
{
|
||||
|
@ -275,6 +280,7 @@ namespace llarp
|
|||
outboundMessageQueues.erase(itr);
|
||||
}
|
||||
}
|
||||
removedSomePaths = true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -282,7 +288,7 @@ namespace llarp
|
|||
{
|
||||
// send non-routing messages first priority
|
||||
auto &non_routing_mq = outboundMessageQueues[zeroID];
|
||||
while(!non_routing_mq.empty())
|
||||
while(not non_routing_mq.empty())
|
||||
{
|
||||
MessageQueueEntry entry = std::move(non_routing_mq.front());
|
||||
non_routing_mq.pop();
|
||||
|
|
|
@ -123,6 +123,8 @@ namespace llarp
|
|||
ILinkManager *_linkManager;
|
||||
std::shared_ptr< Logic > _logic;
|
||||
|
||||
util::ContentionKiller m_Killer;
|
||||
|
||||
// paths cannot have pathid "0", so it can be used as the "pathid"
|
||||
// for non-traffic (control) messages, so they can be prioritized.
|
||||
static const PathID_t zeroID;
|
||||
|
|
|
@ -123,11 +123,6 @@ namespace llarp
|
|||
int remainingDesired = numDesired;
|
||||
|
||||
_nodedb->visit([&](const RouterContact &other) -> bool {
|
||||
// check if we really remainingDesired to
|
||||
if(other.ExpiresSoon(now, 30000)) // TODO: make delta configurable
|
||||
{
|
||||
return remainingDesired > 0;
|
||||
}
|
||||
if(!_rcLookup->RemoteIsAllowed(other.pubkey))
|
||||
{
|
||||
return remainingDesired > 0;
|
||||
|
@ -219,7 +214,7 @@ namespace llarp
|
|||
if(ShouldConnectTo(router))
|
||||
{
|
||||
auto fn = std::bind(&OutboundSessionMaker::DoEstablish, this, router);
|
||||
_logic->queue_func(fn);
|
||||
LogicCall(_logic, fn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,7 +321,7 @@ namespace llarp
|
|||
for(const auto &callback : movedCallbacks)
|
||||
{
|
||||
auto func = std::bind(callback, router, type);
|
||||
_logic->queue_func(func);
|
||||
LogicCall(_logic, func);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -29,8 +29,13 @@
|
|||
#include <iterator>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#if defined(RPI) || defined(ANDROID)
|
||||
#if defined(ANDROID) || defined(IOS)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#if defined(_WIN32)
|
||||
#else
|
||||
#include <curl/curl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool
|
||||
|
@ -143,9 +148,17 @@ namespace llarp
|
|||
void
|
||||
Router::PumpLL()
|
||||
{
|
||||
static constexpr size_t PumpJobThreshhold = 50;
|
||||
static constexpr llarp_time_t PumpInterval = 25;
|
||||
const auto now = Now();
|
||||
if(_stopping.load())
|
||||
return;
|
||||
|
||||
if(_logic->numPendingJobs() >= PumpJobThreshhold
|
||||
&& _lastPump + PumpInterval >= now)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_lastPump = now;
|
||||
paths.PumpDownstream();
|
||||
paths.PumpUpstream();
|
||||
|
||||
|
@ -197,6 +210,14 @@ namespace llarp
|
|||
LogError(rcfile, " contains invalid RC");
|
||||
}
|
||||
|
||||
static size_t
|
||||
RecvIdentKey(char *ptr, size_t, size_t nmemb, void *userdata)
|
||||
{
|
||||
for(size_t idx = 0; idx < nmemb; idx++)
|
||||
static_cast< std::vector< char > * >(userdata)->push_back(ptr[idx]);
|
||||
return nmemb;
|
||||
}
|
||||
|
||||
bool
|
||||
Router::EnsureIdentity()
|
||||
{
|
||||
|
@ -207,10 +228,120 @@ namespace llarp
|
|||
|
||||
if (_identity.IsZero())
|
||||
return false;
|
||||
|
||||
if (_encryption.IsZero())
|
||||
return false;
|
||||
|
||||
if(whitelistRouters)
|
||||
{
|
||||
#if defined(ANDROID) || defined(IOS)
|
||||
LogError("running a service node on mobile device is not possible.");
|
||||
return false;
|
||||
#else
|
||||
#if defined(_WIN32)
|
||||
LogError("running a service node on windows is not possible.");
|
||||
return false;
|
||||
#else
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl)
|
||||
{
|
||||
bool ret = false;
|
||||
std::stringstream ss;
|
||||
ss << "http://" << lokidRPCAddr << "/json_rpc";
|
||||
const auto url = ss.str();
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY);
|
||||
const auto auth = lokidRPCUser + ":" + lokidRPCPassword;
|
||||
curl_easy_setopt(curl, CURLOPT_USERPWD, auth.c_str());
|
||||
curl_slist *list = nullptr;
|
||||
list = curl_slist_append(list, "Content-Type: application/json");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
|
||||
|
||||
nlohmann::json request = {{"id", "0"},
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "get_service_node_privkey"}};
|
||||
const auto data = request.dump();
|
||||
std::vector< char > resp;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data.size());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &RecvIdentKey);
|
||||
do
|
||||
{
|
||||
resp.clear();
|
||||
LogInfo("Getting Identity Keys from lokid...");
|
||||
if(curl_easy_perform(curl) == CURLE_OK)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto j = nlohmann::json::parse(resp);
|
||||
if(not j.is_object())
|
||||
continue;
|
||||
|
||||
const auto itr = j.find("result");
|
||||
if(itr == j.end())
|
||||
continue;
|
||||
if(not itr->is_object())
|
||||
continue;
|
||||
const auto k =
|
||||
(*itr)["service_node_ed25519_privkey"].get< std::string >();
|
||||
if(k.size() != (_identity.size() * 2))
|
||||
{
|
||||
if(k.empty())
|
||||
{
|
||||
LogError("lokid gave no identity key");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("lokid gave invalid identity key");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if(not HexDecode(k.c_str(), _identity.data(), _identity.size()))
|
||||
continue;
|
||||
if(CryptoManager::instance()->check_identity_privkey(_identity))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("lokid gave bogus identity key");
|
||||
}
|
||||
}
|
||||
catch(nlohmann::json::exception &ex)
|
||||
{
|
||||
LogError("Bad response from lokid: ", ex.what());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("failed to get identity keys");
|
||||
}
|
||||
if(ret)
|
||||
{
|
||||
LogInfo("Got Identity Keys from lokid: ", RouterID(pubkey()));
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
} while(true);
|
||||
curl_easy_cleanup(curl);
|
||||
curl_slist_free_all(list);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("failed to init curl");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
return llarp_findOrCreateIdentity(ident_keyfile, _identity);
|
||||
}
|
||||
|
||||
if(usingSNSeed)
|
||||
{
|
||||
LogError("FIXME: load identity key from SNode seed");
|
||||
|
@ -287,7 +418,7 @@ namespace llarp
|
|||
return;
|
||||
auto *self = static_cast< Router * >(user);
|
||||
self->ticker_job_id = 0;
|
||||
self->logic()->queue_func(std::bind(&Router::Tick, self));
|
||||
LogicCall(self->logic(), std::bind(&Router::Tick, self));
|
||||
self->ScheduleTicker(orig);
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace llarp
|
|||
{
|
||||
struct Router final : public AbstractRouter
|
||||
{
|
||||
llarp_time_t _lastPump = 0;
|
||||
bool ready;
|
||||
// transient iwp encryption key
|
||||
fs::path transport_keyfile = "transport.key";
|
||||
|
|
|
@ -53,6 +53,48 @@ namespace llarp
|
|||
PopulateReqHeaders(abyss::http::Headers_t& hdr) override;
|
||||
};
|
||||
|
||||
struct LokiPingHandler final : public CallerHandler
|
||||
{
|
||||
~LokiPingHandler() override = default;
|
||||
LokiPingHandler(::abyss::http::ConnImpl* impl, CallerImpl* parent)
|
||||
: CallerHandler(impl, parent)
|
||||
{
|
||||
}
|
||||
bool
|
||||
HandleJSONResult(const nlohmann::json& result) override
|
||||
{
|
||||
if(not result.is_object())
|
||||
{
|
||||
LogError("invalid result from lokid ping, not an object");
|
||||
return false;
|
||||
}
|
||||
const auto itr = result.find("status");
|
||||
if(itr == result.end())
|
||||
{
|
||||
LogError("invalid result from lokid ping, no result");
|
||||
return false;
|
||||
}
|
||||
if(not itr->is_string())
|
||||
{
|
||||
LogError("invalid result from lokid ping, status not an string");
|
||||
return false;
|
||||
}
|
||||
const auto status = itr->get< std::string >();
|
||||
if(status != "OK")
|
||||
{
|
||||
LogError("lokid ping failed: '", status, "'");
|
||||
return false;
|
||||
}
|
||||
LogInfo("lokid ping: '", status, "'");
|
||||
return true;
|
||||
}
|
||||
void
|
||||
HandleError() override
|
||||
{
|
||||
LogError("Failed to ping lokid");
|
||||
}
|
||||
};
|
||||
|
||||
struct GetServiceNodeListHandler final : public CallerHandler
|
||||
{
|
||||
using PubkeyList_t = std::vector< RouterID >;
|
||||
|
@ -120,7 +162,9 @@ namespace llarp
|
|||
{
|
||||
AbstractRouter* router;
|
||||
llarp_time_t m_NextKeyUpdate = 0;
|
||||
llarp_time_t m_NextPing = 0;
|
||||
const llarp_time_t KeyUpdateInterval = 5000;
|
||||
const llarp_time_t PingInterval = 60 * 5 * 1000;
|
||||
using PubkeyList_t = GetServiceNodeListHandler::PubkeyList_t;
|
||||
|
||||
CallerImpl(AbstractRouter* r) : ::abyss::http::JSONRPC(), router(r)
|
||||
|
@ -130,11 +174,18 @@ namespace llarp
|
|||
void
|
||||
Tick(llarp_time_t now)
|
||||
{
|
||||
if(not router->IsRunning())
|
||||
return;
|
||||
if(now >= m_NextKeyUpdate)
|
||||
{
|
||||
AsyncUpdatePubkeyList();
|
||||
m_NextKeyUpdate = now + KeyUpdateInterval;
|
||||
}
|
||||
if(now >= m_NextPing)
|
||||
{
|
||||
AsyncLokiPing();
|
||||
m_NextPing = now + PingInterval;
|
||||
}
|
||||
Flush();
|
||||
}
|
||||
|
||||
|
@ -145,6 +196,20 @@ namespace llarp
|
|||
password = passwd;
|
||||
}
|
||||
|
||||
void
|
||||
AsyncLokiPing()
|
||||
{
|
||||
LogInfo("Pinging Lokid");
|
||||
static nlohmann::json::number_unsigned_t major(atoi(LLARP_VERSION_MAJ));
|
||||
static nlohmann::json::number_unsigned_t minor(atoi(LLARP_VERSION_MIN));
|
||||
static nlohmann::json::number_unsigned_t patch(
|
||||
atoi(LLARP_VERSION_PATCH));
|
||||
nlohmann::json params = {
|
||||
{"version", nlohmann::json::array({major, minor, patch})}};
|
||||
QueueRPC("lokinet_ping", std::move(params),
|
||||
util::memFn(&CallerImpl::NewLokinetPingConn, this));
|
||||
}
|
||||
|
||||
void
|
||||
AsyncUpdatePubkeyList()
|
||||
{
|
||||
|
@ -162,6 +227,12 @@ namespace llarp
|
|||
return RunAsync(router->netloop(), remote);
|
||||
}
|
||||
|
||||
abyss::http::IRPCClientHandler*
|
||||
NewLokinetPingConn(abyss::http::ConnImpl* impl)
|
||||
{
|
||||
return new LokiPingHandler(impl, this);
|
||||
}
|
||||
|
||||
abyss::http::IRPCClientHandler*
|
||||
NewAsyncUpdatePubkeyListConn(abyss::http::ConnImpl* impl)
|
||||
{
|
||||
|
|
|
@ -17,7 +17,6 @@ namespace llarp
|
|||
: logic(std::move(l))
|
||||
, m_remote(std::move(r))
|
||||
, m_LocalIdentity(localident)
|
||||
, frame(std::make_shared< ProtocolFrame >())
|
||||
, introPubKey(introsetPubKey)
|
||||
, remoteIntro(remote)
|
||||
, handler(h)
|
||||
|
@ -27,31 +26,33 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
AsyncKeyExchange::Result(std::shared_ptr< AsyncKeyExchange > self)
|
||||
AsyncKeyExchange::Result(std::shared_ptr< AsyncKeyExchange > self,
|
||||
std::shared_ptr< ProtocolFrame > frame)
|
||||
{
|
||||
// put values
|
||||
self->handler->PutSenderFor(self->msg.tag, self->m_remote, false);
|
||||
self->handler->PutCachedSessionKeyFor(self->msg.tag, self->sharedKey);
|
||||
self->handler->PutIntroFor(self->msg.tag, self->remoteIntro);
|
||||
self->handler->PutReplyIntroFor(self->msg.tag, self->msg.introReply);
|
||||
self->hook(self->frame);
|
||||
self->hook(frame);
|
||||
}
|
||||
|
||||
void
|
||||
AsyncKeyExchange::Encrypt(std::shared_ptr< AsyncKeyExchange > self)
|
||||
AsyncKeyExchange::Encrypt(std::shared_ptr< AsyncKeyExchange > self,
|
||||
std::shared_ptr< ProtocolFrame > frame)
|
||||
{
|
||||
// derive ntru session key component
|
||||
SharedSecret K;
|
||||
auto crypto = CryptoManager::instance();
|
||||
crypto->pqe_encrypt(self->frame->C, K, self->introPubKey);
|
||||
crypto->pqe_encrypt(frame->C, K, self->introPubKey);
|
||||
// randomize Nonce
|
||||
self->frame->N.Randomize();
|
||||
frame->N.Randomize();
|
||||
// compure post handshake session key
|
||||
// PKE (A, B, N)
|
||||
SharedSecret sharedSecret;
|
||||
path_dh_func dh_client = util::memFn(&Crypto::dh_client, crypto);
|
||||
if(!self->m_LocalIdentity.KeyExchange(dh_client, sharedSecret,
|
||||
self->m_remote, self->frame->N))
|
||||
self->m_remote, frame->N))
|
||||
{
|
||||
LogError("failed to derive x25519 shared key component");
|
||||
}
|
||||
|
@ -68,8 +69,9 @@ namespace llarp
|
|||
// set version
|
||||
self->msg.version = LLARP_PROTO_VERSION;
|
||||
// encrypt and sign
|
||||
if(self->frame->EncryptAndSign(self->msg, K, self->m_LocalIdentity))
|
||||
self->logic->queue_func(std::bind(&AsyncKeyExchange::Result, self));
|
||||
if(frame->EncryptAndSign(self->msg, K, self->m_LocalIdentity))
|
||||
LogicCall(self->logic,
|
||||
std::bind(&AsyncKeyExchange::Result, self, frame));
|
||||
else
|
||||
{
|
||||
LogError("failed to encrypt and sign");
|
||||
|
|
|
@ -19,7 +19,6 @@ namespace llarp
|
|||
ServiceInfo m_remote;
|
||||
const Identity& m_LocalIdentity;
|
||||
ProtocolMessage msg;
|
||||
std::shared_ptr< ProtocolFrame > frame;
|
||||
Introduction intro;
|
||||
const PQPubKey introPubKey;
|
||||
Introduction remoteIntro;
|
||||
|
@ -34,11 +33,13 @@ namespace llarp
|
|||
const ConvoTag& t, ProtocolType proto);
|
||||
|
||||
static void
|
||||
Result(std::shared_ptr< AsyncKeyExchange > user);
|
||||
Result(std::shared_ptr< AsyncKeyExchange > user,
|
||||
std::shared_ptr< ProtocolFrame > frame);
|
||||
|
||||
/// given protocol message make protocol frame
|
||||
static void
|
||||
Encrypt(std::shared_ptr< AsyncKeyExchange > user);
|
||||
Encrypt(std::shared_ptr< AsyncKeyExchange > user,
|
||||
std::shared_ptr< ProtocolFrame > frame);
|
||||
};
|
||||
|
||||
} // namespace service
|
||||
|
|
|
@ -29,12 +29,15 @@ namespace llarp
|
|||
{
|
||||
Endpoint::Endpoint(const std::string& name, AbstractRouter* r,
|
||||
Context* parent)
|
||||
: path::Builder(r, 3, path::default_len), context(parent)
|
||||
: path::Builder(r, 3, path::default_len)
|
||||
, context(parent)
|
||||
, m_RecvQueue(128)
|
||||
{
|
||||
m_state = std::make_unique< EndpointState >();
|
||||
m_state->m_Router = r;
|
||||
m_state->m_Name = name;
|
||||
m_state->m_Tag.Zero();
|
||||
m_RecvQueue.enable();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -805,6 +808,30 @@ namespace llarp
|
|||
return {{"LOKINET_ADDR", m_Identity.pub.Addr().ToString()}};
|
||||
}
|
||||
|
||||
void
|
||||
Endpoint::FlushRecvData()
|
||||
{
|
||||
do
|
||||
{
|
||||
auto maybe = m_RecvQueue.tryPopFront();
|
||||
if(not maybe.has_value())
|
||||
return;
|
||||
auto ev = std::move(maybe.value());
|
||||
ProtocolMessage::ProcessAsync(ev.fromPath, ev.pathid, ev.msg);
|
||||
} while(true);
|
||||
}
|
||||
|
||||
void
|
||||
Endpoint::QueueRecvData(RecvDataEvent ev)
|
||||
{
|
||||
if(m_RecvQueue.full() || m_RecvQueue.empty())
|
||||
{
|
||||
auto self = this;
|
||||
LogicCall(m_router->logic(), [self]() { self->FlushRecvData(); });
|
||||
}
|
||||
m_RecvQueue.pushBack(std::move(ev));
|
||||
}
|
||||
|
||||
bool
|
||||
Endpoint::HandleDataMessage(path::Path_ptr path, const PathID_t from,
|
||||
std::shared_ptr< ProtocolMessage > msg)
|
||||
|
@ -1046,20 +1073,31 @@ namespace llarp
|
|||
{
|
||||
const auto& sessions = m_state->m_SNodeSessions;
|
||||
auto& queue = m_state->m_InboundTrafficQueue;
|
||||
EndpointLogic()->queue_func([&]() {
|
||||
|
||||
auto epPump = [&]() {
|
||||
FlushRecvData();
|
||||
// send downstream packets to user for snode
|
||||
for(const auto& item : sessions)
|
||||
item.second.first->FlushDownstream();
|
||||
// send downstream traffic to user for hidden service
|
||||
util::Lock lock(&m_state->m_InboundTrafficQueueMutex);
|
||||
while(queue.size())
|
||||
while(not queue.empty())
|
||||
{
|
||||
const auto& msg = queue.top();
|
||||
const llarp_buffer_t buf(msg->payload);
|
||||
HandleInboundPacket(msg->tag, buf, msg->proto);
|
||||
queue.pop();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if(NetworkIsIsolated())
|
||||
{
|
||||
LogicCall(EndpointLogic(), epPump);
|
||||
}
|
||||
else
|
||||
{
|
||||
epPump();
|
||||
}
|
||||
|
||||
auto router = Router();
|
||||
// TODO: locking on this container
|
||||
|
@ -1068,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();
|
||||
|
||||
|
|
|
@ -78,6 +78,9 @@ namespace llarp
|
|||
bool
|
||||
IsReady() const;
|
||||
|
||||
void
|
||||
QueueRecvData(RecvDataEvent ev) override;
|
||||
|
||||
/// return true if our introset has expired intros
|
||||
bool
|
||||
IntrosetIsStale() const;
|
||||
|
@ -436,6 +439,9 @@ namespace llarp
|
|||
hooks::Backend_ptr m_OnReady;
|
||||
|
||||
private:
|
||||
void
|
||||
FlushRecvData();
|
||||
|
||||
friend struct EndpointUtil;
|
||||
|
||||
// clang-format off
|
||||
|
@ -448,6 +454,7 @@ namespace llarp
|
|||
// clang-format on
|
||||
|
||||
std::unique_ptr< EndpointState > m_state;
|
||||
thread::Queue< RecvDataEvent > m_RecvQueue;
|
||||
};
|
||||
|
||||
using Endpoint_ptr = std::shared_ptr< Endpoint >;
|
||||
|
|
|
@ -14,6 +14,14 @@ namespace llarp
|
|||
namespace service
|
||||
{
|
||||
using ConvoTag = AlignedBuffer< 16 >;
|
||||
struct ProtocolMessage;
|
||||
|
||||
struct RecvDataEvent
|
||||
{
|
||||
path::Path_ptr fromPath;
|
||||
PathID_t pathid;
|
||||
std::shared_ptr< ProtocolMessage > msg;
|
||||
};
|
||||
|
||||
struct ProtocolMessage;
|
||||
struct IDataHandler
|
||||
|
@ -63,6 +71,9 @@ namespace llarp
|
|||
|
||||
virtual bool
|
||||
HasInboundConvo(const Address& addr) const = 0;
|
||||
|
||||
virtual void
|
||||
QueueRecvData(RecvDataEvent ev) = 0;
|
||||
};
|
||||
} // namespace service
|
||||
} // namespace llarp
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace llarp
|
|||
if(!msg)
|
||||
return false;
|
||||
endpoint = path->Endpoint();
|
||||
r->logic()->queue_func([=]() { path->SendRoutingMessage(*msg, r); });
|
||||
LogicCall(r->logic(), [=]() { path->SendRoutingMessage(*msg, r); });
|
||||
return true;
|
||||
}
|
||||
} // namespace service
|
||||
|
|
|
@ -62,7 +62,6 @@ namespace llarp
|
|||
if(intro.expiresAt > m_NextIntro.expiresAt)
|
||||
m_NextIntro = intro;
|
||||
}
|
||||
currentConvoTag.Randomize();
|
||||
}
|
||||
|
||||
OutboundContext::~OutboundContext() = default;
|
||||
|
@ -176,6 +175,8 @@ namespace llarp
|
|||
OutboundContext::AsyncGenIntro(const llarp_buffer_t& payload,
|
||||
ProtocolType t)
|
||||
{
|
||||
if(not currentConvoTag.IsZero())
|
||||
return;
|
||||
if(remoteIntro.router.IsZero())
|
||||
SwapIntros();
|
||||
|
||||
|
@ -193,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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -14,9 +14,10 @@ namespace llarp
|
|||
switch(lvl)
|
||||
{
|
||||
case eLogNone:
|
||||
break;
|
||||
case eLogDebug:
|
||||
ss << "[DBG] ";
|
||||
return;
|
||||
case eLogTrace:
|
||||
ss << "[TRC] ";
|
||||
break case eLogDebug : ss << "[DBG] ";
|
||||
break;
|
||||
case eLogInfo:
|
||||
ss << "[NFO] ";
|
||||
|
@ -49,6 +50,9 @@ namespace llarp
|
|||
str += tag;
|
||||
switch(lvl)
|
||||
{
|
||||
case eLogTrace:
|
||||
__android_log_write(ANDROID_LOG_TRACE, str.c_str(), msg.c_str());
|
||||
return;
|
||||
case eLogDebug:
|
||||
__android_log_write(ANDROID_LOG_DEBUG, str.c_str(), msg.c_str());
|
||||
return;
|
||||
|
|
|
@ -5,28 +5,46 @@
|
|||
|
||||
namespace llarp
|
||||
{
|
||||
namespace
|
||||
void
|
||||
FileLogStream::Flush(Lines_t *lines, FILE *const f)
|
||||
{
|
||||
static void
|
||||
Flush(std::deque< std::string > lines, FILE *const f)
|
||||
bool wrote_stuff = false;
|
||||
do
|
||||
{
|
||||
for(const auto &line : lines)
|
||||
fprintf(f, "%s\n", line.c_str());
|
||||
auto maybe_line = lines->tryPopFront();
|
||||
if(not maybe_line.has_value())
|
||||
break;
|
||||
const auto &line = maybe_line.value();
|
||||
if(fprintf(f, "%s\n", line.c_str()) >= 0)
|
||||
wrote_stuff = true;
|
||||
} while(true);
|
||||
|
||||
if(wrote_stuff)
|
||||
fflush(f);
|
||||
}
|
||||
} // namespace
|
||||
}
|
||||
|
||||
// namespace
|
||||
FileLogStream::FileLogStream(std::shared_ptr< thread::ThreadPool > disk,
|
||||
FILE *f, llarp_time_t flushInterval,
|
||||
bool closeFile)
|
||||
: m_Disk(std::move(disk))
|
||||
: m_Lines(1024 * 8)
|
||||
, m_Disk(std::move(disk))
|
||||
, m_File(f)
|
||||
, m_FlushInterval(flushInterval)
|
||||
, m_Close(closeFile)
|
||||
{
|
||||
m_Lines.enable();
|
||||
}
|
||||
|
||||
FileLogStream::~FileLogStream()
|
||||
{
|
||||
m_Lines.disable();
|
||||
do
|
||||
{
|
||||
auto line = m_Lines.tryPopFront();
|
||||
if(not line.has_value())
|
||||
break;
|
||||
} while(true);
|
||||
fflush(m_File);
|
||||
if(m_Close)
|
||||
fclose(m_File);
|
||||
|
@ -35,6 +53,8 @@ namespace llarp
|
|||
bool
|
||||
FileLogStream::ShouldFlush(llarp_time_t now) const
|
||||
{
|
||||
if(m_Lines.full())
|
||||
return true;
|
||||
if(m_LastFlush >= now)
|
||||
return false;
|
||||
const auto dlt = now - m_LastFlush;
|
||||
|
@ -54,7 +74,15 @@ namespace llarp
|
|||
void
|
||||
FileLogStream::Print(LogLevel, const char *, const std::string &msg)
|
||||
{
|
||||
m_Lines.emplace_back(msg);
|
||||
m_Lines.pushBack(msg);
|
||||
}
|
||||
|
||||
void
|
||||
FileLogStream::AppendLog(LogLevel lvl, const char *fname, int lineno,
|
||||
const std::string &nodename, const std::string msg)
|
||||
{
|
||||
ILogStream::AppendLog(lvl, fname, lineno, nodename, msg);
|
||||
Tick(llarp::time_now_ms());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -68,9 +96,8 @@ namespace llarp
|
|||
FileLogStream::FlushLinesToDisk(llarp_time_t now)
|
||||
{
|
||||
FILE *const f = m_File;
|
||||
std::deque< std::string > lines(m_Lines);
|
||||
m_Disk->addJob([=]() { Flush(lines, f); });
|
||||
m_Lines.clear();
|
||||
auto lines = &m_Lines;
|
||||
m_Disk->addJob([f, lines]() { Flush(lines, f); });
|
||||
m_LastFlush = now;
|
||||
}
|
||||
} // namespace llarp
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <util/logging/logstream.hpp>
|
||||
|
||||
#include <util/thread/thread_pool.hpp>
|
||||
#include <util/thread/queue.hpp>
|
||||
#include <util/time.hpp>
|
||||
|
||||
#include <deque>
|
||||
|
@ -29,14 +30,21 @@ namespace llarp
|
|||
Tick(llarp_time_t now) override;
|
||||
|
||||
void
|
||||
PostLog(std::stringstream&) const override
|
||||
{
|
||||
}
|
||||
PostLog(std::stringstream&) const override{};
|
||||
|
||||
void
|
||||
AppendLog(LogLevel lvl, const char* fname, int lineno,
|
||||
const std::string& nodename, const std::string msg) override;
|
||||
|
||||
using Lines_t = thread::Queue< std::string >;
|
||||
|
||||
protected:
|
||||
std::deque< std::string > m_Lines;
|
||||
Lines_t m_Lines;
|
||||
|
||||
private:
|
||||
static void
|
||||
Flush(Lines_t* const, FILE* const);
|
||||
|
||||
bool
|
||||
ShouldFlush(llarp_time_t now) const;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace llarp
|
|||
obj["line"] = lineno;
|
||||
obj["level"] = LogLevelToString(lvl);
|
||||
obj["message"] = msg;
|
||||
m_Lines.emplace_back(obj.dump());
|
||||
m_Lines.pushBack(obj.dump());
|
||||
}
|
||||
|
||||
} // namespace llarp
|
||||
|
|
|
@ -236,15 +236,29 @@ namespace llarp
|
|||
*/
|
||||
} // namespace llarp
|
||||
|
||||
#define LogTrace(...) _Log(llarp::eLogTrace, LOG_TAG, __LINE__, __VA_ARGS__)
|
||||
#define LogDebug(...) _Log(llarp::eLogDebug, LOG_TAG, __LINE__, __VA_ARGS__)
|
||||
#define LogInfo(...) _Log(llarp::eLogInfo, LOG_TAG, __LINE__, __VA_ARGS__)
|
||||
#define LogWarn(...) _Log(llarp::eLogWarn, LOG_TAG, __LINE__, __VA_ARGS__)
|
||||
#define LogError(...) _Log(llarp::eLogError, LOG_TAG, __LINE__, __VA_ARGS__)
|
||||
|
||||
#define LogTraceTag(tag, ...) _Log(llarp::eLogTrace, tag, __LINE__, __VA_ARGS__)
|
||||
#define LogDebugTag(tag, ...) _Log(llarp::eLogDebug, tag, __LINE__, __VA_ARGS__)
|
||||
#define LogInfoTag(tag, ...) _Log(llarp::eLogInfo, tag, __LINE__, __VA_ARGS__)
|
||||
#define LogWarnTag(tag, ...) _Log(llarp::eLogWarn, tag, __LINE__, __VA_ARGS__)
|
||||
#define LogErrorTag(tag, ...) _Log(llarp::eLogError, tag, __LINE__, __VA_ARGS__)
|
||||
|
||||
#define LogTraceExplicit(tag, line, ...) \
|
||||
_Log(llarp::eLogTrace, tag, line, __VA_ARGS__)
|
||||
#define LogDebugExplicit(tag, line, ...) \
|
||||
_Log(llarp::eLogDebug, tag, line, __VA_ARGS__)
|
||||
#define LogInfoExplicit(tag, line, ...) \
|
||||
_Log(llarp::eLogInfo, tag, line __VA_ARGS__)
|
||||
#define LogWarnExplicit(tag, line, ...) \
|
||||
_Log(llarp::eLogWarn, tag, line, __VA_ARGS__)
|
||||
#define LogErrorExplicit(tag, line, ...) \
|
||||
_Log(llarp::eLogError, tag, line, __VA_ARGS__)
|
||||
|
||||
#ifndef LOG_TAG
|
||||
#define LOG_TAG "default"
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,8 @@ namespace llarp
|
|||
{
|
||||
switch(lvl)
|
||||
{
|
||||
case eLogTrace:
|
||||
return "TRC";
|
||||
case eLogDebug:
|
||||
return "DBG";
|
||||
case eLogInfo:
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace llarp
|
|||
// probably will need to move out of llarp namespace for c api
|
||||
enum LogLevel
|
||||
{
|
||||
eLogTrace,
|
||||
eLogDebug,
|
||||
eLogInfo,
|
||||
eLogWarn,
|
||||
|
|
|
@ -18,7 +18,8 @@ namespace llarp
|
|||
switch(lvl)
|
||||
{
|
||||
case eLogNone:
|
||||
break;
|
||||
return;
|
||||
case eLogTrace:
|
||||
case eLogDebug:
|
||||
ss << (char)27 << "[0m";
|
||||
break;
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace llarp
|
|||
{
|
||||
case eLogNone:
|
||||
return;
|
||||
case eLogTrace:
|
||||
case eLogDebug:
|
||||
::syslog(LOG_DEBUG, "%s", msg.c_str());
|
||||
return;
|
||||
|
|
|
@ -34,6 +34,8 @@ namespace llarp
|
|||
{
|
||||
case eLogNone:
|
||||
break;
|
||||
case eLogTrace:
|
||||
ss << "[TRC] ";
|
||||
case eLogDebug:
|
||||
ss << "[DBG] ";
|
||||
break;
|
||||
|
|
35
llarp/util/lokinet_init.c
Normal file
35
llarp/util/lokinet_init.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include <util/lokinet_init.h>
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include <winuser.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
Lokinet_INIT(void)
|
||||
{
|
||||
static const char *(CDECL * pwine_get_version)(void);
|
||||
HMODULE hntdll = GetModuleHandle("ntdll.dll");
|
||||
if(hntdll)
|
||||
{
|
||||
pwine_get_version = (void *)GetProcAddress(hntdll, "wine_get_version");
|
||||
if(pwine_get_version)
|
||||
{
|
||||
static const char *text =
|
||||
"dont run lokinet in wine like wtf man we support linux and pretty "
|
||||
"much every flavour of BSD, and even some flavours of unix system "
|
||||
"5.x.\nThis Program Will now crash lmao.";
|
||||
static const char *title = "srsly fam wtf";
|
||||
MessageBoxA(NULL, text, title, MB_ICONHAND);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int
|
||||
Lokinet_INIT(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
24
llarp/util/lokinet_init.h
Normal file
24
llarp/util/lokinet_init.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef LLARP_UTIL_LOKINET_INIT_H
|
||||
#define LLARP_UTIL_LOKINET_INIT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifndef Lokinet_INIT
|
||||
#if defined(_WIN32)
|
||||
#define Lokinet_INIT \
|
||||
DieInCaseSomehowThisGetsRunInWineButLikeWTFThatShouldNotHappenButJustInCaseHandleItWithAPopupOrSomeShit
|
||||
#else
|
||||
#define Lokinet_INIT _lokinet_non_shit_platform_INIT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int
|
||||
Lokinet_INIT(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -2,6 +2,7 @@
|
|||
#include <util/thread/timer.hpp>
|
||||
#include <util/logging/logger.hpp>
|
||||
#include <util/mem.h>
|
||||
#include <util/metrics/metrics.hpp>
|
||||
|
||||
#include <future>
|
||||
|
||||
|
@ -13,8 +14,8 @@ namespace llarp
|
|||
llarp_timer_tick_all_async(m_Timer, m_Thread, now);
|
||||
}
|
||||
|
||||
Logic::Logic()
|
||||
: m_Thread(llarp_init_threadpool(1, "llarp-logic"))
|
||||
Logic::Logic(size_t sz)
|
||||
: m_Thread(llarp_init_threadpool(1, "llarp-logic", sz))
|
||||
, m_Timer(llarp_init_timer())
|
||||
{
|
||||
llarp_threadpool_start(m_Thread);
|
||||
|
@ -36,10 +37,17 @@ namespace llarp
|
|||
llarp_free_timer(m_Timer);
|
||||
}
|
||||
|
||||
size_t
|
||||
Logic::numPendingJobs() const
|
||||
{
|
||||
return m_Thread->pendingJobs();
|
||||
}
|
||||
|
||||
bool
|
||||
Logic::queue_job(struct llarp_thread_job job)
|
||||
{
|
||||
return job.user && job.work && queue_func(std::bind(job.work, job.user));
|
||||
return job.user && job.work
|
||||
&& LogicCall(this, std::bind(job.work, job.user));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -47,28 +55,61 @@ namespace llarp
|
|||
{
|
||||
llarp::LogDebug("logic thread stop");
|
||||
// stop all timers from happening in the future
|
||||
queue_func(std::bind(&llarp_timer_stop, m_Timer));
|
||||
LogicCall(this, std::bind(&llarp_timer_stop, m_Timer));
|
||||
// stop all operations on threadpool
|
||||
llarp_threadpool_stop(m_Thread);
|
||||
}
|
||||
|
||||
bool
|
||||
Logic::queue_func(std::function< void(void) > f)
|
||||
Logic::_traceLogicCall(std::function< void(void) > func, const char* tag,
|
||||
int line)
|
||||
{
|
||||
#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();
|
||||
}
|
||||
return llarp_threadpool_queue_job(m_Thread, f);
|
||||
auto ret = llarp_threadpool_queue_job(m_Thread, f);
|
||||
if(not ret)
|
||||
{
|
||||
METRIC("dropped");
|
||||
}
|
||||
return ret;
|
||||
#undef TAG
|
||||
#undef LINE
|
||||
#undef METRIC
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace llarp
|
|||
class Logic
|
||||
{
|
||||
public:
|
||||
Logic();
|
||||
Logic(size_t queueLength = size_t{1024 * 8});
|
||||
|
||||
~Logic();
|
||||
|
||||
|
@ -27,7 +27,8 @@ namespace llarp
|
|||
queue_job(struct llarp_thread_job job);
|
||||
|
||||
bool
|
||||
queue_func(std::function< void(void) > func);
|
||||
_traceLogicCall(std::function< void(void) > func, const char* filename,
|
||||
int lineo);
|
||||
|
||||
uint32_t
|
||||
call_later(const llarp_timeout_job& job);
|
||||
|
@ -41,6 +42,9 @@ namespace llarp
|
|||
void
|
||||
remove_call(uint32_t id);
|
||||
|
||||
size_t
|
||||
numPendingJobs() const;
|
||||
|
||||
bool
|
||||
can_flush() const;
|
||||
|
||||
|
@ -49,7 +53,19 @@ namespace llarp
|
|||
llarp_threadpool* const m_Thread;
|
||||
llarp_timer_context* const m_Timer;
|
||||
absl::optional< ID_t > m_ID;
|
||||
util::ContentionKiller m_Killer;
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
#ifndef LogicCall
|
||||
#if defined(LOKINET_DEBUG)
|
||||
#ifdef LOG_TAG
|
||||
#define LogicCall(l, ...) l->_traceLogicCall(__VA_ARGS__, LOG_TAG, __LINE__)
|
||||
#else
|
||||
#define LogicCall(l, ...) l->_traceLogicCall(__VA_ARGS__, __FILE__, __LINE__)
|
||||
#endif
|
||||
#else
|
||||
#define LogicCall(l, ...) l->_traceLogicCall(__VA_ARGS__, 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -156,6 +156,21 @@ namespace llarp
|
|||
return ::getpid();
|
||||
#endif
|
||||
}
|
||||
|
||||
// type for detecting contention on a resource
|
||||
struct ContentionKiller
|
||||
{
|
||||
template < typename F >
|
||||
void
|
||||
TryAccess(F visit) const
|
||||
{
|
||||
NullLock lock(&__access);
|
||||
visit();
|
||||
}
|
||||
|
||||
private:
|
||||
mutable NullMutex __access;
|
||||
};
|
||||
} // namespace util
|
||||
} // namespace llarp
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
#include <queue>
|
||||
|
||||
struct llarp_threadpool *
|
||||
llarp_init_threadpool(int workers, const char *name)
|
||||
llarp_init_threadpool(int workers, const char *name, size_t queueLength)
|
||||
{
|
||||
if(workers <= 0)
|
||||
workers = 1;
|
||||
return new llarp_threadpool(workers, name);
|
||||
return new llarp_threadpool(workers, name, queueLength);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -19,7 +19,7 @@ struct llarp_threadpool
|
|||
std::unique_ptr< llarp::thread::ThreadPool > impl;
|
||||
|
||||
llarp_threadpool(int workers, llarp::string_view name,
|
||||
size_t queueLength = size_t{1024})
|
||||
size_t queueLength = size_t{1024 * 8})
|
||||
: impl(std::make_unique< llarp::thread::ThreadPool >(
|
||||
workers, std::max(queueLength, size_t{32}), name))
|
||||
{
|
||||
|
@ -48,7 +48,7 @@ struct llarp_threadpool
|
|||
#endif
|
||||
|
||||
struct llarp_threadpool *
|
||||
llarp_init_threadpool(int workers, const char *name);
|
||||
llarp_init_threadpool(int workers, const char *name, size_t queueLength);
|
||||
|
||||
void
|
||||
llarp_free_threadpool(struct llarp_threadpool **tp);
|
||||
|
|
|
@ -45,12 +45,6 @@ namespace llarp
|
|||
{
|
||||
static_cast< timer* >(user)->exec();
|
||||
}
|
||||
|
||||
bool
|
||||
operator<(const timer& other) const
|
||||
{
|
||||
return (started + timeout) < (other.started + other.timeout);
|
||||
}
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
|
@ -59,7 +53,6 @@ struct llarp_timer_context
|
|||
llarp::util::Mutex timersMutex; // protects timers
|
||||
std::unordered_map< uint32_t, std::unique_ptr< llarp::timer > > timers
|
||||
GUARDED_BY(timersMutex);
|
||||
std::priority_queue< std::unique_ptr< llarp::timer > > calling;
|
||||
llarp::util::Mutex tickerMutex;
|
||||
std::unique_ptr< llarp::util::Condition > ticker;
|
||||
absl::Duration nextTickLen = absl::Milliseconds(100);
|
||||
|
@ -230,14 +223,15 @@ llarp_timer_tick_all(struct llarp_timer_context* t)
|
|||
{
|
||||
if(!t->run())
|
||||
return;
|
||||
|
||||
const auto now = llarp::time_now_ms();
|
||||
t->m_Now = now;
|
||||
std::list< std::unique_ptr< llarp::timer > > hit;
|
||||
{
|
||||
llarp::util::Lock lock(&t->timersMutex);
|
||||
auto itr = t->timers.begin();
|
||||
while(itr != t->timers.end())
|
||||
{
|
||||
if(t->m_Now - itr->second->started >= itr->second->timeout
|
||||
if(now - itr->second->started >= itr->second->timeout
|
||||
|| itr->second->canceled)
|
||||
{
|
||||
// timer hit
|
||||
|
@ -253,14 +247,14 @@ llarp_timer_tick_all(struct llarp_timer_context* t)
|
|||
while(not hit.empty())
|
||||
{
|
||||
const auto& h = hit.front();
|
||||
h->called_at = t->m_Now;
|
||||
h->called_at = now;
|
||||
h->exec();
|
||||
hit.pop_front();
|
||||
}
|
||||
// reindex next tick info
|
||||
{
|
||||
llarp::util::Lock lock(&t->timersMutex);
|
||||
t->m_Now = llarp::time_now_ms();
|
||||
t->m_Now = now;
|
||||
t->m_NextRequiredTickAt = std::numeric_limits< llarp_time_t >::max();
|
||||
for(const auto& item : t->timers)
|
||||
{
|
||||
|
|
|
@ -71,12 +71,13 @@ Build requirements:
|
|||
* gcovr (if generating test coverage with gcc)
|
||||
* libuv >= 1.27.0
|
||||
* libsodium (A patch that removes `undocumented system call` from the Win32 build is in `llarp/win32`.)
|
||||
* libcurl
|
||||
|
||||
### Linux
|
||||
|
||||
build:
|
||||
|
||||
$ sudo apt install build-essential cmake git libcap-dev curl libuv1-dev libsodium-dev
|
||||
$ sudo apt install build-essential cmake git libcap-dev curl libuv1-dev libsodium-dev libcurl-dev
|
||||
$ git clone https://github.com/loki-project/loki-network
|
||||
$ cd loki-network
|
||||
$ make
|
||||
|
|
|
@ -18,7 +18,6 @@ list(APPEND TEST_SRC
|
|||
exit/test_llarp_exit_context.cpp
|
||||
link/test_llarp_link.cpp
|
||||
llarp_test.cpp
|
||||
net/test_llarp_net_inaddr.cpp
|
||||
net/test_llarp_net.cpp
|
||||
routing/llarp_routing_transfer_traffic.cpp
|
||||
routing/test_llarp_routing_obtainexitmessage.cpp
|
||||
|
|
|
@ -69,6 +69,8 @@ namespace llarp
|
|||
|
||||
MOCK_METHOD3(pqe_encrypt,
|
||||
bool(PQCipherBlock &, SharedSecret &, const PQPubKey &));
|
||||
|
||||
MOCK_METHOD1(check_identity_privkey, bool(const SecretKey&));
|
||||
};
|
||||
} // namespace test
|
||||
} // namespace llarp
|
||||
|
|
|
@ -127,7 +127,7 @@ struct LinkLayerTest : public test::LlarpTest< llarp::sodium::CryptoLibSodium >
|
|||
Context Bob;
|
||||
|
||||
bool success = false;
|
||||
const bool shouldDebug = true;
|
||||
const bool shouldDebug = false;
|
||||
|
||||
llarp_ev_loop_ptr netLoop;
|
||||
std::shared_ptr< Logic > m_logic;
|
||||
|
@ -144,7 +144,7 @@ struct LinkLayerTest : public test::LlarpTest< llarp::sodium::CryptoLibSodium >
|
|||
{
|
||||
oldLevel = llarp::LogContext::Instance().minLevel;
|
||||
if(shouldDebug)
|
||||
llarp::SetLogLevel(eLogDebug);
|
||||
llarp::SetLogLevel(eLogTrace);
|
||||
oldRCLifetime = RouterContact::Lifetime;
|
||||
RouterContact::BlockBogons = false;
|
||||
RouterContact::Lifetime = 500;
|
||||
|
@ -288,7 +288,7 @@ TEST_F(LinkLayerTest, TestIWP)
|
|||
ASSERT_TRUE(Alice.Start(m_logic, netLoop, AlicePort));
|
||||
ASSERT_TRUE(Bob.Start(m_logic, netLoop, BobPort));
|
||||
|
||||
m_logic->queue_func([&]() { ASSERT_TRUE(Alice.link->TryEstablishTo(Bob.GetRC())); });
|
||||
LogicCall(m_logic, [&]() { ASSERT_TRUE(Alice.link->TryEstablishTo(Bob.GetRC())); });
|
||||
|
||||
RunMainloop();
|
||||
ASSERT_TRUE(Alice.IsGucci());
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include <gtest/gtest.h>
|
||||
|
||||
#include <net/net.hpp>
|
||||
#include <net/net_inaddr.hpp>
|
||||
#include <net/net_int.hpp>
|
||||
#include <net/ip.hpp>
|
||||
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
#include <gtest/gtest.h>
|
||||
|
||||
#include <net/net_inaddr.hpp>
|
||||
|
||||
struct TestNetInAddr : public ::testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(TestNetInAddr, TestinAddrFrom4Int)
|
||||
{
|
||||
llarp::inAddr test;
|
||||
test.from4int(127, 0, 0, 1);
|
||||
char str[INET6_ADDRSTRLEN];
|
||||
if(inet_ntop(AF_INET, &test._addr, str, INET6_ADDRSTRLEN) == NULL)
|
||||
{
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
ASSERT_TRUE(strcmp("127.0.0.1", str) == 0);
|
||||
}
|
||||
|
||||
TEST_F(TestNetInAddr, TestinAddrFromStr)
|
||||
{
|
||||
llarp::inAddr test;
|
||||
test.from_char_array("127.0.0.1");
|
||||
char str[INET6_ADDRSTRLEN];
|
||||
if(inet_ntop(AF_INET, &test._addr, str, INET6_ADDRSTRLEN) == NULL)
|
||||
{
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
ASSERT_TRUE(strcmp("127.0.0.1", str) == 0);
|
||||
}
|
||||
|
||||
TEST_F(TestNetInAddr, TestinAddrReset)
|
||||
{
|
||||
llarp::inAddr test;
|
||||
test.from_char_array("127.0.0.1");
|
||||
test.reset();
|
||||
char str[INET6_ADDRSTRLEN];
|
||||
if(inet_ntop(AF_INET, &test._addr, str, INET6_ADDRSTRLEN) == NULL)
|
||||
{
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
ASSERT_TRUE(strcmp("0.0.0.0", str) == 0);
|
||||
}
|
||||
|
||||
TEST_F(TestNetInAddr, TestinAddrModeSet)
|
||||
{
|
||||
llarp::inAddr test;
|
||||
test.from_char_array("127.0.0.1");
|
||||
// test.hexDebug();
|
||||
ASSERT_TRUE(test.isIPv4Mode());
|
||||
|
||||
// corrupt it
|
||||
test._addr.s6_addr[10] = 0xfe;
|
||||
test._addr.s6_addr[11] = 0xfe;
|
||||
|
||||
test.setIPv4Mode();
|
||||
// test.hexDebug();
|
||||
ASSERT_TRUE(test.isIPv4Mode());
|
||||
}
|
||||
|
||||
TEST_F(TestNetInAddr, TestinAddrSIIT)
|
||||
{
|
||||
llarp::inAddr test;
|
||||
test.from_char_array("127.0.0.1");
|
||||
|
||||
test.toSIIT();
|
||||
// test.hexDebug();
|
||||
ASSERT_TRUE(llarp::ipv6_is_siit(test._addr));
|
||||
|
||||
test.fromSIIT();
|
||||
// test.hexDebug();
|
||||
ASSERT_TRUE(!llarp::ipv6_is_siit(test._addr));
|
||||
}
|
||||
|
||||
TEST_F(TestNetInAddr, TestinAddrN32)
|
||||
{
|
||||
llarp::inAddr test;
|
||||
test.from_char_array("127.0.0.1");
|
||||
llarp::nuint32_t netOrder = test.toN32();
|
||||
llarp::inAddr test2;
|
||||
test2.fromN32(netOrder);
|
||||
char str[INET6_ADDRSTRLEN];
|
||||
if(inet_ntop(AF_INET, &test2._addr, str, INET6_ADDRSTRLEN) == NULL)
|
||||
{
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
// printf("[%s]\n", str);
|
||||
ASSERT_TRUE(strcmp("127.0.0.1", str) == 0);
|
||||
}
|
||||
|
||||
TEST_F(TestNetInAddr, TestinAddrH32)
|
||||
{
|
||||
llarp::inAddr test;
|
||||
test.from_char_array("127.0.0.1");
|
||||
llarp::huint32_t netOrder = test.toH32();
|
||||
llarp::inAddr test2;
|
||||
test2.fromH32(netOrder);
|
||||
char str[INET6_ADDRSTRLEN];
|
||||
if(inet_ntop(AF_INET, &test2._addr, str, INET6_ADDRSTRLEN) == NULL)
|
||||
{
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
// printf("[%s]\n", str);
|
||||
ASSERT_TRUE(strcmp("127.0.0.1", str) == 0);
|
||||
}
|
|
@ -10,11 +10,11 @@ using System.Runtime.InteropServices;
|
|||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("LokiNET")]
|
||||
[assembly: AssemblyDescription("LokiNET end-user UI")]
|
||||
[assembly: AssemblyTitle("Lokinet for Windows")]
|
||||
[assembly: AssemblyDescription("Lokinet end-user UI")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Loki Project")]
|
||||
[assembly: AssemblyProduct("LokiNET Launcher")]
|
||||
[assembly: AssemblyProduct("Lokinet Launcher")]
|
||||
[assembly: AssemblyCopyright("Copyright ©2018-2019 Loki Project. All rights reserved. See LICENSE for more details.")]
|
||||
[assembly: AssemblyTrademark("Loki, Loki Project, LokiNET are ™ & ©2018-2019 Loki Foundation")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
@ -37,10 +37,10 @@ using System.Runtime.InteropServices;
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("0.5.2")]
|
||||
[assembly: AssemblyFileVersion("0.5.2")]
|
||||
[assembly: AssemblyVersion("0.6.0")]
|
||||
[assembly: AssemblyFileVersion("0.6.0")]
|
||||
#if DEBUG
|
||||
[assembly: AssemblyInformationalVersion("0.5.2-dev-{chash:8}")]
|
||||
[assembly: AssemblyInformationalVersion("0.6.0-dev-{chash:8}")]
|
||||
#else
|
||||
[assembly: AssemblyInformationalVersion("0.5.2 (RELEASE_CODENAME)")]
|
||||
[assembly: AssemblyInformationalVersion("0.6.0 (RELEASE_CODENAME)")]
|
||||
#endif
|
120
ui-win32/dlgBootstrap.Designer.cs
generated
120
ui-win32/dlgBootstrap.Designer.cs
generated
|
@ -28,66 +28,66 @@
|
|||
/// </summary>
|
||||
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
|
||||
|
|
|
@ -1,276 +1,279 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="label1.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
</data>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="label1.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>13, 13</value>
|
||||
</data>
|
||||
<data name="label1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>196, 13</value>
|
||||
</data>
|
||||
<data name="label1.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>0</value>
|
||||
</data>
|
||||
<data name="label1.Text" xml:space="preserve">
|
||||
<value>Enter a URI to a node to bootstrap from:</value>
|
||||
</data>
|
||||
<data name=">>label1.Name" xml:space="preserve">
|
||||
<value>label1</value>
|
||||
</data>
|
||||
<data name=">>label1.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>label1.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>label1.ZOrder" xml:space="preserve">
|
||||
<value>4</value>
|
||||
</data>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="uriBox.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Left, Right</value>
|
||||
</data>
|
||||
<data name="uriBox.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>12, 29</value>
|
||||
</data>
|
||||
<data name="uriBox.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>520, 20</value>
|
||||
</data>
|
||||
<data name="uriBox.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>1</value>
|
||||
</data>
|
||||
<data name=">>uriBox.Name" xml:space="preserve">
|
||||
<value>uriBox</value>
|
||||
</data>
|
||||
<data name=">>uriBox.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>uriBox.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>uriBox.ZOrder" xml:space="preserve">
|
||||
<value>3</value>
|
||||
</data>
|
||||
<data name="label2.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
</data>
|
||||
<data name="label2.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>12, 52</value>
|
||||
</data>
|
||||
<data name="label2.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>347, 13</value>
|
||||
</data>
|
||||
<data name="label2.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>2</value>
|
||||
</data>
|
||||
<data name="label2.Text" xml:space="preserve">
|
||||
<value>This file is automatically saved as $APPDATA\.lokinet\bootstrap.signed.</value>
|
||||
</data>
|
||||
<data name=">>label2.Name" xml:space="preserve">
|
||||
<value>label2</value>
|
||||
</data>
|
||||
<data name=">>label2.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>label2.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>label2.ZOrder" xml:space="preserve">
|
||||
<value>2</value>
|
||||
</data>
|
||||
<data name="btnDownload.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Bottom</value>
|
||||
</data>
|
||||
<data name="btnDownload.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>196, 75</value>
|
||||
</data>
|
||||
<data name="btnDownload.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>75, 23</value>
|
||||
</data>
|
||||
<data name="btnDownload.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>3</value>
|
||||
</data>
|
||||
<data name="btnDownload.Text" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
</data>
|
||||
<data name=">>btnDownload.Name" xml:space="preserve">
|
||||
<value>btnDownload</value>
|
||||
</data>
|
||||
<data name=">>btnDownload.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>btnDownload.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>btnDownload.ZOrder" xml:space="preserve">
|
||||
<value>1</value>
|
||||
</data>
|
||||
<data name="btnCancel.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Bottom</value>
|
||||
</data>
|
||||
<data name="btnCancel.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>278, 75</value>
|
||||
</data>
|
||||
<data name="btnCancel.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>75, 23</value>
|
||||
</data>
|
||||
<data name="btnCancel.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>4</value>
|
||||
</data>
|
||||
<data name="btnCancel.Text" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name=">>btnCancel.Name" xml:space="preserve">
|
||||
<value>btnCancel</value>
|
||||
</data>
|
||||
<data name=">>btnCancel.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>btnCancel.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>btnCancel.ZOrder" xml:space="preserve">
|
||||
<value>0</value>
|
||||
</data>
|
||||
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
|
||||
<value>6, 13</value>
|
||||
</data>
|
||||
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
|
||||
<value>548, 111</value>
|
||||
</data>
|
||||
<data name="$this.StartPosition" type="System.Windows.Forms.FormStartPosition, System.Windows.Forms">
|
||||
<value>CenterParent</value>
|
||||
</data>
|
||||
<data name="$this.Text" xml:space="preserve">
|
||||
<value>bootstrap from web...</value>
|
||||
</data>
|
||||
<data name=">>$this.Name" xml:space="preserve">
|
||||
<value>bootstrap</value>
|
||||
</data>
|
||||
<data name=">>$this.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="label1.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
</data>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="label1.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>13, 13</value>
|
||||
</data>
|
||||
<data name="label1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>196, 13</value>
|
||||
</data>
|
||||
<data name="label1.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>0</value>
|
||||
</data>
|
||||
<data name="label1.Text" xml:space="preserve">
|
||||
<value>Enter a URI to a node to bootstrap from:</value>
|
||||
</data>
|
||||
<data name=">>label1.Name" xml:space="preserve">
|
||||
<value>label1</value>
|
||||
</data>
|
||||
<data name=">>label1.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>label1.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>label1.ZOrder" xml:space="preserve">
|
||||
<value>4</value>
|
||||
</data>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="uriBox.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Left, Right</value>
|
||||
</data>
|
||||
<data name="uriBox.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>12, 29</value>
|
||||
</data>
|
||||
<data name="uriBox.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>520, 20</value>
|
||||
</data>
|
||||
<data name="uriBox.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>1</value>
|
||||
</data>
|
||||
<data name="uriBox.Text" xml:space="preserve">
|
||||
<value>https://seed.lokinet.org/bootstrap.signed</value>
|
||||
</data>
|
||||
<data name=">>uriBox.Name" xml:space="preserve">
|
||||
<value>uriBox</value>
|
||||
</data>
|
||||
<data name=">>uriBox.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>uriBox.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>uriBox.ZOrder" xml:space="preserve">
|
||||
<value>3</value>
|
||||
</data>
|
||||
<data name="label2.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
</data>
|
||||
<data name="label2.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>12, 52</value>
|
||||
</data>
|
||||
<data name="label2.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>347, 13</value>
|
||||
</data>
|
||||
<data name="label2.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>2</value>
|
||||
</data>
|
||||
<data name="label2.Text" xml:space="preserve">
|
||||
<value>This file is automatically saved as $APPDATA\.lokinet\bootstrap.signed.</value>
|
||||
</data>
|
||||
<data name=">>label2.Name" xml:space="preserve">
|
||||
<value>label2</value>
|
||||
</data>
|
||||
<data name=">>label2.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>label2.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>label2.ZOrder" xml:space="preserve">
|
||||
<value>2</value>
|
||||
</data>
|
||||
<data name="btnDownload.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Bottom</value>
|
||||
</data>
|
||||
<data name="btnDownload.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>196, 75</value>
|
||||
</data>
|
||||
<data name="btnDownload.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>75, 23</value>
|
||||
</data>
|
||||
<data name="btnDownload.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>3</value>
|
||||
</data>
|
||||
<data name="btnDownload.Text" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
</data>
|
||||
<data name=">>btnDownload.Name" xml:space="preserve">
|
||||
<value>btnDownload</value>
|
||||
</data>
|
||||
<data name=">>btnDownload.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>btnDownload.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>btnDownload.ZOrder" xml:space="preserve">
|
||||
<value>1</value>
|
||||
</data>
|
||||
<data name="btnCancel.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Bottom</value>
|
||||
</data>
|
||||
<data name="btnCancel.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>278, 75</value>
|
||||
</data>
|
||||
<data name="btnCancel.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>75, 23</value>
|
||||
</data>
|
||||
<data name="btnCancel.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>4</value>
|
||||
</data>
|
||||
<data name="btnCancel.Text" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name=">>btnCancel.Name" xml:space="preserve">
|
||||
<value>btnCancel</value>
|
||||
</data>
|
||||
<data name=">>btnCancel.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>btnCancel.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>btnCancel.ZOrder" xml:space="preserve">
|
||||
<value>0</value>
|
||||
</data>
|
||||
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
|
||||
<value>6, 13</value>
|
||||
</data>
|
||||
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
|
||||
<value>548, 111</value>
|
||||
</data>
|
||||
<data name="$this.StartPosition" type="System.Windows.Forms.FormStartPosition, System.Windows.Forms">
|
||||
<value>CenterParent</value>
|
||||
</data>
|
||||
<data name="$this.Text" xml:space="preserve">
|
||||
<value>bootstrap from web...</value>
|
||||
</data>
|
||||
<data name=">>$this.Name" xml:space="preserve">
|
||||
<value>dlgBootstrap</value>
|
||||
</data>
|
||||
<data name=">>$this.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
</root>
|
Loading…
Reference in a new issue