mirror of https://github.com/oxen-io/lokinet
broken
This commit is contained in:
parent
ba648868c4
commit
60d5277351
|
@ -19,7 +19,7 @@ else()
|
|||
CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17)
|
||||
endif()
|
||||
|
||||
option(HAVE_CXX17_FILESYSTEM "Enable if your C++ compiler and runtime library implements std::[experimental::]filesystem" OFF)
|
||||
option(HAVE_CXX17_FILESYSTEM "Disable if your C++ compiler and runtime library lacks std::[experimental::]filesystem" ON)
|
||||
|
||||
if(COMPILER_SUPPORTS_CXX11 AND NOT HAVE_CXX17_FILESYSTEM)
|
||||
add_cxxflags("-std=c++11")
|
||||
|
@ -47,7 +47,7 @@ else()
|
|||
set(THREAD_LIB pthread)
|
||||
endif()
|
||||
|
||||
add_cxxflags("-fno-rtti -fno-exceptions -fpermissive")
|
||||
add_cxxflags("-fno-exceptions -fpermissive -fno-rtti")
|
||||
|
||||
if (NOT MSVC)
|
||||
add_cflags("-march=native")
|
||||
|
@ -146,7 +146,14 @@ else()
|
|||
)
|
||||
endif()
|
||||
|
||||
set(LIBS ${SODIUM_LIB} ${THREAD_LIB} jemalloc)
|
||||
if(JEMALLOC)
|
||||
set(MALLOC_LIB jemalloc)
|
||||
endif()
|
||||
|
||||
set(LIBS ${SODIUM_LIB} ${THREAD_LIB} ${MALLOC_LIB})
|
||||
if(HAVE_CXX17_FILESYSTEM)
|
||||
set(LIBS ${LIBS} stdc++fs)
|
||||
endif()
|
||||
|
||||
set(LIB lokinet)
|
||||
set(SHARED_LIB ${LIB})
|
||||
|
@ -368,7 +375,6 @@ set(LIB_SRC
|
|||
llarp/dht/publish_intro.cpp
|
||||
llarp/handlers/tun.cpp
|
||||
llarp/link/curvecp.cpp
|
||||
llarp/link/encoder.cpp
|
||||
llarp/link/server.cpp
|
||||
llarp/link/utp.cpp
|
||||
llarp/routing/dht_message.cpp
|
||||
|
|
2
Makefile
2
Makefile
|
@ -43,7 +43,7 @@ clean:
|
|||
rm -f *.a *.so
|
||||
|
||||
debug-configure:
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON -DJEMALLOC=ON
|
||||
|
||||
release-configure: clean
|
||||
cmake -GNinja -DSTATIC_LINK=ON -DCMAKE_BUILD_TYPE=Release -DRELEASE_MOTTO="$(shell cat motto.txt)" -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON
|
||||
|
|
|
@ -25,6 +25,21 @@ namespace llarp
|
|||
struct in6_addr ip;
|
||||
uint16_t port;
|
||||
|
||||
AddressInfo() : IBEncodeMessage()
|
||||
{
|
||||
}
|
||||
|
||||
AddressInfo(const AddressInfo& other)
|
||||
: IBEncodeMessage()
|
||||
, rank(other.rank)
|
||||
, dialect(other.dialect)
|
||||
, pubkey(other.pubkey)
|
||||
{
|
||||
port = other.port;
|
||||
version = other.version;
|
||||
memcpy(ip.s6_addr, other.ip.s6_addr, 16);
|
||||
}
|
||||
|
||||
~AddressInfo();
|
||||
|
||||
AddressInfo&
|
||||
|
|
|
@ -240,15 +240,23 @@ namespace llarp
|
|||
}
|
||||
|
||||
// TODO: check for shadowed values elsewhere
|
||||
uint64_t version = 0;
|
||||
uint64_t version = LLARP_PROTO_VERSION;
|
||||
|
||||
static bool
|
||||
OnKey(dict_reader* r, llarp_buffer_t* k)
|
||||
{
|
||||
if(k)
|
||||
return static_cast< IBEncodeMessage* >(r->user)->DecodeKey(*k,
|
||||
r->buffer);
|
||||
return true;
|
||||
return static_cast< IBEncodeMessage* >(r->user)->HandleKey(k, r->buffer);
|
||||
}
|
||||
|
||||
bool
|
||||
HandleKey(llarp_buffer_t* k, llarp_buffer_t* val)
|
||||
{
|
||||
if(k == nullptr)
|
||||
return true;
|
||||
if(DecodeKey(*k, val))
|
||||
return true;
|
||||
llarp::LogError("unhandled key '", *k->cur, "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
template < size_t bufsz, size_t align = 128 >
|
||||
|
|
|
@ -61,6 +61,8 @@ namespace llarp
|
|||
parent = p;
|
||||
}
|
||||
|
||||
virtual ~TX(){};
|
||||
|
||||
K target;
|
||||
Context* parent;
|
||||
std::set< Key_t > peersAsked;
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace llarp
|
|||
void
|
||||
Randomize()
|
||||
{
|
||||
if(_data && _sz)
|
||||
if(_sz)
|
||||
randombytes(_data, _sz);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,18 @@ namespace llarp
|
|||
struct in6_addr netmask;
|
||||
PubKey pubkey;
|
||||
|
||||
ExitInfo() : IBEncodeMessage()
|
||||
{
|
||||
}
|
||||
|
||||
ExitInfo(const ExitInfo &other) : IBEncodeMessage()
|
||||
{
|
||||
pubkey = other.pubkey;
|
||||
memcpy(address.s6_addr, other.address.s6_addr, 16);
|
||||
memcpy(netmask.s6_addr, other.netmask.s6_addr, 16);
|
||||
version = other.version;
|
||||
}
|
||||
|
||||
~ExitInfo();
|
||||
|
||||
bool
|
||||
|
|
|
@ -15,7 +15,6 @@ namespace llarp
|
|||
{
|
||||
struct ILinkLayer
|
||||
{
|
||||
ILinkLayer(llarp_router* r);
|
||||
virtual ~ILinkLayer();
|
||||
|
||||
bool
|
||||
|
@ -41,10 +40,7 @@ namespace llarp
|
|||
Configure(llarp_ev_loop* loop, const std::string& ifname, int af,
|
||||
uint16_t port);
|
||||
|
||||
virtual ILinkSession*
|
||||
NewInboundSession(const Addr& from) = 0;
|
||||
|
||||
virtual ILinkSession*
|
||||
virtual std::unique_ptr< ILinkSession >
|
||||
NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) = 0;
|
||||
|
||||
virtual void
|
||||
|
@ -129,7 +125,6 @@ namespace llarp
|
|||
std::make_pair(addr, std::unique_ptr< ILinkSession >(s)));
|
||||
}
|
||||
|
||||
llarp_router* m_router;
|
||||
llarp_logic* m_Logic = nullptr;
|
||||
Addr m_ourAddr;
|
||||
llarp_udp_io m_udp;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <llarp/crypto.hpp>
|
||||
#include <llarp/net.hpp>
|
||||
#include <llarp/router_contact.hpp>
|
||||
#include <functional>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
@ -14,51 +16,34 @@ namespace llarp
|
|||
virtual ~ILinkSession(){};
|
||||
|
||||
/// called every event loop tick
|
||||
virtual void
|
||||
Pump(){};
|
||||
std::function< void(void) > Pump;
|
||||
|
||||
/// called every timer tick
|
||||
virtual void
|
||||
Tick(llarp_time_t now){};
|
||||
std::function< void(llarp_time_t) > Tick;
|
||||
|
||||
/// 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;
|
||||
std::function< bool(llarp_buffer_t) > SendMessageBuffer;
|
||||
|
||||
/// start the connection
|
||||
virtual void
|
||||
Start() = 0;
|
||||
std::function< void(void) > Start;
|
||||
|
||||
/// send a keepalive to the remote endpoint
|
||||
virtual bool
|
||||
SendKeepAlive() = 0;
|
||||
std::function< bool(void) > SendKeepAlive;
|
||||
|
||||
/// send close message
|
||||
virtual void
|
||||
SendClose() = 0;
|
||||
std::function< void(void) > SendClose;
|
||||
|
||||
/// return true if we are established
|
||||
virtual bool
|
||||
IsEstablished() const = 0;
|
||||
std::function< bool(void) > IsEstablished;
|
||||
|
||||
/// return true if this session has timed out
|
||||
virtual bool
|
||||
TimedOut(llarp_time_t now) const
|
||||
{
|
||||
return false;
|
||||
};
|
||||
std::function< bool(llarp_time_t) > TimedOut;
|
||||
|
||||
/// get remote public identity key
|
||||
virtual const PubKey&
|
||||
GetPubKey() const = 0;
|
||||
std::function< const PubKey&(void) > GetPubKey;
|
||||
|
||||
/// get remote address endpoint
|
||||
virtual const Addr&
|
||||
GetRemoteEndpoint() const = 0;
|
||||
/// handle LIM
|
||||
std::function< bool(const LinkIntroMessage*) > HandleLinkIntroMessage;
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
|
|
|
@ -55,6 +55,10 @@ namespace llarp
|
|||
bool
|
||||
MessageDone();
|
||||
|
||||
/// resets internal state
|
||||
void
|
||||
Reset();
|
||||
|
||||
private:
|
||||
RouterID
|
||||
GetCurrentFrom();
|
||||
|
@ -63,7 +67,7 @@ namespace llarp
|
|||
bool firstkey;
|
||||
llarp_router* router;
|
||||
ILinkSession* from = nullptr;
|
||||
ILinkMessage* msg = nullptr;
|
||||
std::unique_ptr< ILinkMessage > msg;
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
|
|
|
@ -14,14 +14,32 @@ namespace llarp
|
|||
{
|
||||
struct RouterContact : public IBEncodeMessage
|
||||
{
|
||||
RouterContact() : IBEncodeMessage()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
RouterContact(const RouterContact &other)
|
||||
: addrs(other.addrs)
|
||||
, enckey(other.enckey)
|
||||
, pubkey(other.pubkey)
|
||||
, exits(other.exits)
|
||||
, signature(other.signature)
|
||||
, nickname(other.nickname)
|
||||
, last_updated(other.last_updated)
|
||||
|
||||
{
|
||||
version = other.version;
|
||||
}
|
||||
|
||||
// advertised addresses
|
||||
std::vector< AddressInfo > addrs;
|
||||
std::vector< AddressInfo > addrs = {};
|
||||
// public encryption public key
|
||||
llarp::PubKey enckey;
|
||||
// public signing public key
|
||||
llarp::PubKey pubkey;
|
||||
// advertised exits
|
||||
std::vector< ExitInfo > exits;
|
||||
std::vector< ExitInfo > exits = {};
|
||||
// signature
|
||||
llarp::Signature signature;
|
||||
/// node nickname, yw kee
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <llarp/bencode.h>
|
||||
#include <llarp/logger.hpp>
|
||||
|
||||
bool
|
||||
bencode_write_bytestring(llarp_buffer_t* buff, const void* data, size_t sz)
|
||||
|
@ -113,10 +114,14 @@ bencode_read_dict(llarp_buffer_t* buff, struct dict_reader* r)
|
|||
return false;
|
||||
}
|
||||
|
||||
if(*r->buffer->cur != 'e') // make sure we're at dictionary end
|
||||
if(*r->buffer->cur != 'e')
|
||||
{
|
||||
llarp::LogWarn("reading dict not ending on 'e'");
|
||||
// make sure we're at dictionary end
|
||||
return false;
|
||||
}
|
||||
r->buffer->cur++;
|
||||
return r->on_key(r, 0);
|
||||
return r->on_key(r, nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#if defined(__MINGW32__) || defined(_MSC_VER) || defined(__sun)
|
||||
namespace fs = std::experimental::filesystem;
|
||||
#else
|
||||
namespace fs = std::filesystem;
|
||||
namespace fs = std::experimental::filesystem;
|
||||
#endif // end win32
|
||||
#else
|
||||
// not CPP17 needs this
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
#include "encoder.hpp"
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
/// encode Link Introduce Message onto a buffer
|
||||
/// if router is nullptr then the LIM's r member is omitted.
|
||||
bool
|
||||
EncodeLIM(llarp_buffer_t* buff, const llarp::RouterContact* router)
|
||||
{
|
||||
if(!bencode_start_dict(buff))
|
||||
return false;
|
||||
|
||||
// message type
|
||||
if(!bencode_write_bytestring(buff, "a", 1))
|
||||
return false;
|
||||
if(!bencode_write_bytestring(buff, "i", 1))
|
||||
return false;
|
||||
|
||||
// router contact
|
||||
if(router)
|
||||
{
|
||||
if(!bencode_write_bytestring(buff, "r", 1))
|
||||
return false;
|
||||
if(!router->BEncode(buff))
|
||||
return false;
|
||||
}
|
||||
|
||||
// version
|
||||
if(!bencode_write_version_entry(buff))
|
||||
return false;
|
||||
|
||||
return bencode_end(buff);
|
||||
}
|
||||
} // namespace llarp
|
|
@ -3,10 +3,6 @@
|
|||
|
||||
namespace llarp
|
||||
{
|
||||
ILinkLayer::ILinkLayer(llarp_router* r) : m_router(r)
|
||||
{
|
||||
}
|
||||
|
||||
ILinkLayer::~ILinkLayer()
|
||||
{
|
||||
}
|
||||
|
@ -88,9 +84,7 @@ namespace llarp
|
|||
auto itr = m_Sessions.find(addr);
|
||||
if(itr == m_Sessions.end())
|
||||
m_Sessions
|
||||
.insert(std::make_pair(
|
||||
addr,
|
||||
std::unique_ptr< ILinkSession >(NewOutboundSession(rc, to))))
|
||||
.insert(std::make_pair(addr, std::move(NewOutboundSession(rc, to))))
|
||||
.first->second->Start();
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <llarp/buffer.hpp>
|
||||
#include <llarp/endian.h>
|
||||
#include <utp.h>
|
||||
#include <cassert>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
@ -17,34 +18,35 @@ namespace llarp
|
|||
constexpr size_t FragmentBodySize =
|
||||
FragmentBufferSize - FragmentOverheadSize;
|
||||
|
||||
#ifdef __int128
|
||||
typedef unsigned __int128 Long_t;
|
||||
#else
|
||||
typedef uint64_t Long_t;
|
||||
#endif
|
||||
|
||||
typedef llarp::AlignedBuffer< FragmentBufferSize, false, Long_t >
|
||||
FragmentBuffer;
|
||||
typedef llarp::AlignedBuffer< MAX_LINK_MSG_SIZE, false, Long_t >
|
||||
MessageBuffer;
|
||||
typedef llarp::AlignedBuffer< FragmentBufferSize > FragmentBuffer;
|
||||
|
||||
struct LinkLayer;
|
||||
|
||||
struct BaseSession : public ILinkSession
|
||||
{
|
||||
llarp_router* router = nullptr;
|
||||
RouterContact remoteRC;
|
||||
utp_socket* sock;
|
||||
LinkLayer* parent;
|
||||
bool gotLIM;
|
||||
PubKey remoteTransportPubKey;
|
||||
Addr remoteAddr;
|
||||
SharedSecret sessionKey;
|
||||
llarp_time_t lastActive;
|
||||
llarp_time_t sessionTimeout = 10 * 1000;
|
||||
const static llarp_time_t sessionTimeout = 10 * 1000;
|
||||
std::queue< FragmentBuffer > sendq;
|
||||
FragmentBuffer recvBuf;
|
||||
size_t recvBufOffset = 0;
|
||||
MessageBuffer recvMsg;
|
||||
size_t recvMsgOffset = 0;
|
||||
size_t recvBufOffset;
|
||||
std::vector< byte_t > recvMsg;
|
||||
|
||||
std::function< void(utp_socket*) > handleLinkEstablish;
|
||||
/// base
|
||||
BaseSession(llarp_router* r);
|
||||
|
||||
/// outbound
|
||||
BaseSession(llarp_router* r, utp_socket* s, const RouterContact& rc,
|
||||
const AddressInfo& addr);
|
||||
|
||||
/// inbound
|
||||
BaseSession(llarp_router* r, utp_socket* s, const Addr& remote);
|
||||
|
||||
enum State
|
||||
{
|
||||
|
@ -56,26 +58,33 @@ namespace llarp
|
|||
eClose // utp connection is closed
|
||||
};
|
||||
|
||||
llarp_router*
|
||||
Router();
|
||||
|
||||
State state;
|
||||
|
||||
void
|
||||
EnterState(State st)
|
||||
OnLinkEstablished(LinkLayer* p)
|
||||
{
|
||||
state = st;
|
||||
lastActive = llarp_time_now_ms();
|
||||
parent = p;
|
||||
EnterState(eLinkEstablished);
|
||||
llarp::LogDebug("link established with ", remoteAddr);
|
||||
}
|
||||
|
||||
void
|
||||
EnterState(State st);
|
||||
|
||||
BaseSession();
|
||||
virtual ~BaseSession();
|
||||
|
||||
void
|
||||
PumpWrite(utp_socket* sock)
|
||||
PumpWrite(utp_socket* s)
|
||||
{
|
||||
// TODO: use utp_writev
|
||||
while(sendq.size())
|
||||
{
|
||||
auto& front = sendq.front();
|
||||
write_ll(sock, front.data(), front.size());
|
||||
write_ll(s, front.data(), front.size());
|
||||
sendq.pop();
|
||||
}
|
||||
}
|
||||
|
@ -93,79 +102,17 @@ namespace llarp
|
|||
}
|
||||
|
||||
bool
|
||||
VerifyThenDecrypt(FragmentBuffer& buf)
|
||||
{
|
||||
ShortHash digest;
|
||||
if(!router->crypto.hmac(
|
||||
digest,
|
||||
InitBuffer(buf.data() + FragmentHashSize,
|
||||
FragmentBufferSize - FragmentHashSize),
|
||||
sessionKey))
|
||||
{
|
||||
llarp::LogError("keyed hash failed");
|
||||
return false;
|
||||
}
|
||||
if(digest != ShortHash(buf.data()))
|
||||
{
|
||||
llarp::LogError("Message Integrity Failed");
|
||||
return false;
|
||||
}
|
||||
AlignedBuffer< FragmentNonceSize > nonce(buf.data() + FragmentHashSize);
|
||||
|
||||
auto body = InitBuffer(buf.data() + FragmentOverheadSize,
|
||||
FragmentBufferSize - FragmentOverheadSize);
|
||||
|
||||
router->crypto.xchacha20(body, sessionKey, nonce);
|
||||
|
||||
uint32_t upper, lower;
|
||||
if(!(llarp_buffer_read_uint32(&body, &upper)
|
||||
&& llarp_buffer_read_uint32(&body, &lower)))
|
||||
return false;
|
||||
bool fragmentEnd = upper == 0;
|
||||
if(lower > recvMsgOffset + recvMsg.size())
|
||||
{
|
||||
llarp::LogError("Fragment too big: ", lower, " bytes");
|
||||
return false;
|
||||
}
|
||||
byte_t* ptr = recvMsg.data() + recvMsgOffset;
|
||||
memcpy(ptr, body.cur, lower);
|
||||
recvMsgOffset += lower;
|
||||
if(fragmentEnd)
|
||||
{
|
||||
// got a message
|
||||
auto msgbuf = InitBuffer(recvMsg.data(), recvMsgOffset);
|
||||
recvMsgOffset = 0;
|
||||
return router->HandleRecvLinkMessageBuffer(this, msgbuf);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
VerifyThenDecrypt(FragmentBuffer& buf);
|
||||
|
||||
void
|
||||
EncryptThenHash(FragmentBuffer& buf, const byte_t* ptr, uint32_t sz,
|
||||
bool isLastFragment)
|
||||
|
||||
{
|
||||
buf.Randomize();
|
||||
const byte_t* nonce = buf.data() + FragmentHashSize;
|
||||
byte_t* body = buf.data() + FragmentOverheadSize;
|
||||
byte_t* base = body;
|
||||
if(isLastFragment)
|
||||
htobe32buf(body, 0);
|
||||
body += sizeof(uint32_t);
|
||||
htobe32buf(body, sz);
|
||||
body += sizeof(uint32_t);
|
||||
memcpy(body, ptr, sz);
|
||||
auto payload = InitBuffer(base, FragmentBodySize);
|
||||
router->crypto.xchacha20(payload, sessionKey, nonce);
|
||||
router->crypto.hmac(buf, payload, sessionKey);
|
||||
}
|
||||
bool isLastFragment);
|
||||
|
||||
bool
|
||||
SendMessageBuffer(llarp_buffer_t buf)
|
||||
QueueWriteBuffers(llarp_buffer_t buf)
|
||||
{
|
||||
if(state != eSessionReady)
|
||||
{
|
||||
llarp::LogError("state is ", state);
|
||||
return false;
|
||||
}
|
||||
size_t sz = buf.sz;
|
||||
|
@ -181,23 +128,77 @@ namespace llarp
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Connect()
|
||||
{
|
||||
utp_connect(sock, remoteAddr, remoteAddr.SockLen());
|
||||
EnterState(eConnecting);
|
||||
}
|
||||
|
||||
void
|
||||
OutboundLinkEstablished(LinkLayer* p)
|
||||
{
|
||||
OnLinkEstablished(p);
|
||||
KeyExchangeNonce nonce;
|
||||
nonce.Randomize();
|
||||
SendHandshake(nonce, sock);
|
||||
gotLIM = true;
|
||||
EnterState(eCryptoHandshake);
|
||||
auto router = Router();
|
||||
if(DoKeyExchange(sock, router->crypto.dh_client, nonce,
|
||||
remoteTransportPubKey, router->encryption))
|
||||
{
|
||||
EnterState(eSessionReady);
|
||||
}
|
||||
}
|
||||
|
||||
// send our RC to the remote
|
||||
void
|
||||
SendHandshake(const KeyExchangeNonce& n, utp_socket* s)
|
||||
{
|
||||
auto buf = InitBuffer(recvBuf.data(), recvBuf.size());
|
||||
// fastforward buffer for handshake to fit before
|
||||
buf.cur += sizeof(uint32_t) * 2;
|
||||
byte_t* begin = buf.cur;
|
||||
LinkIntroMessage msg;
|
||||
msg.rc = Router()->rc;
|
||||
|
||||
msg.N = n;
|
||||
if(!msg.BEncode(&buf))
|
||||
{
|
||||
llarp::LogError("failed to encode our RC for handshake");
|
||||
Close(s);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t sz = buf.cur - begin;
|
||||
llarp::LogDebug("handshake is of size ", sz, " bytes");
|
||||
// write handshake header
|
||||
buf.cur = buf.base;
|
||||
llarp_buffer_put_uint32(&buf, LLARP_PROTO_VERSION);
|
||||
llarp_buffer_put_uint32(&buf, sz);
|
||||
// send it
|
||||
write_ll(s, recvBuf.data(), sz + (sizeof(uint32_t) * 2));
|
||||
sock = s;
|
||||
}
|
||||
|
||||
bool
|
||||
DoKeyExchange(utp_socket* sock, llarp_transport_dh_func dh,
|
||||
DoKeyExchange(utp_socket* s, llarp_transport_dh_func dh,
|
||||
const KeyExchangeNonce& n, const PubKey& other,
|
||||
const SecretKey& secret)
|
||||
{
|
||||
sock = s;
|
||||
if(!dh(sessionKey, other, secret, n))
|
||||
{
|
||||
llarp::LogError("key exchange with ", other, " failed");
|
||||
Close(sock);
|
||||
return false;
|
||||
}
|
||||
EnterState(eSessionReady);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Tick(llarp_time_t now)
|
||||
TickImpl(llarp_time_t now)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -207,36 +208,26 @@ namespace llarp
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
LinkEstablished(utp_socket* s)
|
||||
{
|
||||
if(handleLinkEstablish)
|
||||
handleLinkEstablish(s);
|
||||
}
|
||||
|
||||
void
|
||||
SendClose()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Close(utp_socket* sock)
|
||||
Close(utp_socket* s)
|
||||
{
|
||||
if(state != eClose)
|
||||
{
|
||||
utp_shutdown(sock, SHUT_RDWR);
|
||||
utp_close(sock);
|
||||
utp_set_userdata(sock, nullptr);
|
||||
utp_shutdown(s, SHUT_RDWR);
|
||||
utp_close(s);
|
||||
utp_set_userdata(s, nullptr);
|
||||
}
|
||||
EnterState(eClose);
|
||||
sock = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
IsEstablished() const override
|
||||
{
|
||||
return state == eSessionReady;
|
||||
}
|
||||
void
|
||||
RecvHandshake(const void* buf, size_t bufsz, LinkLayer* p, utp_socket* s);
|
||||
|
||||
bool
|
||||
Recv(const void* buf, size_t sz)
|
||||
|
@ -262,74 +253,8 @@ namespace llarp
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RecvHandshake(const void* buf, size_t sz, ILinkLayer* parent,
|
||||
utp_socket* sock)
|
||||
{
|
||||
if(parent->HasSessionVia(remoteAddr))
|
||||
{
|
||||
Close(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
llarp::LogDebug("recv handshake ", sz, " from ", remoteAddr);
|
||||
if((recvBuf.size() - recvBufOffset) < sz)
|
||||
{
|
||||
llarp::LogDebug("handshake too big");
|
||||
Close(sock);
|
||||
return;
|
||||
}
|
||||
if(sz <= 8)
|
||||
{
|
||||
llarp::LogDebug("handshake too small");
|
||||
Close(sock);
|
||||
return;
|
||||
}
|
||||
memcpy(recvBuf.data(), buf, sz);
|
||||
|
||||
// process handshake header
|
||||
uint8_t* ptr = recvBuf.data();
|
||||
uint32_t version = bufbe32toh(ptr);
|
||||
if(version != LLARP_PROTO_VERSION)
|
||||
{
|
||||
llarp::LogWarn("protocol version missmatch ", version,
|
||||
" != ", LLARP_PROTO_VERSION);
|
||||
return;
|
||||
}
|
||||
ptr += sizeof(uint32_t);
|
||||
uint32_t limsz = bufbe32toh(ptr);
|
||||
ptr += sizeof(uint32_t);
|
||||
if(((sizeof(uint32_t) * 2) + limsz) > sz)
|
||||
{
|
||||
// not enough data
|
||||
// TODO: don't bail here, continue reading
|
||||
Close(sock);
|
||||
return;
|
||||
}
|
||||
LinkIntroMessage msg(this);
|
||||
auto mbuf = InitBuffer(ptr, limsz);
|
||||
if(!msg.BDecode(&mbuf))
|
||||
{
|
||||
llarp::LogError("malfromed LIM from ", remoteAddr);
|
||||
return;
|
||||
}
|
||||
if(!msg.HandleMessage(router))
|
||||
{
|
||||
llarp::LogError("failed to handle LIM from ", remoteAddr);
|
||||
Close(sock);
|
||||
return;
|
||||
}
|
||||
remoteRC = msg.rc;
|
||||
if(!DoKeyExchange(sock, router->crypto.dh_server, msg.N, msg.rc.enckey,
|
||||
parent->TransportSecretKey()))
|
||||
return;
|
||||
llarp::LogInfo("we got a new session from ", remoteRC.pubkey);
|
||||
parent->MapAddr(remoteAddr, remoteRC.pubkey);
|
||||
router->HandleLinkSessionEstablished(remoteRC.pubkey);
|
||||
}
|
||||
|
||||
bool
|
||||
TimedOut(llarp_time_t now) const
|
||||
IsTimedOut(llarp_time_t now) const
|
||||
{
|
||||
if(now < lastActive)
|
||||
return false;
|
||||
|
@ -355,30 +280,9 @@ namespace llarp
|
|||
struct LinkLayer : public ILinkLayer
|
||||
{
|
||||
utp_context* _utp_ctx = nullptr;
|
||||
|
||||
llarp_router* router = nullptr;
|
||||
static uint64
|
||||
OnRead(utp_callback_arguments* arg)
|
||||
{
|
||||
BaseSession* self =
|
||||
static_cast< BaseSession* >(utp_get_userdata(arg->socket));
|
||||
if(self)
|
||||
{
|
||||
if(self->state == BaseSession::eSessionReady)
|
||||
self->Recv(arg->buf, arg->len);
|
||||
else
|
||||
{
|
||||
LinkLayer* parent = static_cast< LinkLayer* >(
|
||||
utp_context_get_userdata(arg->context));
|
||||
self->RecvHandshake(arg->buf, arg->len, parent, arg->socket);
|
||||
}
|
||||
utp_read_drained(arg->socket);
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LogWarn("utp_socket got data with no underlying session");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
OnRead(utp_callback_arguments* arg);
|
||||
|
||||
static uint64
|
||||
SendTo(utp_callback_arguments* arg)
|
||||
|
@ -390,25 +294,20 @@ namespace llarp
|
|||
}
|
||||
|
||||
static uint64
|
||||
OnConnect(utp_callback_arguments* arg)
|
||||
{
|
||||
BaseSession* session =
|
||||
static_cast< BaseSession* >(utp_get_userdata(arg->socket));
|
||||
session->LinkEstablished(arg->socket);
|
||||
return 0;
|
||||
}
|
||||
OnStateChange(utp_callback_arguments*);
|
||||
|
||||
static uint64
|
||||
OnAccept(utp_callback_arguments*);
|
||||
|
||||
LinkLayer(llarp_router* r) : ILinkLayer(r)
|
||||
LinkLayer(llarp_router* r) : ILinkLayer()
|
||||
{
|
||||
m_router = r;
|
||||
router = r;
|
||||
_utp_ctx = utp_init(2);
|
||||
utp_context_set_userdata(_utp_ctx, this);
|
||||
utp_set_callback(_utp_ctx, UTP_SENDTO, &LinkLayer::SendTo);
|
||||
utp_set_callback(_utp_ctx, UTP_ON_ACCEPT, &LinkLayer::OnAccept);
|
||||
utp_set_callback(_utp_ctx, UTP_ON_CONNECT, &LinkLayer::OnConnect);
|
||||
utp_set_callback(_utp_ctx, UTP_ON_STATE_CHANGE,
|
||||
&LinkLayer::OnStateChange);
|
||||
utp_set_callback(_utp_ctx, UTP_ON_READ, &LinkLayer::OnRead);
|
||||
utp_context_set_option(_utp_ctx, UTP_LOG_NORMAL, 1);
|
||||
utp_context_set_option(_utp_ctx, UTP_LOG_MTU, 1);
|
||||
|
@ -444,19 +343,19 @@ namespace llarp
|
|||
{
|
||||
}
|
||||
|
||||
llarp_router*
|
||||
GetRouter();
|
||||
|
||||
bool
|
||||
KeyGen(SecretKey& k)
|
||||
{
|
||||
m_router->crypto.encryption_keygen(k);
|
||||
router->crypto.encryption_keygen(k);
|
||||
return true;
|
||||
}
|
||||
|
||||
ILinkSession*
|
||||
std::unique_ptr< ILinkSession >
|
||||
NewOutboundSession(const RouterContact& rc, const AddressInfo& addr);
|
||||
|
||||
ILinkSession*
|
||||
NewInboundSession(const Addr& addr);
|
||||
|
||||
utp_socket*
|
||||
NewSocket()
|
||||
{
|
||||
|
@ -476,125 +375,108 @@ namespace llarp
|
|||
return std::unique_ptr< LinkLayer >(new LinkLayer(r));
|
||||
}
|
||||
|
||||
struct OutboundSession : public BaseSession
|
||||
{
|
||||
utp_socket* sock;
|
||||
PubKey remoteTransportPubKey;
|
||||
OutboundSession(llarp_router* r, utp_socket* s, const RouterContact& rc,
|
||||
const AddressInfo& addr)
|
||||
: BaseSession()
|
||||
{
|
||||
sock = s;
|
||||
router = r;
|
||||
utp_set_userdata(s, this);
|
||||
remoteRC = rc;
|
||||
remoteAddr = addr;
|
||||
remoteTransportPubKey = addr.pubkey;
|
||||
handleLinkEstablish = [=](utp_socket* usock) {
|
||||
OutboundEstablish(r, usock);
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
OutboundEstablish(llarp_router* r, utp_socket* usock)
|
||||
{
|
||||
sock = usock;
|
||||
llarp::LogDebug("link established with ", remoteAddr);
|
||||
EnterState(eLinkEstablished);
|
||||
KeyExchangeNonce nonce;
|
||||
nonce.Randomize();
|
||||
SendHandshake(nonce, r, usock);
|
||||
EnterState(eCryptoHandshake);
|
||||
if(DoKeyExchange(sock, r->crypto.dh_client, nonce,
|
||||
remoteTransportPubKey, r->encryption))
|
||||
{
|
||||
LinkLayer* parent = static_cast< LinkLayer* >(
|
||||
utp_context_get_userdata(utp_get_context(usock)));
|
||||
parent->MapAddr(remoteAddr, remoteRC.pubkey);
|
||||
r->HandleLinkSessionEstablished(remoteRC.pubkey);
|
||||
}
|
||||
}
|
||||
|
||||
// send our RC to the remote
|
||||
void
|
||||
SendHandshake(const KeyExchangeNonce& n, llarp_router* r, utp_socket* s)
|
||||
{
|
||||
auto buf = InitBuffer(recvBuf.data(), recvBuf.size());
|
||||
// fastforward buffer for handshake to fit before
|
||||
buf.cur += sizeof(uint32_t) * 2;
|
||||
|
||||
LinkIntroMessage msg;
|
||||
msg.rc = r->rc;
|
||||
|
||||
msg.N = n;
|
||||
if(!msg.BEncode(&buf))
|
||||
return;
|
||||
|
||||
uint32_t sz = buf.cur - buf.base;
|
||||
sz -= sizeof(uint32_t) * 2;
|
||||
// write handshake header
|
||||
buf.cur = buf.base;
|
||||
llarp_buffer_put_uint32(&buf, LLARP_PROTO_VERSION);
|
||||
llarp_buffer_put_uint32(&buf, sz);
|
||||
// send it
|
||||
write_ll(s, recvBuf.data(), sz);
|
||||
sock = s;
|
||||
}
|
||||
|
||||
void
|
||||
Start()
|
||||
{
|
||||
utp_connect(sock, remoteAddr, remoteAddr.SockLen());
|
||||
EnterState(eConnecting);
|
||||
}
|
||||
};
|
||||
|
||||
struct InboundSession : public BaseSession
|
||||
{
|
||||
utp_socket* sock;
|
||||
InboundSession(llarp_router* r, utp_socket* s, const Addr& addr)
|
||||
: BaseSession()
|
||||
{
|
||||
sock = s;
|
||||
router = r;
|
||||
utp_set_userdata(sock, this);
|
||||
remoteAddr = addr;
|
||||
handleLinkEstablish = [=](utp_socket* usock) {
|
||||
EnterState(eLinkEstablished);
|
||||
sock = usock;
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
Start()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
BaseSession::BaseSession()
|
||||
BaseSession::BaseSession(llarp_router* r)
|
||||
{
|
||||
recvBufOffset = 0;
|
||||
TimedOut = [&](llarp_time_t now) -> bool {
|
||||
return this->IsTimedOut(now);
|
||||
};
|
||||
lastActive = llarp_time_now_ms();
|
||||
Pump = [&]() { PumpWrite(this->sock); };
|
||||
Tick = std::bind(&BaseSession::TickImpl, this, std::placeholders::_1);
|
||||
SendMessageBuffer = std::bind(&BaseSession::QueueWriteBuffers, this,
|
||||
std::placeholders::_1);
|
||||
IsEstablished = [&]() { return this->state == eSessionReady; };
|
||||
HandleLinkIntroMessage = [](const LinkIntroMessage*) -> bool {
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
BaseSession::BaseSession(llarp_router* r, utp_socket* s,
|
||||
const RouterContact& rc, const AddressInfo& addr)
|
||||
: BaseSession(r)
|
||||
{
|
||||
remoteRC.Clear();
|
||||
remoteTransportPubKey = addr.pubkey;
|
||||
remoteRC = rc;
|
||||
sock = s;
|
||||
assert(utp_set_userdata(sock, this) == this);
|
||||
remoteAddr = addr;
|
||||
Start = std::bind(&BaseSession::Connect, this);
|
||||
}
|
||||
|
||||
BaseSession::BaseSession(llarp_router* r, utp_socket* s, const Addr& addr)
|
||||
: BaseSession(r)
|
||||
{
|
||||
remoteRC.Clear();
|
||||
sock = s;
|
||||
assert(utp_set_userdata(sock, this) == this);
|
||||
remoteAddr = addr;
|
||||
Start = []() {};
|
||||
}
|
||||
|
||||
llarp_router*
|
||||
BaseSession::Router()
|
||||
{
|
||||
return parent->router;
|
||||
}
|
||||
|
||||
BaseSession::~BaseSession()
|
||||
{
|
||||
}
|
||||
|
||||
ILinkSession*
|
||||
std::unique_ptr< ILinkSession >
|
||||
LinkLayer::NewOutboundSession(const RouterContact& rc,
|
||||
const AddressInfo& addr)
|
||||
{
|
||||
auto router = m_router;
|
||||
if(router)
|
||||
return new OutboundSession(router, utp_create_socket(_utp_ctx), rc,
|
||||
addr);
|
||||
return nullptr;
|
||||
return std::make_unique< BaseSession >(
|
||||
router, utp_create_socket(_utp_ctx), rc, addr);
|
||||
}
|
||||
|
||||
ILinkSession*
|
||||
LinkLayer::NewInboundSession(const Addr& addr)
|
||||
uint64
|
||||
LinkLayer::OnRead(utp_callback_arguments* arg)
|
||||
{
|
||||
return nullptr;
|
||||
BaseSession* self =
|
||||
static_cast< BaseSession* >(utp_get_userdata(arg->socket));
|
||||
if(self)
|
||||
{
|
||||
assert(self->sock);
|
||||
assert(self->sock == arg->socket);
|
||||
if(self->state == BaseSession::eSessionReady)
|
||||
self->Recv(arg->buf, arg->len);
|
||||
else if(self->state == BaseSession::eLinkEstablished)
|
||||
{
|
||||
LinkLayer* parent =
|
||||
static_cast< LinkLayer* >(utp_context_get_userdata(arg->context));
|
||||
self->RecvHandshake(arg->buf, arg->len, parent, arg->socket);
|
||||
}
|
||||
utp_read_drained(arg->socket);
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LogWarn("utp_socket got data with no underlying session");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64
|
||||
LinkLayer::OnStateChange(utp_callback_arguments* arg)
|
||||
{
|
||||
LinkLayer* l =
|
||||
static_cast< LinkLayer* >(utp_context_get_userdata(arg->context));
|
||||
BaseSession* session =
|
||||
static_cast< BaseSession* >(utp_get_userdata(arg->socket));
|
||||
if(arg->state == UTP_STATE_CONNECT)
|
||||
{
|
||||
assert(session->sock);
|
||||
assert(session->sock == arg->socket);
|
||||
session->OutboundLinkEstablished(l);
|
||||
}
|
||||
else if(arg->state == UTP_STATE_EOF)
|
||||
{
|
||||
session->SendClose();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64
|
||||
|
@ -614,13 +496,175 @@ namespace llarp
|
|||
utp_close(arg->socket);
|
||||
return 0;
|
||||
}
|
||||
InboundSession* session =
|
||||
new InboundSession(self->m_router, arg->socket, remote);
|
||||
BaseSession* session = new BaseSession(self->router, arg->socket, remote);
|
||||
self->PutSession(remote, session);
|
||||
session->LinkEstablished(arg->socket);
|
||||
session->OnLinkEstablished(self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
BaseSession::EncryptThenHash(FragmentBuffer& buf, const byte_t* ptr,
|
||||
uint32_t sz, bool isLastFragment)
|
||||
|
||||
{
|
||||
buf.Randomize();
|
||||
const byte_t* nonce = buf.data() + FragmentHashSize;
|
||||
byte_t* body = buf.data() + FragmentOverheadSize;
|
||||
byte_t* base = body;
|
||||
if(isLastFragment)
|
||||
htobe32buf(body, 0);
|
||||
body += sizeof(uint32_t);
|
||||
htobe32buf(body, sz);
|
||||
body += sizeof(uint32_t);
|
||||
memcpy(body, ptr, sz);
|
||||
auto payload = InitBuffer(base, FragmentBodySize);
|
||||
parent->router->crypto.xchacha20(payload, sessionKey, nonce);
|
||||
parent->router->crypto.hmac(buf, payload, sessionKey);
|
||||
}
|
||||
|
||||
void
|
||||
BaseSession::EnterState(State st)
|
||||
{
|
||||
state = st;
|
||||
lastActive = llarp_time_now_ms();
|
||||
if(st == eSessionReady)
|
||||
{
|
||||
parent->MapAddr(this->remoteAddr, remoteRC.pubkey);
|
||||
Router()->HandleLinkSessionEstablished(remoteRC);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BaseSession::VerifyThenDecrypt(FragmentBuffer& buf)
|
||||
{
|
||||
ShortHash digest;
|
||||
if(!Router()->crypto.hmac(
|
||||
digest,
|
||||
InitBuffer(buf.data() + FragmentHashSize,
|
||||
FragmentBufferSize - FragmentHashSize),
|
||||
sessionKey))
|
||||
{
|
||||
llarp::LogError("keyed hash failed");
|
||||
return false;
|
||||
}
|
||||
if(digest != ShortHash(buf.data()))
|
||||
{
|
||||
llarp::LogError("Message Integrity Failed");
|
||||
return false;
|
||||
}
|
||||
AlignedBuffer< FragmentNonceSize > nonce(buf.data() + FragmentHashSize);
|
||||
|
||||
auto body = InitBuffer(buf.data() + FragmentOverheadSize,
|
||||
FragmentBufferSize - FragmentOverheadSize);
|
||||
|
||||
Router()->crypto.xchacha20(body, sessionKey, nonce);
|
||||
|
||||
uint32_t upper, lower;
|
||||
if(!(llarp_buffer_read_uint32(&body, &upper)
|
||||
&& llarp_buffer_read_uint32(&body, &lower)))
|
||||
return false;
|
||||
bool fragmentEnd = upper == 0;
|
||||
if(recvMsg.size() + lower > MAX_LINK_MSG_SIZE)
|
||||
{
|
||||
llarp::LogError("Fragment too big: ", lower, " bytes");
|
||||
return false;
|
||||
}
|
||||
size_t newsz = recvMsg.size() + lower;
|
||||
recvMsg.reserve(newsz);
|
||||
byte_t* ptr = recvMsg.data() + (newsz - lower);
|
||||
memcpy(ptr, body.cur, lower);
|
||||
if(fragmentEnd)
|
||||
{
|
||||
// got a message
|
||||
auto mbuf = Buffer(recvMsg);
|
||||
auto result = Router()->HandleRecvLinkMessageBuffer(this, mbuf);
|
||||
recvMsg.clear();
|
||||
recvMsg.shrink_to_fit();
|
||||
return result;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BaseSession::RecvHandshake(const void* buf, size_t bufsz, LinkLayer* p,
|
||||
utp_socket* s)
|
||||
{
|
||||
size_t sz = bufsz;
|
||||
parent = p;
|
||||
sock = s;
|
||||
if(parent->HasSessionVia(remoteAddr))
|
||||
{
|
||||
llarp::LogDebug("already have session via ", remoteAddr,
|
||||
" so closing before processing handshake");
|
||||
Close(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
llarp::LogDebug("recv handshake ", sz, " from ", remoteAddr);
|
||||
if(recvBuf.size() < sz)
|
||||
{
|
||||
llarp::LogDebug("handshake too big from ", remoteAddr);
|
||||
Close(sock);
|
||||
return;
|
||||
}
|
||||
if(sz <= 8)
|
||||
{
|
||||
llarp::LogDebug("handshake too small from ", remoteAddr);
|
||||
Close(sock);
|
||||
return;
|
||||
}
|
||||
memcpy(recvBuf.data(), buf, sz);
|
||||
|
||||
// process handshake header
|
||||
uint8_t* ptr = recvBuf.data();
|
||||
uint32_t version = bufbe32toh(ptr);
|
||||
if(version != LLARP_PROTO_VERSION)
|
||||
{
|
||||
llarp::LogWarn("protocol version missmatch ", version,
|
||||
" != ", LLARP_PROTO_VERSION);
|
||||
Close(sock);
|
||||
return;
|
||||
}
|
||||
ptr += sizeof(uint32_t);
|
||||
sz -= sizeof(uint32_t);
|
||||
uint32_t limsz = bufbe32toh(ptr);
|
||||
ptr += sizeof(uint32_t);
|
||||
sz -= sizeof(uint32_t);
|
||||
if(limsz > sz)
|
||||
{
|
||||
// not enough data
|
||||
// TODO: don't bail here, continue reading
|
||||
llarp::LogDebug("not enough data for handshake, want ", limsz,
|
||||
" bytes but got ", sz);
|
||||
Close(sock);
|
||||
return;
|
||||
}
|
||||
llarp::LogInfo("read LIM from ", remoteAddr);
|
||||
|
||||
// process LIM
|
||||
auto mbuf = InitBuffer(ptr, limsz);
|
||||
LinkIntroMessage msg(this);
|
||||
if(!msg.BDecode(&mbuf))
|
||||
{
|
||||
llarp::LogError("Failed to parse LIM from ", remoteAddr);
|
||||
llarp::DumpBuffer(mbuf);
|
||||
Close(sock);
|
||||
return;
|
||||
}
|
||||
if(!msg.HandleMessage(Router()))
|
||||
{
|
||||
llarp::LogError("failed to verify signature of rc");
|
||||
return;
|
||||
}
|
||||
if(!DoKeyExchange(sock, Router()->crypto.dh_server, msg.N, msg.rc.enckey,
|
||||
parent->TransportSecretKey()))
|
||||
return;
|
||||
remoteRC = msg.rc;
|
||||
gotLIM = true;
|
||||
llarp::LogInfo("we got a new session from ", GetPubKey());
|
||||
EnterState(eSessionReady);
|
||||
}
|
||||
|
||||
} // namespace utp
|
||||
|
||||
} // namespace llarp
|
||||
|
|
|
@ -22,9 +22,20 @@ namespace llarp
|
|||
return false;
|
||||
return *strbuf.cur == 'i';
|
||||
}
|
||||
if(llarp_buffer_eq(key, "n"))
|
||||
{
|
||||
if(N.BDecode(buf))
|
||||
return true;
|
||||
llarp::LogWarn("failed to decode nonce in LIM");
|
||||
return false;
|
||||
}
|
||||
if(llarp_buffer_eq(key, "r"))
|
||||
{
|
||||
return rc.BDecode(buf);
|
||||
if(rc.BDecode(buf))
|
||||
return true;
|
||||
llarp::LogWarn("failed to decode RC in LIM");
|
||||
llarp::DumpBuffer(*buf);
|
||||
return false;
|
||||
}
|
||||
else if(llarp_buffer_eq(key, "v"))
|
||||
{
|
||||
|
@ -76,9 +87,6 @@ namespace llarp
|
|||
bool
|
||||
LinkIntroMessage::HandleMessage(llarp_router* router) const
|
||||
{
|
||||
if(!rc.VerifySignature(&router->crypto))
|
||||
return false;
|
||||
router->async_verify_RC(rc, !rc.IsPublicRouter());
|
||||
return true;
|
||||
return rc.VerifySignature(&router->crypto);
|
||||
}
|
||||
} // namespace llarp
|
||||
|
|
|
@ -9,8 +9,6 @@ namespace llarp
|
|||
InboundMessageParser::InboundMessageParser(llarp_router* _router)
|
||||
: router(_router)
|
||||
{
|
||||
reader.user = this;
|
||||
reader.on_key = &OnKey;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -18,11 +16,11 @@ namespace llarp
|
|||
{
|
||||
InboundMessageParser* handler =
|
||||
static_cast< InboundMessageParser* >(r->user);
|
||||
llarp_buffer_t strbuf;
|
||||
|
||||
// we are reading the first key
|
||||
if(handler->firstkey)
|
||||
{
|
||||
llarp_buffer_t strbuf;
|
||||
// check for empty dict
|
||||
if(!key)
|
||||
return false;
|
||||
|
@ -49,25 +47,27 @@ namespace llarp
|
|||
switch(*strbuf.cur)
|
||||
{
|
||||
case 'i':
|
||||
handler->msg = new LinkIntroMessage(handler->from);
|
||||
handler->msg = std::make_unique< LinkIntroMessage >(handler->from);
|
||||
break;
|
||||
case 'd':
|
||||
handler->msg = new RelayDownstreamMessage(handler->from);
|
||||
handler->msg =
|
||||
std::make_unique< RelayDownstreamMessage >(handler->from);
|
||||
break;
|
||||
case 'u':
|
||||
handler->msg = new RelayUpstreamMessage(handler->from);
|
||||
handler->msg =
|
||||
std::make_unique< RelayUpstreamMessage >(handler->from);
|
||||
break;
|
||||
case 'm':
|
||||
handler->msg = new DHTImmeidateMessage(handler->from);
|
||||
handler->msg = std::make_unique< DHTImmeidateMessage >(handler->from);
|
||||
break;
|
||||
case 'c':
|
||||
handler->msg = new LR_CommitMessage(handler->from);
|
||||
handler->msg = std::make_unique< LR_CommitMessage >(handler->from);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
handler->firstkey = false;
|
||||
return handler->msg != nullptr;
|
||||
return true;
|
||||
}
|
||||
// check for last element
|
||||
if(!key)
|
||||
|
@ -83,8 +83,6 @@ namespace llarp
|
|||
if(msg)
|
||||
{
|
||||
result = msg->HandleMessage(router);
|
||||
delete msg;
|
||||
msg = nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -92,8 +90,16 @@ namespace llarp
|
|||
bool
|
||||
InboundMessageParser::ProcessFrom(ILinkSession* src, llarp_buffer_t buf)
|
||||
{
|
||||
from = src;
|
||||
firstkey = true;
|
||||
reader.user = this;
|
||||
reader.on_key = &OnKey;
|
||||
from = src;
|
||||
firstkey = true;
|
||||
return bencode_read_dict(&buf, &reader);
|
||||
}
|
||||
|
||||
void
|
||||
InboundMessageParser::Reset()
|
||||
{
|
||||
msg.reset(nullptr);
|
||||
}
|
||||
} // namespace llarp
|
||||
|
|
|
@ -218,10 +218,10 @@ crypto_threadworker_verifyrc(void *user)
|
|||
{
|
||||
llarp_async_verify_rc *verify_request =
|
||||
static_cast< llarp_async_verify_rc * >(user);
|
||||
verify_request->valid =
|
||||
verify_request->rc.VerifySignature(verify_request->nodedb->crypto);
|
||||
llarp::RouterContact rc = verify_request->rc;
|
||||
verify_request->valid = rc.VerifySignature(verify_request->nodedb->crypto);
|
||||
// if it's valid we need to set it
|
||||
if(verify_request->valid && verify_request->rc.IsPublicRouter())
|
||||
if(verify_request->valid && rc.IsPublicRouter())
|
||||
{
|
||||
llarp::LogDebug("RC is valid, saving to disk");
|
||||
llarp_threadpool_queue_job(verify_request->diskworker,
|
||||
|
|
|
@ -322,8 +322,9 @@ namespace llarp
|
|||
{
|
||||
}
|
||||
|
||||
Path::Path(const std::vector< RouterContact >& h) : hops(h.size())
|
||||
Path::Path(const std::vector< RouterContact >& h)
|
||||
{
|
||||
hops.resize(h.size());
|
||||
size_t hsz = h.size();
|
||||
for(size_t idx = 0; idx < hsz; ++idx)
|
||||
{
|
||||
|
|
|
@ -198,8 +198,7 @@ namespace llarp
|
|||
{
|
||||
// select hops
|
||||
std::vector< RouterContact > hops;
|
||||
for(size_t i = 0; i < numHops; ++i)
|
||||
hops.emplace_back();
|
||||
hops.resize(numHops);
|
||||
size_t idx = 0;
|
||||
while(idx < numHops)
|
||||
{
|
||||
|
|
|
@ -21,19 +21,20 @@ namespace llarp
|
|||
struct async_verify_context
|
||||
{
|
||||
llarp_router *router;
|
||||
llarp::OutboundLinkEstablishJob *establish_job;
|
||||
TryConnectJob *establish_job;
|
||||
};
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
struct TryConnectJob : public llarp::OutboundLinkEstablishJob
|
||||
struct TryConnectJob
|
||||
{
|
||||
llarp::RouterContact rc;
|
||||
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)
|
||||
: rc(remote), link(l), router(r), triesLeft(tries)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -80,8 +81,7 @@ struct TryConnectJob : public llarp::OutboundLinkEstablishJob
|
|||
static void
|
||||
on_try_connecting(void *u)
|
||||
{
|
||||
llarp::OutboundLinkEstablishJob *j =
|
||||
static_cast< llarp::OutboundLinkEstablishJob * >(u);
|
||||
TryConnectJob *j = static_cast< TryConnectJob * >(u);
|
||||
j->Attempt();
|
||||
}
|
||||
|
||||
|
@ -97,27 +97,20 @@ llarp_router_try_connect(struct llarp_router *router,
|
|||
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.get();
|
||||
auto link = router->outboundLink.get();
|
||||
auto itr = router->pendingEstablishJobs.insert(std::make_pair(
|
||||
remote.pubkey,
|
||||
std::make_unique< TryConnectJob >(remote, link, numretries, router)));
|
||||
TryConnectJob *job = itr.first->second.get();
|
||||
// try establishing async
|
||||
llarp_logic_queue_job(router->logic, {job, on_try_connecting});
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_router::HandleLinkSessionEstablished(llarp::RouterID k)
|
||||
llarp_router::HandleLinkSessionEstablished(const llarp::RouterContact &rc)
|
||||
{
|
||||
auto itr = pendingEstablishJobs.find(k);
|
||||
if(itr != pendingEstablishJobs.end())
|
||||
{
|
||||
itr->second->Success();
|
||||
}
|
||||
else
|
||||
{
|
||||
FlushOutboundFor(k);
|
||||
}
|
||||
async_verify_RC(rc);
|
||||
}
|
||||
|
||||
llarp_router::llarp_router()
|
||||
|
@ -341,8 +334,11 @@ llarp_router::on_verify_server_rc(llarp_async_verify_rc *job)
|
|||
|
||||
llarp::LogDebug("rc verified and saved to nodedb");
|
||||
|
||||
// refresh valid routers RC value if it's there
|
||||
router->validRouters[pk] = job->rc;
|
||||
if(router->validRouters.count(pk))
|
||||
{
|
||||
router->validRouters.erase(pk);
|
||||
}
|
||||
router->validRouters.insert(std::make_pair(pk, job->rc));
|
||||
|
||||
// track valid router in dht
|
||||
router->dht->impl.nodes->PutNode(job->rc);
|
||||
|
@ -391,7 +387,7 @@ llarp_router::HandleDHTLookupForTryEstablishTo(
|
|||
const std::vector< llarp::RouterContact > &results)
|
||||
{
|
||||
for(const auto &result : results)
|
||||
async_verify_RC(result, false);
|
||||
async_verify_RC(result);
|
||||
}
|
||||
|
||||
size_t
|
||||
|
@ -568,18 +564,21 @@ llarp_router::GetRandomConnectedRouter(llarp::RouterContact &result) const
|
|||
}
|
||||
|
||||
void
|
||||
llarp_router::async_verify_RC(const llarp::RouterContact &rc,
|
||||
bool isExpectingClient,
|
||||
llarp::OutboundLinkEstablishJob *establish_job)
|
||||
llarp_router::async_verify_RC(const llarp::RouterContact &rc)
|
||||
{
|
||||
llarp_async_verify_rc *job = new llarp_async_verify_rc();
|
||||
llarp::async_verify_context *ctx = new llarp::async_verify_context();
|
||||
ctx->router = this;
|
||||
ctx->establish_job = establish_job;
|
||||
job->user = ctx;
|
||||
job->rc = rc;
|
||||
job->valid = false;
|
||||
job->hook = nullptr;
|
||||
ctx->establish_job = nullptr;
|
||||
|
||||
auto itr = pendingEstablishJobs.find(rc.pubkey);
|
||||
if(itr != pendingEstablishJobs.end())
|
||||
ctx->establish_job = itr->second.get();
|
||||
|
||||
job->user = ctx;
|
||||
job->rc = rc;
|
||||
job->valid = false;
|
||||
job->hook = nullptr;
|
||||
|
||||
job->nodedb = nodedb;
|
||||
job->logic = logic;
|
||||
|
@ -587,10 +586,10 @@ llarp_router::async_verify_RC(const llarp::RouterContact &rc,
|
|||
job->cryptoworker = tp;
|
||||
job->diskworker = disk;
|
||||
|
||||
if(isExpectingClient)
|
||||
job->hook = &llarp_router::on_verify_client_rc;
|
||||
else
|
||||
if(rc.IsPublicRouter())
|
||||
job->hook = &llarp_router::on_verify_server_rc;
|
||||
else
|
||||
job->hook = &llarp_router::on_verify_client_rc;
|
||||
llarp_nodedb_async_verify(job);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ bool
|
|||
llarp_findOrCreateEncryption(llarp_crypto *crypto, const char *fpath,
|
||||
llarp::SecretKey &encryption);
|
||||
|
||||
struct TryConnectJob;
|
||||
|
||||
struct llarp_router
|
||||
{
|
||||
bool ready;
|
||||
|
@ -95,8 +97,7 @@ struct llarp_router
|
|||
validRouters;
|
||||
|
||||
// pending establishing session with routers
|
||||
std::unordered_map< llarp::RouterID,
|
||||
std::unique_ptr< llarp::OutboundLinkEstablishJob >,
|
||||
std::unordered_map< llarp::RouterID, std::unique_ptr< TryConnectJob >,
|
||||
llarp::RouterID::Hash >
|
||||
pendingEstablishJobs;
|
||||
|
||||
|
@ -107,7 +108,8 @@ struct llarp_router
|
|||
llarp_router();
|
||||
virtual ~llarp_router();
|
||||
|
||||
void HandleLinkSessionEstablished(llarp::PubKey);
|
||||
void
|
||||
HandleLinkSessionEstablished(const llarp::RouterContact &);
|
||||
|
||||
bool
|
||||
HandleRecvLinkMessageBuffer(llarp::ILinkSession *from, llarp_buffer_t msg);
|
||||
|
@ -217,8 +219,7 @@ struct llarp_router
|
|||
GetRandomConnectedRouter(llarp::RouterContact &result) const;
|
||||
|
||||
void
|
||||
async_verify_RC(const llarp::RouterContact &rc, bool isExpectingClient,
|
||||
llarp::OutboundLinkEstablishJob *job = nullptr);
|
||||
async_verify_RC(const llarp::RouterContact &rc);
|
||||
|
||||
void
|
||||
HandleDHTLookupForSendTo(llarp::RouterID remote,
|
||||
|
|
|
@ -223,9 +223,13 @@ namespace llarp
|
|||
RouterContact &
|
||||
RouterContact::operator=(const RouterContact &other)
|
||||
{
|
||||
addrs = other.addrs;
|
||||
signature = other.signature;
|
||||
exits = other.exits;
|
||||
addrs.clear();
|
||||
exits.clear();
|
||||
addrs = other.addrs;
|
||||
exits = other.exits;
|
||||
|
||||
signature = other.signature;
|
||||
|
||||
last_updated = other.last_updated;
|
||||
enckey = other.enckey;
|
||||
pubkey = other.pubkey;
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
// win32 needs experimental
|
||||
#include <experimental/filesystem>
|
||||
#else
|
||||
#include <filesystem>
|
||||
#include <experimental/filesystem>
|
||||
#endif
|
||||
#else
|
||||
// OpenBSD needs this
|
||||
|
|
Loading…
Reference in New Issue