remove iwp and start on curvecp

does not compile
pull/15/head
Jeff Becker 6 years ago
parent 7765d7c006
commit c3c388b6aa
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -144,7 +144,11 @@ else()
)
endif()
set(LIBS ${SODIUM_LIB} ${THREAD_LIB})
find_package(OpenSSL)
include_directories(${OPENSSL_INCLUDE_DIR})
set(LIBS ${SODIUM_LIB} ${THREAD_LIB} ${OPENSSL_LIBRARIES})
set(LIB lokinet)
set(SHARED_LIB ${LIB})
@ -331,7 +335,6 @@ set(LIB_SRC
llarp/pathbuilder.cpp
llarp/pathset.cpp
llarp/proofofwork.cpp
llarp/relay_ack.cpp
llarp/relay_commit.cpp
llarp/relay_up_down.cpp
llarp/router_contact.cpp
@ -339,6 +342,8 @@ set(LIB_SRC
llarp/service.cpp
llarp/transit_hop.cpp
llarp/testnet.c
llarp/curvecp/server.cpp
llarp/curvecp/client.cpp
llarp/dht/context.cpp
llarp/dht/decode.cpp
llarp/dht/dht_immediate.cpp
@ -348,12 +353,6 @@ set(LIB_SRC
llarp/dht/got_router.cpp
llarp/dht/publish_intro.cpp
llarp/handlers/tun.cpp
llarp/iwp/frame_header.cpp
llarp/iwp/frame_state.cpp
llarp/iwp/session.cpp
llarp/iwp/server.cpp
llarp/iwp/transit_message.cpp
llarp/iwp/xmit.cpp
llarp/link/encoder.cpp
llarp/routing/dht_message.cpp
llarp/routing/message_parser.cpp

@ -221,7 +221,7 @@ main(int argc, char *argv[])
if(verifyMode)
{
llarp_crypto crypto;
llarp_crypto_libsodium_init(&crypto);
llarp_crypto_init(&crypto);
if(!rc.Read(rcfname))
{
std::cout << "failed to read " << rcfname << std::endl;
@ -277,7 +277,7 @@ main(int argc, char *argv[])
if(listMode)
{
llarp_crypto crypto;
llarp_crypto_libsodium_init(&crypto);
llarp_crypto_init(&crypto);
auto nodedb = llarp_nodedb_new(&crypto);
llarp_nodedb_iter itr;
itr.visit = [](llarp_nodedb_iter *i) -> bool {
@ -298,7 +298,7 @@ main(int argc, char *argv[])
return 1;
}
llarp_crypto crypto;
llarp_crypto_libsodium_init(&crypto);
llarp_crypto_init(&crypto);
auto nodedb = llarp_nodedb_new(&crypto);
if(!llarp_nodedb_ensure_dir(nodesdir))
{
@ -354,7 +354,7 @@ main(int argc, char *argv[])
rc.last_updated = llarp_time_now_ms();
// load longterm identity
llarp_crypto crypt;
llarp_crypto_libsodium_init(&crypt);
llarp_crypto_init(&crypt);
// which is in daemon.ini config: router.encryption-privkey (defaults
// "encryption.key")

@ -121,7 +121,6 @@ namespace llarp
// lowest, " dropMs: ", dropMs);
if(lowest > dropMs)
{
llarp::LogInfo(m_name, " dropping");
item->~T();
nextTickInterval += initialIntervalMs / std::sqrt(++dropNum);
firstPut = 0;

@ -4,6 +4,7 @@
#include <llarp/common.h>
#include <stdbool.h>
#include <stdint.h>
#include <openssl/ssl.h>
/**
* crypto.h
@ -100,9 +101,9 @@ struct llarp_crypto
bool (*pqe_encrypt)(byte_t *, byte_t *, const byte_t *);
};
/// set crypto function pointers to use libsodium
/// initialize crypto subsystem
void
llarp_crypto_libsodium_init(struct llarp_crypto *c);
llarp_crypto_init(struct llarp_crypto *c);
/// check for initialize crypto
bool

@ -174,9 +174,9 @@ namespace llarp
/// get routers closest to target excluding requester
bool
HandleExploritoryRouterLookup(const Key_t& requester, uint64_t txid,
const RouterID& target,
std::vector< IMessage* >& reply);
HandleExploritoryRouterLookup(
const Key_t& requester, uint64_t txid, const RouterID& target,
std::vector< std::unique_ptr< IMessage > >& reply);
std::set< service::IntroSet >
FindRandomIntroSetsWithTagExcluding(
@ -187,7 +187,7 @@ namespace llarp
void
LookupRouterRelayed(const Key_t& requester, uint64_t txid,
const Key_t& target, bool recursive,
std::vector< IMessage* >& replies);
std::vector< std::unique_ptr< IMessage > >& replies);
/// relay a dht messeage from a local path to the main network
bool

@ -22,19 +22,21 @@ namespace llarp
}
virtual bool
HandleMessage(llarp_dht_context* dht,
std::vector< IMessage* >& replies) const = 0;
HandleMessage(
llarp_dht_context* dht,
std::vector< std::unique_ptr< IMessage > >& replies) const = 0;
Key_t From;
PathID_t pathID;
};
IMessage*
std::unique_ptr< IMessage >
DecodeMessage(const Key_t& from, llarp_buffer_t* buf, bool relayed = false);
bool
DecodeMesssageList(const Key_t& from, llarp_buffer_t* buf,
std::vector< IMessage* >& dst, bool relayed = false);
DecodeMesssageList(Key_t from, llarp_buffer_t* buf,
std::vector< std::unique_ptr< IMessage > >& dst,
bool relayed = false);
} // namespace dht
} // namespace llarp

@ -44,7 +44,7 @@ namespace llarp
bool
HandleMessage(llarp_dht_context* ctx,
std::vector< IMessage* >& replies) const;
std::vector< std::unique_ptr< IMessage > >& replies) const;
};
} // namespace dht
} // namespace llarp

@ -34,7 +34,7 @@ namespace llarp
virtual bool
HandleMessage(llarp_dht_context* ctx,
std::vector< IMessage* >& replies) const;
std::vector< std::unique_ptr< IMessage > >& replies) const;
RouterID K;
bool iterative = false;
@ -55,7 +55,7 @@ namespace llarp
/// TODO: smart path expiration logic needs to be implemented
virtual bool
HandleMessage(llarp_dht_context* ctx,
std::vector< IMessage* >& replies) const;
std::vector< std::unique_ptr< IMessage > >& replies) const;
};
} // namespace dht
} // namespace llarp

@ -31,7 +31,7 @@ namespace llarp
virtual bool
HandleMessage(llarp_dht_context* ctx,
std::vector< IMessage* >& replies) const;
std::vector< std::unique_ptr< IMessage > >& replies) const;
};
struct RelayedGotIntroMessage : public GotIntroMessage
@ -42,7 +42,7 @@ namespace llarp
bool
HandleMessage(llarp_dht_context* ctx,
std::vector< IMessage* >& replies) const;
std::vector< std::unique_ptr< IMessage > >& replies) const;
};
} // namespace dht
} // namespace llarp

@ -36,7 +36,7 @@ namespace llarp
virtual bool
HandleMessage(llarp_dht_context* ctx,
std::vector< IMessage* >& replies) const;
std::vector< std::unique_ptr< IMessage > >& replies) const;
std::vector< RouterContact > R;
std::vector< RouterID > N;

@ -38,8 +38,8 @@ namespace llarp
virtual bool
HandleMessage(llarp_dht_context* ctx,
std::vector< IMessage* >& replies) const;
std::vector< std::unique_ptr< IMessage > >& replies) const;
};
} // namespace dht
} // namespace llarp
#endif
#endif

@ -0,0 +1,31 @@
#ifndef LLARP_DTLS_HPP
#define LLARP_DTLS_HPP
#include <openssl/ssl.h>
namespace llarp
{
namespace dtls
{
struct Base
{
Base(uint16_t mtu)
{
_ctx = SSL_CTX_new(DTLS_with_buffers_method());
SSL_CTX_set_custom_verify(_ctx, SSL_VERIFY_PEER, []());
}
~Base()
{
if(_ctx)
SSL_CTX_free(_ctx);
}
SSL_CTX* _ctx = nullptr;
};
} // namespace dtls
} // namespace llarp
#endif

@ -0,0 +1,33 @@
#ifndef LLARP_ESTABLISH_JOB_HPP
#define LLARP_ESTABLISH_JOB_HPP
namespace llarp
{
struct OutboundLinkEstablishJob
{
RouterContact rc;
OutboundLinkEstablishJob(const RouterContact& remote) : rc(remote)
{
}
virtual ~OutboundLinkEstablishJob(){};
virtual void
Success() = 0;
virtual void
Failed() = 0;
virtual void
AttemptTimedout() = 0;
virtual void
Attempt() = 0;
virtual bool
ShouldRetry() const = 0;
};
} // namespace llarp
#endif

@ -9,7 +9,7 @@ struct llarp_iwp_args
struct llarp_logic* logic;
struct llarp_threadpool* cryptoworker;
struct llarp_router* router;
std::string keyfile;
bool permitInbound;
};
#endif

@ -1,21 +0,0 @@
#pragma once
#include "llarp/address_info.hpp"
struct llarp_link;
struct llarp_link_session;
struct llarp_link_establish_job
{
void *user;
void (*result)(struct llarp_link_establish_job *);
llarp::AddressInfo ai;
uint64_t timeout;
uint16_t retries;
llarp::PubKey pubkey;
/** set on success by try_establish */
struct llarp_link *link;
/** set on success by try_establish */
struct llarp_link_session *session;
};

@ -1,39 +0,0 @@
#pragma once
#include "llarp/buffer.h"
enum header_flag
{
eSessionInvalidated = (1 << 0),
eHighPacketDrop = (1 << 1),
eHighMTUDetected = (1 << 2),
eProtoUpgrade = (1 << 3)
};
struct frame_header
{
byte_t *ptr;
frame_header(byte_t *buf);
byte_t *
data();
uint8_t &
version();
uint8_t &
msgtype();
uint16_t
size() const;
void
setsize(uint16_t sz);
uint8_t &
flags();
void
setflag(header_flag f);
};

@ -1,118 +0,0 @@
#pragma once
#include <llarp/codel.hpp>
#include <llarp/crypto.hpp>
#include "frame_header.hpp"
#include "inbound_message.hpp"
#include "llarp/logger.hpp"
#include "llarp/time.h"
#include "llarp/types.h"
#include "sendbuf.hpp"
#include "sendqueue.hpp"
#include "transit_message.hpp"
#include <queue>
#include <unordered_map>
enum msgtype
{
eALIV = 0x00,
eXMIT = 0x01,
eACKS = 0x02,
eFRAG = 0x03
};
static inline byte_t *
init_sendbuf(sendbuf_t *buf, msgtype t, uint16_t sz, uint8_t flags)
{
frame_header hdr(buf->data());
hdr.version() = 0;
hdr.msgtype() = t;
hdr.setsize(sz);
buf->data()[4] = 0;
buf->data()[5] = flags;
return hdr.data();
}
struct llarp_router;
struct llarp_link_session;
struct frame_state
{
byte_t rxflags = 0;
byte_t txflags = 0;
uint64_t rxids = 0;
uint64_t txids = 0;
llarp_time_t lastEvent = 0;
std::unordered_map< uint64_t, llarp::ShortHash > rxIDs;
std::unordered_map< llarp::ShortHash, transit_message,
llarp::ShortHash::Hash >
rx;
std::unordered_map< uint64_t, transit_message > tx;
typedef llarp::util::CoDelQueue<
InboundMessage, InboundMessage::GetTime, InboundMessage::PutTime,
InboundMessage::OrderCompare, llarp::util::DummyMutex,
llarp::util::DummyLock >
recvqueue_t;
llarp_link_session *parent = nullptr;
sendqueue_t sendqueue;
recvqueue_t recvqueue;
uint64_t nextMsgID = 0;
frame_state(llarp_link_session *session)
: parent(session)
, sendqueue("iwp_outbound_message")
, recvqueue("iwp_inbound_message")
{
}
/// return true if both sides have the same state flags
bool
flags_agree(byte_t flags) const;
bool
either_has_flag(byte_t flag) const;
bool
process_inbound_queue();
llarp_router *
Router();
void
clear();
bool
inbound_frame_complete(const transit_message &msg);
void
push_ackfor(uint64_t id, uint32_t bitmask);
bool
got_xmit(frame_header hdr, size_t sz);
void
alive();
bool
got_frag(frame_header hdr, size_t sz);
bool
got_acks(frame_header hdr, size_t sz);
void
retransmit(llarp_time_t now);
// get next frame to encrypt and transmit
bool
next_frame(llarp_buffer_t *buf);
void
pop_next_frame();
bool
process(byte_t *buf, size_t sz);
};

@ -1,67 +0,0 @@
#pragma once
#include "buffer.hpp"
#include "llarp/time.h"
#include "llarp/types.h"
#include <vector>
struct InboundMessage
{
uint64_t msgid;
std::vector< byte_t > msg;
llarp_time_t queued = 0;
InboundMessage()
{
}
InboundMessage(uint64_t id, const std::vector< byte_t > &m)
: msgid(id), msg(m)
{
}
~InboundMessage()
{
}
bool
operator<(const InboundMessage &other) const
{
// order in ascending order for codel queue
return msgid < other.msgid;
}
llarp_buffer_t
Buffer() const
{
return llarp::ConstBuffer(msg);
}
struct GetTime
{
llarp_time_t
operator()(const InboundMessage &msg)
{
return msg.queued;
}
};
struct OrderCompare
{
bool
operator()(const InboundMessage &left, const InboundMessage &right) const
{
return left < right;
}
};
struct PutTime
{
void
operator()(InboundMessage &msg)
{
msg.queued = llarp_time_now_ms();
}
};
};

@ -1,86 +0,0 @@
#pragma once
#include <llarp/buffer.h>
#include <llarp/time.h>
#include <memory>
#include <queue>
struct sendbuf_t
{
sendbuf_t()
{
_sz = 0;
}
sendbuf_t(const sendbuf_t &other)
{
_sz = std::min(other._sz, sizeof(_buf));
memcpy(_buf, other._buf, _sz);
}
sendbuf_t(size_t s)
{
if(s > sizeof(_buf))
throw std::logic_error("sendbuf too big");
_sz = s;
}
~sendbuf_t()
{
}
size_t
size() const
{
return _sz;
}
byte_t *
data()
{
return _buf;
}
llarp_buffer_t
Buffer()
{
llarp_buffer_t buf;
buf.base = _buf;
buf.sz = _sz;
buf.cur = buf.base;
return buf;
}
struct GetTime
{
llarp_time_t
operator()(const sendbuf_t &buf) const
{
return buf.timestamp;
}
};
struct PutTime
{
void
operator()(sendbuf_t &buf) const
{
buf.timestamp = llarp_time_now_ms();
}
};
struct Compare
{
bool
operator()(const sendbuf_t &left, const sendbuf_t &right) const
{
return left.timestamp > right.timestamp;
}
};
llarp_time_t timestamp = 0;
private:
size_t _sz;
byte_t _buf[1500];
};

@ -1,11 +0,0 @@
#ifndef LLARP_IWP_SENDQUEUE_HPP
#define LLARP_IWP_SENDQUEUE_HPP
#include <llarp/codel.hpp>
#include <llarp/iwp/sendbuf.hpp>
typedef llarp::util::CoDelQueue<
sendbuf_t, sendbuf_t::GetTime, sendbuf_t::PutTime, sendbuf_t::Compare,
llarp::util::DummyMutex, llarp::util::DummyLock >
sendqueue_t;
#endif

@ -1,148 +0,0 @@
#pragma once
#include <llarp/iwp.hpp>
#include <llarp/threading.hpp>
#include "llarp/iwp/establish_job.hpp"
#include "router.hpp"
#include "session.hpp"
#ifndef __linux__
#ifdef saddr
#undef saddr
#endif
#endif
#include <algorithm>
#include <fstream>
struct llarp_link
{
typedef llarp::util::Mutex mtx_t;
typedef llarp::util::Lock lock_t;
llarp_router *router;
llarp_crypto *crypto;
llarp_logic *logic;
llarp_ev_loop *netloop;
llarp_async_iwp *iwp;
llarp_threadpool *worker;
llarp_link *parent = nullptr;
llarp_udp_io udp;
llarp::Addr addr;
std::string keyfile;
uint32_t timeout_job_id;
const char *
name() const
{
return m_name;
}
const char *m_name;
typedef std::unordered_map< llarp::Addr, llarp_link_session,
llarp::Addr::Hash >
LinkMap_t;
LinkMap_t m_sessions;
mtx_t m_sessions_Mutex;
typedef std::unordered_map< llarp::PubKey, llarp::Addr, llarp::PubKey::Hash >
SessionMap_t;
SessionMap_t m_Connected;
mtx_t m_Connected_Mutex;
std::atomic< bool > pumpingLogic;
llarp::SecretKey seckey;
llarp_link(const llarp_iwp_args &args);
~llarp_link();
bool
has_intro_from(const llarp::Addr &from);
void
remove_from(const llarp::Addr &from);
/// does nothing if we have no session already established
void
KeepAliveSessionTo(const byte_t *pubkey);
/// does nothing if we have no session already established
void
CloseSessionTo(const byte_t *pubkey);
bool
has_session_to(const byte_t *pubkey);
void
TickSessions();
bool
sendto(const byte_t *pubkey, llarp_buffer_t buf);
bool
has_session_via(const llarp::Addr &dst);
void
MapAddr(const llarp::Addr &addr, const llarp::PubKey &pk);
void
visit_session(const llarp::Addr &addr,
std::function< void(llarp_link_session &) > visit);
void
pending_session_active(const llarp::Addr &addr);
void
clear_sessions();
static void
handle_logic_pump(void *user);
void
PumpLogic();
const uint8_t *
pubkey();
bool
ensure_privkey();
bool
keygen(const char *fname);
static void
handle_cleanup_timer(void *l, uint64_t orig, uint64_t left);
// this is called in net threadpool
static void
handle_recvfrom(struct llarp_udp_io *udp, const struct sockaddr *saddr,
const void *buf, ssize_t sz);
void
cancel_timer();
void
issue_cleanup_timer(uint64_t timeout);
void
get_our_address(llarp::AddressInfo &addr);
static void
after_recv(llarp_udp_io *udp);
bool
configure(struct llarp_ev_loop *netloop, const char *ifname, int af,
uint16_t port);
bool
start_link(struct llarp_logic *pLogic);
bool
stop_link();
bool
try_establish(struct llarp_link_establish_job *job);
};

@ -1,193 +0,0 @@
#pragma once
#include <atomic>
#include <llarp/codel.hpp>
#include "frame_state.hpp"
#include "llarp/buffer.h"
#include "llarp/crypto.hpp"
#include "llarp/crypto_async.h"
#include "llarp/net.hpp"
#include "llarp/router_contact.hpp"
#include "llarp/time.h"
#include "llarp/types.h"
struct llarp_udp_io;
struct llarp_async_iwp;
struct llarp_logic;
struct llarp_link;
struct transit_message;
struct llarp_link_establish_job;
struct llarp_link_session
{
static constexpr llarp_time_t SESSION_TIMEOUT = 10000;
static constexpr llarp_time_t KEEP_ALIVE_INTERVAL = SESSION_TIMEOUT / 4;
static constexpr size_t MAX_PAD = 128;
llarp_link_session();
void
init(llarp_link *l, const byte_t *seckey, const llarp::Addr &a);
~llarp_link_session();
void
session_start();
bool sendto(llarp_buffer_t);
bool
has_timed_out();
bool
timedout(llarp_time_t now, llarp_time_t timeout = SESSION_TIMEOUT);
void
close();
void
session_established();
llarp_link *
get_parent();
llarp::RouterContact *
get_remote_router();
bool
CheckRCValid();
bool
IsEstablished();
void
send_LIM();
bool
is_invalidated() const;
void
done();
void
pump();
void
introduce(uint8_t *pub);
void
intro_ack();
void
on_intro_ack(const void *buf, size_t sz);
void
on_intro(const void *buf, size_t sz);
void
on_session_start(const void *buf, size_t sz);
void
encrypt_frame_async_send(const void *buf, size_t sz);
// void send_keepalive(void *user);
bool
Tick(llarp_time_t now);
void
keepalive();
void
PumpCryptoOutbound();
// process inbound and outbound queues (logic thread)
void
TickLogic(llarp_time_t now);
// this is called from net thread
void
recv(const void *buf, size_t sz);
llarp_router *
Router();
llarp_udp_io *udp = nullptr;
llarp_crypto *crypto = nullptr;
llarp_async_iwp *iwp = nullptr;
llarp_link *serv = nullptr;
llarp::RouterContact *our_router = nullptr;
llarp::RouterContact remote_router;
llarp::SecretKey eph_seckey;
llarp::PubKey remote;
llarp::SharedSecret sessionkey;
llarp_link_establish_job *establish_job = nullptr;
llarp_time_t createdAt = 0;
llarp_time_t lastKeepalive = 0;
uint32_t establish_job_id = 0;
uint32_t frames = 0;
std::atomic< bool > working;
llarp::util::CoDelQueue< iwp_async_frame, FrameGetTime, FramePutTime,
FrameCompareTime >
outboundFrames;
llarp::util::CoDelQueue< iwp_async_frame, FrameGetTime, FramePutTime,
FrameCompareTime >
decryptedFrames;
llarp::Addr addr;
/// timestamp last intro packet sent at
llarp_time_t lastIntroSentAt = 0;
uint32_t intro_resend_job_id = 0;
iwp_async_session_start start;
iwp_async_introack introack;
byte_t token[32];
byte_t workbuf[MAX_PAD + 128];
enum State
{
eInitial,
eIntroRecv,
eIntroSent,
eIntroAckSent,
eSessionStartSent,
eLIMSent,
eEstablished,
eTimeout
};
State state;
void
EnterState(State st);
void
add_outbound_message(uint64_t id, const llarp::ShortHash &digest,
llarp_buffer_t payload);
void
EncryptOutboundFrames();
iwp_async_frame
alloc_frame(const void *buf, size_t sz);
void
decrypt_frame(const void *buf, size_t sz);
static void
handle_frame_decrypt(iwp_async_frame *f);
static void
handle_introack_timeout(void *user, uint64_t timeout, uint64_t left);
frame_state frame;
};
struct llarp_link_session_iter
{
void *user;
struct llarp_link *link;
bool (*visit)(struct llarp_link_session_iter *, struct llarp_link_session *);
};

@ -1,74 +0,0 @@
#pragma once
#include "llarp/types.h"
#include "sendbuf.hpp"
#include "sendqueue.hpp"
#include "xmit.hpp"
#include <bitset>
#include <unordered_map>
#include <vector>
struct transit_message
{
xmit msginfo;
std::bitset< 32 > status = {};
typedef std::vector< byte_t > fragment_t;
std::unordered_map< byte_t, fragment_t > frags;
fragment_t lastfrag;
llarp_time_t lastAck = 0;
llarp_time_t lastRetransmit = 0;
llarp_time_t started;
void
clear();
// calculate acked bitmask
uint32_t
get_bitmask() const;
// outbound
transit_message(llarp_buffer_t buf, const byte_t *hash, uint64_t id,
uint16_t mtu = 1024);
// inbound
transit_message(const xmit &x);
/// ack packets based off a bitmask
void
ack(uint32_t bitmask);
bool
should_send_ack(llarp_time_t now) const;
bool
should_resend_frags(llarp_time_t now) const;
bool
should_resend_xmit(llarp_time_t now) const;
bool
completed() const;
// template < typename T >
void
generate_xmit(sendqueue_t &queue, byte_t flags = 0);
// template < typename T >
void
retransmit_frags(sendqueue_t &queue, byte_t flags = 0);
bool
reassemble(std::vector< byte_t > &buffer) const;
void
put_message(llarp_buffer_t buf, const byte_t *hash, uint64_t id,
uint16_t mtu = 1024);
void
put_lastfrag(byte_t *buf, size_t sz);
bool
put_frag(byte_t fragno, byte_t *buf);
};

@ -1,43 +0,0 @@
#pragma once
#include "llarp/buffer.h"
struct xmit
{
byte_t buffer[48];
xmit() = default;
xmit(byte_t *ptr);
xmit(const xmit &other);
void
set_info(const byte_t *hash, uint64_t id, uint16_t fragsz, uint16_t lastsz,
uint8_t numfrags, uint8_t flags = 0x01);
const byte_t *
hash() const;
uint64_t
msgid() const;
// size of each full fragment
uint16_t
fragsize() const;
// number of full fragments
uint8_t
numfrags() const;
// size of the entire message
size_t
totalsize() const;
// size of the last fragment
uint16_t
lastfrag() const;
uint8_t
flags();
};

@ -0,0 +1,15 @@
#ifndef LLARP_LINK_CURVECP_HPP
#define LLARP_LINK_CURVECP_HPP
#include <llarp/link_layer.hpp>
namespace llarp
{
namespace curvecp
{
std::unique_ptr< ILinkLayer >
NewServer(llarp_router* r);
}
} // namespace llarp
#endif

@ -0,0 +1,205 @@
#ifndef LLARP_LINK_SERVER_HPP
#define LLARP_LINK_SERVER_HPP
#include <unordered_map>
#include <llarp/threading.hpp>
#include <llarp/router_contact.hpp>
#include <llarp/crypto.hpp>
#include <llarp/net.hpp>
namespace llarp
{
struct ILinkSession;
struct ILinkLayer
{
ILinkLayer(llarp_router* r) : m_router(r)
{
}
bool
HasSessionTo(const PubKey& pk)
{
util::Lock l(m_LinksMutex);
return m_Links.find(pk) != m_Links.end();
}
bool
HasSessionVia(const Addr& addr)
{
util::Lock l(m_SessionsMutex);
return m_Sessions.find(addr) != m_Sessions.end();
}
static void
udp_tick(llarp_udp_io* udp)
{
static_cast< ILinkLayer* >(udp->user)->Tick();
}
static void
udp_recv_from(llarp_udp_io* udp, const sockaddr* from, const void* buf,
const ssize_t sz)
{
static_cast< ILinkLayer* >(udp->user)->RecvFrom(*from, buf, sz);
}
bool
Configure(llarp_ev_loop* loop, const std::string& ifname, int af,
uint16_t port)
{
m_udp.user = this;
m_udp.recvfrom = &ILinkLayer::udp_recv_from;
m_udp.tick = &ILinkLayer::udp_tick;
if(ifname == "*")
{
m_ourAddr = AllInterfaces(af);
}
else if(!GetIFAddr(ifname, m_ourAddr, af))
return false;
return llarp_ev_add_udp(loop, &m_udp, m_ourAddr) != -1;
}
virtual ILinkSession*
NewInboundSession(const Addr& from) const = 0;
virtual ILinkSession*
NewOutboundSession(const RouterContact& rc) const = 0;
void
Tick()
{
auto now = llarp_time_now_ms();
util::Lock l(m_SessionsMutex);
auto itr = m_Sessions.begin();
while(itr != m_Sessions.end())
{
itr->second->Tick(now);
if(itr->second->TimedOut(now))
itr = m_Sessions.erase(itr);
else
++itr;
}
}
void
RecvFrom(const Addr& from, const void* buf, size_t sz)
{
util::Lock l(m_SessionsMutex);
auto itr = m_Sessions.find(from);
if(itr == m_Sessions.end())
m_Sessions
.insert(std::make_pair(
from, std::unique_ptr< ILinkSession >(NewInboundSession(from))))
.first->second->Recv(buf, sz);
else
itr->second->Recv(buf, sz);
}
virtual bool
PickAddress(const RouterContact& rc, llarp::Addr& picked) const = 0;
void
TryEstablishTo(const RouterContact& rc)
{
llarp::Addr to;
if(!PickAddress(rc, to))
return;
util::Lock l(m_SessionsMutex);
auto itr = m_Sessions.find(to);
if(itr == m_Sessions.end())
m_Sessions
.insert(std::make_pair(
to, std::unique_ptr< ILinkSession >(NewOutboundSession(rc))))
.first->second->Handshake();
else
itr->second->Handshake();
}
virtual bool
Start(llarp_logic* l) = 0;
virtual void
Stop() = 0;
virtual const char*
Name() const = 0;
void
CloseSessionTo(const PubKey& remote)
{
llarp::Addr addr;
{
util::Lock l(m_LinksMutex);
auto itr = m_Links.find(remote);
if(itr == m_Links.end())
return;
addr = itr->second;
}
{
util::Lock l(m_SessionsMutex);
auto itr = m_Sessions.find(addr);
if(itr == m_Sessions.end())
return;
itr->second->SendClose();
m_Sessions.erase(itr);
}
}
void
KeepAliveSessionTo(const PubKey& remote)
{
llarp::Addr addr;
{
util::Lock l(m_LinksMutex);
auto itr = m_Links.find(remote);
if(itr == m_Links.end())
return;
addr = itr->second;
}
{
util::Lock l(m_SessionsMutex);
auto itr = m_Sessions.find(addr);
if(itr == m_Sessions.end())
return;
itr->second->SendKeepAlive();
}
}
bool
SendTo(const PubKey& remote, llarp_buffer_t buf)
{
bool result = false;
llarp::Addr addr;
{
util::Lock l(m_LinksMutex);
auto itr = m_Links.find(remote);
if(itr == m_Links.end())
return false;
addr = itr->second;
}
{
util::Lock l(m_SessionsMutex);
auto itr = m_Sessions.find(addr);
if(itr == m_Sessions.end())
return false;
result = itr->second->SendMessageBuffer(buf);
}
return result;
}
bool
GetOurAddressInfo(llarp::AddressInfo& addr) const;
protected:
llarp_router* m_router;
Addr m_ourAddr;
llarp_udp_io m_udp;
util::Mutex m_LinksMutex;
util::Mutex m_SessionsMutex;
std::unordered_map< PubKey, Addr, PubKey::Hash > m_Links;
std::unordered_map< Addr, std::unique_ptr< ILinkSession >, Addr::Hash >
m_Sessions;
};
} // namespace llarp
#endif

@ -0,0 +1,61 @@
#ifndef LLARP_LINK_SESSION_HPP
#define LLARP_LINK_SESSION_HPP
#include <llarp/crypto.hpp>
#include <llarp/net.hpp>
namespace llarp
{
struct LinkIntroMessage;
struct ILinkMessage;
struct ILinkSession
{
virtual ~ILinkSession(){};
virtual void
Tick(llarp_time_t now) = 0;
/// handle a link intro message
virtual bool
HandleLinkIntro(const LinkIntroMessage* msg) = 0;
/// send a message buffer to the remote endpoint
virtual bool
SendMessageBuffer(llarp_buffer_t buf) = 0;
/// handle low level recv of data
virtual bool
Recv(const void* buf, size_t sz) = 0;
/// send handshake
virtual void
Handshake() = 0;
/// send a keepalive to the remote endpoint
virtual bool
SendKeepAlive() = 0;
/// send close message
virtual void
SendClose() = 0;
/// return true if we are established
virtual bool
IsEstablished() const = 0;
/// return true if this session has timed out
virtual bool
TimedOut(llarp_time_t now) const = 0;
/// get remote public identity key
virtual const PubKey&
GetPubKey() const = 0;
/// get remote address endpoint
virtual const Addr&
GetRemoteEndpoint() const = 0;
};
} // namespace llarp
#endif

@ -0,0 +1,5 @@
#ifndef LLARP_LINK_LAYER_HPP
#define LLARP_LINK_LAYER_HPP
#include <llarp/link/server.hpp>
#include <llarp/link/session.hpp>
#endif

@ -3,29 +3,36 @@
#include <llarp/bencode.hpp>
#include <llarp/router_id.hpp>
#include <llarp/link/session.hpp>
#include <queue>
#include <vector>
struct llarp_router;
struct llarp_link_session;
struct llarp_link_session_iter;
namespace llarp
{
struct ILinkMessage;
struct ILinkSession;
typedef std::queue< ILinkMessage* > SendQueue;
/// parsed link layer message
struct ILinkMessage : public IBEncodeMessage
{
/// who did this message come from (rc.k)
RouterID remote = {};
/// who did this message come from or is going to
ILinkSession* session;
uint64_t version = 0;
ILinkMessage() = default;
ILinkMessage(const RouterID& id);
ILinkMessage() : ILinkMessage(nullptr)
{
}
ILinkMessage(ILinkSession* from) : session(from)
{
}
virtual ~ILinkMessage()
{
}
virtual bool
HandleMessage(llarp_router* router) const = 0;
@ -41,7 +48,7 @@ namespace llarp
/// start processig message from a link session
bool
ProcessFrom(llarp_link_session* from, llarp_buffer_t buf);
ProcessFrom(ILinkSession* from, llarp_buffer_t buf);
/// called when the message is fully read
/// return true when the message was accepted otherwise returns false
@ -55,8 +62,8 @@ namespace llarp
private:
bool firstkey;
llarp_router* router;
llarp_link_session* from;
ILinkMessage* msg = nullptr;
ILinkSession* from = nullptr;
ILinkMessage* msg = nullptr;
};
} // namespace llarp

@ -8,9 +8,7 @@
#include <llarp/messages/dht_immediate.hpp>
#include <llarp/messages/link_intro.hpp>
#include <llarp/messages/relay.hpp>
#include <llarp/messages/relay_ack.hpp>
#include <llarp/messages/relay_commit.hpp>
#include <llarp/messages/path_confirm.hpp>
#endif

@ -11,7 +11,7 @@ namespace llarp
{
struct DHTMessage : public IMessage
{
std::vector< llarp::dht::IMessage* > M;
std::vector< std::unique_ptr< llarp::dht::IMessage > > M;
uint64_t V = 0;
~DHTMessage();
@ -28,4 +28,4 @@ namespace llarp
} // namespace routing
} // namespace llarp
#endif
#endif

@ -8,13 +8,17 @@ namespace llarp
{
struct DHTImmeidateMessage : public ILinkMessage
{
DHTImmeidateMessage(const RouterID& from) : ILinkMessage(from)
DHTImmeidateMessage(ILinkSession* parent) : ILinkMessage(parent)
{
}
DHTImmeidateMessage() : ILinkMessage()
{
}
~DHTImmeidateMessage();
std::vector< llarp::dht::IMessage* > msgs;
std::vector< std::unique_ptr< llarp::dht::IMessage > > msgs;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);

@ -1,17 +1,22 @@
#ifndef LLARP_MESSAGES_LINK_INTRO_HPP
#define LLARP_MESSAGES_LINK_INTRO_HPP
#include <llarp/link_message.hpp>
#include <llarp/router_contact.hpp>
namespace llarp
{
struct ILinkSession;
struct LinkIntroMessage : public ILinkMessage
{
LinkIntroMessage(RouterContact* rc) : ILinkMessage(), RC(rc)
LinkIntroMessage(ILinkSession* s) : ILinkMessage(), from(s)
{
}
~LinkIntroMessage();
RouterContact* RC;
ILinkSession* from;
RouterContact rc;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);

@ -16,7 +16,7 @@ namespace llarp
TunnelNonce Y;
RelayUpstreamMessage();
RelayUpstreamMessage(const RouterID& from);
RelayUpstreamMessage(ILinkSession* from);
~RelayUpstreamMessage();
bool
@ -35,7 +35,7 @@ namespace llarp
Encrypted X;
TunnelNonce Y;
RelayDownstreamMessage();
RelayDownstreamMessage(const RouterID& from);
RelayDownstreamMessage(ILinkSession* from);
~RelayDownstreamMessage();
bool

@ -1,41 +0,0 @@
#ifndef LLARP_MESSAGES_RELAY_ACK_HPP
#define LLARP_MESSAGES_RELAY_ACK_HPP
#include <llarp/crypto.hpp>
#include <llarp/encrypted_frame.hpp>
#include <llarp/link_message.hpp>
#include <llarp/path_types.hpp>
namespace llarp
{
struct LR_AckRecord
{
uint64_t version = 0;
bool
BEncode(llarp_buffer_t* buf) const;
bool
BDecode(llarp_buffer_t* buf);
};
struct LR_AckMessage : public ILinkMessage
{
std::vector< EncryptedFrame > replies;
uint64_t version = 0;
LR_AckMessage(const RouterID& from);
~LR_AckMessage();
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
bool
BEncode(llarp_buffer_t* buf) const;
bool
HandleMessage(llarp_router* router) const;
};
} // namespace llarp
#endif

@ -46,13 +46,12 @@ namespace llarp
struct LR_CommitMessage : public ILinkMessage
{
std::array< EncryptedFrame, 8 > frames;
uint64_t version;
LR_CommitMessage() : ILinkMessage()
{
}
LR_CommitMessage(const RouterID &from) : ILinkMessage(from)
LR_CommitMessage(ILinkSession *from) : ILinkMessage(from)
{
}

@ -245,10 +245,17 @@ namespace llarp
};
};
Addr
AllInterfaces(int af);
/// get first network interface with public address
bool
GetBestNetIF(std::string& ifname, int af = AF_INET);
/// get network interface address for network interface with ifname
bool
GetIFAddr(const std::string& ifname, Addr& addr, int af = AF_INET);
} // namespace llarp
#endif

@ -27,15 +27,4 @@ llarp_run_router(struct llarp_router *router, struct llarp_nodedb *nodedb);
void
llarp_stop_router(struct llarp_router *router);
struct llarp_router_link_iter
{
void *user;
bool (*visit)(struct llarp_router_link_iter *, struct llarp_router *,
struct llarp_link *);
};
void
llarp_router_iterate_links(struct llarp_router *router,
struct llarp_router_link_iter iter);
#endif

@ -67,4 +67,4 @@ namespace llarp
} // namespace service
} // namespace llarp
#endif
#endif

@ -95,7 +95,7 @@ namespace llarp
int
Context::LoadDatabase()
{
llarp_crypto_libsodium_init(&crypto);
llarp_crypto_init(&crypto);
nodedb = llarp_nodedb_new(&crypto);
if(!nodedb_dir[0])
{

@ -162,7 +162,7 @@ namespace llarp
} // namespace llarp
void
llarp_crypto_libsodium_init(struct llarp_crypto *c)
llarp_crypto_init(struct llarp_crypto *c)
{
assert(sodium_init() != -1);
char *avx2 = getenv("AVX2_FORCE_DISABLE");
@ -198,4 +198,4 @@ llarp_randint()
uint64_t i;
randombytes((byte_t *)&i, sizeof(i));
return i;
}
}

@ -184,14 +184,14 @@ namespace llarp
}
void
Context::LookupRouterRelayed(const Key_t &requester, uint64_t txid,
const Key_t &target, bool recursive,
std::vector< IMessage * > &replies)
Context::LookupRouterRelayed(
const Key_t &requester, uint64_t txid, const Key_t &target,
bool recursive, std::vector< std::unique_ptr< IMessage > > &replies)
{
if(target == ourKey)
{
// we are the target, give them our RC
replies.push_back(
replies.emplace_back(
new GotRouterMessage(requester, txid, {router->rc}, false));
return;
}
@ -202,7 +202,7 @@ namespace llarp
if(next == target)
{
// we know it
replies.push_back(new GotRouterMessage(
replies.emplace_back(new GotRouterMessage(
requester, txid, {nodes->nodes[target].rc}, false));
}
else if(recursive) // are we doing a recursive lookup?
@ -217,19 +217,21 @@ namespace llarp
{
// no we are closer to the target so tell requester it's not there
// so they switch to iterative lookup
replies.push_back(new GotRouterMessage(requester, txid, {}, false));
replies.emplace_back(
new GotRouterMessage(requester, txid, {}, false));
}
}
else // iterative lookup and we don't have it tell them we don't have
// the target router
{
replies.push_back(new GotRouterMessage(requester, txid, {}, false));
replies.emplace_back(
new GotRouterMessage(requester, txid, {}, false));
}
}
else
{
// we don't know it and have no closer peers to ask
replies.push_back(new GotRouterMessage(requester, txid, {}, false));
replies.emplace_back(new GotRouterMessage(requester, txid, {}, false));
}
}
@ -280,9 +282,9 @@ namespace llarp
void
Context::DHTSendTo(const Key_t &peer, IMessage *msg, bool keepalive)
{
auto m = new llarp::DHTImmeidateMessage(peer);
m->msgs.push_back(msg);
router->SendToOrQueue(peer, m);
llarp::DHTImmeidateMessage m;
m.msgs.emplace_back(msg);
router->SendToOrQueue(peer, &m);
if(keepalive)
{
auto now = llarp_time_now_ms();
@ -402,7 +404,7 @@ namespace llarp
return;
}
routing::DHTMessage msg;
msg.M.push_back(new GotIntroMessage(valuesFound, whoasked.txid));
msg.M.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid));
if(!path->SendRoutingMessage(&msg, parent->router))
{
llarp::LogWarn(
@ -577,10 +579,9 @@ namespace llarp
}
bool
Context::HandleExploritoryRouterLookup(const Key_t &requester,
uint64_t txid,
const RouterID &target,
std::vector< IMessage * > &reply)
Context::HandleExploritoryRouterLookup(
const Key_t &requester, uint64_t txid, const RouterID &target,
std::vector< std::unique_ptr< IMessage > > &reply)
{
std::vector< RouterID > closer;
Key_t t(target.data());
@ -594,7 +595,7 @@ namespace llarp
}
for(const auto &f : found)
closer.emplace_back(f.data());
reply.push_back(new GotRouterMessage(txid, closer, false));
reply.emplace_back(new GotRouterMessage(txid, closer, false));
return true;
}
@ -625,9 +626,8 @@ namespace llarp
void
Start(const TXOwner &peer)
{
parent->DHTSendTo(
peer.node,
new FindRouterMessage(parent->OurKey(), target, peer.txid));
FindRouterMessage msg(parent->OurKey(), target, peer.txid);
parent->DHTSendTo(peer.node, &msg);
}
void
@ -645,9 +645,8 @@ namespace llarp
}
else
{
parent->DHTSendTo(
whoasked.node,
new GotRouterMessage({}, whoasked.txid, valuesFound, false));
GotRouterMessage msg({}, whoasked.txid, valuesFound, false);
parent->DHTSendTo(whoasked.node, &msg);
}
}
};
@ -678,8 +677,8 @@ namespace llarp
return;
}
routing::DHTMessage msg;
msg.M.push_back(new GotRouterMessage(parent->OurKey(), whoasked.txid,
valuesFound, true));
msg.M.emplace_back(new GotRouterMessage(parent->OurKey(), whoasked.txid,
valuesFound, true));
if(!path->SendRoutingMessage(&msg, parent->router))
{
llarp::LogWarn(

@ -8,8 +8,8 @@ namespace llarp
struct MessageDecoder
{
const Key_t &From;
std::unique_ptr< IMessage > msg;
bool firstKey = true;
IMessage *msg = nullptr;
bool relayed = false;
MessageDecoder(const Key_t &from) : From(from)
@ -37,32 +37,33 @@ namespace llarp
return false;
llarp::LogInfo("Handle DHT message ", *strbuf.base,
" relayed=", dec->relayed);
IMessage *msg;
switch(*strbuf.base)
{
case 'F':
dec->msg = new FindIntroMessage(dec->From, dec->relayed);
msg = new FindIntroMessage(dec->From, dec->relayed);
break;
case 'R':
if(dec->relayed)
dec->msg = new RelayedFindRouterMessage(dec->From);
msg = new RelayedFindRouterMessage(dec->From);
else
dec->msg = new FindRouterMessage(dec->From);
msg = new FindRouterMessage(dec->From);
break;
case 'S':
dec->msg = new GotRouterMessage(dec->From, dec->relayed);
msg = new GotRouterMessage(dec->From, dec->relayed);
break;
case 'I':
dec->msg = new PublishIntroMessage();
msg = new PublishIntroMessage();
break;
case 'G':
if(dec->relayed)
{
dec->msg = new RelayedGotIntroMessage();
msg = new RelayedGotIntroMessage();
break;
}
else
{
dec->msg = new GotIntroMessage(dec->From);
msg = new GotIntroMessage(dec->From);
break;
}
default:
@ -70,6 +71,7 @@ namespace llarp
// bad msg type
return false;
}
dec->msg = std::unique_ptr< IMessage >(msg);
dec->firstKey = false;
return dec->msg != nullptr;
}
@ -78,7 +80,7 @@ namespace llarp
}
};
IMessage *
std::unique_ptr< IMessage >
DecodeMesssage(const Key_t &from, llarp_buffer_t *buf, bool relayed)
{
MessageDecoder dec(from);
@ -86,26 +88,20 @@ namespace llarp
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;
if(!bencode_read_dict(buf, &r))
return nullptr;
}
return std::unique_ptr< IMessage >(std::move(dec.msg));
}
struct ListDecoder
{
ListDecoder(const Key_t &from, std::vector< IMessage * > &list)
ListDecoder(const Key_t &from,
std::vector< std::unique_ptr< IMessage > > &list)
: From(from), l(list){};
bool relayed = false;
const Key_t &From;
std::vector< IMessage * > &l;
std::vector< std::unique_ptr< IMessage > > &l;
static bool
on_item(list_reader *r, bool has)
@ -116,7 +112,7 @@ namespace llarp
auto msg = DecodeMesssage(dec->From, r->buffer, dec->relayed);
if(msg)
{
dec->l.push_back(msg);
dec->l.emplace_back(std::move(msg));
return true;
}
else
@ -125,8 +121,9 @@ namespace llarp
};
bool
DecodeMesssageList(const Key_t &from, llarp_buffer_t *buf,
std::vector< IMessage * > &list, bool relayed)
DecodeMesssageList(Key_t from, llarp_buffer_t *buf,
std::vector< std::unique_ptr< IMessage > > &list,
bool relayed)
{
ListDecoder dec(from, list);
dec.relayed = relayed;
@ -136,4 +133,4 @@ namespace llarp
return bencode_read_list(buf, &r);
}
} // namespace dht
} // namespace llarp
} // namespace llarp

@ -5,16 +5,14 @@ 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);
return llarp::dht::DecodeMesssageList(session->GetPubKey().data(), buf,
msgs);
if(llarp_buffer_eq(key, "v"))
{
if(!bencode_read_integer(buf, &version))
@ -62,24 +60,19 @@ namespace llarp
bool
DHTImmeidateMessage::HandleMessage(llarp_router *router) const
{
DHTImmeidateMessage *reply = new DHTImmeidateMessage(remote);
bool result = true;
DHTImmeidateMessage reply(session);
bool result = true;
for(auto &msg : msgs)
{
result &= msg->HandleMessage(router->dht, reply->msgs);
result &= msg->HandleMessage(router->dht, reply.msgs);
}
if(reply->msgs.size())
if(reply.msgs.size())
{
if(result)
{
result = router->SendToOrQueue(remote.data(), reply);
result = router->SendToOrQueue(session->GetPubKey(), &reply);
}
return result;
}
else
{
delete reply;
return result;
}
return result;
}
} // namespace llarp

@ -87,7 +87,7 @@ namespace llarp
bool
FindIntroMessage::HandleMessage(
llarp_dht_context* ctx,
std::vector< llarp::dht::IMessage* >& replies) const
std::vector< std::unique_ptr< IMessage > >& replies) const
{
if(R > 5)
{
@ -109,7 +109,7 @@ namespace llarp
if(introset)
{
service::IntroSet i = *introset;
replies.push_back(new GotIntroMessage({i}, T));
replies.emplace_back(new GotIntroMessage({i}, T));
return true;
}
else
@ -117,7 +117,7 @@ namespace llarp
if(R == 0)
{
// we don't have it, reply with a direct reply
replies.push_back(new GotIntroMessage({}, T));
replies.emplace_back(new GotIntroMessage({}, T));
return true;
}
else
@ -135,7 +135,7 @@ namespace llarp
{
// we are not closer than our peer to the target so don't
// recurse farther
replies.push_back(new GotIntroMessage({}, T));
replies.emplace_back(new GotIntroMessage({}, T));
return true;
}
else if(R > 0)
@ -179,7 +179,7 @@ namespace llarp
{
reply.push_back(introset);
}
replies.push_back(new GotIntroMessage(reply, T));
replies.emplace_back(new GotIntroMessage(reply, T));
return true;
}
else

@ -11,7 +11,8 @@ namespace llarp
{
bool
RelayedFindRouterMessage::HandleMessage(
llarp_dht_context *ctx, std::vector< IMessage * > &replies) const
llarp_dht_context *ctx,
std::vector< std::unique_ptr< IMessage > > &replies) const
{
auto &dht = ctx->impl;
/// lookup for us, send an immeidate reply
@ -20,7 +21,7 @@ namespace llarp
auto path = dht.router->paths.GetByUpstream(K, pathID);
if(path)
{
replies.push_back(
replies.emplace_back(
new GotRouterMessage(K.data(), txid, {dht.router->rc}, false));
return true;
}
@ -129,8 +130,9 @@ namespace llarp
}
bool
FindRouterMessage::HandleMessage(llarp_dht_context *ctx,
std::vector< IMessage * > &replies) const
FindRouterMessage::HandleMessage(
llarp_dht_context *ctx,
std::vector< std::unique_ptr< IMessage > > &replies) const
{
auto &dht = ctx->impl;
if(!dht.allowTransit)

@ -19,8 +19,9 @@ namespace llarp
}
bool
GotIntroMessage::HandleMessage(llarp_dht_context *ctx,
std::vector< IMessage * > &replies) const
GotIntroMessage::HandleMessage(
llarp_dht_context *ctx,
std::vector< std::unique_ptr< IMessage > > &replies) const
{
auto &dht = ctx->impl;
auto crypto = &dht.router->crypto;
@ -56,7 +57,8 @@ namespace llarp
bool
RelayedGotIntroMessage::HandleMessage(
llarp_dht_context *ctx, std::vector< IMessage * > &replies) const
llarp_dht_context *ctx,
std::vector< std::unique_ptr< IMessage > > &replies) const
{
// TODO: implement me better?
auto pathset = ctx->impl.router->paths.GetLocalPathSet(pathID);

@ -66,8 +66,9 @@ namespace llarp
}
bool
GotRouterMessage::HandleMessage(llarp_dht_context *ctx,
std::vector< IMessage * > &replies) const
GotRouterMessage::HandleMessage(
llarp_dht_context *ctx,
std::vector< std::unique_ptr< IMessage > > &replies) const
{
auto &dht = ctx->impl;
if(relayed)

@ -40,8 +40,9 @@ namespace llarp
}
bool
PublishIntroMessage::HandleMessage(llarp_dht_context *ctx,
std::vector< IMessage * > &replies) const
PublishIntroMessage::HandleMessage(
llarp_dht_context *ctx,
std::vector< std::unique_ptr< IMessage > > &replies) const
{
if(S > 5)
{
@ -67,7 +68,7 @@ namespace llarp
return false;
}
dht.services->PutNode(I);
replies.push_back(new GotIntroMessage({I}, txID));
replies.emplace_back(new GotIntroMessage({I}, txID));
Key_t peer;
std::set< Key_t > exclude;
for(const auto &e : E)
@ -103,4 +104,4 @@ namespace llarp
return bencode_end(buf);
}
} // namespace dht
} // namespace llarp
} // namespace llarp

@ -0,0 +1 @@
#include <llarp/dtls.hpp>

@ -1,48 +0,0 @@
#include "llarp/iwp/frame_header.hpp"
#include "llarp/endian.h"
frame_header::frame_header(byte_t *buf) : ptr(buf)
{
}
byte_t *
frame_header::data()
{
return ptr + 6;
}
uint8_t &
frame_header::version()
{
return ptr[0];
}
uint8_t &
frame_header::msgtype()
{
return ptr[1];
}
uint16_t
frame_header::size() const
{
return bufbe16toh(ptr + 2);
}
void
frame_header::setsize(uint16_t sz)
{
htobe16buf(ptr + 2, sz);
}
uint8_t &
frame_header::flags()
{
return ptr[5];
}
void
frame_header::setflag(header_flag f)
{
ptr[5] |= f;
}

@ -1,364 +0,0 @@
#ifdef _MSC_VER
#define NOMINMAX
#endif
#include "llarp/iwp/frame_state.hpp"
#include <algorithm>
#include "buffer.hpp"
#include "llarp/crypto.hpp"
#include "llarp/endian.h"
#include "llarp/iwp/inbound_message.hpp"
#include "llarp/iwp/session.hpp"
#include "llarp/logger.hpp"
#include "llarp/iwp/server.hpp"
#include "mem.hpp"
#include "router.hpp"
llarp_router *
frame_state::Router()
{
return parent->Router();
}
bool
frame_state::process_inbound_queue()
{
uint64_t last = rxids;
recvqueue.Process([&](InboundMessage &msg) {
if(last != msg.msgid)
{
auto buffer = msg.Buffer();
if(!Router()->HandleRecvLinkMessage(parent, buffer))
{
llarp::LogWarn("failed to process inbound message ", msg.msgid);
llarp::DumpBuffer< llarp_buffer_t, 128 >(buffer);
}
last = msg.msgid;
}
else
{
llarp::LogWarn("duplicate inbound message ", last);
}
});
// TODO: this isn't right
return true;
}
bool
frame_state::flags_agree(byte_t flags) const
{
return ((rxflags & flags) & (txflags & flags)) == flags;
}
bool
frame_state::either_has_flag(byte_t flag) const
{
return (rxflags & flag) == flag || (txflags & flag) == flag;
}
void
frame_state::clear()
{
rx.clear();
tx.clear();
}
bool
frame_state::got_xmit(frame_header hdr, size_t sz)
{
if(hdr.size() > sz)
{
// overflow
llarp::LogWarn("invalid XMIT frame size ", hdr.size(), " > ", sz);
return false;
}
sz = hdr.size();
// extract xmit data
xmit x(hdr.data());
const auto bufsz = sizeof(x.buffer);
if(sz - bufsz < x.lastfrag())
{
// bad size of last fragment
llarp::LogWarn("XMIT frag size missmatch ", sz - bufsz, " < ",
x.lastfrag());
return false;
}
// check LSB set on flags
if(x.flags() & 0x01)
{
auto id = x.msgid();
auto h = x.hash();
auto itr = rx.find(h);
if(itr == rx.end())
{
if(x.numfrags() > 0)
{
auto &msg = rx.insert(std::make_pair(h, transit_message(x)))
.first->second;
rxIDs.insert(std::make_pair(id, h));
llarp::LogDebug("got message XMIT with ", (int)x.numfrags(),
" fragment"
"s");
// inserted, put last fragment
msg.put_lastfrag(hdr.data() + sizeof(x.buffer), x.lastfrag());
push_ackfor(id, 0);
return true;
}
else
{
// handle zero fragment message immediately
transit_message msg(x);
msg.put_lastfrag(hdr.data() + sizeof(x.buffer), x.lastfrag());
push_ackfor(id, 0);
return inbound_frame_complete(msg);
}
}
else
llarp::LogWarn("duplicate XMIT h=", llarp::ShortHash(h));
}
else
llarp::LogWarn("LSB not set on flags");
return false;
}
bool
frame_state::got_frag(frame_header hdr, size_t sz)
{
if(hdr.size() > sz)
{
// overflow
llarp::LogWarn("invalid FRAG frame size ", hdr.size(), " > ", sz);
return false;
}
sz = hdr.size();
if(sz <= 9)
{
// underflow
llarp::LogWarn("invalid FRAG frame size ", sz, " <= 9");
return false;
}
uint64_t msgid;
byte_t fragno;
msgid = bufbe64toh(hdr.data());
fragno = hdr.data()[8];
auto idItr = rxIDs.find(msgid);
if(idItr == rxIDs.end())
{
push_ackfor(msgid, ~0);
return true;
}
auto itr = rx.find(idItr->second);
if(itr == rx.end())
{
push_ackfor(msgid, ~0);
return true;
}
auto fragsize = itr->second.msginfo.fragsize();
if(fragsize != sz - 9)
{
llarp::LogWarn("RX fragment size missmatch ", fragsize, " != ", sz - 9);
return false;
}
llarp::LogDebug("RX got fragment ", (int)fragno, " msgid=", msgid);
if(!itr->second.put_frag(fragno, hdr.data() + 9))
{
llarp::LogWarn("inbound message does not have fragment msgid=", msgid,
" fragno=", (int)fragno);
return false;
}
auto mask = itr->second.get_bitmask();
if(itr->second.completed())
{
push_ackfor(msgid, mask);
bool result = inbound_frame_complete(itr->second);
rxIDs.erase(idItr);
rx.erase(itr);
return result;
}
else if(itr->second.should_send_ack(llarp_time_now_ms()))
{
push_ackfor(msgid, mask);
}
return true;
}
void
frame_state::push_ackfor(uint64_t id, uint32_t bitmask)
{
llarp::LogDebug("ACK for msgid=", id, " mask=", bitmask);
sendqueue.EmplaceIf(
[&](sendbuf_t &pkt) -> bool {
auto body_ptr = init_sendbuf(&pkt, eACKS, 12, txflags);
htobe64buf(body_ptr, id);
htobe32buf(body_ptr + 8, bitmask);
return true;
},
18);
}
bool
frame_state::inbound_frame_complete(const transit_message &rxmsg)
{
bool success = false;
std::vector< byte_t > msg;
llarp::ShortHash digest;
auto id = rxmsg.msginfo.msgid();
if(rxmsg.reassemble(msg))
{
auto router = Router();
auto buf = llarp::Buffer< decltype(msg) >(msg);
router->crypto.shorthash(digest, buf);
if(memcmp(digest, rxmsg.msginfo.hash(), 32))
{
llarp::LogWarn("message hash missmatch ", digest,
" != ", llarp::AlignedBuffer< 32 >(rxmsg.msginfo.hash()));
return false;
}
llarp_link_session *impl = parent;
if(id == 0)
{
success = router->HandleRecvLinkMessage(parent, buf);
if(impl->CheckRCValid())
{
if(!impl->IsEstablished())
{
// client side got server's LIM
impl->send_LIM();
impl->session_established();
}
++nextMsgID;
}
else
{
llarp::PubKey k = impl->remote_router.pubkey;
llarp::LogWarn("spoofed LIM from ", k);
impl->close();
success = false;
}
}
else
{
recvqueue.Emplace(id, msg);
success = true;
}
}
if(!success)
llarp::LogWarn("Failed to process inbound message ", id);
return success;
}
bool
frame_state::got_acks(frame_header hdr, size_t sz)
{
if(hdr.size() > sz)
{
llarp::LogError("invalid ACKS frame size ", hdr.size(), " > ", sz);
return false;
}
sz = hdr.size();
if(sz < 12)
{
llarp::LogError("invalid ACKS frame size ", sz, " < 12");
return false;
}
auto ptr = hdr.data();
uint64_t msgid = bufbe64toh(ptr);
uint32_t bitmask = bufbe32toh(ptr + 8);
auto itr = tx.find(msgid);
if(itr == tx.end())
{
llarp::LogDebug("ACK for missing TX frame msgid=", msgid);
return true;
}
auto now = llarp_time_now_ms();
if(bitmask == ~(0U))
{
tx.erase(msgid);
}
else
{
itr->second.ack(bitmask);
if(itr->second.completed())
{
llarp::LogDebug("message transmitted msgid=", msgid);
tx.erase(itr);
}
else if(itr->second.should_resend_frags(now))
{
llarp::LogDebug("message ", msgid, " retransmit fragments");
itr->second.retransmit_frags(sendqueue, txflags);
}
}
return true;
}
bool
frame_state::process(byte_t *buf, size_t sz)
{
frame_header hdr(buf);
if(hdr.flags() & eSessionInvalidated)
{
rxflags |= eSessionInvalidated;
}
switch(hdr.msgtype())
{
case eALIV:
// llarp::LogDebug("iwp_link::frame_state::process Got alive");
if(rxflags & eSessionInvalidated)
{
txflags |= eSessionInvalidated;
}
return true;
case eXMIT:
llarp::LogDebug("iwp_link::frame_state::process Got xmit");
return got_xmit(hdr, sz - 6);
case eACKS:
llarp::LogDebug("iwp_link::frame_state::process Got ack");
return got_acks(hdr, sz - 6);
case msgtype::eFRAG:
llarp::LogDebug("iwp_link::frame_state::process Got frag");
return got_frag(hdr, sz - 6);
default:
llarp::LogWarn(
"iwp_link::frame_state::process - unknown header message type: ",
(int)hdr.msgtype());
return false;
}
}
void
frame_state::retransmit(llarp_time_t now)
{
for(auto &item : tx)
{
if(item.second.should_resend_xmit(now))
{
item.second.generate_xmit(sendqueue, txflags);
}
item.second.retransmit_frags(sendqueue, txflags);
}
}
void
frame_state::alive()
{
lastEvent = llarp_time_now_ms();
}

@ -1,366 +0,0 @@
#include <llarp/iwp/server.hpp>
#include "str.hpp"
llarp_link::llarp_link(const llarp_iwp_args& args)
: router(args.router)
, crypto(args.crypto)
, logic(args.logic)
, worker(args.cryptoworker)
, keyfile(args.keyfile)
, m_name("IWP")
{
iwp = llarp_async_iwp_new(crypto, logic, worker);
pumpingLogic.store(false);
}
llarp_link::~llarp_link()
{
llarp_async_iwp_free(iwp);
}
void
llarp_link::CloseSessionTo(const byte_t* pubkey)
{
llarp::Addr addr;
llarp::PubKey pk(pubkey);
{
lock_t lock(m_Connected_Mutex);
auto itr = m_Connected.find(pk);
if(itr == m_Connected.end())
return;
addr = itr->second;
}
{
lock_t lock(m_sessions_Mutex);
auto itr = m_sessions.find(addr);
if(itr != m_sessions.end())
itr->second.close();
}
}
void
llarp_link::KeepAliveSessionTo(const byte_t* pubkey)
{
llarp::Addr addr;
llarp::PubKey pk(pubkey);
{
lock_t lock(m_Connected_Mutex);
auto itr = m_Connected.find(pk);
if(itr == m_Connected.end())
return;
addr = itr->second;
}
{
lock_t lock(m_sessions_Mutex);
auto itr = m_sessions.find(addr);
if(itr != m_sessions.end())
itr->second.keepalive();
}
}
void
llarp_link::MapAddr(const llarp::Addr& src, const llarp::PubKey& identity)
{
lock_t lock(m_Connected_Mutex);
m_Connected[identity] = src;
}
bool
llarp_link::has_session_to(const byte_t* pubkey)
{
llarp::PubKey pk(pubkey);
lock_t lock(m_Connected_Mutex);
return m_Connected.find(pk) != m_Connected.end();
}
void
llarp_link::TickSessions()
{
auto now = llarp_time_now_ms();
{
lock_t lock(m_sessions_Mutex);
auto itr = m_sessions.begin();
while(itr != m_sessions.end())
{
if(itr->second.Tick(now))
{
if(itr->second.IsEstablished())
m_Connected.erase(itr->second.get_remote_router()->pubkey);
itr = m_sessions.erase(itr);
}
else
++itr;
}
}
}
bool
llarp_link::sendto(const byte_t* pubkey, llarp_buffer_t buf)
{
llarp_link_session* link = nullptr;
{
lock_t lock(m_Connected_Mutex);
auto itr = m_Connected.find(pubkey);
if(itr != m_Connected.end())
{
lock_t innerlock(m_sessions_Mutex);
auto inner_itr = m_sessions.find(itr->second);
if(inner_itr != m_sessions.end())
{
link = &inner_itr->second;
}
}
}
return link && link->sendto(buf);
}
bool
llarp_link::has_session_via(const llarp::Addr& dst)
{
return m_sessions.find(dst) != m_sessions.end();
}
void
llarp_link::clear_sessions()
{
m_sessions.clear();
}
void
llarp_link::PumpLogic()
{
auto now = llarp_time_now_ms();
auto itr = m_sessions.begin();
while(itr != m_sessions.end())
{
itr->second.TickLogic(now);
++itr;
}
}
const uint8_t*
llarp_link::pubkey()
{
return llarp::seckey_topublic(seckey);
}
bool
llarp_link::ensure_privkey()
{
llarp::LogDebug("ensure transport private key at ", keyfile);
std::error_code ec;
if(!fs::exists(keyfile, ec))
{
if(!keygen(keyfile.c_str()))
return false;
}
std::ifstream f(keyfile);
if(f.is_open())
{
f.read((char*)seckey.data(), seckey.size());
return true;
}
return false;
}
bool
llarp_link::keygen(const char* fname)
{
crypto->encryption_keygen(seckey);
llarp::LogInfo("new transport key generated");
std::ofstream f(fname);
if(f.is_open())
{
f.write((char*)seckey.data(), seckey.size());
return true;
}
return false;
}
void
llarp_link::handle_cleanup_timer(void* l, uint64_t orig, uint64_t left)
{
if(left)
return;
llarp_link* link = static_cast< llarp_link* >(l);
link->timeout_job_id = 0;
link->TickSessions();
link->issue_cleanup_timer(orig);
}
void
llarp_link::visit_session(const llarp::Addr& fromaddr,
std::function< void(llarp_link_session&) > visit)
{
{
lock_t lock(m_sessions_Mutex);
auto itr = m_sessions.find(fromaddr);
if(itr == m_sessions.end())
{
m_sessions[fromaddr].init(this, seckey, fromaddr);
}
}
visit(m_sessions.at(fromaddr));
}
void
llarp_link::remove_from(const llarp::Addr& fromaddr)
{
lock_t lock(m_sessions_Mutex);
m_sessions.erase(fromaddr);
}
void
llarp_link::handle_recvfrom(struct llarp_udp_io* udp,
const struct sockaddr* saddr, const void* buf,
ssize_t sz)
{
llarp_link* link = static_cast< llarp_link* >(udp->user);
link->visit_session(*saddr,
[buf, sz](llarp_link_session& s) { s.recv(buf, sz); });
}
void
llarp_link::cancel_timer()
{
if(timeout_job_id)
{
llarp_logic_cancel_call(logic, timeout_job_id);
}
timeout_job_id = 0;
}
void
llarp_link::issue_cleanup_timer(uint64_t timeout)
{
timeout_job_id = llarp_logic_call_later(
logic, {timeout, this, &llarp_link::handle_cleanup_timer});
}
void
llarp_link::get_our_address(llarp::AddressInfo& addr)
{
addr.rank = 1;
addr.dialect = "IWP";
addr.pubkey = pubkey();
addr.port = this->addr.port();
memcpy(addr.ip.s6_addr, this->addr.addr6(), 16);
}
void
llarp_link::after_recv(llarp_udp_io* udp)
{
llarp_link* self = static_cast< llarp_link* >(udp->user);
llarp_logic_queue_job(
self->logic,
{self, [](void* u) { static_cast< llarp_link* >(u)->PumpLogic(); }});
}
bool
llarp_link::configure(struct llarp_ev_loop* netloop, const char* ifname, int af,
uint16_t port)
{
if(!ensure_privkey())
{
llarp::LogError("failed to ensure private key");
return false;
}
llarp::LogDebug("configure link ifname=", ifname, " af=", af, " port=", port);
// bind
sockaddr_in ip4addr;
sockaddr_in6 ip6addr;
sockaddr* addr = nullptr;
switch(af)
{
case AF_INET:
addr = (sockaddr*)&ip4addr;
llarp::Zero(addr, sizeof(ip4addr));
break;
case AF_INET6:
addr = (sockaddr*)&ip6addr;
llarp::Zero(addr, sizeof(ip6addr));
break;
// TODO: AF_PACKET
default:
llarp::LogError(__FILE__, "unsupported address family", af);
return false;
}
addr->sa_family = af;
if(!llarp::StrEq(ifname, "*"))
{
if(!llarp_getifaddr(ifname, af, addr))
{
llarp::LogError("failed to get address of network interface ", ifname);
return false;
}
}
else
m_name = "OWP"; // outboundLink_name;
switch(af)
{
case AF_INET:
ip4addr.sin_port = htons(port);
break;
case AF_INET6:
ip6addr.sin6_port = htons(port);
break;
// TODO: AF_PACKET
default:
return false;
}
this->addr = *addr;
this->netloop = netloop;
udp.recvfrom = &llarp_link::handle_recvfrom;
udp.user = this;
udp.tick = &llarp_link::after_recv;
llarp::LogDebug("bind IWP link to ", addr);
if(llarp_ev_add_udp(netloop, &udp, addr) == -1)
{
llarp::LogError("failed to bind to ", addr);
return false;
}
return true;
}
bool
llarp_link::start_link(struct llarp_logic* pLogic)
{
// give link implementations
// link->parent = l;
timeout_job_id = 0;
this->logic = pLogic;
// start cleanup timer
issue_cleanup_timer(500);
return true;
}
bool
llarp_link::stop_link()
{
cancel_timer();
llarp_ev_close_udp(&udp);
clear_sessions();
return true;
}
bool
llarp_link::try_establish(struct llarp_link_establish_job* job)
{
llarp::Addr dst(job->ai);
if(has_session_via(dst))
return false;
llarp::LogInfo("establish session to ", job->ai.pubkey, " via ", dst);
visit_session(dst, [job](llarp_link_session& s) {
s.establish_job = job;
s.frame.alive(); // mark it alive
s.introduce(job->ai.pubkey);
});
return true;
}

