mirror of https://github.com/oxen-io/lokinet
session renegotiation, RC expiration, more utp unit tests, network isolation.
This commit is contained in:
parent
22c9a0c814
commit
cca19290de
|
@ -135,7 +135,7 @@ router's full identity
|
|||
|
||||
{
|
||||
a: [ one, or, many, AI, here ... ],
|
||||
i: "<max 16 bytes network identifier>",
|
||||
i: "<max 8 bytes network identifier>",
|
||||
k: "<32 bytes public long term identity signing key>",
|
||||
n: "<optional max 32 bytes router nickname>",
|
||||
p: "<32 bytes public path encryption key>",
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace llarp
|
|||
{
|
||||
if(!item.BDecode(buf))
|
||||
{
|
||||
llarp::LogWarnTag("llarp/BEncode.hpp", "failed to decode key ", k,
|
||||
llarp::LogWarnTag("llarp/bencode.hpp", "failed to decode key ", k,
|
||||
" for entry in dict");
|
||||
|
||||
return false;
|
||||
|
@ -261,7 +261,9 @@ namespace llarp
|
|||
return true;
|
||||
if(DecodeKey(*k, val))
|
||||
return true;
|
||||
llarp::LogError("unhandled key '", *k->cur, "'");
|
||||
llarp::LogWarnTag("llarp/bencode.hpp", "undefined key '", *k->cur,
|
||||
"' for entry in dict");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace llarp
|
|||
{
|
||||
crypto = std::unique_ptr< llarp::Crypto >(
|
||||
new llarp::Crypto{llarp::Crypto::sodium{}});
|
||||
nodedb = new llarp_nodedb(crypto.get());
|
||||
nodedb = new llarp_nodedb(crypto.get(), router->disk);
|
||||
|
||||
if(!llarp_nodedb::ensure_dir(nodedb_dir.c_str()))
|
||||
{
|
||||
|
@ -129,8 +129,6 @@ namespace llarp
|
|||
{
|
||||
llarp::LogInfo(LLARP_VERSION, " ", LLARP_RELEASE_MOTTO);
|
||||
llarp::LogInfo("starting up");
|
||||
if(!this->LoadDatabase())
|
||||
return -1;
|
||||
llarp_ev_loop_alloc(&mainloop);
|
||||
|
||||
// ensure worker thread pool
|
||||
|
@ -150,7 +148,9 @@ namespace llarp
|
|||
logic = new Logic;
|
||||
|
||||
router = new Router(worker, mainloop, logic);
|
||||
|
||||
// must be done after router is made so we can use its disk io worker
|
||||
if(!this->LoadDatabase())
|
||||
return 1;
|
||||
if(!router->Configure(config))
|
||||
{
|
||||
llarp::LogError("Failed to configure router");
|
||||
|
|
|
@ -700,7 +700,7 @@ namespace llarp
|
|||
bool
|
||||
Validate(const RouterContact &rc) const override
|
||||
{
|
||||
if(!rc.Verify(parent->Crypto()))
|
||||
if(!rc.Verify(parent->Crypto(), parent->Now()))
|
||||
{
|
||||
llarp::LogWarn("rc from lookup result is invalid");
|
||||
return false;
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace llarp
|
|||
ILinkLayer::ILinkLayer(const byte_t* routerEncSecret, GetRCFunc getrc,
|
||||
LinkMessageHandler handler, SignBufferFunc signbuf,
|
||||
SessionEstablishedHandler establishedSession,
|
||||
SessionRenegotiateHandler reneg,
|
||||
TimeoutHandler timeout, SessionClosedHandler closed)
|
||||
: HandleMessage(handler)
|
||||
, HandleTimeout(timeout)
|
||||
|
@ -13,6 +14,7 @@ namespace llarp
|
|||
, GetOurRC(getrc)
|
||||
, SessionEstablished(establishedSession)
|
||||
, SessionClosed(closed)
|
||||
, SessionRenegotiate(reneg)
|
||||
, m_RouterEncSecret(routerEncSecret)
|
||||
{
|
||||
}
|
||||
|
@ -40,6 +42,29 @@ namespace llarp
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ILinkLayer::VisitSessionByPubkey(const byte_t* pk,
|
||||
std::function< bool(ILinkSession*) > visit)
|
||||
{
|
||||
auto itr = m_AuthedLinks.find(pk);
|
||||
if(itr != m_AuthedLinks.end())
|
||||
{
|
||||
return visit(itr->second.get());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ILinkLayer::ForEachSession(std::function< void(ILinkSession*) > visit)
|
||||
{
|
||||
auto itr = m_AuthedLinks.begin();
|
||||
while(itr != m_AuthedLinks.end())
|
||||
{
|
||||
visit(itr->second.get());
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ILinkLayer::Configure(llarp_ev_loop* loop, const std::string& ifname, int af,
|
||||
uint16_t port)
|
||||
|
|
|
@ -30,6 +30,13 @@ namespace llarp
|
|||
/// handler of session established
|
||||
using SessionEstablishedHandler = std::function< void(llarp::RouterContact) >;
|
||||
|
||||
/// f(new, old)
|
||||
/// handler of session renegotiation
|
||||
/// returns true if the new rc is valid
|
||||
/// returns false otherwise and the session is terminated
|
||||
using SessionRenegotiateHandler =
|
||||
std::function< bool(llarp::RouterContact, llarp::RouterContact) >;
|
||||
|
||||
/// handles close of all sessions with pubkey
|
||||
using SessionClosedHandler = std::function< void(llarp::RouterID) >;
|
||||
|
||||
|
@ -38,7 +45,8 @@ namespace llarp
|
|||
ILinkLayer(const byte_t* routerEncSecret, GetRCFunc getrc,
|
||||
LinkMessageHandler handler, SignBufferFunc signFunc,
|
||||
SessionEstablishedHandler sessionEstablish,
|
||||
TimeoutHandler timeout, SessionClosedHandler closed);
|
||||
SessionRenegotiateHandler renegotiate, TimeoutHandler timeout,
|
||||
SessionClosedHandler closed);
|
||||
virtual ~ILinkLayer();
|
||||
|
||||
/// get current time via event loop
|
||||
|
@ -57,6 +65,9 @@ namespace llarp
|
|||
void
|
||||
ForEachSession(std::function< void(const ILinkSession*) > visit) const;
|
||||
|
||||
void
|
||||
ForEachSession(std::function< void(ILinkSession*) > visit);
|
||||
|
||||
static void
|
||||
udp_tick(llarp_udp_io* udp)
|
||||
{
|
||||
|
@ -116,6 +127,10 @@ namespace llarp
|
|||
bool
|
||||
GetOurAddressInfo(AddressInfo& addr) const;
|
||||
|
||||
bool
|
||||
VisitSessionByPubkey(const byte_t* pk,
|
||||
std::function< bool(ILinkSession*) > visit);
|
||||
|
||||
virtual uint16_t
|
||||
Rank() const = 0;
|
||||
|
||||
|
@ -153,6 +168,7 @@ namespace llarp
|
|||
GetRCFunc GetOurRC;
|
||||
SessionEstablishedHandler SessionEstablished;
|
||||
SessionClosedHandler SessionClosed;
|
||||
SessionRenegotiateHandler SessionRenegotiate;
|
||||
|
||||
private:
|
||||
static void
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace llarp
|
|||
std::function< const byte_t *(void) > GetPubKey;
|
||||
|
||||
/// get remote address
|
||||
std::function< const Addr &(void) > GetRemoteEndpoint;
|
||||
std::function< Addr(void) > GetRemoteEndpoint;
|
||||
|
||||
// get remote rc
|
||||
std::function< llarp::RouterContact(void) > GetRemoteRC;
|
||||
|
@ -58,6 +58,9 @@ namespace llarp
|
|||
|
||||
/// get parent link layer
|
||||
std::function< ILinkLayer *(void) > GetLinkLayer;
|
||||
|
||||
/// renegotiate session when we have a new RC locally
|
||||
std::function< bool(void) > RenegotiateSession;
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
|
|
|
@ -233,8 +233,8 @@ namespace llarp
|
|||
return remoteRC.pubkey;
|
||||
}
|
||||
|
||||
const Addr&
|
||||
Session::RemoteEndpoint() const
|
||||
Addr
|
||||
Session::RemoteEndpoint()
|
||||
{
|
||||
return remoteAddr;
|
||||
}
|
||||
|
@ -346,10 +346,11 @@ namespace llarp
|
|||
llarp::GetRCFunc getrc, llarp::LinkMessageHandler h,
|
||||
llarp::SignBufferFunc sign,
|
||||
llarp::SessionEstablishedHandler established,
|
||||
llarp::SessionRenegotiateHandler reneg,
|
||||
llarp::TimeoutHandler timeout,
|
||||
llarp::SessionClosedHandler closed)
|
||||
: ILinkLayer(routerEncSecret, getrc, h, sign, established, timeout,
|
||||
closed)
|
||||
: ILinkLayer(routerEncSecret, getrc, h, sign, established, reneg,
|
||||
timeout, closed)
|
||||
{
|
||||
_crypto = crypto;
|
||||
_utp_ctx = utp_init(2);
|
||||
|
@ -494,6 +495,7 @@ namespace llarp
|
|||
void
|
||||
LinkLayer::Stop()
|
||||
{
|
||||
ForEachSession([](ILinkSession* s) { s->SendClose(); });
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -525,11 +527,14 @@ namespace llarp
|
|||
std::unique_ptr< ILinkLayer >
|
||||
NewServer(llarp::Crypto* crypto, const byte_t* routerEncSecret,
|
||||
llarp::GetRCFunc getrc, llarp::LinkMessageHandler h,
|
||||
llarp::SignBufferFunc sign, llarp::SessionEstablishedHandler est,
|
||||
llarp::TimeoutHandler timeout, llarp::SessionClosedHandler closed)
|
||||
llarp::SessionEstablishedHandler est,
|
||||
llarp::SessionRenegotiateHandler reneg,
|
||||
llarp::SignBufferFunc sign, llarp::TimeoutHandler timeout,
|
||||
llarp::SessionClosedHandler closed)
|
||||
{
|
||||
return std::unique_ptr< ILinkLayer >(new LinkLayer(
|
||||
crypto, routerEncSecret, getrc, h, sign, est, timeout, closed));
|
||||
return std::unique_ptr< ILinkLayer >(
|
||||
new LinkLayer(crypto, routerEncSecret, getrc, h, sign, est, reneg,
|
||||
timeout, closed));
|
||||
}
|
||||
|
||||
std::unique_ptr< ILinkLayer >
|
||||
|
@ -539,10 +544,12 @@ namespace llarp
|
|||
&r->crypto, r->encryption, std::bind(&llarp::Router::rc, r),
|
||||
std::bind(&llarp::Router::HandleRecvLinkMessageBuffer, r,
|
||||
std::placeholders::_1, std::placeholders::_2),
|
||||
std::bind(&llarp::Router::Sign, r, std::placeholders::_1,
|
||||
std::placeholders::_2),
|
||||
std::bind(&llarp::Router::OnSessionEstablished, r,
|
||||
std::placeholders::_1),
|
||||
std::bind(&llarp::Router::CheckRenegotiateValid, r,
|
||||
std::placeholders::_1, std::placeholders::_2),
|
||||
std::bind(&llarp::Router::Sign, r, std::placeholders::_1,
|
||||
std::placeholders::_2),
|
||||
std::bind(&llarp::Router::OnConnectTimeout, r, std::placeholders::_1),
|
||||
std::bind(&llarp::Router::SessionClosed, r, std::placeholders::_1));
|
||||
}
|
||||
|
@ -594,8 +601,9 @@ namespace llarp
|
|||
return this->state == eSessionReady || this->state == eLinkEstablished;
|
||||
};
|
||||
|
||||
SendClose = std::bind(&Session::Close, this);
|
||||
GetRemoteEndpoint = std::bind(&Session::RemoteEndpoint, this);
|
||||
SendClose = std::bind(&Session::Close, this);
|
||||
GetRemoteEndpoint = std::bind(&Session::RemoteEndpoint, this);
|
||||
RenegotiateSession = std::bind(&Session::Rehandshake, this);
|
||||
}
|
||||
|
||||
/// outbound session
|
||||
|
@ -660,7 +668,7 @@ namespace llarp
|
|||
auto buf = StackBuffer< decltype(tmp) >(tmp);
|
||||
LinkIntroMessage replymsg;
|
||||
replymsg.rc = parent->GetOurRC();
|
||||
if(!replymsg.rc.Verify(Crypto()))
|
||||
if(!replymsg.rc.Verify(Crypto(), parent->Now()))
|
||||
{
|
||||
llarp::LogError("our RC is invalid? closing session to", remoteAddr);
|
||||
Close();
|
||||
|
@ -754,7 +762,7 @@ namespace llarp
|
|||
// build our RC
|
||||
LinkIntroMessage msg;
|
||||
msg.rc = parent->GetOurRC();
|
||||
if(!msg.rc.Verify(Crypto()))
|
||||
if(!msg.rc.Verify(Crypto(), parent->Now()))
|
||||
{
|
||||
llarp::LogError("our RC is invalid? closing session to", remoteAddr);
|
||||
Close();
|
||||
|
@ -926,9 +934,7 @@ namespace llarp
|
|||
// key'd hash
|
||||
if(!Crypto()->hmac(buf.data(), payload, txKey))
|
||||
return false;
|
||||
if(msgid)
|
||||
return MutateKey(txKey, A);
|
||||
return true;
|
||||
return MutateKey(txKey, A);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -940,9 +946,53 @@ namespace llarp
|
|||
{
|
||||
parent->MapAddr(remoteRC.pubkey.data(), this);
|
||||
parent->SessionEstablished(remoteRC);
|
||||
/// future LIM are used for session renegotiation
|
||||
GotLIM = std::bind(&Session::GotSessionRenegotiate, this,
|
||||
std::placeholders::_1);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Session::GotSessionRenegotiate(const LinkIntroMessage* msg)
|
||||
{
|
||||
// check with parent and possibly process and store new rc
|
||||
if(!parent->SessionRenegotiate(msg->rc, remoteRC))
|
||||
{
|
||||
// failed to renegotiate
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
// set remote rc
|
||||
remoteRC = msg->rc;
|
||||
// recalcuate rx key
|
||||
return DoKeyExchange(Crypto()->transport_dh_server, rxKey, msg->N,
|
||||
remoteRC.enckey, parent->RouterEncryptionSecret());
|
||||
}
|
||||
|
||||
bool
|
||||
Session::Rehandshake()
|
||||
{
|
||||
byte_t tmp[LinkIntroMessage::MaxSize];
|
||||
LinkIntroMessage lim;
|
||||
lim.rc = parent->GetOurRC();
|
||||
lim.N.Randomize();
|
||||
lim.P = 60 * 1000 * 10;
|
||||
if(!lim.Sign(parent->Sign))
|
||||
return false;
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
if(!lim.BEncode(&buf))
|
||||
return false;
|
||||
// rewind and resize buffer
|
||||
buf.sz = buf.cur - buf.base;
|
||||
buf.cur = buf.base;
|
||||
// send message
|
||||
if(!SendMessageBuffer(buf))
|
||||
return false;
|
||||
// regen our tx Key
|
||||
return DoKeyExchange(Crypto()->transport_dh_client, txKey, lim.N,
|
||||
remoteRC.enckey, parent->RouterEncryptionSecret());
|
||||
}
|
||||
|
||||
bool
|
||||
Session::VerifyThenDecrypt(const byte_t* ptr)
|
||||
{
|
||||
|
@ -1019,6 +1069,13 @@ namespace llarp
|
|||
}
|
||||
// determine if this message is done
|
||||
bool result = true;
|
||||
// mutate key
|
||||
if(!MutateKey(rxKey, A))
|
||||
{
|
||||
llarp::LogError("failed to mutate rx key");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(remaining == 0)
|
||||
{
|
||||
llarp_buffer_t buf = itr->second.buffer;
|
||||
|
@ -1032,15 +1089,6 @@ namespace llarp
|
|||
// get rid of message buffer
|
||||
itr = m_RecvMsgs.erase(itr);
|
||||
}
|
||||
// mutate key
|
||||
if(msgid)
|
||||
{
|
||||
if(!MutateKey(rxKey, A))
|
||||
{
|
||||
llarp::LogError("failed to mutate rx key");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,9 @@ namespace llarp
|
|||
std::unique_ptr< ILinkLayer >
|
||||
NewServer(llarp::Crypto* crypto, const byte_t* routerEncSecret,
|
||||
llarp::GetRCFunc getrc, llarp::LinkMessageHandler h,
|
||||
llarp::SessionEstablishedHandler est, llarp::SignBufferFunc sign,
|
||||
llarp::TimeoutHandler timeout,
|
||||
llarp::SessionEstablishedHandler est,
|
||||
llarp::SessionRenegotiateHandler reneg,
|
||||
llarp::SignBufferFunc sign, llarp::TimeoutHandler timeout,
|
||||
llarp::SessionClosedHandler closed);
|
||||
|
||||
std::unique_ptr< ILinkLayer >
|
||||
|
|
|
@ -162,6 +162,14 @@ namespace llarp
|
|||
Session();
|
||||
~Session();
|
||||
|
||||
/// handle LIM after handshake
|
||||
bool
|
||||
GotSessionRenegotiate(const LinkIntroMessage* msg);
|
||||
|
||||
/// re negotiate session with our new local RC
|
||||
bool
|
||||
Rehandshake();
|
||||
|
||||
/// pump tx queue
|
||||
void
|
||||
PumpWrite();
|
||||
|
@ -234,8 +242,8 @@ namespace llarp
|
|||
RemotePubKey() const;
|
||||
|
||||
/// get remote address
|
||||
const Addr&
|
||||
RemoteEndpoint() const;
|
||||
Addr
|
||||
RemoteEndpoint();
|
||||
|
||||
/// get parent link
|
||||
ILinkLayer*
|
||||
|
@ -279,6 +287,7 @@ namespace llarp
|
|||
llarp::GetRCFunc getrc, llarp::LinkMessageHandler h,
|
||||
llarp::SignBufferFunc sign,
|
||||
llarp::SessionEstablishedHandler established,
|
||||
llarp::SessionRenegotiateHandler reneg,
|
||||
llarp::TimeoutHandler timeout,
|
||||
llarp::SessionClosedHandler closed);
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ namespace llarp
|
|||
return false;
|
||||
}
|
||||
// verify RC
|
||||
if(!rc.Verify(c))
|
||||
if(!rc.Verify(c, llarp::time_now_ms()))
|
||||
{
|
||||
llarp::LogError("invalid RC in link intro");
|
||||
return false;
|
||||
|
|
|
@ -66,6 +66,31 @@ llarp_nodedb::getRCFilePath(const byte_t *pubkey) const
|
|||
return filepath.string();
|
||||
}
|
||||
|
||||
struct async_insert_rc
|
||||
{
|
||||
llarp_nodedb *nodedb;
|
||||
llarp::RouterContact rc;
|
||||
async_insert_rc(llarp_nodedb *n, const llarp::RouterContact &r)
|
||||
: nodedb(n), rc(r)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
handle_async_insert_rc(void *u)
|
||||
{
|
||||
async_insert_rc *job = static_cast< async_insert_rc * >(u);
|
||||
job->nodedb->Insert(job->rc);
|
||||
delete job;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_nodedb::InsertAsync(llarp::RouterContact rc)
|
||||
{
|
||||
async_insert_rc *ctx = new async_insert_rc(this, rc);
|
||||
llarp_threadpool_queue_job(disk, {ctx, &handle_async_insert_rc});
|
||||
}
|
||||
|
||||
/// insert and write to disk
|
||||
bool
|
||||
llarp_nodedb::Insert(const llarp::RouterContact &rc)
|
||||
|
@ -144,7 +169,7 @@ llarp_nodedb::loadfile(const fs::path &fpath)
|
|||
llarp::LogError("failed to read file ", fpath);
|
||||
return false;
|
||||
}
|
||||
if(!rc.Verify(crypto))
|
||||
if(!rc.Verify(crypto, llarp::time_now_ms()))
|
||||
{
|
||||
llarp::LogError(fpath, " contains invalid RC");
|
||||
return false;
|
||||
|
@ -231,7 +256,8 @@ crypto_threadworker_verifyrc(void *user)
|
|||
llarp_async_verify_rc *verify_request =
|
||||
static_cast< llarp_async_verify_rc * >(user);
|
||||
llarp::RouterContact rc = verify_request->rc;
|
||||
verify_request->valid = rc.Verify(verify_request->nodedb->crypto);
|
||||
verify_request->valid =
|
||||
rc.Verify(verify_request->nodedb->crypto, llarp::time_now_ms());
|
||||
// if it's valid we need to set it
|
||||
if(verify_request->valid && rc.IsPublicRouter())
|
||||
{
|
||||
|
|
|
@ -28,7 +28,8 @@ struct llarp_nodedb_iter
|
|||
|
||||
struct llarp_nodedb
|
||||
{
|
||||
llarp_nodedb(llarp::Crypto *c) : crypto(c)
|
||||
llarp_nodedb(llarp::Crypto *c, llarp_threadpool *diskworker)
|
||||
: crypto(c), disk(diskworker)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -38,6 +39,7 @@ struct llarp_nodedb
|
|||
}
|
||||
|
||||
llarp::Crypto *crypto;
|
||||
llarp_threadpool *disk;
|
||||
llarp::util::Mutex access;
|
||||
std::unordered_map< llarp::RouterID, llarp::RouterContact,
|
||||
llarp::RouterID::Hash >
|
||||
|
@ -63,6 +65,10 @@ struct llarp_nodedb
|
|||
bool
|
||||
Insert(const llarp::RouterContact &rc);
|
||||
|
||||
/// insert and write to disk in background
|
||||
void
|
||||
InsertAsync(llarp::RouterContact rc);
|
||||
|
||||
ssize_t
|
||||
Load(const fs::path &path);
|
||||
|
||||
|
|
|
@ -182,6 +182,7 @@ namespace llarp
|
|||
Router::OnSessionEstablished(llarp::RouterContact rc)
|
||||
{
|
||||
async_verify_RC(rc, nullptr);
|
||||
llarp::LogInfo("session with ", rc.pubkey, "established");
|
||||
}
|
||||
|
||||
Router::Router(struct llarp_threadpool *_tp, struct llarp_ev_loop *_netloop,
|
||||
|
@ -321,16 +322,14 @@ namespace llarp
|
|||
{
|
||||
return;
|
||||
}
|
||||
if(results[0].Verify(&crypto))
|
||||
if(results[0].Verify(&crypto, Now()))
|
||||
{
|
||||
nodedb->Insert(results[0]);
|
||||
llarp_router_try_connect(this, results[0], 10);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DiscardOutboundFor(remote);
|
||||
}
|
||||
DiscardOutboundFor(remote);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -346,6 +345,17 @@ namespace llarp
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Router::ForEachPeer(std::function< void(llarp::ILinkSession *) > visit)
|
||||
{
|
||||
outboundLink->ForEachSession(
|
||||
[visit](llarp::ILinkSession *peer) { visit(peer); });
|
||||
for(const auto &link : inboundLinks)
|
||||
{
|
||||
link->ForEachSession([visit](llarp::ILinkSession *peer) { visit(peer); });
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Router::try_connect(fs::path rcfile)
|
||||
{
|
||||
|
@ -355,7 +365,7 @@ namespace llarp
|
|||
llarp::LogError("failure to decode or verify of remote RC");
|
||||
return;
|
||||
}
|
||||
if(remote.Verify(&crypto))
|
||||
if(remote.Verify(&crypto, Now()))
|
||||
{
|
||||
llarp::LogDebug("verified signature");
|
||||
// store into filesystem
|
||||
|
@ -421,7 +431,7 @@ namespace llarp
|
|||
Router::SaveRC()
|
||||
{
|
||||
llarp::LogDebug("verify RC signature");
|
||||
if(!rc().Verify(&crypto))
|
||||
if(!rc().Verify(&crypto, Now()))
|
||||
{
|
||||
rc().Dump< MAX_RC_SIZE >();
|
||||
llarp::LogError("RC is invalid, not saving");
|
||||
|
@ -545,7 +555,7 @@ namespace llarp
|
|||
return;
|
||||
for(const auto &rc : results)
|
||||
{
|
||||
if(rc.Verify(&crypto))
|
||||
if(rc.Verify(&crypto, Now()))
|
||||
nodedb->Insert(rc);
|
||||
else
|
||||
return;
|
||||
|
@ -625,11 +635,68 @@ namespace llarp
|
|||
return validRouters.size();
|
||||
}
|
||||
|
||||
bool
|
||||
Router::UpdateOurRC(bool rotateKeys)
|
||||
{
|
||||
llarp::SecretKey nextOnionKey;
|
||||
llarp::RouterContact nextRC = _rc;
|
||||
if(rotateKeys)
|
||||
{
|
||||
crypto.encryption_keygen(nextOnionKey);
|
||||
nextRC.enckey = llarp::seckey_topublic(nextOnionKey);
|
||||
}
|
||||
nextRC.last_updated = Now();
|
||||
if(!nextRC.Sign(&crypto, identity))
|
||||
return false;
|
||||
_rc = nextRC;
|
||||
if(rotateKeys)
|
||||
{
|
||||
encryption = nextOnionKey;
|
||||
// propagate RC by renegotiating sessions
|
||||
ForEachPeer([&](llarp::ILinkSession *s) {
|
||||
if(!s->RenegotiateSession())
|
||||
{
|
||||
llarp::LogWarn("failed to renegotiate session with ",
|
||||
s->GetRemoteEndpoint());
|
||||
}
|
||||
});
|
||||
}
|
||||
// TODO: do this async
|
||||
return SaveRC();
|
||||
}
|
||||
|
||||
bool
|
||||
Router::CheckRenegotiateValid(RouterContact newrc, RouterContact oldrc)
|
||||
{
|
||||
// missmatch of identity ?
|
||||
if(newrc.pubkey != oldrc.pubkey)
|
||||
return false;
|
||||
|
||||
// store it in nodedb async
|
||||
nodedb->InsertAsync(newrc);
|
||||
// update valid routers
|
||||
{
|
||||
auto itr = validRouters.find(newrc.pubkey);
|
||||
if(itr == validRouters.end())
|
||||
validRouters[newrc.pubkey] = newrc;
|
||||
else
|
||||
itr->second = newrc;
|
||||
}
|
||||
// TODO: check for other places that need updating the RC
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Router::Tick()
|
||||
{
|
||||
// llarp::LogDebug("tick router");
|
||||
auto now = llarp_ev_loop_time_now_ms(netloop);
|
||||
if(_rc.ExpiresSoon(now))
|
||||
{
|
||||
if(!UpdateOurRC())
|
||||
llarp::LogError("Failed to update our RC");
|
||||
}
|
||||
|
||||
paths.TickPaths(now);
|
||||
paths.ExpirePaths(now);
|
||||
{
|
||||
|
@ -950,7 +1017,8 @@ namespace llarp
|
|||
// TODO: enable this once the network can serialize xi
|
||||
//_rc.exits.emplace_back(_rc.pubkey, a);
|
||||
llarp::LogInfo(
|
||||
"Neato tehl33toh, You are a freaking exit relay. w00t!!!!! your exit "
|
||||
"Neato tehl33toh, You are a freaking exit relay. w00t!!!!! your "
|
||||
"exit "
|
||||
"is advertised as exiting at ",
|
||||
a);
|
||||
}
|
||||
|
@ -1316,10 +1384,16 @@ namespace llarp
|
|||
{
|
||||
self->bootstrapRCList.emplace_back();
|
||||
auto &rc = self->bootstrapRCList.back();
|
||||
if(rc.Read(val) && rc.Verify(&self->crypto))
|
||||
if(rc.Read(val) && rc.Verify(&self->crypto, self->Now()))
|
||||
{
|
||||
llarp::LogInfo("Added bootstrap node ", RouterID(rc.pubkey.data()));
|
||||
}
|
||||
else if(self->Now() - rc.last_updated > RouterContact::Lifetime)
|
||||
{
|
||||
llarp::LogWarn("Bootstrap node ", RouterID(rc.pubkey.data()),
|
||||
" is too old and needs to be refreshed");
|
||||
self->bootstrapRCList.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LogError("malformed rc file: ", val);
|
||||
|
|
|
@ -304,6 +304,16 @@ namespace llarp
|
|||
ForEachPeer(
|
||||
std::function< void(const llarp::ILinkSession *, bool) > visit) const;
|
||||
|
||||
void
|
||||
ForEachPeer(std::function< void(llarp::ILinkSession *) > visit);
|
||||
|
||||
/// check if newRc matches oldRC and update local rc for this remote contact
|
||||
/// if valid
|
||||
/// returns true on valid and updated
|
||||
/// returns false otherwise
|
||||
bool
|
||||
CheckRenegotiateValid(RouterContact newRc, RouterContact oldRC);
|
||||
|
||||
/// flush outbound message queue
|
||||
void
|
||||
FlushOutbound();
|
||||
|
@ -368,6 +378,9 @@ namespace llarp
|
|||
HandleAsyncLoadRCForSendTo(llarp_async_load_rc *async);
|
||||
|
||||
private:
|
||||
bool
|
||||
UpdateOurRC(bool rotateKeys = true);
|
||||
|
||||
template < typename Config >
|
||||
void
|
||||
mergeHiddenServiceConfig(const Config &in, Config &out)
|
||||
|
|
|
@ -14,6 +14,46 @@ namespace llarp
|
|||
{
|
||||
bool RouterContact::IgnoreBogons = false;
|
||||
|
||||
/// 1 hour
|
||||
llarp_time_t RouterContact::Lifetime = 60 * 60 * 1000;
|
||||
|
||||
NetID::NetID() : AlignedBuffer< 8 >((const byte_t *)LLARP_NET_ID)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
NetID::operator==(const NetID &other) const
|
||||
{
|
||||
return memcmp(data(), other.data(), size()) == 0;
|
||||
}
|
||||
|
||||
std::string
|
||||
NetID::ToString() const
|
||||
{
|
||||
size_t l = strnlen((const char *)data(), size());
|
||||
return std::string((const char *)data(), l);
|
||||
}
|
||||
|
||||
bool
|
||||
NetID::BDecode(llarp_buffer_t *buf)
|
||||
{
|
||||
Zero();
|
||||
llarp_buffer_t strbuf;
|
||||
if(!bencode_read_string(buf, &strbuf))
|
||||
return false;
|
||||
if(strbuf.sz > 8)
|
||||
return false;
|
||||
memcpy(data(), strbuf.base, strbuf.sz);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
NetID::BEncode(llarp_buffer_t *buf) const
|
||||
{
|
||||
size_t l = strnlen((const char *)data(), size());
|
||||
return bencode_write_bytestring(buf, data(), l);
|
||||
}
|
||||
|
||||
bool
|
||||
RouterContact::BEncode(llarp_buffer_t *buf) const
|
||||
{
|
||||
|
@ -27,6 +67,12 @@ namespace llarp
|
|||
if(!BEncodeWriteList(addrs.begin(), addrs.end(), buf))
|
||||
return false;
|
||||
|
||||
/* write netid */
|
||||
if(!bencode_write_bytestring(buf, "i", 1))
|
||||
return false;
|
||||
if(!bencode_write_bytestring(buf, netID.data(), netID.size()))
|
||||
return false;
|
||||
|
||||
/* write signing pubkey */
|
||||
if(!bencode_write_bytestring(buf, "k", 1))
|
||||
return false;
|
||||
|
@ -50,7 +96,7 @@ namespace llarp
|
|||
return false;
|
||||
|
||||
/* write last updated */
|
||||
if(!bencode_write_bytestring(buf, "u", 1))
|
||||
if(!bencode_write_bytestring(buf, "t", 1))
|
||||
return false;
|
||||
if(!bencode_write_uint64(buf, last_updated))
|
||||
return false;
|
||||
|
@ -92,6 +138,9 @@ namespace llarp
|
|||
if(!BEncodeMaybeReadDictList("a", addrs, read, key, buf))
|
||||
return false;
|
||||
|
||||
if(!BEncodeMaybeReadDictEntry("i", netID, read, key, buf))
|
||||
return false;
|
||||
|
||||
if(!BEncodeMaybeReadDictEntry("k", pubkey, read, key, buf))
|
||||
return false;
|
||||
|
||||
|
@ -113,7 +162,7 @@ namespace llarp
|
|||
if(!BEncodeMaybeReadDictInt("v", version, read, key, buf))
|
||||
return false;
|
||||
|
||||
if(!BEncodeMaybeReadDictInt("u", last_updated, read, key, buf))
|
||||
if(!BEncodeMaybeReadDictInt("t", last_updated, read, key, buf))
|
||||
return false;
|
||||
|
||||
if(!BEncodeMaybeReadDictList("x", exits, read, key, buf))
|
||||
|
@ -144,6 +193,18 @@ namespace llarp
|
|||
memcpy(nickname, nick.c_str(), std::min(nick.size(), nickname.size()));
|
||||
}
|
||||
|
||||
bool
|
||||
RouterContact::IsExpired(llarp_time_t now) const
|
||||
{
|
||||
return now > last_updated && now - last_updated >= Lifetime;
|
||||
}
|
||||
|
||||
bool
|
||||
RouterContact::ExpiresSoon(llarp_time_t now, llarp_time_t dlt) const
|
||||
{
|
||||
return now - (last_updated + Lifetime) >= dlt;
|
||||
}
|
||||
|
||||
std::string
|
||||
RouterContact::Nick() const
|
||||
{
|
||||
|
@ -167,8 +228,12 @@ namespace llarp
|
|||
}
|
||||
|
||||
bool
|
||||
RouterContact::Verify(llarp::Crypto *crypto) const
|
||||
RouterContact::Verify(llarp::Crypto *crypto, llarp_time_t now) const
|
||||
{
|
||||
if(netID.ToString() != LLARP_NET_ID)
|
||||
return false;
|
||||
if(IsExpired(now))
|
||||
return false;
|
||||
for(const auto &a : addrs)
|
||||
{
|
||||
if(IsBogon(a.ip) && !IgnoreBogons)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <bencode.hpp>
|
||||
#include <crypto.h>
|
||||
#include <exit_info.hpp>
|
||||
#include <version.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
@ -13,11 +14,44 @@
|
|||
|
||||
namespace llarp
|
||||
{
|
||||
/// NetID
|
||||
struct NetID final : public AlignedBuffer< 8 >
|
||||
{
|
||||
NetID();
|
||||
|
||||
bool
|
||||
operator==(const NetID &other) const;
|
||||
|
||||
bool
|
||||
operator!=(const NetID &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
friend std::ostream &
|
||||
operator<<(std::ostream &out, const NetID &id)
|
||||
{
|
||||
return out << id.ToString();
|
||||
}
|
||||
|
||||
std::string
|
||||
ToString() const;
|
||||
|
||||
bool
|
||||
BDecode(llarp_buffer_t *buf);
|
||||
|
||||
bool
|
||||
BEncode(llarp_buffer_t *buf) const;
|
||||
};
|
||||
|
||||
/// RouterContact
|
||||
struct RouterContact final : public IBEncodeMessage
|
||||
{
|
||||
/// for unit tests
|
||||
static bool IgnoreBogons;
|
||||
|
||||
static llarp_time_t Lifetime;
|
||||
|
||||
RouterContact() : IBEncodeMessage()
|
||||
{
|
||||
Clear();
|
||||
|
@ -26,6 +60,7 @@ namespace llarp
|
|||
RouterContact(const RouterContact &other)
|
||||
: IBEncodeMessage()
|
||||
, addrs(other.addrs)
|
||||
, netID(other.netID)
|
||||
, enckey(other.enckey)
|
||||
, pubkey(other.pubkey)
|
||||
, exits(other.exits)
|
||||
|
@ -38,6 +73,8 @@ namespace llarp
|
|||
|
||||
// advertised addresses
|
||||
std::vector< AddressInfo > addrs;
|
||||
// network identifier
|
||||
NetID netID;
|
||||
// public encryption public key
|
||||
llarp::PubKey enckey;
|
||||
// public signing public key
|
||||
|
@ -59,7 +96,8 @@ namespace llarp
|
|||
{
|
||||
return addrs == other.addrs && enckey == other.enckey
|
||||
&& pubkey == other.pubkey && signature == other.signature
|
||||
&& nickname == other.nickname && last_updated == other.last_updated;
|
||||
&& nickname == other.nickname && last_updated == other.last_updated
|
||||
&& netID == other.netID;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -97,11 +135,18 @@ namespace llarp
|
|||
SetNick(const std::string &nick);
|
||||
|
||||
bool
|
||||
Verify(llarp::Crypto *crypto) const;
|
||||
Verify(llarp::Crypto *crypto, llarp_time_t now) const;
|
||||
|
||||
bool
|
||||
Sign(llarp::Crypto *crypto, const llarp::SecretKey &secret);
|
||||
|
||||
/// does this RC expire soon? default delta is 1 minute
|
||||
bool
|
||||
ExpiresSoon(llarp_time_t now, llarp_time_t dlt = 60000) const;
|
||||
|
||||
bool
|
||||
IsExpired(llarp_time_t now) const;
|
||||
|
||||
bool
|
||||
OtherIsNewer(const RouterContact &other) const
|
||||
{
|
||||
|
|
|
@ -29,4 +29,8 @@
|
|||
#define LLARP_RELEASE_MOTTO "(dev build)"
|
||||
#endif
|
||||
|
||||
#ifndef LLARP_NET_ID
|
||||
#define LLARP_NET_ID "testnet"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -43,6 +43,15 @@ struct UTPTest : public ::testing::Test
|
|||
return rc.pubkey;
|
||||
}
|
||||
|
||||
/// regenerate rc and rotate onion key
|
||||
bool
|
||||
Regen()
|
||||
{
|
||||
crypto->encryption_keygen(encryptionKey);
|
||||
rc.enckey = llarp::seckey_topublic(encryptionKey);
|
||||
return rc.Sign(crypto, signingKey);
|
||||
}
|
||||
|
||||
std::unique_ptr< Link_t > link;
|
||||
|
||||
bool
|
||||
|
@ -84,6 +93,8 @@ struct UTPTest : public ::testing::Test
|
|||
llarp_ev_loop* netLoop;
|
||||
std::unique_ptr< llarp::Logic > logic;
|
||||
|
||||
llarp_time_t oldRCLifetime;
|
||||
|
||||
UTPTest()
|
||||
: crypto(llarp::Crypto::sodium{})
|
||||
, Alice(crypto)
|
||||
|
@ -95,7 +106,9 @@ struct UTPTest : public ::testing::Test
|
|||
void
|
||||
SetUp()
|
||||
{
|
||||
oldRCLifetime = llarp::RouterContact::Lifetime;
|
||||
llarp::RouterContact::IgnoreBogons = true;
|
||||
llarp::RouterContact::Lifetime = 500;
|
||||
llarp_ev_loop_alloc(&netLoop);
|
||||
logic.reset(new llarp::Logic());
|
||||
}
|
||||
|
@ -108,6 +121,7 @@ struct UTPTest : public ::testing::Test
|
|||
logic.reset();
|
||||
llarp_ev_loop_free(&netLoop);
|
||||
llarp::RouterContact::IgnoreBogons = false;
|
||||
llarp::RouterContact::Lifetime = oldRCLifetime;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -134,17 +148,101 @@ struct UTPTest : public ::testing::Test
|
|||
bool AliceGotMessage(llarp_buffer_t)
|
||||
{
|
||||
success = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BobGotMessage(llarp_buffer_t)
|
||||
{
|
||||
success = true;
|
||||
Stop();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(UTPTest, TestAliceAndBob)
|
||||
TEST_F(UTPTest, TestAliceRenegWithBob)
|
||||
{
|
||||
Alice.link.reset(new Link_t(
|
||||
&crypto, Alice.encryptionKey,
|
||||
[&]() -> const llarp::RouterContact& { return Alice.GetRC(); },
|
||||
[&](llarp::ILinkSession* s, llarp_buffer_t buf) -> bool {
|
||||
if(Alice.gotLIM)
|
||||
{
|
||||
Alice.Regen();
|
||||
return s->RenegotiateSession();
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LinkIntroMessage msg;
|
||||
if(!msg.BDecode(&buf))
|
||||
return false;
|
||||
if(!s->GotLIM(&msg))
|
||||
return false;
|
||||
Alice.gotLIM = true;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
[&](llarp::Signature& sig, llarp_buffer_t buf) -> bool {
|
||||
return crypto.sign(sig, Alice.signingKey, buf);
|
||||
},
|
||||
[&](llarp::RouterContact rc) {
|
||||
ASSERT_EQ(rc, Bob.GetRC());
|
||||
llarp::LogInfo("alice established with bob");
|
||||
},
|
||||
[&](llarp::RouterContact, llarp::RouterContact) -> bool { return true; },
|
||||
[&](llarp::ILinkSession* session) {
|
||||
ASSERT_FALSE(session->IsEstablished());
|
||||
Stop();
|
||||
},
|
||||
[&](llarp::RouterID router) { ASSERT_EQ(router, Bob.GetRouterID()); }));
|
||||
|
||||
auto sendDiscardMessage = [](llarp::ILinkSession* s) -> bool {
|
||||
// send discard message in reply to complete unit test
|
||||
byte_t tmp[32] = {0};
|
||||
auto otherBuf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
llarp::DiscardMessage discard;
|
||||
if(!discard.BEncode(&otherBuf))
|
||||
return false;
|
||||
otherBuf.sz = otherBuf.cur - otherBuf.base;
|
||||
otherBuf.cur = otherBuf.base;
|
||||
return s->SendMessageBuffer(otherBuf);
|
||||
};
|
||||
|
||||
Bob.link.reset(new Link_t(
|
||||
&crypto, Bob.encryptionKey,
|
||||
[&]() -> const llarp::RouterContact& { return Bob.GetRC(); },
|
||||
[&](llarp::ILinkSession* s, llarp_buffer_t buf) -> bool {
|
||||
llarp::LinkIntroMessage msg;
|
||||
if(!msg.BDecode(&buf))
|
||||
return false;
|
||||
if(!s->GotLIM(&msg))
|
||||
return false;
|
||||
Bob.gotLIM = true;
|
||||
return sendDiscardMessage(s);
|
||||
},
|
||||
[&](llarp::Signature& sig, llarp_buffer_t buf) -> bool {
|
||||
return crypto.sign(sig, Bob.signingKey, buf);
|
||||
},
|
||||
[&](llarp::RouterContact rc) {
|
||||
ASSERT_EQ(rc, Alice.GetRC());
|
||||
llarp::LogInfo("bob established with alice");
|
||||
Bob.link->VisitSessionByPubkey(Alice.GetRC().pubkey.data(),
|
||||
sendDiscardMessage);
|
||||
},
|
||||
[&](llarp::RouterContact newrc, llarp::RouterContact oldrc) -> bool {
|
||||
success = newrc.pubkey == oldrc.pubkey;
|
||||
return true;
|
||||
},
|
||||
[&](llarp::ILinkSession* session) {
|
||||
ASSERT_FALSE(session->IsEstablished());
|
||||
},
|
||||
[&](llarp::RouterID router) { ASSERT_EQ(router, Alice.GetRouterID()); }));
|
||||
|
||||
ASSERT_TRUE(Alice.Start(logic.get(), netLoop, AlicePort));
|
||||
ASSERT_TRUE(Bob.Start(logic.get(), netLoop, BobPort));
|
||||
|
||||
ASSERT_TRUE(Alice.link->TryEstablishTo(Bob.GetRC()));
|
||||
|
||||
RunMainloop();
|
||||
ASSERT_TRUE(Alice.gotLIM);
|
||||
ASSERT_TRUE(Bob.gotLIM);
|
||||
ASSERT_TRUE(success);
|
||||
}
|
||||
|
||||
TEST_F(UTPTest, TestAliceConnectToBob)
|
||||
{
|
||||
Alice.link.reset(new Link_t(
|
||||
&crypto, Alice.encryptionKey,
|
||||
|
@ -161,42 +259,58 @@ TEST_F(UTPTest, TestAliceAndBob)
|
|||
return false;
|
||||
if(!s->GotLIM(&msg))
|
||||
return false;
|
||||
Alice.gotLIM = true;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
[&](llarp::Signature& sig, llarp_buffer_t buf) -> bool {
|
||||
return crypto.sign(sig, Alice.signingKey, buf);
|
||||
},
|
||||
[&](llarp::RouterContact rc) { ASSERT_EQ(rc, Bob.GetRC()); },
|
||||
[&](llarp::RouterContact rc) {
|
||||
ASSERT_EQ(rc, Bob.GetRC());
|
||||
llarp::LogInfo("alice established with bob");
|
||||
},
|
||||
[&](llarp::RouterContact, llarp::RouterContact) -> bool { return true; },
|
||||
[&](llarp::ILinkSession* session) {
|
||||
ASSERT_FALSE(session->IsEstablished());
|
||||
Stop();
|
||||
},
|
||||
[&](llarp::RouterID router) { ASSERT_EQ(router, Bob.GetRouterID()); }));
|
||||
|
||||
auto sendDiscardMessage = [](llarp::ILinkSession* s) -> bool {
|
||||
// send discard message in reply to complete unit test
|
||||
byte_t tmp[32] = {0};
|
||||
auto otherBuf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
llarp::DiscardMessage discard;
|
||||
if(!discard.BEncode(&otherBuf))
|
||||
return false;
|
||||
otherBuf.sz = otherBuf.cur - otherBuf.base;
|
||||
otherBuf.cur = otherBuf.base;
|
||||
return s->SendMessageBuffer(otherBuf);
|
||||
};
|
||||
|
||||
Bob.link.reset(new Link_t(
|
||||
&crypto, Bob.encryptionKey,
|
||||
[&]() -> const llarp::RouterContact& { return Bob.GetRC(); },
|
||||
[&](llarp::ILinkSession* s, llarp_buffer_t buf) -> bool {
|
||||
if(Bob.gotLIM)
|
||||
{
|
||||
return BobGotMessage(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LinkIntroMessage msg;
|
||||
if(!msg.BDecode(&buf))
|
||||
return false;
|
||||
if(!s->GotLIM(&msg))
|
||||
return false;
|
||||
Bob.gotLIM = true;
|
||||
return true;
|
||||
}
|
||||
llarp::LinkIntroMessage msg;
|
||||
if(!msg.BDecode(&buf))
|
||||
return false;
|
||||
if(!s->GotLIM(&msg))
|
||||
return false;
|
||||
Bob.gotLIM = true;
|
||||
return true;
|
||||
},
|
||||
[&](llarp::Signature& sig, llarp_buffer_t buf) -> bool {
|
||||
return crypto.sign(sig, Bob.signingKey, buf);
|
||||
},
|
||||
[&](llarp::RouterContact rc) { ASSERT_EQ(rc, Alice.GetRC()); },
|
||||
[&](llarp::RouterContact rc) {
|
||||
ASSERT_EQ(rc, Alice.GetRC());
|
||||
llarp::LogInfo("bob established with alice");
|
||||
Bob.link->VisitSessionByPubkey(Alice.GetRC().pubkey.data(),
|
||||
sendDiscardMessage);
|
||||
},
|
||||
[&](llarp::RouterContact, llarp::RouterContact) -> bool { return true; },
|
||||
[&](llarp::ILinkSession* session) {
|
||||
ASSERT_FALSE(session->IsEstablished());
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue