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

@ -32,7 +32,7 @@ else()
endif()
set(DEBUG_FLAGS "-g")
set(OPTIMIZE_FLAGS "-Os")
set(OPTIMIZE_FLAGS "-O0")
if(ASAN)
set(DEBUG_FLAGS "${DEBUG_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
@ -155,6 +155,7 @@ set(LIB_SRC
set(TEST_SRC
test/main.cpp
test/dht_unittest.cpp
test/encrypted_frame_unittest.cpp
)
set(TEST_EXE testAll)
set(GTEST_DIR test/gtest)

@ -70,6 +70,7 @@ testnet: testnet-build
supervisord -n -d $(TESTNET_ROOT) -l $(TESTNET_LOG) -c $(TESTNET_CONF)
test: debug-configure
ninja
ninja test
format:

@ -60,11 +60,11 @@ def main():
'dir': 'netdb'
}
config['connect'] = {}
for otherid in range(args.svc):
if otherid % args.connect == 0:
name = svcNodeName(otherid)
config['connect'][name] = os.path.join(
basedir, name, 'rc.signed')
for otherid in range(args.connect):
otherid = (nodeid + otherid) % args.svc
name = svcNodeName(otherid)
config['connect'][name] = os.path.join(
basedir, name, 'rc.signed')
d = os.path.join(args.dir, clientNodeName(nodeid))
if not os.path.exists(d):

@ -21,6 +21,12 @@ namespace llarp
return bencode_write_bytestring(buf, _data.data(), _data.size());
}
void
Fill(byte_t fill)
{
std::fill(_data.begin(), _data.end(), fill);
}
void
Randomize()
{

@ -102,6 +102,7 @@ namespace llarp
llarp_crypto* crypto;
byte_t* seckey;
EncryptedFrame* target;
void
AsyncDecrypt(llarp_threadpool* worker, EncryptedFrame* frame, User* user)
{

@ -90,7 +90,7 @@ namespace llarp
_glog.out << "\n" << std::flush;
#endif
}
}
} // namespace llarp
#define Debug(x, ...) _Log(llarp::eLogDebug, __FILE__, x, ##__VA_ARGS__)
#define Info(x, ...) _Log(llarp::eLogInfo, __FILE__, x, ##__VA_ARGS__)

@ -54,8 +54,8 @@ llarp_nodedb_get_random_rc(struct llarp_nodedb *n, struct llarp_rc *result);
/// select a random rc at hop number N
void
llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *result,
size_t N);
llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev,
struct llarp_rc *result, size_t N);
/// return number of RC loaded
size_t