@ -1,737 +0,0 @@
#ifdef _MSC_VER
#define NOMINMAX
#endif
#include <algorithm>
#include <llarp/crypto.hpp>
#include <llarp/iwp.hpp>
#include <llarp/iwp/server.hpp>
#include <llarp/iwp/session.hpp>
#include "address_info.hpp"
#include "buffer.hpp"
#include "link/encoder.hpp"
#include "llarp/ev.h" // for handle_frame_encrypt
static void
handle_crypto_outbound(void *u)
{
llarp_link_session *self = static_cast< llarp_link_session * >(u);
self->EncryptOutboundFrames();
self->working = false;
}
llarp_link_session::llarp_link_session()
: outboundFrames("iwp_outbound")
, decryptedFrames("iwp_inbound")
, state(eInitial)
, frame(this)
{
}
void
llarp_link_session::init(llarp_link *l, const byte_t *seckey,
const llarp::Addr &a)
{
udp = &l->udp;
crypto = &l->router->crypto;
iwp = l->iwp;
serv = l;
addr = a;
eph_seckey = seckey;
crypto->randbytes(token, 32);
frame.alive();
working.store(false);
createdAt = llarp_time_now_ms();
}
llarp_link_session::~llarp_link_session()
{
frame.clear();
}
llarp_router *
llarp_link_session::Router()
{
return serv->router;
}
bool
llarp_link_session::sendto(llarp_buffer_t msg)
{
auto now = llarp_time_now_ms();
if(timedout(now))
return false;
auto id = frame.txids++;
// llarp::LogDebug("session sending to, number", id);
llarp::ShortHash digest;
crypto->shorthash(digest, msg);
add_outbound_message(id, digest, msg);
return true;
}
bool
llarp_link_session::timedout(llarp_time_t now, llarp_time_t timeout)
{
if(frame.lastEvent == 0)
return false;
if(now <= frame.lastEvent)
return false;
auto diff = now - frame.lastEvent;
return diff >= timeout;
}
bool
llarp_link_session::has_timed_out()
{
auto now = llarp_time_now_ms();
return timedout(now);
}
static void
send_keepalive(void *user)
{
llarp_link_session *self = static_cast< llarp_link_session * >(user);
if(self->is_invalidated())
{
return;
}
// all zeros means keepalive
byte_t tmp[8] = {0};
// set flags for tx
frame_header hdr(tmp);
hdr.flags() = self->frame.txflags;
// send frame after encrypting
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
self->lastKeepalive = llarp_time_now_ms();
self->encrypt_frame_async_send(buf.base, buf.sz);
self->pump();
self->PumpCryptoOutbound();
}
void
llarp_link_session::close()
{
// set our side invalidated and close async when the other side also marks
// as session invalidated
frame.txflags |= eSessionInvalidated;
keepalive();
}
void
llarp_link_session::session_established()
{
llarp::RouterID remote = remote_router.pubkey;
llarp::LogInfo("Session to ", remote, " established");
EnterState(eEstablished);
serv->MapAddr(addr, remote_router.pubkey);
llarp_logic_cancel_call(serv->logic, establish_job_id);
}
llarp::RouterContact *
llarp_link_session::get_remote_router()
{
return &remote_router;
}
void
llarp_link_session::add_outbound_message(uint64_t id,
const llarp::ShortHash &digest,
llarp_buffer_t buf)
{
// insert and generate xmit
frame.tx.insert(std::make_pair(id, transit_message(buf, digest, id)))
.first->second.generate_xmit(frame.sendqueue, frame.txflags);
pump();
PumpCryptoOutbound();
}
bool
llarp_link_session::CheckRCValid()
{
// verify signatuire
if(!remote_router.VerifySignature(crypto))
{
llarp::LogError("invalid sig on rc");
return false;
}
if(remote_router.addrs.size()
== 0) // the remote node is a client node so accept it
return true;
// check if the RC owns a pubkey that we are using
for(const auto &ai : remote_router.addrs)
{
llarp::LogInfo("remote=", remote, " ai=", ai, " addr=", addr);
if(ai.pubkey == remote)
return true;
}
return false;
}
bool
llarp_link_session::IsEstablished()
{
return state == eEstablished;
}
void
llarp_link_session::send_LIM()
{
llarp::ShortHash 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, &serv->router->rc))
{
EnterState(eLIMSent);
// rewind message buffer
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// hash message buffer
crypto->shorthash(digest, buf);
// send
add_outbound_message(0, digest, buf);
++frame.txids;
}
else
llarp::LogError("LIM Encode failed");
}
static void
handle_generated_session_start(iwp_async_session_start *start)
{
llarp_link_session *link = static_cast< llarp_link_session * >(start->user);
if(llarp_ev_udp_sendto(link->udp, link->addr, start->buf, start->sz) == -1)
{
llarp::LogError("sendto failed");
return;
}
link->working = false;
link->EnterState(llarp_link_session::eSessionStartSent);
}
static void
handle_verify_intro(iwp_async_intro *intro)
{
llarp_link_session *self = static_cast< llarp_link_session * >(intro->user);
if(self == nullptr)
return;
self->working = false;
if(!intro->buf)
{
return;
}
delete[] intro->buf;
memcpy(self->remote, intro->remote_pubkey, 32);
llarp::LogInfo("got intro from ", llarp::PubKey(self->remote));
self->intro_ack();
}
static void
handle_verify_introack(iwp_async_introack *introack)
{
llarp_link_session *link =
static_cast< llarp_link_session * >(introack->user);
if(introack->buf == nullptr)
{
// invalid signature
link->working = false;
llarp::LogError("introack verify failed from ", link->addr);
return;
}
link->session_start();
}
static void
handle_establish_timeout(void *user, uint64_t orig, uint64_t left)
{
if(orig == 0)
return;
llarp_link_session *self = static_cast< llarp_link_session * >(user);
self->establish_job_id = 0;
if(self->establish_job)
{
llarp_link_establish_job *job = self->establish_job;
self->establish_job = nullptr;
job->link = self->serv;
if(self->IsEstablished())
{
job->session = self;
}
else
{
// timer timeout
job->session = nullptr;
}
if(!self->working)
job->result(job);
}
}
void
llarp_link_session::done()
{
if(intro_resend_job_id)
llarp_logic_cancel_call(serv->logic, intro_resend_job_id);
if(establish_job_id)
llarp_logic_cancel_call(serv->logic, establish_job_id);
}
void
llarp_link_session::PumpCryptoOutbound()
{
if(working)
return;
working = true;
llarp_threadpool_queue_job(serv->worker, {this, &handle_crypto_outbound});
}
// void llarp_link_session::PumpCodelInbound()
// {
// pump_recv_timer_id =
// llarp_logic_call_later(logic,
// {decryptedFrames.nextTickInterval, this,
// &handle_inbound_codel_delayed});
// }
void
llarp_link_session::EnterState(State st)
{
llarp::LogDebug("EnterState - entering state: ", st,
state == eLIMSent ? "eLIMSent" : "",
state == eSessionStartSent ? "eSessionStartSent" : "");
frame.alive();
state = st;
if(state == eSessionStartSent || state == eIntroAckSent)
{
// llarp::LogInfo("EnterState - ", state==eLIMSent?"eLIMSent":"",
// state==eSessionStartSent?"eSessionStartSent":"");
// PumpCodelInbound();
// PumpCodelOutbound();
PumpCryptoOutbound();
// StartInboundCodel();
}
}
void
llarp_link_session::on_intro(const void *buf, size_t sz)
{
if(sz < 32 * 3)
return;
// copy
auto intro = new iwp_async_intro;
intro->buf = new byte_t[sz];
memcpy(intro->buf, buf, sz);
memcpy(intro->nonce, intro->buf + 32, 32);
intro->sz = sz;
// give secret key
memcpy(intro->secretkey, eph_seckey, 64);
intro->user = this;
// set call back hook
intro->hook = &handle_verify_intro;
// call
EnterState(eIntroRecv);
working = true;
iwp_call_async_verify_intro(iwp, intro);
}
void
llarp_link_session::on_intro_ack(const void *buf, size_t sz)
{
if(sz >= sizeof(workbuf))
{
// too big?
llarp::LogError("introack too big");
return;
}
if(working)
return;
// cancel resend
llarp_logic_cancel_call(serv->logic, intro_resend_job_id);
// copy buffer so we own it
memcpy(workbuf, buf, sz);
// set intro ack parameters
introack.buf = workbuf;
introack.sz = sz;
introack.nonce = workbuf + 32;
introack.remote_pubkey = remote;
introack.token = token;
introack.secretkey = eph_seckey;
introack.user = this;
introack.hook = &handle_verify_introack;
// async verify
working = true;
iwp_call_async_verify_introack(iwp, &introack);
}
bool
llarp_link_session::is_invalidated() const
{
return frame.flags_agree(eSessionInvalidated);
}
llarp_link *
llarp_link_session::get_parent()
{
return serv;
}
void
llarp_link_session::TickLogic(llarp_time_t now)
{
decryptedFrames.Process(
[=](iwp_async_frame &f) { handle_frame_decrypt(&f); });
frame.process_inbound_queue();
frame.retransmit(now);
pump();
}
bool
llarp_link_session::Tick(llarp_time_t now)
{
if(timedout(now, SESSION_TIMEOUT))
{
// we are timed out
// when we are done doing stuff with all of our frames from the crypto
// workers we are done
llarp::LogWarn("Tick - ", addr, " timed out with ", frames,
" frames left, working=", working);
return !working;
}
if(is_invalidated())
{
// both sides agreeed to session invalidation
// terminate our session when all of our frames from the crypto workers
// are done
return !working;
}
if(state == eLIMSent || state == eEstablished)
{
if(now - lastKeepalive > KEEP_ALIVE_INTERVAL)
send_keepalive(this);
}
return false;
}
void
llarp_link_session::keepalive()
{
send_keepalive(this);
}
void
llarp_link_session::EncryptOutboundFrames()
{
outboundFrames.Process([&](iwp_async_frame &frame) {
if(iwp_encrypt_frame(&frame))
if(llarp_ev_udp_sendto(udp, addr, frame.buf, frame.sz) == -1)
llarp::LogError("sendto ", addr, " failed");
});
}
static void
handle_verify_session_start(iwp_async_session_start *s)
{
llarp_link_session *self = static_cast< llarp_link_session * >(s->user);
self->working = false;
if(!s->buf)
{
// verify fail
llarp::LogWarn("session start verify failed from ", self->addr);
}
else
{
llarp::LogInfo("session start okay from ", self->addr);
self->send_LIM();
self->pump();
}
}
static void
handle_introack_generated(iwp_async_introack *i)
{
llarp_link_session *link = static_cast< llarp_link_session * >(i->user);
link->working = false;
if(i->buf)
{
link->frame.alive();
llarp::LogDebug("send introack to ", link->addr, " via ", link->serv->addr);
if(llarp_ev_udp_sendto(link->udp, link->addr, i->buf, i->sz) != -1)
link->EnterState(llarp_link_session::State::eIntroAckSent);
}
else
{
// failed to generate?
llarp::LogWarn("failed to generate introack");
}
}
static void
handle_generated_intro(iwp_async_intro *i)
{
llarp_link_session *link = static_cast< llarp_link_session * >(i->user);
link->working = false;
if(i->buf)
{
llarp_ev_udp_sendto(link->udp, link->addr, i->buf, i->sz);
delete[] i->buf;
link->EnterState(llarp_link_session::eIntroSent);
link->lastIntroSentAt = llarp_time_now_ms();
auto dlt = (link->createdAt - link->lastIntroSentAt) + 500;
auto logic = link->serv->logic;
link->intro_resend_job_id = llarp_logic_call_later(
logic, {dlt, link, &llarp_link_session::handle_introack_timeout});
}
else
{
llarp::LogWarn("failed to generate intro");
}
delete i;
}
void
llarp_link_session::handle_introack_timeout(void *user, uint64_t timeout,
uint64_t left)
{
if(timeout && left == 0)
{
// timeout reached
llarp_link_session *self = static_cast< llarp_link_session * >(user);
// retry introduce
self->introduce(nullptr);
}
}
void
llarp_link_session::introduce(uint8_t *pub)
{
llarp::LogDebug("session introduce");
if(pub)
memcpy(remote, pub, PUBKEYSIZE);
auto intro = new iwp_async_intro;
intro->buf = new byte_t[1500];
size_t w0sz = (llarp_randint() % MAX_PAD);
intro->sz = (32 * 3) + w0sz;
// randomize w0
if(w0sz)
{
crypto->randbytes(intro->buf + (32 * 3), w0sz);
}
memcpy(intro->secretkey, eph_seckey, 64);
// copy in pubkey
memcpy(intro->remote_pubkey, remote, 32);
// randomize nonce
crypto->randbytes(intro->nonce, 32);
// async generate intro packet
intro->user = this;
intro->hook = &handle_generated_intro;
working = true;
iwp_call_async_gen_intro(iwp, intro);
// start introduce timer
if(pub)
establish_job_id = llarp_logic_call_later(
serv->logic, {5000, this, &handle_establish_timeout});
}
void
llarp_link_session::handle_frame_decrypt(iwp_async_frame *frame)
{
llarp_link_session *self = static_cast< llarp_link_session * >(frame->user);
if(frame->success)
{
if(self->frame.process(frame->buf + 64, frame->sz - 64))
{
self->frame.alive();
}
else
llarp::LogError("invalid frame from ", self->addr);
}
else
llarp::LogError("decrypt frame fail from ", self->addr);
}
void
llarp_link_session::decrypt_frame(const void *buf, size_t sz)
{
if(sz > 64)
{
llarp_link_session *self = this;
decryptedFrames.EmplaceIf([&](iwp_async_frame &f) -> bool {
if(sz > sizeof(f.buf))
return false;
f.sz = sz;
f.sessionkey = sessionkey;
f.iwp = iwp;
f.user = self;
memcpy(f.buf, buf, sz);
return iwp_decrypt_frame(&f);
});
// f->hook = &handle_frame_decrypt;
// iwp_call_async_frame_decrypt(iwp, f);
}
else
llarp::LogWarn("short packet of ", sz, " bytes");
}
void
llarp_link_session::session_start()
{
llarp::LogInfo("session gen start");
size_t w2sz = llarp_randint() % MAX_PAD;
start.buf = workbuf;
start.sz = w2sz + (32 * 3);
start.nonce = workbuf + 32;
crypto->randbytes(start.nonce, 32);
memcpy(start.buf + 64, token, 32);
if(w2sz)
crypto->randbytes(start.buf + (32 * 3), w2sz);
start.remote_pubkey = remote;
start.secretkey = eph_seckey;
start.sessionkey = sessionkey;
start.token = token;
start.user = this;
start.hook = &handle_generated_session_start;
working = true;
iwp_call_async_gen_session_start(iwp, &start);
}
void
llarp_link_session::on_session_start(const void *buf, size_t sz)
{
llarp::LogInfo("session start from ", addr);
if(sz > sizeof(workbuf))
{
llarp::LogDebug("session start too big");
working = false;
return;
}
// own the buffer
memcpy(workbuf, buf, sz);
// verify session start
start.buf = workbuf;
start.sz = sz;
start.nonce = workbuf + 32;
start.token = token;
start.remote_pubkey = remote;
start.secretkey = eph_seckey;
start.sessionkey = sessionkey;
start.user = this;
start.hook = &handle_verify_session_start;
working = true;
iwp_call_async_verify_session_start(iwp, &start);
}
void
llarp_link_session::intro_ack()
{
llarp::LogDebug("session introack");
uint16_t w1sz = llarp_randint() % MAX_PAD;
introack.buf = workbuf;
introack.sz = (32 * 3) + w1sz;
// randomize padding
if(w1sz)
crypto->randbytes(introack.buf + (32 * 3), w1sz);
// randomize nonce
introack.nonce = introack.buf + 32;
crypto->randbytes(introack.nonce, 32);
// token
crypto->randbytes(token, 32);
introack.token = token;
// keys
introack.remote_pubkey = remote;
introack.secretkey = eph_seckey;
// call
working = true;
introack.user = this;
introack.hook = &handle_introack_generated;
iwp_call_async_gen_introack(iwp, &introack);
}
// this is called from net thread
void
llarp_link_session::recv(const void *buf, size_t sz)
{
// llarp::LogDebug("session recv", state);
// frame_header hdr((byte_t *)buf);
// llarp::LogDebug("recv - message header type ", (int)hdr.msgtype());
switch(state)
{
case eInitial:
case eIntroRecv:
// got intro
llarp::LogDebug("session recv - intro");
on_intro(buf, sz);
break;
case eIntroSent:
// got intro ack
llarp::LogDebug("session recv - introack");
on_intro_ack(buf, sz);
break;
case eIntroAckSent:
// probably a session start
llarp::LogDebug("session recv - sessionstart");
on_session_start(buf, sz);
break;
case eSessionStartSent:
case eLIMSent:
case eEstablished:
// session is started
/*
llarp::LogDebug("session recv - ",
state == eSessionStartSent ? "startsent" : "",
state == eLIMSent ? "limset" : "",
state == eEstablished ? "established" : "");
*/
decrypt_frame(buf, sz);
break;
default:
llarp::LogError("session recv - invalid state: ", state);
// invalid state?
break;
}
}
void
llarp_link_session::encrypt_frame_async_send(const void *buf, size_t sz)
{
// 64 bytes frame overhead for nonce and hmac
if(sz + 64 > 1500)
return;
llarp_link_session *self = this;
outboundFrames.EmplaceIf([&](iwp_async_frame &frame) -> bool {
frame.iwp = iwp;
frame.sessionkey = sessionkey;
frame.user = self;
frame.sz = sz + 64;
memcpy(frame.buf + 64, buf, sz);
// maybe add upto 128 random bytes to the packet
auto padding = llarp_randint() % MAX_PAD;
if(padding)
crypto->randbytes(frame.buf + 64 + sz, padding);
frame.sz += padding;
return true;
});
}
void
llarp_link_session::pump()
{
bool flush = false;
frame.sendqueue.Process([&](sendbuf_t &msg) {
encrypt_frame_async_send(msg.data(), msg.size());
flush = true;
});
if(flush)
PumpCryptoOutbound();
}

@ -1,204 +0,0 @@
#include "llarp/iwp/transit_message.hpp"
#include "llarp/endian.h"
#include "llarp/iwp/frame_state.hpp"
#include "llarp/iwp/sendbuf.hpp"
#include "llarp/time.h"
void
transit_message::clear()
{
frags.clear();
lastfrag.clear();
}
// calculate acked bitmask
uint32_t
transit_message::get_bitmask() const
{
uint32_t bitmask = 0;
uint8_t idx = 0;
while(idx < 32)
{
bitmask |= (status.test(idx) ? (1 << idx) : 0);
++idx;
}
return bitmask;
}
// outbound
transit_message::transit_message(llarp_buffer_t buf, const byte_t *hash,
uint64_t id, uint16_t mtu)
{
started = llarp_time_now_ms();
put_message(buf, hash, id, mtu);
}
// inbound
transit_message::transit_message(const xmit &x) : msginfo(x)
{
started = llarp_time_now_ms();
byte_t fragidx = 0;
uint16_t fragsize = x.fragsize();
while(fragidx < x.numfrags())
{
frags[fragidx].resize(fragsize);
++fragidx;
}
status.reset();
}
/// ack packets based off a bitmask
void
transit_message::ack(uint32_t bitmask)
{
uint8_t idx = 0;
while(idx < 32)
{
if(bitmask & (1 << idx))
{
status.set(idx);
}
++idx;
}
lastAck = llarp_time_now_ms();
}
bool
transit_message::should_send_ack(llarp_time_t now) const
{
if(now < started)
return false;
if(msginfo.numfrags() == 0)
return true;
if(status.count() == 0)
return true;
if(now < lastRetransmit)
return false;
return now - lastRetransmit > 200;
}
bool
transit_message::should_resend_xmit(llarp_time_t now) const
{
if(now < started)
return false;
return lastAck == 0 && now - started > 1000;
}
bool
transit_message::should_resend_frags(llarp_time_t now) const
{
if(now < started || now < lastAck)
return false;
return lastAck > 0 && now - lastAck > 500 && !completed();
}
bool
transit_message::completed() const
{
for(byte_t idx = 0; idx < msginfo.numfrags(); ++idx)
{
if(!status.test(idx))
return false;
}
return true;
}
// template < typename T >
void
transit_message::generate_xmit(sendqueue_t &queue, byte_t flags)
{
uint16_t sz = lastfrag.size() + sizeof(msginfo.buffer);
queue.EmplaceIf(
[&](sendbuf_t &pkt) -> bool {
auto body_ptr = init_sendbuf(&pkt, eXMIT, sz, flags);
memcpy(body_ptr, msginfo.buffer, sizeof(msginfo.buffer));
body_ptr += sizeof(msginfo.buffer);
memcpy(body_ptr, lastfrag.data(), lastfrag.size());
return true;
},
sz + 6);
}
// template < typename T >
void
transit_message::retransmit_frags(sendqueue_t &queue, byte_t flags)
{
auto msgid = msginfo.msgid();
auto fragsize = msginfo.fragsize();
for(auto &frag : frags)
{
if(status.test(frag.first))
continue;
uint16_t sz = 9 + fragsize;
queue.EmplaceIf(
[&](sendbuf_t &pkt) -> bool {
auto body_ptr = init_sendbuf(&pkt, eFRAG, sz, flags);
htobe64buf(body_ptr, msgid);
body_ptr[8] = frag.first;
memcpy(body_ptr + 9, frag.second.data(), fragsize);
return true;
},
sz + 6);
}
lastRetransmit = llarp_time_now_ms();
}
bool
transit_message::reassemble(std::vector< byte_t > &buffer) const
{
auto total = msginfo.totalsize();
buffer.resize(total);
auto fragsz = msginfo.fragsize();
auto ptr = &buffer[0];
for(byte_t idx = 0; idx < msginfo.numfrags(); ++idx)
{
if(!status.test(idx))
return false;
memcpy(ptr, frags.at(idx).data(), fragsz);
ptr += fragsz;
}
memcpy(ptr, lastfrag.data(), lastfrag.size());
return true;
}
void
transit_message::put_message(llarp_buffer_t buf, const byte_t *hash,
uint64_t id, uint16_t mtu)
{
status.reset();
uint8_t fragid = 0;
uint16_t fragsize = mtu;
size_t left = buf.sz;
while(left > fragsize)
{
auto &frag = frags[fragid];
frag.resize(fragsize);
memcpy(frag.data(), buf.cur, fragsize);
buf.cur += fragsize;
fragid++;
left -= fragsize;
}
uint16_t lastfrag = buf.sz - (buf.cur - buf.base);
// set info for xmit
msginfo.set_info(hash, id, fragsize, lastfrag, fragid);
put_lastfrag(buf.cur, lastfrag);
}
void
transit_message::put_lastfrag(byte_t *buf, size_t sz)
{
lastfrag.resize(sz);
memcpy(lastfrag.data(), buf, sz);
}
bool
transit_message::put_frag(byte_t fragno, byte_t *buf)
{
auto itr = frags.find(fragno);
if(itr == frags.end())
return false;
memcpy(itr->second.data(), buf, msginfo.fragsize());
status.set(fragno);
return true;
}

@ -1,74 +0,0 @@
#include "llarp/iwp/xmit.hpp"
#include "llarp/endian.h"
xmit::xmit(byte_t *ptr)
{
memcpy(buffer, ptr, sizeof(buffer));
}
xmit::xmit(const xmit &other)
{
memcpy(buffer, other.buffer, sizeof(buffer));
}
void
xmit::set_info(const byte_t *hash, uint64_t id, uint16_t fragsz,
uint16_t lastsz, uint8_t numfrags, uint8_t flags)
{
memcpy(buffer, hash, 32);
// memcpy(buffer + 32, &id, 8);
htobe64buf(buffer + 32, id);
// memcpy(buffer + 40, &fragsz, 2);
htobe16buf(buffer + 40, fragsz);
// memcpy(buffer + 42, &lastsz, 2);
htobe16buf(buffer + 42, lastsz);
buffer[44] = 0;
buffer[45] = 0;
buffer[46] = numfrags;
buffer[47] = flags;
}
const byte_t *
xmit::hash() const
{
return &buffer[0];
}
uint64_t
xmit::msgid() const
{
return bufbe64toh(buffer + 32);
}
// size of each full fragment
uint16_t
xmit::fragsize() const
{
return bufbe16toh(buffer + 40);
}
// number of full fragments
uint8_t
xmit::numfrags() const
{
return buffer[46];
}
// size of the entire message
size_t
xmit::totalsize() const
{
return (fragsize() * numfrags()) + lastfrag();
}
// size of the last fragment
uint16_t
xmit::lastfrag() const
{
return bufbe16toh(buffer + 42);
}
uint8_t
xmit::flags()
{
return buffer[47];
}

