handle inter node messages

currently only handling LIM
pull/1/head
Jeff Becker 6 years ago
parent c2ef57d9a2
commit 93f0e03958
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -27,12 +27,10 @@ set(LIB_SRC
llarp/iwp_link.cpp
llarp/link.c
llarp/link_intro.cpp
llarp/link_relay_down.cpp
llarp/link_relay_up.cpp
llarp/link_message.cpp
llarp/logic.c
llarp/mem.cpp
llarp/mem_std.cpp
llarp/muxer.cpp
llarp/net.cpp
llarp/nodedb.cpp
llarp/router_contact.c

@ -16,7 +16,6 @@ progress()
struct llarp_main
{
struct llarp_alloc mem;
struct llarp_crypto crypto;
struct llarp_router *router = nullptr;
struct llarp_threadpool *worker = nullptr;
@ -182,8 +181,6 @@ main(int argc, char *argv[])
}
sllarp = new llarp_main;
llarp_mem_stdlib(&sllarp->mem);
auto mem = &sllarp->mem;
// llarp_new_config(&sllarp->config);
// llarp_ev_loop_alloc(&sllarp->mainloop);
llarp_crypto_libsodium_init(&sllarp->crypto);
@ -197,8 +194,8 @@ main(int argc, char *argv[])
llarp_rc_clear(&tmp);
// if we zero it out then
// allocate fresh pointers that the bencoder can expect to be ready
tmp.addrs = llarp_ai_list_new(mem);
tmp.exits = llarp_xi_list_new(mem);
tmp.addrs = llarp_ai_list_new();
tmp.exits = llarp_xi_list_new();
// set updated timestamp
tmp.last_updated = llarp_time_now_ms();
// load longterm identity
@ -242,7 +239,7 @@ main(int argc, char *argv[])
buf.sz = sizeof(tmpc);
f.read((char *)tmpc, sizeof(MAX_RC_SIZE));
// printf("contents[%s]\n", tmpc);
if(!llarp_rc_bdecode(mem, &tmp, &buf))
if(!llarp_rc_bdecode(&tmp, &buf))
{
printf("Can't decode\n");
return 0;

@ -39,7 +39,7 @@ struct llarp_ai_list;
/// list of address information initialization
struct llarp_ai_list *
llarp_ai_list_new(struct llarp_alloc *mem);
llarp_ai_list_new();
/// list of address information destruction
void

@ -20,8 +20,8 @@ struct llarp_async_iwp;
/// allocator
struct llarp_async_iwp *
llarp_async_iwp_new(struct llarp_alloc *mem, struct llarp_crypto *crypto,
struct llarp_logic *logic, struct llarp_threadpool *worker);
llarp_async_iwp_new(struct llarp_crypto *crypto, struct llarp_logic *logic,
struct llarp_threadpool *worker);
/// deallocator
void

@ -30,7 +30,7 @@ llarp_xi_bencode(struct llarp_xi *xi, llarp_buffer_t *buf);
struct llarp_xi_list;
struct llarp_xi_list *
llarp_xi_list_new(struct llarp_alloc *mem);
llarp_xi_list_new();
void
llarp_xi_list_free(struct llarp_xi_list *l);

@ -1,15 +0,0 @@
#ifndef LLARP_FRAME_HANDLER_HPP
#define LLARP_FRAME_HANDLER_HPP
#include <llarp/mem.h>
#include <vector>
namespace llarp
{
struct FrameHandler
{
bool
Process(const std::vector< byte_t >& buffer);
};
}
#endif

@ -1,14 +0,0 @@
#ifndef LLARP_IBFQ_H_
#define LLARP_IBFQ_H_
#include <llarp/buffer.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

@ -1,34 +0,0 @@
#ifndef LLARP_IBMQ_H_
#define LLARP_IBMQ_H_
#include <llarp/buffer.h>
#include <llarp/msg_handler.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
struct llarp_mq;
struct llarp_mq *
llarp_init_mq();
void
llarp_free_mq(struct llarp_mq **queue);
/**
offer a full message to the inbound message queue
return true if successfully added
return false if the queue is full
*/
bool
llarp_mq_offer(struct llarp_mq *queue, llarp_buffer_t msg);
size_t
llarp_mq_peek(struct llarp_mq *queue);
/** return true if we have more messages to process */
bool
llarp_mq_process(struct llarp_mq *queue, struct llarp_msg_muxer *muxer);
#ifdef __cplusplus
}
#endif
#endif

@ -2,7 +2,6 @@
#define LLARP_IWP_H_
#include <llarp/crypto.h>
#include <llarp/link.h>
#include <llarp/msg_handler.h>
#include <llarp/router_identity.h>
#ifdef __cplusplus
@ -11,16 +10,15 @@ extern "C" {
struct llarp_iwp_args
{
struct llarp_alloc* mem;
struct llarp_crypto* crypto;
struct llarp_logic* logic;
struct llarp_threadpool* cryptoworker;
struct llarp_router* router;
const char* keyfile;
};
void
iwp_link_init(struct llarp_link* link, struct llarp_iwp_args args,
struct llarp_msg_muxer* muxer);
iwp_link_init(struct llarp_link* link, struct llarp_iwp_args args);
#ifdef __cplusplus
}

@ -5,7 +5,6 @@
#include <llarp/ev.h>
#include <llarp/logic.h>
#include <llarp/mem.h>
#include <llarp/msg_handler.h>
#include <llarp/obmd.h>
#include <stdbool.h>
@ -61,9 +60,13 @@ struct llarp_link_ev_listener
const char *);
};
// forward declare
struct llarp_router;
struct llarp_link
{
void *impl;
struct llarp_router *router;
const char *(*name)(void);
void (*get_our_address)(struct llarp_link *, struct llarp_ai *);
/*
@ -99,6 +102,10 @@ struct llarp_link_session
bool (*timeout)(struct llarp_link_session *);
/** explicit close session */
void (*close)(struct llarp_link_session *);
/** set session established */
void (*established)(struct llarp_link_session *);
/** get router contact of remote router */
struct llarp_rc *(*get_remote_router)(struct llarp_link_session *);
};
bool

@ -0,0 +1,38 @@
#ifndef LLARP_LINK_MESSAGE_HPP
#define LLARP_LINK_MESSAGE_HPP
#include <llarp/bencode.h>
#include <llarp/link.h>
#include <queue>
#include <vector>
namespace llarp
{
typedef std::vector< byte_t > OutboundMessage;
struct InboundMessageHandler
{
InboundMessageHandler(llarp_router* router);
dict_reader reader;
static bool
OnKey(dict_reader* r, llarp_buffer_t* buf);
bool
ProcessFrom(llarp_link_session* from, llarp_buffer_t buf);
bool
FlushReplies();
private:
char msgtype;
bool firstkey;
uint64_t proto;
llarp_router* router;
llarp_link_session* from;
std::queue< OutboundMessage > sendq;
};
}
#endif

@ -1,60 +0,0 @@
#ifndef LLARP_MSG_HANDLER_H_
#define LLARP_MSG_HANDLER_H_
#include <llarp/buffer.h>
#include <llarp/dht.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* foward declare */
struct llarp_msg_muxer;
struct llarp_link_session;
struct llarp_router;
struct llarp_frame_handler
{
/**
* participating paths
*/
struct llarp_path_context *paths;
/**
* parent muxer
*/
struct llarp_msg_muxer *parent;
/**
handle fully formed frame from link session
*/
bool (*process)(struct llarp_frame_handler *, struct llarp_link_session *,
llarp_buffer_t);
};
struct llarp_msg_handler
{
struct llarp_path_context *paths;
struct llarp_dht_context *dht;
bool (*process)(struct llarp_msg_handler *, llarp_buffer_t);
};
struct llarp_msg_muxer
{
/** get a message handler for a link level message given msg.a */
struct llarp_frame_handler *(*link_handler_for)(struct llarp_router *,
const char);
/** get a message handler for a routing layer message given msg.A */
struct llarp_msg_handler *(*routing_handler_for)(struct llarp_router *,
const char);
};
/** fill function pointers with default values */
void
llarp_msg_muxer_init(struct llarp_msg_muxer *muxer);
#ifdef __cplusplus
}
#endif
#endif

@ -1,5 +1,8 @@
#ifndef LLARP_PATH_H
#define LLARP_PATH_H
#ifdef __cplusplus
extern "C" {
#endif
#include <llarp/types.h>
@ -10,9 +13,15 @@ struct llarp_transit_hop
llarp_path_id_t id;
llarp_sharedkey_t symkey;
llarp_pubkey_t nextHop;
llarp_pubkey_t prevHop;
uint64_t started;
uint64_t lifetime;
llarp_version_t version;
llarp_proto_version_t version;
};
struct llarp_path_context;
#ifdef __cplusplus
}
#endif
#endif

@ -2,10 +2,8 @@
#define LLARP_ROUTER_H_
#include <llarp/config.h>
#include <llarp/ev.h>
#include <llarp/ibmq.h>
#include <llarp/link.h>
#include <llarp/logic.h>
#include <llarp/obmd.h>
#include <llarp/router_contact.h>
#include <llarp/threadpool.h>
@ -37,13 +35,6 @@ llarp_run_router(struct llarp_router *router);
void
llarp_stop_router(struct llarp_router *router);
/** get router's inbound link level frame queue */
struct llarp_link_queue *
llarp_router_link_queue(struct llarp_router *router);
/** get router's outbound link level frame dispatcher */
struct llarp_link_dispatcher *
llarp_router_link_dispatcher(struct llarp_router *router);
struct llarp_router_link_iter
{
void *user;

@ -19,8 +19,7 @@ struct llarp_rc
};
bool
llarp_rc_bdecode(struct llarp_alloc *mem, struct llarp_rc *rc,
llarp_buffer_t *buf);
llarp_rc_bdecode(struct llarp_rc *rc, llarp_buffer_t *buf);
bool
llarp_rc_bencode(struct llarp_rc *rc, llarp_buffer_t *buf);

@ -7,12 +7,7 @@
struct llarp_ai_list
{
llarp_alloc *mem;
std::vector< llarp_ai > list;
llarp_ai_list(llarp_alloc *m) : mem(m)
{
}
};
static bool
@ -194,9 +189,9 @@ llarp_ai_list_bencode(struct llarp_ai_list *l, llarp_buffer_t *buff)
}
struct llarp_ai_list *
llarp_ai_list_new(struct llarp_alloc *mem)
llarp_ai_list_new()
{
return new llarp_ai_list(mem);
return new llarp_ai_list;
}
void