@ -169,30 +169,29 @@ namespace llarp
LR_CommitMessage* LRCM = nullptr;
static void
HandleDone(void* user)
HandleDone(void* u)
{
AsyncPathKeyExchangeContext< User >* ctx =
static_cast< AsyncPathKeyExchangeContext< User >* >(user);
static_cast< AsyncPathKeyExchangeContext< User >* >(u);
ctx->result(ctx);
delete ctx;
}
static void
GenerateNextKey(void* user)
GenerateNextKey(void* u)
{
AsyncPathKeyExchangeContext< User >* ctx =
static_cast< AsyncPathKeyExchangeContext< User >* >(user);
static_cast< AsyncPathKeyExchangeContext< User >* >(u);
auto& hop = ctx->path->hops[ctx->idx];
// generate key
ctx->crypto->encryption_keygen(hop.commkey);
hop.nonce.Randomize();
// do key exchange
if(!ctx->crypto->dh_client(hop.shared, hop.router.enckey, hop.nonce,
hop.commkey))
{
llarp::Error("Failed to generate shared key for path build");
delete ctx->user;
delete ctx;
abort();
return;
}
// randomize hop's path id
@ -210,13 +209,23 @@ namespace llarp
{
hop.upstream = hop.router.pubkey;
}
auto buf = frame.Buffer();
buf->cur = buf->base + EncryptedFrame::OverheadSize;
// generate record
if(!record.BEncode(frame.Buffer()))
if(!record.BEncode(buf))
{
// failed to encode?
llarp::Error("Failed to generate Commit Record");
delete ctx->user;
delete ctx;
abort();
return;
}
// rewind
buf->cur = buf->base;
if(!frame.EncryptInPlace(hop.commkey, hop.router.enckey, ctx->crypto))
{
llarp::Error("Failed to encrypt LRCR");
abort();
return;
}

@ -34,8 +34,10 @@ struct llarp_pathbuild_job;
/// response callback
typedef void (*llarp_pathbuilder_hook)(struct llarp_pathbuild_job*);
// select hop function (nodedb, result, hopnnumber) called in logic thread
// select hop function (nodedb, prevhop, result, hopnnumber) called in logic
// thread
typedef void (*llarp_pathbuilder_select_hop_func)(struct llarp_nodedb*,
struct llarp_rc*,
struct llarp_rc*, size_t);
// request struct

@ -16,14 +16,14 @@ namespace llarp
}
static bool
dh(uint8_t *out, uint8_t *client_pk, uint8_t *server_pk, uint8_t *pubkey,
uint8_t *secret)
dh(uint8_t *out, uint8_t *client_pk, uint8_t *server_pk, uint8_t *themPub,
uint8_t *usSec)
{
llarp::SharedSecret shared;
crypto_generichash_state h;
const size_t outsz = SHAREDKEYSIZE;
if(crypto_scalarmult_curve25519(shared, secret, pubkey))
if(crypto_scalarmult_curve25519(shared, usSec, themPub))
return false;
crypto_generichash_init(&h, NULL, 0U, outsz);
crypto_generichash_update(&h, client_pk, 32);
@ -34,31 +34,7 @@ namespace llarp
}
static bool
dh_client(byte_t *shared, byte_t *pk, byte_t *n, byte_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(byte_t *shared, byte_t *pk, byte_t *n, byte_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)
dh_client(uint8_t *shared, uint8_t *pk, uint8_t *sk, uint8_t *n)
{
llarp::SharedSecret dh_result;
if(dh(dh_result, llarp::seckey_topublic(sk), pk, pk, sk))
@ -69,7 +45,7 @@ namespace llarp
}
static bool
transport_dh_server(uint8_t *shared, uint8_t *pk, uint8_t *sk, uint8_t *n)
dh_server(uint8_t *shared, uint8_t *pk, uint8_t *sk, uint8_t *n)
{
llarp::SharedSecret dh_result;
if(dh(dh_result, pk, llarp::seckey_topublic(sk), pk, sk))
@ -155,34 +131,34 @@ namespace llarp
} // namespace llarp
extern "C" {
const byte_t *
llarp_seckey_topublic(const byte_t *secret)
extern "C"
{
return secret + 32;
}
const byte_t *
llarp_seckey_topublic(const byte_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->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->identity_keygen = llarp::sodium::sigkeygen;
c->encryption_keygen = llarp::sodium::enckeygen;
int seed;
c->randbytes(&seed, sizeof(seed));
srand(seed);
}
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->transport_dh_client = llarp::sodium::dh_client;
c->transport_dh_server = llarp::sodium::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->identity_keygen = llarp::sodium::sigkeygen;
c->encryption_keygen = llarp::sodium::enckeygen;
int seed;
c->randbytes(&seed, sizeof(seed));
srand(seed);
}
}

@ -52,11 +52,12 @@ namespace llarp
crypto->randbytes(nonce, TUNNONCESIZE);
// derive shared key
if(!DH(shared, otherPubkey, nonce, ourSecretKey))
if(!DH(shared, otherPubkey, ourSecretKey, nonce))
{
llarp::Error("DH failed");
return false;
}
// encrypt body
if(!Encrypt(buf, shared, nonce))
{
@ -110,7 +111,7 @@ namespace llarp
SharedSecret shared;
ShortHash digest;
if(!DH(shared, otherPubkey, nonce, ourSecretKey))
if(!DH(shared, otherPubkey, ourSecretKey, nonce))
{
llarp::Error("DH failed");
return false;

@ -30,8 +30,8 @@
namespace iwp
{
// session activity timeout is 5s
constexpr llarp_time_t SESSION_TIMEOUT = 5000;
// session activity timeout is 10s
constexpr llarp_time_t SESSION_TIMEOUT = 10000;
constexpr size_t MAX_PAD = 128;
@ -678,7 +678,7 @@ namespace iwp
uint32_t establish_job_id = 0;
uint32_t frames = 0;
bool working = false;
llarp::Addr addr;
iwp_async_intro intro;
iwp_async_introack introack;
@ -853,7 +853,7 @@ namespace iwp
// when we are done doing stuff with all of our frames from the crypto
// workers we are done
llarp::Debug(addr, " timed out with ", frames, " frames left");
return frames == 0;
return frames == 0 && !working;
}
if(is_invalidated())
{
@ -862,7 +862,7 @@ namespace iwp
// are done
llarp::Debug(addr, " invaldiated session with ", frames,
" frames left");
return frames == 0;
return frames == 0 && !working;
}
// send keepalive if we are established or a session is made
if(state == eEstablished || state == eLIMSent)
@ -905,6 +905,7 @@ namespace iwp
start.sessionkey = sessionkey;
start.user = this;
start.hook = &handle_verify_session_start;
working = true;
iwp_call_async_verify_session_start(iwp, &start);
}
@ -954,6 +955,7 @@ namespace iwp
handle_generated_session_start(iwp_async_session_start *start)
{
session *link = static_cast< session * >(start->user);
link->working = false;
if(llarp_ev_udp_sendto(link->udp, link->addr, start->buf, start->sz)
== -1)
llarp::Error("sendto failed");
@ -983,6 +985,7 @@ namespace iwp
start.sessionkey = sessionkey;
start.user = this;
start.hook = &handle_generated_session_start;
working = true;
iwp_call_async_gen_session_start(iwp, &start);
}
@ -1090,6 +1093,7 @@ namespace iwp
// call
introack.user = this;
introack.hook = &handle_introack_generated;
working = true;
iwp_call_async_gen_introack(iwp, &introack);
}
@ -1119,6 +1123,7 @@ namespace iwp
// call
EnterState(eIntroRecv);
working = true;
iwp_call_async_verify_intro(iwp, &intro);
}
@ -1144,6 +1149,7 @@ namespace iwp
introack.user = this;
introack.hook = &handle_verify_introack;
// async verify
working = true;
iwp_call_async_verify_introack(iwp, &introack);
}
@ -1154,6 +1160,7 @@ namespace iwp
handle_generated_intro(iwp_async_intro *i)
{
session *link = static_cast< session * >(i->user);
link->working = false;
if(i->buf)
{
llarp::Debug("send intro");
@ -1195,6 +1202,7 @@ namespace iwp
// async generate intro packet
intro.user = this;
intro.hook = &handle_generated_intro;
working = true;
iwp_call_async_gen_intro(iwp, &intro);
// start introduce timer
establish_job_id = llarp_logic_call_later(
@ -1403,6 +1411,7 @@ namespace iwp
{
llarp::Debug("removing session ", addr);
session *s = static_cast< session * >(itr->second.impl);
s->done();
if(s->frames)
{
llarp::Warn("session has ", s->frames,
@ -1531,6 +1540,7 @@ namespace iwp
if(!impl->IsEstablished())
{
impl->send_LIM();
impl->session_established();
}
}
else
@ -1552,12 +1562,13 @@ namespace iwp
delete rxmsg;
rx.erase(id);
return success;
}
} // namespace iwp
void
session::handle_verify_intro(iwp_async_intro *intro)
{
session *self = static_cast< session * >(intro->user);
self->working = false;
if(!intro->buf)
{
llarp::Error("intro verify failed from ", self->addr, " via ",
@ -1570,6 +1581,8 @@ namespace iwp
void
session::session_established()
{
llarp::RouterID remote = remote_router.pubkey;
llarp::Info("session to ", remote, " established");
EnterState(eEstablished);
serv->MapAddr(addr, remote_router.pubkey);
llarp_logic_cancel_call(logic, establish_job_id);
@ -1636,11 +1649,6 @@ namespace iwp
{
llarp::Debug("message transmitted msgid=", msgid);
session *impl = static_cast< session * >(parent->impl);
if(msgid == 0)
{
// first message acked means we are established
impl->session_established();
}
tx.erase(msgid);
delete msg;
}
@ -1664,6 +1672,7 @@ namespace iwp
session::handle_verify_introack(iwp_async_introack *introack)
{
session *link = static_cast< session * >(introack->user);
link->working = false;
if(introack->buf == nullptr)
{
// invalid signature
@ -1678,6 +1687,7 @@ namespace iwp
session::handle_verify_session_start(iwp_async_session_start *s)
{
session *self = static_cast< session * >(s->user);
self->working = false;
if(!s->buf)
{
// verify fail
@ -1878,7 +1888,7 @@ namespace iwp
self->establish_job->link = self->serv->parent;
if(left)
{
// timer cancelled
// timer cancelled which means we were established
self->establish_job->session = self->parent;
}
else

@ -49,6 +49,7 @@ namespace llarp
return false;
}
// create the message to parse based off message type
llarp::Debug("inbound message ", *strbuf.cur);
switch(*strbuf.cur)
{
case 'i':
@ -113,4 +114,4 @@ namespace llarp
firstkey = true;
return bencode_read_dict(&buf, &reader);
}
}
} // namespace llarp

@ -380,17 +380,38 @@ llarp_nodedb_num_loaded(struct llarp_nodedb *n)
}
void
llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *result,
size_t N)
llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev,
struct llarp_rc *result, size_t N)
{
/// TODO: check for "guard" status for N = 0?
auto sz = n->entries.size();
auto itr = n->entries.begin();
if(sz > 1)
auto sz = n->entries.size();
if(prev)
{
std::advance(itr, rand() % (sz - 1));
do
{
auto itr = n->entries.begin();
if(sz > 1)
{
auto idx = rand() % (sz - 1);
std::advance(itr, idx);
}
if(memcmp(prev->pubkey, itr->second.pubkey, PUBKEYSIZE) == 0)
continue;
llarp_rc_copy(result, &itr->second);
return;
} while(true);
}
else
{
auto itr = n->entries.begin();
if(sz > 1)
{
auto idx = rand() % (sz - 1);
std::advance(itr, idx);
}
llarp_rc_copy(result, &itr->second);
}
llarp_rc_copy(result, &itr->second);
}
} // end extern

@ -5,15 +5,6 @@
namespace llarp
{
Path::Path(llarp_path_hops* h)
{
for(size_t idx = 0; idx < h->numHops; ++idx)
{
hops.emplace_back();
llarp_rc_copy(&hops[idx].router, &h->hops[idx].router);
}
}
PathContext::PathContext(llarp_router* router)
: m_Router(router), m_AllowTransit(false)
{
@ -69,6 +60,7 @@ namespace llarp
PathContext::ForwardLRCM(const RouterID& nextHop,
std::deque< EncryptedFrame >& frames)
{
llarp::Info("fowarding LRCM to ", nextHop);
LR_CommitMessage* msg = new LR_CommitMessage;
while(frames.size())
{
@ -155,6 +147,14 @@ namespace llarp
{
}
Path::Path(llarp_path_hops* h) : hops(h->numHops)
{
for(size_t idx = 0; idx < h->numHops; ++idx)
{
llarp_rc_copy(&hops[idx].router, &h->hops[idx].router);
}
}
const PathID_t&
Path::PathID() const
{

@ -20,9 +20,14 @@ namespace llarp
pathbuilder_generated_keys(
AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx)
{
llarp::Debug("Generated LRCM");
auto remote = ctx->path->Upstream();
llarp::Debug("Generated LRCM to", remote);
auto router = ctx->user->router;
router->SendToOrQueue(ctx->path->Upstream(), ctx->LRCM);
if(!router->SendToOrQueue(remote, ctx->LRCM))
{
llarp::Error("failed to send LRCM");
return;
}
ctx->path->status = ePathBuilding;
router->paths.AddOwnPath(ctx->path);
ctx->user->pathBuildStarted(ctx->user);
@ -33,12 +38,14 @@ namespace llarp
{
llarp_pathbuild_job* job = static_cast< llarp_pathbuild_job* >(user);
// select hops
size_t idx = 0;
size_t idx = 0;
llarp_rc* prev = nullptr;
while(idx < job->hops.numHops)
{
auto rc = &job->hops.hops[idx].router;
llarp_rc* rc = &job->hops.hops[idx].router;
llarp_rc_clear(rc);
job->selectHop(job->router->nodedb, rc, idx);
job->selectHop(job->router->nodedb, prev, rc, idx);
prev = rc;
++idx;
}
@ -54,9 +61,8 @@ namespace llarp
llarp_pathbuilder_context::llarp_pathbuilder_context(
llarp_router* p_router, struct llarp_dht_context* p_dht)
: router(p_router), dht(p_dht)
{
this->router = p_router;
this->dht = p_dht;
}
extern "C" {

@ -75,6 +75,7 @@ namespace llarp
" when we are not allowing transit");
return false;
}
llarp::Info("Got LRCM from ", remote);
return AsyncDecrypt(&router->paths);
}

@ -71,32 +71,33 @@ llarp_router::SendToOrQueue(const llarp::RouterID &remote,
else
chosen = outboundLink;
if(chosen)
{
SendTo(remote, msg, chosen);
delete msg;
return true;
}
// this will create an entry in the obmq if it's not already there
outboundMesssageQueue[remote].push(msg);
if(!chosen)
// we don't have an open session to that router right now
auto rc = llarp_nodedb_get_rc(nodedb, remote);
if(rc)
{
// we don't have an open session to that router right now
auto rc = llarp_nodedb_get_rc(nodedb, remote);
if(rc)
{
// try connecting directly as the rc is loaded from disk
llarp_router_try_connect(this, rc, 10);
return true;
}
// try requesting the rc from the disk
llarp_async_load_rc *job = new llarp_async_load_rc;
job->diskworker = disk;
job->nodedb = nodedb;
job->logic = logic;
job->user = this;
job->hook = &HandleAsyncLoadRCForSendTo;
memcpy(job->pubkey, remote, PUBKEYSIZE);
llarp_nodedb_async_load_rc(job);
// try connecting directly as the rc is loaded from disk
llarp_router_try_connect(this, rc, 10);
return true;
}
else
FlushOutboundFor(remote, chosen);
// try requesting the rc from the disk
llarp_async_load_rc *job = new llarp_async_load_rc;
job->diskworker = disk;
job->nodedb = nodedb;
job->logic = logic;
job->user = this;
job->hook = &HandleAsyncLoadRCForSendTo;
memcpy(job->pubkey, remote, PUBKEYSIZE);
llarp_nodedb_async_load_rc(job);
return true;
}
@ -280,10 +281,16 @@ llarp_router::connect_job_retry(void *user, uint64_t orig, uint64_t left)
return;
llarp_link_establish_job *job =
static_cast< llarp_link_establish_job * >(user);
llarp::Addr remote = job->ai;
llarp::Info("trying to establish session again with ", remote);
job->link->try_establish(job->link, job);
if(job->link)
{
llarp::Info("trying to establish session again with ", remote);
job->link->try_establish(job->link, job);
}
else
{
llarp::Error("establish session retry failed, no link for ", remote);
}
}
void
@ -430,7 +437,8 @@ llarp_router::send_padded_message(llarp_link_session_iter *itr,
}
void
llarp_router::SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg)
llarp_router::SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg,
llarp_link *link)
{
llarp_buffer_t buf =
llarp::StackBuffer< decltype(linkmsg_buffer) >(linkmsg_buffer);
@ -444,7 +452,11 @@ llarp_router::SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg)
// set size of message
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
if(link)
{
link->sendto(link, remote, buf);
return;
}
bool sent = outboundLink->sendto(outboundLink, remote, buf);
if(!sent)
{
@ -485,7 +497,10 @@ llarp_router::FlushOutboundFor(const llarp::RouterID &remote,
llarp::Debug("Flush outbound for ", remote);
auto itr = outboundMesssageQueue.find(remote);
if(itr == outboundMesssageQueue.end())
{
llarp::Error("outbound queue not found for ", remote);
return;
}
while(itr->second.size())
{
auto buf = llarp::StackBuffer< decltype(linkmsg_buffer) >(linkmsg_buffer);
@ -700,209 +715,210 @@ llarp_router::HasPendingConnectJob(const llarp::RouterID &remote)
return pendingEstablishJobs.find(remote) != pendingEstablishJobs.end();
}
extern "C" {
struct llarp_router *
llarp_init_router(struct llarp_threadpool *tp, struct llarp_ev_loop *netloop,
struct llarp_logic *logic)
extern "C"
{
llarp_router *router = new llarp_router();
if(router)
struct llarp_router *
llarp_init_router(struct llarp_threadpool *tp, struct llarp_ev_loop *netloop,
struct llarp_logic *logic)
{
router->netloop = netloop;
router->tp = tp;
router->logic = logic;
// TODO: make disk io threadpool count configurable
llarp_router *router = new llarp_router();
if(router)
{
router->netloop = netloop;
router->tp = tp;
router->logic = logic;
// TODO: make disk io threadpool count configurable
#ifdef TESTNET
router->disk = tp;
router->disk = tp;
#else
router->disk = llarp_init_threadpool(1, "llarp-diskio");
router->disk = llarp_init_threadpool(1, "llarp-diskio");
#endif
llarp_crypto_libsodium_init(&router->crypto);
llarp_crypto_libsodium_init(&router->crypto);
}
return router;
}
return router;
}
bool
llarp_configure_router(struct llarp_router *router, struct llarp_config *conf)
{
llarp_config_iterator iter;
iter.user = router;
iter.visit = llarp::router_iter_config;
llarp_config_iter(conf, &iter);
if(!router->InitOutboundLink())
return false;
if(!router->Ready())
bool
llarp_configure_router(struct llarp_router *router, struct llarp_config *conf)
{
return false;
llarp_config_iterator iter;
iter.user = router;
iter.visit = llarp::router_iter_config;
llarp_config_iter(conf, &iter);
if(!router->InitOutboundLink())
return false;
if(!router->Ready())
{
return false;
}
return router->EnsureIdentity();
}
return router->EnsureIdentity();
}
void
llarp_run_router(struct llarp_router *router, struct llarp_nodedb *nodedb)
{
router->nodedb = nodedb;
router->Run();
}
void
llarp_run_router(struct llarp_router *router, struct llarp_nodedb *nodedb)
{
router->nodedb = nodedb;
router->Run();
}
bool
llarp_router_try_connect(struct llarp_router *router, struct llarp_rc *remote,
uint16_t numretries)
{
// do we already have a pending job for this remote?
if(router->HasPendingConnectJob(remote->pubkey))
bool
llarp_router_try_connect(struct llarp_router *router, struct llarp_rc *remote,
uint16_t numretries)
{
// do we already have a pending job for this remote?
if(router->HasPendingConnectJob(remote->pubkey))
return false;
// try first address only
llarp_ai addr;
if(llarp_ai_list_index(remote->addrs, 0, &addr))
{
auto link = router->outboundLink;
auto itr = router->pendingEstablishJobs.emplace(
std::make_pair(remote->pubkey, llarp_link_establish_job{}));
auto job = &itr.first->second;
llarp_ai_copy(&job->ai, &addr);
memcpy(job->pubkey, remote->pubkey, PUBKEYSIZE);
job->retries = numretries;
job->timeout = 10000;
job->result = &llarp_router::on_try_connect_result;
// give router as user pointer
job->user = router;
// try establishing
link->try_establish(link, job);
return true;
}
return false;
// try first address only
llarp_ai addr;
if(llarp_ai_list_index(remote->addrs, 0, &addr))
{
auto link = router->outboundLink;
auto itr = router->pendingEstablishJobs.emplace(
std::make_pair(remote->pubkey, llarp_link_establish_job{}));
auto job = &itr.first->second;
llarp_ai_copy(&job->ai, &addr);
memcpy(job->pubkey, remote->pubkey, PUBKEYSIZE);
job->retries = numretries;
job->timeout = 10000;
job->result = &llarp_router::on_try_connect_result;
// give router as user pointer
job->user = router;
// try establishing
link->try_establish(link, job);
return true;
}
return false;
}
void
llarp_rc_clear(struct llarp_rc *rc)
{
// zero out router contact
llarp::Zero(rc, sizeof(llarp_rc));
}
void
llarp_rc_clear(struct llarp_rc *rc)
{
// zero out router contact
llarp::Zero(rc, sizeof(llarp_rc));
}
bool
llarp_rc_addr_list_iter(struct llarp_ai_list_iter *iter, struct llarp_ai *ai)
{
struct llarp_rc *rc = (llarp_rc *)iter->user;
llarp_ai_list_pushback(rc->addrs, ai);
return true;
}
bool
llarp_rc_addr_list_iter(struct llarp_ai_list_iter *iter, struct llarp_ai *ai)
{
struct llarp_rc *rc = (llarp_rc *)iter->user;
llarp_ai_list_pushback(rc->addrs, ai);
return true;
}
void
llarp_rc_set_addrs(struct llarp_rc *rc, struct llarp_alloc *mem,
struct llarp_ai_list *addr)
{
rc->addrs = llarp_ai_list_new();
struct llarp_ai_list_iter ai_itr;
ai_itr.user = rc;
ai_itr.visit = &llarp_rc_addr_list_iter;
llarp_ai_list_iterate(addr, &ai_itr);
}
void
llarp_rc_set_addrs(struct llarp_rc *rc, struct llarp_alloc *mem,
struct llarp_ai_list *addr)
{
rc->addrs = llarp_ai_list_new();
struct llarp_ai_list_iter ai_itr;
ai_itr.user = rc;
ai_itr.visit = &llarp_rc_addr_list_iter;
llarp_ai_list_iterate(addr, &ai_itr);
}
void
llarp_rc_set_pubkey(struct llarp_rc *rc, const uint8_t *pubkey)
{
// set public key
memcpy(rc->pubkey, pubkey, 32);
}
void
llarp_rc_set_pubkey(struct llarp_rc *rc, const uint8_t *pubkey)
{
// set public key
memcpy(rc->pubkey, pubkey, 32);
}
bool
llarp_findOrCreateIdentity(llarp_crypto *crypto, const char *fpath,
byte_t *secretkey)
{
llarp::Debug("find or create ", fpath);
fs::path path(fpath);
std::error_code ec;
if(!fs::exists(path, ec))
bool
llarp_findOrCreateIdentity(llarp_crypto *crypto, const char *fpath,
byte_t *secretkey)
{
llarp::Info("regenerated identity key");
crypto->identity_keygen(secretkey);
std::ofstream f(path, std::ios::binary);
llarp::Debug("find or create ", fpath);
fs::path path(fpath);
std::error_code ec;
if(!fs::exists(path, ec))
{
llarp::Info("regenerated identity key");
crypto->identity_keygen(secretkey);
std::ofstream f(path, std::ios::binary);
if(f.is_open())
{
f.write((char *)secretkey, SECKEYSIZE);
}
}
std::ifstream f(path, std::ios::binary);
if(f.is_open())
{
f.write((char *)secretkey, SECKEYSIZE);
f.read((char *)secretkey, SECKEYSIZE);
return true;
}
llarp::Info("failed to get identity key");
return false;
}
std::ifstream f(path, std::ios::binary);
if(f.is_open())
bool
llarp_rc_write(struct llarp_rc *rc, const char *fpath)
{
f.read((char *)secretkey, SECKEYSIZE);
return true;
}
llarp::Info("failed to get identity key");
return false;
}
fs::path our_rc_file(fpath);
byte_t tmp[MAX_RC_SIZE];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
bool
llarp_rc_write(struct llarp_rc *rc, const char *fpath)
{
fs::path our_rc_file(fpath);
byte_t tmp[MAX_RC_SIZE];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(llarp_rc_bencode(rc, &buf))
{
std::ofstream f(our_rc_file, std::ios::binary);
if(f.is_open())
{
f.write((char *)buf.base, buf.cur - buf.base);
return true;
}
}
return false;
}
if(llarp_rc_bencode(rc, &buf))
{
std::ofstream f(our_rc_file, std::ios::binary);
if(f.is_open())
void
llarp_rc_sign(llarp_crypto *crypto, const byte_t *seckey, struct llarp_rc *rc)
{
byte_t buf[MAX_RC_SIZE];
auto signbuf = llarp::StackBuffer< decltype(buf) >(buf);
// zero out previous signature
llarp::Zero(rc->signature, sizeof(rc->signature));
// encode
if(llarp_rc_bencode(rc, &signbuf))
{
f.write((char *)buf.base, buf.cur - buf.base);
return true;
// sign
signbuf.sz = signbuf.cur - signbuf.base;
crypto->sign(rc->signature, seckey, signbuf);
}
}
return false;
}
void
llarp_rc_sign(llarp_crypto *crypto, const byte_t *seckey, struct llarp_rc *rc)
{
byte_t buf[MAX_RC_SIZE];
auto signbuf = llarp::StackBuffer< decltype(buf) >(buf);
// zero out previous signature
llarp::Zero(rc->signature, sizeof(rc->signature));
// encode
if(llarp_rc_bencode(rc, &signbuf))
void
llarp_stop_router(struct llarp_router *router)
{
// sign
signbuf.sz = signbuf.cur - signbuf.base;
crypto->sign(rc->signature, seckey, signbuf);
if(router)
router->Close();
}
}
void
llarp_stop_router(struct llarp_router *router)
{
if(router)
router->Close();
}
void
llarp_router_iterate_links(struct llarp_router *router,
struct llarp_router_link_iter i)
{
for(auto link : router->inboundLinks)
if(!i.visit(&i, router, link))
return;
i.visit(&i, router, router->outboundLink);
}
void
llarp_router_iterate_links(struct llarp_router *router,
struct llarp_router_link_iter i)
{
for(auto link : router->inboundLinks)
if(!i.visit(&i, router, link))
return;
i.visit(&i, router, router->outboundLink);
}
void
llarp_free_router(struct llarp_router **router)
{
if(*router)
void
llarp_free_router(struct llarp_router **router)
{
delete *router;
if(*router)
{
delete *router;
}
*router = nullptr;
}
*router = nullptr;
}
void
llarp_router_override_path_selection(struct llarp_router *router,
llarp_pathbuilder_select_hop_func func)
{
if(func)
router->selectHopFunc = func;
}
void
llarp_router_override_path_selection(struct llarp_router *router,
llarp_pathbuilder_select_hop_func func)
{
if(func)
router->selectHopFunc = func;
}
}
namespace llarp

@ -80,15 +80,12 @@ struct llarp_router
typedef std::queue< llarp::ILinkMessage * > MessageQueue;
/// outbound message queue
std::unordered_map< llarp::PubKey, MessageQueue, llarp::PubKeyHash >
outboundMesssageQueue;
std::map< llarp::PubKey, MessageQueue > outboundMesssageQueue;
/// loki verified routers
std::unordered_map< llarp::PubKey, llarp_rc, llarp::PubKeyHash > validRouters;
std::unordered_map< llarp::PubKey, llarp_link_establish_job,
llarp::PubKeyHash >
pendingEstablishJobs;
std::map< llarp::PubKey, llarp_link_establish_job > pendingEstablishJobs;
llarp_router();
~llarp_router();
@ -149,7 +146,8 @@ struct llarp_router
/// sendto or drop
void
SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg);
SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg,
llarp_link *chosen = nullptr);
/// manually flush outbound message queue for just 1 router
void

@ -0,0 +1,57 @@
#include <gtest/gtest.h>
#include <llarp/crypto.hpp>
#include <llarp/encrypted_frame.hpp>
#include <llarp/messages/relay_commit.hpp>
using EncryptedFrame = llarp::EncryptedFrame;
using SecretKey = llarp::SecretKey;
using PubKey = llarp::PubKey;
using LRAR = llarp::LR_AcceptRecord;
class FrameTest : public ::testing::Test
{
public:
llarp_crypto crypto;
SecretKey alice, bob;
FrameTest()
{
llarp_crypto_libsodium_init(&crypto);
}
~FrameTest()
{
}
void
SetUp()
{
crypto.encryption_keygen(alice);
crypto.encryption_keygen(bob);
}
void
TearDown()
{
}
};
TEST_F(FrameTest, TestFrameCrypto)
{
EncryptedFrame f(256);
f.Fill(0);
LRAR record;
record.upstream.Fill(1);
record.downstream.Fill(2);
record.pathid.Fill(3);
auto buf = f.Buffer();
buf->cur = buf->base + EncryptedFrame::OverheadSize;
ASSERT_TRUE(record.BEncode(buf));
buf->cur = buf->base;
// encrypt alice to bob
ASSERT_TRUE(f.EncryptInPlace(alice, llarp::seckey_topublic(bob), &crypto));
ASSERT_TRUE(f.DecryptInPlace(bob, &crypto));
};
Loading…
Cancel
Save