mirror of
https://github.com/oxen-io/lokinet
synced 2023-12-14 06:53:00 +01:00
awe yeh
This commit is contained in:
parent
773eb21a71
commit
4718281202
13 changed files with 410 additions and 60 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -5,4 +5,7 @@
|
|||
*.o
|
||||
*.plist
|
||||
|
||||
llarpd
|
||||
llarpd
|
||||
|
||||
*.test
|
||||
*.bin
|
31
Makefile
31
Makefile
|
@ -11,8 +11,18 @@ STATIC_OBJ = $(STATIC_SRC_CPP:.cpp=.cpp.o) $(STATIC_SRC_C:.c=.c.o)
|
|||
DAEMON_SRC = $(wildcard $(REPO)/daemon/*.c)
|
||||
DAEMON_OBJ = $(DAEMON_SRC:.c=.c.o)
|
||||
|
||||
TEST_SRC_C = $(wildcard $(REPO)/test/*.c)
|
||||
TEST_SRC_CPP = $(wildcard $(REPO)/test/*.cpp)
|
||||
|
||||
TEST_OBJ_C = $(TEST_SRC_C:.c=.c.bin)
|
||||
TEST_OBJ_CPP = $(TEST_SRC_CPP:.cpp=.cpp.bin)
|
||||
|
||||
TEST_SRC = $(TEST_SRC_C) $(TEST_SRC_CPP)
|
||||
|
||||
TEST_OBJ = $(TEST_OBJ_C) $(TEST_OBJ_CPP)
|
||||
|
||||
HDRS = $(wildcard $(REPO)/llarp/*.hpp) $(wildcard $(REPO)/include/*/*.h)
|
||||
SRCS = $(DAEMON_SRC) $(STATIC_SRC_CPP) $(STATIC_SRC_C)
|
||||
SRCS = $(DAEMON_SRC) $(STATIC_SRC_CPP) $(STATIC_SRC_C) $(TEST_SRC_C) $(TEST_SRC_CPP)
|
||||
FORMAT = clang-format
|
||||
|
||||
SODIUM_FLAGS = $(shell pkg-config --cflags libsodium)
|
||||
|
@ -31,7 +41,7 @@ endif
|
|||
|
||||
REQUIRED_CFLAGS = $(LIBUV_FLAGS) $(SODIUM_FLAGS) -I$(REPO)/include -std=c99 $(CFLAGS) $(DEBUG_FLAGS) $(VER_FLAGS)
|
||||
REQUIRED_CXXFLAGS = $(LIBUV_FLAGS) $(SODIUM_FLAGS) -I$(REPO)/include -std=c++17 $(CXXFLAGS) $(DEBUG_FLAGS) $(VER_FLAGS)
|
||||
REQUIRED_LDFLAGS = $(LDFLAGS) -ljemalloc $(SODIUM_LIBS) $(LIBUV_LIBS)
|
||||
REQUIRED_LDFLAGS = $(LDFLAGS) -ljemalloc $(SODIUM_LIBS) $(LIBUV_LIBS) -lm -lstdc++
|
||||
|
||||
all: build
|
||||
|
||||
|
@ -40,6 +50,21 @@ format: $(HDRS) $(SRCS)
|
|||
|
||||
build: $(EXE)
|
||||
|
||||
test: $(TEST_OBJ_CPP) $(TEST_OBJ_C)
|
||||
|
||||
|
||||
$(TEST_SRC): $(STATIC_LIB)
|
||||
|
||||
$(TEST_OBJ_CPP): $(TEST_SRC_CPP)
|
||||
$(CXX) $(REQUIRED_CXXFLAGS) $< -o $<.bin $(STATIC_LIB) $(REQUIRED_LDFLAGS)
|
||||
mv $<.bin $<.test
|
||||
$<.test
|
||||
|
||||
$(TEST_OBJ_C): $(TEST_SRC_C)
|
||||
$(CC) $(REQUIRED_CFLAGS) $< -o $<.bin $(STATIC_LIB) $(REQUIRED_LDFLAGS)
|
||||
mv $<.bin $<.test
|
||||
$<.test
|
||||
|
||||
$(EXE): $(DAEMON_OBJ) $(STATIC_LIB)
|
||||
$(CXX) $(DAEMON_OBJ) $(STATIC_LIB) $(REQUIRED_LDFLAGS) -o $(EXE)
|
||||
|
||||
|
@ -53,4 +78,4 @@ $(STATIC_LIB): $(STATIC_OBJ)
|
|||
$(AR) -r $(STATIC_LIB) $(STATIC_OBJ)
|
||||
|
||||
clean:
|
||||
$(RM) $(DAEMON_OBJ) $(EXE) $(STATIC_OBJ) $(STATIC_LIB)
|
||||
$(RM) $(DAEMON_OBJ) $(EXE) $(STATIC_OBJ) $(STATIC_LIB) $(TEST_OBJ)
|
||||
|
|
|
@ -25,16 +25,24 @@ typedef uint8_t llarp_hmacsec_t[HMACSECSIZE];
|
|||
typedef uint8_t llarp_sig_t[SIGSIZE];
|
||||
typedef uint8_t llarp_tunnel_nounce_t[TUNNOUNCESIZE];
|
||||
|
||||
struct llarp_keypair
|
||||
{
|
||||
llarp_pubkey_t pub;
|
||||
llarp_seckey_t sec;
|
||||
};
|
||||
|
||||
typedef bool (*llarp_dh_func)(llarp_sharedkey_t *, llarp_pubkey_t, llarp_tunnel_nounce_t, llarp_seckey_t);
|
||||
|
||||
struct llarp_crypto {
|
||||
bool (*xchacha20)(llarp_buffer_t, llarp_sharedkey_t, llarp_nounce_t);
|
||||
bool (*dh_client)(llarp_sharedkey_t *, llarp_pubkey_t, llarp_tunnel_nounce_t,
|
||||
llarp_seckey_t);
|
||||
bool (*dh_server)(llarp_sharedkey_t *, llarp_pubkey_t, llarp_tunnel_nounce_t,
|
||||
llarp_seckey_t);
|
||||
llarp_dh_func dh_client;
|
||||
llarp_dh_func dh_server;
|
||||
bool (*hash)(llarp_hash_t *, llarp_buffer_t);
|
||||
bool (*hmac)(llarp_hash_t *, llarp_buffer_t, llarp_hmacsec_t);
|
||||
bool (*sign)(llarp_sig_t *, llarp_seckey_t, llarp_buffer_t);
|
||||
bool (*verify)(llarp_pubkey_t, llarp_buffer_t, llarp_sig_t);
|
||||
void (*randomize)(llarp_buffer_t);
|
||||
void (*keygen)(struct llarp_keypair *);
|
||||
};
|
||||
|
||||
void llarp_crypto_libsodium_init(struct llarp_crypto *c);
|
||||
|
|
37
include/llarp/crypto_async.h
Normal file
37
include/llarp/crypto_async.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef LLARP_CRYPTO_ASYNC_H_
|
||||
#define LLARP_CRYPTO_ASYNC_H_
|
||||
#include <llarp/crypto.h>
|
||||
#include <llarp/ev.h>
|
||||
#include <llarp/threadpool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct llarp_async_dh;
|
||||
|
||||
struct llarp_async_dh * llarp_async_dh_new(struct llarp_crypto * crypto, struct llarp_ev_loop * ev, struct llarp_threadpool * tp);
|
||||
void llarp_async_dh_free(struct llarp_async_dh ** dh);
|
||||
|
||||
struct llarp_dh_result;
|
||||
|
||||
typedef void (*llarp_dh_complete_hook)(struct llarp_dh_result *);
|
||||
|
||||
|
||||
struct llarp_dh_internal;
|
||||
|
||||
struct llarp_dh_result
|
||||
{
|
||||
struct llarp_dh_internal * impl;
|
||||
llarp_sharedkey_t result;
|
||||
void * user;
|
||||
llarp_dh_complete_hook hook;
|
||||
};
|
||||
|
||||
void llarp_async_client_dh(struct llarp_async_dh * dh, llarp_seckey_t ourkey, llarp_pubkey_t theirkey, llarp_tunnel_nounce_t nounce, llarp_dh_complete_hook result, void * user);
|
||||
void llarp_async_server_dh(struct llarp_async_dh * dh, llarp_seckey_t ourkey, llarp_pubkey_t theirkey, llarp_tunnel_nounce_t nounce, llarp_dh_complete_hook result, void * user);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -34,21 +34,33 @@ int llarp_ev_add_udp_listener(struct llarp_ev_loop *ev,
|
|||
|
||||
int llarp_ev_close_udp_listener(struct llarp_udp_listener *listener);
|
||||
|
||||
struct llarp_ev_job {
|
||||
struct llarp_ev_async_call;
|
||||
|
||||
typedef void (*llarp_ev_work_func)(struct llarp_ev_async_call *);
|
||||
|
||||
|
||||
struct llarp_ev_caller;
|
||||
|
||||
struct llarp_ev_async_call {
|
||||
/** the loop this job belongs to */
|
||||
struct llarp_ev_loop *loop;
|
||||
const struct llarp_ev_loop *loop;
|
||||
/** private implementation */
|
||||
const struct llarp_ev_caller * parent;
|
||||
/** user data */
|
||||
void *user;
|
||||
/** work is called async when ready in the event loop thread */
|
||||
void (*work)(struct llarp_ev_job *);
|
||||
const void *user;
|
||||
/**
|
||||
work is called async when ready in the event loop thread
|
||||
must not free from inside this call as it is done elsewhere
|
||||
*/
|
||||
const llarp_ev_work_func work;
|
||||
};
|
||||
|
||||
/**
|
||||
call work async in event loop thread (thread safe)
|
||||
return true if we queued the job otherwise return false
|
||||
*/
|
||||
bool llarp_ev_async(struct llarp_ev_loop *ev, struct llarp_ev_job job);
|
||||
struct llarp_ev_caller * llarp_ev_prepare_async(struct llarp_ev_loop *ev, llarp_ev_work_func func);
|
||||
|
||||
bool llarp_ev_call_async(struct llarp_ev_caller * c, void * user);
|
||||
|
||||
void llarp_ev_caller_stop(struct llarp_ev_caller * c);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -10,16 +10,21 @@ struct llarp_threadpool;
|
|||
struct llarp_threadpool *llarp_init_threadpool(int workers);
|
||||
void llarp_free_threadpool(struct llarp_threadpool **tp);
|
||||
|
||||
typedef void (*llarp_thread_work_func)(void*);
|
||||
|
||||
|
||||
/** job to be done in worker thread */
|
||||
struct llarp_thread_job {
|
||||
/**
|
||||
called async after work is executed
|
||||
*/
|
||||
struct llarp_ev_job *result;
|
||||
struct llarp_ev_caller * caller;
|
||||
void * data;
|
||||
|
||||
/** user data to pass to work function */
|
||||
void *user;
|
||||
/** called in threadpool worker thread */
|
||||
void (*work)(void *);
|
||||
llarp_thread_work_func work;
|
||||
};
|
||||
|
||||
void llarp_threadpool_queue_job(struct llarp_threadpool *tp,
|
||||
|
|
85
llarp/crypto_async.c
Normal file
85
llarp/crypto_async.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
#include <llarp/crypto_async.h>
|
||||
#include <llarp/mem.h>
|
||||
#include <string.h>
|
||||
|
||||
struct llarp_async_dh
|
||||
{
|
||||
llarp_dh_func client;
|
||||
llarp_dh_func server;
|
||||
struct llarp_threadpool * tp;
|
||||
struct llarp_ev_caller * caller;
|
||||
};
|
||||
|
||||
struct llarp_dh_internal
|
||||
{
|
||||
llarp_dh_func func;
|
||||
llarp_pubkey_t theirkey;
|
||||
llarp_seckey_t ourkey;
|
||||
llarp_tunnel_nounce_t nounce;
|
||||
struct llarp_dh_result result;
|
||||
};
|
||||
|
||||
static void llarp_crypto_dh_work(void * user)
|
||||
{
|
||||
struct llarp_dh_internal * impl = (struct llarp_dh_internal *)user;
|
||||
impl->func(&impl->result.result, impl->theirkey, impl->nounce, impl->ourkey);
|
||||
}
|
||||
|
||||
static void llarp_crypto_dh_result(struct llarp_ev_async_call * call)
|
||||
{
|
||||
struct llarp_dh_internal * impl = (struct llarp_dh_internal *) call->user;
|
||||
impl->result.hook(&impl->result);
|
||||
llarp_g_mem.free(impl);
|
||||
}
|
||||
|
||||
static void llarp_async_dh_exec(struct llarp_async_dh * dh, llarp_dh_func func, llarp_seckey_t ourkey, llarp_pubkey_t theirkey, llarp_tunnel_nounce_t nounce, llarp_dh_complete_hook result, void * user)
|
||||
{
|
||||
struct llarp_dh_internal * impl = llarp_g_mem.alloc(sizeof(struct llarp_dh_internal), 16);
|
||||
memcpy(impl->theirkey, theirkey, sizeof(llarp_pubkey_t));
|
||||
memcpy(impl->ourkey, ourkey, sizeof(llarp_seckey_t));
|
||||
memcpy(impl->nounce, nounce, sizeof(llarp_tunnel_nounce_t));
|
||||
impl->result.impl = impl;
|
||||
impl->result.user = user;
|
||||
impl->result.hook = result;
|
||||
impl->func = func;
|
||||
struct llarp_thread_job job = {
|
||||
.caller = dh->caller,
|
||||
.data = impl,
|
||||
.user = impl,
|
||||
.work = &llarp_crypto_dh_work
|
||||
};
|
||||
llarp_threadpool_queue_job(dh->tp, job);
|
||||
}
|
||||
|
||||
|
||||
void llarp_async_client_dh(struct llarp_async_dh * dh, llarp_seckey_t ourkey, llarp_pubkey_t theirkey, llarp_tunnel_nounce_t nounce, llarp_dh_complete_hook result, void * user)
|
||||
{
|
||||
llarp_async_dh_exec(dh, dh->client, ourkey, theirkey, nounce, result, user);
|
||||
}
|
||||
|
||||
void llarp_async_server_dh(struct llarp_async_dh * dh, llarp_seckey_t ourkey, llarp_pubkey_t theirkey, llarp_tunnel_nounce_t nounce, llarp_dh_complete_hook result, void * user)
|
||||
{
|
||||
llarp_async_dh_exec(dh, dh->server, ourkey, theirkey, nounce, result, user);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct llarp_async_dh * llarp_async_dh_new(struct llarp_crypto * crypto, struct llarp_ev_loop * ev, struct llarp_threadpool * tp)
|
||||
{
|
||||
struct llarp_async_dh * dh = llarp_g_mem.alloc(sizeof(struct llarp_async_dh), 16);
|
||||
dh->client = crypto->dh_client;
|
||||
dh->server = crypto->dh_server;
|
||||
dh->tp = tp;
|
||||
dh->caller = llarp_ev_prepare_async(ev, &llarp_crypto_dh_result);
|
||||
return dh;
|
||||
}
|
||||
|
||||
void llarp_async_dh_free(struct llarp_async_dh ** dh)
|
||||
{
|
||||
if(*dh)
|
||||
{
|
||||
llarp_ev_caller_stop((*dh)->caller);
|
||||
llarp_g_mem.free(*dh);
|
||||
*dh = NULL;
|
||||
}
|
||||
}
|
|
@ -1,17 +1,15 @@
|
|||
#include <llarp/crypto.h>
|
||||
#include <sodium/crypto_generichash.h>
|
||||
#include <sodium/crypto_scalarmult.h>
|
||||
#include <sodium/crypto_sign.h>
|
||||
#include <sodium/crypto_stream_xchacha20.h>
|
||||
#include <sodium.h>
|
||||
#include <assert.h>
|
||||
|
||||
namespace llarp {
|
||||
namespace sodium {
|
||||
bool xchacha20(llarp_buffer_t buff, llarp_sharedkey_t k, llarp_nounce_t n) {
|
||||
static bool xchacha20(llarp_buffer_t buff, llarp_sharedkey_t k, llarp_nounce_t n) {
|
||||
uint8_t *base = (uint8_t *)buff.base;
|
||||
return crypto_stream_xchacha20_xor(base, base, buff.sz, n, k) == 0;
|
||||
}
|
||||
|
||||
bool dh(llarp_sharedkey_t *shared, uint8_t *client_pk, uint8_t *server_pk,
|
||||
static bool dh(llarp_sharedkey_t *shared, uint8_t *client_pk, uint8_t *server_pk,
|
||||
uint8_t *remote_key, uint8_t *local_key) {
|
||||
uint8_t *out = *shared;
|
||||
const size_t outsz = SHAREDKEYSIZE;
|
||||
|
@ -26,7 +24,7 @@ bool dh(llarp_sharedkey_t *shared, uint8_t *client_pk, uint8_t *server_pk,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool dh_client(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
|
||||
static bool dh_client(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
|
||||
llarp_tunnel_nounce_t n, llarp_seckey_t sk) {
|
||||
llarp_pubkey_t local_pk;
|
||||
crypto_scalarmult_base(local_pk, sk);
|
||||
|
@ -37,7 +35,7 @@ bool dh_client(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool dh_server(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
|
||||
static bool dh_server(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
|
||||
llarp_tunnel_nounce_t n, llarp_seckey_t sk) {
|
||||
llarp_pubkey_t local_pk;
|
||||
crypto_scalarmult_base(local_pk, sk);
|
||||
|
@ -48,31 +46,44 @@ bool dh_server(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool hash(llarp_hash_t *result, llarp_buffer_t buff) {
|
||||
static bool hash(llarp_hash_t *result, llarp_buffer_t buff) {
|
||||
const uint8_t *base = (const uint8_t *)buff.base;
|
||||
return crypto_generichash(*result, HASHSIZE, base, buff.sz, nullptr, 0) != -1;
|
||||
}
|
||||
|
||||
bool hmac(llarp_hash_t *result, llarp_buffer_t buff, llarp_seckey_t secret) {
|
||||
static bool hmac(llarp_hash_t *result, llarp_buffer_t buff, llarp_seckey_t secret) {
|
||||
const uint8_t *base = (const uint8_t *)buff.base;
|
||||
return crypto_generichash(*result, sizeof(llarp_hash_t), base, buff.sz,
|
||||
secret, HMACSECSIZE) != -1;
|
||||
}
|
||||
|
||||
bool sign(llarp_sig_t *result, llarp_seckey_t secret, llarp_buffer_t buff) {
|
||||
static bool sign(llarp_sig_t *result, llarp_seckey_t secret, llarp_buffer_t buff) {
|
||||
const uint8_t *base = (const uint8_t *)buff.base;
|
||||
return crypto_sign_detached(*result, nullptr, base, buff.sz, secret) != -1;
|
||||
}
|
||||
|
||||
bool verify(llarp_pubkey_t pub, llarp_buffer_t buff, llarp_sig_t sig) {
|
||||
static bool verify(llarp_pubkey_t pub, llarp_buffer_t buff, llarp_sig_t sig) {
|
||||
const uint8_t *base = (const uint8_t *)buff.base;
|
||||
return crypto_sign_verify_detached(sig, base, buff.sz, pub) != -1;
|
||||
}
|
||||
|
||||
static void randomize(llarp_buffer_t buff)
|
||||
{
|
||||
randombytes((unsigned char *)buff.base, buff.sz);
|
||||
}
|
||||
|
||||
static void keygen(struct llarp_keypair * keys)
|
||||
{
|
||||
randombytes(keys->sec, sizeof(llarp_seckey_t));
|
||||
unsigned char sk[64];
|
||||
crypto_sign_seed_keypair(keys->pub, sk, keys->sec);
|
||||
}
|
||||
} // namespace sodium
|
||||
} // namespace llarp
|
||||
|
||||
extern "C" {
|
||||
void llarp_crypto_libsodium_init(struct llarp_crypto *c) {
|
||||
assert(sodium_init() != -1);
|
||||
c->xchacha20 = llarp::sodium::xchacha20;
|
||||
c->dh_client = llarp::sodium::dh_client;
|
||||
c->dh_server = llarp::sodium::dh_server;
|
||||
|
@ -80,5 +91,7 @@ void llarp_crypto_libsodium_init(struct llarp_crypto *c) {
|
|||
c->hmac = llarp::sodium::hmac;
|
||||
c->sign = llarp::sodium::sign;
|
||||
c->verify = llarp::sodium::verify;
|
||||
c->randomize = llarp::sodium::randomize;
|
||||
c->keygen = llarp::sodium::keygen;
|
||||
}
|
||||
}
|
||||
|
|
113
llarp/ev.cpp
113
llarp/ev.cpp
|
@ -2,6 +2,65 @@
|
|||
#include <llarp/ev.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
struct llarp_ev_caller
|
||||
{
|
||||
static void * operator new(size_t sz)
|
||||
{
|
||||
return llarp::Alloc<llarp_ev_caller>();
|
||||
}
|
||||
|
||||
static void operator delete(void * ptr)
|
||||
{
|
||||
llarp_g_mem.free(ptr);
|
||||
}
|
||||
|
||||
|
||||
llarp_ev_caller(llarp_ev_loop * ev, llarp_ev_work_func func) :
|
||||
loop(ev),
|
||||
work(func)
|
||||
{
|
||||
async.data = this;
|
||||
}
|
||||
|
||||
~llarp_ev_caller()
|
||||
{
|
||||
}
|
||||
|
||||
bool appendCall(void * user)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(access);
|
||||
bool should = pending.size() == 0;
|
||||
llarp_ev_async_call * call = new llarp_ev_async_call{
|
||||
loop,
|
||||
this,
|
||||
user,
|
||||
this->work};
|
||||
pending.push(call);
|
||||
return should;
|
||||
}
|
||||
|
||||
void Call()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(access);
|
||||
while(pending.size() > 0)
|
||||
{
|
||||
auto & front = pending.front();
|
||||
front->work(front);
|
||||
pending.pop();
|
||||
}
|
||||
}
|
||||
|
||||
std::mutex access;
|
||||
struct llarp_ev_loop * loop;
|
||||
uv_async_t async;
|
||||
std::queue<llarp_ev_async_call *> pending;
|
||||
llarp_ev_work_func work;
|
||||
};
|
||||
|
||||
|
||||
struct llarp_ev_loop {
|
||||
uv_loop_t _loop;
|
||||
|
||||
|
@ -61,16 +120,14 @@ static void udp_close_cb(uv_handle_t *handle) {
|
|||
|
||||
namespace llarp {
|
||||
|
||||
static void ev_handle_async_closed(uv_handle_t *handle) {
|
||||
struct llarp_ev_job *ev = static_cast<llarp_ev_job *>(handle->data);
|
||||
llarp_g_mem.free(ev);
|
||||
llarp_g_mem.free(handle);
|
||||
static void ev_caller_async_closed(uv_handle_t *handle) {
|
||||
llarp_ev_caller *caller = static_cast<llarp_ev_caller *>(handle->data);
|
||||
delete caller;
|
||||
}
|
||||
|
||||
static void ev_handle_async(uv_async_t *handle) {
|
||||
struct llarp_ev_job *ev = static_cast<llarp_ev_job *>(handle->data);
|
||||
ev->work(ev);
|
||||
uv_close((uv_handle_t *)handle, ev_handle_async_closed);
|
||||
static void ev_handle_async_call(uv_async_t *handle) {
|
||||
llarp_ev_caller * caller = static_cast<llarp_ev_caller *>(handle->data);
|
||||
caller->Call();
|
||||
}
|
||||
} // namespace llarp
|
||||
|
||||
|
@ -132,23 +189,29 @@ int llarp_ev_close_udp_listener(struct llarp_udp_listener *listener) {
|
|||
|
||||
void llarp_ev_loop_stop(struct llarp_ev_loop *loop) { uv_stop(loop->loop()); }
|
||||
|
||||
bool llarp_ev_async(struct llarp_ev_loop *loop, struct llarp_ev_job job) {
|
||||
struct llarp_ev_job *job_copy =
|
||||
static_cast<struct llarp_ev_job *>(llarp_g_mem.alloc(
|
||||
sizeof(struct llarp_ev_job), llarp::alignment<llarp_ev_job>()));
|
||||
job_copy->work = job.work;
|
||||
job_copy->loop = loop;
|
||||
job_copy->user = job.user;
|
||||
uv_async_t *async = static_cast<uv_async_t *>(
|
||||
llarp_g_mem.alloc(sizeof(uv_async_t), llarp::alignment<uv_async_t>()));
|
||||
async->data = job_copy;
|
||||
if (uv_async_init(loop->loop(), async, llarp::ev_handle_async) == 0 &&
|
||||
uv_async_send(async))
|
||||
return true;
|
||||
else {
|
||||
llarp_g_mem.free(job_copy);
|
||||
llarp_g_mem.free(async);
|
||||
return false;
|
||||
struct llarp_ev_caller * llarp_ev_prepare_async(struct llarp_ev_loop * loop, llarp_ev_work_func work)
|
||||
{
|
||||
llarp_ev_caller * caller = new llarp_ev_caller(loop, work);
|
||||
if(uv_async_init(loop->loop(), &caller->async, llarp::ev_handle_async_call) == 0)
|
||||
return caller;
|
||||
else
|
||||
{
|
||||
delete caller;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool llarp_ev_call_async(struct llarp_ev_caller * caller, void * user)
|
||||
{
|
||||
if(caller->appendCall(user))
|
||||
return uv_async_send(&caller->async) == 0;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
void llarp_ev_caller_stop(struct llarp_ev_caller * caller)
|
||||
{
|
||||
uv_close((uv_handle_t*)&caller->async, llarp::ev_caller_async_closed);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,13 @@ namespace llarp {
|
|||
template <typename T> static constexpr size_t alignment() {
|
||||
return std::exp2(1 + std::floor(std::log2(sizeof(T))));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T * Alloc(llarp_alloc * mem=&llarp_g_mem)
|
||||
{
|
||||
return static_cast<T *>(
|
||||
mem->alloc(sizeof(T), alignment<T>()));
|
||||
}
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
namespace llarp {
|
||||
namespace thread {
|
||||
Pool::Pool(size_t workers) {
|
||||
stop.store(true);
|
||||
stop.store(false);
|
||||
while (workers--) {
|
||||
threads.emplace_back([this] {
|
||||
for (;;) {
|
||||
|
@ -21,10 +21,12 @@ Pool::Pool(size_t workers) {
|
|||
// do work
|
||||
job.work(job.user);
|
||||
// inform result if needed
|
||||
if (job.result && job.result->loop)
|
||||
if (!llarp_ev_async(job.result->loop, *job.result)) {
|
||||
if (job.caller)
|
||||
{
|
||||
if (!llarp_ev_call_async(job.caller, job.data)) {
|
||||
std::cerr << "failed to queue result in thread worker" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -73,6 +75,16 @@ struct llarp_threadpool *llarp_init_threadpool(int workers) {
|
|||
|
||||
void llarp_threadpool_join(struct llarp_threadpool *pool) { pool->impl.Join(); }
|
||||
|
||||
void llarp_threadpool_start(struct llarp_threadpool * pool)
|
||||
{
|
||||
/** no op */
|
||||
}
|
||||
|
||||
void llarp_threadpool_queue_job(struct llarp_threadpool * pool, struct llarp_thread_job job)
|
||||
{
|
||||
pool->impl.QueueJob(job);
|
||||
}
|
||||
|
||||
void llarp_free_threadpool(struct llarp_threadpool **pool) {
|
||||
delete *pool;
|
||||
*pool = nullptr;
|
||||
|
|
74
test/test_async_dh.c
Normal file
74
test/test_async_dh.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
#include <llarp/crypto_async.h>
|
||||
#include <llarp/mem.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
struct dh_bench_main
|
||||
{
|
||||
size_t completed;
|
||||
size_t num;
|
||||
struct llarp_ev_loop * ev;
|
||||
struct llarp_async_dh * dh;
|
||||
};
|
||||
|
||||
static void handle_dh_complete(struct llarp_dh_result * res)
|
||||
{
|
||||
struct dh_bench_main * m = (struct dh_bench_main *) res->user;
|
||||
m->completed++;
|
||||
if(m->completed % 1000 == 0)
|
||||
printf("completed %ld\n", m->completed);
|
||||
if(m->completed == m->num)
|
||||
{
|
||||
printf("we done\n");
|
||||
llarp_ev_loop_stop(m->ev);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
struct dh_bench_main dh_main;
|
||||
struct llarp_crypto crypto;
|
||||
struct llarp_threadpool * tp;
|
||||
|
||||
llarp_mem_jemalloc();
|
||||
llarp_crypto_libsodium_init(&crypto);
|
||||
llarp_ev_loop_alloc(&dh_main.ev);
|
||||
|
||||
tp = llarp_init_threadpool(8);
|
||||
dh_main.dh = llarp_async_dh_new(&crypto, dh_main.ev, tp);
|
||||
llarp_threadpool_start(tp);
|
||||
|
||||
/* do work here */
|
||||
dh_main.num = 100000;
|
||||
dh_main.completed = 0;
|
||||
struct llarp_keypair ourkey;
|
||||
struct llarp_keypair theirkey;
|
||||
|
||||
crypto.keygen(&ourkey);
|
||||
crypto.keygen(&theirkey);
|
||||
|
||||
|
||||
llarp_tunnel_nounce_t nounce;
|
||||
llarp_buffer_t n_buff;
|
||||
n_buff.base = nounce;
|
||||
n_buff.cur = n_buff.base;
|
||||
n_buff.sz = sizeof(llarp_tunnel_nounce_t);
|
||||
|
||||
size_t sz = dh_main.num;
|
||||
printf("starting %ld dh jobs\n", sz);
|
||||
while(sz--)
|
||||
{
|
||||
crypto.randomize(n_buff);
|
||||
llarp_async_client_dh(dh_main.dh, ourkey.sec, theirkey.pub, nounce, handle_dh_complete, &dh_main);
|
||||
}
|
||||
printf("started %ld dh jobs\n", dh_main.num);
|
||||
llarp_ev_loop_run(dh_main.ev);
|
||||
|
||||
llarp_threadpool_join(tp);
|
||||
llarp_async_dh_free(&dh_main.dh);
|
||||
|
||||
llarp_ev_loop_free(&dh_main.ev);
|
||||
llarp_free_threadpool(&tp);
|
||||
printf("did %ld of %ld work\n", dh_main.completed, dh_main.num);
|
||||
return 0;
|
||||
}
|
6
test/test_cpp.cpp
Normal file
6
test/test_cpp.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue