pull/1/head
Ryan Tharp 6 years ago
commit 3f6a5c4ca5

@ -1,13 +1,16 @@
cmake_minimum_required(VERSION 2.8.10)
set(WITH_SHARED OFF)
set(DEBUG_FLAGS "")
set(OPTIMIZE_FLAGS "-Os")
if(ASAN)
set(DEBUG_FLAGS "${DEBUG_FLAGS} -O1 -g -fsanitize=address -fno-omit-frame-pointer")
set(DEBUG_FLAGS "${DEBUG_FLAGS} -g -fsanitize=address -fno-omit-frame-pointer")
set(OPTIMIZE_FLAGS "-O0")
endif(ASAN)
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_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -Wall ${DEBUG_FLAGS} ${OPTIMIZE_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall ${DEBUG_FLAGS} ${OPTIMIZE_FLAGS}")
if(NOT GIT_VERSION)
exec_program("git" ${CMAKE_CURRENT_SOURCE_DIR} ARGS "rev-parse --short HEAD" OUTPUT_VARIABLE GIT_VERSION)
@ -39,11 +42,13 @@ set(STATIC_LIB ${LIB}-static)
set(LIB_SRC
llarp/address_info.cpp
llarp/bencode.c
llarp/buffer.cpp
llarp/config.cpp
llarp/context.cpp
llarp/crypto_async.cpp
llarp/crypto_libsodium.cpp
llarp/dht.cpp
llarp/ev.cpp
llarp/exit_info.cpp
llarp/exit_route.c
@ -56,6 +61,7 @@ set(LIB_SRC
llarp/mem.cpp
llarp/net.cpp
llarp/nodedb.cpp
llarp/relay_commit.cpp
llarp/router_contact.cpp
llarp/router.cpp
llarp/router_identity.c
@ -67,12 +73,14 @@ set(LIB_SRC
include_directories(include)
add_library(${STATIC_LIB} STATIC ${LIB_SRC})
add_library(${SHARED_LIB} SHARED ${LIB_SRC})
if(WITH_SHARED)
add_library(${SHARED_LIB} SHARED ${LIB_SRC})
target_link_libraries(${SHARED_LIB} ${LIBS})
endif()
add_executable(${EXE} ${EXE_SRC})
target_link_libraries(${STATIC_LIB} ${LIBS})
target_link_libraries(${EXE} ${STATIC_LIB})
target_link_libraries(${SHARED_LIB} ${STATIC_LIB} ${LIBS})
add_executable(rcutil daemon/rcutil.cpp)
target_link_libraries(rcutil ${STATIC_LIB} ${LIBS})

@ -410,7 +410,7 @@ transfer one or more dht messages directly without a previously made path.
{
a: "m",
d: [many, dht, messages],
m: [many, dht, messages],
v: 0
}

@ -1,5 +1,6 @@
#ifndef LLARP_H_
#define LLARP_H_
#include <llarp/dht.h>
#include <llarp/ev.h>
#include <llarp/logic.h>
#include <llarp/mem.h>
@ -22,6 +23,10 @@ llarp_main_init(const char *fname);
void
llarp_main_signal(struct llarp_main *ptr, int sig);
/** set custom dht message handler function */
void
llarp_main_set_dht_handler(struct llarp_main *ptr, llarp_dht_msg_handler h);
/** run main context */
int
llarp_main_run(struct llarp_main *ptr);

@ -17,13 +17,14 @@ namespace llarp
int num_nethreads = 1;
std::vector< std::thread > netio_threads;
llarp_crypto crypto;
llarp_router *router = nullptr;
llarp_threadpool *worker = nullptr;
llarp_logic *logic = nullptr;
llarp_config *config = nullptr;
llarp_nodedb *nodedb = nullptr;
llarp_ev_loop *mainloop = nullptr;
char nodedb_dir[256] = {0};
llarp_router *router = nullptr;
llarp_threadpool *worker = nullptr;
llarp_logic *logic = nullptr;
llarp_config *config = nullptr;
llarp_nodedb *nodedb = nullptr;
llarp_ev_loop *mainloop = nullptr;
llarp_dht_msg_handler custom_dht_func = nullptr;
char nodedb_dir[256] = {0};
bool
LoadConfig(const std::string &fname);

@ -0,0 +1,129 @@
#ifndef LLARP_ALIGNED_HPP
#define LLARP_ALIGNED_HPP
#include <llarp/crypto.h>
#include <sodium.h>
#include <iomanip>
#include <iostream>
#include <llarp/logger.hpp>
namespace llarp
{
/// aligned buffer, sz must be multiple of 8 bytes
template < size_t sz >
struct AlignedBuffer
{
AlignedBuffer()
{
Zero();
}
AlignedBuffer(const AlignedBuffer& other) : AlignedBuffer(other.data())
{
}
AlignedBuffer(const byte_t* data)
{
for(size_t idx = 0; idx < sz; ++idx)
buf.b[idx] = data[idx];
}
AlignedBuffer&
operator=(const byte_t* data)
{
for(size_t idx = 0; idx < sz; ++idx)
buf.b[idx] = data[idx];
return *this;
}
byte_t& operator[](size_t idx)
{
return buf.b[idx];
}
friend std::ostream&
operator<<(std::ostream& out, const AlignedBuffer& self)
{
size_t idx = 0;
out << std::hex << std::setw(2) << std::setfill('0');
while(idx < sz)
{
out << (int)self.buf.b[idx++];
}
return out << std::dec << std::setw(0) << std::setfill(' ');
}
bool
operator==(const AlignedBuffer& other) const
{
return memcmp(data(), other.data(), sz) == 0;
}
bool
operator!=(const AlignedBuffer& other) const
{
return !(*this == other);
}
size_t
size() const
{
return sz;
}
void
Zero()
{
for(size_t idx = 0; sz < idx / 8; ++idx)
buf.l[idx] = 0;
}
void
Randomize()
{
randombytes(buf.b, sz);
}
byte_t*
data()
{
return &buf.b[0];
}
const byte_t*
data() const
{
return &buf.b[0];
}
uint64_t*
data_l()
{
return &buf.l[0];
}
const uint64_t*
data_l() const
{
return &buf.l[0];
}
operator const byte_t*() const
{
return &buf.b[0];
}
operator byte_t*()
{
return &buf.b[0];
}
private:
union {
byte_t b[sz];
uint64_t l[sz / 8];
} buf;
};
}
#endif

@ -18,122 +18,41 @@
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;
return llarp_buffer_write(buff, data, sz);
}
bool
bencode_write_bytestring(llarp_buffer_t* buff, const void* data, size_t sz);
static bool INLINE
bencode_write_int(llarp_buffer_t* buff, int i)
{
return llarp_buffer_writef(buff, "i%de", i);
}
bool
bencode_write_int(llarp_buffer_t* buff, int i);
static bool INLINE
bencode_write_uint16(llarp_buffer_t* buff, uint16_t i)
{
return llarp_buffer_writef(buff, "i%de", i);
}
bool
bencode_write_uint16(llarp_buffer_t* buff, uint16_t i);
static bool INLINE
bencode_write_int64(llarp_buffer_t* buff, int64_t i)
{
return llarp_buffer_writef(buff, "i%lde", i);
}
bool
bencode_write_int64(llarp_buffer_t* buff, int64_t i);
static bool INLINE
bencode_write_uint64(llarp_buffer_t* buff, uint64_t i)
{
return llarp_buffer_writef(buff, "i%lde", i);
}
bool
bencode_write_uint64(llarp_buffer_t* buff, uint64_t i);
static bool INLINE
bencode_write_sizeint(llarp_buffer_t* buff, size_t i)
{
return llarp_buffer_writef(buff, "i%lde", i);
}
bool
bencode_write_sizeint(llarp_buffer_t* buff, size_t i);
static bool INLINE
bencode_start_list(llarp_buffer_t* buff)
{
return llarp_buffer_write(buff, "l", 1);
}
bool
bencode_start_list(llarp_buffer_t* buff);
static bool INLINE
bencode_start_dict(llarp_buffer_t* buff)
{
return llarp_buffer_write(buff, "d", 1);
}
bool
bencode_start_dict(llarp_buffer_t* buff);
static bool INLINE
bencode_end(llarp_buffer_t* buff)
{
return llarp_buffer_write(buff, "e", 1);
}
bool
bencode_end(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);
}
bool
bencode_write_version_entry(llarp_buffer_t* buff);
static bool INLINE
bdecode_read_integer(struct llarp_buffer_t* buffer, uint64_t* result)
{
size_t len;
if(*buffer->cur != 'i')
return false;
char numbuf[32];
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);
return true;
}
static bool INLINE
bdecode_read_string(llarp_buffer_t* buffer, llarp_buffer_t* result)
{
size_t len, slen;
int num;
char numbuf[10];
len =
llarp_buffer_read_until(buffer, ':', (byte_t*)numbuf, sizeof(numbuf) - 1);
if(!len)
return false;
bool
bencode_read_integer(struct llarp_buffer_t* buffer, uint64_t* result);
numbuf[len] = 0;
num = atoi(numbuf);
if(num < 0)
return false;
slen = num;
buffer->cur++;
len = llarp_buffer_size_left(*buffer);
if(len < slen)
return false;
result->base = buffer->cur;
result->cur = buffer->cur;
result->sz = slen;
buffer->cur += slen;
return true;
}
bool
bencode_read_string(llarp_buffer_t* buffer, llarp_buffer_t* result);
struct dict_reader
{
@ -149,28 +68,8 @@ struct dict_reader
bool (*on_key)(struct dict_reader*, llarp_buffer_t*);
};
static bool INLINE
bdecode_read_dict(llarp_buffer_t* buff, struct dict_reader* r)
{
llarp_buffer_t strbuf; // temporary buffer for current element
r->buffer = buff; // set up dict_reader
if(*r->buffer->cur != 'd') // ensure is a dictionary
return false;
r->buffer->cur++;
while(llarp_buffer_size_left(*r->buffer) && *r->buffer->cur != 'e')
{
if(bdecode_read_string(r->buffer, &strbuf))
{
if(!r->on_key(r, &strbuf)) // check for early abort
return false;
}
}
if(*r->buffer->cur != 'e') // make sure we're at dictionary end
return false;
r->buffer->cur++;
return r->on_key(r, 0);
}
bool
bencode_read_dict(llarp_buffer_t* buff, struct dict_reader* r);
struct list_reader
{
@ -186,24 +85,8 @@ struct list_reader
bool (*on_item)(struct list_reader*, bool);
};
static bool INLINE
bdecode_read_list(llarp_buffer_t* buff, struct list_reader* r)
{
r->buffer = buff;
if(*r->buffer->cur != 'l') // ensure is a list
return false;
r->buffer->cur++;
while(llarp_buffer_size_left(*r->buffer) && *r->buffer->cur != 'e')
{
if(!r->on_item(r, true)) // check for early abort
return false;
}
if(*r->buffer->cur != 'e') // make sure we're at a list end
return false;
r->buffer->cur++;
return r->on_item(r, false);
}
bool
bencode_read_list(llarp_buffer_t* buff, struct list_reader* r);
#ifdef __cplusplus
}

@ -1,6 +1,9 @@
#ifndef LLARP_DHT_H_
#define LLARP_DHT_H_
#include <llarp/buffer.h>
#include <llarp/router.h>
/**
* dht.h
*
@ -15,12 +18,54 @@ struct llarp_dht_context;
/// allocator
struct llarp_dht_context*
llarp_dht_context_new();
llarp_dht_context_new(struct llarp_router* parent);
/// deallocator
void
llarp_dht_context_free(struct llarp_dht_context* dht);
struct llarp_dht_msg;
/// handler function
/// f(outmsg, inmsg)
/// returns true if outmsg has been filled otherwise returns false
typedef bool (*llarp_dht_msg_handler)(struct llarp_dht_msg*,
struct llarp_dht_msg*);
/// start dht context with our location in keyspace
void
llarp_dht_context_start(struct llarp_dht_context* ctx, const byte_t* key);
// override dht message handler with custom handler
void
llarp_dht_set_msg_handler(struct llarp_dht_context* ctx,
llarp_dht_msg_handler func);
struct llarp_router_lookup_job;
typedef void (*llarp_rotuer_lookup_handler)(struct llarp_router_lookup_job*);
struct llarp_router_lookup_job
{
void* user;
llarp_rotuer_lookup_handler hook;
struct llarp_dht_context* dht;
llarp_pubkey_t target;
bool found;
llarp_rc result;
};
// shallow copy
void
llarp_dht_put_local_router(struct llarp_dht_context* ctx, struct llarp_rc* rc);
void
llarp_dht_remove_local_router(struct llarp_dht_context* ctx, const byte_t* id);
void
llarp_dht_lookup_router(struct llarp_dht_context* ctx,
struct llarp_router_lookup_job* job);
#ifdef __cplusplus
}
#endif

@ -0,0 +1,296 @@
#ifndef LLARP_DHT_HPP_
#define LLARP_DHT_HPP_
#include <llarp/buffer.h>
#include <llarp/dht.h>
#include <llarp/router.h>
#include <llarp/router_contact.h>
#include <llarp/time.h>
#include <llarp/aligned.hpp>
#include <array>
#include <functional>
#include <map>
#include <unordered_map>
#include <vector>
namespace llarp
{
namespace dht
{
const size_t MAX_MSG_SIZE = 2048;
struct Key_t : public llarp::AlignedBuffer< 32 >
{
Key_t(const byte_t* val) : llarp::AlignedBuffer< 32 >(val)
{
}
Key_t() : llarp::AlignedBuffer< 32 >()
{
}
Key_t
operator^(const Key_t& other) const
{
Key_t dist;
for(size_t idx = 0; idx < 32; ++idx)
dist[idx] = (*this)[idx] ^ other[idx];
return dist;
}
bool
operator<(const Key_t& other) const
{
return memcmp(data_l(), other.data_l(), 32) < 0;
}
};
struct Node
{
llarp_rc* rc;
Key_t ID;
Node() : rc(nullptr)
{
ID.Zero();
}
Node(llarp_rc* other) : rc(other)
{
ID = other->pubkey;
}
};
struct SearchJob
{
const static uint64_t JobTimeout = 30000;
SearchJob();
SearchJob(const Key_t& requestor, const Key_t& target,
llarp_router_lookup_job* job);
void
Completed(const llarp_rc* router, bool timeout = false) const;
bool
IsExpired(llarp_time_t now) const;
private:
llarp_time_t started;
Key_t requestor;
Key_t target;
llarp_router_lookup_job* job;
};
struct XorMetric
{
const Key_t& us;
XorMetric(const Key_t& ourKey) : us(ourKey){};
bool
operator()(const Key_t& left, const Key_t& right) const
{
return (us ^ left) < right;
};
};
struct IMessage
{
virtual ~IMessage(){};
IMessage(const Key_t& from) : From(from)
{
}
virtual bool
BEncode(llarp_buffer_t* buf) const = 0;
virtual bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* val) = 0;
virtual bool
HandleMessage(llarp_router* router,
std::vector< IMessage* >& replies) const = 0;
Key_t From;
};
IMessage*
DecodeMessage(const Key_t& from, llarp_buffer_t* buf);
bool
DecodeMesssageList(const Key_t& from, llarp_buffer_t* buf,
std::vector< IMessage* >& dst);
struct Bucket
{
typedef std::map< Key_t, Node, XorMetric > BucketStorage_t;
Bucket(const Key_t& us) : nodes(XorMetric(us)){};
bool
FindClosest(const Key_t& target, Key_t& result) const;
bool
FindCloseExcluding(const Key_t& target, Key_t& result,
const Key_t& exclude) const;
BucketStorage_t nodes;
};
struct Context
{
Context();
~Context();
llarp_dht_msg_handler custom_handler = nullptr;
SearchJob*
FindPendingTX(const Key_t& owner, uint64_t txid);
void
RemovePendingLookup(const Key_t& owner, uint64_t txid);
void
LookupRouter(const Key_t& target, const Key_t& whoasked,
const Key_t& askpeer,
llarp_router_lookup_job* job = nullptr);
void
LookupRouterViaJob(llarp_router_lookup_job* job);
void
LookupRouterRelayed(const Key_t& requester, uint64_t txid,
const Key_t& target,
std::vector< IMessage* >& replies);
void
Init(const Key_t& us, llarp_router* router);
void
QueueRouterLookup(llarp_router_lookup_job* job);
static void
handle_cleaner_timer(void* user, uint64_t orig, uint64_t left);
static void
queue_router_lookup(void* user);
llarp_router* router = nullptr;
Bucket* nodes = nullptr;
private:
void
ScheduleCleanupTimer();
void
CleanupTX();
uint64_t ids;
struct TXOwner
{
Key_t requester = {0};
uint64_t txid = 0;
bool
operator==(const TXOwner& other) const
{
return txid == other.txid && requester == other.requester;
}
bool
operator<(const TXOwner& other) const
{
return txid < other.txid && requester < other.requester;
}
};
struct TXOwnerHash
{
std::size_t
operator()(TXOwner const& o) const noexcept
{
std::size_t sz2;
memcpy(&sz2, &o.requester[0], sizeof(std::size_t));
return o.txid ^ (sz2 << 1);
}
};
std::unordered_map< TXOwner, SearchJob, TXOwnerHash > pendingTX;
Key_t ourKey;
};
struct GotRouterMessage : public IMessage
{
GotRouterMessage(const Key_t& from) : IMessage(from)
{
}
GotRouterMessage(const Key_t& from, uint64_t id, const llarp_rc* result)
: IMessage(from), txid(id)
{
if(result)
{
R.emplace_back();
llarp_rc_clear(&R.back());
llarp_rc_copy(&R.back(), result);
}
}
~GotRouterMessage();
bool
BEncode(llarp_buffer_t* buf) const;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* val);
bool
HandleMessage(llarp_router* router,
std::vector< IMessage* >& replies) const;
std::vector< llarp_rc > R;
uint64_t txid = 0;
uint64_t version = 0;
};
struct FindRouterMessage : public IMessage
{
FindRouterMessage(const Key_t& from) : IMessage(from)
{
}
FindRouterMessage(const Key_t& from, const Key_t& target, uint64_t id)
: IMessage(from), K(target), txid(id)
{
}
~FindRouterMessage();
bool
BEncode(llarp_buffer_t* buf) const;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* val);
bool
HandleMessage(llarp_router* router,
std::vector< IMessage* >& replies) const;
Key_t K;
uint64_t txid = 0;
uint64_t version = 0;
};
}
}
struct llarp_dht_context
{
llarp::dht::Context impl;
llarp_router* parent;
llarp_dht_context(llarp_router* router);
};
#endif

@ -14,6 +14,9 @@
extern "C" {
#endif
/** 2^15 bytes */
const size_t MAX_LINK_MSG_SIZE = 32768;
/**
* wire layer transport interface
*/
@ -79,7 +82,12 @@ struct llarp_link
bool (*stop_link)(struct llarp_link *);
void (*iter_sessions)(struct llarp_link *, struct llarp_link_session_iter);
bool (*try_establish)(struct llarp_link *, struct llarp_link_establish_job *);
/// send to already established session given its public identity key
/// returns false if we don't have this session
/// returns true if the messages were queued
bool (*sendto)(struct llarp_link *, const byte_t *, llarp_buffer_t);
/// return true if we have a session to router given public identity key
bool (*has_session_to)(struct llarp_link *, const byte_t *);
void (*mark_session_active)(struct llarp_link *, struct llarp_link_session *);
void (*free_impl)(struct llarp_link *);
};

@ -3,18 +3,43 @@
#include <llarp/bencode.h>
#include <llarp/link.h>
#include <llarp/relay_commit.hpp>
#include <llarp/aligned.hpp>
#include <queue>
#include <vector>
namespace llarp
{
typedef std::vector< byte_t > Message;
typedef AlignedBuffer< 32 > RouterID;
struct InboundMessageHandler
struct ILinkMessage;
typedef std::queue< ILinkMessage* > SendQueue;
/// parsed link layer message
struct ILinkMessage
{
InboundMessageHandler(llarp_router* router);
/// who did this message come from (rc.k)
RouterID remote = {};
uint64_t version = 0;
ILinkMessage(const RouterID& id);
virtual ~ILinkMessage(){};
virtual bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) = 0;
virtual bool
BEncode(llarp_buffer_t* buf) const = 0;
virtual bool
HandleMessage(llarp_router* router) const = 0;
};
struct InboundMessageParser
{
InboundMessageParser(llarp_router* router);
dict_reader reader;
static bool
@ -29,28 +54,15 @@ namespace llarp
bool
MessageDone();
/// called to send any replies
bool
FlushReplies();
private:
bool
DecodeLIM(llarp_buffer_t key, llarp_buffer_t* buff);
bool
DecodeDHT(llarp_buffer_t key, llarp_buffer_t* buff);
bool
DecodeLRCM(llarp_buffer_t key, llarp_buffer_t* buff);
RouterID
GetCurrentFrom();
private:
char msgtype;
bool firstkey;
uint64_t proto;
llarp_router* router;
llarp_link_session* from;
llarp::LR_CommitMessage lrcm;
std::queue< Message > sendq;
ILinkMessage* msg = nullptr;
};
}

@ -5,6 +5,7 @@
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
namespace llarp
{
@ -30,14 +31,14 @@ namespace llarp
/** internal */
template < typename TArg >
void
LogAppend(std::stringstream& ss, TArg&& arg)
LogAppend(std::stringstream& ss, TArg&& arg) noexcept
{
ss << std::forward< TArg >(arg);
}
/** internal */
template < typename TArg, typename... TArgs >
void
LogAppend(std::stringstream& ss, TArg&& arg, TArgs&&... args)
LogAppend(std::stringstream& ss, TArg&& arg, TArgs&&... args) noexcept
{
LogAppend(ss, std::forward< TArg >(arg));
LogAppend(ss, std::forward< TArgs >(args)...);
@ -46,12 +47,12 @@ namespace llarp
/** internal */
template < typename... TArgs >
void
Log(LogLevel lvl, const char* tag, TArgs&&... args)
_Log(LogLevel lvl, const char* fname, TArgs&&... args) noexcept
{
if(_glog.minlevel > lvl)
return;
std::stringstream ss;
std::stringstream ss("");
switch(lvl)
{
case eLogDebug:
@ -71,41 +72,25 @@ namespace llarp
ss << "[ERR] ";
break;
}
auto t = std::time(nullptr);
auto now = std::localtime(&t);
auto t = std::time(nullptr);
auto now = std::localtime(&t);
std::string tag = fname;
auto pos = tag.rfind('/');
if(pos != std::string::npos)
tag = tag.substr(pos + 1);
while(tag.size() % 8)
tag += " ";
ss << std::put_time(now, "%F %T") << " " << tag << "\t";
LogAppend(ss, std::forward< TArgs >(args)...);
ss << (char)27 << "[0;0m";
_glog.out << ss.str() << std::endl;
}
template < typename... TArgs >
void
Debug(const char* tag, TArgs&&... args)
{
Log(eLogDebug, tag, std::forward< TArgs >(args)...);
}
template < typename... TArgs >
void
Info(const char* tag, TArgs&&... args)
{
Log(eLogInfo, tag, std::forward< TArgs >(args)...);
}
template < typename... TArgs >
void
Warn(const char* tag, TArgs&&... args)
{
Log(eLogWarn, tag, std::forward< TArgs >(args)...);
}
template < typename... TArgs >
void
Error(const char* tag, TArgs&&... args)
{
Log(eLogError, tag, std::forward< TArgs >(args)...);
}
}
#define Debug(x, ...) _Log(llarp::eLogDebug, __FILE__, x, ##__VA_ARGS__)
#define Info(x, ...) _Log(llarp::eLogInfo, __FILE__, x, ##__VA_ARGS__)
#define Warn(x, ...) _Log(llarp::eLogWarn, __FILE__, x, ##__VA_ARGS__)
#define Error(x, ...) _Log(llarp::eLogError, __FILE__, x, ##__VA_ARGS__)
#endif

@ -0,0 +1,30 @@
#ifndef LLARP_MESSAGES_DHT_IMMEDIATE_HPP
#define LLARP_MESSAGES_DHT_IMMEDIATE_HPP
#include <llarp/dht.hpp>
#include <llarp/link_message.hpp>
#include <vector>
namespace llarp
{
struct DHTImmeidateMessage : public ILinkMessage
{
DHTImmeidateMessage(const RouterID& from) : ILinkMessage(from)
{
}
~DHTImmeidateMessage();
std::vector< llarp::dht::IMessage* > msgs;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
bool
BEncode(llarp_buffer_t* buf) const;
bool
HandleMessage(llarp_router* router) const;
};
}
#endif

@ -0,0 +1,27 @@
#ifndef LLARP_MESSAGES_LINK_INTRO_HPP
#define LLARP_MESSAGES_LINK_INTRO_HPP
#include <llarp/link_message.hpp>
namespace llarp
{
struct LinkIntroMessage : public ILinkMessage
{
LinkIntroMessage(llarp_rc* rc) : ILinkMessage({}), RC(rc)
{
}
~LinkIntroMessage();
llarp_rc* RC;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
bool
BEncode(llarp_buffer_t* buf) const;
bool
HandleMessage(llarp_router* router) const;
};
}
#endif

@ -2,6 +2,7 @@
#define LLARP_RELAY_COMMIT_HPP
#include <llarp/crypto.h>
#include <llarp/encrypted_frame.hpp>
#include <llarp/link_message.hpp>
#include <vector>
namespace llarp
@ -47,19 +48,27 @@ namespace llarp
BEncode(llarp_buffer_t *buf);
};
struct LR_CommitMessage
struct LR_CommitMessage : public ILinkMessage
{
std::vector< EncryptedFrame > frames;
uint64_t version;
LR_CommitMessage(const RouterID &from) : ILinkMessage(from)
{
}
~LR_CommitMessage();
void
Clear();
bool
BDecode(llarp_buffer_t *buf);
DecodeKey(llarp_buffer_t key, llarp_buffer_t *buf);
bool
BEncode(llarp_buffer_t *buf);
BEncode(llarp_buffer_t *buf) const;
bool
HandleMessage(llarp_router *router) const;
};
struct AsyncPathDecryption

@ -24,7 +24,7 @@ void
llarp_free_router(struct llarp_router **router);
bool
llarp_router_try_connect(struct llarp_router *router, struct llarp_rc *remtoe);
llarp_router_try_connect(struct llarp_router *router, struct llarp_rc *remote);
bool
llarp_configure_router(struct llarp_router *router, struct llarp_config *conf);

@ -30,7 +30,7 @@ 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);
llarp_rc_copy(struct llarp_rc *dst, const struct llarp_rc *src);
void
llarp_rc_set_addrs(struct llarp_rc *rc, struct llarp_alloc *mem,

@ -26,7 +26,7 @@ llarp_ai_decode_key(struct dict_reader *r, llarp_buffer_t *key)
// rank
if(llarp_buffer_eq(*key, "c"))
{
if(!bdecode_read_integer(r->buffer, &i))
if(!bencode_read_integer(r->buffer, &i))
return false;
if(i > 65536 || i <= 0)
@ -39,7 +39,7 @@ llarp_ai_decode_key(struct dict_reader *r, llarp_buffer_t *key)
// dialect
if(llarp_buffer_eq(*key, "d"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz >= sizeof(ai->dialect))
@ -53,7 +53,7 @@ llarp_ai_decode_key(struct dict_reader *r, llarp_buffer_t *key)
// encryption public key
if(llarp_buffer_eq(*key, "e"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != sizeof(llarp_pubkey_t))
@ -66,7 +66,7 @@ llarp_ai_decode_key(struct dict_reader *r, llarp_buffer_t *key)
// ip address
if(llarp_buffer_eq(*key, "i"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz >= sizeof(tmp))
@ -80,7 +80,7 @@ llarp_ai_decode_key(struct dict_reader *r, llarp_buffer_t *key)
// port
if(llarp_buffer_eq(*key, "p"))
{
if(!bdecode_read_integer(r->buffer, &i))
if(!bencode_read_integer(r->buffer, &i))
return false;
if(i > 65536 || i <= 0)
@ -93,7 +93,7 @@ llarp_ai_decode_key(struct dict_reader *r, llarp_buffer_t *key)
// version
if(llarp_buffer_eq(*key, "v"))
{
if(!bdecode_read_integer(r->buffer, &i))
if(!bencode_read_integer(r->buffer, &i))
return false;
return i == LLARP_PROTO_VERSION;
}
@ -130,7 +130,7 @@ llarp_ai_bdecode(struct llarp_ai *ai, llarp_buffer_t *buff)
{
struct dict_reader reader = {
.buffer = nullptr, .user = ai, .on_key = &llarp_ai_decode_key};
return bdecode_read_dict(buff, &reader);
return bencode_read_dict(buff, &reader);
}
bool
@ -255,6 +255,6 @@ llarp_ai_list_bdecode(struct llarp_ai_list *l, llarp_buffer_t *buff)
{
struct list_reader r = {
.buffer = nullptr, .user = l, .on_item = &llarp_ai_list_bdecode_item};
return bdecode_read_list(buff, &r);
return bencode_read_list(buff, &r);
}
}

@ -0,0 +1,160 @@
#include <llarp/bencode.h>
bool
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);
}
bool
bencode_write_int(llarp_buffer_t* buff, int i)
{
return llarp_buffer_writef(buff, "i%de", i);
}
bool
bencode_write_uint16(llarp_buffer_t* buff, uint16_t i)
{
return llarp_buffer_writef(buff, "i%de", i);
}
bool
bencode_write_int64(llarp_buffer_t* buff, int64_t i)
{
return llarp_buffer_writef(buff, "i%lde", i);
}
bool
bencode_write_uint64(llarp_buffer_t* buff, uint64_t i)
{
return llarp_buffer_writef(buff, "i%lde", i);
}
bool
bencode_write_sizeint(llarp_buffer_t* buff, size_t i)
{
return llarp_buffer_writef(buff, "i%lde", i);
}
bool
bencode_start_list(llarp_buffer_t* buff)
{
return llarp_buffer_write(buff, "l", 1);
}
bool
bencode_start_dict(llarp_buffer_t* buff)
{
return llarp_buffer_write(buff, "d", 1);
}
bool
bencode_end(llarp_buffer_t* buff)
{
return llarp_buffer_write(buff, "e", 1);
}
bool
bencode_write_version_entry(llarp_buffer_t* buff)
{
return llarp_buffer_writef(buff, "1:vi%de", LLARP_PROTO_VERSION);
}
bool
bencode_read_integer(struct llarp_buffer_t* buffer, uint64_t* result)
{
size_t len;
if(*buffer->cur != 'i')
return false;
char numbuf[32];
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);
return *result != -1;
}
bool
bencode_read_string(llarp_buffer_t* buffer, llarp_buffer_t* result)
{
size_t len, slen;
int num;
char numbuf[10];
len =
llarp_buffer_read_until(buffer, ':', (byte_t*)numbuf, sizeof(numbuf) - 1);
if(!len)
return false;
numbuf[len] = 0;
num = atoi(numbuf);
if(num < 0)
return false;
slen = num;
buffer->cur++;
len = llarp_buffer_size_left(*buffer);
if(len < slen)
return false;
result->base = buffer->cur;
result->cur = buffer->cur;
result->sz = slen;
buffer->cur += slen;
return true;
}
bool
bencode_read_dict(llarp_buffer_t* buff, struct dict_reader* r)
{
llarp_buffer_t strbuf; // temporary buffer for current element
r->buffer = buff; // set up dict_reader
if(*r->buffer->cur != 'd') // ensure is a dictionary
return false;
r->buffer->cur++;
while(llarp_buffer_size_left(*r->buffer) && *r->buffer->cur != 'e')
{
if(bencode_read_string(r->buffer, &strbuf))
{
if(!r->on_key(r, &strbuf)) // check for early abort
return false;
}
}
if(*r->buffer->cur != 'e') // make sure we're at dictionary end
return false;
r->buffer->cur++;
return r->on_key(r, 0);
}
bool
bencode_read_list(llarp_buffer_t* buff, struct list_reader* r)
{
r->buffer = buff;
if(*r->buffer->cur != 'l') // ensure is a list
return false;
r->buffer->cur++;
while(llarp_buffer_size_left(*r->buffer) && *r->buffer->cur != 'e')
{
if(!r->on_item(r, true)) // check for early abort
return false;
}
if(*r->buffer->cur != 'e') // make sure we're at a list end
return false;
r->buffer->cur++;
return r->on_item(r, false);
}

@ -2,6 +2,7 @@
#include <signal.h>
#include <llarp.hpp>
#include "logger.hpp"
#include "router.hpp"
#if(__FreeBSD__)
#include <pthread_np.h>
@ -11,7 +12,7 @@ namespace llarp
{
Context::Context(std::ostream &stdout) : out(stdout)
{
llarp::Info(__FILE__, LLARP_VERSION, " ", LLARP_RELEASE_MOTTO);
llarp::Info(LLARP_VERSION, " ", LLARP_RELEASE_MOTTO);
}
Context::~Context()
@ -27,18 +28,18 @@ namespace llarp
bool
Context::ReloadConfig()
{
llarp::Info(__FILE__, "loading config at ", configfile);
llarp::Info("loading config at ", configfile);
if(!llarp_load_config(config, configfile.c_str()))
{
llarp_config_iterator iter;
iter.user = this;
iter.visit = &iter_config;
llarp_config_iter(config, &iter);
llarp::Info(__FILE__, "config loaded");
llarp::Info("config loaded");
return true;
}
llarp_free_config(&config);
llarp::Error(__FILE__, "failed to load config file ", configfile);
llarp::Error("failed to load config file ", configfile);
return false;
}
@ -76,7 +77,7 @@ namespace llarp
int
Context::Run()
{
llarp::Info(__FILE__, "starting up");
llarp::Info("starting up");
llarp_ev_loop_alloc(&mainloop);
llarp_crypto_libsodium_init(&crypto);
nodedb = llarp_nodedb_new(&crypto);
@ -95,6 +96,11 @@ namespace llarp
if(llarp_configure_router(router, config))
{
if(custom_dht_func)
{
llarp::Info("using custom dht function");
llarp_dht_set_msg_handler(router->dht, custom_dht_func);
}
llarp_run_router(router, nodedb);
// run net io thread
auto netio = mainloop;
@ -111,18 +117,18 @@ namespace llarp
"llarp-netio");
#endif
}
llarp::Info(__FILE__, "Ready");
llarp::Info("Ready");
llarp_logic_mainloop(logic);
return 0;
}
else
llarp::Error(__FILE__, "failed to start router");
llarp::Error("failed to start router");
}
else
llarp::Error(__FILE__, "Failed to initialize nodedb");
llarp::Error("Failed to initialize nodedb");
}
else
llarp::Error(__FILE__, "no nodedb defined");
llarp::Error("no nodedb defined");
return 1;
}
@ -131,12 +137,12 @@ namespace llarp
{
if(sig == SIGINT)
{
llarp::Info(__FILE__, "SIGINT");
llarp::Info("SIGINT");
SigINT();
}
if(sig == SIGHUP)
{
llarp::Info(__FILE__, "SIGHUP");
llarp::Info("SIGHUP");
ReloadConfig();
}
}
@ -150,55 +156,55 @@ namespace llarp
void
Context::Close()
{
llarp::Debug(__FILE__, "stop router");
llarp::Debug("stop router");
if(router)
llarp_stop_router(router);
llarp::Debug(__FILE__, "stop workers");
llarp::Debug("stop workers");
if(worker)
llarp_threadpool_stop(worker);
llarp::Debug(__FILE__, "join workers");
llarp::Debug("join workers");
if(worker)
llarp_threadpool_join(worker);
llarp::Debug(__FILE__, "stop logic");
llarp::Debug("stop logic");
if(logic)
llarp_logic_stop(logic);
llarp::Debug(__FILE__, "free config");
llarp::Debug("free config");
llarp_free_config(&config);
llarp::Debug(__FILE__, "free workers");
llarp::Debug("free workers");
llarp_free_threadpool(&worker);
llarp::Debug(__FILE__, "free nodedb");
llarp::Debug("free nodedb");
llarp_nodedb_free(&nodedb);
for(size_t i = 0; i < netio_threads.size(); ++i)
{
if(mainloop)
{
llarp::Debug(__FILE__, "stopping event loop thread ", i);
llarp::Debug("stopping event loop thread ", i);
llarp_ev_loop_stop(mainloop);
}
}
llarp::Debug(__FILE__, "free router");
llarp::Debug("free router");
llarp_free_router(&router);
llarp::Debug(__FILE__, "free logic");
llarp::Debug("free logic");
llarp_free_logic(&logic);
for(auto &t : netio_threads)
{
llarp::Debug(__FILE__, "join netio thread");
llarp::Debug("join netio thread");
t.join();
}
netio_threads.clear();
llarp::Debug(__FILE__, "free mainloop");
llarp::Debug("free mainloop");
llarp_ev_loop_free(&mainloop);
}
@ -234,6 +240,12 @@ llarp_main_init(const char *fname)
return m;
}
void
llarp_main_set_dht_handler(struct llarp_main *ptr, llarp_dht_msg_handler func)
{
ptr->ctx->custom_dht_func = func;
}
void
llarp_main_signal(struct llarp_main *ptr, int sig)
{

@ -2,11 +2,11 @@
#define LLARP_CRYPTO_HPP
#include <llarp/crypto.h>
#include <array>
#include <llarp/aligned.hpp>
namespace llarp
{
typedef std::array< uint8_t, sizeof(llarp_pubkey_t) > pubkey;
typedef AlignedBuffer< PUBKEYSIZE > pubkey;
struct pubkeyhash
{

@ -0,0 +1,572 @@
#include <llarp/bencode.h>
#include <llarp/dht.hpp>
#include <llarp/messages/dht_immediate.hpp>
#include "router.hpp"
#include <sodium.h>
#include <set>
namespace llarp
{
DHTImmeidateMessage::~DHTImmeidateMessage()
{
for(auto &msg : msgs)
delete msg;
msgs.clear();
}
bool
DHTImmeidateMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t *buf)
{
if(llarp_buffer_eq(key, "m"))
return llarp::dht::DecodeMesssageList(remote.data(), buf, msgs);
if(llarp_buffer_eq(key, "v"))
{
if(!bencode_read_integer(buf, &version))
return false;
return version == LLARP_PROTO_VERSION;
}
// bad key
return false;
}
bool
DHTImmeidateMessage::BEncode(llarp_buffer_t *buf) const
{
if(!bencode_start_dict(buf))
return false;
// message type
if(!bencode_write_bytestring(buf, "a", 1))
return false;
if(!bencode_write_bytestring(buf, "m", 1))
return false;
// dht messages
if(!bencode_write_bytestring(buf, "m", 1))
return false;
// begin list
if(!bencode_start_list(buf))
return false;
for(const auto &msg : msgs)
{
if(!msg->BEncode(buf))
return false;
}
// end list
if(!bencode_end(buf))
return false;
// protocol version
if(!bencode_write_version_entry(buf))
return false;
return bencode_end(buf);
}
bool
DHTImmeidateMessage::HandleMessage(llarp_router *router) const
{
DHTImmeidateMessage *reply = new DHTImmeidateMessage(remote);
bool result = true;
for(auto &msg : msgs)
{
result &= msg->HandleMessage(router, reply->msgs);
}
return result && router->SendToOrQueue(remote.data(), {reply});
}
namespace dht
{
GotRouterMessage::~GotRouterMessage()
{
for(auto &rc : R)
llarp_rc_free(&rc);
R.clear();
}
bool
GotRouterMessage::BEncode(llarp_buffer_t *buf) const
{
return false;
}
bool
GotRouterMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t *val)
{
return false;
}
bool
GotRouterMessage::HandleMessage(llarp_router *router,
std::vector< IMessage * > &replies) const
{
auto &dht = router->dht->impl;
auto pending = dht.FindPendingTX(From, txid);
if(pending)
{
if(R.size())
pending->Completed(&R[0]);
else
pending->Completed(nullptr);
dht.RemovePendingLookup(From, txid);
return true;
}
llarp::Warn("Got response for DHT transaction we are not tracking, txid=",
txid);
return false;
}
FindRouterMessage::~FindRouterMessage()
{
}
bool
FindRouterMessage::BEncode(llarp_buffer_t *buf) const
{
if(!bencode_start_dict(buf))
return false;
// message type
if(!bencode_write_bytestring(buf, "A", 1))
return false;
if(!bencode_write_bytestring(buf, "R", 1))
return false;
// key
if(!bencode_write_bytestring(buf, "K", 1))
return false;
if(!bencode_write_bytestring(buf, K.data(), K.size()))
return false;
// txid
if(!bencode_write_bytestring(buf, "T", 1))
return false;
if(!bencode_write_uint64(buf, txid))
return false;
// version
if(!bencode_write_bytestring(buf, "V", 1))
return false;
if(!bencode_write_uint64(buf, version))
return false;
return bencode_end(buf);
}
bool
FindRouterMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t *val)
{
llarp_buffer_t strbuf;
if(llarp_buffer_eq(key, "K"))
{
if(!bencode_read_string(val, &strbuf))
return false;
if(strbuf.sz != K.size())
return false;
memcpy(K.data(), strbuf.base, K.size());
return true;
}
if(llarp_buffer_eq(key, "T"))
{
return bencode_read_integer(val, &txid);
}
if(llarp_buffer_eq(key, "V"))
{
return bencode_read_integer(val, &version);
}
return false;
}
bool
FindRouterMessage::HandleMessage(llarp_router *router,
std::vector< IMessage * > &replies) const
{
auto &dht = router->dht->impl;
auto pending = dht.FindPendingTX(From, txid);
if(pending)
{
llarp::Warn("Got duplicate DHT lookup from ", From, " txid=", txid);
return false;
}
dht.LookupRouterRelayed(From, txid, K, replies);
return true;
}
struct MessageDecoder
{
const Key_t &From;
bool firstKey = true;
IMessage *msg = nullptr;
MessageDecoder(const Key_t &from) : From(from)
{
}
static bool
on_key(dict_reader *r, llarp_buffer_t *key)
{
llarp_buffer_t strbuf;
MessageDecoder *dec = static_cast< MessageDecoder * >(r->user);
// check for empty dict
if(!key)
return !dec->firstKey;
// first key
if(dec->firstKey)
{
if(!llarp_buffer_eq(*key, "A"))
return false;
if(!bencode_read_string(r->buffer, &strbuf))
return false;
// bad msg size?
if(strbuf.sz != 1)
return false;
switch(*strbuf.base)
{
case 'R':
dec->msg = new FindRouterMessage(dec->From);
break;
case 'S':
dec->msg = new GotRouterMessage(dec->From);
break;
default:
llarp::Warn("unknown dht message type: ", (char)*strbuf.base);
// bad msg type
return false;
}
dec->firstKey = false;
return true;
}
else
return dec->msg->DecodeKey(*key, r->buffer);
}
};
IMessage *
DecodeMesssage(const Key_t &from, llarp_buffer_t *buf)
{
MessageDecoder dec(from);
dict_reader r;
r.user = &dec;
r.on_key = &MessageDecoder::on_key;
if(bencode_read_dict(buf, &r))
return dec.msg;
else
{
if(dec.msg)
delete dec.msg;
return nullptr;
}
}
struct ListDecoder
{
ListDecoder(const Key_t &from, std::vector< IMessage * > &list)
: From(from), l(list){};
const Key_t &From;
std::vector< IMessage * > &l;
static bool
on_item(list_reader *r, bool has)
{
ListDecoder *dec = static_cast< ListDecoder * >(r->user);
if(!has)
return true;
auto msg = DecodeMesssage(dec->From, r->buffer);
if(msg)
{
dec->l.push_back(msg);
return true;
}
else
return false;
}
};
bool
DecodeMesssageList(const Key_t &from, llarp_buffer_t *buf,
std::vector< IMessage * > &list)
{
ListDecoder dec(from, list);
list_reader r;
r.user = &dec;
r.on_item = &ListDecoder::on_item;
return bencode_read_list(buf, &r);
}
SearchJob::SearchJob()
{
started = 0;
requestor.Zero();
target.Zero();
}
SearchJob::SearchJob(const Key_t &asker, const Key_t &key,
llarp_router_lookup_job *j)
: started(llarp_time_now_ms()), requestor(asker), target(key), job(j)
{
}
void
SearchJob::Completed(const llarp_rc *router, bool timeout) const
{
if(job && job->hook)
{
if(router)
{
job->found = true;
llarp_rc_copy(&job->result, router);
}
job->hook(job);
}
}
bool
SearchJob::IsExpired(llarp_time_t now) const
{
return now - started >= JobTimeout;
}
bool
Bucket::FindClosest(const Key_t &target, Key_t &result) const
{
auto itr = nodes.lower_bound(target);
if(itr == nodes.end())
return false;
result = itr->second.ID;
return true;
}
bool
Bucket::FindCloseExcluding(const Key_t &target, Key_t &result,
const Key_t &exclude) const
{
auto itr = nodes.lower_bound(target);
if(itr == nodes.end())
return false;
if(itr->second.ID == exclude)
++itr;
if(itr == nodes.end())
return false;
result = itr->second.ID;
return true;
}
Context::Context()
{
randombytes((byte_t *)&ids, sizeof(uint64_t));
}
Context::~Context()
{
if(nodes)
delete nodes;
}
void
Context::handle_cleaner_timer(void *u, uint64_t orig, uint64_t left)
{
if(left)
return;
Context *ctx = static_cast< Context * >(u);
ctx->CleanupTX();
}
void
Context::LookupRouterRelayed(const Key_t &requester, uint64_t txid,
const Key_t &target,
std::vector< IMessage * > &replies)
{
if(target == ourKey)
{
// we are the target, give them our RC
replies.push_back(new GotRouterMessage(requester, txid, &router->rc));
return;
}
Key_t next = ourKey;
nodes->FindClosest(target, next);
if(next == ourKey)
{
// we are closest and don't have a match
replies.push_back(new GotRouterMessage(requester, txid, nullptr));
return;
}
if(next == target)
{
// we know it
replies.push_back(
new GotRouterMessage(requester, txid, nodes->nodes[target].rc));
return;
}
// ask neighbor
LookupRouter(target, requester, next);
}
void
Context::RemovePendingLookup(const Key_t &owner, uint64_t id)
{
auto itr = pendingTX.find({owner, id});
if(itr == pendingTX.end())
return;
pendingTX.erase(itr);
}
SearchJob *
Context::FindPendingTX(const Key_t &owner, uint64_t id)
{
auto itr = pendingTX.find({owner, id});
if(itr == pendingTX.end())
return nullptr;
else
return &itr->second;
}
void
Context::CleanupTX()
{
auto now = llarp_time_now_ms();
std::set< TXOwner > expired;
for(auto &item : pendingTX)
if(item.second.IsExpired(now))
expired.insert(item.first);
for(const auto &e : expired)
{
pendingTX[e].Completed(nullptr, true);
RemovePendingLookup(e.requester, e.txid);
if(e.requester != ourKey)
{
// inform not found
auto msg = new llarp::DHTImmeidateMessage(e.requester);
msg->msgs.push_back(
new GotRouterMessage(e.requester, e.txid, nullptr));
router->SendToOrQueue(e.requester, {msg});
}
}
ScheduleCleanupTimer();
}
void
Context::Init(const Key_t &us, llarp_router *r)
{
router = r;
ourKey = us;
nodes = new Bucket(ourKey);
llarp::Debug("intialize dht with key ", ourKey);
}
void
Context::ScheduleCleanupTimer()
{
llarp_logic_call_later(router->logic,
{1000, this, &handle_cleaner_timer});
}
void
Context::LookupRouter(const Key_t &target, const Key_t &whoasked,
const Key_t &askpeer, llarp_router_lookup_job *job)
{
auto id = ++ids;
pendingTX[{whoasked, id}] = SearchJob(whoasked, target, job);
llarp::Info("Asking ", askpeer, " for router ", target, " for ",
whoasked);
auto msg = new llarp::DHTImmeidateMessage(askpeer);
msg->msgs.push_back(new FindRouterMessage(askpeer, target, id));
router->SendToOrQueue(askpeer, {msg});
}
void
Context::LookupRouterViaJob(llarp_router_lookup_job *job)
{
Key_t peer;
if(nodes->FindCloseExcluding(job->target, peer, ourKey))
LookupRouter(job->target, ourKey, peer, job);
else if(job->hook)
{
job->found = false;
job->hook(job);
}
}
void
Context::queue_router_lookup(void *user)
{
llarp_router_lookup_job *job =
static_cast< llarp_router_lookup_job * >(user);
job->dht->impl.LookupRouterViaJob(job);
}
}
}
llarp_dht_context::llarp_dht_context(llarp_router *router)
{
parent = router;
}
extern "C" {
struct llarp_dht_context *
llarp_dht_context_new(struct llarp_router *router)
{
return new llarp_dht_context(router);
}
void
llarp_dht_context_free(struct llarp_dht_context *ctx)
{
delete ctx;
}
void
llarp_dht_put_local_router(struct llarp_dht_context *ctx, struct llarp_rc *rc)
{
llarp::dht::Key_t k = rc->pubkey;
llarp::Debug("put router at ", k);
ctx->impl.nodes->nodes[k] = rc;
}
void
llarp_dht_remove_local_router(struct llarp_dht_context *ctx, const byte_t *id)
{
auto &nodes = ctx->impl.nodes->nodes;
auto itr = nodes.find(id);
if(itr == nodes.end())
return;
nodes.erase(itr);
}
void
llarp_dht_set_msg_handler(struct llarp_dht_context *ctx,
llarp_dht_msg_handler handler)
{
ctx->impl.custom_handler = handler;
}
void
llarp_dht_context_start(struct llarp_dht_context *ctx, const byte_t *key)
{
ctx->impl.Init(key, ctx->parent);
}
void
llarp_dh_lookup_router(struct llarp_dht_context *ctx,
struct llarp_router_lookup_job *job)
{
job->dht = ctx;
llarp_logic_queue_job(ctx->parent->logic,
{job, &llarp::dht::Context::queue_router_lookup});
}
}

@ -50,10 +50,11 @@ namespace llarp
default:
return -1;
}
llarp::Debug(__FILE__, "send ", sz, " bytes");
ssize_t sent = ::sendto(fd, data, sz, SOCK_NONBLOCK, to, slen);
if(sent == -1)
perror("sendto()");
{
llarp::Warn(strerror(errno));
}
return sent;
}
};
@ -116,7 +117,7 @@ struct llarp_epoll_loop : public llarp_ev_loop
// handle signalfd
if(events[idx].data.fd == pipefds[0])
{
llarp::Debug(__FILE__, "exiting epoll loop");
llarp::Debug("exiting epoll loop");
return 0;
}
llarp::ev_io* ev = static_cast< llarp::ev_io* >(events[idx].data.ptr);
@ -124,7 +125,7 @@ struct llarp_epoll_loop : public llarp_ev_loop
{
if(ev->read(readbuf, sizeof(readbuf)) == -1)
{
llarp::Debug(__FILE__, "close ev");
llarp::Debug("close ev");
close_ev(ev);
}
}
@ -173,7 +174,7 @@ struct llarp_epoll_loop : public llarp_ev_loop
}
}
llarp::Addr a(*addr);
llarp::Debug(__FILE__, "bind to ", a.to_string());
llarp::Debug("bind to ", a);
if(bind(fd, addr, slen) == -1)
{
perror("bind()");

@ -106,7 +106,7 @@ llarp_xi_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
// address
if(llarp_buffer_eq(*key, "a"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz >= sizeof(tmp))
return false;
@ -116,7 +116,7 @@ llarp_xi_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
if(llarp_buffer_eq(*key, "b"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz >= sizeof(tmp))
return false;
@ -126,7 +126,7 @@ llarp_xi_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
if(llarp_buffer_eq(*key, "k"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != sizeof(llarp_pubkey_t))
return false;
@ -136,7 +136,7 @@ llarp_xi_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
if(llarp_buffer_eq(*key, "v"))
{
if(!bdecode_read_integer(r->buffer, &v))
if(!bencode_read_integer(r->buffer, &v))
return false;
return v == LLARP_PROTO_VERSION;
}
@ -148,7 +148,7 @@ bool
llarp_xi_bdecode(struct llarp_xi *xi, llarp_buffer_t *buf)
{
struct dict_reader r = {buf, xi, &llarp_xi_decode_dict};
return bdecode_read_dict(buf, &r);
return bencode_read_dict(buf, &r);
}
void
@ -187,6 +187,6 @@ bool
llarp_xi_list_bdecode(struct llarp_xi_list *l, llarp_buffer_t *buff)
{
list_reader r = {buff, l, &llarp_xi_list_decode_item};
return bdecode_read_list(buff, &r);
return bencode_read_list(buff, &r);
}
}

@ -6,6 +6,7 @@
#include <sodium/crypto_sign_ed25519.h>
#include <algorithm>
#include <bitset>
#include <cassert>
#include <fstream>
@ -408,7 +409,7 @@ namespace iwp
void
push_ackfor(uint64_t id, uint32_t bitmask)
{
llarp::Debug(__FILE__, "ACK for msgid=", id, " mask=", bitmask);
llarp::Debug("ACK for msgid=", id, " mask=", bitmask);
sendqueue.emplace();
auto &buf = sendqueue.back();
// TODO: set flags to nonzero as needed
@ -424,8 +425,7 @@ namespace iwp
if(hdr.size() > sz)
{
// overflow
llarp::Warn(__FILE__, "invalid XMIT frame size ", hdr.size(), " > ",
sz);
llarp::Warn("invalid XMIT frame size ", hdr.size(), " > ", sz);
return false;
}
sz = hdr.size();
@ -438,7 +438,7 @@ namespace iwp
if(sz - bufsz < x.lastfrag())
{
// bad size of last fragment
llarp::Warn(__FILE__, "XMIT frag size missmatch ", sz - bufsz, " < ",
llarp::Warn("XMIT frag size missmatch ", sz - bufsz, " < ",
x.lastfrag());
return false;
}
@ -461,10 +461,10 @@ namespace iwp
return true;
}
else
llarp::Warn(__FILE__, "duplicate XMIT msgid=", x.msgid());
llarp::Warn("duplicate XMIT msgid=", x.msgid());
}
else
llarp::Warn(__FILE__, "LSB not set on flags");
llarp::Warn("LSB not set on flags");
return false;
}
@ -480,8 +480,7 @@ namespace iwp
if(hdr.size() > sz)
{
// overflow
llarp::Warn(__FILE__, "invalid FRAG frame size ", hdr.size(), " > ",
sz);
llarp::Warn("invalid FRAG frame size ", hdr.size(), " > ", sz);
return false;
}
sz = hdr.size();
@ -489,7 +488,7 @@ namespace iwp
if(sz <= 9)
{
// underflow
llarp::Warn(__FILE__, "invalid FRAG frame size ", sz, " <= 9");
llarp::Warn("invalid FRAG frame size ", sz, " <= 9");
return false;
}
@ -503,20 +502,18 @@ namespace iwp
auto itr = rx.find(msgid);
if(itr == rx.end())
{
llarp::Warn(__FILE__, "no such RX fragment, msgid=", msgid);
llarp::Warn("no such RX fragment, msgid=", msgid);
return false;
}
auto fragsize = itr->second.msginfo.fragsize();
if(fragsize != sz - 9)
{
llarp::Warn(__FILE__, "RX fragment size missmatch ", fragsize,
" != ", sz - 9);
llarp::Warn("RX fragment size missmatch ", fragsize, " != ", sz - 9);
return false;
}
if(!itr->second.put_frag(fragno, hdr.data() + 9))
{
llarp::Warn(__FILE__,
"inbound message does not have fragment msgid=", msgid,
llarp::Warn("inbound message does not have fragment msgid=", msgid,
" fragno=", (int)fragno);
return false;
}
@ -735,7 +732,7 @@ namespace iwp
{
// verify fail
// TODO: remove session?
llarp::Warn(__FILE__, "session start verify failed");
llarp::Warn("session start verify failed");
return;
}
self->send_LIM();
@ -744,7 +741,7 @@ namespace iwp
void
send_LIM()
{
llarp::Debug(__FILE__, "send LIM");
llarp::Debug("send LIM");
llarp_shorthash_t digest;
// 64 bytes overhead for link message
byte_t tmp[MAX_RC_SIZE + 64];
@ -766,7 +763,7 @@ namespace iwp
EnterState(eLIMSent);
}
else
llarp::Error(__FILE__, "LIM Encode failed");
llarp::Error("LIM Encode failed");
}
static void
@ -881,7 +878,7 @@ namespace iwp
if(introack->buf == nullptr)
{
// invalid signature
llarp::Error(__FILE__, "introack verify failed");
llarp::Error("introack verify failed");
return;
}
link->EnterState(eIntroAckRecv);
@ -930,10 +927,10 @@ namespace iwp
self->pump();
}
else
llarp::Error(__FILE__, "invalid frame");
llarp::Error("invalid frame");
}
else
llarp::Error(__FILE__, "decrypt frame fail");
llarp::Error("decrypt frame fail");
delete frame;
--self->frames;
@ -949,7 +946,7 @@ namespace iwp
iwp_call_async_frame_decrypt(iwp, frame);
}
else
llarp::Warn(__FILE__, "short packet of ", sz, " bytes");
llarp::Warn("short packet of ", sz, " bytes");
}
static void
@ -994,7 +991,7 @@ namespace iwp
session *self = static_cast< session * >(intro->user);
if(!intro->buf)
{
llarp::Error(__FILE__, "intro verify failed");
llarp::Error("intro verify failed");
delete self;
return;
}
@ -1037,7 +1034,7 @@ namespace iwp
if(sz >= sizeof(workbuf))
{
// too big?
llarp::Error(__FILE__, "intro too big");
llarp::Error("intro too big");
// TOOD: session destroy ?
return;
}
@ -1066,7 +1063,7 @@ namespace iwp
if(sz >= sizeof(workbuf))
{
// too big?
llarp::Error(__FILE__, "introack too big");
llarp::Error("introack too big");
// TOOD: session destroy ?
return;
}
@ -1091,17 +1088,17 @@ namespace iwp
session *link = static_cast< session * >(i->user);
if(i->buf)
{
llarp::Debug(__FILE__, "send intro");
llarp::Debug("send intro");
if(llarp_ev_udp_sendto(link->udp, link->addr, i->buf, i->sz) == -1)
{
llarp::Warn(__FILE__, "send intro failed");
llarp::Warn("send intro failed");
return;
}
link->EnterState(eIntroSent);
}
else
{
llarp::Warn(__FILE__, "failed to generate intro");
llarp::Warn("failed to generate intro");
}
}
@ -1167,6 +1164,12 @@ namespace iwp
LinkMap_t m_sessions;
mtx_t m_sessions_Mutex;
typedef std::unordered_map< llarp::pubkey, llarp::Addr, llarp::pubkeyhash >
SessionMap_t;
SessionMap_t m_Connected;
mtx_t m_Connected_Mutex;
llarp_seckey_t seckey;
server(llarp_router *r, llarp_crypto *c, llarp_logic *l,
@ -1183,6 +1186,59 @@ namespace iwp
llarp_async_iwp_free(iwp);
}
// set that src address has identity pubkey
void
MapAddr(const llarp::Addr &src, llarp::pubkey identity)
{
lock_t lock(m_Connected_Mutex);
m_Connected[identity] = src;
}
static bool
HasSessionToRouter(llarp_link *l, const byte_t *pubkey)
{
server *serv = static_cast< server * >(l->impl);
lock_t lock(serv->m_Connected_Mutex);
return serv->m_Connected.find(pubkey) != serv->m_Connected.end();
}
static bool
SendToSession(llarp_link *l, const byte_t *pubkey, llarp_buffer_t buf)
{
server *serv = static_cast< server * >(l->impl);
{
lock_t lock(serv->m_Connected_Mutex);
auto itr = serv->m_Connected.find(pubkey);
if(itr != serv->m_Connected.end())
{
lock_t innerlock(serv->m_sessions_Mutex);
auto inner_itr = serv->m_sessions.find(itr->second);
if(inner_itr != serv->m_sessions.end())
{
auto link = &inner_itr->second;
return link->sendto(link, buf);
}
}
}
return false;
}
void
UnmapAddr(const llarp::Addr &src)
{
lock_t lock(m_Connected_Mutex);
auto itr = std::find_if(
m_Connected.begin(), m_Connected.end(),
[src](const auto &item) -> bool { return src == item.second; });
if(itr == std::end(m_Connected))
return;
// remove from dht tracking
llarp_dht_remove_local_router(router->dht, itr->first);
m_Connected.erase(itr);
}
session *
create_session(const llarp::Addr &src, const byte_t *seckey)
{
@ -1261,8 +1317,8 @@ namespace iwp
auto itr = m_sessions.find(addr);
if(itr != m_sessions.end())
{
llarp::Debug(__FILE__, "session with ", addr.to_string(),
" is stale, removing");
llarp::Debug("session with ", addr, " is stale, removing");
UnmapAddr(addr);
session *s = static_cast< session * >(itr->second.impl);
m_sessions.erase(itr);
if(s->keepalive_timer_id)
@ -1284,7 +1340,7 @@ namespace iwp
}
if(s->frames)
{
llarp::Warn(__FILE__, "session has ", s->frames,
llarp::Warn("session has ", s->frames,
" left but is idle, not deallocating session so we "
"leak but don't die");
}
@ -1304,7 +1360,7 @@ namespace iwp
bool
ensure_privkey()
{
llarp::Debug(__FILE__, "ensure transport private key at ", keyfile);
llarp::Debug("ensure transport private key at ", keyfile);
std::error_code ec;
if(!fs::exists(keyfile, ec))
{
@ -1324,7 +1380,7 @@ namespace iwp
keygen(const char *fname)
{
crypto->encryption_keygen(seckey);
llarp::Info(__FILE__, "new transport key generated");
llarp::Info("new transport key generated");
std::ofstream f(fname);
if(f.is_open())
{
@ -1394,16 +1450,20 @@ namespace iwp
{
alive();
session *impl = static_cast< session * >(parent->impl);
if(id == 0 && impl->state == session::eSessionStartSent)
if(id == 0)
{
// send our LIM
impl->send_LIM();
// send our LIM if we are an outbound session
if(impl->state == session::eSessionStartSent)
{
impl->send_LIM();
}
impl->serv->MapAddr(impl->addr, impl->remote_router.pubkey);
}
}
}
else
{
llarp::Warn(__FILE__, "failed to reassemble message ", id);
llarp::Warn("failed to reassemble message ", id);
}
rx.erase(id);
return success;
@ -1414,13 +1474,13 @@ namespace iwp
{
if(hdr.size() > sz)
{
llarp::Error(__FILE__, "invalid ACKS frame size ", hdr.size(), " > ", sz);
llarp::Error("invalid ACKS frame size ", hdr.size(), " > ", sz);
return false;
}
sz = hdr.size();
if(sz < 12)
{
llarp::Error(__FILE__, "invalid ACKS frame size ", sz, " < 12");
llarp::Error("invalid ACKS frame size ", sz, " < 12");
return false;
}
@ -1433,7 +1493,7 @@ namespace iwp
auto itr = tx.find(msgid);
if(itr == tx.end())
{
llarp::Error(__FILE__, "ACK for missing TX frame msgid=", msgid);
llarp::Error("ACK for missing TX frame msgid=", msgid);
return false;
}
@ -1443,7 +1503,7 @@ namespace iwp
if(itr->second->completed())
{
llarp::Debug(__FILE__, "message transmitted msgid=", msgid);
llarp::Debug("message transmitted msgid=", msgid);
delete itr->second;
tx.erase(itr);
session *impl = static_cast< session * >(parent->impl);
@ -1455,7 +1515,7 @@ namespace iwp
}
else
{
llarp::Debug(__FILE__, "message ", msgid, " retransmit fragments");
llarp::Debug("message ", msgid, " retransmit fragments");
itr->second->retransmit_frags(sendqueue);
}
@ -1498,12 +1558,11 @@ namespace iwp
if(!link->ensure_privkey())
{
llarp::Error(__FILE__, "failed to ensure private key");
llarp::Error("failed to ensure private key");
return false;
}
llarp::Debug(__FILE__, "configure link ifname=", ifname, " af=", af,
" port=", port);
llarp::Debug("configure link ifname=", ifname, " af=", af, " port=", port);
// bind
sockaddr_in ip4addr;
sockaddr_in6 ip6addr;
@ -1529,8 +1588,7 @@ namespace iwp
{
if(!llarp_getifaddr(ifname, af, addr))
{
llarp::Error(__FILE__, "failed to get address of network interface ",
ifname);
llarp::Error("failed to get address of network interface ", ifname);
return false;
}
}
@ -1552,10 +1610,10 @@ namespace iwp
link->netloop = netloop;
link->udp.recvfrom = &server::handle_recvfrom;
link->udp.user = link;
llarp::Debug(__FILE__, "bind IWP link to ", link->addr.to_string());
llarp::Debug("bind IWP link to ", link->addr);
if(llarp_ev_add_udp(link->netloop, &link->udp, link->addr) == -1)
{
llarp::Error(__FILE__, "failed to bind to ", link->addr.to_string());
llarp::Error("failed to bind to ", link->addr);
return false;
}
return true;
@ -1601,7 +1659,7 @@ namespace iwp
server *link = static_cast< server * >(l->impl);
{
llarp::Addr dst(job->ai);
llarp::Debug(__FILE__, "establish session to ", dst.to_string());
llarp::Debug("establish session to ", dst);
session *s = link->find_session(dst);
if(s == nullptr)
{
@ -1662,24 +1720,24 @@ namespace iwp
if(link->serv->has_session_to(link->addr))
{
// duplicate session
llarp::Warn(__FILE__, "duplicate session to ", link->addr.to_string());
llarp::Warn("duplicate session to ", link->addr);
delete link;
return;
}
link->serv->put_session(link->addr, link);
llarp::Debug(__FILE__, "send introack");
llarp::Debug("send introack");
if(llarp_ev_udp_sendto(link->udp, link->addr, i->buf, i->sz) == -1)
{
llarp::Warn(__FILE__, "sendto failed");
llarp::Warn("sendto failed");
return;
}
llarp::Debug(__FILE__, "sent");
llarp::Debug("sent");
link->EnterState(eIntroAckSent);
}
else
{
// failed to generate?
llarp::Warn(__FILE__, "failed to generate introack");
llarp::Warn("failed to generate introack");
delete link;
}
}
@ -1699,6 +1757,8 @@ iwp_link_init(struct llarp_link *link, struct llarp_iwp_args args)
link->stop_link = iwp::link_stop;
link->iter_sessions = iwp::link_iter_sessions;
link->try_establish = iwp::link_try_establish;
link->has_session_to = iwp::server::HasSessionToRouter;
link->sendto = iwp::server::SendToSession;
link->mark_session_active = iwp::link_mark_session_active;
link->free_impl = iwp::link_free;
}

@ -5,8 +5,8 @@ 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;
&& link->iter_sessions && link->try_establish && link->sendto
&& link->has_session_to && link->mark_session_active && link->free_impl;
}
bool

@ -0,0 +1,77 @@
#include <llarp/bencode.h>
#include <llarp/router_contact.h>
#include <llarp/messages/link_intro.hpp>
#include "logger.hpp"
namespace llarp
{
LinkIntroMessage::~LinkIntroMessage()
{
}
bool
LinkIntroMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf)
{
if(llarp_buffer_eq(key, "r"))
{
if(!llarp_rc_bdecode(RC, buf))
{
llarp::Warn("failed to decode RC");
return false;
}
remote = (byte_t*)RC->pubkey;
llarp::Debug("decoded RC from ", remote);
return true;
}
else if(llarp_buffer_eq(key, "v"))
{
if(!bencode_read_integer(buf, &version))
return false;
if(version != LLARP_PROTO_VERSION)
{
llarp::Warn("llarp protocol version missmatch ", version,
" != ", LLARP_PROTO_VERSION);
return false;
}
llarp::Debug("LIM version ", version);
return true;
}
else
{
llarp::Warn("invalid LIM key: ", *key.cur);
return false;
}
}
bool
LinkIntroMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!bencode_write_bytestring(buf, "a", 1))
return false;
if(!bencode_write_bytestring(buf, "i", 1))
return false;
if(RC)
{
if(!bencode_write_bytestring(buf, "r", 1))
return false;
if(!llarp_rc_bencode(RC, buf))
return false;
}
if(!bencode_write_version_entry(buf))
return false;
return bencode_end(buf);
}
bool
LinkIntroMessage::HandleMessage(llarp_router* router) const
{
llarp::Info("got LIM from ", remote);
return true;
}
}

@ -1,12 +1,19 @@
#include <llarp/router_contact.h>
#include <llarp/link_message.hpp>
#include <llarp/messages/dht_immediate.hpp>
#include <llarp/messages/link_intro.hpp>
#include <llarp/messages/relay_commit.hpp>
#include "buffer.hpp"
#include "logger.hpp"
#include "router.hpp"
namespace llarp
{
InboundMessageHandler::InboundMessageHandler(llarp_router* _router)
ILinkMessage::ILinkMessage(const RouterID& id) : remote(id)
{
}
InboundMessageParser::InboundMessageParser(llarp_router* _router)
: router(_router)
{
reader.user = this;
@ -14,10 +21,10 @@ namespace llarp
}
bool
InboundMessageHandler::OnKey(dict_reader* r, llarp_buffer_t* key)
InboundMessageParser::OnKey(dict_reader* r, llarp_buffer_t* key)
{
InboundMessageHandler* handler =
static_cast< InboundMessageHandler* >(r->user);
InboundMessageParser* handler =
static_cast< InboundMessageParser* >(r->user);
llarp_buffer_t strbuf;
// we are reading the first key
@ -33,7 +40,7 @@ namespace llarp
return false;
}
if(!bdecode_read_string(r->buffer, &strbuf))
if(!bencode_read_string(r->buffer, &strbuf))
{
llarp::Warn(__FILE__, "could not read value of message type");
return false;
@ -44,106 +51,56 @@ namespace llarp
llarp::Warn(__FILE__, "bad mesage type size: ", strbuf.sz);
return false;
}
handler->msgtype = *strbuf.cur;
switch(*strbuf.cur)
{
case 'i':
handler->msg = new LinkIntroMessage(
handler->from->get_remote_router(handler->from));
break;
case 'm':
handler->msg = new DHTImmeidateMessage(handler->GetCurrentFrom());
break;
case 'c':
handler->msg = new LR_CommitMessage(handler->GetCurrentFrom());
break;
default:
return false;
}
handler->firstkey = false;
return true;
return handler->msg != nullptr;
}
// check for last element
if(!key)
return handler->MessageDone();
switch(handler->msgtype)
{
// link introduce
case 'i':
return handler->DecodeLIM(*key, r->buffer);
// immidate dht
case 'd':
return handler->DecodeDHT(*key, r->buffer);
// relay commit
case 'c':
return handler->DecodeLRCM(*key, r->buffer);
// unknown message type
default:
return false;
}
}
bool
InboundMessageHandler::DecodeLIM(llarp_buffer_t key, llarp_buffer_t* buff)
{
if(llarp_buffer_eq(key, "r"))
{
if(!llarp_rc_bdecode(from->get_remote_router(from), buff))
{
llarp::Warn(__FILE__, "failed to decode RC");
return false;
}
return true;
}
else if(llarp_buffer_eq(key, "v"))
{
if(!bdecode_read_integer(buff, &proto))
return false;
if(proto != LLARP_PROTO_VERSION)
{
llarp::Warn(__FILE__, "llarp protocol version missmatch ", proto);
return false;
}
return true;
}
else
{
llarp::Warn(__FILE__, "invalid LIM key: ", *key.cur);
return false;
}
}
bool
InboundMessageHandler::DecodeDHT(llarp_buffer_t key, llarp_buffer_t* buf)
{
return false;
return handler->msg->DecodeKey(*key, r->buffer);
}
bool
InboundMessageHandler::DecodeLRCM(llarp_buffer_t key, llarp_buffer_t* buf)
RouterID
InboundMessageParser::GetCurrentFrom()
{
return false;
auto rc = from->get_remote_router(from);
return rc->pubkey;
}
bool
InboundMessageHandler::MessageDone()
InboundMessageParser::MessageDone()
{
switch(msgtype)
bool result = false;
if(msg)
{
case 'c':
return router->ProcessLRCM(lrcm);
default:
return true;
result = msg->HandleMessage(router);
delete msg;
msg = nullptr;
}
return result;
}
bool
InboundMessageHandler::ProcessFrom(llarp_link_session* src,
llarp_buffer_t buf)
InboundMessageParser::ProcessFrom(llarp_link_session* src, llarp_buffer_t buf)
{
from = src;
msgtype = 0;
firstkey = true;
return bdecode_read_dict(&buf, &reader);
}
bool
InboundMessageHandler::FlushReplies()
{
bool success = true;
while(sendq.size())
{
auto& msg = sendq.front();
auto buf = llarp::Buffer< decltype(msg) >(msg);
success &= from->sendto(from, buf);
sendq.pop();
}
return success;
return bencode_read_dict(&buf, &reader);
}
}

@ -36,7 +36,7 @@ llarp_free_logic(struct llarp_logic** logic)
void
llarp_logic_stop(struct llarp_logic* logic)
{
llarp::Debug(__FILE__, "logic thread stop");
llarp::Debug("logic thread stop");
if(logic->thread)
{
llarp_threadpool_stop(logic->thread);
@ -44,7 +44,7 @@ llarp_logic_stop(struct llarp_logic* logic)
}
llarp_free_threadpool(&logic->thread);
llarp::Debug(__FILE__, "logic timer stop");
llarp::Debug("logic timer stop");
if(logic->timer)
llarp_timer_stop(logic->timer);
}

@ -2,7 +2,7 @@
#define LLARP_NET_HPP
#include <llarp/address_info.h>
#include <llarp/net.h>
#include <string>
#include <iostream>
#include "mem.hpp"
bool
@ -103,32 +103,31 @@ namespace llarp
}
}
std::string
to_string() const
friend std::ostream&
operator<<(std::ostream& out, const Addr& a)
{
std::string str;
char tmp[128];
char tmp[128] = {0};
socklen_t sz;
const void* ptr = nullptr;
if(af() == AF_INET6)
if(a.af() == AF_INET6)
{
str += "[";
out << "[";
sz = sizeof(sockaddr_in6);
ptr = addr6();
ptr = a.addr6();
}
else
{
sz = sizeof(sockaddr_in);
ptr = addr4();
ptr = a.addr4();
}
if(inet_ntop(af(), ptr, tmp, sz))
if(inet_ntop(a.af(), ptr, tmp, sz))
{
str += tmp;
if(af() == AF_INET6)
str += "]";
out << tmp;
if(a.af() == AF_INET6)
out << "]";
}
return str + ":" + std::to_string(port());
return out << ":" << a.port();
}
operator const sockaddr*() const

@ -346,4 +346,11 @@ llarp_nodedb_async_verify(struct llarp_nodedb *nodedb,
// queue the crypto check
llarp_threadpool_queue_job(cryptoworker, { job, &verify_rc });
}
bool
llarp_nodedb_find_rc(struct llarp_nodedb *nodedb, struct llarp_rc *dst,
llarp_pubkey_t k)
{
return false;
}
}

@ -0,0 +1,29 @@
#include <llarp/messages/relay_commit.hpp>
namespace llarp
{
LR_CommitMessage::~LR_CommitMessage()
{
}
bool
LR_CommitMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf)
{
// TODO: implement
return false;
}
bool
LR_CommitMessage::BEncode(llarp_buffer_t* buf) const
{
// TODO: implement
return false;
}
bool
LR_CommitMessage::HandleMessage(llarp_router* router) const
{
// TODO: implement
return false;
}
}

@ -27,13 +27,15 @@ namespace llarp
} // namespace llarp
llarp_router::llarp_router() : ready(false), inbound_msg_handler(this)
llarp_router::llarp_router()
: ready(false), dht(llarp_dht_context_new(this)), inbound_msg_parser(this)
{
llarp_rc_clear(&rc);
}
llarp_router::~llarp_router()
{
llarp_dht_context_free(dht);
llarp_rc_free(&rc);
}
@ -41,18 +43,53 @@ bool
llarp_router::HandleRecvLinkMessage(llarp_link_session *session,
llarp_buffer_t buf)
{
if(inbound_msg_handler.ProcessFrom(session, buf))
{
return inbound_msg_handler.FlushReplies();
}
else
return false;
return inbound_msg_parser.ProcessFrom(session, buf);
}
bool
llarp_router::ProcessLRCM(llarp::LR_CommitMessage msg)
llarp_router::SendToOrQueue(const llarp::RouterID &remote,
std::vector< llarp::ILinkMessage * > msgs)
{
return false;
bool has = false;
for(auto &link : links)
has |= link->has_session_to(link, remote);
if(!has)
{
llarp_rc rc;
llarp_rc_clear(&rc);
llarp_pubkey_t k;
memcpy(k, remote, sizeof(llarp_pubkey_t));
if(!llarp_nodedb_find_rc(nodedb, &rc, k))
{
llarp::Warn("cannot find router ", remote, " locally so we are dropping ",
msgs.size(), " messages to them");
for(auto &msg : msgs)
delete msg;
msgs.clear();
return false;
}
for(const auto &msg : msgs)
{
// this will create an entry in the obmq if it's not already there
outboundMesssageQueue[remote].push(msg);
}
// queued
llarp_router_try_connect(this, &rc);
llarp_rc_clear(&rc);
return true;
}
for(const auto &msg : msgs)
{
outboundMesssageQueue[remote].push(msg);
}
FlushOutboundFor(remote);
return true;
}
void
@ -75,11 +112,11 @@ llarp_router::try_connect(fs::path rcfile)
f.read((char *)buf.base, sz);
}
else
llarp::Error(__FILE__, rcfile, " too large");
llarp::Error(rcfile, " too large");
}
else
{
llarp::Error(__FILE__, "failed to open ", rcfile);
llarp::Error("failed to open ", rcfile);
return;
}
}
@ -87,17 +124,17 @@ llarp_router::try_connect(fs::path rcfile)
{
if(llarp_rc_verify_sig(&crypto, &remote))
{
llarp::Debug(__FILE__, "verified signature");
llarp::Debug("verified signature");
if(!llarp_router_try_connect(this, &remote))
{
llarp::Warn(__FILE__, "session already made");
llarp::Warn("session already made");
}
}
else
llarp::Error(__FILE__, "failed to verify signature of RC");
llarp::Error("failed to verify signature of RC");
}
else
llarp::Error(__FILE__, "failed to decode RC");
llarp::Error("failed to decode RC");
llarp_rc_free(&remote);
}
@ -124,10 +161,10 @@ llarp_router::Ready()
bool
llarp_router::SaveRC()
{
llarp::Debug(__FILE__, "verify RC signature");
llarp::Debug("verify RC signature");
if(!llarp_rc_verify_sig(&crypto, &rc))
{
llarp::Error(__FILE__, "RC has bad signature not saving");
llarp::Error("RC has bad signature not saving");
return false;
}
@ -140,11 +177,11 @@ llarp_router::SaveRC()
if(f.is_open())
{
f.write((char *)buf.base, buf.cur - buf.base);
llarp::Info(__FILE__, "our RC saved to ", our_rc_file.c_str());
llarp::Info("our RC saved to ", our_rc_file.c_str());
return true;
}
}
llarp::Error(__FILE__, "did not save RC to ", our_rc_file.c_str());
llarp::Error("did not save RC to ", our_rc_file.c_str());
return false;
}
@ -166,7 +203,7 @@ llarp_router::connect_job_retry(void *user)
llarp_link_establish_job *job =
static_cast< llarp_link_establish_job * >(user);
llarp::Info(__FILE__, "trying to establish session again");
llarp::Info("trying to establish session again");
job->link->try_establish(job->link, job);
}
@ -187,7 +224,7 @@ llarp_router::on_verify_server_rc(llarp_async_verify_rc *job)
auto router = ctx->router;
if(!job->valid)
{
llarp::Warn(__FILE__, "invalid server RC");
llarp::Warn("invalid server RC");
if(ctx->establish_job)
{
// was an outbound attempt
@ -201,15 +238,14 @@ llarp_router::on_verify_server_rc(llarp_async_verify_rc *job)
return;
}
llarp::Debug(__FILE__, "rc verified");
llarp::Debug("rc verified");
// this was an outbound establish job
if(ctx->establish_job->session)
{
auto session = ctx->establish_job->session;
llarp::pubkey pubkey;
memcpy(&pubkey[0], job->rc.pubkey, pubkey.size());
// refresh valid routers RC value if it's there
auto v = router->validRouters.find(pubkey);
if(v != router->validRouters.end())
{
@ -218,22 +254,7 @@ llarp_router::on_verify_server_rc(llarp_async_verify_rc *job)
}
router->validRouters[pubkey] = job->rc;
auto itr = router->pendingMessages.find(pubkey);
if(itr != router->pendingMessages.end())
{
// flush pending
if(itr->second.size())
{
llarp::Debug(__FILE__, "flush ", itr->second.size(),
" pending messages");
}
for(auto &msg : itr->second)
{
auto buf = llarp::Buffer< decltype(msg) >(msg);
session->sendto(session, buf);
}
router->pendingMessages.erase(itr);
}
router->FlushOutboundFor(pubkey);
}
else
llarp_rc_free(&job->rc);
@ -241,6 +262,47 @@ llarp_router::on_verify_server_rc(llarp_async_verify_rc *job)
delete job;
}
void
llarp_router::FlushOutboundFor(const llarp::RouterID &remote)
{
auto itr = outboundMesssageQueue.find(remote);
if(itr == outboundMesssageQueue.end())
return;
while(itr->second.size())
{
auto buf = llarp::StackBuffer< decltype(linkmsg_buffer) >(linkmsg_buffer);
auto &msg = itr->second.front();
if(!msg->BEncode(&buf))
{
llarp::Warn("failed to encode outbound message, buffer size left: ",
llarp_buffer_size_left(buf));
delete msg;
itr->second.pop();
continue;
}
// set size of message
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
bool sent = false;
for(auto &link : links)
{
if(!sent)
{
sent = link->sendto(link, remote, buf);
}
}
if(!sent)
{
llarp::Warn("failed to flush outboud message queue for ", remote);
}
delete msg;
itr->second.pop();
}
}
void
llarp_router::on_try_connect_result(llarp_link_establish_job *job)
{
@ -248,10 +310,12 @@ llarp_router::on_try_connect_result(llarp_link_establish_job *job)
if(job->session)
{
auto session = job->session;
llarp_dht_put_local_router(router->dht,
session->get_remote_router(session));
router->async_verify_RC(session, false, job);
return;
}
llarp::Info(__FILE__, "session not established");
llarp::Info("session not established");
llarp_logic_queue_job(router->logic, {job, &llarp_router::connect_job_retry});
}
void
@ -296,29 +360,24 @@ llarp_router::Run()
return;
}
char tmp[68] = {0};
llarp::pubkey ourPubkey;
memcpy(&ourPubkey[0], pubkey(), 32);
const char *us =
llarp::HexEncode< llarp::pubkey, decltype(tmp) >(ourPubkey, tmp);
llarp::pubkey ourPubkey = pubkey();
llarp::Debug(__FILE__, "our router has public key ", us);
llarp::Info("our router has public key ", ourPubkey);
llarp_dht_context_start(dht, ourPubkey);
// start links
for(auto link : links)
{
int result = link->start_link(link, logic);
if(result == -1)
llarp::Warn(__FILE__, "Link ", link->name(), " failed to start");
llarp::Warn("Link ", link->name(), " failed to start");
else
llarp::Debug(__FILE__, "Link ", link->name(), " started");
llarp::Debug("Link ", link->name(), " started");
}
for(const auto &itr : connect)
{
llarp::Info(__FILE__, "connecting to node ", itr.first);
llarp::Info("connecting to node ", itr.first);
try_connect(itr.second);
}
}
@ -574,8 +633,7 @@ namespace llarp
{
// we failed to configure IPv6
// try IPv4
llarp::Info(__FILE__, "link ", key,
" failed to configure IPv6, trying IPv4");
llarp::Info("link ", key, " failed to configure IPv6, trying IPv4");
af = AF_INET;
if(link->configure(link, self->netloop, key, af, proto))
{
@ -587,7 +645,7 @@ namespace llarp
}
}
}
llarp::Error(__FILE__, "link ", key, " failed to configure");
llarp::Error("link ", key, " failed to configure");
}
else if(StrEq(section, "iwp-connect"))
{

@ -1,15 +1,18 @@
#ifndef LLARP_ROUTER_HPP
#define LLARP_ROUTER_HPP
#include <llarp/dht.h>
#include <llarp/link.h>
#include <llarp/nodedb.h>
#include <llarp/path.h>
#include <llarp/router.h>
#include <llarp/router_contact.h>
#include <functional>
#include <list>
#include <map>
#include <unordered_map>
#include <llarp/dht.hpp>
#include <llarp/link_message.hpp>
#include "crypto.hpp"
@ -51,15 +54,24 @@ struct llarp_router
llarp_path_context *paths;
llarp_seckey_t identity;
llarp_threadpool *disk;
llarp_dht_context *dht;
llarp_nodedb *nodedb;
llarp::InboundMessageHandler inbound_msg_handler;
// buffer for serializing link messages
byte_t linkmsg_buffer[MAX_LINK_MSG_SIZE];
llarp::InboundMessageParser inbound_msg_parser;
std::list< llarp_link * > links;
std::map< llarp::pubkey, std::vector< llarp::Message > > pendingMessages;
typedef std::queue< llarp::ILinkMessage * > MessageQueue;
/// outbound message queue
std::unordered_map< llarp::pubkey, MessageQueue, llarp::pubkeyhash >
outboundMesssageQueue;
/// loki verified routers
std::unordered_map< llarp::pubkey, llarp_rc, llarp::pubkeyhash > validRouters;
llarp_router();
@ -95,11 +107,20 @@ struct llarp_router
void
try_connect(fs::path rcfile);
/// send to remote router or queue for sending
/// returns false on overflow
/// returns true on successful queue
bool
SendToOrQueue(const llarp::RouterID &remote,
std::vector< llarp::ILinkMessage * > msgs);
/// manually flush outbound message queue for just 1 router
void
QueueSendTo(const byte_t *pubkey, const std::vector< llarp::Message > &msgs);
FlushOutboundFor(const llarp::RouterID &remote);
bool
ProcessLRCM(llarp::LR_CommitMessage msg);
/// flush outbound message queue
void
FlushOutbound();
void
async_verify_RC(llarp_link_session *session, bool isExpectingClient,

@ -47,7 +47,7 @@ llarp_rc_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
if(llarp_buffer_eq(*key, "k"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != sizeof(llarp_pubkey_t))
return false;
@ -57,14 +57,14 @@ llarp_rc_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
if(llarp_buffer_eq(*key, "u"))
{
if(!bdecode_read_integer(r->buffer, &rc->last_updated))
if(!bencode_read_integer(r->buffer, &rc->last_updated))
return false;
return true;
}
if(llarp_buffer_eq(*key, "v"))
{
if(!bdecode_read_integer(r->buffer, &v))
if(!bencode_read_integer(r->buffer, &v))
return false;
return v == LLARP_PROTO_VERSION;
}
@ -81,7 +81,7 @@ llarp_rc_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
if(llarp_buffer_eq(*key, "z"))
{
if(!bdecode_read_string(r->buffer, &strbuf))
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != sizeof(llarp_sig_t))
return false;
@ -93,10 +93,10 @@ llarp_rc_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
}
void
llarp_rc_copy(struct llarp_rc *dst, struct llarp_rc *src)
llarp_rc_copy(struct llarp_rc *dst, const struct llarp_rc *src)
{
llarp_rc_free(dst);
llarp_rc_clear(dst);
memcpy(dst->pubkey, src->pubkey, sizeof(llarp_pubkey_t));
memcpy(dst->signature, src->signature, sizeof(llarp_sig_t));
dst->last_updated = src->last_updated;
@ -117,7 +117,7 @@ bool
llarp_rc_bdecode(struct llarp_rc *rc, llarp_buffer_t *buff)
{
dict_reader r = {buff, rc, &llarp_rc_decode_dict};
return bdecode_read_dict(buff, &r);
return bencode_read_dict(buff, &r);
}
bool

@ -3,7 +3,7 @@
#include <cstring>
#include "logger.hpp"
#if (__FreeBSD__)
#if(__FreeBSD__)
#include <pthread_np.h>
#endif
@ -16,8 +16,17 @@ namespace llarp
stop = false;
while(workers--)
{
threads.emplace_back([this] {
threads.emplace_back([this, name] {
if(name)
{
#if(__APPLE__ && __MACH__)
pthread_setname_np(name);
#elif(__FreeBSD__)
pthread_set_name_np(pthread_self(), name);
#else
pthread_setname_np(pthread_self(), name);
#endif
}
for(;;)
{
llarp_thread_job job;
@ -35,21 +44,6 @@ namespace llarp
}
});
}
if(name)
{
#if (__APPLE__ && __MACH__)
//for(auto &t : threads)
// FIXME: send signal to thread
// name has to be set from inside the thread
//pthread_setname_np(name);
#elif (__FreeBSD__)
for(auto &t : threads)
pthread_set_name_np(t.native_handle(), name);
#else
for(auto &t : threads)
pthread_setname_np(t.native_handle(), name);
#endif
}
}
void
@ -112,7 +106,7 @@ llarp_init_threadpool(int workers, const char *name)
void
llarp_threadpool_join(struct llarp_threadpool *pool)
{
llarp::Debug(__FILE__, "threadpool join");
llarp::Debug("threadpool join");
pool->impl.Join();
}
@ -124,7 +118,7 @@ llarp_threadpool_start(struct llarp_threadpool *pool)
void
llarp_threadpool_stop(struct llarp_threadpool *pool)
{
llarp::Debug(__FILE__, "threadpool stop");
llarp::Debug("threadpool stop");
pool->impl.Stop();
}
@ -132,7 +126,7 @@ void
llarp_threadpool_wait(struct llarp_threadpool *pool)
{
std::mutex mtx;
llarp::Debug(__FILE__, "threadpool wait");
llarp::Debug("threadpool wait");
{
std::unique_lock< std::mutex > lock(mtx);
pool->impl.done.wait(lock);

@ -175,10 +175,10 @@ llarp_timer_stop(struct llarp_timer_context* t)
{
// destroy all timers
// don't call callbacks on timers
llarp::Debug(__FILE__, "clear timers");
llarp::Debug("clear timers");
t->timers.clear();
t->stop();
llarp::Debug(__FILE__, "stop timers");
llarp::Debug("stop timers");
t->ticker.notify_all();
}

@ -4,37 +4,52 @@ Low Latency Anon Routing Protocol
We'll be ready when we're ready.
[what/why](doc/high-level.txt)
[who](https://github.com/majestrate)
[what + why](doc/high-level.txt)
[when](http://i0.kym-cdn.com/photos/images/original/000/117/021/enhanced-buzz-28895-1301694293-0.jpg)
[where](https://joedaeskimo.files.wordpress.com/2011/01/idklol.jpg)
[how](doc/proto_v0.txt)
## Reference Implementation
## Building
You have 2 ways the build this project
### The recommended way (for stable builds)
$ git clone --recursive https://github.com/majestrate/llarpd-builder
$ cd llarpd-builder
$ make
### The "I want to risk ripping my fingernails off in frustration" way (for dev builds)
Build requirements:
* CMake / gmake / ninja
* CMake
* ninja
* libsodium >= 1.0.14
* c++ 17 capable C++ compiler
* c11 capable C compiler
Building:
Building a debug build:
$ make
Building in another directory:
## Running
$ mkdir build
$ cd build
$ cmake ..
$ make
Building really fast (requires ninja):
Right now the reference daemon connects to nodes you tell it to and that's it.
If you built using the `recommended` way just run:
$ mkdir build
$ cd build
$ cmake -GNinja ..
$ ninja
$ ./llarpd
Running:
It'll attempt to connect to a test node I run and keep the session alive.
That's it.
$ ./llarpd daemon.ini
If you built using the dev build you are expected to configure the daemon yourself.

@ -1,82 +0,0 @@
#include <llarp/crypto_async.h>
#include <llarp/mem.h>
#include <stdio.h>
struct bench_main {
size_t completed;
size_t num;
size_t jobs;
struct llarp_threadpool *pool;
struct llarp_async_cipher *cipher;
struct llarp_crypto crypto;
};
static void handle_cipher_complete(struct llarp_cipher_result *res) {
struct bench_main *m = (struct bench_main *)res->user;
size_t sz = m->jobs;
m->completed++;
size_t left = m->num - m->completed;
if (m->completed % 10000 == 0)
printf("completed %ld and %ld left\n", m->completed, left);
if (m->completed == m->num) {
llarp_threadpool_stop(m->pool);
printf("done\n");
} else if (m->completed % sz == 0) {
llarp_nounce_t nounce;
while (sz--) {
m->crypto.randbytes(nounce, sizeof(llarp_nounce_t));
llarp_async_cipher_queue_op(m->cipher, &res->buff, nounce,
handle_cipher_complete, m);
}
}
}
int main(int argc, char *argv[]) {
struct bench_main b_main;
struct llarp_threadpool *tp;
llarp_mem_stdlib();
llarp_crypto_libsodium_init(&b_main.crypto);
b_main.pool = llarp_init_threadpool(1);
llarp_threadpool_start(b_main.pool);
tp = llarp_init_threadpool(8);
b_main.num = 5000000;
b_main.jobs = 5000;
b_main.completed = 0;
llarp_sharedkey_t key;
b_main.crypto.randbytes(key, sizeof(llarp_sharedkey_t));
b_main.cipher = llarp_async_cipher_new(key, &b_main.crypto, b_main.pool, tp);
llarp_threadpool_start(tp);
llarp_nounce_t nounce;
llarp_buffer_t n_buff;
n_buff.base = nounce;
n_buff.cur = n_buff.base;
n_buff.sz = sizeof(llarp_nounce_t);
size_t sz = b_main.jobs;
printf("starting %ld jobs\n", sz);
/* do work here */
while (sz--) {
llarp_buffer_t *msg = llarp_g_mem.alloc(sizeof(llarp_buffer_t), 8);
msg->base = llarp_g_mem.alloc(1024, 1024);
msg->sz = 1024;
msg->cur = msg->base;
b_main.crypto.randomize(*msg);
b_main.crypto.randbytes(nounce, sizeof(llarp_nounce_t));
llarp_async_cipher_queue_op(b_main.cipher, msg, nounce,
handle_cipher_complete, &b_main);
}
printf("started %ld jobs\n", b_main.jobs);
llarp_threadpool_wait(b_main.pool);
llarp_threadpool_join(b_main.pool);
llarp_threadpool_stop(tp);
llarp_threadpool_join(tp);
llarp_free_threadpool(&tp);
llarp_free_threadpool(&b_main.pool);
llarp_async_cipher_free(&b_main.cipher);
printf("did %ld of %ld work\n", b_main.completed, b_main.num);
return 0;
}

@ -1,75 +0,0 @@
#include <llarp/crypto_async.h>
#include <llarp/mem.h>
#include <stdio.h>
struct dh_bench_main {
size_t completed;
size_t num;
struct llarp_threadpool *result;
struct llarp_async_dh *dh;
};
static void handle_dh_complete(struct llarp_dh_result *res) {
struct dh_bench_main *m = (struct dh_bench_main *)res->user;
m->completed++;
if (m->completed % 10000 == 0) printf("completed %ld\n", m->completed);
if (m->completed == m->num) {
printf("done\n");
llarp_threadpool_stop(m->result);
}
}
int main(int argc, char *argv[]) {
struct dh_bench_main dh_main;
struct llarp_crypto crypto;
struct llarp_threadpool *tp;
llarp_mem_stdlib();
llarp_crypto_libsodium_init(&crypto);
tp = llarp_init_threadpool(8);
dh_main.result = llarp_init_threadpool(1);
llarp_threadpool_start(dh_main.result);
dh_main.num = 500000;
dh_main.completed = 0;
llarp_seckey_t ourkey;
llarp_seckey_t theirkey;
crypto.keygen(&ourkey);
crypto.keygen(&theirkey);
dh_main.dh = llarp_async_dh_new(ourkey, &crypto, dh_main.result, tp);
llarp_threadpool_start(tp);
llarp_tunnel_nounce_t nounce;
llarp_buffer_t n_buff;
n_buff.base = nounce;
n_buff.cur = n_buff.base;
n_buff.sz = sizeof(llarp_tunnel_nounce_t);
uint8_t *theirpubkey = llarp_seckey_topublic(theirkey);
size_t sz = dh_main.num;
printf("starting %ld dh jobs\n", sz);
/* do work here */
while (sz--) {
crypto.randomize(n_buff);
llarp_async_client_dh(dh_main.dh, theirpubkey, nounce, handle_dh_complete,
&dh_main);
}
printf("started %ld dh jobs\n", dh_main.num);
llarp_threadpool_wait(dh_main.result);
llarp_threadpool_join(dh_main.result);
llarp_threadpool_stop(tp);
llarp_threadpool_join(tp);
llarp_free_threadpool(&tp);
llarp_free_threadpool(&dh_main.result);
llarp_async_dh_free(&dh_main.dh);
printf("did %ld of %ld work\n", dh_main.completed, dh_main.num);
return 0;
}

@ -1,3 +0,0 @@
int main(int argc, char *argv[]) { return 0; }
Loading…
Cancel
Save