@ -6,7 +6,6 @@
struct llarp_async_iwp
{
struct llarp_alloc *mem;
struct llarp_crypto *crypto;
struct llarp_logic *logic;
struct llarp_threadpool *worker;
@ -67,7 +66,6 @@ namespace iwp
buf.cur = buf.base;
buf.sz = intro->sz - 32;
crypto->hmac(intro->buf, buf, sharedkey);
llarp::dumphex< llarp_hmac_t >(intro->buf);
// inform result
llarp_logic_queue_job(intro->iwp->logic, {intro, &inform_intro});
}
@ -300,6 +298,9 @@ namespace iwp
// T = HS(token + n)
memcpy(tmp, token, 32);
memcpy(tmp + 32, N, 32);
buf.base = tmp;
buf.cur = buf.base;
buf.sz = sizeof(tmp);
shorthash(T, buf);
// K = TKE(a.k, b.k, T)
dh(K, a_K, b_sK, T);
@ -335,15 +336,18 @@ namespace iwp
llarp_sharedkey_t digest;
llarp_buffer_t buf;
buf.base = body;
buf.base = nonce;
buf.cur = buf.base;
buf.sz = frame->sz - 64;
buf.sz = frame->sz - 32;
// h = MDS(n + x, S)
crypto->hmac(digest, buf, frame->sessionkey);
// check hmac
frame->success = memcmp(digest, hmac, 32) == 0;
// x = SE(S, p, n[0:24])
buf.base = body;
buf.cur = buf.base;
buf.sz = frame->sz - 64;
crypto->xchacha20(buf, frame->sessionkey, nonce);
// inform result
llarp_logic_queue_job(frame->iwp->logic, {user, &inform_frame_done});
@ -368,6 +372,9 @@ namespace iwp
// x = SE(S, p, n[0:24])
crypto->xchacha20(buf, frame->sessionkey, nonce);
// h = MDS(n + x, S)
buf.base = nonce;
buf.cur = buf.base;
buf.sz = frame->sz - 32;
crypto->hmac(hmac, buf, frame->sessionkey);
// inform result
llarp_logic_queue_job(frame->iwp->logic, {user, &inform_frame_done});
@ -450,13 +457,12 @@ iwp_call_async_verify_session_start(struct llarp_async_iwp *iwp,
}
struct llarp_async_iwp *
llarp_async_iwp_new(struct llarp_alloc *mem, struct llarp_crypto *crypto,
struct llarp_logic *logic, struct llarp_threadpool *worker)
llarp_async_iwp_new(struct llarp_crypto *crypto, struct llarp_logic *logic,
struct llarp_threadpool *worker)
{
llarp_async_iwp *iwp = new llarp_async_iwp;
if(iwp)
{
iwp->mem = mem;
iwp->crypto = crypto;
iwp->logic = logic;
iwp->worker = worker;

@ -2,7 +2,7 @@
#include <llarp/iwp.h>
#include <llarp/net.h>
#include <llarp/time.h>
#include <llarp/frame_handler.hpp>
#include "link/encoder.hpp"
#include <sodium/crypto_sign_ed25519.h>
@ -16,24 +16,18 @@
#include <set>
#include <vector>
#include "buffer.hpp"
#include "crypto.hpp"
#include "fs.hpp"
#include "mem.hpp"
#include "net.hpp"
#include "router.hpp"
namespace iwp
{
// session activity timeout is 10s
constexpr llarp_time_t SESSION_TIMEOUT = 10000;
enum header_flag
{
eSessionInvalidated = (1 << 0),
eHighPacketDrop = (1 << 1),
eHighMTUDetected = (1 << 2),
eProtoUpgrade = (1 << 3)
};
enum msgtype
{
eALIV = 0x00,
@ -42,6 +36,16 @@ namespace iwp
eFRAG = 0x03
};
typedef std::vector< byte_t > sendbuf_t;
enum header_flag
{
eSessionInvalidated = (1 << 0),
eHighPacketDrop = (1 << 1),
eHighMTUDetected = (1 << 2),
eProtoUpgrade = (1 << 3)
};
/** plaintext frame header */
struct frame_header
{
@ -72,16 +76,15 @@ namespace iwp
uint16_t
size() const
{
uint16_t sz = (ptr[3] | 0x00ff) << 8;
sz |= (ptr[2] & 0x00ff);
uint16_t sz;
memcpy(&sz, ptr + 2, 2);
return sz;
}
void
setsize(uint16_t sz)
{
ptr[3] = (sz | 0xff00) >> 8;
ptr[2] = (sz | 0x00ff);
memcpy(ptr + 2, &sz, 2);
}
uint8_t
@ -97,6 +100,19 @@ namespace iwp
}
};
byte_t *
init_sendbuf(sendbuf_t &buf, msgtype t, uint16_t sz, uint8_t flags)
{
buf.resize(6 + sz);
frame_header hdr(buf.data());
hdr.version() = 0;
hdr.msgtype() = t;
hdr.setsize(sz);
buf[4] = 0;
buf[5] = flags;
return hdr.data();
}
/** xmit header */
struct xmit
{
@ -196,7 +212,7 @@ namespace iwp
xmit msginfo;
std::bitset< 16 > status;
std::map< uint16_t, fragment_t > frags;
std::map< uint8_t, fragment_t > frags;
fragment_t lastfrag;
transit_message()
@ -213,11 +229,78 @@ namespace iwp
{
}
void
ack(uint32_t bitmask)
{
uint8_t idx = 0;
while(idx < 16)
{
if(bitmask & (1 << idx))
{
status.set(idx);
}
++idx;
}
}
bool
completed() const
{
for(const auto &item : frags)
{
if(!status.test(item.first))
return false;
}
return true;
}
template < typename T >
void
generate_xmit(T &queue)
{
queue.emplace();
auto &xmitbuf = queue.back();
auto body_ptr = init_sendbuf(xmitbuf, eXMIT,
sizeof(msginfo.buffer) + lastfrag.size(), 0);
memcpy(body_ptr, msginfo.buffer, sizeof(msginfo.buffer));
body_ptr += sizeof(msginfo.buffer);
memcpy(body_ptr, lastfrag.data(), lastfrag.size());
}
template < typename T >
void
retransmit_frags(T &queue)
{
auto msgid = msginfo.msgid();
auto fragsize = msginfo.fragsize();
for(auto &frag : frags)
{
if(status.test(frag.first))
continue;
queue.emplace();
auto &fragbuf = queue.back();
auto body_ptr = init_sendbuf(fragbuf, eFRAG, 9 + fragsize, 0);
memcpy(body_ptr, &msgid, 8);
body_ptr[8] = frag.first;
memcpy(body_ptr + 9, frag.second.data(), fragsize);
}
}
bool
reassemble(std::vector< byte_t > &buffer)
{
// TODO: implement
return false;
auto total = msginfo.totalsize();
printf("reassemble message of size %d\n", total);
buffer.resize(total);
auto fragsz = msginfo.fragsize();
auto ptr = buffer.data();
for(const auto &frag : frags)
{
memcpy(ptr, frag.second.data(), fragsz);
ptr += fragsz;
}
memcpy(ptr, lastfrag.data(), lastfrag.size());
return true;
}
void
@ -225,7 +308,7 @@ namespace iwp
uint16_t mtu = 1024)
{
status.reset();
uint16_t fragid = 0;
uint8_t fragid = 0;
uint16_t fragsize = mtu;
while((buf.cur - buf.base) > fragsize)
{
@ -234,12 +317,12 @@ namespace iwp
buf.cur += fragsize;
frags[fragid++] = frag;
}
uint16_t lastfrag = buf.cur - buf.base;
uint16_t lastfrag = buf.sz - (buf.cur - buf.base);
// set info for xmit
msginfo.set_info(hash, id, mtu, frags.size(), lastfrag);
msginfo.set_info(hash, id, fragsize, lastfrag, frags.size());
// copy message hash
memcpy(msginfo.buffer, hash, 32);
put_lastfrag(buf.cur, buf.cur - buf.base);
put_lastfrag(buf.cur, lastfrag);
}
void
@ -258,47 +341,58 @@ namespace iwp
std::map< uint64_t, transit_message > rx;
std::map< uint64_t, transit_message * > tx;
typedef std::vector< byte_t > sendbuf_t;
std::queue< sendbuf_t > sendqueue;
typedef std::queue< sendbuf_t > sendqueue_t;
llarp::FrameHandler *handler = nullptr;
llarp_router *router = nullptr;
llarp_link_session *parent = nullptr;
sendqueue_t sendqueue;
void
clear()
{
rx.clear();
for(auto &item : tx)
delete item.second;
tx.clear();
}
bool
inbound_frame_complete(uint64_t id)
{
std::vector< byte_t > buf;
if(rx[id].reassemble(buf) && handler)
bool success = false;
std::vector< byte_t > msg;
if(rx[id].reassemble(msg))
{
if(handler->Process(buf))
printf("processed frame %ld\n", id);
else
printf("failed to process frame %ld", id);
printf("handle message of size: %ld\n", msg.size());
auto buf = llarp::Buffer< decltype(msg) >(msg);
success = router->HandleRecvLinkMessage(parent, buf);
if(success)
{
alive();
if(id == 0)
parent->established(parent);
}
}
else
{
printf("failed to reassemble message %ld\n", id);
}
rx.erase(id);
}
void
init_sendbuf(sendbuf_t &buf, msgtype t, uint16_t sz, uint8_t flags)
{
buf.resize(6 + sz);
buf[0] = 0;
buf[1] = t;
buf[2] = sz & 0x00ff;
buf[3] = (sz & 0xff00) >> 8;
buf[4] = 0;
buf[5] = flags;
return success;
}
void
push_ackfor(uint64_t id, uint32_t bitmask)
{
sendbuf_t buf;
sendqueue.emplace();
auto &buf = sendqueue.back();
// TODO: set flags to nonzero as needed
init_sendbuf(buf, eACKS, 12, 0);
// TODO: this assumes big endian
memcpy(buf.data() + 6, &id, 8);
memcpy(buf.data() + 14, &bitmask, 4);
sendqueue.push(buf);
printf("ACK for %ld %d\n", id, bitmask);
}
bool
@ -307,7 +401,7 @@ namespace iwp
if(hdr.size() > sz)
{
// overflow
printf("invalid XMIT frame size\n");
printf("invalid XMIT frame size %d > %ld\n", hdr.size(), sz);
return false;
}
sz = hdr.size();
@ -330,27 +424,26 @@ namespace iwp
// check LSB set on flags
if(x.flags() & 0x01)
{
if(x.numfrags() > 0)
auto id = x.msgid();
auto itr = rx.try_emplace(id, x);
if(itr.second)
{
auto itr = rx.try_emplace(x.msgid(), x);
if(itr.second)
// inserted, put last fragment
itr.first->second.put_lastfrag(hdr.data() + sizeof(x.buffer),
x.lastfrag());
alive();
if(x.numfrags() == 0)
{
// inserted, put last fragment
itr.first->second.put_lastfrag(hdr.data() + sizeof(x.buffer),
x.lastfrag());
return true;
printf("short XMIT\n");
push_ackfor(id, 0);
return inbound_frame_complete(id);
}
else
printf("duplicate XMIT msgid=%ld\n", x.msgid());
printf("got XMIT with %d fragments\n", x.numfrags());
return true;
}
else
{
// short XMIT , no fragments so just ack
auto id = x.msgid();
push_ackfor(
id, 0); // TODO: should this be before or after handling frame?
inbound_frame_complete(id);
}
printf("duplicate XMIT msgid=%ld\n", x.msgid());
}
else
printf("XMIT flags LSB not set\n");
@ -372,14 +465,62 @@ namespace iwp
bool
got_acks(frame_header &hdr, size_t sz)
{
return false;
if(hdr.size() > sz)
{
printf("invalid ACKS frame size %d > %ld\n", hdr.size(), sz);
return false;
}
sz = hdr.size();
if(sz < 12)
{
printf("invalid ACKS frame size %ld < 12\n", sz);
return false;
}
auto ptr = hdr.data();
uint64_t msgid;
uint32_t bitmask;
memcpy(&msgid, ptr, 8);
memcpy(&bitmask, ptr + 8, 4);
auto itr = tx.find(msgid);
if(itr == tx.end())
{
printf("ACK for missing TX frame: %ld\n", msgid);
return false;
}
alive();
itr->second->ack(bitmask);
if(itr->second->completed())
{
printf("message %ld acknoleged\n", msgid);
delete itr->second;
tx.erase(itr);
}
else
{
printf("message %ld retransmit fragments\n", msgid);
itr->second->retransmit_frags(sendqueue);
}
return true;
}
// queue new outbound message
void
queue_tx(uint64_t id, transit_message *msg)
{
tx.try_emplace(id, msg);
auto itr = tx.try_emplace(id, msg);
if(itr.second)
{
msg->generate_xmit(sendqueue);
msg->retransmit_frags(sendqueue);
}
else // duplicate
delete msg;
}
// get next frame to encrypt and transmit
@ -413,11 +554,11 @@ namespace iwp
alive();
return true;
case eXMIT:
return got_xmit(hdr, sz - 4);
return got_xmit(hdr, sz - 6);
case eACKS:
return got_acks(hdr, sz - 4);
return got_acks(hdr, sz - 6);
case eFRAG:
return got_frag(hdr, sz - 4);
return got_frag(hdr, sz - 6);
default:
return false;
}
@ -427,12 +568,16 @@ namespace iwp
struct session
{
llarp_alloc *mem;
llarp_msg_muxer *muxer;
llarp_udp_io *udp;
llarp_crypto *crypto;
llarp_async_iwp *iwp;
llarp_logic *logic;
llarp_rc *our_router;
llarp_link_session *parent = nullptr;
llarp_link *link = nullptr;
llarp_rc *our_router = nullptr;
llarp_rc remote_router;
llarp_seckey_t eph_seckey;
llarp_pubkey_t remote;
@ -440,6 +585,8 @@ namespace iwp
llarp_link_establish_job *establish_job = nullptr;
uint32_t establish_job_id = 0;
llarp::Addr addr;
iwp_async_intro intro;
iwp_async_introack introack;
@ -456,23 +603,18 @@ namespace iwp
eIntroSent,
eIntroAckSent,
eIntroAckRecv,
eSessionStartSent,
eLIMSent,
eEstablished,
eTimeout
};
State state;
session(llarp_alloc *m, llarp_msg_muxer *mux, llarp_udp_io *u,
llarp_async_iwp *i, llarp_crypto *c, llarp_logic *l,
const byte_t *seckey, const llarp::Addr &a)
: mem(m)
, muxer(mux)
, udp(u)
, crypto(c)
, iwp(i)
, logic(l)
, addr(a)
, state(eInitial)
session(llarp_alloc *m, llarp_udp_io *u, llarp_async_iwp *i,
llarp_crypto *c, llarp_logic *l, const byte_t *seckey,
const llarp::Addr &a)
: mem(m), udp(u), crypto(c), iwp(i), logic(l), addr(a), state(eInitial)
{
if(seckey)
memcpy(eph_seckey, seckey, sizeof(llarp_seckey_t));
@ -480,10 +622,21 @@ namespace iwp
{
c->encryption_keygen(eph_seckey);
}
llarp::Zero(&remote_router, sizeof(llarp_rc));
}
~session()
{
llarp_rc_free(&remote_router);
frame.clear();
}
static llarp_rc *
get_remote_router(llarp_link_session *s)
{
session *self = static_cast< session * >(s->impl);
return &self->remote_router;
}
static bool
@ -513,6 +666,7 @@ namespace iwp
while(frame.next_frame(buf))
{
encrypt_frame_async_send(buf.base, buf.sz);
frame.pop_next_frame();
}
}
@ -534,6 +688,9 @@ namespace iwp
// probably a session start
on_session_start(buf, sz);
return;
case eSessionStartSent:
case eLIMSent:
case eEstablished:
// session is started
decrypt_frame(buf, sz);
@ -554,11 +711,43 @@ namespace iwp
printf("session start verify fail\n");
return;
}
printf("session start okay\n");
printf("session start verified, sending LIM\n");
self->send_LIM();
}
// auto msg = new transit_message;
void
send_LIM()
{
llarp_shorthash_t digest;
// 64 bytes overhead for link message
byte_t tmp[MAX_RC_SIZE + 64];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
// return a llarp_buffer_t of encoded link message
if(llarp::EncodeLIM(&buf, our_router))
{
// rewind message buffer
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
auto msg = new transit_message;
// hash message buffer
crypto->shorthash(digest, buf);
// put message buffer
auto id = frame.txids++;
msg->put_message(buf, digest, id);
// put into outbound send queue
add_outbound_message(id, msg);
EnterState(eLIMSent);
}
else
printf("failed to encode LIM\n");
}
// auto buffer = llarp::EncodeLIM< decltype(buf) >(buf, our_router);
void
session_established()
{
printf("session established\n");
EnterState(eEstablished);
llarp_logic_cancel_call(logic, establish_job_id);
}
void
@ -592,6 +781,12 @@ namespace iwp
return static_cast< session * >(s->impl)->timedout(now);
}
static void
set_established(llarp_link_session *s)
{
static_cast< session * >(s->impl)->session_established();
}
static void
close(llarp_link_session *s)
{
@ -620,7 +815,7 @@ namespace iwp
{
session *link = static_cast< session * >(start->user);
llarp_ev_udp_sendto(link->udp, link->addr, start->buf, start->sz);
link->EnterState(eEstablished);
link->EnterState(eSessionStartSent);
printf("session start sent\n");
}
@ -650,7 +845,12 @@ namespace iwp
session *self = static_cast< session * >(frame->user);
if(frame->success)
{
self->frame.process(frame->buf + 64, frame->sz - 64);
if(self->frame.process(frame->buf + 64, frame->sz - 64))
{
self->pump();
}
else
printf("invalid frame\n");
}
else
printf("decrypt frame fail\n");
@ -703,7 +903,7 @@ namespace iwp
printf("encrypt frame of size %ld\n", sz);
// 64 bytes frame overhead for nonce and hmac
auto frame = alloc_frame(nullptr, sz + 64);
memcpy(frame->buf + 64, buf, sz - 64);
memcpy(frame->buf + 64, buf, sz);
frame->hook = &handle_frame_encrypt;
iwp_call_async_frame_encrypt(iwp, frame);
}
@ -832,6 +1032,29 @@ namespace iwp
}
}
static void
handle_establish_timeout(void *user, uint64_t orig, uint64_t left)
{
session *self = static_cast< session * >(user);
if(self->establish_job)
{
self->establish_job->link = self->link;
if(left)
{
// timer cancelled
self->establish_job->session = self->parent;
}
else
{
// timer timeout
self->establish_job->session = nullptr;
}
self->establish_job->result(self->establish_job);
delete self->establish_job;
self->establish_job = nullptr;
}
}
void
introduce(uint8_t *pub)
{
@ -856,13 +1079,15 @@ namespace iwp
intro.user = this;
intro.hook = &handle_generated_intro;
iwp_call_async_gen_intro(iwp, &intro);
// start introduce timer
establish_job_id = llarp_logic_call_later(
logic, {5000, this, &handle_establish_timeout});
}
void
EnterState(State st)
{
if(state == eInitial)
frame.alive();
frame.alive();
state = st;
}
};
@ -872,12 +1097,13 @@ namespace iwp
typedef std::mutex mtx_t;
typedef std::lock_guard< mtx_t > lock_t;
llarp_router *router;
llarp_alloc *mem;
llarp_logic *logic;
llarp_crypto *crypto;
llarp_ev_loop *netloop;
llarp_msg_muxer *muxer;
llarp_async_iwp *iwp;
llarp_link *link = nullptr;
llarp_udp_io udp;
llarp::Addr addr;
char keyfile[255];
@ -890,12 +1116,13 @@ namespace iwp
llarp_seckey_t seckey;
server(llarp_alloc *m, llarp_crypto *c, llarp_logic *l, llarp_threadpool *w)
server(llarp_router *r, llarp_crypto *c, llarp_logic *l,
llarp_threadpool *w)
{
mem = m;
router = r;
crypto = c;
logic = l;
iwp = llarp_async_iwp_new(mem, crypto, logic, w);
iwp = llarp_async_iwp_new(crypto, logic, w);
}
~server()
@ -906,7 +1133,7 @@ namespace iwp
session *
create_session(const llarp::Addr &src, const byte_t *seckey)
{
return new session(mem, muxer, &udp, iwp, crypto, logic, seckey, src);
return new session(mem, &udp, iwp, crypto, logic, seckey, src);
}
bool
@ -924,10 +1151,17 @@ namespace iwp
s.sendto = &session::sendto;
s.timeout = &session::is_timedout;
s.close = &session::close;
s.get_remote_router = &session::get_remote_router;
s.established = &session::set_established;
{
lock_t lock(m_sessions_Mutex);
m_sessions[src] = s;
impl->parent = &m_sessions[src];
}
impl->link = link;
impl->frame.router = router;
impl->frame.parent = impl->parent;
impl->our_router = &router->rc;
}
session *
@ -1078,12 +1312,11 @@ namespace iwp
};
server *
link_alloc(struct llarp_alloc *mem, struct llarp_msg_muxer *muxer,
const char *keyfile, struct llarp_crypto *crypto,
struct llarp_logic *logic, struct llarp_threadpool *worker)
link_alloc(struct llarp_router *router, const char *keyfile,
struct llarp_crypto *crypto, struct llarp_logic *logic,
struct llarp_threadpool *worker)
{
server *link = new server(mem, crypto, logic, worker);
link->muxer = muxer;
server *link = new server(router, crypto, logic, worker);
llarp::Zero(link->keyfile, sizeof(link->keyfile));
strncpy(link->keyfile, keyfile, sizeof(link->keyfile));
return link;
@ -1167,7 +1400,9 @@ namespace iwp
bool
link_start(struct llarp_link *l, struct llarp_logic *logic)
{
server *link = static_cast< server * >(l->impl);
server *link = static_cast< server * >(l->impl);
// give link implementations
link->link = l;
link->timeout_job_id = 0;
link->logic = logic;
// start cleanup timer
@ -1236,10 +1471,9 @@ namespace iwp
extern "C" {
void
iwp_link_init(struct llarp_link *link, struct llarp_iwp_args args,
struct llarp_msg_muxer *muxer)
iwp_link_init(struct llarp_link *link, struct llarp_iwp_args args)
{
link->impl = iwp::link_alloc(args.mem, muxer, args.keyfile, args.crypto,
link->impl = iwp::link_alloc(args.router, args.keyfile, args.crypto,
args.logic, args.cryptoworker);
link->name = iwp::link_name;
link->get_our_address = iwp::link_get_addr;

@ -12,5 +12,6 @@ llarp_link_initialized(struct llarp_link* link)
bool
llarp_link_session_initialized(struct llarp_link_session* s)
{
return s && s->impl && s->sendto && s->timeout && s->close;
return s && s->impl && s->sendto && s->timeout && s->close
&& s->get_remote_router && s->established;
}

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

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

@ -0,0 +1,114 @@
#include <llarp/router_contact.h>
#include <llarp/link_message.hpp>
#include "buffer.hpp"
namespace llarp
{
InboundMessageHandler::InboundMessageHandler(llarp_router* _router)
: router(_router)
{
reader.user = this;
reader.on_key = &OnKey;
}
bool
InboundMessageHandler::OnKey(dict_reader* r, llarp_buffer_t* key)
{
InboundMessageHandler* handler =
static_cast< InboundMessageHandler* >(r->user);
llarp_buffer_t strbuf;
// we are reading the first key
if(handler->firstkey)
{
// check for empty dict
if(!key)
return false;
// we are expecting the first key to be 'a'
if(!llarp_buffer_eq(*key, "a"))
{
printf("message does not have message type\n");
return false;
}
if(!bdecode_read_string(r->buffer, &strbuf))
{
printf("could not value of message type");
return false;
}
// bad key size
if(strbuf.sz != 1)
{
printf("bad mesage type size: %ld\n", strbuf.sz);
return false;
}
handler->msgtype = *strbuf.cur;
handler->firstkey = false;
return true;
}
// check for not the last element
if(!key)
return true;
switch(handler->msgtype)
{
// LIM
case 'i':
if(llarp_buffer_eq(*key, "r"))
{
if(!llarp_rc_bdecode(handler->from->get_remote_router(handler->from),
r->buffer))
{
printf("failed to decode RC\n");
return false;
}
printf("decoded rc\n");
return true;
}
else if(llarp_buffer_eq(*key, "v"))
{
if(!bdecode_read_integer(r->buffer, &handler->proto))
return false;
if(handler->proto != LLARP_PROTO_VERSION)
{
printf("llarp protocol version missmatch\n");
return false;
}
return true;
}
else
{
printf("invalid LIM key: %c\n", *key->cur);
return false;
}
default:
printf("unknown link message type: %c\n", handler->msgtype);
return false;
}
}
bool
InboundMessageHandler::ProcessFrom(llarp_link_session* src,
llarp_buffer_t buf)
{
from = src;
msgtype = 0;
firstkey = true;
return bdecode_read_dict(&buf, &reader);
}
bool
InboundMessageHandler::FlushReplies()
{
printf("sending replies\n");
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;
}
}

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

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

@ -1,5 +1,6 @@
#ifndef LLARP_MEM_HPP
#define LLARP_MEM_HPP
#include <llarp/buffer.h>
#include <llarp/mem.h>
#include <stdio.h>
@ -42,6 +43,20 @@ namespace llarp
}
}
template < typename T >
void
dumphex_buffer(T buff)
{
size_t idx = 0;
printf("buffer of size %ld\n", buff.sz);
while(idx < buff.sz)
{
printf("%.2x ", buff.base[idx++]);
if(idx % 8 == 0)
printf("\n");
}
}
} // namespace llarp
#endif

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

@ -66,7 +66,7 @@ struct llarp_nodedb
fclose(f);
llarp_rc *rc = llarp::Alloc< llarp_rc >(mem);
llarp::Zero(rc, sizeof(llarp_rc));
if(llarp_rc_bdecode(mem, rc, &buff))
if(llarp_rc_bdecode(rc, &buff))
{
if(llarp_rc_verify_sig(crypto, rc))
{

@ -1,10 +1,10 @@
#include "router.hpp"
#include <llarp/dtls.h>
#include <llarp/ibfq.h>
#include <llarp/iwp.h>
#include <llarp/link.h>
#include <llarp/proto.h>
#include <llarp/router.h>
#include <llarp/link_message.hpp>
#include "buffer.hpp"
#include "net.hpp"
#include "str.hpp"
@ -18,10 +18,10 @@ namespace llarp
const char *key, const char *val);
} // namespace llarp
llarp_router::llarp_router(struct llarp_alloc *m) : ready(false), mem(m)
llarp_router::llarp_router(struct llarp_alloc *m)
: ready(false), mem(m), inbound_msg_handler(this)
{
llarp_rc_clear(&rc);
llarp_msg_muxer_init(&muxer);
}
llarp_router::~llarp_router()
@ -29,6 +29,18 @@ llarp_router::~llarp_router()
llarp_rc_free(&rc);
}
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;
}
void
llarp_router::try_connect(fs::path rcfile)
{
@ -57,7 +69,7 @@ llarp_router::try_connect(fs::path rcfile)
return;
}
}
if(llarp_rc_bdecode(mem, &remote, &buf))
if(llarp_rc_bdecode(&remote, &buf))
{
if(llarp_rc_verify_sig(&crypto, &remote))
{
@ -142,7 +154,6 @@ llarp_router::on_try_connect_result(llarp_link_establish_job *job)
printf("session made\n");
else
printf("session not made\n");
delete job;
}
void
@ -151,7 +162,7 @@ llarp_router::Run()
// zero out router contact
llarp::Zero(&rc, sizeof(llarp_rc));
// fill our address list
rc.addrs = llarp_ai_list_new(mem);
rc.addrs = llarp_ai_list_new();
for(auto link : links)
{
llarp_ai addr;
@ -224,7 +235,6 @@ llarp_init_router(struct llarp_alloc *mem, struct llarp_threadpool *tp,
router->tp = tp;
router->logic = logic;
llarp_crypto_libsodium_init(&router->crypto);
llarp_msg_muxer_init(&router->muxer);
}
return router;
}
@ -286,7 +296,7 @@ void
llarp_rc_set_addrs(struct llarp_rc *rc, struct llarp_alloc *mem,
struct llarp_ai_list *addr)
{
rc->addrs = llarp_ai_list_new(mem);
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;
@ -418,13 +428,13 @@ namespace llarp
llarp::Zero(link, sizeof(llarp_link));
llarp_iwp_args args = {
.mem = self->mem,
.crypto = &self->crypto,
.logic = self->logic,
.cryptoworker = self->tp,
.router = self,
.keyfile = self->transport_keyfile.c_str(),
};
iwp_link_init(link, args, &self->muxer);
iwp_link_init(link, args);
if(llarp_link_initialized(link))
{
if(link->configure(link, self->netloop, key, af, proto))

@ -1,12 +1,15 @@
#ifndef LLARP_ROUTER_HPP
#define LLARP_ROUTER_HPP
#include <llarp/link.h>
#include <llarp/path.h>
#include <llarp/router.h>
#include <llarp/router_contact.h>
#include <functional>
#include <list>
#include <map>
#include <llarp/link_message.hpp>
#include "fs.hpp"
#include "mem.hpp"
@ -35,23 +38,27 @@ struct llarp_router
// path to write our self signed rc to
fs::path our_rc_file = "rc.signed";
// our router contact
llarp_rc rc;
llarp_ev_loop *netloop;
llarp_threadpool *tp;
llarp_logic *logic;
llarp_crypto crypto;
llarp_msg_muxer muxer;
llarp_path_context *paths;
llarp_alloc *mem;
llarp_seckey_t identity;
llarp::InboundMessageHandler inbound_msg_handler;
std::list< llarp_link * > links;
std::map< char, llarp_frame_handler > frame_handlers;
llarp_router(llarp_alloc *mem);
~llarp_router();
bool
HandleRecvLinkMessage(struct llarp_link_session *from, llarp_buffer_t msg);
void
AddLink(struct llarp_link *link);

@ -25,9 +25,7 @@ llarp_rc_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
{
uint64_t v;
llarp_buffer_t strbuf;
struct llarp_rc_decoder *dec = r->user;
struct llarp_alloc *mem = dec->mem;
struct llarp_rc *rc = dec->rc;
struct llarp_rc *rc = r->user;
if(!key)
return true;
@ -38,7 +36,7 @@ llarp_rc_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
{
llarp_ai_list_free(rc->addrs);
}
rc->addrs = llarp_ai_list_new(mem);
rc->addrs = llarp_ai_list_new();
return llarp_ai_list_bdecode(rc->addrs, r->buffer);
}
@ -72,7 +70,7 @@ llarp_rc_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
{
llarp_xi_list_free(rc->exits);
}
rc->exits = llarp_xi_list_new(mem);
rc->exits = llarp_xi_list_new();
return llarp_xi_list_bdecode(rc->exits, r->buffer);
}
@ -90,11 +88,9 @@ llarp_rc_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
}
bool
llarp_rc_bdecode(struct llarp_alloc *mem, struct llarp_rc *rc,
llarp_buffer_t *buff)
llarp_rc_bdecode(struct llarp_rc *rc, llarp_buffer_t *buff)
{
struct llarp_rc_decoder decode = {.rc = rc, .mem = mem};
struct dict_reader r = {.user = &decode, .on_key = &llarp_rc_decode_dict};
struct dict_reader r = {.user = rc, .on_key = &llarp_rc_decode_dict};
return bdecode_read_dict(buff, &r);
}
@ -135,6 +131,7 @@ llarp_rc_bencode(struct llarp_rc *rc, llarp_buffer_t *buff)
/* write dict begin */
if(!bencode_start_dict(buff))
return false;
if(rc->addrs)
{
/* write ai if they exist */

@ -76,20 +76,13 @@ struct llarp_timer_context
}
void
cancel(uint32_t id, bool lockit = true)
cancel(uint32_t id)
{
std::unique_lock< std::mutex >* lock = nullptr;
if(lockit)
lock = new std::unique_lock< std::mutex >(timersMutex);
auto itr = timers.find(id);
if(itr != timers.end())
{
itr->second.exec();
}
if(lock)
delete lock;
}
void
@ -122,7 +115,7 @@ struct llarp_timer_context
for(auto id : ids)
{
cancel(id, false);
cancel(id);
}
}
};

Loading…
Cancel
Save