@ -15,7 +15,7 @@ namespace llarp
{
if(llarp_buffer_eq(key, "r"))
{
return RC->BDecode(buf);
return rc.BDecode(buf);
}
else if(llarp_buffer_eq(key, "v"))
{
@ -48,13 +48,10 @@ namespace llarp
if(!bencode_write_bytestring(buf, "i", 1))
return false;
if(RC)
{
if(!bencode_write_bytestring(buf, "r", 1))
return false;
if(!RC->BEncode(buf))
return false;
}
if(!bencode_write_bytestring(buf, "r", 1))
return false;
if(rc.BEncode(buf))
return false;
if(!bencode_write_version_entry(buf))
return false;
@ -65,8 +62,7 @@ namespace llarp
bool
LinkIntroMessage::HandleMessage(llarp_router* router) const
{
RouterContact contact = *RC;
router->async_verify_RC(contact, !contact.IsPublicRouter());
router->async_verify_RC(rc, !rc.IsPublicRouter());
return true;
}
} // namespace llarp

@ -0,0 +1,5 @@
#ifndef LLARP_LINK_LAYER_HPP
#define LLARP_LINK_LAYER_HPP
#include <llarp/link/server.hpp>
#include <llarp/link/session.hpp>
#endif

@ -1,16 +1,11 @@
#include <llarp/router_contact.hpp>
#include <llarp/messages.hpp>
#include "buffer.hpp"
#include "llarp/iwp/session.hpp"
#include "logger.hpp"
#include "router.hpp"
namespace llarp
{
ILinkMessage::ILinkMessage(const RouterID& id) : remote(id)
{
}
InboundMessageParser::InboundMessageParser(llarp_router* _router)
: router(_router)
{
@ -54,23 +49,19 @@ namespace llarp
switch(*strbuf.cur)
{
case 'i':
handler->msg =
new LinkIntroMessage(handler->from->get_remote_router());
handler->msg = new LinkIntroMessage(handler->from);
break;
case 'd':
handler->msg = new RelayDownstreamMessage(handler->GetCurrentFrom());
handler->msg = new RelayDownstreamMessage(handler->from);
break;
case 'u':
handler->msg = new RelayUpstreamMessage(handler->GetCurrentFrom());
handler->msg = new RelayUpstreamMessage(handler->from);
break;
case 'm':
handler->msg = new DHTImmeidateMessage(handler->GetCurrentFrom());
break;
case 'a':
handler->msg = new LR_AckMessage(handler->GetCurrentFrom());
handler->msg = new DHTImmeidateMessage(handler->from);
break;
case 'c':
handler->msg = new LR_CommitMessage(handler->GetCurrentFrom());
handler->msg = new LR_CommitMessage(handler->from);
break;
default:
return false;
@ -85,12 +76,6 @@ namespace llarp
return handler->msg->DecodeKey(*key, r->buffer);
}
RouterID
InboundMessageParser::GetCurrentFrom()
{
return from->get_remote_router()->pubkey;
}
bool
InboundMessageParser::MessageDone()
{
@ -105,7 +90,7 @@ namespace llarp
}
bool
InboundMessageParser::ProcessFrom(llarp_link_session* src, llarp_buffer_t buf)
InboundMessageParser::ProcessFrom(ILinkSession* src, llarp_buffer_t buf)
{
from = src;
firstkey = true;

@ -2,6 +2,7 @@
#include <llarp/encrypted_frame.hpp>
#include <llarp/path.hpp>
#include <llarp/pathbuilder.hpp>
#include <llarp/messages/dht.hpp>
#include "buffer.hpp"
#include "router.hpp"
@ -405,11 +406,11 @@ namespace llarp
r->crypto.xchacha20(buf, hop.shared, n);
n ^= hop.nonceXOR;
}
RelayUpstreamMessage* msg = new RelayUpstreamMessage;
msg->X = buf;
msg->Y = Y;
msg->pathid = TXID();
if(r->SendToOrQueue(Upstream(), msg))
RelayUpstreamMessage msg;
msg.X = buf;
msg.Y = Y;
msg.pathid = TXID();
if(r->SendToOrQueue(Upstream(), &msg))
return true;
llarp::LogError("send to ", Upstream(), " failed");
return false;
@ -546,11 +547,12 @@ namespace llarp
bool
Path::HandleDHTMessage(const llarp::dht::IMessage* msg, llarp_router* r)
{
std::vector< llarp::dht::IMessage* > discard;
auto result = msg->HandleMessage(r->dht, discard);
for(auto& msg : discard)
delete msg;
return result;
llarp::routing::DHTMessage reply;
if(!msg->HandleMessage(r->dht, reply.M))
return false;
if(reply.M.size())
return SendRoutingMessage(&reply, r);
return true;
}
} // namespace path

@ -1,85 +0,0 @@
#include <llarp/messages/relay_ack.hpp>
#include "router.hpp"
namespace llarp
{
bool
LR_AckRecord::BEncode(llarp_buffer_t* buf) const
{
return false;
}
bool
LR_AckRecord::BDecode(llarp_buffer_t* buf)
{
return false;
}
LR_AckMessage::LR_AckMessage(const RouterID& from) : ILinkMessage(from)
{
}
LR_AckMessage::~LR_AckMessage()
{
}
bool
LR_AckMessage::BEncode(llarp_buffer_t* buf) const
{
return false;
}
bool
LR_AckMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf)
{
return false;
}
struct LRAM_Decrypt
{
typedef AsyncFrameDecrypter< LRAM_Decrypt > Decrypter;
llarp_router* router;
Decrypter* decrypt;
std::vector< EncryptedFrame > frames;
LR_AckRecord record;
LRAM_Decrypt(llarp_router* r, byte_t* seckey,
const std::vector< EncryptedFrame >& f)
: router(r), frames(f)
{
decrypt = new Decrypter(&r->crypto, seckey, &Decrypted);
}
~LRAM_Decrypt()
{
delete decrypt;
}
static void
Decrypted(llarp_buffer_t* buf, LRAM_Decrypt* self)
{
if(!buf)
{
llarp::LogError("Failed to decrypt LRAM frame");
delete self;
return;
}
if(!self->record.BDecode(buf))
{
llarp::LogError("LRAR invalid format");
delete self;
return;
}
}
};
bool
LR_AckMessage::HandleMessage(llarp_router* router) const
{
// TODO: use different private key for different path contexts as client
LRAM_Decrypt* lram = new LRAM_Decrypt(router, router->encryption, replies);
lram->decrypt->AsyncDecrypt(router->tp, &lram->frames[0], lram);
return true;
}
} // namespace llarp

@ -55,8 +55,6 @@ namespace llarp
}
if(!router->paths.AllowingTransit())
{
llarp::LogError("got an LRCM from ", remote,
" when we are not allowing transit");
return false;
}
return AsyncDecrypt(&router->paths);
@ -132,7 +130,7 @@ namespace llarp
return false;
}
self->work = new PoW;
self->work = new PoW();
return self->work->BDecode(r->buffer);
}
return read;
@ -176,7 +174,7 @@ namespace llarp
const LR_CommitMessage* commit)
: decrypter(dec), frames(commit->frames), context(ctx), hop(new Hop())
{
hop->info.downstream = commit->remote;
hop->info.downstream = commit->session->GetPubKey();
}
~LRCMFrameDecrypt()

@ -5,7 +5,7 @@
namespace llarp
{
RelayUpstreamMessage::RelayUpstreamMessage(const RouterID &from)
RelayUpstreamMessage::RelayUpstreamMessage(ILinkSession *from)
: ILinkMessage(from)
{
}
@ -54,21 +54,17 @@ namespace llarp
}
bool
RelayUpstreamMessage::HandleMessage(llarp_router *router) const
RelayUpstreamMessage::HandleMessage(llarp_router *r) const
{
auto path = router->paths.GetByDownstream(remote, pathid);
auto path = r->paths.GetByDownstream(session->GetPubKey(), pathid);
if(path)
{
return path->HandleUpstream(X.Buffer(), Y, router);
}
else
{
llarp::LogWarn("No such path downstream=", remote, " pathid=", pathid);
return false;
return path->HandleUpstream(X.Buffer(), Y, r);
}
return false;
}
RelayDownstreamMessage::RelayDownstreamMessage(const RouterID &from)
RelayDownstreamMessage::RelayDownstreamMessage(ILinkSession *from)
: ILinkMessage(from)
{
}
@ -116,16 +112,12 @@ namespace llarp
}
bool
RelayDownstreamMessage::HandleMessage(llarp_router *router) const
RelayDownstreamMessage::HandleMessage(llarp_router *r) const
{
auto path = router->paths.GetByUpstream(remote, pathid);
auto path = r->paths.GetByUpstream(session->GetPubKey(), pathid);
if(path)
{
return path->HandleDownstream(X.Buffer(), Y, router);
}
else
{
llarp::LogWarn("No such path upstream=", remote, " pathid=", pathid);
return path->HandleDownstream(X.Buffer(), Y, r);
}
return false;
}

@ -2,9 +2,7 @@
#include <llarp/proto.h>
#include <llarp/iwp.hpp>
#include <llarp/link_message.hpp>
#include "llarp/iwp/establish_job.hpp"
#include "llarp/iwp/server.hpp"
#include "llarp/iwp/session.hpp"
#include <llarp/link/curvecp.hpp>
#include "buffer.hpp"
#include "encode.hpp"
@ -23,11 +21,70 @@ namespace llarp
struct async_verify_context
{
llarp_router *router;
llarp_link_establish_job *establish_job;
llarp::OutboundLinkEstablishJob *establish_job;
};
} // namespace llarp
struct TryConnectJob : public llarp::OutboundLinkEstablishJob
{
llarp::ILinkLayer *link;
llarp_router *router;
uint16_t triesLeft;
TryConnectJob(const llarp::RouterContact &remote, llarp::ILinkLayer *l,
uint16_t tries, llarp_router *r)
: OutboundLinkEstablishJob(remote), link(l), router(r), triesLeft(tries)
{
}
void
Failed()
{
link->CloseSessionTo(rc.pubkey);
}
void
Success()
{
router->FlushOutboundFor(rc.pubkey, link);
router->pendingEstablishJobs.erase(rc.pubkey);
// we are gone
}
void
AttemptTimedout()
{
--triesLeft;
if(!ShouldRetry())
{
router->pendingEstablishJobs.erase(rc.pubkey);
// we are gone after this
return;
}
Attempt();
}
void
Attempt()
{
link->TryEstablishTo(rc);
}
bool
ShouldRetry() const
{
return triesLeft > 0;
}
};
static void
on_try_connecting(void *u)
{
llarp::OutboundLinkEstablishJob *j =
static_cast< llarp::OutboundLinkEstablishJob * >(u);
j->Attempt();
}
bool
llarp_router_try_connect(struct llarp_router *router,
const llarp::RouterContact &remote,
@ -39,34 +96,14 @@ llarp_router_try_connect(struct llarp_router *router,
llarp::LogDebug("We have pending connect jobs to ", remote.pubkey);
return false;
}
// try first address only
if(remote.addrs.size())
{
auto link = router->outboundLink;
auto itr = router->pendingEstablishJobs.insert(
std::make_pair(remote.pubkey, llarp_link_establish_job()));
auto job = &itr.first->second;
job->ai = remote.addrs.front();
job->pubkey = remote.pubkey;
job->retries = numretries;
job->timeout = 10000;
job->result = &llarp_router::on_try_connect_result;
// give router as user pointer
job->user = router;
job->link = link;
// try establishing async
llarp_logic_queue_job(router->logic,
{job, [](void *u) {
llarp_link_establish_job *j =
static_cast< llarp_link_establish_job * >(u);
j->link->try_establish(j);
j->link = nullptr;
}});
return true;
}
llarp::LogWarn("couldn't get first address for ", remote.pubkey);
return false;
auto link = router->outboundLink.get();
auto itr = router->pendingEstablishJobs.insert(std::make_pair(
remote.pubkey, new TryConnectJob(remote, link, numretries, router)));
llarp::OutboundLinkEstablishJob *job = itr.first->second;
// try establishing async
llarp_logic_queue_job(router->logic, {job, on_try_connecting});
return true;
}
llarp_router::llarp_router()
@ -88,8 +125,8 @@ llarp_router::~llarp_router()
}
bool
llarp_router::HandleRecvLinkMessage(llarp_link_session *session,
llarp_buffer_t buf)
llarp_router::HandleRecvLinkMessageBuffer(llarp::ILinkSession *session,
llarp_buffer_t buf)
{
return inbound_link_msg_parser.ProcessFrom(session, buf);
}
@ -114,14 +151,14 @@ llarp_router::SendToOrQueue(const llarp::RouterID &remote,
{
std::unique_ptr< const llarp::ILinkMessage > msg =
std::unique_ptr< const llarp::ILinkMessage >(m);
llarp_link *chosen = nullptr;
llarp::ILinkLayer *chosen = nullptr;
if(inboundLinks.size() == 0)
chosen = outboundLink;
chosen = outboundLink.get();
else
chosen = inboundLinks.front();
chosen = inboundLinks.front().get();
if(chosen->has_session_to(remote))
if(chosen->HasSessionTo(remote))
{
SendTo(remote, msg, chosen);
return true;
@ -132,7 +169,16 @@ llarp_router::SendToOrQueue(const llarp::RouterID &remote,
{
outboundMessageQueue.insert(std::make_pair(remote, MessageQueue()));
}
outboundMessageQueue[remote].push(std::move(msg));
// encode
llarp_buffer_t buf =
llarp::StackBuffer< decltype(linkmsg_buffer) >(linkmsg_buffer);
if(!msg->BEncode(&buf))
return false;
// queue buffer
auto &q = outboundMessageQueue[remote];
buf.sz = buf.cur - buf.base;
q.emplace(buf.sz);
memcpy(q.back().data(), buf.base, buf.sz);
// we don't have an open session to that router right now
if(llarp_nodedb_get_rc(nodedb, remote, rc))
@ -208,9 +254,9 @@ llarp_router::EnsureEncryptionKey()
}
void
llarp_router::AddInboundLink(struct llarp_link *link)
llarp_router::AddInboundLink(std::unique_ptr< llarp::ILinkLayer > &link)
{
inboundLinks.push_back(link);
inboundLinks.push_back(std::move(link));
}
bool
@ -236,38 +282,17 @@ void
llarp_router::Close()
{
llarp::LogInfo("Closing ", inboundLinks.size(), " server bindings");
for(auto link : inboundLinks)
for(const auto &link : inboundLinks)
{
link->stop_link();
delete link;
link->Stop();
}
inboundLinks.clear();
llarp::LogInfo("Closing LokiNetwork client");
if(outboundLink)
{
outboundLink->stop_link();
delete outboundLink;
outboundLink = nullptr;
}
}
void
llarp_router::connect_job_retry(void *user, uint64_t orig, uint64_t left)
{
if(left)
return;
llarp_link_establish_job *job =
static_cast< llarp_link_establish_job * >(user);
llarp::Addr remote = job->ai;
if(job->link)
{
llarp::LogInfo("trying to establish session again with ", remote);
job->link->try_establish(job);
}
else
{
llarp::LogError("establish session retry failed, no link for ", remote);
outboundLink->Stop();
outboundLink.reset(nullptr);
}
}
@ -293,11 +318,8 @@ llarp_router::on_verify_server_rc(llarp_async_verify_rc *job)
if(ctx->establish_job)
{
// was an outbound attempt
auto session = ctx->establish_job->session;
if(session)
session->close();
ctx->establish_job->Failed();
}
router->pendingEstablishJobs.erase(pk);
router->DiscardOutboundFor(pk);
return;
}
@ -314,10 +336,7 @@ llarp_router::on_verify_server_rc(llarp_async_verify_rc *job)
// this was an outbound establish job
if(ctx->establish_job)
{
auto session = ctx->establish_job->session;
router->FlushOutboundFor(pk, session->get_parent());
// this frees the job
router->pendingEstablishJobs.erase(pk);
ctx->establish_job->Success();
}
else // this was an inbound session
router->FlushOutboundFor(pk, router->GetLinkWithSessionByPubkey(pk));
@ -422,7 +441,7 @@ llarp_router::Tick()
void
llarp_router::SendTo(llarp::RouterID remote,
std::unique_ptr< const llarp::ILinkMessage > &msg,
llarp_link *link)
llarp::ILinkLayer *selected)
{
llarp_buffer_t buf =
llarp::StackBuffer< decltype(linkmsg_buffer) >(linkmsg_buffer);
@ -436,22 +455,24 @@ llarp_router::SendTo(llarp::RouterID remote,
// set size of message
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
if(link)
if(selected)
{
link->sendto(remote, buf);
selected->SendTo(remote, buf);
return;
}
bool sent = outboundLink->sendto(remote, buf);
bool sent = outboundLink->SendTo(remote, buf);
if(!sent)
{
for(auto link : inboundLinks)
for(const auto &link : inboundLinks)
{
if(!sent)
{
sent = link->sendto(remote, buf);
sent = link->SendTo(remote, buf);
}
}
}
if(!sent)
llarp::LogWarn("message to ", remote, " was dropped");
}
void
@ -472,22 +493,22 @@ llarp_router::SessionClosed(const llarp::RouterID &remote)
validRouters.erase(itr);
}
llarp_link *
llarp::ILinkLayer *
llarp_router::GetLinkWithSessionByPubkey(const llarp::RouterID &pubkey)
{
for(auto &link : inboundLinks)
if(outboundLink->HasSessionTo(pubkey))
return outboundLink.get();
for(const auto &link : inboundLinks)
{
if(link->has_session_to(pubkey))
return link;
if(link->HasSessionTo(pubkey))
return link.get();
}
if(outboundLink->has_session_to(pubkey))
return outboundLink;
return nullptr;
}
void
llarp_router::FlushOutboundFor(const llarp::RouterID &remote,
llarp_link *chosen)
llarp::ILinkLayer *chosen)
{
llarp::LogDebug("Flush outbound for ", remote);
auto itr = outboundMessageQueue.find(remote);
@ -502,61 +523,15 @@ llarp_router::FlushOutboundFor(const llarp::RouterID &remote,
}
while(itr->second.size())
{
auto buf = llarp::StackBuffer< decltype(linkmsg_buffer) >(linkmsg_buffer);
const auto &msg = itr->second.front();
if(!msg->BEncode(&buf))
{
llarp::LogWarn("failed to encode outbound message, buffer size left: ",
llarp_buffer_size_left(buf));
itr->second.pop();
continue;
}
// set size of message
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
if(!chosen->sendto(remote, buf))
auto buf = llarp::ConstBuffer(itr->second.front());
if(!chosen->SendTo(remote, buf))
llarp::LogWarn("failed to send outboud message to ", remote, " via ",
chosen->name());
chosen->Name());
itr->second.pop();
}
}
void
llarp_router::on_try_connect_result(llarp_link_establish_job *job)
{
llarp_router *router = static_cast< llarp_router * >(job->user);
if(job->session)
{
// llarp::LogDebug("try_connect got session");
// auto session = job->session;
// router->async_verify_RC(session->get_remote_router(), false, job);
return;
}
// llarp::LogDebug("try_connect no session");
llarp::PubKey pk = job->pubkey;
if(job->retries > 0)
{
job->retries--;
job->timeout *= 3;
job->timeout /= 2;
llarp::LogInfo("session not established with ", pk, " relaxing timeout to ",
job->timeout);
// exponential backoff
llarp_logic_call_later(
router->logic, {job->timeout, job, &llarp_router::connect_job_retry});
}
else
{
llarp::LogWarn("failed to connect to ", pk,
" dropping all pending messages");
router->DiscardOutboundFor(pk);
router->pendingEstablishJobs.erase(pk);
}
}
void
llarp_router::DiscardOutboundFor(const llarp::RouterID &remote)
{
@ -581,7 +556,7 @@ llarp_router::GetRandomConnectedRouter(llarp::RouterContact &result) const
void
llarp_router::async_verify_RC(const llarp::RouterContact &rc,
bool isExpectingClient,
llarp_link_establish_job *establish_job)
llarp::OutboundLinkEstablishJob *establish_job)
{
llarp_async_verify_rc *job = new llarp_async_verify_rc();
llarp::async_verify_context *ctx = new llarp::async_verify_context();
@ -620,10 +595,11 @@ llarp_router::Run()
}
llarp::LogInfo("You have ", inboundLinks.size(), " inbound links");
for(auto link : inboundLinks)
for(const auto &link : inboundLinks)
{
llarp::AddressInfo addr;
link->get_our_address(addr);
if(!link->GetOurAddressInfo(addr))
continue;
llarp::Addr a(addr);
if(this->publicOverride && a.sameAddr(publicAddr))
{
@ -637,12 +613,11 @@ llarp_router::Run()
};
if(this->publicOverride)
{
llarp::ILinkLayer *link = nullptr;
// llarp::LogWarn("Need to load our public IP into RC!");
llarp_link *link = nullptr;
if(inboundLinks.size() == 1)
{
link = inboundLinks.front();
link = inboundLinks.front().get();
}
else
{
@ -651,15 +626,17 @@ llarp_router::Run()
llarp::LogError("No inbound links found, aborting");
return;
}
link = inboundLinks.front();
link = inboundLinks.front().get();
}
if(link->GetOurAddressInfo(this->addrInfo))
{
// override ip and port
this->addrInfo.ip = *publicAddr.addr6();
this->addrInfo.port = publicAddr.port();
llarp::LogInfo("Loaded our public ", publicAddr, " override into RC!");
// we need the link to set the pubkey
rc.addrs.push_back(this->addrInfo);
}
link->get_our_address(this->addrInfo);
// override ip and port
this->addrInfo.ip = *publicAddr.addr6();
this->addrInfo.port = publicAddr.port();
llarp::LogInfo("Loaded our public ", publicAddr, " override into RC!");
// we need the link to set the pubkey
rc.addrs.push_back(this->addrInfo);
}
// set public encryption key
rc.enckey = llarp::seckey_topublic(encryption);
@ -681,7 +658,7 @@ llarp_router::Run()
}
llarp::LogDebug("starting outbound link");
if(!outboundLink->start_link(logic))
if(!outboundLink->Start(logic))
{
llarp::LogWarn("outbound link failed to start");
}
@ -689,15 +666,15 @@ llarp_router::Run()
int IBLinksStarted = 0;
// start links
for(auto link : inboundLinks)
for(const auto &link : inboundLinks)
{
if(link->start_link(logic))
if(link->Start(logic))
{
llarp::LogDebug("Link ", link->name(), " started");
llarp::LogDebug("Link ", link->Name(), " started");
IBLinksStarted++;
}
else
llarp::LogWarn("Link ", link->name(), " failed to start");
llarp::LogWarn("Link ", link->Name(), " failed to start");
}
if(IBLinksStarted > 0)
@ -748,29 +725,19 @@ llarp_router::InitOutboundLink()
if(outboundLink)
return true;
llarp_iwp_args args = {
&crypto, logic, tp, this, transport_keyfile.string(),
};
auto link = new llarp_link(args);
auto link = llarp::curvecp::NewServer(this);
auto afs = {AF_INET, AF_INET6};
if(link)
for(auto af : afs)
{
llarp::LogInfo("outbound link initialized");
for(auto af : afs)
if(link->Configure(netloop, "*", af, 0))
{
if(link->configure(netloop, "*", af, 0))
{
outboundLink = link;
llarp::LogInfo("outbound link ready");
return true;
}
outboundLink = std::move(link);
llarp::LogInfo("outbound link ready");
return true;
}
}
delete link;
llarp::LogError("failed to initialize outbound link");
return false;
}
@ -796,7 +763,7 @@ llarp_init_router(struct llarp_threadpool *tp, struct llarp_ev_loop *netloop,
#else
router->disk = llarp_init_threadpool(1, "llarp-diskio");
#endif
llarp_crypto_libsodium_init(&router->crypto);
llarp_crypto_init(&router->crypto);
}
return router;
}
@ -831,16 +798,6 @@ llarp_stop_router(struct llarp_router *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_free_router(struct llarp_router **router)
{
@ -949,51 +906,31 @@ namespace llarp
proto = std::atoi(val);
}
struct llarp_link *link = nullptr;
if(StrEq(section, "bind"))
{
if(!StrEq(key, "*"))
{
llarp_iwp_args args = {
&self->crypto,
self->logic,
self->tp,
self,
self->transport_keyfile.string(),
};
llarp::LogInfo("interface specific binding activated");
link = new llarp_link(args);
if(link)
auto server = llarp::curvecp::NewServer(self);
if(server->Configure(self->netloop, key, af, proto))
{
llarp::LogInfo("link ", key, " initialized");
if(link->configure(self->netloop, key, af, proto))
self->AddInboundLink(server);
return;
}
if(af == AF_INET6)
{
// we failed to configure IPv6
// try IPv4
llarp::LogInfo("link ", key,
" failed to configure IPv6, trying IPv4");
af = AF_INET;
if(server->Configure(self->netloop, key, af, proto))
{
self->AddInboundLink(link);
self->AddInboundLink(server);
return;
}
if(af == AF_INET6)
{
// we failed to configure IPv6
// try IPv4
llarp::LogInfo("link ", key,
" failed to configure IPv6, trying IPv4");
af = AF_INET;
if(link->configure(self->netloop, key, af, proto))
{
self->AddInboundLink(link);
return;
}
}
}
else
{
llarp::LogError("link ", key, " failed to initialize. Link state",
link);
}
llarp::LogError("Failed to set up curvecp link");
}
llarp::LogError("link ", key,
" failed to configure. (Note: We don't support * yet)");
}
else if(StrEq(section, "services"))
{
@ -1061,5 +998,5 @@ namespace llarp
self->publicOverride = true;
}
}
}
} // namespace llarp
} // namespace llarp

