clang format and lots of stupid bug fixes

pull/1/head
Jeff Becker 6 years ago
parent afdf5fa51c
commit bc9e32d690
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -1,7 +1,9 @@
cmake_minimum_required(VERSION 2.8.10)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -Wall -fPIC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall -fPIC")
set(DEBUG_FLAGS "-O1 -g -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -Wall -fPIC ${DEBUG_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall -fPIC ${DEBUG_FLAGS}")
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
@ -10,12 +12,12 @@ find_package(sodium)
set(EXE llarpd)
set(EXE_SRC daemon/main.cpp)
set(LIBS ${sodium_LIBRARY_RELEASE} pthread stdc++fs jemalloc mbedx509 mbedcrypto mbedtls)
set(LIBS ${sodium_LIBRARY_RELEASE} pthread stdc++fs)
set(LIB llarp)
set(LIB_SRC
llarp/address_info.c
llarp/address_info.cpp
llarp/buffer.cpp
llarp/config.cpp
llarp/crypto_async.cpp
@ -30,7 +32,6 @@ set(LIB_SRC
llarp/link_relay_up.cpp
llarp/logic.c
llarp/mem.cpp
llarp/mem_jemalloc.cpp
llarp/mem_std.cpp
llarp/muxer.cpp
llarp/net.cpp

@ -9,7 +9,7 @@ clean: build.ninja
ninja clean
build.ninja:
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang
compile: build.ninja
ninja

@ -10,5 +10,5 @@ named-node0=remote-rc.signed
#named-node1=/path/to/routercontact1
[iwp-links]
lo=1090
tun0=1090
#lo=eth

@ -1,10 +1,12 @@
#include <llarp.h>
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
static void progress() {
static void
progress()
{
printf(".");
fflush(stdout);
}
@ -13,147 +15,168 @@ struct llarp_main
{
struct llarp_alloc mem;
struct llarp_crypto crypto;
struct llarp_router *router = nullptr;
struct llarp_router *router = nullptr;
struct llarp_threadpool *worker = nullptr;
struct llarp_threadpool *thread = nullptr;
struct llarp_logic *logic = nullptr;
struct llarp_config *config = nullptr;
struct llarp_nodedb *nodedb = nullptr;
struct llarp_ev_loop *mainloop = nullptr;
struct llarp_logic *logic = nullptr;
struct llarp_config *config = nullptr;
struct llarp_nodedb *nodedb = nullptr;
struct llarp_ev_loop *mainloop = nullptr;
char nodedb_dir[256];
int exitcode;
int shutdown()
int
shutdown()
{
printf("Shutting down ");
progress();
if(mainloop)
llarp_ev_loop_stop(mainloop);
progress();
if(worker)
llarp_threadpool_stop(worker);
progress();
if(worker)
llarp_threadpool_join(worker);
progress();
if (logic)
if(logic)
llarp_logic_stop(logic);
progress();
if(router)
llarp_stop_router(router);
progress();
llarp_free_router(&router);
progress();
llarp_free_config(&config);
progress();
llarp_ev_loop_free(&mainloop);
progress();
llarp_free_threadpool(&worker);
progress();
llarp_free_logic(&logic);
progress();
printf("\n");
fflush(stdout);
return exitcode;
}
};
void iter_main_config(struct llarp_config_iterator *itr, const char *section,
const char *key, const char *val) {
llarp_main *m = static_cast<llarp_main *>(itr->user);
void
iter_main_config(struct llarp_config_iterator *itr, const char *section,
const char *key, const char *val)
{
llarp_main *m = static_cast< llarp_main * >(itr->user);
if (!strcmp(section, "router")) {
if (!strcmp(key, "threads")) {
if(!strcmp(section, "router"))
{
if(!strcmp(key, "threads"))
{
int workers = atoi(val);
if (workers > 0 && m->worker == nullptr) {
if(workers > 0 && m->worker == nullptr)
{
m->worker = llarp_init_threadpool(workers, "llarp-worker");
}
}
}
if (!strcmp(section, "netdb")) {
if (!strcmp(key, "dir")) {
if(!strcmp(section, "netdb"))
{
if(!strcmp(key, "dir"))
{
strncpy(m->nodedb_dir, val, sizeof(m->nodedb_dir));
}
}
}
llarp_main *llarp = nullptr;
llarp_main * llarp = nullptr;
void run_net(void * user)
void
run_net(void *user)
{
llarp_ev_loop_run(static_cast<llarp_ev_loop*>(user));
llarp_ev_loop_run(static_cast< llarp_ev_loop * >(user));
}
void handle_signal(int sig)
void
handle_signal(int sig)
{
printf("\ninterrupted\n");
llarp_ev_loop_stop(llarp->mainloop);
llarp_logic_stop(llarp->logic);
}
int main(int argc, char *argv[]) {
int
main(int argc, char *argv[])
{
const char *conffname = "daemon.ini";
if (argc > 1) conffname = argv[1];
if(argc > 1)
conffname = argv[1];
llarp = new llarp_main;
llarp_mem_jemalloc(&llarp->mem);
llarp_mem_stdlib(&llarp->mem);
auto mem = &llarp->mem;
llarp_new_config(&llarp->config);
llarp_ev_loop_alloc(&llarp->mainloop);
llarp_crypto_libsodium_init(&llarp->crypto);
printf("%s loading config file %s\n", LLARP_VERSION, conffname);
if (!llarp_load_config(llarp->config, conffname)) {
if(!llarp_load_config(llarp->config, conffname))
{
llarp_config_iterator iter;
iter.user = llarp;
iter.user = llarp;
iter.visit = iter_main_config;
llarp_config_iter(llarp->config, &iter);
llarp->nodedb = llarp_nodedb_new(mem, &llarp->crypto);
if (llarp->nodedb_dir[0]) {
if(llarp->nodedb_dir[0])
{
llarp->nodedb_dir[sizeof(llarp->nodedb_dir) - 1] = 0;
char *dir = llarp->nodedb_dir;
if (llarp_nodedb_ensure_dir(dir)) {
if(llarp_nodedb_ensure_dir(llarp->nodedb_dir))
{
// ensure worker thread pool
if (!llarp->worker) llarp->worker = llarp_init_threadpool(2, "llarp-worker");
if(!llarp->worker)
llarp->worker = llarp_init_threadpool(2, "llarp-worker");
// ensure netio thread
llarp->thread = llarp_init_threadpool(1, "llarp-netio");
llarp->logic = llarp_init_logic(mem);
llarp->router = llarp_init_router(mem, llarp->worker, llarp->mainloop, llarp->logic);
llarp->logic = llarp_init_logic(mem);
llarp->router = llarp_init_router(mem, llarp->worker, llarp->mainloop,
llarp->logic);
if (llarp_configure_router(llarp->router, llarp->config)) {
if(llarp_configure_router(llarp->router, llarp->config))
{
signal(SIGINT, handle_signal);
printf("starting router\n");
llarp_run_router(llarp->router);
// run mainloop
llarp_threadpool_queue_job(llarp->thread, {llarp->mainloop, &run_net});
llarp_threadpool_queue_job(llarp->thread,
{llarp->mainloop, &run_net});
printf("running\n");
llarp->exitcode = 0;
llarp_logic_mainloop(llarp->logic);
} else
}
else
printf("Failed to configure router\n");
} else
printf("failed to initialize nodedb at %s\n", dir);
} else
}
else
printf("failed to initialize nodedb\n");
}
else
printf("no nodedb defined\n");
return llarp->shutdown();
} else
}
else
printf("Failed to load config %s\n", conffname);
delete llarp;
return 1;

@ -1,9 +1,9 @@
#ifndef LLARP_H_
#define LLARP_H_
#include <llarp/router.h>
#include <llarp/version.h>
#include <llarp/mem.h>
#include <llarp/ev.h>
#include <llarp/logic.h>
#include <llarp/mem.h>
#include <llarp/nodedb.h>
#include <llarp/router.h>
#include <llarp/version.h>
#endif

@ -11,7 +11,8 @@ extern "C" {
#define MAX_AI_DIALECT_SIZE 5
struct llarp_ai {
struct llarp_ai
{
uint16_t rank;
char dialect[MAX_AI_DIALECT_SIZE + 1];
llarp_pubkey_t enc_key;
@ -19,25 +20,45 @@ struct llarp_ai {
uint16_t port;
};
bool llarp_ai_bencode(struct llarp_ai *ai, llarp_buffer_t *buff);
bool llarp_ai_bdecode(struct llarp_ai *ai, llarp_buffer_t *buff);
bool
llarp_ai_bencode(struct llarp_ai *ai, llarp_buffer_t *buff);
bool
llarp_ai_bdecode(struct llarp_ai *ai, llarp_buffer_t *buff);
struct llarp_ai_list;
struct llarp_ai_list *llarp_ai_list_new(struct llarp_alloc * mem);
void llarp_ai_list_free(struct llarp_ai_list **l);
struct llarp_ai_list *
llarp_ai_list_new(struct llarp_alloc *mem);
void
llarp_ai_list_free(struct llarp_ai_list *l);
void
llarp_ai_copy(struct llarp_ai *dst, struct llarp_ai *src);
bool
llarp_ai_list_bencode(struct llarp_ai_list *l, llarp_buffer_t *buff);
bool
llarp_ai_list_bdecode(struct llarp_ai_list *l, llarp_buffer_t *buff);
struct llarp_ai
llarp_ai_list_popfront(struct llarp_ai_list *l);
/** pushes a copy of ai to the end of the list */
void
llarp_ai_list_pushback(struct llarp_ai_list *l, struct llarp_ai *ai);
void llarp_ai_copy(struct llarp_ai * dst, struct llarp_ai * src);
bool llarp_ai_list_bencode(struct llarp_ai_list *l, llarp_buffer_t *buff);
bool llarp_ai_list_bdecode(struct llarp_ai_list *l, llarp_buffer_t *buff);
size_t
llarp_ai_list_size(struct llarp_ai_list *l);
struct llarp_ai llarp_ai_list_popfront(struct llarp_ai_list *l);
void llarp_ai_list_pushback(struct llarp_ai_list *l, struct llarp_ai ai);
size_t llarp_ai_list_size(struct llarp_ai_list *l);
struct llarp_ai *llarp_ai_list_index(struct llarp_ai_list *l, ssize_t idx);
bool
llarp_ai_list_index(struct llarp_ai_list *l, ssize_t idx,
struct llarp_ai *result);
struct llarp_ai_list_iter {
struct llarp_ai_list_iter
{
void *user;
/** set by llarp_ai_list_iterate() */
struct llarp_ai_list *list;
@ -45,8 +66,8 @@ struct llarp_ai_list_iter {
bool (*visit)(struct llarp_ai_list_iter *, struct llarp_ai *);
};
void llarp_ai_list_iterate(struct llarp_ai_list *l,
struct llarp_ai_list_iter *iter);
void
llarp_ai_list_iterate(struct llarp_ai_list *l, struct llarp_ai_list_iter *iter);
#ifdef __cplusplus
}

@ -10,49 +10,70 @@
extern "C" {
#endif
static bool INLINE bencode_write_bytestring(llarp_buffer_t* buff,
const void* data, size_t sz) {
if (!llarp_buffer_writef(buff, "%ld:", sz)) return false;
static bool INLINE
bencode_write_bytestring(llarp_buffer_t* buff, const void* data, size_t sz)
{
if(!llarp_buffer_writef(buff, "%ld:", sz))
return false;
return llarp_buffer_write(buff, data, sz);
}
static bool INLINE bencode_write_int(llarp_buffer_t* buff, int i) {
static bool INLINE
bencode_write_int(llarp_buffer_t* buff, int i)
{
return llarp_buffer_writef(buff, "i%de", i);
}
static bool INLINE bencode_write_uint16(llarp_buffer_t* buff, uint16_t i) {
static bool INLINE
bencode_write_uint16(llarp_buffer_t* buff, uint16_t i)
{
return llarp_buffer_writef(buff, "i%de", i);
}
static bool INLINE bencode_write_int64(llarp_buffer_t* buff, int64_t i) {
static bool INLINE
bencode_write_int64(llarp_buffer_t* buff, int64_t i)
{
return llarp_buffer_writef(buff, "i%lde", i);
}
static bool INLINE bencode_write_uint64(llarp_buffer_t* buff, uint64_t i) {
static bool INLINE
bencode_write_uint64(llarp_buffer_t* buff, uint64_t i)
{
return llarp_buffer_writef(buff, "i%lde", i);
}
static bool INLINE bencode_write_sizeint(llarp_buffer_t* buff, size_t i) {
static bool INLINE
bencode_write_sizeint(llarp_buffer_t* buff, size_t i)
{
return llarp_buffer_writef(buff, "i%lde", i);
}
static bool INLINE bencode_start_list(llarp_buffer_t* buff) {
static bool INLINE
bencode_start_list(llarp_buffer_t* buff)
{
return llarp_buffer_write(buff, "l", 1);
}
static bool INLINE bencode_start_dict(llarp_buffer_t* buff) {
static bool INLINE
bencode_start_dict(llarp_buffer_t* buff)
{
return llarp_buffer_write(buff, "d", 1);
}
static bool INLINE bencode_end(llarp_buffer_t* buff) {
static bool INLINE
bencode_end(llarp_buffer_t* buff)
{
return llarp_buffer_write(buff, "e", 1);
}
static bool INLINE bencode_write_version_entry(llarp_buffer_t* buff) {
static bool INLINE
bencode_write_version_entry(llarp_buffer_t* buff)
{
return llarp_buffer_writef(buff, "1:vi%de", LLARP_PROTO_VERSION);
}
static bool INLINE bdecode_read_integer(struct llarp_buffer_t * buffer, int64_t * result)
static bool INLINE
bdecode_read_integer(struct llarp_buffer_t* buffer, int64_t* result)
{
size_t len;
if(*buffer->cur != 'i')
@ -60,86 +81,108 @@ static bool INLINE bdecode_read_integer(struct llarp_buffer_t * buffer, int64_t
char numbuf[32];
len = llarp_buffer_read_until(buffer, 'e', numbuf, sizeof(numbuf)-1);
buffer->cur++;
len =
llarp_buffer_read_until(buffer, 'e', (byte_t*)numbuf, sizeof(numbuf) - 1);
if(!len)
return false;
buffer->cur++;
numbuf[len] = 0;
*result = atol(numbuf);
*result = atol(numbuf);
return true;
}
static bool INLINE bdecode_read_string(llarp_buffer_t * buffer, llarp_buffer_t * result)
static bool INLINE
bdecode_read_string(llarp_buffer_t* buffer, llarp_buffer_t* result)
{
size_t len, slen;
size_t len;
int slen;
char numbuf[10];
len = llarp_buffer_read_until(buffer, ':', numbuf, sizeof(numbuf)-1);
if(!len)
len =
llarp_buffer_read_until(buffer, ':', (byte_t*)numbuf, sizeof(numbuf) - 1);
if(!len)
return false;
buffer->cur ++;
numbuf[len] = 0;
slen = atoi(numbuf);
if(slen <= 0)
slen = atoi(numbuf);
if(slen < 0)
return false;
buffer->cur++;
len = llarp_buffer_size_left(buffer);
if (len > slen)
if(len < slen)
return false;
result->base = buffer->cur;
result->cur = buffer->cur;
result->sz = slen;
buffer->cur += slen;
result->sz = slen;
buffer->cur ++;
return true;
return true;
}
struct dict_reader
{
llarp_buffer_t * buffer;
void * user;
/**
* called when we got a key string, return true to continue iteration
llarp_buffer_t* buffer;
void* user;
/**
* called when we got a key string, return true to continue iteration
* called with null key on done iterating
*/
bool (*on_key)(struct dict_reader *, llarp_buffer_t *);
*/
bool (*on_key)(struct dict_reader*, llarp_buffer_t*);
};
static bool INLINE bdecode_read_dict(llarp_buffer_t * buff, struct dict_reader * r)
static bool INLINE
bdecode_read_dict(llarp_buffer_t* buff, struct dict_reader* r)
{
llarp_buffer_t strbuf;
r->buffer = buff;
while(llarp_buffer_size_left(buff) && *buff->cur != 'e')
if(*r->buffer->cur != 'd')
return false;
r->buffer->cur++;
while(llarp_buffer_size_left(r->buffer) && *r->buffer->cur != 'e')
{
if(bdecode_read_string(buff, &strbuf))
if(bdecode_read_string(r->buffer, &strbuf))
{
if(!r->on_key(r, &strbuf)) return false;
if(!r->on_key(r, &strbuf))
return false;
}
}
return *buff->cur == 'e' && r->on_key(r, 0);
if(*r->buffer->cur != 'e')
return false;
r->buffer->cur++;
return r->on_key(r, 0);
}
struct list_reader
{
llarp_buffer_t * buffer;
void * user;
bool (*on_item) (struct list_reader *, bool);
llarp_buffer_t* buffer;
void* user;
bool (*on_item)(struct list_reader*, bool);
};
static bool INLINE bdecode_read_list(llarp_buffer_t * buff, struct list_reader * r)
static bool INLINE
bdecode_read_list(llarp_buffer_t* buff, struct list_reader* r)
{
r->buffer = buff;
if(*buff->cur != 'l')
if(*r->buffer->cur != 'l')
return false;
buff->cur ++;
while(llarp_buffer_size_left(buff) && *buff->cur != 'e')
r->buffer->cur++;
while(llarp_buffer_size_left(r->buffer) && *r->buffer->cur != 'e')
{
if(!r->on_item(r, true)) return false;
if(!r->on_item(r, true))
return false;
}
return *buff->cur == 'e' && r->on_item(r, false);
if(*r->buffer->cur != 'e')
return false;
r->buffer->cur++;
return r->on_item(r, false);
}
#ifdef __cplusplus

@ -10,25 +10,34 @@
#ifdef __cplusplus
extern "C" {
#endif
typedef struct llarp_buffer_t {
char *base;
typedef uint8_t byte_t;
typedef struct llarp_buffer_t
{
byte_t *base;
byte_t *cur;
size_t sz;
char *cur;
} llarp_buffer_t;
size_t llarp_buffer_size_left(llarp_buffer_t *buff);
bool llarp_buffer_write(llarp_buffer_t *buff, const void *data, size_t sz);
size_t
llarp_buffer_size_left(llarp_buffer_t *buff);
bool llarp_buffer_writef(llarp_buffer_t *buff, const char *fmt, ...);
bool
llarp_buffer_write(llarp_buffer_t *buff, const void *data, size_t sz);
bool llarp_buffer_readfile(llarp_buffer_t *buff, FILE *f,
struct llarp_alloc *mem);
bool
llarp_buffer_writef(llarp_buffer_t *buff, const char *fmt, ...);
size_t llarp_buffer_read_until(llarp_buffer_t * buff, char delim, char * result, size_t resultlen);
bool
llarp_buffer_readfile(llarp_buffer_t *buff, FILE *f, struct llarp_alloc *mem);
bool llarp_buffer_eq(llarp_buffer_t buff, const char * data);
size_t
llarp_buffer_read_until(llarp_buffer_t *buff, char delim, byte_t *result,
size_t resultlen);
bool
llarp_buffer_eq(llarp_buffer_t buff, const char *data);
#ifdef __cplusplus
}

@ -7,13 +7,17 @@ extern "C" {
struct llarp_config;
void llarp_new_config(struct llarp_config **conf);
void llarp_free_config(struct llarp_config **conf);
void
llarp_new_config(struct llarp_config **conf);
void
llarp_free_config(struct llarp_config **conf);
/** @brief return -1 on fail otherwiwse 0 */
int llarp_load_config(struct llarp_config *conf, const char *fname);
int
llarp_load_config(struct llarp_config *conf, const char *fname);
struct llarp_config_iterator {
struct llarp_config_iterator
{
void *user;
/** set by llarp_config_iter */
struct llarp_config *conf;
@ -22,8 +26,9 @@ struct llarp_config_iterator {
const char *);
};
void llarp_config_iter(struct llarp_config *conf,
struct llarp_config_iterator *iter);
void
llarp_config_iter(struct llarp_config *conf,
struct llarp_config_iterator *iter);
#ifdef __cplusplus
}

@ -10,52 +10,50 @@ extern "C" {
#define PUBKEYSIZE 32
#define SECKEYSIZE 64
#define NOUNCESIZE 24
#define NONCESIZE 24
#define SHAREDKEYSIZE 32
#define HASHSIZE 64
#define SHORTHASHSIZE 32
#define HMACSECSIZE 32
#define SIGSIZE 64
#define TUNNOUNCESIZE 32
#define TUNNONCESIZE 32
#define HMACSIZE 32
typedef uint8_t llarp_pubkey_t[PUBKEYSIZE];
typedef uint8_t llarp_seckey_t[SECKEYSIZE];
typedef uint8_t llarp_nounce_t[NOUNCESIZE];
typedef uint8_t llarp_sharedkey_t[SHAREDKEYSIZE];
typedef uint8_t llarp_hash_t[HASHSIZE];
typedef uint8_t llarp_shorthash_t[SHORTHASHSIZE];
typedef uint8_t llarp_hmac_t[HMACSIZE];
typedef uint8_t llarp_hmacsec_t[HMACSECSIZE];
typedef uint8_t llarp_sig_t[SIGSIZE];
typedef uint8_t llarp_tunnel_nounce_t[TUNNOUNCESIZE];
static INLINE uint8_t *llarp_seckey_topublic(llarp_seckey_t k) {
return k + 32;
}
typedef byte_t llarp_pubkey_t[PUBKEYSIZE];
typedef byte_t llarp_seckey_t[SECKEYSIZE];
typedef byte_t llarp_nonce_t[NONCESIZE];
typedef byte_t llarp_sharedkey_t[SHAREDKEYSIZE];
typedef byte_t llarp_hash_t[HASHSIZE];
typedef byte_t llarp_shorthash_t[SHORTHASHSIZE];
typedef byte_t llarp_hmac_t[HMACSIZE];
typedef byte_t llarp_hmacsec_t[HMACSECSIZE];
typedef byte_t llarp_sig_t[SIGSIZE];
typedef byte_t llarp_tunnel_nonce_t[TUNNONCESIZE];
byte_t *
llarp_seckey_topublic(byte_t *secret);
typedef bool (*llarp_dh_func)(llarp_sharedkey_t *, llarp_pubkey_t,
llarp_tunnel_nounce_t, llarp_seckey_t);
llarp_tunnel_nonce_t, llarp_seckey_t);
typedef bool (*llarp_transport_dh_func)(byte_t *, byte_t *, byte_t *, byte_t *);
typedef bool (*llarp_transport_dh_func)(uint8_t *, uint8_t *,
uint8_t *, uint8_t *);
typedef bool (*llarp_sym_cipher_func)(llarp_buffer_t, llarp_sharedkey_t,
llarp_nounce_t);
llarp_nonce_t);
typedef bool (*llarp_hash_func)(llarp_hash_t *, llarp_buffer_t);
typedef bool (*llarp_hash_func)(byte_t *, llarp_buffer_t);
typedef bool (*llarp_shorthash_func)(llarp_shorthash_t *, llarp_buffer_t);
typedef bool (*llarp_shorthash_func)(byte_t *, llarp_buffer_t);
typedef bool (*llarp_hmac_func)(uint8_t *, llarp_buffer_t,
const uint8_t *);
typedef bool (*llarp_hmac_func)(byte_t *, llarp_buffer_t, const byte_t *);
typedef bool (*llarp_sign_func)(uint8_t *, const uint8_t *, llarp_buffer_t);
typedef bool (*llarp_sign_func)(byte_t *, const byte_t *, llarp_buffer_t);
typedef bool (*llarp_verify_func)(const uint8_t *, llarp_buffer_t, const uint8_t *);
typedef bool (*llarp_verify_func)(const byte_t *, llarp_buffer_t,
const byte_t *);
struct llarp_crypto {
struct llarp_crypto
{
llarp_sym_cipher_func xchacha20;
llarp_dh_func dh_client;
llarp_dh_func dh_server;
@ -68,13 +66,15 @@ struct llarp_crypto {
llarp_verify_func verify;
void (*randomize)(llarp_buffer_t);
void (*randbytes)(void *, size_t);
void (*keygen)(uint8_t *);
void (*keygen)(byte_t *);
};
void llarp_crypto_libsodium_init(struct llarp_crypto *c);
void
llarp_crypto_libsodium_init(struct llarp_crypto *c);
bool
llarp_crypto_initialized(struct llarp_crypto *c);
bool llarp_crypto_initialized(struct llarp_crypto * c);
#ifdef __cplusplus
}
#endif

@ -2,8 +2,8 @@
#define LLARP_CRYPTO_ASYNC_H_
#include <llarp/crypto.h>
#include <llarp/ev.h>
#include <llarp/threadpool.h>
#include <llarp/logic.h>
#include <llarp/threadpool.h>
#ifdef __cplusplus
extern "C" {
@ -11,120 +11,127 @@ extern "C" {
struct llarp_async_iwp;
struct llarp_async_iwp * llarp_async_iwp_new(struct llarp_alloc * mem,
struct llarp_crypto * crypto,
struct llarp_logic * logic,
struct llarp_threadpool * worker);
struct llarp_async_iwp *
llarp_async_iwp_new(struct llarp_alloc *mem, struct llarp_crypto *crypto,
struct llarp_logic *logic, struct llarp_threadpool *worker);
struct iwp_async_keygen;
typedef void (*iwp_keygen_hook)(struct iwp_async_keygen *);
struct iwp_async_keygen
{
struct llarp_async_iwp * iwp;
void * user;
uint8_t * keybuf;
struct llarp_async_iwp *iwp;
void *user;
uint8_t *keybuf;
iwp_keygen_hook hook;
};
void iwp_call_async_keygen(struct llarp_async_iwp * iwp, struct iwp_async_keygen * keygen);
void
iwp_call_async_keygen(struct llarp_async_iwp *iwp,
struct iwp_async_keygen *keygen);
struct iwp_async_intro;
typedef void (*iwp_intro_hook)(struct iwp_async_intro *);
struct iwp_async_intro
{
struct llarp_async_iwp * iwp;
void * user;
uint8_t * buf;
struct llarp_async_iwp *iwp;
void *user;
uint8_t *buf;
size_t sz;
/** nonce paramter */
uint8_t * nonce;
uint8_t *nonce;
/** remote public key */
uint8_t * remote_pubkey;
uint8_t *remote_pubkey;
/** local private key */
uint8_t * secretkey;
uint8_t *secretkey;
/** callback */
iwp_intro_hook hook;
};
void
iwp_call_async_gen_intro(struct llarp_async_iwp *iwp,
struct iwp_async_intro *intro);
void iwp_call_async_gen_intro(struct llarp_async_iwp * iwp, struct iwp_async_intro * intro);
struct iwp_async_introack;
typedef void (*iwp_introack_hook)(struct iwp_async_introack *);
struct iwp_async_introack
{
struct llarp_async_iwp * iwp;
void * user;
uint8_t * buf;
struct llarp_async_iwp *iwp;
void *user;
uint8_t *buf;
size_t sz;
/** nonce paramter */
uint8_t * nonce;
uint8_t *nonce;
/** token paramter */
uint8_t * token;
uint8_t *token;
/** remote public key */
uint8_t * remote_pubkey;
uint8_t *remote_pubkey;
/** local private key */
uint8_t * secretkey;
uint8_t *secretkey;
/** callback */
iwp_introack_hook hook;
};
void
iwp_call_async_gen_introack(struct llarp_async_iwp *iwp,
struct iwp_async_introack *introack);
void iwp_call_async_gen_introack(struct llarp_async_iwp * iwp, struct iwp_async_introack * introack);
void iwp_call_async_verify_introack(struct llarp_async_iwp * iwp, struct iwp_async_introack * introack);
void
iwp_call_async_verify_introack(struct llarp_async_iwp *iwp,
struct iwp_async_introack *introack);
struct iwp_async_session_start;
typedef void (*iwp_session_start_hook)(struct iwp_async_session_start *);
struct iwp_async_session_start
{
struct llarp_async_iwp * iwp;
void * user;
uint8_t * buf;
struct llarp_async_iwp *iwp;
void *user;
uint8_t *buf;
size_t sz;
uint8_t * nonce;
uint8_t * token;
uint8_t * sessionkey;
uint8_t * secretkey;
uint8_t * remote_pubkey;
uint8_t *nonce;
uint8_t *token;
uint8_t *sessionkey;
uint8_t *secretkey;
uint8_t *remote_pubkey;
iwp_session_start_hook hook;
};
void iwp_call_async_gen_session_start(struct llarp_async_iwp * iwp, struct iwp_async_session_start * start);
void
iwp_call_async_gen_session_start(struct llarp_async_iwp *iwp,
struct iwp_async_session_start *start);
void iwp_call_async_verify_session_start(struct llarp_async_iwp * iwp, struct iwp_async_session_start * start);
void
iwp_call_async_verify_session_start(struct llarp_async_iwp *iwp,
struct iwp_async_session_start *start);
struct iwp_async_frame;
typedef void (*iwp_async_frame_hook)(struct iwp_async_frame * );
typedef void (*iwp_async_frame_hook)(struct iwp_async_frame *);
struct iwp_async_frame
{
void * user;
void *user;
bool success;
uint8_t * sessionkey;
uint8_t *sessionkey;
size_t sz;
iwp_async_frame_hook hook;
uint8_t buf[1500];
};
void iwp_call_async_frame_decrypt(struct llarp_async_iwp * iwp, struct iwp_async_frame * frame);
void
iwp_call_async_frame_decrypt(struct llarp_async_iwp *iwp,
struct iwp_async_frame *frame);
void iwp_call_async_frame_encrypt(struct llarp_async_iwp * iwp, struct iwp_async_frame * frame);
void
iwp_call_async_frame_encrypt(struct llarp_async_iwp *iwp,
struct iwp_async_frame *frame);
#ifdef __cplusplus
}

@ -6,8 +6,10 @@ extern "C" {
struct llarp_dht_context;
struct llarp_dht_context* llarp_dht_context_new();
void llarp_dht_context_free(struct llarp_dht_context* dht);
struct llarp_dht_context*
llarp_dht_context_new();
void
llarp_dht_context_free(struct llarp_dht_context* dht);
#ifdef __cplusplus
}

@ -1,21 +1,23 @@
#ifndef LLARP_DTLS_H_
#define LLARP_DTLS_H_
#include <llarp/mem.h>
#include <llarp/link.h>
#include <llarp/mem.h>
#ifdef __cplusplus
extern "C" {
#endif
struct llarp_dtls_args {
struct llarp_alloc * mem;
const char * keyfile;
const char * certfile;
struct llarp_dtls_args
{
struct llarp_alloc* mem;
const char* keyfile;
const char* certfile;
};
void dtls_link_init(struct llarp_link* link, struct llarp_dtls_args args,
struct llarp_msg_muxer* muxer);
void
dtls_link_init(struct llarp_link* link, struct llarp_dtls_args args,
struct llarp_msg_muxer* muxer);
#ifdef __cplusplus
}

@ -1,11 +1,11 @@
#ifndef LLARP_EV_H
#define LLARP_EV_H
#include <netinet/in.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#ifdef __cplusplus
extern "C" {
@ -13,28 +13,36 @@ extern "C" {
struct llarp_ev_loop;
void llarp_ev_loop_alloc(struct llarp_ev_loop **ev);
void llarp_ev_loop_free(struct llarp_ev_loop **ev);
void
llarp_ev_loop_alloc(struct llarp_ev_loop **ev);
void
llarp_ev_loop_free(struct llarp_ev_loop **ev);
int llarp_ev_loop_run(struct llarp_ev_loop *ev);
int
llarp_ev_loop_run(struct llarp_ev_loop *ev);
/** stop event loop and wait for it to complete all jobs */
void llarp_ev_loop_stop(struct llarp_ev_loop *ev);
void
llarp_ev_loop_stop(struct llarp_ev_loop *ev);
struct llarp_udp_io {
struct llarp_udp_io
{
struct sockaddr addr;
void *user;
void *impl;
struct llarp_ev_loop * parent;
struct llarp_ev_loop *parent;
void (*recvfrom)(struct llarp_udp_io *, const struct sockaddr *, const void *,
ssize_t);
};
int llarp_ev_add_udp(struct llarp_ev_loop *ev, struct llarp_udp_io *udp);
int
llarp_ev_add_udp(struct llarp_ev_loop *ev, struct llarp_udp_io *udp);
int llarp_ev_udp_sendto(struct llarp_udp_io *udp, const struct sockaddr *to,
const void *data, size_t sz);
int
llarp_ev_udp_sendto(struct llarp_udp_io *udp, const struct sockaddr *to,
const void *data, size_t sz);
int llarp_ev_close_udp(struct llarp_udp_io *udp);
int
llarp_ev_close_udp(struct llarp_udp_io *udp);
#ifdef __cplusplus
}

@ -8,31 +8,47 @@
extern "C" {
#endif
struct llarp_xi {
struct llarp_xi
{
struct in6_addr address;
struct in6_addr netmask;
llarp_pubkey_t pubkey;
};
bool llarp_xi_bdecode(struct llarp_xi *xi, llarp_buffer_t *buf);
bool llarp_xi_bencode(struct llarp_xi *xi, llarp_buffer_t *buf);
bool
llarp_xi_bdecode(struct llarp_xi *xi, llarp_buffer_t *buf);
bool
llarp_xi_bencode(struct llarp_xi *xi, llarp_buffer_t *buf);
struct llarp_xi_list;
struct llarp_xi_list *llarp_xi_list_new(struct llarp_alloc * mem);
void llarp_xi_list_free(struct llarp_xi_list **l);
struct llarp_xi_list *
llarp_xi_list_new(struct llarp_alloc *mem);
bool llarp_xi_list_bdecode(struct llarp_xi_list *l, llarp_buffer_t *buf);
bool llarp_xi_list_bencode(struct llarp_xi_list *l, llarp_buffer_t *buf);
void
llarp_xi_list_free(struct llarp_xi_list *l);
struct llarp_xi_list_iter {
bool
llarp_xi_list_bdecode(struct llarp_xi_list *l, llarp_buffer_t *buf);
bool
llarp_xi_list_bencode(struct llarp_xi_list *l, llarp_buffer_t *buf);
void
llarp_xi_list_pushback(struct llarp_xi_list *l, struct llarp_xi *xi);
void
llarp_xi_copy(struct llarp_xi *dst, struct llarp_xi *src);
struct llarp_xi_list_iter
{
void *user;
struct llarp_xi_list *list;
bool (*visit)(struct llarp_xi_list_iter *, struct llarp_xi *);
};
void llarp_xi_list_iterate(struct llarp_xi_list *l,
struct llarp_xi_list_iter *iter);
void
llarp_xi_list_iterate(struct llarp_xi_list *l, struct llarp_xi_list_iter *iter);
#ifdef __cplusplus
}

@ -7,15 +7,18 @@
extern "C" {
#endif
struct llarp_xr {
struct llarp_xr
{
struct in6_addr gateway;
struct in6_addr netmask;
struct in6_addr source;
uint64_t lifetime;
};
bool llarp_xr_bencode(struct llarp_xr* xr, llarp_buffer_t* buff);
bool llarp_xr_bdecode(struct llarp_xr* xr, llarp_buffer_t* buff);
bool
llarp_xr_bencode(struct llarp_xr* xr, llarp_buffer_t* buff);
bool
llarp_xr_bdecode(struct llarp_xr* xr, llarp_buffer_t* buff);
#ifdef __cplusplus
}

@ -10,17 +10,22 @@ extern "C" {
struct llarp_mq;
struct llarp_mq *llarp_init_mq();
void llarp_free_mq(struct llarp_mq **queue);
struct llarp_mq *
llarp_init_mq();
void
llarp_free_mq(struct llarp_mq **queue);
/**
offer a full message to the inbound message queue
return true if successfully added
return false if the queue is full
*/
bool llarp_mq_offer(struct llarp_mq *queue, llarp_buffer_t msg);
size_t llarp_mq_peek(struct llarp_mq *queue);
bool
llarp_mq_offer(struct llarp_mq *queue, llarp_buffer_t msg);
size_t
llarp_mq_peek(struct llarp_mq *queue);
/** return true if we have more messages to process */
bool llarp_mq_process(struct llarp_mq *queue, struct llarp_msg_muxer *muxer);
bool
llarp_mq_process(struct llarp_mq *queue, struct llarp_msg_muxer *muxer);
#ifdef __cplusplus
}

@ -9,16 +9,18 @@
extern "C" {
#endif
struct llarp_iwp_args {
struct llarp_alloc * mem;
struct llarp_iwp_args
{
struct llarp_alloc* mem;
struct llarp_crypto* crypto;
struct llarp_logic * logic;
struct llarp_threadpool * cryptoworker;
const char * keyfile;
struct llarp_logic* logic;
struct llarp_threadpool* cryptoworker;
const char* keyfile;
};
void iwp_link_init(struct llarp_link* link, struct llarp_iwp_args args,
struct llarp_msg_muxer* muxer);
void
iwp_link_init(struct llarp_link* link, struct llarp_iwp_args args,
struct llarp_msg_muxer* muxer);
#ifdef __cplusplus
}

@ -1,5 +1,6 @@
#ifndef LLARP_LINK_H_
#define LLARP_LINK_H_
#include <llarp/address_info.h>
#include <llarp/crypto.h>
#include <llarp/ev.h>
#include <llarp/logic.h>
@ -25,43 +26,43 @@ struct llarp_link;
*/
struct llarp_link_session;
struct llarp_link_session_listener {
/** outbound session establish job */
struct llarp_link_establish_job
{
void *user;
/** set by try_establish */
struct llarp_link *link;
/** set by try_establish */
struct llarp_ai *ai;
/** callback to handle result */
void (*result)(struct llarp_link_session_listener *,
struct llarp_link_session *);
};
/** information for establishing an outbound session */
struct llarp_link_establish_job {
struct llarp_ai *ai;
void (*result)(struct llarp_link_establish_job *);
struct llarp_ai ai;
uint64_t timeout;
/** set on success by try_establish */
struct llarp_link *link;
/** set on success by try_establish */
struct llarp_link_session *session;
};
struct llarp_link_session_iter {
struct llarp_link_session_iter
{
void *user;
struct llarp_link *link;
bool (*visit)(struct llarp_link_session_iter *, struct llarp_link_session *);
};
struct llarp_link_ev_listener {
struct llarp_link_ev_listener
{
void *user;
void (*established)(struct llarp_link_ev_listener *, struct llarp_link_session *,
bool);
void (*established)(struct llarp_link_ev_listener *,
struct llarp_link_session *, bool);
void (*timeout)(struct llarp_link_ev_listener *, struct llarp_link_session *,
bool);
void (*tx)(struct llarp_link_ev_listener *, struct llarp_link_session *, size_t);
void (*rx)(struct llarp_link_ev_listener *, struct llarp_link_session *, size_t);
void (*tx)(struct llarp_link_ev_listener *, struct llarp_link_session *,
size_t);
void (*rx)(struct llarp_link_ev_listener *, struct llarp_link_session *,
size_t);
void (*error)(struct llarp_link_ev_listener *, struct llarp_link_session *,
const char *);
};
struct llarp_link {
struct llarp_link
{
void *impl;
const char *(*name)(void);
void (*get_our_address)(struct llarp_link *, struct llarp_ai *);
@ -69,24 +70,27 @@ struct llarp_link {
int (*register_listener)(struct llarp_link *, struct llarp_link_ev_listener);
void (*deregister_listener)(struct llarp_link *, int);
*/
bool (*configure)(struct llarp_link *, struct llarp_ev_loop *, const char *, int, uint16_t);
bool (*configure)(struct llarp_link *, struct llarp_ev_loop *, const char *,
int, uint16_t);
bool (*start_link)(struct llarp_link *, struct llarp_logic *);
bool (*stop_link)(struct llarp_link *);
void (*iter_sessions)(struct llarp_link *, struct llarp_link_session_iter*);
void (*try_establish)(struct llarp_link *, struct llarp_link_establish_job,
struct llarp_link_session_listener);
/**
struct llarp_link_session * (*acquire_session_for_addr)(struct llarp_link *, const struct sockaddr *);
void (*iter_sessions)(struct llarp_link *, struct llarp_link_session_iter);
bool (*try_establish)(struct llarp_link *, struct llarp_link_establish_job *);
/**
struct llarp_link_session * (*acquire_session_for_addr)(struct llarp_link
*, const struct sockaddr *);
*/
void (*mark_session_active)(struct llarp_link *, struct llarp_link_session *);
void (*free_impl)(struct llarp_link *);
};
/** checks if all members are initialized */
bool llarp_link_initialized(struct llarp_link * link);
struct llarp_link_session {
bool
llarp_link_initialized(struct llarp_link *link);
struct llarp_link_session
{
struct sockaddr addr;
void *impl;
/** send an entire message, splits up into smaller pieces and does encryption
@ -98,7 +102,8 @@ struct llarp_link_session {
void (*close)(struct llarp_link_session *);
};
bool llarp_link_session_initialized(struct llarp_link_session * s);
bool
llarp_link_session_initialized(struct llarp_link_session *s);
#ifdef __cplusplus
}

@ -9,20 +9,25 @@ extern "C" {
struct llarp_logic;
struct llarp_logic* llarp_init_logic(struct llarp_alloc * mem);
struct llarp_logic*
llarp_init_logic(struct llarp_alloc* mem);
void llarp_free_logic(struct llarp_logic** logic);
void
llarp_free_logic(struct llarp_logic** logic);
void llarp_logic_queue_job(struct llarp_logic* logic,
struct llarp_thread_job job);
void
llarp_logic_queue_job(struct llarp_logic* logic, struct llarp_thread_job job);
uint32_t llarp_logic_call_later(struct llarp_logic* logic,
struct llarp_timeout_job job);
void llarp_logic_cancel_call(struct llarp_logic* logic, uint32_t id);
uint32_t
llarp_logic_call_later(struct llarp_logic* logic, struct llarp_timeout_job job);
void
llarp_logic_cancel_call(struct llarp_logic* logic, uint32_t id);
void llarp_logic_stop(struct llarp_logic* logic);
void
llarp_logic_stop(struct llarp_logic* logic);
void llarp_logic_mainloop(struct llarp_logic* logic);
void
llarp_logic_mainloop(struct llarp_logic* logic);
#ifdef __cplusplus
}

@ -1,30 +1,38 @@
#ifndef LLARP_MEM_H_
#define LLARP_MEM_H_
#ifdef NO_JEMALLOC
#include <stdlib.h>
#include <stdint.h>
#else
#include <jemalloc/jemalloc.h>
#endif
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct llarp_alloc {
void * impl;
void *(*alloc)(struct llarp_alloc * mem, size_t sz, size_t align);
void (*free)(struct llarp_alloc * mem, void *ptr);
struct llarp_alloc
{
void *impl;
void *(*alloc)(struct llarp_alloc *mem, size_t sz, size_t align);
void (*free)(struct llarp_alloc *mem, void *ptr);
};
void llarp_mem_stdlib(struct llarp_alloc * mem);
void llarp_mem_jemalloc(struct llarp_alloc * mem);
void llarp_mem_dmalloc(struct llarp_alloc * mem);
void llarp_mem_slab(struct llarp_alloc * mem, uint32_t * buf, size_t sz);
void
llarp_mem_stdlib(struct llarp_alloc *mem);
void
llarp_mem_jemalloc(struct llarp_alloc *mem);
void
llarp_mem_dmalloc(struct llarp_alloc *mem);
void
llarp_mem_slab(struct llarp_alloc *mem, uint32_t *buf, size_t sz);
/** constant time memcmp */
bool llarp_eq(const void * a, const void * b, size_t sz);
bool
llarp_eq(const void *a, const void *b, size_t sz);
#ifdef __cplusplus
}
#endif

@ -13,7 +13,8 @@ struct llarp_msg_muxer;
struct llarp_link_session;
struct llarp_router;
struct llarp_frame_handler {
struct llarp_frame_handler
{
/**
* participating paths
*/
@ -31,13 +32,15 @@ struct llarp_frame_handler {
llarp_buffer_t);
};
struct llarp_msg_handler {
struct llarp_msg_handler
{
struct llarp_path_context *paths;
struct llarp_dht_context *dht;
bool (*process)(struct llarp_msg_handler *, llarp_buffer_t);
};
struct llarp_msg_muxer {
struct llarp_msg_muxer
{
/** get a message handler for a link level message given msg.a */
struct llarp_frame_handler *(*link_handler_for)(struct llarp_router *,
const char);
@ -47,7 +50,8 @@ struct llarp_msg_muxer {
};
/** fill function pointers with default values */
void llarp_msg_muxer_init(struct llarp_msg_muxer *muxer);
void
llarp_msg_muxer_init(struct llarp_msg_muxer *muxer);
#ifdef __cplusplus
}

@ -1,10 +1,11 @@
#ifndef LLARP_NET_H
#define LLARP_NET_H
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdbool.h>
#ifdef __linux__
#include <linux/if_packet.h>
#endif
@ -12,9 +13,10 @@
#ifdef __cplusplus
extern "C" {
#endif
bool llarp_getifaddr(const char * ifname, int af, struct sockaddr* addr);
bool
llarp_getifaddr(const char* ifname, int af, struct sockaddr* addr);
#ifdef __cplusplus
}
#endif

@ -9,23 +9,29 @@ extern "C" {
struct llarp_nodedb;
/** create an empty nodedb */
struct llarp_nodedb *llarp_nodedb_new(struct llarp_alloc * mem, struct llarp_crypto * crypto);
struct llarp_nodedb *
llarp_nodedb_new(struct llarp_alloc *mem, struct llarp_crypto *crypto);
/** free a nodedb and all loaded rc */
void llarp_nodedb_free(struct llarp_nodedb **n);
void
llarp_nodedb_free(struct llarp_nodedb **n);
/** ensure a nodedb fs skiplist structure is at dir
create if not there.
*/
bool llarp_nodedb_ensure_dir(const char *dir);
bool
llarp_nodedb_ensure_dir(const char *dir);
/** load entire nodedb from fs skiplist at dir */
ssize_t llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir);
ssize_t
llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir);
/** store entire nodedb to fs skiplist at dir */
ssize_t llarp_nodedb_store_dir(struct llarp_nodedb *n, const char *dir);
ssize_t
llarp_nodedb_store_dir(struct llarp_nodedb *n, const char *dir);
struct llarp_nodedb_iter {
struct llarp_nodedb_iter
{
void *user;
struct llarp_rc *rc;
bool (*visit)(struct llarp_nodedb_iter *);
@ -34,15 +40,16 @@ struct llarp_nodedb_iter {
/**
iterate over all loaded rc with an iterator
*/
void llarp_nodedb_iterate_all(struct llarp_nodedb *n,
struct llarp_nodedb_iter i);
void
llarp_nodedb_iterate_all(struct llarp_nodedb *n, struct llarp_nodedb_iter i);
/**
find rc by rc.k being value k
returns true if found otherwise returns false
*/
bool llarp_nodedb_find_rc(struct llarp_nodedb *n, struct llarp_rc *rc,
llarp_pubkey_t k);
bool
llarp_nodedb_find_rc(struct llarp_nodedb *n, struct llarp_rc *rc,
llarp_pubkey_t k);
/**
put an rc into the node db
@ -50,7 +57,8 @@ bool llarp_nodedb_find_rc(struct llarp_nodedb *n, struct llarp_rc *rc,
flushes the single entry to disk
returns true on success and false on error
*/
bool llarp_nodedb_put_rc(struct llarp_nodedb *n, struct llarp_rc *rc);
bool
llarp_nodedb_put_rc(struct llarp_nodedb *n, struct llarp_rc *rc);
#ifdef __cplusplus
}

@ -16,14 +16,18 @@ struct llarp_link;
*/
struct llarp_link_dispatcher;
struct llarp_link_dispatcher *llarp_init_link_dispatcher();
void llarp_free_link_dispatcher(struct llarp_link_dispatcher **dispatcher);
void llarp_link_sendto(struct llarp_link_dispatcher *dispatcher,
llarp_pubkey_t pubkey, llarp_buffer_t msg);
void llarp_link_register(struct llarp_link_dispatcher *dispatcher,
struct llarp_link *link);
struct llarp_link_dispatcher *
llarp_init_link_dispatcher();
void
llarp_free_link_dispatcher(struct llarp_link_dispatcher **dispatcher);
void
llarp_link_sendto(struct llarp_link_dispatcher *dispatcher,
llarp_pubkey_t pubkey, llarp_buffer_t msg);
void
llarp_link_register(struct llarp_link_dispatcher *dispatcher,
struct llarp_link *link);
#ifdef __cplusplus
}

@ -5,7 +5,8 @@
typedef uint64_t llarp_path_id_t;
struct llarp_transit_hop {
struct llarp_transit_hop
{
llarp_path_id_t id;
llarp_sharedkey_t symkey;
llarp_pubkey_t nextHop;

@ -7,13 +7,14 @@
extern "C" {
#endif
struct llarp_quic_args {
struct llarp_quic_args
{
};
bool quic_link_init(struct llarp_link* link, struct llarp_quic_args args,
struct llarp_msg_muxer* muxer);
bool
quic_link_init(struct llarp_link* link, struct llarp_quic_args args,
struct llarp_msg_muxer* muxer);
#ifdef __cplusplus
}
#endif

@ -3,8 +3,10 @@
#include <llarp/config.h>
#include <llarp/ev.h>
#include <llarp/ibmq.h>
#include <llarp/link.h>
#include <llarp/logic.h>
#include <llarp/obmd.h>
#include <llarp/router_contact.h>
#include <llarp/threadpool.h>
#ifdef __cplusplus
@ -13,20 +15,42 @@ extern "C" {
struct llarp_router;
struct llarp_router *llarp_init_router(struct llarp_alloc * mem, struct llarp_threadpool *worker, struct llarp_ev_loop * netloop, struct llarp_logic *logic);
void llarp_free_router(struct llarp_router **router);
struct llarp_router *
llarp_init_router(struct llarp_alloc *mem, struct llarp_threadpool *worker,
struct llarp_ev_loop *netloop, struct llarp_logic *logic);
bool llarp_configure_router(struct llarp_router *router,
struct llarp_config *conf);
void
llarp_free_router(struct llarp_router **router);
void llarp_run_router(struct llarp_router *router);
void llarp_stop_router(struct llarp_router *router);
bool
llarp_configure_router(struct llarp_router *router, struct llarp_config *conf);
void
llarp_run_router(struct llarp_router *router);
void
llarp_stop_router(struct llarp_router *router);
/** return false if we already have a session pending or made */
bool
llarp_router_try_connect(struct llarp_router *router, struct llarp_rc *remote);
/** get router's inbound link level frame queue */
struct llarp_link_queue *llarp_router_link_queue(struct llarp_router *router);
struct llarp_link_queue *
llarp_router_link_queue(struct llarp_router *router);
/** get router's outbound link level frame dispatcher */
struct llarp_link_dispatcher *llarp_router_link_dispatcher(
struct llarp_router *router);
struct llarp_link_dispatcher *
llarp_router_link_dispatcher(struct llarp_router *router);
struct llarp_router_link_iter
{
void *user;
bool (*visit)(struct llarp_router_link_iter *, struct llarp_router *,
struct llarp_link *);
};
void
llarp_router_iterate_links(struct llarp_router *router,
struct llarp_router_link_iter iter);
#ifdef __cplusplus
}

@ -8,18 +8,29 @@ extern "C" {
#endif
const size_t MAX_RC_SIZE = 1024;
struct llarp_rc {
struct llarp_rc
{
struct llarp_ai_list *addrs;
llarp_pubkey_t pubkey;
struct llarp_xi_list *exits;
llarp_sig_t signature;
};
bool llarp_rc_bdecode(struct llarp_alloc * mem, struct llarp_rc *rc, llarp_buffer_t *buf);
bool llarp_rc_bencode(struct llarp_rc *rc, llarp_buffer_t *buf);
void llarp_rc_free(struct llarp_rc *rc);
bool llarp_rc_verify_sig(struct llarp_crypto * crypto, struct llarp_rc *rc);
bool
llarp_rc_bdecode(struct llarp_alloc *mem, struct llarp_rc *rc,
llarp_buffer_t *buf);
bool
llarp_rc_bencode(struct llarp_rc *rc, llarp_buffer_t *buf);
void
llarp_rc_free(struct llarp_rc *rc);
bool
llarp_rc_verify_sig(struct llarp_crypto *crypto, struct llarp_rc *rc);
void
llarp_rc_copy(struct llarp_rc *dst, struct llarp_rc *src);
#ifdef __cplusplus
}

@ -12,7 +12,8 @@ extern "C" {
/**
* rotuer identity private info
*/
struct llarp_router_ident {
struct llarp_router_ident
{
struct llarp_crypto *crypto;
llarp_seckey_t signkey;
uint64_t updated;
@ -21,19 +22,23 @@ struct llarp_router_ident {
struct llarp_xi_list *exits;
};
void llarp_router_ident_new(struct llarp_router_ident **ri,
struct llarp_crypto *crypto);
void
llarp_router_ident_new(struct llarp_router_ident **ri,
struct llarp_crypto *crypto);
void llarp_router_ident_append_ai(struct llarp_router_ident *ri,
struct llarp_ai *ai);
void
llarp_router_ident_append_ai(struct llarp_router_ident *ri,
struct llarp_ai *ai);
bool llarp_router_ident_bdecode(struct llarp_router_ident *ri,
llarp_buffer_t *buf);
bool llarp_router_ident_bencode(struct llarp_router_ident *ri,
llarp_buffer_t *buf);
void llarp_router_ident_free(struct llarp_router_ident **ri);
bool llarp_router_ident_generate_rc(struct llarp_router_ident *ri,
struct llarp_rc **rc);
bool
llarp_router_ident_bdecode(struct llarp_router_ident *ri, llarp_buffer_t *buf);
bool
llarp_router_ident_bencode(struct llarp_router_ident *ri, llarp_buffer_t *buf);
void
llarp_router_ident_free(struct llarp_router_ident **ri);
bool
llarp_router_ident_generate_rc(struct llarp_router_ident *ri,
struct llarp_rc **rc);
#ifdef __cplusplus
}

@ -6,18 +6,21 @@
extern "C" {
#endif
struct llarp_service_info {
struct llarp_service_info
{
llarp_buffer_t name;
llarp_pubkey_t signingkey;
llarp_buffer_t vanity;
};
void llarp_service_info_hash(struct llarp_service_info *si, llarp_hash_t *h);
bool llarp_service_info_bencode(struct llarp_serivce_info *si,
llarp_buffer_t *buff);
bool llarp_service_info_bdecode(struct llarp_serivce_info *si,
llarp_buffer_t buff);
void llarp_service_info_free(struct llarp_service_info **si);
void
llarp_service_info_hash(struct llarp_service_info *si, llarp_hash_t *h);
bool
llarp_service_info_bencode(struct llarp_serivce_info *si, llarp_buffer_t *buff);
bool
llarp_service_info_bdecode(struct llarp_serivce_info *si, llarp_buffer_t buff);
void
llarp_service_info_free(struct llarp_service_info **si);
#ifdef __cplusplus
}

@ -5,9 +5,12 @@
extern "C" {
#endif
size_t INLINE strnlen(const char* str, size_t sz) {
size_t INLINE
strnlen(const char* str, size_t sz)
{
size_t slen = 0;
while (sz-- && str[slen]) slen++;
while(sz-- && str[slen])
slen++;
return slen;
}

@ -6,26 +6,33 @@ extern "C" {
struct llarp_threadpool;
struct llarp_threadpool *llarp_init_threadpool(int workers, const char * name);
void llarp_free_threadpool(struct llarp_threadpool **tp);
struct llarp_threadpool *
llarp_init_threadpool(int workers, const char *name);
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 {
struct llarp_thread_job
{
/** user data to pass to work function */
void *user;
/** called in threadpool worker thread */
llarp_thread_work_func work;
};
void llarp_threadpool_queue_job(struct llarp_threadpool *tp,
struct llarp_thread_job j);
void
llarp_threadpool_queue_job(struct llarp_threadpool *tp,
struct llarp_thread_job j);
void llarp_threadpool_stop(struct llarp_threadpool *tp);
void llarp_threadpool_join(struct llarp_threadpool *tp);
void
llarp_threadpool_stop(struct llarp_threadpool *tp);
void
llarp_threadpool_join(struct llarp_threadpool *tp);
void llarp_threadpool_wait(struct llarp_threadpool *tp);
void
llarp_threadpool_wait(struct llarp_threadpool *tp);
#ifdef __cplusplus
}

@ -5,8 +5,10 @@
extern "C" {
#endif
llarp_time_t llarp_time_now_ms();
llarp_seconds_t llarp_time_now_sec();
llarp_time_t
llarp_time_now_ms();
llarp_seconds_t
llarp_time_now_sec();
#ifdef __cplusplus
}

@ -9,7 +9,8 @@ extern "C" {
/** called with userptr, original timeout, left */
typedef void (*llarp_timer_handler_func)(void *, uint64_t, uint64_t);
struct llarp_timeout_job {
struct llarp_timeout_job
{
uint64_t timeout;
void *user;
llarp_timer_handler_func handler;
@ -17,21 +18,26 @@ struct llarp_timeout_job {
struct llarp_timer_context;
struct llarp_timer_context *llarp_init_timer();
struct llarp_timer_context *
llarp_init_timer();
uint32_t llarp_timer_call_later(struct llarp_timer_context *t,
struct llarp_timeout_job job);
uint32_t
llarp_timer_call_later(struct llarp_timer_context *t,
struct llarp_timeout_job job);
void llarp_timer_cancel(struct llarp_timer_context *t, uint32_t id);
void
llarp_timer_cancel(struct llarp_timer_context *t, uint32_t id);
// cancel all
void llarp_timer_stop(struct llarp_timer_context *t);
void
llarp_timer_stop(struct llarp_timer_context *t);
// blocking run timer and send events to thread pool
void llarp_timer_run(struct llarp_timer_context *t,
struct llarp_threadpool *pool);
void
llarp_timer_run(struct llarp_timer_context *t, struct llarp_threadpool *pool);
void llarp_free_timer(struct llarp_timer_context **t);
void
llarp_free_timer(struct llarp_timer_context **t);
#ifdef __cplusplus
}

@ -1,5 +1,5 @@
#ifndef LLARP_TYPES_H
#define LLARP_TYEPS_H
#define LLARP_TYPES_H
#include <stdint.h>
#ifdef __cplusplus

@ -4,80 +4,200 @@
#include <llarp/mem.h>
#include <llarp/string.h>
bool llarp_ai_bdecode(struct llarp_ai *ai, llarp_buffer_t *buff)
static bool
llarp_ai_decode_key(struct dict_reader *r, llarp_buffer_t *key)
{
int64_t i;
char tmp[128] = {0};
llarp_buffer_t strbuf;
struct llarp_ai *ai = r->user;
// done
if(!key)
return true;
// rank
if(llarp_buffer_eq(*key, "c"))
{
if(!bdecode_read_integer(r->buffer, &i))
return false;
if(i > 65536 || i <= 0)
return false;
ai->rank = i;
return true;
}
// dialect
if(llarp_buffer_eq(*key, "d"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz >= sizeof(ai->dialect))
return false;
memcpy(ai->dialect, strbuf.base, strbuf.sz);
ai->dialect[strbuf.sz] = 0;
return true;
}
// encryption public key
if(llarp_buffer_eq(*key, "e"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != sizeof(llarp_pubkey_t))
return false;
memcpy(ai->enc_key, strbuf.base, sizeof(llarp_pubkey_t));
return true;
}
// ip address
if(llarp_buffer_eq(*key, "i"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz >= sizeof(tmp))
return false;
memcpy(tmp, strbuf.base, strbuf.sz);
tmp[strbuf.sz] = 0;
return inet_pton(AF_INET6, tmp, ai->ip.s6_addr) == 1;
}
// port
if(llarp_buffer_eq(*key, "p"))
{
if(!bdecode_read_integer(r->buffer, &i))
return false;
if(i > 65536 || i <= 0)
return false;
ai->port = i;
return true;
}
// version
if(llarp_buffer_eq(*key, "v"))
{
if(!bdecode_read_integer(r->buffer, &i))
return false;
return i == LLARP_PROTO_VERSION;
}
// bad key
return false;
}
bool llarp_ai_bencode(struct llarp_ai *ai, llarp_buffer_t *buff) {
bool
llarp_ai_bdecode(struct llarp_ai *ai, llarp_buffer_t *buff)
{
struct dict_reader reader = {.user = ai, .on_key = &llarp_ai_decode_key};
return bdecode_read_dict(buff, &reader);
}
bool
llarp_ai_bencode(struct llarp_ai *ai, llarp_buffer_t *buff)
{
char ipbuff[128] = {0};
const char *ipstr;
if (!bencode_start_dict(buff)) return false;
if(!bencode_start_dict(buff))
return false;
/* rank */
if (!bencode_write_bytestring(buff, "c", 1)) return false;
if (!bencode_write_uint16(buff, ai->rank)) return false;
if(!bencode_write_bytestring(buff, "c", 1))
return false;
if(!bencode_write_uint16(buff, ai->rank))
return false;
/* dialect */
if (!bencode_write_bytestring(buff, "d", 1)) return false;
if (!bencode_write_bytestring(buff, ai->dialect,
strnlen(ai->dialect, sizeof(ai->dialect))))
if(!bencode_write_bytestring(buff, "d", 1))
return false;
if(!bencode_write_bytestring(buff, ai->dialect,
strnlen(ai->dialect, sizeof(ai->dialect))))
return false;
/* encryption key */
if (!bencode_write_bytestring(buff, "e", 1)) return false;
if (!bencode_write_bytestring(buff, ai->enc_key, sizeof(llarp_pubkey_t)))
if(!bencode_write_bytestring(buff, "e", 1))
return false;
if(!bencode_write_bytestring(buff, ai->enc_key, sizeof(llarp_pubkey_t)))
return false;
/** ip */
ipstr = inet_ntop(AF_INET6, &ai->ip, ipbuff, sizeof(ipbuff));
if (!ipstr) return false;
if (!bencode_write_bytestring(buff, "i", 1)) return false;
if (!bencode_write_bytestring(buff, ipstr, strnlen(ipstr, sizeof(ipbuff))))
if(!ipstr)
return false;
if(!bencode_write_bytestring(buff, "i", 1))
return false;
if(!bencode_write_bytestring(buff, ipstr, strnlen(ipstr, sizeof(ipbuff))))
return false;
/** port */
if (!bencode_write_bytestring(buff, "p", 1)) return false;
if (!bencode_write_uint16(buff, ai->port)) return false;
if(!bencode_write_bytestring(buff, "p", 1))
return false;
if(!bencode_write_uint16(buff, ai->port))
return false;
/** version */
if (!bencode_write_version_entry(buff)) return false;
if(!bencode_write_version_entry(buff))
return false;
/** end */
return bencode_end(buff);
}
static bool llarp_ai_list_iter_bencode(struct llarp_ai_list_iter *iter,
struct llarp_ai *ai) {
static bool
llarp_ai_list_iter_bencode(struct llarp_ai_list_iter *iter, struct llarp_ai *ai)
{
return llarp_ai_bencode(ai, iter->user);
}
bool llarp_ai_list_bencode(struct llarp_ai_list *l, llarp_buffer_t *buff) {
if (!bencode_start_list(buff)) return false;
struct llarp_ai_list_iter ai_itr = {.user = buff,
bool
llarp_ai_list_bencode(struct llarp_ai_list *l, llarp_buffer_t *buff)
{
if(!bencode_start_list(buff))
return false;
struct llarp_ai_list_iter ai_itr = {.user = buff,
.visit = &llarp_ai_list_iter_bencode};
llarp_ai_list_iterate(l, &ai_itr);
return bencode_end(buff);
}
struct llarp_ai_list_node {
struct llarp_ai_list_node
{
struct llarp_ai data;
struct llarp_ai_list_node *next;
};
struct llarp_ai_list {
struct llarp_alloc * mem;
struct llarp_ai_list
{
struct llarp_alloc *mem;
struct llarp_ai_list_node *root;
};
struct llarp_ai_list *llarp_ai_list_new(struct llarp_alloc * mem) {
struct llarp_ai_list *
llarp_ai_list_new(struct llarp_alloc *mem)
{
struct llarp_ai_list *l = mem->alloc(mem, sizeof(struct llarp_ai_list), 8);
if (l) {
l->mem = mem;
if(l)
{
l->mem = mem;
l->root = NULL;
}
return l;
}
void llarp_ai_list_free(struct llarp_ai_list **l) {
if (*l) {
struct llarp_alloc * mem = (*l)->mem;
void
llarp_ai_list_free(struct llarp_ai_list **l)
{
if(*l)
{
struct llarp_alloc *mem = (*l)->mem;
struct llarp_ai_list_node *cur = (*l)->root;
while (cur) {
while(cur)
{
struct llarp_ai_list_node *tmp = cur->next;
mem->free(mem, cur);
cur = tmp;
@ -87,12 +207,14 @@ void llarp_ai_list_free(struct llarp_ai_list **l) {
}
}
void llarp_ai_copy(struct llarp_ai * dst, struct llarp_ai * src)
void
llarp_ai_copy(struct llarp_ai *dst, struct llarp_ai *src)
{
memcpy(dst, src, sizeof(struct llarp_ai));
}
void llarp_ai_list_pushback(struct llarp_ai_list * l, struct llarp_ai a)
void
llarp_ai_list_pushback(struct llarp_ai_list *l, struct llarp_ai *ai)
{
struct llarp_ai_list_node *cur = l->root;
if(cur)
@ -100,31 +222,77 @@ void llarp_ai_list_pushback(struct llarp_ai_list * l, struct llarp_ai a)
// go to the end of the list
while(cur->next)
cur = cur->next;
cur->next = l->mem->alloc(l->mem, sizeof(struct llarp_ai_list_node), 16);
cur = cur->next;
cur = cur->next;
}
else
{
l->root = l->mem->alloc(l->mem, sizeof(struct llarp_ai_list_node), 16);
cur = l->root;
cur = l->root;
}
llarp_ai_copy(&cur->data, &a);
llarp_ai_copy(&cur->data, ai);
cur->next = 0;
}
void llarp_ai_list_iterate(struct llarp_ai_list *l,
struct llarp_ai_list_iter *itr) {
void
llarp_ai_list_iterate(struct llarp_ai_list *l, struct llarp_ai_list_iter *itr)
{
struct llarp_ai_list_node *cur = l->root;
itr->list = l;
while (cur) {
if (!itr->visit(itr, &cur->data)) return;
itr->list = l;
while(cur)
{
if(!itr->visit(itr, &cur->data))
return;
cur = cur->next;
};
}
bool llarp_ai_list_bdecode(struct llarp_ai_list * l, llarp_buffer_t * buff)
bool
llarp_ai_list_index(struct llarp_ai_list *l, ssize_t idx, struct llarp_ai *dst)
{
// TODO: implement negative indexes
if(idx < 0)
return false;
struct llarp_ai_list_node *cur = l->root;
if(!cur)
return false;
while(idx && cur)
{
cur = cur->next;
--idx;
}
if(cur)
{
llarp_ai_copy(dst, &cur->data);
return true;
}
return false;
}
static bool
llarp_ai_list_bdecode_item(struct list_reader *r, bool more)
{
if(!more)
return true;
struct llarp_ai_list *l = r->user;
struct llarp_ai ai;
if(!llarp_ai_bdecode(&ai, r->buffer))
return false;
llarp_ai_list_pushback(l, &ai);
return true;
}
bool
llarp_ai_list_bdecode(struct llarp_ai_list *l, llarp_buffer_t *buff)
{
struct list_reader r = {.user = l, .on_item = &llarp_ai_list_bdecode_item};
return bdecode_read_list(buff, &r);
}

@ -0,0 +1,262 @@
#include <arpa/inet.h>
#include <llarp/address_info.h>
#include <llarp/bencode.h>
#include <llarp/mem.h>
#include <llarp/string.h>
#include <vector>
struct llarp_ai_list
{
llarp_alloc *mem;
std::vector< llarp_ai > list;
llarp_ai_list(llarp_alloc *m) : mem(m)
{
}
};
static bool
llarp_ai_decode_key(struct dict_reader *r, llarp_buffer_t *key)
{
int64_t i;
char tmp[128] = {0};
llarp_buffer_t strbuf;
llarp_ai *ai = static_cast< llarp_ai * >(r->user);
// done
if(!key)
return true;
// rank
if(llarp_buffer_eq(*key, "c"))
{
if(!bdecode_read_integer(r->buffer, &i))
return false;
if(i > 65536 || i <= 0)
return false;
ai->rank = i;
return true;
}
// dialect
if(llarp_buffer_eq(*key, "d"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz >= sizeof(ai->dialect))
return false;
memcpy(ai->dialect, strbuf.base, strbuf.sz);
ai->dialect[strbuf.sz] = 0;
return true;
}
// encryption public key
if(llarp_buffer_eq(*key, "e"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != sizeof(llarp_pubkey_t))
return false;
memcpy(ai->enc_key, strbuf.base, sizeof(llarp_pubkey_t));
return true;
}
// ip address
if(llarp_buffer_eq(*key, "i"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz >= sizeof(tmp))
return false;
memcpy(tmp, strbuf.base, strbuf.sz);
tmp[strbuf.sz] = 0;
return inet_pton(AF_INET6, tmp, ai->ip.s6_addr) == 1;
}
// port
if(llarp_buffer_eq(*key, "p"))
{
if(!bdecode_read_integer(r->buffer, &i))
return false;
if(i > 65536 || i <= 0)
return false;
ai->port = i;
return true;
}
// version
if(llarp_buffer_eq(*key, "v"))
{
if(!bdecode_read_integer(r->buffer, &i))
return false;
return i == LLARP_PROTO_VERSION;
}
// bad key
return false;
}
static bool
llarp_ai_list_bdecode_item(struct list_reader *r, bool more)
{
if(!more)
return true;
llarp_ai_list *l = static_cast< llarp_ai_list * >(r->user);
llarp_ai ai;
if(!llarp_ai_bdecode(&ai, r->buffer))
return false;
llarp_ai_list_pushback(l, &ai);
return true;
}
static bool
llarp_ai_list_iter_bencode(struct llarp_ai_list_iter *iter, struct llarp_ai *ai)
{
return llarp_ai_bencode(ai, static_cast< llarp_buffer_t * >(iter->user));
}
extern "C" {
bool
llarp_ai_bdecode(struct llarp_ai *ai, llarp_buffer_t *buff)
{
struct dict_reader reader = {.user = ai, .on_key = &llarp_ai_decode_key};
return bdecode_read_dict(buff, &reader);
}
bool
llarp_ai_bencode(struct llarp_ai *ai, llarp_buffer_t *buff)
{
char ipbuff[128] = {0};
const char *ipstr;
if(!bencode_start_dict(buff))
return false;
/* rank */
if(!bencode_write_bytestring(buff, "c", 1))
return false;
if(!bencode_write_uint16(buff, ai->rank))
return false;
/* dialect */
if(!bencode_write_bytestring(buff, "d", 1))
return false;
if(!bencode_write_bytestring(buff, ai->dialect,
strnlen(ai->dialect, sizeof(ai->dialect))))
return false;
/* encryption key */
if(!bencode_write_bytestring(buff, "e", 1))
return false;
if(!bencode_write_bytestring(buff, ai->enc_key, sizeof(llarp_pubkey_t)))
return false;
/** ip */
ipstr = inet_ntop(AF_INET6, &ai->ip, ipbuff, sizeof(ipbuff));
if(!ipstr)
return false;
if(!bencode_write_bytestring(buff, "i", 1))
return false;
if(!bencode_write_bytestring(buff, ipstr, strnlen(ipstr, sizeof(ipbuff))))
return false;
/** port */
if(!bencode_write_bytestring(buff, "p", 1))
return false;
if(!bencode_write_uint16(buff, ai->port))
return false;
/** version */
if(!bencode_write_version_entry(buff))
return false;
/** end */
return bencode_end(buff);
}
bool
llarp_ai_list_bencode(struct llarp_ai_list *l, llarp_buffer_t *buff)
{
if(!bencode_start_list(buff))
return false;
struct llarp_ai_list_iter ai_itr = {.user = buff,
.visit = &llarp_ai_list_iter_bencode};
llarp_ai_list_iterate(l, &ai_itr);
return bencode_end(buff);
}
struct llarp_ai_list *
llarp_ai_list_new(struct llarp_alloc *mem)
{
void *ptr = mem->alloc(mem, sizeof(struct llarp_ai_list), 8);
if(ptr)
{
return new(ptr) llarp_ai_list(mem);
}
return nullptr;
}
void
llarp_ai_list_free(struct llarp_ai_list *l)
{
if(l)
{
struct llarp_alloc *mem = l->mem;
l->~llarp_ai_list();
mem->free(mem, l);
}
}
void
llarp_ai_copy(struct llarp_ai *dst, struct llarp_ai *src)
{
memcpy(dst, src, sizeof(struct llarp_ai));
}
void
llarp_ai_list_pushback(struct llarp_ai_list *l, struct llarp_ai *ai)
{
llarp_ai a;
llarp_ai_copy(&a, ai);
l->list.push_back(a);
}
void
llarp_ai_list_iterate(struct llarp_ai_list *l, struct llarp_ai_list_iter *itr)
{
itr->list = l;
for(auto &ai : l->list)
if(!itr->visit(itr, &ai))
return;
}
bool
llarp_ai_list_index(struct llarp_ai_list *l, ssize_t idx, struct llarp_ai *dst)
{
// TODO: implement negative indexes
if(idx < 0)
return false;
if(l->list.size() > idx)
{
llarp_ai_copy(dst, &l->list[idx]);
return true;
}
return false;
}
bool
llarp_ai_list_bdecode(struct llarp_ai_list *l, llarp_buffer_t *buff)
{
struct list_reader r = {.user = l, .on_item = &llarp_ai_list_bdecode_item};
return bdecode_read_list(buff, &r);
}
}

@ -4,58 +4,76 @@
#include <list>
#include <string>
namespace llarp {
template <typename ValType>
bool BEncode(const ValType &t, llarp_buffer_t *buff);
template <typename ValType>
bool BDecode(ValType &t, llarp_buffer_t *buff);
static bool bencodeDict(llarp_buffer_t *buff) {
static uint8_t c = 'd';
return llarp_buffer_write(buff, &c, 1);
}
static bool bencodeList(llarp_buffer_t *buff) {
static uint8_t c = 'l';
return llarp_buffer_write(buff, &c, 1);
}
static bool bencodeEnd(llarp_buffer_t *buff) {
static char c = 'e';
return llarp_buffer_write(buff, &c, 1);
}
static bool bencodeDictKey(llarp_buffer_t *buff, const std::string &key) {
std::string kstr = std::to_string(key.size()) + ":" + key;
return llarp_buffer_write(buff, kstr.c_str(), kstr.size());
}
template <typename IntType>
static bool bencodeDict_Int(llarp_buffer_t *buff, const std::string &key,
IntType i) {
std::string istr = "i" + std::to_string(i) + "e";
return bencodeDictKey(buff, key) &&
llarp_buffer_write(buff, istr.c_str(), istr.size());
}
static bool bencodeDict_Bytes(llarp_buffer_t *buff, const std::string &key,
const void *data, size_t sz) {
std::string sz_str = std::to_string(sz) + ":";
return bencodeDictKey(buff, key) &&
llarp_buffer_write(buff, sz_str.c_str(), sz_str.size()) &&
llarp_buffer_write(buff, data, sz);
}
template <typename T>
bool BEncode(const std::list<T> &l, llarp_buffer_t *buff) {
if (bencodeList(buff)) {
for (const auto &itr : l)
if (!BEncode(itr, buff)) return false;
return bencodeEnd(buff);
namespace llarp
{
template < typename ValType >
bool
BEncode(const ValType &t, llarp_buffer_t *buff);
template < typename ValType >
bool
BDecode(ValType &t, llarp_buffer_t *buff);
static bool
bencodeDict(llarp_buffer_t *buff)
{
static uint8_t c = 'd';
return llarp_buffer_write(buff, &c, 1);
}
static bool
bencodeList(llarp_buffer_t *buff)
{
static uint8_t c = 'l';
return llarp_buffer_write(buff, &c, 1);
}
static bool
bencodeEnd(llarp_buffer_t *buff)
{
static char c = 'e';
return llarp_buffer_write(buff, &c, 1);
}
static bool
bencodeDictKey(llarp_buffer_t *buff, const std::string &key)
{
std::string kstr = std::to_string(key.size()) + ":" + key;
return llarp_buffer_write(buff, kstr.c_str(), kstr.size());
}
template < typename IntType >
static bool
bencodeDict_Int(llarp_buffer_t *buff, const std::string &key, IntType i)
{
std::string istr = "i" + std::to_string(i) + "e";
return bencodeDictKey(buff, key)
&& llarp_buffer_write(buff, istr.c_str(), istr.size());
}
static bool
bencodeDict_Bytes(llarp_buffer_t *buff, const std::string &key,
const void *data, size_t sz)
{
std::string sz_str = std::to_string(sz) + ":";
return bencodeDictKey(buff, key)
&& llarp_buffer_write(buff, sz_str.c_str(), sz_str.size())
&& llarp_buffer_write(buff, data, sz);
}
template < typename T >
bool
BEncode(const std::list< T > &l, llarp_buffer_t *buff)
{
if(bencodeList(buff))
{
for(const auto &itr : l)
if(!BEncode(itr, buff))
return false;
return bencodeEnd(buff);
}
return false;
}
return false;
}
} // namespace llarp
#endif

@ -4,29 +4,39 @@
extern "C" {
size_t llarp_buffer_size_left(llarp_buffer_t* buff) {
size_t
llarp_buffer_size_left(llarp_buffer_t* buff)
{
size_t diff = buff->cur - buff->base;
if (diff > buff->sz)
if(diff > buff->sz)
return 0;
else
return buff->sz - diff;
}
bool llarp_buffer_writef(llarp_buffer_t* buff, const char* fmt, ...) {
bool
llarp_buffer_writef(llarp_buffer_t* buff, const char* fmt, ...)
{
int written;
size_t sz = llarp_buffer_size_left(buff);
ssize_t sz = llarp_buffer_size_left(buff);
va_list args;
va_start(args, fmt);
written = vsnprintf(buff->cur, sz, fmt, args);
written = vsnprintf((char*)buff->cur, sz, fmt, args);
va_end(args);
if (written == -1) return false;
if(written <= 0)
return false;
if(sz < written)
return false;
buff->cur += written;
return true;
}
bool llarp_buffer_write(llarp_buffer_t* buff, const void* data, size_t sz) {
bool
llarp_buffer_write(llarp_buffer_t* buff, const void* data, size_t sz)
{
size_t left = llarp_buffer_size_left(buff);
if (left >= sz) {
if(left >= sz)
{
memcpy(buff->cur, data, sz);
buff->cur += sz;
return true;
@ -34,15 +44,18 @@ bool llarp_buffer_write(llarp_buffer_t* buff, const void* data, size_t sz) {
return false;
}
bool llarp_buffer_readfile(llarp_buffer_t* buff, FILE* f, llarp_alloc* mem) {
bool
llarp_buffer_readfile(llarp_buffer_t* buff, FILE* f, llarp_alloc* mem)
{
ssize_t len;
fseek(f, 0, SEEK_END);
len = ftell(f);
rewind(f);
if (len > 0) {
buff->base = static_cast<char*>(mem->alloc(mem, len, 8));
buff->cur = buff->base;
buff->sz = len;
if(len > 0)
{
buff->base = static_cast< uint8_t* >(mem->alloc(mem, len, 8));
buff->cur = buff->base;
buff->sz = len;
ssize_t sz = fread(buff->base, len, 1, f);
rewind(f);
return sz == len;
@ -50,34 +63,38 @@ bool llarp_buffer_readfile(llarp_buffer_t* buff, FILE* f, llarp_alloc* mem) {
return false;
}
size_t llarp_buffer_read_until(llarp_buffer_t * buff, char delim, char * result, size_t resultsize)
size_t
llarp_buffer_read_until(llarp_buffer_t* buff, char delim, byte_t* result,
size_t resultsize)
{
size_t read = 0;
while(*buff->cur != delim && resultsize && (buff->cur != buff->base + buff->sz))
while(*buff->cur != delim && resultsize
&& (buff->cur != buff->base + buff->sz))
{
*result = *buff->cur;
buff->cur ++;
result ++;
resultsize --;
read ++;
buff->cur++;
result++;
resultsize--;
read++;
}
if(llarp_buffer_size_left(buff))
return read;
else
else
return 0;
}
bool llarp_buffer_eq(llarp_buffer_t buf, const char * str)
bool
llarp_buffer_eq(llarp_buffer_t buf, const char* str)
{
while(*str && buf.cur != (buf.base + buf.sz))
{
if(*buf.cur != *str) return false;
buf.cur ++;
if(*buf.cur != *str)
return false;
buf.cur++;
str++;
}
return *str == 0;
}
}

@ -6,17 +6,37 @@
namespace llarp
{
/** initialize llarp_buffer_t from stack allocated buffer */
template<typename T>
llarp_buffer_t StackBuffer(T & stack)
template < typename T >
void
StackBuffer(llarp_buffer_t& buff, T& stack)
{
buff.base = stack;
buff.cur = buff.base;
buff.sz = sizeof(stack);
}
template < typename T >
llarp_buffer_t
StackBuffer(T& stack)
{
llarp_buffer_t buff;
buff.base = (char*) stack;
buff.cur = (char*) stack;
buff.sz = sizeof(stack);
buff.base = stack;
buff.cur = buff.base;
buff.sz = sizeof(stack);
return buff;
}
}
/** initialize llarp_buffer_t from container */
template < typename T >
llarp_buffer_t
Buffer(T& t)
{
llarp_buffer_t buff;
buff.base = &t[0];
buff.cur = buff.base;
buff.sz = t.size();
return buff;
}
}
#endif

@ -3,61 +3,75 @@
#include "ini.hpp"
#include "mem.hpp"
namespace llarp {
template <typename Config, typename Section>
static const Section & find_section(Config &c, const std::string &name,
const Section &fallback) {
if (c.sections.find(name) == c.sections.end()) return fallback;
return c.sections[name].values;
}
bool Config::Load(const char *fname) {
std::ifstream f;
f.open(fname);
if (f.is_open()) {
ini::Parser parser(f);
auto &top = parser.top();
router = find_section(top, "router", section_t{});
network = find_section(top, "network", section_t{});
connect = find_section(top, "iwp-connect", section_t{});
netdb = find_section(top, "netdb", section_t{});
iwp_links = find_section(top, "iwp-links", section_t{});
return true;
namespace llarp
{
template < typename Config, typename Section >
static const Section &
find_section(Config &c, const std::string &name, const Section &fallback)
{
if(c.sections.find(name) == c.sections.end())
return fallback;
return c.sections[name].values;
}
return false;
};
bool
Config::Load(const char *fname)
{
std::ifstream f;
f.open(fname);
if(f.is_open())
{
ini::Parser parser(f);
auto &top = parser.top();
router = find_section(top, "router", section_t{});
network = find_section(top, "network", section_t{});
connect = find_section(top, "iwp-connect", section_t{});
netdb = find_section(top, "netdb", section_t{});
iwp_links = find_section(top, "iwp-links", section_t{});
return true;
}
return false;
};
} // namespace llarp
extern "C" {
void llarp_new_config(struct llarp_config **conf) {
void
llarp_new_config(struct llarp_config **conf)
{
llarp_config *c = new llarp_config;
*conf = c;
*conf = c;
}
void llarp_free_config(struct llarp_config **conf) {
if (*conf) delete *conf;
void
llarp_free_config(struct llarp_config **conf)
{
if(*conf)
delete *conf;
*conf = nullptr;
}
int llarp_load_config(struct llarp_config *conf, const char *fname) {
if (!conf->impl.Load(fname)) return -1;
int
llarp_load_config(struct llarp_config *conf, const char *fname)
{
if(!conf->impl.Load(fname))
return -1;
return 0;
}
void llarp_config_iter(struct llarp_config *conf,
struct llarp_config_iterator *iter) {
iter->conf = conf;
std::map<std::string, llarp::Config::section_t &> sections = {
void
llarp_config_iter(struct llarp_config *conf, struct llarp_config_iterator *iter)
{
iter->conf = conf;
std::map< std::string, llarp::Config::section_t & > sections = {
{"router", conf->impl.router},
{"network", conf->impl.network},
{"iwp-connect", conf->impl.connect},
{"iwp-links", conf->impl.iwp_links},
{"netdb", conf->impl.netdb}};
for (const auto &section : sections)
for (const auto &item : section.second)
for(const auto section : sections)
for(const auto item : section.second)
iter->visit(iter, section.first.c_str(), item.first.c_str(),
item.second.c_str());
}

@ -5,22 +5,26 @@
#include <llarp/config.h>
namespace llarp {
struct Config {
typedef std::list<std::pair<std::string, std::string> > section_t;
namespace llarp
{
struct Config
{
typedef std::list< std::pair< std::string, std::string > > section_t;
section_t router;
section_t network;
section_t netdb;
section_t iwp_links;
section_t connect;
section_t router;
section_t network;
section_t netdb;
section_t iwp_links;
section_t connect;
bool Load(const char *fname);
};
bool
Load(const char *fname);
};
} // namespace llarp
extern "C" {
struct llarp_config {
struct llarp_config
{
llarp::Config impl;
};
}

@ -4,8 +4,9 @@
#include <llarp/crypto.h>
#include <array>
namespace llarp {
typedef std::array<uint8_t, sizeof(llarp_pubkey_t)> pubkey;
namespace llarp
{
typedef std::array< uint8_t, sizeof(llarp_pubkey_t) > pubkey;
}
#endif

@ -1,235 +1,246 @@
#include <llarp/crypto_async.h>
#include <llarp/mem.h>
#include <string.h>
#include "buffer.hpp"
#include "mem.hpp"
struct llarp_async_iwp
{
struct llarp_alloc * mem;
struct llarp_crypto * crypto;
struct llarp_logic * logic;
struct llarp_threadpool * worker;
struct llarp_alloc *mem;
struct llarp_crypto *crypto;
struct llarp_logic *logic;
struct llarp_threadpool *worker;
};
namespace iwp
{
void
inform_keygen(void *user)
{
iwp_async_keygen *keygen = static_cast< iwp_async_keygen * >(user);
keygen->hook(keygen);
}
void inform_keygen(void * user)
{
iwp_async_keygen * keygen = static_cast<iwp_async_keygen *>(user);
keygen->hook(keygen);
}
void keygen(void * user)
{
iwp_async_keygen * keygen = static_cast<iwp_async_keygen *>(user);
keygen->iwp->crypto->keygen(keygen->keybuf);
llarp_thread_job job = {
.user = user,
.work = &inform_keygen
};
llarp_logic_queue_job(keygen->iwp->logic, job);
}
void inform_gen_intro(void * user)
{
iwp_async_intro * intro = static_cast<iwp_async_intro *>(user);
intro->hook(intro);
}
void gen_intro(void * user)
{
iwp_async_intro * intro = static_cast<iwp_async_intro *>(user);
llarp_sharedkey_t sharedkey;
llarp_shorthash_t e_k;
llarp_buffer_t buf;
llarp_crypto * crypto = intro->iwp->crypto;
uint8_t tmp[64];
llarp_thread_job job = {
.user = user,
.work = &inform_gen_intro
};
// S = TKE(a.k, b.k, n)
crypto->transport_dh_client(sharedkey, intro->remote_pubkey, intro->secretkey, intro->nonce);
buf.base = (char*)tmp;
buf.sz = sizeof(tmp);
// e_k = HS(b.k + n)
memcpy(tmp, intro->remote_pubkey, 32);
memcpy(tmp + 32, intro->nonce, 32);
crypto->shorthash(&e_k, buf);
// e = SE(a.k, e_k, n[0:24])
memcpy(intro->buf + 32, llarp_seckey_topublic(intro->secretkey), 32);
buf.base = (char*) intro->buf + 32;
buf.sz = 32;
crypto->xchacha20(buf, e_k, intro->nonce);
// h = MDS( n + e + w0, S)
buf.sz = intro->sz - 32;
crypto->hmac(intro->buf, buf, sharedkey);
// inform result
llarp_logic_queue_job(intro->iwp->logic, job);
}
void
keygen(void *user)
{
iwp_async_keygen *keygen = static_cast< iwp_async_keygen * >(user);
keygen->iwp->crypto->keygen(keygen->keybuf);
llarp_thread_job job = {.user = user, .work = &inform_keygen};
llarp_logic_queue_job(keygen->iwp->logic, job);
}
void
inform_gen_intro(void *user)
{
iwp_async_intro *intro = static_cast< iwp_async_intro * >(user);
intro->hook(intro);
}
void inform_verify_introack(void * user)
{
iwp_async_introack * introack = static_cast<iwp_async_introack *>(user);
introack->hook(introack);
}
void
gen_intro(void *user)
{
iwp_async_intro *intro = static_cast< iwp_async_intro * >(user);
llarp_sharedkey_t sharedkey;
llarp_shorthash_t e_k;
llarp_nonce_t n;
llarp_crypto *crypto = intro->iwp->crypto;
byte_t tmp[64];
// S = TKE(a.k, b.k, n)
printf("dh\n");
crypto->transport_dh_client(sharedkey, intro->remote_pubkey,
intro->secretkey, intro->nonce);
llarp_buffer_t buf;
llarp::StackBuffer< decltype(tmp) >(buf, tmp);
// copy nonce
memcpy(n, intro->nonce, 24);
// e_k = HS(b.k + n)
memcpy(tmp, intro->remote_pubkey, 32);
memcpy(tmp + 32, intro->nonce, 32);
printf("shorthash\n");
crypto->shorthash(e_k, buf);
printf("copy\n");
// e = SE(a.k, e_k, n[0:24])
memcpy(intro->buf + 32, llarp_seckey_topublic(intro->secretkey), 32);
buf.base = intro->buf + 32;
buf.sz = 32;
printf("chacha\n");
crypto->xchacha20(buf, e_k, n);
// h = MDS( n + e + w0, S)
buf.sz = intro->sz - 32;
printf("hmac\n");
crypto->hmac(intro->buf, buf, sharedkey);
// inform result
llarp_logic_queue_job(intro->iwp->logic, {intro, &inform_gen_intro});
}
void
inform_verify_introack(void *user)
{
iwp_async_introack *introack = static_cast< iwp_async_introack * >(user);
introack->hook(introack);
}
void verify_introack(void * user)
{
iwp_async_introack * introack = static_cast<iwp_async_introack *>(user);
auto crypto = introack->iwp->crypto;
auto logic = introack->iwp->logic;
llarp_thread_job job = {
.user = user,
.work = &inform_verify_introack
};
llarp_hmac_t digest;
llarp_sharedkey_t sharedkey;
auto hmac = introack->buf;
auto body = introack->buf + 32;
auto pubkey = introack->remote_pubkey;
auto secretkey = introack->secretkey;
auto nonce = introack->buf + 32;
auto token = introack->buf + 64;
size_t bodysz = introack->sz - 32;
llarp_buffer_t buf;
buf.base = (char*) body;
buf.sz = bodysz;
// S = TKE(a.k, b.k, n)
crypto->transport_dh_client(sharedkey, pubkey, secretkey, nonce);
// h = MDS(n + x + w1, S)
crypto->hmac(digest, buf, sharedkey);
if(!llarp_eq(digest, hmac, 32))
void
verify_introack(void *user)
{
// fail to verify hmac
introack->buf = nullptr;
iwp_async_introack *introack = static_cast< iwp_async_introack * >(user);
auto crypto = introack->iwp->crypto;
auto logic = introack->iwp->logic;
llarp_thread_job job = {.user = user, .work = &inform_verify_introack};
llarp_hmac_t digest;
llarp_sharedkey_t sharedkey;
auto hmac = introack->buf;
auto body = introack->buf + 32;
auto pubkey = introack->remote_pubkey;
auto secretkey = introack->secretkey;
auto nonce = introack->buf + 32;
auto token = introack->buf + 64;
size_t bodysz = introack->sz - 32;
llarp_buffer_t buf;
buf.base = body;
buf.cur = body;
buf.sz = bodysz;
// S = TKE(a.k, b.k, n)
crypto->transport_dh_client(sharedkey, pubkey, secretkey, nonce);
// h = MDS(n + x + w1, S)
crypto->hmac(digest, buf, sharedkey);
if(!llarp_eq(digest, hmac, 32))
{
// fail to verify hmac
introack->buf = nullptr;
llarp_logic_queue_job(logic, job);
return;
}
buf.base = token;
buf.sz = 32;
// token = SD(S, x, n[0:24])
crypto->xchacha20(buf, sharedkey, nonce);
// copy token
memcpy(introack->token, token, 32);
llarp_logic_queue_job(logic, job);
return;
}
buf.base = (char *) token;
buf.sz = 32;
// token = SD(S, x, n[0:24])
crypto->xchacha20(buf, sharedkey, nonce);
// copy token
memcpy(introack->token, token, 32);
llarp_logic_queue_job(logic, job);
}
void inform_gen_session_start(void * user)
void
inform_gen_session_start(void *user)
{
iwp_async_session_start * session = static_cast<iwp_async_session_start *>(user);
session->hook(session);
iwp_async_session_start *session =
static_cast< iwp_async_session_start * >(user);
session->hook(session);
}
void gen_session_start(void * user)
void
gen_session_start(void *user)
{
iwp_async_session_start * session = static_cast<iwp_async_session_start *>(user);
iwp_async_session_start *session =
static_cast< iwp_async_session_start * >(user);
auto crypto = session->iwp->crypto;
auto dh = crypto->transport_dh_client;
auto dh = crypto->transport_dh_client;
auto shorthash = crypto->shorthash;
auto hmac = crypto->hmac;
auto encrypt = crypto->xchacha20;
auto hmac = crypto->hmac;
auto encrypt = crypto->xchacha20;
auto logic = session->iwp->logic;
auto a_sK = session->secretkey;
auto b_K = session->remote_pubkey;
auto N = session->nonce;
auto a_sK = session->secretkey;
auto b_K = session->remote_pubkey;
auto N = session->nonce;
auto token = session->token;
auto K = session->sessionkey;
auto K = session->sessionkey;
llarp_sharedkey_t e_K;
llarp_shorthash_t T;
llarp_buffer_t buf;
uint8_t tmp[64];
byte_t tmp[64];
llarp_buffer_t buf;
llarp::StackBuffer< decltype(tmp) >(buf, tmp);
// T = HS(token + n)
memcpy(tmp, token, 32);
memcpy(tmp + 32, N, 32);
buf.base = (char *) tmp;
buf.sz = 64;
shorthash(&T, buf);
shorthash(T, buf);
// e_K = TKE(a.k, b.k, N)
dh(e_K, b_K, a_sK, N);
// K = TKE(a.k, b.k, T)
dh(K, b_K, a_sK, T);
// x = SE(e_K, token, n[0:24])
buf.base = (char *) (session->buf + 64);
buf.sz = 32;
buf.base = (session->buf + 32);
buf.sz = 32;
memcpy(buf.base, token, 32);
encrypt(buf, e_K, N);
// h = MDS(n + x + w2, e_K)
buf.base = (char*) (session->buf + 32);
buf.sz = session->sz - 32;
buf.base = (session->buf + 32);
buf.sz = session->sz - 32;
hmac(session->buf, buf, e_K);
// K = TKE(a.k, b.k, T)
dh(K, b_K, a_sK, T);
llarp_logic_queue_job(logic, {user, &inform_gen_session_start});
}
}
extern "C" {
void iwp_call_async_keygen(struct llarp_async_iwp * iwp, struct iwp_async_keygen * keygen)
void
iwp_call_async_keygen(struct llarp_async_iwp *iwp,
struct iwp_async_keygen *keygen)
{
keygen->iwp = iwp;
llarp_threadpool_queue_job(iwp->worker, {keygen, &iwp::keygen});
}
void iwp_call_async_gen_intro(struct llarp_async_iwp * iwp, struct iwp_async_intro * intro)
void
iwp_call_async_gen_intro(struct llarp_async_iwp *iwp,
struct iwp_async_intro *intro)
{
intro->iwp = iwp;
llarp_threadpool_queue_job(iwp->worker, {intro, &iwp::gen_intro});
}
void iwp_call_async_verify_introack(struct llarp_async_iwp * iwp, struct iwp_async_introack * introack)
void
iwp_call_async_verify_introack(struct llarp_async_iwp *iwp,
struct iwp_async_introack *introack)
{
introack->iwp = iwp;
llarp_threadpool_queue_job(iwp->worker, {introack, &iwp::verify_introack});
}
void iwp_call_async_gen_session_start(struct llarp_async_iwp * iwp, struct iwp_async_session_start * session)
void
iwp_call_async_gen_session_start(struct llarp_async_iwp *iwp,
struct iwp_async_session_start *session)
{
session->iwp = iwp;
llarp_threadpool_queue_job(iwp->worker, {session, &iwp::gen_session_start});
}
void iwp_call_async_frame_decrypt(struct llarp_async_iwp * iwp, struct iwp_async_frame * frame)
void
iwp_call_async_frame_decrypt(struct llarp_async_iwp *iwp,
struct iwp_async_frame *frame)
{
}
struct llarp_async_iwp * llarp_async_iwp_new(struct llarp_alloc * mem,
struct llarp_crypto * crypto,
struct llarp_logic * logic,
struct llarp_threadpool * worker)
struct llarp_async_iwp *
llarp_async_iwp_new(struct llarp_alloc *mem, struct llarp_crypto *crypto,
struct llarp_logic *logic, struct llarp_threadpool *worker)
{
struct llarp_async_iwp * iwp = llarp::Alloc<llarp_async_iwp>(mem);
struct llarp_async_iwp *iwp = llarp::Alloc< llarp_async_iwp >(mem);
if(iwp)
{
iwp->mem = mem;
iwp->mem = mem;
iwp->crypto = crypto;
iwp->logic = logic;
iwp->logic = logic;
iwp->worker = worker;
}
return iwp;
}
}

@ -2,123 +2,168 @@
#include <llarp/crypto.h>
#include <sodium.h>
namespace llarp {
namespace sodium {
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;
}
namespace llarp
{
namespace sodium
{
static bool
xchacha20(llarp_buffer_t buff, llarp_sharedkey_t k, llarp_nonce_t n)
{
return crypto_stream_xchacha20_xor(buff.base, buff.base, buff.sz, n, k)
== 0;
}
static bool dh(uint8_t * out, uint8_t *client_pk,
uint8_t *server_pk, uint8_t *remote_key, uint8_t *local_key) {
crypto_generichash_state h;
const size_t outsz = SHAREDKEYSIZE;
if (crypto_scalarmult(out, local_key, remote_key) == -1) return false;
crypto_generichash_init(&h, NULL, 0U, outsz);
crypto_generichash_update(&h, client_pk, sizeof(llarp_pubkey_t));
crypto_generichash_update(&h, server_pk, sizeof(llarp_pubkey_t));
crypto_generichash_update(&h, out, crypto_scalarmult_BYTES);
crypto_generichash_final(&h, out, outsz);
return true;
}
static bool
dh(uint8_t *out, uint8_t *client_pk, uint8_t *server_pk,
uint8_t *remote_key, uint8_t *local_key)
{
crypto_generichash_state h;
const size_t outsz = SHAREDKEYSIZE;
if(crypto_scalarmult(out, local_key, remote_key) == -1)
return false;
crypto_generichash_init(&h, NULL, 0U, outsz);
crypto_generichash_update(&h, client_pk, sizeof(llarp_pubkey_t));
crypto_generichash_update(&h, server_pk, sizeof(llarp_pubkey_t));
crypto_generichash_update(&h, out, crypto_scalarmult_BYTES);
crypto_generichash_final(&h, out, outsz);
return true;
}
static bool dh_client(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
llarp_tunnel_nounce_t n, llarp_seckey_t sk) {
if (dh(*shared, llarp_seckey_topublic(sk), pk, pk, sk)) {
return crypto_generichash(*shared, SHAREDKEYSIZE, *shared, SHAREDKEYSIZE, n,
TUNNOUNCESIZE) != -1;
}
return false;
}
static bool
dh_client(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
llarp_tunnel_nonce_t n, llarp_seckey_t sk)
{
if(dh(*shared, llarp_seckey_topublic(sk), pk, pk, sk))
{
return crypto_generichash(*shared, SHAREDKEYSIZE, *shared,
SHAREDKEYSIZE, n, TUNNONCESIZE)
!= -1;
}
return false;
}
static bool dh_server(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
llarp_tunnel_nounce_t n, llarp_seckey_t sk) {
if (dh(*shared, pk, llarp_seckey_topublic(sk), pk, sk)) {
return crypto_generichash(*shared, SHAREDKEYSIZE, *shared, SHAREDKEYSIZE, n,
TUNNOUNCESIZE) != -1;
}
return false;
}
static bool
dh_server(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
llarp_tunnel_nonce_t n, llarp_seckey_t sk)
{
if(dh(*shared, pk, llarp_seckey_topublic(sk), pk, sk))
{
return crypto_generichash(*shared, SHAREDKEYSIZE, *shared,
SHAREDKEYSIZE, n, TUNNONCESIZE)
!= -1;
}
return false;
}
static bool
transport_dh_client(uint8_t *shared, uint8_t *pk, uint8_t *sk, uint8_t *n)
{
if(dh(shared, llarp_seckey_topublic(sk), pk, pk, sk))
{
return crypto_generichash(shared, SHAREDKEYSIZE, shared, SHAREDKEYSIZE,
n, 32)
!= -1;
}
return false;
}
static bool transport_dh_client(uint8_t *shared, uint8_t * pk,
uint8_t * sk, uint8_t * n) {
if (dh(shared, llarp_seckey_topublic(sk), pk, pk, sk)) {
return crypto_generichash(shared, SHAREDKEYSIZE, shared, SHAREDKEYSIZE, n,
NOUNCESIZE) != -1;
}
return false;
}
static bool
transport_dh_server(uint8_t *shared, uint8_t *pk, uint8_t *sk, uint8_t *n)
{
if(dh(shared, pk, llarp_seckey_topublic(sk), pk, sk))
{
return crypto_generichash(shared, SHAREDKEYSIZE, shared, SHAREDKEYSIZE,
n, 32)
!= -1;
}
return false;
}
static bool transport_dh_server(uint8_t *shared, uint8_t * pk,
uint8_t * sk, uint8_t * n) {
if (dh(shared, pk, llarp_seckey_topublic(sk), pk, sk)) {
return crypto_generichash(shared, SHAREDKEYSIZE, shared, SHAREDKEYSIZE, n,
NOUNCESIZE) != -1;
}
return false;
}
static bool
hash(uint8_t *result, llarp_buffer_t buff)
{
return crypto_generichash(result, HASHSIZE, buff.base, buff.sz, nullptr,
0)
!= -1;
}
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;
}
static bool shorthash(llarp_shorthash_t *result, llarp_buffer_t buff) {
const uint8_t *base = (const uint8_t *)buff.base;
return crypto_generichash(*result, SHORTHASHSIZE, base, buff.sz, nullptr, 0) != -1;
}
static bool
shorthash(uint8_t *result, llarp_buffer_t buff)
{
return crypto_generichash(result, SHORTHASHSIZE, buff.base, buff.sz,
nullptr, 0)
!= -1;
}
static bool hmac(uint8_t *result, llarp_buffer_t buff,
const uint8_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;
}
static bool
hmac(uint8_t *result, llarp_buffer_t buff, const uint8_t *secret)
{
return crypto_generichash(result, sizeof(llarp_hash_t), buff.base,
buff.sz, secret, HMACSECSIZE)
!= -1;
}
static bool sign(uint8_t *result, const uint8_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;
}
static bool
sign(uint8_t *result, const uint8_t *secret, llarp_buffer_t buff)
{
return crypto_sign_detached(result, nullptr, buff.base, buff.sz, secret)
!= -1;
}
static bool verify(const uint8_t * pub, llarp_buffer_t buff, const uint8_t * sig) {
const uint8_t *base = (const uint8_t *)buff.base;
return crypto_sign_verify_detached(sig, base, buff.sz, pub) != -1;
}
static bool
verify(const uint8_t *pub, llarp_buffer_t buff, const uint8_t *sig)
{
return crypto_sign_verify_detached(sig, buff.base, buff.sz, pub) != -1;
}
static void randomize(llarp_buffer_t buff) {
randombytes((unsigned char *)buff.base, buff.sz);
}
static void
randomize(llarp_buffer_t buff)
{
randombytes((unsigned char *)buff.base, buff.sz);
}
static inline void randbytes(void *ptr, size_t sz) {
randombytes((unsigned char *)ptr, sz);
}
static inline void
randbytes(void *ptr, size_t sz)
{
randombytes((unsigned char *)ptr, sz);
}
static void keygen(uint8_t *keys) {
unsigned char seed[32];
uint8_t *pk = llarp_seckey_topublic(keys);
crypto_sign_seed_keypair(pk, keys, seed);
}
} // namespace sodium
static void
keygen(uint8_t *keys)
{
uint8_t *pk = llarp_seckey_topublic(keys);
crypto_sign_keypair(pk, keys);
}
} // namespace sodium
} // namespace llarp
extern "C" {
void llarp_crypto_libsodium_init(struct llarp_crypto *c) {
uint8_t *
llarp_seckey_topublic(uint8_t *secret)
{
return secret + 32;
}
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;
c->xchacha20 = llarp::sodium::xchacha20;
c->dh_client = llarp::sodium::dh_client;
c->dh_server = llarp::sodium::dh_server;
c->transport_dh_client = llarp::sodium::transport_dh_client;
c->transport_dh_server = llarp::sodium::transport_dh_server;
c->hash = llarp::sodium::hash;
c->shorthash = llarp::sodium::shorthash;
c->hmac = llarp::sodium::hmac;
c->sign = llarp::sodium::sign;
c->verify = llarp::sodium::verify;
c->randomize = llarp::sodium::randomize;
c->randbytes = llarp::sodium::randbytes;
c->keygen = llarp::sodium::keygen;
c->hash = llarp::sodium::hash;
c->shorthash = llarp::sodium::shorthash;
c->hmac = llarp::sodium::hmac;
c->sign = llarp::sodium::sign;
c->verify = llarp::sodium::verify;
c->randomize = llarp::sodium::randomize;
c->randbytes = llarp::sodium::randbytes;
c->keygen = llarp::sodium::keygen;
int seed;
c->randbytes(&seed, sizeof(seed));
srand(seed);
}
}

@ -9,8 +9,10 @@
#endif
extern "C" {
void llarp_ev_loop_alloc(struct llarp_ev_loop **ev) {
void
llarp_ev_loop_alloc(struct llarp_ev_loop **ev)
{
#ifdef __linux__
*ev = new llarp_epoll_loop;
#endif
@ -20,30 +22,46 @@ void llarp_ev_loop_alloc(struct llarp_ev_loop **ev) {
(*ev)->init();
}
void llarp_ev_loop_free(struct llarp_ev_loop **ev) {
void
llarp_ev_loop_free(struct llarp_ev_loop **ev)
{
delete *ev;
*ev = nullptr;
}
int llarp_ev_loop_run(struct llarp_ev_loop *ev) { return ev->run(); }
int
llarp_ev_loop_run(struct llarp_ev_loop *ev)
{
return ev->run();
}
int llarp_ev_add_udp(struct llarp_ev_loop *ev,
struct llarp_udp_io * udp) {
int
llarp_ev_add_udp(struct llarp_ev_loop *ev, struct llarp_udp_io *udp)
{
udp->parent = ev;
if(ev->udp_listen(udp)) return 0;
if(ev->udp_listen(udp))
return 0;
return -1;
}
int llarp_ev_close_udp_close(struct llarp_udp_io * udp) {
if(udp->parent->udp_close(udp)) return 0;
int
llarp_ev_close_udp_close(struct llarp_udp_io *udp)
{
if(udp->parent->udp_close(udp))
return 0;
return -1;
}
void llarp_ev_loop_stop(struct llarp_ev_loop *loop) { loop->stop(); }
int llarp_ev_udp_sendto(struct llarp_udp_io * udp, const sockaddr * to, const void * buf, size_t sz)
void
llarp_ev_loop_stop(struct llarp_ev_loop *loop)
{
return static_cast<llarp::ev_io*>(udp->impl)->sendto(to, buf,sz);
loop->stop();
}
int
llarp_ev_udp_sendto(struct llarp_udp_io *udp, const sockaddr *to,
const void *buf, size_t sz)
{
return static_cast< llarp::ev_io * >(udp->impl)->sendto(to, buf, sz);
}
}

@ -4,24 +4,38 @@
#include <unistd.h>
namespace llarp {
struct ev_io {
int fd;
ev_io(int f) : fd(f){};
virtual int read(void* buf, size_t sz) = 0;
virtual int sendto(const sockaddr* dst, const void* data, size_t sz) = 0;
virtual ~ev_io() { ::close(fd); };
};
namespace llarp
{
struct ev_io
{
int fd;
ev_io(int f) : fd(f){};
virtual int
read(void* buf, size_t sz) = 0;
virtual int
sendto(const sockaddr* dst, const void* data, size_t sz) = 0;
virtual ~ev_io()
{
::close(fd);
};
};
}; // namespace llarp
struct llarp_ev_loop {
virtual bool init() = 0;
virtual int run() = 0;
virtual void stop() = 0;
struct llarp_ev_loop
{
virtual bool
init() = 0;
virtual int
run() = 0;
virtual void
stop() = 0;
virtual bool udp_listen(llarp_udp_io* l) = 0;
virtual bool udp_close(llarp_udp_io* l) = 0;
virtual bool close_ev(llarp::ev_io * ev) = 0;
virtual bool
udp_listen(llarp_udp_io* l) = 0;
virtual bool
udp_close(llarp_udp_io* l) = 0;
virtual bool
close_ev(llarp::ev_io* ev) = 0;
virtual ~llarp_ev_loop(){};
};

@ -1,69 +1,103 @@
#ifndef EV_EPOLL_HPP
#define EV_EPOLL_HPP
#include <llarp/buffer.h>
#include <llarp/net.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <cstdio>
#include "ev.hpp"
namespace llarp {
struct udp_listener : public ev_io {
llarp_udp_io* udp;
udp_listener(int fd, llarp_udp_io* u) : ev_io(fd), udp(u){};
namespace llarp
{
struct udp_listener : public ev_io
{
llarp_udp_io* udp;
~udp_listener() {}
udp_listener(int fd, llarp_udp_io* u) : ev_io(fd), udp(u){};
virtual int read(void* buf, size_t sz) {
sockaddr src;
socklen_t slen;
int ret = ::recvfrom(fd, buf, sz, 0, &src, &slen);
if (ret == -1) return -1;
udp->recvfrom(udp, &src, buf, ret);
return 0;
}
~udp_listener()
{
}
virtual int sendto(const sockaddr* to, const void* data, size_t sz) {
socklen_t slen;
switch (to->sa_family) {
case AF_INET:
slen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
slen = sizeof(struct sockaddr_in6);
break;
default:
virtual int
read(void* buf, size_t sz)
{
sockaddr src;
socklen_t slen;
int ret = ::recvfrom(fd, buf, sz, 0, &src, &slen);
if(ret == -1)
return -1;
udp->recvfrom(udp, &src, buf, ret);
return 0;
}
return ::sendto(fd, data, sz, 0, to, slen);
}
};
virtual int
sendto(const sockaddr* to, const void* data, size_t sz)
{
socklen_t slen;
switch(to->sa_family)
{
case AF_INET:
printf("af_inet\n");
slen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
printf("af_inet6\n");
slen = sizeof(struct sockaddr_in6);
break;
default:
return -1;
}
printf("send %ld via %d\n", sz, fd);
ssize_t sent = ::sendto(fd, data, sz, SOCK_NONBLOCK, to, slen);
if(sent == -1)
perror("sendto()");
return sent;
}
};
}; // namespace llarp
struct llarp_epoll_loop : public llarp_ev_loop {
struct llarp_epoll_loop : public llarp_ev_loop
{
int epollfd;
llarp_epoll_loop() : epollfd(-1) {}
llarp_epoll_loop() : epollfd(-1)
{
}
~llarp_epoll_loop() {}
~llarp_epoll_loop()
{
}
bool init() {
if (epollfd == -1) epollfd = epoll_create1(EPOLL_CLOEXEC);
bool
init()
{
if(epollfd == -1)
epollfd = epoll_create1(EPOLL_CLOEXEC);
return epollfd != -1;
}
int run() {
int
run()
{
epoll_event events[1024];
int result;
char readbuf[2048];
do {
byte_t readbuf[2048];
do
{
result = epoll_wait(epollfd, events, 1024, -1);
if (result > 0) {
if(result > 0)
{
printf("epoll %d\n", result);
int idx = 0;
while (idx < result) {
llarp::ev_io* ev = static_cast<llarp::ev_io*>(events[idx].data.ptr);
if (events[idx].events & EPOLLIN) {
if (ev->read(readbuf, sizeof(readbuf)) == -1) {
while(idx < result)
{
llarp::ev_io* ev = static_cast< llarp::ev_io* >(events[idx].data.ptr);
if(events[idx].events & EPOLLIN)
{
if(ev->read(readbuf, sizeof(readbuf)) == -1)
{
printf("close ev\n");
close_ev(ev);
delete ev;
}
@ -71,13 +105,16 @@ struct llarp_epoll_loop : public llarp_ev_loop {
++idx;
}
}
} while (result != -1);
} while(result != -1);
return result;
}
int udp_bind(const sockaddr* addr) {
int
udp_bind(const sockaddr* addr)
{
socklen_t slen;
switch (addr->sa_family) {
switch(addr->sa_family)
{
case AF_INET:
slen = sizeof(struct sockaddr_in);
break;
@ -91,27 +128,34 @@ struct llarp_epoll_loop : public llarp_ev_loop {
return -1;
}
int fd = socket(addr->sa_family, SOCK_DGRAM, 0);
if (fd == -1) return -1;
if (bind(fd, addr, slen) == -1) {
if(fd == -1)
return -1;
if(bind(fd, addr, slen) == -1)
{
close(fd);
return -1;
}
return fd;
}
bool close_ev(llarp::ev_io * ev)
bool
close_ev(llarp::ev_io* ev)
{
return epoll_ctl(epollfd, EPOLL_CTL_DEL, ev->fd, nullptr) != -1;
}
bool udp_listen(llarp_udp_io* l) {
bool
udp_listen(llarp_udp_io* l)
{
int fd = udp_bind(&l->addr);
if (fd == -1) return false;
if(fd == -1)
return false;
llarp::udp_listener* listener = new llarp::udp_listener(fd, l);
epoll_event ev;
ev.data.ptr = listener;
ev.events = EPOLLIN;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
ev.events = EPOLLIN;
if(epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1)
{
delete listener;
return false;
}
@ -119,16 +163,20 @@ struct llarp_epoll_loop : public llarp_ev_loop {
return true;
}
bool udp_close(llarp_udp_io* l)
bool
udp_close(llarp_udp_io* l)
{
auto listener = static_cast<llarp::udp_listener*>(l->impl);
if(!listener) return false;
auto listener = static_cast< llarp::udp_listener* >(l->impl);
if(!listener)
return false;
return close_ev(listener);
}
void stop() {
if (epollfd != -1) ::close(epollfd);
void
stop()
{
if(epollfd != -1)
::close(epollfd);
epollfd = -1;
}

@ -4,95 +4,226 @@
#include <llarp/mem.h>
#include <llarp/string.h>
struct llarp_xi_list_node {
struct llarp_xi_list_node
{
struct llarp_xi data;
struct llarp_xi_list_node *next;
};
struct llarp_xi_list {
struct llarp_alloc * mem;
struct llarp_xi_list
{
struct llarp_alloc *mem;
struct llarp_xi_list_node *root;
};
struct llarp_xi_list *llarp_xi_list_new(struct llarp_alloc * mem) {
struct llarp_xi_list *
llarp_xi_list_new(struct llarp_alloc *mem)
{
struct llarp_xi_list *l = mem->alloc(mem, sizeof(struct llarp_xi_list), 8);
if (l) {
l->mem = mem;
if(l)
{
l->mem = mem;
l->root = NULL;
}
return l;
}
void llarp_xi_list_free(struct llarp_xi_list **l) {
if (*l) {
struct llarp_alloc * mem = (*l)->mem;
struct llarp_xi_list_node *current = (*l)->root;
while (current) {
void
llarp_xi_list_free(struct llarp_xi_list *l)
{
if(l)
{
struct llarp_alloc *mem = l->mem;
struct llarp_xi_list_node *current = l->root;
while(current)
{
struct llarp_xi_list_node *tmp = current->next;
mem->free(mem, current);
current = tmp;
}
mem->free(mem, *l);
*l = NULL;
mem->free(mem, l);
}
}
static bool llarp_xi_iter_bencode(struct llarp_xi_list_iter *iter,
struct llarp_xi *xi) {
static bool
llarp_xi_iter_bencode(struct llarp_xi_list_iter *iter, struct llarp_xi *xi)
{
return llarp_xi_bencode(xi, iter->user);
}
bool llarp_xi_list_bencode(struct llarp_xi_list *l, llarp_buffer_t *buff) {
if (!bencode_start_list(buff)) return false;
struct llarp_xi_list_iter xi_itr = {.user = buff,
bool
llarp_xi_list_bencode(struct llarp_xi_list *l, llarp_buffer_t *buff)
{
if(!bencode_start_list(buff))
return false;
struct llarp_xi_list_iter xi_itr = {.user = buff,
.visit = &llarp_xi_iter_bencode};
llarp_xi_list_iterate(l, &xi_itr);
return bencode_end(buff);
}
void llarp_xi_list_iterate(struct llarp_xi_list *l,
struct llarp_xi_list_iter *iter) {
void
llarp_xi_list_iterate(struct llarp_xi_list *l, struct llarp_xi_list_iter *iter)
{
struct llarp_xi_list_node *current = l->root;
iter->list = l;
while (current) {
if (!iter->visit(iter, &current->data)) return;
iter->list = l;
while(current)
{
if(!iter->visit(iter, &current->data))
return;
current = current->next;
}
}
bool llarp_xi_bencode(struct llarp_xi *xi, llarp_buffer_t *buff) {
bool
llarp_xi_bencode(struct llarp_xi *xi, llarp_buffer_t *buff)
{
char addr_buff[128] = {0};
const char *addr;
if (!bencode_start_dict(buff)) return false;
if(!bencode_start_dict(buff))
return false;
/** address */
addr = inet_ntop(AF_INET6, &xi->address, addr_buff, sizeof(addr_buff));
if (!addr) return false;
if (!bencode_write_bytestring(buff, "a", 1)) return false;
if (!bencode_write_bytestring(buff, addr, strnlen(addr, sizeof(addr_buff))))
if(!addr)
return false;
if(!bencode_write_bytestring(buff, "a", 1))
return false;
if(!bencode_write_bytestring(buff, addr, strnlen(addr, sizeof(addr_buff))))
return false;
/** netmask */
addr = inet_ntop(AF_INET6, &xi->netmask, addr_buff, sizeof(addr_buff));
if (!addr) return false;
if (!bencode_write_bytestring(buff, "b", 1)) return false;
if (!bencode_write_bytestring(buff, addr, strnlen(addr, sizeof(addr_buff))))
if(!addr)
return false;
if(!bencode_write_bytestring(buff, "b", 1))
return false;
if(!bencode_write_bytestring(buff, addr, strnlen(addr, sizeof(addr_buff))))
return false;
/** public key */
if (!bencode_write_bytestring(buff, "k", 1)) return false;
if (!bencode_write_bytestring(buff, xi->pubkey, sizeof(llarp_pubkey_t)))
if(!bencode_write_bytestring(buff, "k", 1))
return false;
if(!bencode_write_bytestring(buff, xi->pubkey, sizeof(llarp_pubkey_t)))
return false;
/** version */
if (!bencode_write_version_entry(buff)) return false;
if(!bencode_write_version_entry(buff))
return false;
return bencode_end(buff);
}
bool llarp_xi_list_bdecode(struct llarp_xi_list * l, llarp_buffer_t * buff)
static bool
llarp_xi_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
{
if(!key)
return true;
struct llarp_xi *xi = r->user;
llarp_buffer_t strbuf;
int64_t v;
char tmp[128] = {0};
// address
if(llarp_buffer_eq(*key, "a"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz >= sizeof(tmp))
return false;
memcpy(tmp, strbuf.base, strbuf.sz);
return inet_pton(AF_INET6, tmp, xi->address.s6_addr) == 1;
}
if(llarp_buffer_eq(*key, "b"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz >= sizeof(tmp))
return false;
memcpy(tmp, strbuf.base, strbuf.sz);
return inet_pton(AF_INET6, tmp, xi->netmask.s6_addr) == 1;
}
if(llarp_buffer_eq(*key, "k"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != sizeof(llarp_pubkey_t))
return false;
memcpy(xi->pubkey, strbuf.base, sizeof(llarp_pubkey_t));
return true;
}
if(llarp_buffer_eq(*key, "v"))
{
if(!bdecode_read_integer(r->buffer, &v))
return false;
return v == LLARP_PROTO_VERSION;
}
return false;
}
bool
llarp_xi_bdecode(struct llarp_xi *xi, llarp_buffer_t *buf)
{
struct dict_reader r = {.user = xi, .on_key = &llarp_xi_decode_dict};
return bdecode_read_dict(buf, &r);
}
void
llarp_xi_list_pushback(struct llarp_xi_list *l, struct llarp_xi *xi)
{
struct llarp_xi_list_node *cur = l->root;
if(cur)
{
// go to the end of the list
while(cur->next)
cur = cur->next;
cur->next = l->mem->alloc(l->mem, sizeof(struct llarp_xi_list_node), 16);
cur = cur->next;
}
else
{
l->root = l->mem->alloc(l->mem, sizeof(struct llarp_xi_list_node), 16);
cur = l->root;
}
llarp_xi_copy(&cur->data, xi);
cur->next = 0;
}
void
llarp_xi_copy(struct llarp_xi *dst, struct llarp_xi *src)
{
memcpy(dst, src, sizeof(struct llarp_xi));
}
static bool
llarp_xi_list_decode_item(struct list_reader *r, bool more)
{
if(!more)
return true;
struct llarp_xi_list *l = r->user;
struct llarp_xi xi;
if(!llarp_xi_bdecode(&xi, r->buffer))
return false;
llarp_xi_list_pushback(l, &xi);
return true;
}
bool
llarp_xi_list_bdecode(struct llarp_xi_list *l, llarp_buffer_t *buff)
{
struct list_reader r = {
.user = l,
.on_item = &llarp_xi_list_decode_item,
};
return bdecode_read_list(buff, &r);
}

@ -3,39 +3,51 @@
#include <llarp/exit_route.h>
#include <llarp/string.h>
bool llarp_xr_bencode(struct llarp_xr* xr, llarp_buffer_t* buff) {
bool
llarp_xr_bencode(struct llarp_xr* xr, llarp_buffer_t* buff)
{
char addr_buff[128] = {0};
const char* addr;
if (!bencode_start_dict(buff)) return false;
if(!bencode_start_dict(buff))
return false;
/** gateway */
addr = inet_ntop(AF_INET6, &xr->gateway, addr_buff, sizeof(addr_buff));
if (!addr) return false;
if (!bencode_write_bytestring(buff, "a", 1)) return false;
if (!bencode_write_bytestring(buff, addr, strnlen(addr, sizeof(addr_buff))))
if(!addr)
return false;
if(!bencode_write_bytestring(buff, "a", 1))
return false;
if(!bencode_write_bytestring(buff, addr, strnlen(addr, sizeof(addr_buff))))
return false;
/** netmask */
addr = inet_ntop(AF_INET6, &xr->netmask, addr_buff, sizeof(addr_buff));
if (!addr) return false;
if (!bencode_write_bytestring(buff, "b", 1)) return false;
if (!bencode_write_bytestring(buff, addr, strnlen(addr, sizeof(addr_buff))))
if(!addr)
return false;
if(!bencode_write_bytestring(buff, "b", 1))
return false;
if(!bencode_write_bytestring(buff, addr, strnlen(addr, sizeof(addr_buff))))
return false;
/** source */
addr = inet_ntop(AF_INET6, &xr->source, addr_buff, sizeof(addr_buff));
if (!addr) return false;
if (!bencode_write_bytestring(buff, "c", 1)) return false;
if (!bencode_write_bytestring(buff, addr, strnlen(addr, sizeof(addr_buff))))
if(!addr)
return false;
if(!bencode_write_bytestring(buff, "c", 1))
return false;
if(!bencode_write_bytestring(buff, addr, strnlen(addr, sizeof(addr_buff))))
return false;
/** lifetime */
if (!bencode_write_bytestring(buff, "l", 1)) return false;
if (!bencode_write_uint64(buff, xr->lifetime)) return false;
if(!bencode_write_bytestring(buff, "l", 1))
return false;
if(!bencode_write_uint64(buff, xr->lifetime))
return false;
/** version */
if (!bencode_write_version_entry(buff)) return false;
if(!bencode_write_version_entry(buff))
return false;
/* end */
return bencode_end(buff);

@ -34,142 +34,203 @@
#include <stdexcept>
#include <string>
namespace ini {
struct Level {
Level() : parent(NULL), depth(0) {}
Level(Level *p) : parent(p), depth(0) {}
typedef std::list<std::pair<std::string, std::string> > value_map_t;
typedef std::map<std::string, Level> section_map_t;
typedef std::list<section_map_t::const_iterator> sections_t;
value_map_t values;
section_map_t sections;
sections_t ordered_sections;
Level *parent;
size_t depth;
static std::string default_value;
const std::string &operator[](const std::string &name) {
for (const auto &itr : values)
if (itr.first == name) return itr.second;
return default_value;
namespace ini
{
struct Level
{
Level() : parent(NULL), depth(0)
{
}
Level(Level *p) : parent(p), depth(0)
{
}
typedef std::list< std::pair< std::string, std::string > > value_map_t;
typedef std::map< std::string, Level > section_map_t;
typedef std::list< section_map_t::const_iterator > sections_t;
value_map_t values;
section_map_t sections;
sections_t ordered_sections;
Level *parent;
size_t depth;
static std::string default_value;
const std::string &operator[](const std::string &name)
{
for(const auto &itr : values)
if(itr.first == name)
return itr.second;
return default_value;
}
Level &
operator()(const std::string &name)
{
return sections[name];
}
};
class Parser
{
public:
Parser(const std::string &fname) : Parser(fname.c_str())
{
}
Parser(const char *fn);
Parser(std::istream &f) : f_(&f), ln_(0)
{
parse(top_);
}
Level &
top()
{
return top_;
}
void
dump(std::ostream &s)
{
dump(s, top(), "");
}
private:
void
dump(std::ostream &s, const Level &l, const std::string &sname);
void
parse(Level &l);
void
parseSLine(std::string &sname, size_t &depth);
void
err(const char *s);
private:
Level top_;
std::ifstream f0_;
std::istream *f_;
std::string line_;
size_t ln_;
};
inline void
Parser::err(const char *s)
{
char buf[256];
sprintf(buf, "%s on line #%ld", s, ln_);
throw std::runtime_error(buf);
}
Level &operator()(const std::string &name) { return sections[name]; }
};
class Parser {
public:
Parser(const std::string &fname) : Parser(fname.c_str()) {}
Parser(const char *fn);
Parser(std::istream &f) : f_(&f), ln_(0) { parse(top_); }
Level &top() { return top_; }
void dump(std::ostream &s) { dump(s, top(), ""); }
private:
void dump(std::ostream &s, const Level &l, const std::string &sname);
void parse(Level &l);
void parseSLine(std::string &sname, size_t &depth);
void err(const char *s);
private:
Level top_;
std::ifstream f0_;
std::istream *f_;
std::string line_;
size_t ln_;
};
inline void Parser::err(const char *s) {
char buf[256];
sprintf(buf, "%s on line #%ld", s, ln_);
throw std::runtime_error(buf);
}
inline std::string trim(const std::string &s) {
char p[] = " \t\r\n";
long sp = 0;
long ep = s.length() - 1;
for (; sp <= ep; ++sp)
if (!strchr(p, s[sp])) break;
for (; ep >= 0; --ep)
if (!strchr(p, s[ep])) break;
return s.substr(sp, ep - sp + 1);
}
inline Parser::Parser(const char *fn) : f0_(fn), f_(&f0_), ln_(0) {
if (!f0_) throw std::runtime_error(std::string("failed to open file: ") + fn);
parse(top_);
}
inline void Parser::parseSLine(std::string &sname, size_t &depth) {
depth = 0;
for (; depth < line_.length(); ++depth)
if (line_[depth] != '[') break;
sname = line_.substr(depth, line_.length() - 2 * depth);
}
inline void Parser::parse(Level &l) {
while (std::getline(*f_, line_)) {
++ln_;
if (line_[0] == '#' || line_[0] == ';') continue;
line_ = trim(line_);
if (line_.empty()) continue;
if (line_[0] == '[') {
size_t depth;
std::string sname;
parseSLine(sname, depth);
Level *lp = NULL;
Level *parent = &l;
if (depth > l.depth + 1) err("section with wrong depth");
if (l.depth == depth - 1)
lp = &l.sections[sname];
else {
lp = l.parent;
size_t n = l.depth - depth;
for (size_t i = 0; i < n; ++i) lp = lp->parent;
parent = lp;
lp = &lp->sections[sname];
inline std::string
trim(const std::string &s)
{
char p[] = " \t\r\n";
long sp = 0;
long ep = s.length() - 1;
for(; sp <= ep; ++sp)
if(!strchr(p, s[sp]))
break;
for(; ep >= 0; --ep)
if(!strchr(p, s[ep]))
break;
return s.substr(sp, ep - sp + 1);
}
inline Parser::Parser(const char *fn) : f0_(fn), f_(&f0_), ln_(0)
{
if(!f0_)
throw std::runtime_error(std::string("failed to open file: ") + fn);
parse(top_);
}
inline void
Parser::parseSLine(std::string &sname, size_t &depth)
{
depth = 0;
for(; depth < line_.length(); ++depth)
if(line_[depth] != '[')
break;
sname = line_.substr(depth, line_.length() - 2 * depth);
}
inline void
Parser::parse(Level &l)
{
while(std::getline(*f_, line_))
{
++ln_;
if(line_[0] == '#' || line_[0] == ';')
continue;
line_ = trim(line_);
if(line_.empty())
continue;
if(line_[0] == '[')
{
size_t depth;
std::string sname;
parseSLine(sname, depth);
Level *lp = NULL;
Level *parent = &l;
if(depth > l.depth + 1)
err("section with wrong depth");
if(l.depth == depth - 1)
lp = &l.sections[sname];
else
{
lp = l.parent;
size_t n = l.depth - depth;
for(size_t i = 0; i < n; ++i)
lp = lp->parent;
parent = lp;
lp = &lp->sections[sname];
}
if(lp->depth != 0)
err("duplicate section name on the same level");
if(!lp->parent)
{
lp->depth = depth;
lp->parent = parent;
}
parent->ordered_sections.push_back(parent->sections.find(sname));
parse(*lp);
}
if (lp->depth != 0) err("duplicate section name on the same level");
if (!lp->parent) {
lp->depth = depth;
lp->parent = parent;
else
{
size_t n = line_.find('=');
if(n == std::string::npos)
err("no '=' found");
auto p =
std::make_pair(trim(line_.substr(0, n)),
trim(line_.substr(n + 1, line_.length() - n - 1)));
l.values.push_back(p);
}
parent->ordered_sections.push_back(parent->sections.find(sname));
parse(*lp);
} else {
size_t n = line_.find('=');
if (n == std::string::npos) err("no '=' found");
auto p =
std::make_pair(trim(line_.substr(0, n)),
trim(line_.substr(n + 1, line_.length() - n - 1)));
l.values.push_back(p);
}
}
}
inline void Parser::dump(std::ostream &s, const Level &l,
const std::string &sname) {
if (!sname.empty()) s << '\n';
for (size_t i = 0; i < l.depth; ++i) s << '[';
if (!sname.empty()) s << sname;
for (size_t i = 0; i < l.depth; ++i) s << ']';
if (!sname.empty()) s << std::endl;
for (const auto &itr : l.values)
s << itr.first << '=' << itr.second << std::endl;
for (Level::sections_t::const_iterator it = l.ordered_sections.begin();
it != l.ordered_sections.end(); ++it) {
assert((*it)->second.depth == l.depth + 1);
dump(s, (*it)->second, (*it)->first);
inline void
Parser::dump(std::ostream &s, const Level &l, const std::string &sname)
{
if(!sname.empty())
s << '\n';
for(size_t i = 0; i < l.depth; ++i)
s << '[';
if(!sname.empty())
s << sname;
for(size_t i = 0; i < l.depth; ++i)
s << ']';
if(!sname.empty())
s << std::endl;
for(const auto &itr : l.values)
s << itr.first << '=' << itr.second << std::endl;
for(Level::sections_t::const_iterator it = l.ordered_sections.begin();
it != l.ordered_sections.end(); ++it)
{
assert((*it)->second.depth == l.depth + 1);
dump(s, (*it)->second, (*it)->first);
}
}
}
} // namespace ini

File diff suppressed because it is too large Load Diff

@ -1,12 +1,16 @@
#include <llarp/link.h>
bool llarp_link_initialized(struct llarp_link * link)
bool
llarp_link_initialized(struct llarp_link* link)
{
return link && link->impl && link->name && link->get_our_address && link->configure && link->start_link && link->stop_link && link->iter_sessions && link->try_establish && link->mark_session_active && link->free_impl;
return link && link->impl && link->name && link->get_our_address
&& link->configure && link->start_link && link->stop_link
&& link->iter_sessions && link->try_establish && link->mark_session_active
&& link->free_impl;
}
bool llarp_link_session_initialized(struct llarp_link_session * s)
bool
llarp_link_session_initialized(struct llarp_link_session* s)
{
return s && s->impl && s->sendto && s->timeout && s->close;
}

@ -2,23 +2,32 @@
#define LLARP_LINK_HANDLERS_HPP
#include <llarp/msg_handler.h>
namespace llarp {
namespace frame {
bool process_intro(struct llarp_frame_handler* h, struct llarp_link_session* s,
llarp_buffer_t msg);
bool process_relay_commit(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg);
bool process_relay_down(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg);
bool process_relay_up(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg);
bool process_relay_accept(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg);
bool process_relay_status(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg);
bool process_relay_exit(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg);
} // namespace frame
namespace llarp
{
namespace frame
{
bool
process_intro(struct llarp_frame_handler* h, struct llarp_link_session* s,
llarp_buffer_t msg);
bool
process_relay_commit(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg);
bool
process_relay_down(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg);
bool
process_relay_up(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg);
bool
process_relay_accept(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg);
bool
process_relay_status(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg);
bool
process_relay_exit(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg);
} // namespace frame
} // namespace llarp
#endif

@ -1,10 +1,14 @@
#include "link_handlers.hpp"
namespace llarp {
namespace frame {
bool process_intro(struct llarp_frame_handler* h, struct llarp_link_session* s,
llarp_buffer_t msg) {
return false;
}
} // namespace frame
namespace llarp
{
namespace frame
{
bool
process_intro(struct llarp_frame_handler* h, struct llarp_link_session* s,
llarp_buffer_t msg)
{
return false;
}
} // namespace frame
} // namespace llarp

@ -1,10 +1,14 @@
#include "link_handlers.hpp"
namespace llarp {
namespace frame {
bool process_relay_down(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg) {
return false;
}
} // namespace frame
namespace llarp
{
namespace frame
{
bool
process_relay_down(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg)
{
return false;
}
} // namespace frame
} // namespace llarp

@ -1,10 +1,14 @@
#include "link_handlers.hpp"
namespace llarp {
namespace frame {
bool process_relay_up(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg) {
return false;
}
} // namespace frame
namespace llarp
{
namespace frame
{
bool
process_relay_up(struct llarp_frame_handler* h,
struct llarp_link_session* s, llarp_buffer_t msg)
{
return false;
}
} // namespace frame
} // namespace llarp

@ -1,25 +1,32 @@
#include <llarp/logic.h>
#include <llarp/mem.h>
struct llarp_logic {
struct llarp_alloc * mem;
struct llarp_logic
{
struct llarp_alloc* mem;
struct llarp_threadpool* thread;
struct llarp_timer_context* timer;
};
struct llarp_logic* llarp_init_logic(struct llarp_alloc * mem) {
struct llarp_logic*
llarp_init_logic(struct llarp_alloc* mem)
{
struct llarp_logic* logic = mem->alloc(mem, sizeof(struct llarp_logic), 8);
if (logic) {
logic->mem = mem;
if(logic)
{
logic->mem = mem;
logic->thread = llarp_init_threadpool(1, "llarp-logic");
logic->timer = llarp_init_timer();
logic->timer = llarp_init_timer();
}
return logic;
};
void llarp_free_logic(struct llarp_logic** logic) {
if (*logic) {
struct llarp_alloc * mem = (*logic)->mem;
void
llarp_free_logic(struct llarp_logic** logic)
{
if(*logic)
{
struct llarp_alloc* mem = (*logic)->mem;
llarp_free_threadpool(&(*logic)->thread);
llarp_free_timer(&(*logic)->timer);
mem->free(mem, *logic);
@ -27,28 +34,34 @@ void llarp_free_logic(struct llarp_logic** logic) {
}
}
void llarp_logic_stop(struct llarp_logic* logic) {
void
llarp_logic_stop(struct llarp_logic* logic)
{
llarp_timer_stop(logic->timer);
llarp_threadpool_stop(logic->thread);
llarp_threadpool_join(logic->thread);
}
void llarp_logic_mainloop(struct llarp_logic* logic) {
void
llarp_logic_mainloop(struct llarp_logic* logic)
{
llarp_timer_run(logic->timer, logic->thread);
}
void llarp_logic_queue_job(struct llarp_logic * logic, struct llarp_thread_job job)
void
llarp_logic_queue_job(struct llarp_logic* logic, struct llarp_thread_job job)
{
llarp_threadpool_queue_job(logic->thread, job);
}
uint32_t llarp_logic_call_later(struct llarp_logic* logic, struct llarp_timeout_job job)
uint32_t
llarp_logic_call_later(struct llarp_logic* logic, struct llarp_timeout_job job)
{
return llarp_timer_call_later(logic->timer, job);
}
void llarp_logic_cancel_call(struct llarp_logic * logic, uint32_t id)
void
llarp_logic_cancel_call(struct llarp_logic* logic, uint32_t id)
{
llarp_timer_cancel(logic->timer, id);
}

@ -1,10 +1,13 @@
#define NO_JEMALLOC
#include <llarp/mem.h>
#include <cstdlib>
namespace llarp
{
void Zero(void * ptr, size_t sz)
void
Zero(void *ptr, size_t sz)
{
uint8_t * p = (uint8_t *) ptr;
uint8_t *p = (uint8_t *)ptr;
while(sz--)
{
*p = 0;
@ -15,21 +18,23 @@ namespace llarp
extern "C" {
void llarp_mem_slab(struct llarp_alloc * mem, uint32_t * buf, size_t sz)
{
// not implemented
abort();
}
void
llarp_mem_slab(struct llarp_alloc *mem, uint32_t *buf, size_t sz)
{
// not implemented
abort();
}
bool llarp_eq(const void * a, const void * b, size_t sz)
bool
llarp_eq(const void *a, const void *b, size_t sz)
{
bool result = true;
const uint8_t *a_ptr = (const uint8_t *)a;
const uint8_t *b_ptr = (const uint8_t *)b;
while(sz--)
{
bool result = true;
const uint8_t * a_ptr = (const uint8_t *) a;
const uint8_t * b_ptr = (const uint8_t *) b;
while(sz--)
{
result &= a_ptr[sz] == b_ptr[sz];
}
return result;
result &= a_ptr[sz] == b_ptr[sz];
}
return result;
}
}

@ -1,26 +1,32 @@
#ifndef LLARP_MEM_HPP
#define LLARP_MEM_HPP
#include <llarp/mem.h>
namespace llarp {
template <typename T>
static constexpr size_t alignment() {
size_t idx = 0;
size_t sz = sizeof(T);
while (sz) {
++idx;
sz >>= 1;
namespace llarp
{
template < typename T >
static constexpr size_t
alignment()
{
size_t idx = 0;
size_t sz = sizeof(T);
while(sz)
{
++idx;
sz >>= 1;
}
return 1 << idx;
}
return 1 << idx;
}
template <typename T>
static T *Alloc(llarp_alloc *mem) {
return static_cast<T *>(mem->alloc(mem, sizeof(T), alignment<T>()));
}
template < typename T >
static T *
Alloc(llarp_alloc *mem)
{
return static_cast< T * >(mem->alloc(mem, sizeof(T), alignment< T >()));
}
void Zero(void * ptr, size_t sz);
} // namespace llarp
void
Zero(void *ptr, size_t sz);
} // namespace llarp
#endif

@ -1,21 +0,0 @@
#include <jemalloc/jemalloc.h>
#include <llarp/mem.h>
namespace llarp {
static void *jem_malloc(struct llarp_alloc * mem, size_t sz, size_t align) {
(void) mem;
return mallocx(sz, MALLOCX_ALIGN(align));
}
static void jem_free(struct llarp_alloc * mem, void *ptr) {
(void) mem;
if (ptr) free(ptr);
}
} // namespace llarp
extern "C" {
void llarp_mem_jemalloc(struct llarp_alloc * mem) {
mem->alloc = llarp::jem_malloc;
mem->free = llarp::jem_free;
}
}

@ -1,28 +1,39 @@
#define NO_JEMALLOC
#include <llarp/mem.h>
#include <cstdlib>
#include <cstring>
namespace llarp {
void *std_malloc(struct llarp_alloc *mem, size_t sz, size_t align) {
(void)mem;
(void)align;
void *ptr = malloc(sz);
if (ptr) {
std::memset(ptr, 0, sz);
return ptr;
namespace llarp
{
void *
std_malloc(struct llarp_alloc *mem, size_t sz, size_t align)
{
(void)mem;
(void)align;
void *ptr = malloc(sz);
if(ptr)
{
std::memset(ptr, 0, sz);
return ptr;
}
abort();
}
abort();
}
void std_free(struct llarp_alloc * mem, void *ptr) {
(void) mem;
if (ptr) free(ptr);
}
void
std_free(struct llarp_alloc *mem, void *ptr)
{
(void)mem;
if(ptr)
free(ptr);
}
} // namespace llarp
extern "C" {
void llarp_mem_stdlib(struct llarp_alloc * mem) {
void
llarp_mem_stdlib(struct llarp_alloc *mem)
{
mem->alloc = llarp::std_malloc;
mem->free = llarp::std_free;
mem->free = llarp::std_free;
}
}

@ -1,46 +1,33 @@
#include <llarp/msg_handler.h>
#include "link_handlers.hpp"
#include "router.hpp"
namespace llarp {
struct llarp_frame_handler introduce_handler = {
.paths = nullptr,
.parent = nullptr,
.process = &llarp::frame::process_intro};
struct llarp_frame_handler lrdm_handler = {
.paths = nullptr,
.parent = nullptr,
.process = &llarp::frame::process_relay_down};
struct llarp_frame_handler lrum_handler = {
.paths = nullptr,
.parent = nullptr,
.process = &llarp::frame::process_relay_up};
static struct llarp_frame_handler* find_frame_handler(struct llarp_router* r,
const char ch) {
struct llarp_frame_handler* handler = nullptr;
switch (ch) {
case 'i':
handler = &introduce_handler;
}
if (handler) {
handler->paths = r->paths;
handler->parent = &r->muxer;
namespace llarp
{
static struct llarp_frame_handler*
find_frame_handler(struct llarp_router* r, const char ch)
{
auto itr = r->frame_handlers.find(ch);
if(itr != r->frame_handlers.end())
{
auto handler = &itr->second;
handler->paths = r->paths;
handler->parent = &r->muxer;
}
return nullptr;
}
return handler;
}
static struct llarp_msg_handler* find_msg_handler(struct llarp_router* r,
const char ch) {
return nullptr;
}
static struct llarp_msg_handler*
find_msg_handler(struct llarp_router* r, const char ch)
{
return nullptr;
}
} // namespace llarp
extern "C" {
void llarp_msg_muxer_init(struct llarp_msg_muxer* muxer) {
muxer->link_handler_for = &llarp::find_frame_handler;
void
llarp_msg_muxer_init(struct llarp_msg_muxer* muxer)
{
muxer->link_handler_for = &llarp::find_frame_handler;
muxer->routing_handler_for = &llarp::find_msg_handler;
}
}

@ -1,35 +1,75 @@
#include <llarp/net.h>
#include "net.hpp"
#include "str.hpp"
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <cstdio>
bool
operator==(const sockaddr& a, const sockaddr& b)
{
socklen_t sz = sizeof(a.sa_data);
switch(a.sa_family)
{
case AF_INET:
sz = sizeof(sockaddr_in);
break;
case AF_INET6:
sz = sizeof(sockaddr_in6);
break;
case AF_PACKET:
sz = sizeof(sockaddr_ll);
break;
default:
break;
}
return a.sa_family == b.sa_family && memcmp(a.sa_data, b.sa_data, sz) == 0;
}
bool
operator<(const sockaddr_in6& a, const sockaddr_in6& b)
{
return memcmp(&a, &b, sizeof(sockaddr_in6)) < 0;
}
bool
operator<(const in6_addr& a, const in6_addr& b)
{
return memcmp(&a, &b, sizeof(in6_addr)) < 0;
}
extern "C" {
bool llarp_getifaddr(const char * ifname, int af, struct sockaddr* addr) {
bool
llarp_getifaddr(const char* ifname, int af, struct sockaddr* addr)
{
ifaddrs* ifa = nullptr;
bool found = false;
bool found = false;
socklen_t sl = sizeof(sockaddr_in6);
if (af == AF_INET) sl = sizeof(sockaddr_in);
if (af == AF_PACKET) sl = sizeof(sockaddr_ll);
if(af == AF_INET)
sl = sizeof(sockaddr_in);
if(af == AF_PACKET)
sl = sizeof(sockaddr_ll);
if (getifaddrs(&ifa) == -1) return false;
if(getifaddrs(&ifa) == -1)
return false;
ifaddrs* i = ifa;
while (i) {
if (i->ifa_addr)
while(i)
{
if(i->ifa_addr)
{
if (llarp::StrEq(i->ifa_name, ifname) && i->ifa_addr->sa_family == af) {
if(llarp::StrEq(i->ifa_name, ifname) && i->ifa_addr->sa_family == af)
{
memcpy(addr, i->ifa_addr, sl);
addr->sa_family = af;
found = true;
found = true;
break;
}
}
i = i->ifa_next;
}
if (ifa) freeifaddrs(ifa);
if(ifa)
freeifaddrs(ifa);
return found;
}
}

@ -1,105 +1,141 @@
#ifndef LLARP_NET_HPP
#define LLARP_NET_HPP
#include <llarp/address_info.h>
#include <llarp/net.h>
#include <string>
bool operator == (const sockaddr& a, const sockaddr& b)
{
socklen_t sz = sizeof(a.sa_data);
switch(a.sa_family)
{
case AF_INET:
sz = sizeof(sockaddr_in);
break;
case AF_INET6:
sz = sizeof(sockaddr_in6);
break;
case AF_PACKET:
sz = sizeof(sockaddr_ll);
break;
default:
break;
}
return a.sa_family == b.sa_family && memcmp(a.sa_data, b.sa_data, sz) == 0;
}
bool
operator==(const sockaddr& a, const sockaddr& b);
bool operator < (const sockaddr_in6 & a, const sockaddr_in6 & b)
{
return memcmp(&a, &b, sizeof(sockaddr_in6)) < 0;
}
bool
operator<(const sockaddr_in6& a, const sockaddr_in6& b);
bool operator < (const in6_addr & a, const in6_addr b)
{
return memcmp(&a, &b, sizeof(in6_addr)) < 0;
}
bool
operator<(const in6_addr& a, const in6_addr& b);
namespace llarp
{
struct Addr
{
int af = AF_INET;
in6_addr addr = {0};
int af = AF_INET;
in6_addr addr = {};
uint16_t port = 0;
sockaddr saddr;
Addr() {};
Addr(const Addr & other) {
af = other.af;
sockaddr _addr = {0, {0}};
~Addr(){};
Addr(){};
Addr(const Addr& other)
{
af = other.af;
port = other.port;
memcpy(addr.s6_addr, other.addr.s6_addr, 16);
memcpy(&saddr, &other.saddr, sizeof(sockaddr));
memcpy(addr.s6_addr, other.addr.s6_addr, sizeof(addr.s6_addr));
CopyInto(_addr);
}
Addr(const llarp_ai & other) {
Addr(const llarp_ai& other)
{
af = AF_INET6;
memcpy(addr.s6_addr, other.ip.s6_addr, 16);
port = other.port;
saddr.sa_family = af;
memcpy(((sockaddr_in6 *)&saddr)->sin6_addr.s6_addr, addr.s6_addr, 16);
((sockaddr_in6 *)&saddr)->sin6_port = htons(port);
CopyInto(_addr);
}
Addr(const sockaddr & other) {
uint8_t * addrptr = addr.s6_addr;
Addr(const sockaddr& other)
{
uint8_t* addrptr = addr.s6_addr;
switch(other.sa_family)
{
case AF_INET:
// SIIT
af = AF_INET;
memcpy(12+addrptr, &((const sockaddr_in*)(&other))->sin_addr, 4);
addrptr[11] = 0xff;
addrptr[10] = 0xff;
port = ntohs(((sockaddr_in*)(&other))->sin_port);
break;
case AF_INET6:
af = AF_INET6;
memcpy(addrptr, &((const sockaddr_in6*)(&other))->sin6_addr, 16);
port = ntohs(((sockaddr_in6*)(&other))->sin6_port);
break;
// TODO : sockaddr_ll
default:
break;
case AF_INET:
// SIIT
af = AF_INET;
memcpy(12 + addrptr, &((const sockaddr_in*)(&other))->sin_addr,
sizeof(in_addr));
addrptr[11] = 0xff;
addrptr[10] = 0xff;
port = ntohs(((sockaddr_in*)(&other))->sin_port);
break;
case AF_INET6:
af = AF_INET6;
memcpy(addrptr, &((const sockaddr_in6*)(&other))->sin6_addr,
sizeof(addr.s6_addr));
port = ntohs(((sockaddr_in6*)(&other))->sin6_port);
break;
// TODO : sockaddr_ll
default:
break;
}
saddr.sa_family = af;
memcpy(saddr.sa_data, other.sa_data, sizeof(saddr.sa_data));
CopyInto(_addr);
}
void CopyInto(sockaddr & other) const
std::string
to_string() const
{
memcpy(other.sa_data, saddr.sa_data, sizeof(saddr.sa_data));
other.sa_family = af;
std::string str;
char tmp[128];
socklen_t sz;
const void* ptr = nullptr;
if(af == AF_INET)
{
sz = sizeof(sockaddr_in);
ptr = &addr.s6_addr[12];
}
if(af == AF_INET6)
{
str += "[";
sz = sizeof(sockaddr_in6);
ptr = &addr.s6_addr[0];
}
if(inet_ntop(af, ptr, tmp, sz))
{
str += tmp;
if(af == AF_INET6)
str += "]";
}
return str + ":" + std::to_string(port);
}
operator const sockaddr * () const
operator const sockaddr*() const
{
return &saddr;
return &_addr;
}
bool operator < (const Addr & other) const
void
CopyInto(sockaddr& other) const
{
void *dst, *src;
in_port_t* ptr;
size_t slen;
switch(af)
{
case AF_INET:
dst = (void*)&((const sockaddr_in*)&other)->sin_addr;
src = (void*)&addr.s6_addr[12];
ptr = &((sockaddr_in*)&other)->sin_port;
slen = sizeof(in_addr);
break;
case AF_INET6:
dst = (void*)&((const sockaddr_in6*)&other)->sin6_addr;
src = (void*)&addr.s6_addr[0];
ptr = &((sockaddr_in6*)&other)->sin6_port;
slen = sizeof(in6_addr);
break;
default:
return;
}
memcpy(ptr, src, slen);
*ptr = htons(port);
other.sa_family = af;
}
bool
operator<(const Addr& other) const
{
return af < other.af && addr < other.addr && port < other.port;
}
};
}

@ -7,15 +7,18 @@
static const char skiplist_subdirs[] = "0123456789ABCDEF";
struct llarp_nodedb {
struct llarp_nodedb
{
llarp_nodedb(llarp_alloc *m, llarp_crypto *c) : mem(m), crypto(c)
{
}
llarp_nodedb(llarp_alloc * m, llarp_crypto * c) : mem(m), crypto(c) {}
llarp_alloc * mem;
llarp_crypto * crypto;
std::map<llarp::pubkey, llarp_rc *> entries;
llarp_alloc *mem;
llarp_crypto *crypto;
std::map< llarp::pubkey, llarp_rc * > entries;
void Clear()
void
Clear()
{
auto itr = entries.begin();
while(itr != entries.end())
@ -24,37 +27,49 @@ struct llarp_nodedb {
itr = entries.erase(itr);
}
}
ssize_t Load(const fs::path &path) {
ssize_t
Load(const fs::path &path)
{
std::error_code ec;
if (!fs::exists(path, ec)) {
if(!fs::exists(path, ec))
{
return -1;
}
ssize_t loaded = 0;
for (const char &ch : skiplist_subdirs) {
for(const char &ch : skiplist_subdirs)
{
fs::path sub = path / std::string(ch, 1);
for (auto &f : fs::directory_iterator(sub)) {
for(auto &f : fs::directory_iterator(sub))
{
ssize_t l = loadSubdir(f);
if (l > 0) loaded += l;
if(l > 0)
loaded += l;
}
}
return loaded;
}
bool loadfile(const fs::path &fpath) {
bool
loadfile(const fs::path &fpath)
{
llarp_buffer_t buff;
FILE *f = fopen(fpath.c_str(), "rb");
if (!f) return false;
if (!llarp_buffer_readfile(&buff, f, mem)) {
if(!f)
return false;
if(!llarp_buffer_readfile(&buff, f, mem))
{
fclose(f);
return false;
}
fclose(f);
llarp_rc *rc = llarp::Alloc<llarp_rc>(mem);
llarp_rc *rc = llarp::Alloc< llarp_rc >(mem);
llarp::Zero(rc, sizeof(llarp_rc));
if (llarp_rc_bdecode(mem, rc, &buff)) {
if (llarp_rc_verify_sig(crypto, rc)) {
if(llarp_rc_bdecode(mem, rc, &buff))
{
if(llarp_rc_verify_sig(crypto, rc))
{
llarp::pubkey pk;
memcpy(pk.data(), rc->pubkey, pk.size());
entries[pk] = rc;
@ -66,10 +81,14 @@ struct llarp_nodedb {
return false;
}
ssize_t loadSubdir(const fs::path &dir) {
ssize_t
loadSubdir(const fs::path &dir)
{
ssize_t sz = 0;
for (auto &path : fs::directory_iterator(dir)) {
if (loadfile(path)) sz++;
for(auto &path : fs::directory_iterator(dir))
{
if(loadfile(path))
sz++;
}
return sz;
}
@ -77,14 +96,20 @@ struct llarp_nodedb {
extern "C" {
struct llarp_nodedb *llarp_nodedb_new(struct llarp_alloc * mem, struct llarp_crypto * crypto) {
void * ptr = mem->alloc(mem, sizeof(llarp_nodedb), llarp::alignment<llarp_nodedb>());
if(!ptr) return nullptr;
return new (ptr) llarp_nodedb(mem, crypto);
struct llarp_nodedb *
llarp_nodedb_new(struct llarp_alloc *mem, struct llarp_crypto *crypto)
{
void *ptr =
mem->alloc(mem, sizeof(llarp_nodedb), llarp::alignment< llarp_nodedb >());
if(!ptr)
return nullptr;
return new(ptr) llarp_nodedb(mem, crypto);
}
void llarp_nodedb_free(struct llarp_nodedb **n) {
if (*n)
void
llarp_nodedb_free(struct llarp_nodedb **n)
{
if(*n)
{
struct llarp_alloc *mem = (*n)->mem;
(*n)->Clear();
@ -94,24 +119,33 @@ void llarp_nodedb_free(struct llarp_nodedb **n) {
*n = nullptr;
}
bool llarp_nodedb_ensure_dir(const char *dir) {
bool
llarp_nodedb_ensure_dir(const char *dir)
{
fs::path path(dir);
std::error_code ec;
if (!fs::exists(dir, ec)) fs::create_directories(path, ec);
if(!fs::exists(dir, ec))
fs::create_directories(path, ec);
if (ec) return false;
if(ec)
return false;
if (!fs::is_directory(path)) return false;
if(!fs::is_directory(path))
return false;
for (const char &ch : skiplist_subdirs) {
for(const char &ch : skiplist_subdirs)
{
fs::path sub = path / std::string(ch, 1);
fs::create_directory(sub, ec);
if (ec) return false;
if(ec)
return false;
}
return true;
}
ssize_t llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir) {
ssize_t
llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir)
{
return n->Load(dir);
}
}

@ -1,42 +1,97 @@
#include "router.hpp"
#include <llarp/ibfq.h>
#include <llarp/dtls.h>
#include <llarp/ibfq.h>
#include <llarp/iwp.h>
#include <llarp/link.h>
#include <llarp/proto.h>
#include <llarp/router.h>
#include "str.hpp"
#include "buffer.hpp"
#include "net.hpp"
#include "str.hpp"
#include <fstream>
namespace llarp {
void router_iter_config(llarp_config_iterator *iter, const char *section,
const char *key, const char *val);
namespace llarp
{
void
router_iter_config(llarp_config_iterator *iter, const char *section,
const char *key, const char *val);
} // namespace llarp
llarp_router::llarp_router(struct llarp_alloc *m) : ready(false), mem(m) { llarp_msg_muxer_init(&muxer); }
llarp_router::~llarp_router() {}
llarp_router::llarp_router(struct llarp_alloc *m) : ready(false), mem(m)
{
llarp_msg_muxer_init(&muxer);
}
void llarp_router::AddLink(struct llarp_link *link) {
llarp::router_links *head = &links;
while (head->next && head->link) head = head->next;
llarp_router::~llarp_router()
{
}
if (head->link)
void
llarp_router::try_connect(fs::path rcfile)
{
byte_t tmp[MAX_RC_SIZE];
llarp_rc remote = {0};
llarp_buffer_t buf;
llarp::StackBuffer< decltype(tmp) >(buf, tmp);
// open file
{
std::ifstream f(rcfile, std::ios::binary);
if(f.is_open())
{
f.seekg(0, std::ios::end);
size_t sz = f.tellg();
f.seekg(0, std::ios::beg);
if(sz <= buf.sz)
{
f.read((char *)buf.base, sz);
}
else
printf("file too large\n");
}
else
{
return;
}
}
if(llarp_rc_bdecode(mem, &remote, &buf))
{
void * ptr = mem->alloc(mem, sizeof(llarp::router_links), 8);
head->next = new (ptr) llarp::router_links{link, nullptr};
if(llarp_rc_verify_sig(&crypto, &remote))
{
printf("signature valided\n");
if(llarp_router_try_connect(this, &remote))
{
printf("session attempt started\n");
}
else
{
printf("session already pending\n");
}
}
else
printf("failed to verify signature\n");
}
else
head->link = link;
printf("failed to decode buffer, read=%ld\n", buf.cur - buf.base);
llarp_rc_free(&remote);
}
void
llarp_router::AddLink(struct llarp_link *link)
{
links.push_back(link);
ready = true;
}
bool llarp_router::Ready() { return ready; }
bool
llarp_router::Ready()
{
return ready;
}
bool llarp_router::EnsureIdentity()
bool
llarp_router::EnsureIdentity()
{
std::error_code ec;
if(!fs::exists(ident_keyfile, ec))
@ -45,19 +100,20 @@ bool llarp_router::EnsureIdentity()
std::ofstream f(ident_keyfile, std::ios::binary);
if(f.is_open())
{
f.write((char*)identity, sizeof(identity));
f.write((char *)identity, sizeof(identity));
}
}
std::ifstream f(ident_keyfile, std::ios::binary);
if(f.is_open())
{
f.read((char*)identity, sizeof(identity));
f.read((char *)identity, sizeof(identity));
return true;
}
return false;
}
bool llarp_router::SaveRC()
bool
llarp_router::SaveRC()
{
printf("verify rc signature... ");
if(!llarp_rc_verify_sig(&crypto, &rc))
@ -66,107 +122,204 @@ bool llarp_router::SaveRC()
return false;
}
printf(" OK.\n");
uint8_t tmp[MAX_RC_SIZE];
auto buf = llarp::StackBuffer<decltype(tmp)>(tmp);
byte_t tmp[MAX_RC_SIZE];
llarp_buffer_t buf;
llarp::StackBuffer< decltype(tmp) >(buf, tmp);
if(llarp_rc_bencode(&rc, &buf))
{
std::ofstream f(our_rc_file, std::ios::binary);
std::ofstream f(our_rc_file);
if(f.is_open())
{
f.write(buf.base, buf.cur - buf.base);
f.write((char *)buf.base, buf.cur - buf.base);
return true;
}
}
return false;
}
void llarp_router::ForEachLink(std::function<void(llarp_link *)> visitor) {
llarp::router_links *cur = &links;
do {
if (cur->link) visitor(cur->link);
cur = cur->next;
} while (cur);
void
llarp_router::Close()
{
for(auto link : links)
{
link->stop_link(link);
}
}
void
llarp_router::on_try_connect_result(llarp_link_establish_job *job)
{
printf("on_try_connect_result\n");
llarp_router *self = static_cast< llarp_router * >(job->user);
if(job->session)
printf("session made\n");
else
printf("session not made\n");
self->mem->free(self->mem, job);
}
void
llarp_router::Run()
{
// zero out router contact
llarp::Zero(&rc, sizeof(llarp_rc));
// fill our address list
rc.addrs = llarp_ai_list_new(mem);
llarp_ai addr;
for(auto link : links)
{
link->get_our_address(link, &addr);
llarp_ai_list_pushback(rc.addrs, &addr);
};
// set public key
memcpy(rc.pubkey, pubkey(), 32);
{
// sign router contact
byte_t rcbuf[MAX_RC_SIZE];
llarp_buffer_t signbuf;
llarp::StackBuffer< decltype(rcbuf) >(signbuf, rcbuf);
// encode
if(!llarp_rc_bencode(&rc, &signbuf))
return;
// sign
signbuf.sz = signbuf.cur - signbuf.base;
printf("sign %ld bytes\n", signbuf.sz);
crypto.sign(rc.signature, identity, signbuf);
}
if(!SaveRC())
return;
printf("saved router contact\n");
// start links
for(auto link : links)
{
int result = link->start_link(link, logic);
if(result == -1)
printf("link %s failed to start\n", link->name());
else
printf("link %s started\n", link->name());
}
printf("connecting to routers\n");
for(const auto &itr : connect)
{
printf("try connecting to %s\n", itr.first.c_str());
try_connect(itr.second);
}
}
void llarp_router::Close() {
ForEachLink([](llarp_link *l) { l->stop_link(l); });
bool
llarp_router::iter_try_connect(llarp_router_link_iter *iter,
llarp_router *router, llarp_link *link)
{
if(!link)
return false;
auto mem = router->mem;
llarp_link_establish_job *job = llarp::Alloc< llarp_link_establish_job >(mem);
if(!job)
return false;
llarp_ai *ai = static_cast< llarp_ai * >(iter->user);
llarp_ai_copy(&job->ai, ai);
job->timeout = 5000;
job->result = &llarp_router::on_try_connect_result;
// give router as user pointer
job->user = router;
printf("try_establish\n");
link->try_establish(link, job);
printf("return true\n");
return true;
}
extern "C" {
struct llarp_router *llarp_init_router(struct llarp_alloc * mem, struct llarp_threadpool *tp, struct llarp_ev_loop * netloop, struct llarp_logic * logic) {
void * ptr = mem->alloc(mem, sizeof(llarp_router), 16);
if(!ptr) return nullptr;
llarp_router *router = new (ptr) llarp_router(mem);
struct llarp_router *
llarp_init_router(struct llarp_alloc *mem, struct llarp_threadpool *tp,
struct llarp_ev_loop *netloop, struct llarp_logic *logic)
{
llarp_router *router = new llarp_router(mem);
if(router)
{
router->netloop = netloop;
router->tp = tp;
router->logic = logic;
router->tp = tp;
router->logic = logic;
llarp_crypto_libsodium_init(&router->crypto);
llarp_msg_muxer_init(&router->muxer);
}
return router;
}
bool llarp_configure_router(struct llarp_router *router,
struct llarp_config *conf) {
bool
llarp_configure_router(struct llarp_router *router, struct llarp_config *conf)
{
llarp_config_iterator iter;
iter.user = router;
iter.user = router;
iter.visit = llarp::router_iter_config;
llarp_config_iter(conf, &iter);
if(!router->Ready()) return false;
if(!router->Ready())
{
printf("router not ready\n");
return false;
}
return router->EnsureIdentity();
}
void llarp_run_router(struct llarp_router *router) {
void
llarp_run_router(struct llarp_router *router)
{
router->Run();
}
// zero out router contact
llarp::Zero(&router->rc, sizeof(llarp_rc));
// fill our address list
router->rc.addrs = llarp_ai_list_new(router->mem);
router->ForEachLink([router](llarp_link *link) {
llarp_ai addr;
link->get_our_address(link, &addr);
llarp_ai_list_pushback(router->rc.addrs, addr);
});
// set public key
memcpy(router->rc.pubkey, router->pubkey(), 32);
// sign router contact
char buf[MAX_RC_SIZE];
auto signbuf = llarp::StackBuffer<decltype(buf)>(buf);
// encode
if(llarp_rc_bencode(&router->rc, &signbuf))
bool
llarp_router_try_connect(struct llarp_router *router, struct llarp_rc *remote)
{
// try first address only
llarp_ai addr;
if(llarp_ai_list_index(remote->addrs, 0, &addr))
{
// sign
signbuf.sz = signbuf.cur - signbuf.base;
router->crypto.sign(router->rc.signature, router->identity, signbuf);
if(router->SaveRC())
{
printf("saved router contact\n");
llarp_logic * logic = router->logic;
router->ForEachLink([logic](llarp_link *link) {
int result = link->start_link(link, logic);
if (result == -1) printf("link %s failed to start\n", link->name());
});
return;
}
printf("try connect to first address\n");
llarp_router_iterate_links(router,
{&addr, &llarp_router::iter_try_connect});
return true;
}
printf("failed to generate rc\n");
else
printf("router has no addresses?\n");
return false;
}
void llarp_stop_router(struct llarp_router *router) {
void
llarp_stop_router(struct llarp_router *router)
{
if(router)
router->Close();
}
void llarp_free_router(struct llarp_router **router) {
if (*router) {
struct llarp_alloc * mem = (*router)->mem;
(*router)->ForEachLink([mem](llarp_link *link) { link->free_impl(link); mem->free(mem, link); });
(*router)->~llarp_router();
mem->free(mem, *router);
void
llarp_router_iterate_links(struct llarp_router *router,
struct llarp_router_link_iter i)
{
for(auto link : router->links)
if(!i.visit(&i, router, link))
return;
}
void
llarp_free_router(struct llarp_router **router)
{
if(*router)
{
for(auto &link : (*router)->links)
{
link->free_impl(link);
delete link;
}
delete *router;
}
*router = nullptr;
}
@ -174,72 +327,75 @@ void llarp_free_router(struct llarp_router **router) {
namespace llarp
{
void router_iter_config(llarp_config_iterator *iter, const char *section,
const char *key, const char *val)
{
llarp_router *self = static_cast<llarp_router *>(iter->user);
int af;
uint16_t proto;
if (StrEq(val, "eth"))
{
af = AF_PACKET;
proto = LLARP_ETH_PROTO;
}
else
{
af = AF_INET;
proto = std::atoi(val);
}
struct llarp_link *link = nullptr;
if (StrEq(section, "iwp-links"))
{
link = llarp::Alloc<llarp_link>(self->mem);
llarp::Zero(link, sizeof(*link));
llarp_iwp_args args = {
.mem = self->mem,
.crypto = &self->crypto,
.logic = self->logic,
.cryptoworker = self->tp,
.keyfile = self->transport_keyfile.c_str(),
};
iwp_link_init(link, args, &self->muxer);
}
else if (StrEq(section, "iwp-connect"))
void
router_iter_config(llarp_config_iterator *iter, const char *section,
const char *key, const char *val)
{
std::error_code ec;
if(fs::exists(val, ec))
self->connect.try_emplace(key, val);
llarp_router *self = static_cast< llarp_router * >(iter->user);
int af;
uint16_t proto;
if(StrEq(val, "eth"))
{
af = AF_PACKET;
proto = LLARP_ETH_PROTO;
}
else
printf("cannot read %s\n", val);
return;
}
else if (StrEq(section, "router"))
{
if(StrEq(key, "contact-file"))
{
self->our_rc_file = val;
printf("storing signed rc at %s\n", self->our_rc_file.c_str());
af = AF_INET;
proto = std::atoi(val);
}
return;
}
else
return;
if(llarp_link_initialized(link))
{
printf("link initialized...");
if (link->configure(link, self->netloop, key, af, proto))
struct llarp_link *link = nullptr;
if(StrEq(section, "iwp-links"))
{
link = new llarp_link;
llarp::Zero(link, sizeof(llarp_link));
llarp_iwp_args args = {
.mem = self->mem,
.crypto = &self->crypto,
.logic = self->logic,
.cryptoworker = self->tp,
.keyfile = self->transport_keyfile.c_str(),
};
iwp_link_init(link, args, &self->muxer);
}
else if(StrEq(section, "iwp-connect"))
{
std::error_code ec;
if(fs::exists(val, ec))
self->connect.try_emplace(key, val);
else
printf("cannot read %s\n", val);
return;
}
else if(StrEq(section, "router"))
{
printf("configured on %s\n", key);
self->AddLink(link);
if(StrEq(key, "contact-file"))
{
self->our_rc_file = val;
printf("storing signed rc at %s\n", self->our_rc_file.c_str());
}
return;
}
else
return;
if(llarp_link_initialized(link))
{
printf("link initialized...");
if(link->configure(link, self->netloop, key, af, proto))
{
llarp_ai ai;
link->get_our_address(link, &ai);
llarp::Addr addr = ai;
printf("configured on %s as %s\n", key, addr.to_string().c_str());
self->AddLink(link);
return;
}
}
self->mem->free(self->mem, link);
printf("failed to configure link for %s\n", key);
}
self->mem->free(self->mem, link);
printf("failed to configure link for %s\n", key);
}
} // namespace llarp

@ -4,61 +4,90 @@
#include <llarp/router.h>
#include <llarp/router_contact.h>
#include <functional>
#include <list>
#include <map>
#include "mem.hpp"
#include "fs.hpp"
#include "mem.hpp"
namespace llarp {
struct router_links {
llarp_link *link = nullptr;
router_links *next = nullptr;
};
namespace llarp
{
struct try_connect_ctx
{
llarp_router *router = nullptr;
llarp_ai addr;
};
} // namespace llarp
struct llarp_router {
struct llarp_router
{
bool ready;
// transient iwp encryption key
fs::path transport_keyfile = "transport.key";
// nodes to connect to on startup
std::map<std::string, fs::path> connect;
std::map< std::string, fs::path > connect;
// long term identity key
fs::path ident_keyfile = "identity.key";
// path to write our self signed rc to
fs::path our_rc_file = "rc.signed";
llarp_rc rc;
llarp_ev_loop * netloop;
llarp_ev_loop *netloop;
llarp_threadpool *tp;
llarp_logic * logic;
llarp::router_links links;
llarp_logic *logic;
llarp_crypto crypto;
llarp_msg_muxer muxer;
llarp_path_context *paths;
llarp_alloc * mem;
llarp_alloc *mem;
llarp_seckey_t identity;
llarp_router(llarp_alloc * mem);
std::list< llarp_link * > links;
std::map< char, llarp_frame_handler > frame_handlers;
llarp_router(llarp_alloc *mem);
~llarp_router();
void AddLink(struct llarp_link *link);
void
AddLink(struct llarp_link *link);
void
Close();
bool
Ready();
void
Run();
bool
EnsureIdentity();
bool
SaveRC();
void ForEachLink(std::function<void(llarp_link *)> visitor);
uint8_t *
pubkey()
{
return llarp_seckey_topublic(identity);
}
void Close();
void
try_connect(fs::path rcfile);
bool Ready();
bool
has_session_to(const uint8_t *pubkey) const;
bool EnsureIdentity();
bool SaveRC();
static bool
iter_try_connect(llarp_router_link_iter *i, llarp_router *router,
llarp_link *l);
uint8_t * pubkey() { return llarp_seckey_topublic(identity); }
static void
on_try_connect_result(llarp_link_establish_job *job);
};
#endif

@ -2,52 +2,69 @@
#include <llarp/router_contact.h>
#include <llarp/version.h>
void llarp_rc_free(struct llarp_rc *rc) {
llarp_xi_list_free(&rc->exits);
llarp_ai_list_free(&rc->addrs);
void
llarp_rc_free(struct llarp_rc *rc)
{
if(rc->exits)
llarp_xi_list_free(rc->exits);
if(rc->addrs)
llarp_ai_list_free(rc->addrs);
rc->exits = 0;
rc->addrs = 0;
}
struct llarp_rc_decoder
{
struct llarp_rc * rc;
struct llarp_alloc * mem;
struct llarp_rc *rc;
struct llarp_alloc *mem;
};
static bool llarp_rc_decode_dict(struct dict_reader * r, llarp_buffer_t * key)
static bool
llarp_rc_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
{
int64_t v;
llarp_buffer_t strbuf;
struct llarp_rc_decoder * dec = r->user;
struct llarp_alloc * mem = dec->mem;
struct llarp_rc * rc = dec->rc;
struct llarp_rc_decoder *dec = r->user;
struct llarp_alloc *mem = dec->mem;
struct llarp_rc *rc = dec->rc;
if(!key) return true;
if(!key)
return true;
if(llarp_buffer_eq(*key, "a"))
{
if(rc->addrs)
{
llarp_ai_list_free(rc->addrs);
}
rc->addrs = llarp_ai_list_new(mem);
return llarp_ai_list_bdecode(rc->addrs, r->buffer);
}
if(llarp_buffer_eq(*key, "k"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
if(!bdecode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != sizeof(llarp_pubkey_t))
if(strbuf.sz != sizeof(llarp_pubkey_t))
return false;
memcpy(rc->pubkey, strbuf.base, sizeof(llarp_pubkey_t));
return true;
}
}
if(llarp_buffer_eq(*key, "v"))
{
if(!bdecode_read_integer(r->buffer, &v))
if(!bdecode_read_integer(r->buffer, &v))
return false;
return v == LLARP_PROTO_VERSION;
}
if(llarp_buffer_eq(*key, "x"))
{
if(rc->exits)
{
llarp_xi_list_free(rc->exits);
}
rc->exits = llarp_xi_list_new(mem);
return llarp_xi_list_bdecode(rc->exits, r->buffer);
}
@ -65,71 +82,83 @@ static bool llarp_rc_decode_dict(struct dict_reader * r, llarp_buffer_t * key)
return false;
}
bool llarp_rc_bdecode(struct llarp_alloc * mem, struct llarp_rc * rc, llarp_buffer_t *buff) {
struct llarp_rc_decoder decode = {
.rc = rc,
.mem = mem
};
struct dict_reader r = {
.user = &decode,
.on_key = &llarp_rc_decode_dict
};
bool
llarp_rc_bdecode(struct llarp_alloc *mem, struct llarp_rc *rc,
llarp_buffer_t *buff)
{
struct llarp_rc_decoder decode = {.rc = rc, .mem = mem};
struct dict_reader r = {.user = &decode, .on_key = &llarp_rc_decode_dict};
return bdecode_read_dict(buff, &r);
}
bool llarp_rc_verify_sig(struct llarp_crypto * crypto, struct llarp_rc * rc)
bool
llarp_rc_verify_sig(struct llarp_crypto *crypto, struct llarp_rc *rc)
{
bool result = false;
llarp_sig_t sig;
char tmp[MAX_RC_SIZE];
byte_t tmp[MAX_RC_SIZE];
llarp_buffer_t buf;
buf.base = tmp;
buf.cur = tmp;
buf.sz = sizeof(tmp);
buf.cur = tmp;
buf.sz = sizeof(tmp);
// copy sig
memcpy(sig, rc->signature, sizeof(llarp_sig_t));
// zero sig
memset(rc->signature, 0, sizeof(llarp_sig_t));
// zero sig
size_t sz = 0;
while(sz < sizeof(llarp_sig_t))
rc->signature[sz++] = 0;
// bencode
if(llarp_rc_bencode(rc, &buf))
{
buf.sz = buf.cur - buf.base;
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// verify
result = crypto->verify(rc->pubkey, buf, sig);
// restore sig
memcpy(rc->signature, sig, sizeof(llarp_sig_t));
result = crypto->verify(rc->pubkey, buf, sig);
}
else
printf("llarp_rc_bencode() failed\n");
// restore sig
memcpy(rc->signature, sig, sizeof(llarp_sig_t));
return result;
}
bool llarp_rc_bencode(struct llarp_rc *rc, llarp_buffer_t *buff) {
bool
llarp_rc_bencode(struct llarp_rc *rc, llarp_buffer_t *buff)
{
/* write dict begin */
if (!bencode_start_dict(buff)) return false;
if (rc->addrs) {
if(!bencode_start_dict(buff))
return false;
if(rc->addrs)
{
/* write ai if they exist */
if (!bencode_write_bytestring(buff, "a", 1)) return false;
if (!llarp_ai_list_bencode(rc->addrs, buff)) return false;
if(!bencode_write_bytestring(buff, "a", 1))
return false;
if(!llarp_ai_list_bencode(rc->addrs, buff))
return false;
}
/* write pubkey */
if (!bencode_write_bytestring(buff, "k", 1)) return false;
if (!bencode_write_bytestring(buff, rc->pubkey, sizeof(llarp_pubkey_t)))
if(!bencode_write_bytestring(buff, "k", 1))
return false;
if(!bencode_write_bytestring(buff, rc->pubkey, sizeof(llarp_pubkey_t)))
return false;
/* write version */
if (!bencode_write_version_entry(buff)) return false;
if(!bencode_write_version_entry(buff))
return false;
if (rc->exits) {
if(rc->exits)
{
/* write ai if they exist */
if (!bencode_write_bytestring(buff, "x", 1)) return false;
if (!llarp_xi_list_bencode(rc->exits, buff)) return false;
if(!bencode_write_bytestring(buff, "x", 1))
return false;
if(!llarp_xi_list_bencode(rc->exits, buff))
return false;
}
/* write signature */
if (!bencode_write_bytestring(buff, "z", 1)) return false;
if (!bencode_write_bytestring(buff, rc->signature, sizeof(llarp_sig_t)))
if(!bencode_write_bytestring(buff, "z", 1))
return false;
if(!bencode_write_bytestring(buff, rc->signature, sizeof(llarp_sig_t)))
return false;
return bencode_end(buff);
}

@ -2,15 +2,20 @@
#define LIBLLARP_STR_HPP
#include <cstring>
namespace llarp {
static bool StrEq(const char *s1, const char *s2) {
size_t sz1 = strlen(s1);
size_t sz2 = strlen(s2);
if (sz1 == sz2) {
return strncmp(s1, s2, sz1) == 0;
} else
return false;
}
namespace llarp
{
static bool
StrEq(const char *s1, const char *s2)
{
size_t sz1 = strlen(s1);
size_t sz2 = strlen(s2);
if(sz1 == sz2)
{
return strncmp(s1, s2, sz1) == 0;
}
else
return false;
}
} // namespace llarp

@ -2,97 +2,135 @@
#include <pthread.h>
#include <cstring>
namespace llarp {
namespace thread {
Pool::Pool(size_t workers, const char * name) {
stop = false;
while (workers--) {
threads.emplace_back([this, name] {
namespace llarp
{
namespace thread
{
Pool::Pool(size_t workers, const char *name)
{
stop = false;
while(workers--)
{
threads.emplace_back([this] {
for(;;)
{
llarp_thread_job job;
{
lock_t lock(this->queue_mutex);
this->condition.wait(
lock, [this] { return this->stop || !this->jobs.empty(); });
if(this->stop && this->jobs.empty())
return;
job = std::move(this->jobs.front());
this->jobs.pop_front();
}
// do work
job.work(job.user);
}
});
}
if(name)
pthread_setname_np(pthread_self(), name);
llarp_thread_job job;
for (;;) {
{
lock_t lock(this->queue_mutex);
this->condition.wait(
lock, [this] { return this->stop || !this->jobs.empty(); });
if (this->stop && this->jobs.empty()) return;
job = std::move(this->jobs.front());
this->jobs.pop_front();
}
// do work
job.work(job.user);
{
for(auto &t : threads)
pthread_setname_np(t.native_handle(), name);
}
});
}
}
void Pool::Stop() {
{
lock_t lock(queue_mutex);
stop = true;
}
condition.notify_all();
done.notify_all();
}
void Pool::Join() {
for (auto &t : threads) t.join();
threads.clear();
}
void Pool::QueueJob(const llarp_thread_job &job) {
{
lock_t lock(queue_mutex);
// don't allow enqueueing after stopping the pool
if (stop) throw std::runtime_error("enqueue on stopped ThreadPool");
jobs.emplace_back(job);
}
condition.notify_one();
}
}
void
Pool::Stop()
{
{
lock_t lock(queue_mutex);
stop = true;
}
condition.notify_all();
done.notify_all();
}
void
Pool::Join()
{
for(auto &t : threads)
t.join();
threads.clear();
}
void
Pool::QueueJob(const llarp_thread_job &job)
{
{
lock_t lock(queue_mutex);
// don't allow enqueueing after stopping the pool
if(stop)
throw std::runtime_error("enqueue on stopped ThreadPool");
jobs.emplace_back(job);
}
condition.notify_one();
}
} // namespace thread
} // namespace thread
} // namespace llarp
struct llarp_threadpool {
struct llarp_threadpool
{
llarp::thread::Pool impl;
llarp_threadpool(int workers, const char * name) : impl(workers, name) {}
llarp_threadpool(int workers, const char *name) : impl(workers, name)
{
}
};
extern "C" {
struct llarp_threadpool *llarp_init_threadpool(int workers, const char * name) {
if (workers > 0)
struct llarp_threadpool *
llarp_init_threadpool(int workers, const char *name)
{
if(workers > 0)
return new llarp_threadpool(workers, name);
else
return nullptr;
}
void llarp_threadpool_join(struct llarp_threadpool *pool) { pool->impl.Join(); }
void
llarp_threadpool_join(struct llarp_threadpool *pool)
{
pool->impl.Join();
}
void llarp_threadpool_start(struct llarp_threadpool *pool) { /** no op */
void
llarp_threadpool_start(struct llarp_threadpool *pool)
{ /** no op */
}
void llarp_threadpool_stop(struct llarp_threadpool *pool) { pool->impl.Stop(); }
void
llarp_threadpool_stop(struct llarp_threadpool *pool)
{
pool->impl.Stop();
}
void llarp_threadpool_wait(struct llarp_threadpool *pool) {
void
llarp_threadpool_wait(struct llarp_threadpool *pool)
{
std::mutex mtx;
{
std::unique_lock<std::mutex> lock(mtx);
std::unique_lock< std::mutex > lock(mtx);
pool->impl.done.wait(lock);
}
}
void llarp_threadpool_queue_job(struct llarp_threadpool *pool,
struct llarp_thread_job job) {
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) {
void
llarp_free_threadpool(struct llarp_threadpool **pool)
{
delete *pool;
*pool = nullptr;
}

@ -9,25 +9,31 @@
#include <thread>
#include <vector>
namespace llarp {
namespace thread {
typedef std::mutex mtx_t;
typedef std::unique_lock<mtx_t> lock_t;
struct Pool {
Pool(size_t sz, const char * name);
void QueueJob(const llarp_thread_job& job);
void Join();
void Stop();
std::vector<std::thread> threads;
std::deque<llarp_thread_job> jobs;
namespace llarp
{
namespace thread
{
typedef std::mutex mtx_t;
typedef std::unique_lock< mtx_t > lock_t;
struct Pool
{
Pool(size_t sz, const char* name);
void
QueueJob(const llarp_thread_job& job);
void
Join();
void
Stop();
std::vector< std::thread > threads;
std::deque< llarp_thread_job > jobs;
mtx_t queue_mutex;
std::condition_variable condition;
std::condition_variable done;
bool stop;
};
mtx_t queue_mutex;
std::condition_variable condition;
std::condition_variable done;
bool stop;
};
} // namespace thread
} // namespace thread
} // namespace llarp
#endif

@ -1,23 +1,30 @@
#include <llarp/time.h>
#include <chrono>
namespace llarp {
typedef std::chrono::steady_clock clock_t;
namespace llarp
{
typedef std::chrono::steady_clock clock_t;
template <typename Res, typename IntType>
static IntType time_since_epoch() {
return std::chrono::duration_cast<Res>(
llarp::clock_t::now().time_since_epoch())
.count();
}
template < typename Res, typename IntType >
static IntType
time_since_epoch()
{
return std::chrono::duration_cast< Res >(
llarp::clock_t::now().time_since_epoch())
.count();
}
} // namespace llarp
extern "C" {
llarp_time_t llarp_time_now_ms() {
return llarp::time_since_epoch<std::chrono::milliseconds, llarp_time_t>();
llarp_time_t
llarp_time_now_ms()
{
return llarp::time_since_epoch< std::chrono::milliseconds, llarp_time_t >();
}
llarp_seconds_t llarp_time_now_sec() {
return llarp::time_since_epoch<std::chrono::seconds, llarp_seconds_t>();
llarp_seconds_t
llarp_time_now_sec()
{
return llarp::time_since_epoch< std::chrono::seconds, llarp_seconds_t >();
}
}

@ -4,93 +4,124 @@
#include <list>
#include <map>
namespace llarp {
struct timer {
static uint64_t now() {
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count();
}
llarp_timer_context * parent;
void* user;
uint64_t started;
uint64_t timeout;
llarp_timer_handler_func func;
uint32_t id;
namespace llarp
{
struct timer
{
static uint64_t
now()
{
return std::chrono::duration_cast< std::chrono::milliseconds >(
std::chrono::steady_clock::now().time_since_epoch())
.count();
}
timer(llarp_timer_context * ctx=nullptr, uint64_t ms = 0, void* _user = nullptr,
llarp_timer_handler_func _func = nullptr, uint32_t _id=0)
: parent(ctx), user(_user), started(now()), timeout(ms), func(_func), id(_id) {}
llarp_timer_context* parent;
void* user;
uint64_t started;
uint64_t timeout;
llarp_timer_handler_func func;
uint32_t id;
timer(llarp_timer_context* ctx = nullptr, uint64_t ms = 0,
void* _user = nullptr, llarp_timer_handler_func _func = nullptr,
uint32_t _id = 0)
: parent(ctx)
, user(_user)
, started(now())
, timeout(ms)
, func(_func)
, id(_id)
{
}
void exec();
void
exec();
static void call(void * user)
{
static_cast<timer *>(user)->exec();
}
static void
call(void* user)
{
static_cast< timer* >(user)->exec();
}
operator llarp_thread_job ()
{
return {this, timer::call};
}
};
operator llarp_thread_job()
{
return {this, timer::call};
}
};
}; // namespace llarp
struct llarp_timer_context {
llarp_threadpool * threadpool;
struct llarp_timer_context
{
llarp_threadpool* threadpool;
std::mutex timersMutex;
std::map<uint32_t, llarp::timer> timers;
std::map< uint32_t, llarp::timer > timers;
std::mutex tickerMutex;
std::condition_variable ticker;
std::chrono::milliseconds nextTickLen = std::chrono::milliseconds(10);
uint32_t ids = 0;
std::atomic<bool> _run = true;
uint32_t ids = 0;
std::atomic< bool > _run = true;
bool run() { return _run.load(); }
bool
run()
{
return _run.load();
}
void stop() { _run.store(false); }
void
stop()
{
_run.store(false);
}
void cancel(uint32_t id, bool lockit = true) {
std::unique_lock<std::mutex>* lock = nullptr;
if (lockit) lock = new std::unique_lock<std::mutex>(timersMutex);
void
cancel(uint32_t id, bool lockit = true)
{
std::unique_lock< std::mutex >* lock = nullptr;
if(lockit)
lock = new std::unique_lock< std::mutex >(timersMutex);
auto itr = timers.find(id);
if (itr != timers.end()) {
if(itr != timers.end())
{
itr->second.exec();
}
if (lock) delete lock;
if(lock)
delete lock;
}
void remove(uint32_t id)
void
remove(uint32_t id)
{
std::unique_lock<std::mutex> lock (timersMutex);
std::unique_lock< std::mutex > lock(timersMutex);
timers.erase(id);
}
uint32_t call_later(void* user, llarp_timer_handler_func func,
uint64_t timeout_ms) {
std::unique_lock<std::mutex> lock(timersMutex);
uint32_t
call_later(void* user, llarp_timer_handler_func func, uint64_t timeout_ms)
{
std::unique_lock< std::mutex > lock(timersMutex);
uint32_t id = ++ids;
timers[id] = llarp::timer(this, timeout_ms, user, func, id);
timers[id] = llarp::timer(this, timeout_ms, user, func, id);
return id;
}
void cancel_all() {
std::unique_lock<std::mutex> lock(timersMutex);
void
cancel_all()
{
std::unique_lock< std::mutex > lock(timersMutex);
std::list<uint32_t> ids;
std::list< uint32_t > ids;
for (auto& item : timers) {
for(auto& item : timers)
{
ids.push_back(item.first);
}
for (auto id : ids) {
for(auto id : ids)
{
cancel(id, false);
}
}
@ -98,27 +129,36 @@ struct llarp_timer_context {
extern "C" {
struct llarp_timer_context* llarp_init_timer() {
struct llarp_timer_context*
llarp_init_timer()
{
return new llarp_timer_context;
}
uint32_t llarp_timer_call_later(struct llarp_timer_context* t,
struct llarp_timeout_job job) {
uint32_t
llarp_timer_call_later(struct llarp_timer_context* t,
struct llarp_timeout_job job)
{
return t->call_later(job.user, job.handler, job.timeout);
}
void llarp_free_timer(struct llarp_timer_context** t) {
if (*t) delete *t;
void
llarp_free_timer(struct llarp_timer_context** t)
{
if(*t)
delete *t;
*t = nullptr;
}
void llarp_timer_stop(struct llarp_timer_context* t) {
void
llarp_timer_stop(struct llarp_timer_context* t)
{
t->stop();
{
std::unique_lock<std::mutex> lock(t->tickerMutex);
std::unique_lock< std::mutex > lock(t->tickerMutex);
auto itr = t->timers.begin();
while (itr != t->timers.end())
while(itr != t->timers.end())
{
// timer expired
llarp_threadpool_queue_job(t->threadpool, itr->second);
@ -127,20 +167,24 @@ void llarp_timer_stop(struct llarp_timer_context* t) {
}
}
void llarp_timer_cancel(struct llarp_timer_context* t, uint32_t id) {
void
llarp_timer_cancel(struct llarp_timer_context* t, uint32_t id)
{
t->cancel(id);
}
void llarp_timer_run(struct llarp_timer_context* t,
struct llarp_threadpool* pool) {
void
llarp_timer_run(struct llarp_timer_context* t, struct llarp_threadpool* pool)
{
t->threadpool = pool;
while (t->run()) {
std::unique_lock<std::mutex> lock(t->tickerMutex);
while(t->run())
{
std::unique_lock< std::mutex > lock(t->tickerMutex);
t->ticker.wait_for(lock, t->nextTickLen);
// we woke up
auto now = llarp::timer::now();
auto itr = t->timers.begin();
while (itr != t->timers.end())
while(itr != t->timers.end())
{
if(now - itr->second.started >= itr->second.timeout)
{
@ -155,12 +199,14 @@ void llarp_timer_run(struct llarp_timer_context* t,
namespace llarp
{
void timer::exec()
void
timer::exec()
{
if (func) {
auto ms = now();
if(func)
{
auto ms = now();
auto diff = ms - started;
if (diff >= timeout)
if(diff >= timeout)
func(user, timeout, 0);
else
func(user, timeout, diff);

Loading…
Cancel
Save