2018-12-12 01:32:10 +00:00
|
|
|
#include <link/server.hpp>
|
2018-09-03 13:10:56 +00:00
|
|
|
|
2019-01-13 16:30:07 +00:00
|
|
|
#include <crypto/crypto.hpp>
|
2019-01-10 19:41:51 +00:00
|
|
|
#include <util/fs.hpp>
|
|
|
|
|
2018-09-03 13:10:56 +00:00
|
|
|
namespace llarp
|
|
|
|
{
|
2019-01-02 01:04:04 +00:00
|
|
|
ILinkLayer::ILinkLayer(const SecretKey& routerEncSecret, GetRCFunc getrc,
|
2018-12-17 20:46:08 +00:00
|
|
|
LinkMessageHandler handler, SignBufferFunc signbuf,
|
|
|
|
SessionEstablishedHandler establishedSession,
|
2018-12-19 16:17:41 +00:00
|
|
|
SessionRenegotiateHandler reneg,
|
2018-12-17 20:46:08 +00:00
|
|
|
TimeoutHandler timeout, SessionClosedHandler closed)
|
|
|
|
: HandleMessage(handler)
|
|
|
|
, HandleTimeout(timeout)
|
|
|
|
, Sign(signbuf)
|
|
|
|
, GetOurRC(getrc)
|
|
|
|
, SessionEstablished(establishedSession)
|
|
|
|
, SessionClosed(closed)
|
2018-12-19 16:17:41 +00:00
|
|
|
, SessionRenegotiate(reneg)
|
2018-12-17 20:46:08 +00:00
|
|
|
, m_RouterEncSecret(routerEncSecret)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-09-03 13:10:56 +00:00
|
|
|
ILinkLayer::~ILinkLayer()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2019-01-02 01:03:53 +00:00
|
|
|
ILinkLayer::HasSessionTo(const RouterID& id)
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2018-09-10 13:43:36 +00:00
|
|
|
Lock l(m_AuthedLinksMutex);
|
2019-01-02 01:03:53 +00:00
|
|
|
return m_AuthedLinks.find(id) != m_AuthedLinks.end();
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 18:18:12 +00:00
|
|
|
void
|
|
|
|
ILinkLayer::ForEachSession(
|
|
|
|
std::function< void(const ILinkSession*) > visit) const
|
|
|
|
{
|
|
|
|
auto itr = m_AuthedLinks.begin();
|
|
|
|
while(itr != m_AuthedLinks.end())
|
|
|
|
{
|
|
|
|
visit(itr->second.get());
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-19 16:17:41 +00:00
|
|
|
bool
|
2019-01-02 01:03:53 +00:00
|
|
|
ILinkLayer::VisitSessionByPubkey(const RouterID& pk,
|
2018-12-19 16:17:41 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-03 13:10:56 +00:00
|
|
|
bool
|
|
|
|
ILinkLayer::Configure(llarp_ev_loop* loop, const std::string& ifname, int af,
|
|
|
|
uint16_t port)
|
|
|
|
{
|
2018-10-29 16:48:36 +00:00
|
|
|
m_Loop = loop;
|
2018-09-03 13:10:56 +00:00
|
|
|
m_udp.user = this;
|
|
|
|
m_udp.recvfrom = &ILinkLayer::udp_recv_from;
|
|
|
|
m_udp.tick = &ILinkLayer::udp_tick;
|
|
|
|
if(ifname == "*")
|
|
|
|
{
|
|
|
|
if(!AllInterfaces(af, m_ourAddr))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if(!GetIFAddr(ifname, m_ourAddr, af))
|
|
|
|
return false;
|
2018-09-04 19:15:06 +00:00
|
|
|
m_ourAddr.port(port);
|
2018-09-03 13:10:56 +00:00
|
|
|
return llarp_ev_add_udp(loop, &m_udp, m_ourAddr) != -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ILinkLayer::Pump()
|
|
|
|
{
|
2018-12-17 20:46:08 +00:00
|
|
|
auto _now = Now();
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2018-09-10 13:43:36 +00:00
|
|
|
Lock lock(m_AuthedLinksMutex);
|
2018-09-07 20:36:06 +00:00
|
|
|
auto itr = m_AuthedLinks.begin();
|
|
|
|
while(itr != m_AuthedLinks.end())
|
2018-09-07 17:41:49 +00:00
|
|
|
{
|
2018-12-27 19:10:38 +00:00
|
|
|
if(itr->second.get() && !itr->second->TimedOut(_now))
|
2018-09-07 20:36:06 +00:00
|
|
|
{
|
|
|
|
itr->second->Pump();
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
else
|
2018-11-19 21:55:41 +00:00
|
|
|
{
|
2018-12-11 13:33:23 +00:00
|
|
|
llarp::LogInfo("session to ", RouterID(itr->second->GetPubKey()),
|
|
|
|
" timed out");
|
2018-09-07 20:36:06 +00:00
|
|
|
itr = m_AuthedLinks.erase(itr);
|
2018-11-19 21:55:41 +00:00
|
|
|
}
|
2018-09-07 17:41:49 +00:00
|
|
|
}
|
2018-09-07 20:36:06 +00:00
|
|
|
}
|
|
|
|
{
|
2018-09-10 13:43:36 +00:00
|
|
|
Lock lock(m_PendingMutex);
|
2018-09-07 20:36:06 +00:00
|
|
|
|
|
|
|
auto itr = m_Pending.begin();
|
|
|
|
while(itr != m_Pending.end())
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2019-01-07 12:47:57 +00:00
|
|
|
if(itr->second.get() && !itr->second->TimedOut(_now))
|
2018-09-07 20:36:06 +00:00
|
|
|
{
|
2019-01-07 12:47:57 +00:00
|
|
|
itr->second->Pump();
|
2018-09-07 20:36:06 +00:00
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
itr = m_Pending.erase(itr);
|
2018-09-06 13:16:24 +00:00
|
|
|
}
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-07 12:47:57 +00:00
|
|
|
bool
|
2019-01-02 01:03:53 +00:00
|
|
|
ILinkLayer::MapAddr(const RouterID& pk, ILinkSession* s)
|
2018-09-07 17:41:49 +00:00
|
|
|
{
|
2018-12-03 01:52:40 +00:00
|
|
|
static constexpr size_t MaxSessionsPerKey = 16;
|
2018-09-10 13:43:36 +00:00
|
|
|
Lock l_authed(m_AuthedLinksMutex);
|
|
|
|
Lock l_pending(m_PendingMutex);
|
2019-01-10 12:30:21 +00:00
|
|
|
llarp::Addr addr = s->GetRemoteEndpoint();
|
2019-01-13 16:30:07 +00:00
|
|
|
auto itr = m_Pending.find(addr);
|
2019-01-04 12:43:53 +00:00
|
|
|
if(itr != m_Pending.end())
|
2018-09-07 17:41:49 +00:00
|
|
|
{
|
2019-01-10 12:30:21 +00:00
|
|
|
if(m_AuthedLinks.count(pk) > MaxSessionsPerKey)
|
|
|
|
{
|
2019-01-04 12:43:53 +00:00
|
|
|
s->SendClose();
|
2019-01-10 12:30:21 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
m_AuthedLinks.emplace(pk, std::move(itr->second));
|
2019-01-04 12:43:53 +00:00
|
|
|
itr = m_Pending.erase(itr);
|
2019-01-10 12:30:21 +00:00
|
|
|
return true;
|
2019-01-07 12:47:57 +00:00
|
|
|
}
|
2019-01-10 12:30:21 +00:00
|
|
|
return false;
|
2018-09-07 17:41:49 +00:00
|
|
|
}
|
|
|
|
|
2018-09-03 13:10:56 +00:00
|
|
|
bool
|
2018-09-04 12:41:25 +00:00
|
|
|
ILinkLayer::PickAddress(const RouterContact& rc,
|
|
|
|
llarp::AddressInfo& picked) const
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
|
|
|
std::string OurDialect = Name();
|
|
|
|
for(const auto& addr : rc.addrs)
|
|
|
|
{
|
|
|
|
if(addr.dialect == OurDialect)
|
|
|
|
{
|
|
|
|
picked = addr;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-01-07 16:35:25 +00:00
|
|
|
void
|
2019-01-13 16:30:07 +00:00
|
|
|
ILinkLayer::RemovePending(ILinkSession* s)
|
2019-01-07 16:35:25 +00:00
|
|
|
{
|
|
|
|
llarp::Addr remote = s->GetRemoteEndpoint();
|
|
|
|
m_Pending.erase(remote);
|
|
|
|
}
|
|
|
|
|
2019-02-15 22:19:19 +00:00
|
|
|
util::StatusObject
|
|
|
|
ILinkLayer::ExtractStatus() const
|
|
|
|
{
|
|
|
|
std::vector<util::StatusObject> pending, established;
|
|
|
|
|
|
|
|
std::transform(m_Pending.begin(), m_Pending.end(), std::back_inserter(pending), [](const auto & item) -> util::StatusObject {
|
|
|
|
return item.second->ExtractStatus();
|
|
|
|
});
|
|
|
|
std::transform(m_AuthedLinks.begin(), m_AuthedLinks.end(), std::back_inserter(established), [](const auto & item) -> util::StatusObject {
|
|
|
|
return item.second->ExtractStatus();
|
|
|
|
});
|
|
|
|
|
|
|
|
return {
|
|
|
|
{"name", Name()},
|
|
|
|
{"rank", uint64_t(Rank())},
|
|
|
|
{"addr", m_ourAddr.ToString()},
|
|
|
|
{"sessions", util::StatusObject{
|
|
|
|
{"pending", pending},
|
|
|
|
{"established", established}
|
|
|
|
}}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-11-21 14:56:12 +00:00
|
|
|
bool
|
2018-12-19 17:48:29 +00:00
|
|
|
ILinkLayer::TryEstablishTo(RouterContact rc)
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2018-09-04 12:41:25 +00:00
|
|
|
llarp::AddressInfo to;
|
2018-09-03 13:10:56 +00:00
|
|
|
if(!PickAddress(rc, to))
|
2018-11-21 14:56:12 +00:00
|
|
|
return false;
|
2019-01-02 01:03:53 +00:00
|
|
|
llarp::LogInfo("Try establish to ", RouterID(rc.pubkey.as_array()));
|
2018-09-04 12:41:25 +00:00
|
|
|
llarp::Addr addr(to);
|
2018-09-06 20:31:58 +00:00
|
|
|
auto s = NewOutboundSession(rc, to);
|
2019-01-07 12:47:57 +00:00
|
|
|
if(PutSession(s))
|
|
|
|
{
|
|
|
|
s->Start();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
delete s;
|
|
|
|
return false;
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2018-12-10 14:14:55 +00:00
|
|
|
ILinkLayer::Start(Logic* l)
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
|
|
|
m_Logic = l;
|
2018-09-07 17:41:49 +00:00
|
|
|
ScheduleTick(100);
|
2018-09-03 13:10:56 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-02-15 22:19:19 +00:00
|
|
|
void
|
|
|
|
ILinkLayer::Tick(llarp_time_t now)
|
|
|
|
{
|
|
|
|
Lock l(m_AuthedLinksMutex);
|
|
|
|
auto itr = m_AuthedLinks.begin();
|
|
|
|
while(itr != m_AuthedLinks.end())
|
|
|
|
{
|
|
|
|
itr->second->Tick(now);
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-03 13:10:56 +00:00
|
|
|
void
|
|
|
|
ILinkLayer::Stop()
|
|
|
|
{
|
|
|
|
if(m_Logic && tick_id)
|
2018-12-10 14:14:55 +00:00
|
|
|
m_Logic->remove_call(tick_id);
|
2018-09-24 10:23:11 +00:00
|
|
|
{
|
|
|
|
Lock l(m_AuthedLinksMutex);
|
|
|
|
auto itr = m_AuthedLinks.begin();
|
|
|
|
while(itr != m_AuthedLinks.end())
|
|
|
|
{
|
|
|
|
itr->second->SendClose();
|
2018-12-24 16:31:58 +00:00
|
|
|
++itr;
|
2018-09-24 10:23:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
Lock l(m_PendingMutex);
|
|
|
|
auto itr = m_Pending.begin();
|
|
|
|
while(itr != m_Pending.end())
|
|
|
|
{
|
2019-01-07 12:47:57 +00:00
|
|
|
itr->second->SendClose();
|
2018-12-24 16:31:58 +00:00
|
|
|
++itr;
|
2018-09-24 10:23:11 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-01-02 01:04:04 +00:00
|
|
|
ILinkLayer::CloseSessionTo(const RouterID& remote)
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2018-09-10 13:43:36 +00:00
|
|
|
Lock l(m_AuthedLinksMutex);
|
2018-12-10 17:22:59 +00:00
|
|
|
RouterID r = remote;
|
|
|
|
llarp::LogInfo("Closing all to ", r);
|
|
|
|
auto range = m_AuthedLinks.equal_range(r);
|
2018-09-07 20:36:06 +00:00
|
|
|
auto itr = range.first;
|
|
|
|
while(itr != range.second)
|
|
|
|
{
|
|
|
|
itr->second->SendClose();
|
|
|
|
itr = m_AuthedLinks.erase(itr);
|
|
|
|
}
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-01-02 01:04:04 +00:00
|
|
|
ILinkLayer::KeepAliveSessionTo(const RouterID& remote)
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2018-09-10 13:43:36 +00:00
|
|
|
Lock l(m_AuthedLinksMutex);
|
2018-09-07 20:36:06 +00:00
|
|
|
auto range = m_AuthedLinks.equal_range(remote);
|
|
|
|
auto itr = range.first;
|
|
|
|
while(itr != range.second)
|
|
|
|
{
|
|
|
|
itr->second->SendKeepAlive();
|
|
|
|
++itr;
|
|
|
|
}
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2019-02-01 01:58:06 +00:00
|
|
|
ILinkLayer::SendTo(const RouterID& remote, const llarp_buffer_t& buf)
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2018-09-18 20:56:22 +00:00
|
|
|
ILinkSession* s = nullptr;
|
2018-09-07 20:36:06 +00:00
|
|
|
{
|
2018-11-05 13:19:08 +00:00
|
|
|
Lock l(m_AuthedLinksMutex);
|
|
|
|
auto range = m_AuthedLinks.equal_range(remote);
|
|
|
|
auto itr = range.first;
|
|
|
|
// pick lowest backlog session
|
|
|
|
size_t min = std::numeric_limits< size_t >::max();
|
|
|
|
|
|
|
|
while(itr != range.second)
|
2018-09-18 20:56:22 +00:00
|
|
|
{
|
2018-11-05 13:19:08 +00:00
|
|
|
auto backlog = itr->second->SendQueueBacklog();
|
|
|
|
if(backlog < min)
|
|
|
|
{
|
|
|
|
s = itr->second.get();
|
|
|
|
min = backlog;
|
|
|
|
}
|
|
|
|
++itr;
|
2018-09-18 20:56:22 +00:00
|
|
|
}
|
2018-09-07 20:36:06 +00:00
|
|
|
}
|
2018-09-18 20:56:22 +00:00
|
|
|
return s && s->SendMessageBuffer(buf);
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ILinkLayer::GetOurAddressInfo(llarp::AddressInfo& addr) const
|
|
|
|
{
|
|
|
|
addr.dialect = Name();
|
|
|
|
addr.pubkey = TransportPubKey();
|
|
|
|
addr.rank = Rank();
|
|
|
|
addr.port = m_ourAddr.port();
|
|
|
|
addr.ip = *m_ourAddr.addr6();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const byte_t*
|
|
|
|
ILinkLayer::TransportPubKey() const
|
|
|
|
{
|
2018-09-04 12:55:20 +00:00
|
|
|
return llarp::seckey_topublic(TransportSecretKey());
|
|
|
|
}
|
|
|
|
|
2019-01-02 01:04:04 +00:00
|
|
|
const SecretKey&
|
2018-09-04 12:55:20 +00:00
|
|
|
ILinkLayer::TransportSecretKey() const
|
|
|
|
{
|
|
|
|
return m_SecretKey;
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
2018-12-17 20:46:08 +00:00
|
|
|
bool
|
|
|
|
ILinkLayer::GenEphemeralKeys()
|
|
|
|
{
|
|
|
|
return KeyGen(m_SecretKey);
|
|
|
|
}
|
|
|
|
|
2018-09-03 13:10:56 +00:00
|
|
|
bool
|
|
|
|
ILinkLayer::EnsureKeys(const char* f)
|
|
|
|
{
|
|
|
|
fs::path fpath(f);
|
|
|
|
llarp::SecretKey keys;
|
|
|
|
std::error_code ec;
|
|
|
|
if(!fs::exists(fpath, ec))
|
|
|
|
{
|
|
|
|
if(!KeyGen(m_SecretKey))
|
|
|
|
return false;
|
|
|
|
// generated new keys
|
|
|
|
if(!BEncodeWriteFile< decltype(keys), 128 >(f, m_SecretKey))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// load keys
|
|
|
|
if(!BDecodeReadFile(f, m_SecretKey))
|
2018-09-04 19:15:06 +00:00
|
|
|
{
|
|
|
|
llarp::LogError("Failed to load keyfile ", f);
|
2018-09-03 13:10:56 +00:00
|
|
|
return false;
|
2018-09-04 19:15:06 +00:00
|
|
|
}
|
2018-09-03 13:10:56 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-01-07 12:47:57 +00:00
|
|
|
bool
|
2018-09-10 13:43:36 +00:00
|
|
|
ILinkLayer::PutSession(ILinkSession* s)
|
2018-09-07 17:41:49 +00:00
|
|
|
{
|
2018-09-10 13:43:36 +00:00
|
|
|
Lock lock(m_PendingMutex);
|
2019-01-09 14:21:55 +00:00
|
|
|
llarp::Addr addr = s->GetRemoteEndpoint();
|
2019-01-13 16:30:07 +00:00
|
|
|
auto itr = m_Pending.find(addr);
|
2019-01-07 12:47:57 +00:00
|
|
|
if(itr != m_Pending.end())
|
|
|
|
return false;
|
2019-02-11 14:43:48 +00:00
|
|
|
m_Pending.emplace(addr, std::unique_ptr< ILinkSession >(s));
|
2019-01-07 12:47:57 +00:00
|
|
|
return true;
|
2018-09-07 17:41:49 +00:00
|
|
|
}
|
|
|
|
|
2018-09-03 13:10:56 +00:00
|
|
|
void
|
2018-10-29 16:48:36 +00:00
|
|
|
ILinkLayer::OnTick(uint64_t interval)
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2018-12-27 19:10:38 +00:00
|
|
|
auto now = Now();
|
|
|
|
Tick(now);
|
2018-09-03 13:10:56 +00:00
|
|
|
ScheduleTick(interval);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ILinkLayer::ScheduleTick(uint64_t interval)
|
|
|
|
{
|
2018-12-10 14:14:55 +00:00
|
|
|
tick_id = m_Logic->call_later({interval, this, &ILinkLayer::on_timer_tick});
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace llarp
|