@ -4,10 +4,12 @@
#include <llarp/nodedb.hpp>
#include <llarp/router_contact.hpp>
#include <llarp/path.hpp>
#include <llarp/link_layer.hpp>
#include <functional>
#include <list>
#include <map>
#include <vector>
#include <unordered_map>
#include <llarp/dht.hpp>
@ -15,7 +17,7 @@
#include <llarp/link_message.hpp>
#include <llarp/routing/handler.hpp>
#include <llarp/service.hpp>
#include "llarp/iwp/establish_job.hpp"
#include <llarp/establish_job.hpp>
#include "crypto.hpp"
#include "fs.hpp"
@ -24,9 +26,6 @@
/** 2^15 bytes */
#define MAX_LINK_MSG_SIZE (32768)
struct llarp_link;
struct llarp_link_session_iter;
bool
llarp_findOrCreateEncryption(llarp_crypto *crypto, const char *fpath,
llarp::SecretKey &encryption);
@ -81,32 +80,37 @@ struct llarp_router
llarp::service::Context hiddenServiceContext;
llarp_link *outboundLink = nullptr;
std::list< llarp_link * > inboundLinks;
std::unique_ptr< llarp::ILinkLayer > outboundLink;
std::list< std::unique_ptr< llarp::ILinkLayer > > inboundLinks;
typedef std::queue< std::unique_ptr< const llarp::ILinkMessage > >
MessageQueue;
typedef std::queue< std::vector< byte_t > > MessageQueue;
/// outbound message queue
std::map< llarp::RouterID, MessageQueue > outboundMessageQueue;
std::unordered_map< llarp::RouterID, MessageQueue, llarp::RouterID::Hash >
outboundMessageQueue;
/// loki verified routers
std::map< llarp::RouterID, llarp::RouterContact > validRouters;
std::unordered_map< llarp::RouterID, llarp::RouterContact,
llarp::RouterID::Hash >
validRouters;
// pending establishing session with routers
std::map< llarp::PubKey, llarp_link_establish_job > pendingEstablishJobs;
std::unordered_map< llarp::RouterID, llarp::OutboundLinkEstablishJob *,
llarp::RouterID::Hash >
pendingEstablishJobs;
// sessions to persist -> timestamp to end persist at
std::map< llarp::RouterID, llarp_time_t > m_PersistingSessions;
std::unordered_map< llarp::RouterID, llarp_time_t, llarp::RouterID::Hash >
m_PersistingSessions;
llarp_router();
virtual ~llarp_router();
bool
HandleRecvLinkMessage(struct llarp_link_session *from, llarp_buffer_t msg);
HandleRecvLinkMessageBuffer(llarp::ILinkSession *from, llarp_buffer_t msg);
void
AddInboundLink(struct llarp_link *link);
AddInboundLink(std::unique_ptr< llarp::ILinkLayer > &link);
bool
InitOutboundLink();
@ -169,11 +173,12 @@ struct llarp_router
void
SendTo(llarp::RouterID remote,
std::unique_ptr< const llarp::ILinkMessage > &msg,
llarp_link *chosen = nullptr);
llarp::ILinkLayer *chosen);
/// manually flush outbound message queue for just 1 router
void
FlushOutboundFor(const llarp::RouterID &remote, llarp_link *chosen);
FlushOutboundFor(const llarp::RouterID &remote,
llarp::ILinkLayer *chosen = nullptr);
/// manually discard all pending messages to remote router
void
@ -199,7 +204,7 @@ struct llarp_router
void
ScheduleTicker(uint64_t i = 1000);
llarp_link *
llarp::ILinkLayer *
GetLinkWithSessionByPubkey(const llarp::RouterID &remote);
size_t
@ -210,7 +215,7 @@ struct llarp_router
void
async_verify_RC(const llarp::RouterContact &rc, bool isExpectingClient,
llarp_link_establish_job *job = nullptr);
llarp::OutboundLinkEstablishJob *job = nullptr);
void
HandleDHTLookupForSendTo(llarp::RouterID remote,
@ -220,16 +225,6 @@ struct llarp_router
HandleDHTLookupForTryEstablishTo(
const std::vector< llarp::RouterContact > &results);
static bool
iter_try_connect(llarp_router_link_iter *i, llarp_router *router,
llarp_link *l);
static void
on_try_connect_result(llarp_link_establish_job *job);
static void
connect_job_retry(void *user, uint64_t orig, uint64_t left);
static void
on_verify_client_rc(llarp_async_verify_rc *context);
@ -239,10 +234,6 @@ struct llarp_router
static void
handle_router_ticker(void *user, uint64_t orig, uint64_t left);
static bool
send_padded_message(struct llarp_link_session_iter *itr,
struct llarp_link_session *peer);
static void
HandleAsyncLoadRCForSendTo(llarp_async_load_rc *async);
};

@ -7,8 +7,6 @@ namespace llarp
{
DHTMessage::~DHTMessage()
{
for(auto& msg : M)
delete msg;
}
bool
@ -54,15 +52,15 @@ namespace llarp
{
// set source as us
llarp::dht::Key_t us = r->pubkey();
for(auto& msg : M)
for(const auto& msg : M)
{
msg->From = us;
msg->pathID = from;
if(!h->HandleDHTMessage(msg, r))
if(!h->HandleDHTMessage(msg.get(), r))
return false;
}
return true;
}
} // namespace routing
} // namespace llarp
} // namespace llarp

@ -440,7 +440,7 @@ namespace llarp
Endpoint::CachedTagResult::BuildRequestMessage(uint64_t txid)
{
llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage();
msg->M.push_back(new llarp::dht::FindIntroMessage(tag, txid));
msg->M.emplace_back(new llarp::dht::FindIntroMessage(tag, txid));
lastRequest = llarp_time_now_ms();
return msg;
}
@ -453,7 +453,7 @@ namespace llarp
{
m_CurrentPublishTX = llarp_randint();
llarp::routing::DHTMessage msg;
msg.M.push_back(new llarp::dht::PublishIntroMessage(
msg.M.emplace_back(new llarp::dht::PublishIntroMessage(
m_IntroSet, m_CurrentPublishTX, 4));
if(path->SendRoutingMessage(&msg, r))
{
@ -530,7 +530,7 @@ namespace llarp
BuildRequestMessage()
{
llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage();
msg->M.push_back(new llarp::dht::FindIntroMessage(txid, remote, 5));
msg->M.emplace_back(new llarp::dht::FindIntroMessage(txid, remote, 5));
llarp::LogInfo("build request for ", remote);
return msg;
}
@ -614,7 +614,7 @@ namespace llarp
auto path = GetEstablishedPathClosestTo(router);
routing::DHTMessage msg;
auto txid = GenTXID();
msg.M.push_back(
msg.M.emplace_back(
new dht::FindRouterMessage({}, dht::Key_t(router), txid));
if(path && path->SendRoutingMessage(&msg, m_Router))

@ -7,7 +7,7 @@ struct Base32Test : public ::testing::Test
{
Base32Test()
{
llarp_crypto_libsodium_init(&crypto);
llarp_crypto_init(&crypto);
}
llarp_crypto crypto;
@ -21,4 +21,4 @@ TEST_F(Base32Test, Serialize)
std::string encoded = llarp::Base32Encode(addr, tmp);
ASSERT_TRUE(llarp::Base32Decode(tmp, otherAddr));
ASSERT_TRUE(otherAddr == addr);
};
};

@ -16,7 +16,7 @@ class FrameTest : public ::testing::Test
FrameTest()
{
llarp_crypto_libsodium_init(&crypto);
llarp_crypto_init(&crypto);
}
~FrameTest()
@ -61,4 +61,4 @@ TEST_F(FrameTest, TestFrameCrypto)
LRCR otherRecord;
ASSERT_TRUE(otherRecord.BDecode(buf));
ASSERT_TRUE(otherRecord == record);
};
};

@ -8,7 +8,7 @@ struct HiddenServiceTest : public ::testing::Test
HiddenServiceTest()
{
llarp_crypto_libsodium_init(&crypto);
llarp_crypto_init(&crypto);
}
llarp_crypto*
@ -49,4 +49,4 @@ TEST_F(HiddenServiceTest, TestAddressToFromString)
llarp::service::Address addr;
ASSERT_TRUE(addr.FromString(str));
ASSERT_TRUE(addr == ident.pub.Addr());
}
}

@ -4,37 +4,38 @@
namespace llarp
{
struct PQCryptoTest : public ::testing::Test
{
llarp_crypto crypto;
PQKeyPair keys;
PQCryptoTest()
struct PQCryptoTest : public ::testing::Test
{
llarp_crypto_libsodium_init(&crypto);
}
llarp_crypto crypto;
PQKeyPair keys;
llarp_crypto * Crypto()
{
return &crypto;
}
PQCryptoTest()
{
llarp_crypto_init(&crypto);
}
void SetUp()
{
crypto.pqe_keygen(keys);
}
llarp_crypto*
Crypto()
{
return &crypto;
}
};
void
SetUp()
{
crypto.pqe_keygen(keys);
}
};
TEST_F(PQCryptoTest, TestCrypto)
{
PQCipherBlock block;
SharedSecret shared, otherShared;
auto c = Crypto();
TEST_F(PQCryptoTest, TestCrypto)
{
PQCipherBlock block;
SharedSecret shared, otherShared;
auto c = Crypto();
ASSERT_TRUE(keys.size() == PQ_KEYPAIRSIZE);
ASSERT_TRUE(c->pqe_encrypt(block, shared, pq_keypair_to_public(keys)));
ASSERT_TRUE(c->pqe_decrypt(block, otherShared, pq_keypair_to_secret(keys)));
ASSERT_TRUE(otherShared == shared);
}
}
ASSERT_TRUE(keys.size() == PQ_KEYPAIRSIZE);
ASSERT_TRUE(c->pqe_encrypt(block, shared, pq_keypair_to_public(keys)));
ASSERT_TRUE(c->pqe_decrypt(block, otherShared, pq_keypair_to_secret(keys)));
ASSERT_TRUE(otherShared == shared);
}
} // namespace llarp

Loading…
Cancel
Save