mirror of https://github.com/oxen-io/lokinet
parent
7765d7c006
commit
c3c388b6aa
@ -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
|
@ -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
|
@ -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
|
|
@ -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];
|
|
||||||
}
|
|
@ -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,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
|
|
Loading…
Reference in New Issue