lokinet/llarp/exit/endpoint.cpp

242 lines
6.5 KiB
C++
Raw Normal View History

#include "endpoint.hpp"
2019-06-18 01:19:39 +02:00
#include <llarp/handlers/exit.hpp>
#include <llarp/path/path_context.hpp>
#include <llarp/router/abstractrouter.hpp>
#include <llarp/quic/tunnel.hpp>
namespace llarp
{
namespace exit
{
Endpoint::Endpoint(
const llarp::PubKey& remoteIdent,
2021-04-07 14:52:17 +02:00
const llarp::path::HopHandler_ptr& beginPath,
bool rewriteIP,
huint128_t ip,
llarp::handlers::ExitEndpoint* parent)
2021-04-07 14:52:17 +02:00
: createdAt{parent->Now()}
, m_Parent{parent}
, m_remoteSignKey{remoteIdent}
, m_CurrentPath{beginPath}
, m_IP{ip}
, m_RewriteSource{rewriteIP}
2018-11-14 13:23:08 +01:00
{
2018-11-28 13:32:38 +01:00
m_LastActive = parent->Now();
2018-11-14 13:23:08 +01:00
}
Endpoint::~Endpoint()
{
2021-04-07 14:52:17 +02:00
if (m_CurrentPath)
m_Parent->DelEndpointInfo(m_CurrentPath->RXID());
2018-11-14 13:23:08 +01:00
}
2018-11-14 19:02:27 +01:00
void
Endpoint::Close()
{
m_Parent->RemoveExit(this);
}
2019-02-11 18:14:43 +01:00
util::StatusObject
Endpoint::ExtractStatus() const
2019-02-08 20:43:25 +01:00
{
auto now = m_Parent->Now();
2021-03-05 18:31:52 +01:00
util::StatusObject obj{
{"identity", m_remoteSignKey.ToString()},
{"ip", m_IP.ToString()},
{"txRate", m_TxRate},
{"rxRate", m_RxRate},
{"createdAt", to_json(createdAt)},
{"exiting", !m_RewriteSource},
{"looksDead", LooksDead(now)},
{"expiresSoon", ExpiresSoon(now)},
{"expired", IsExpired(now)}};
2019-02-11 18:14:43 +01:00
return obj;
2019-02-08 20:43:25 +01:00
}
2018-11-14 13:23:08 +01:00
bool
Endpoint::UpdateLocalPath(const llarp::PathID_t& nextPath)
{
if (!m_Parent->UpdateEndpointPath(m_remoteSignKey, nextPath))
2018-11-14 13:23:08 +01:00
return false;
2021-04-07 14:52:17 +02:00
const RouterID us{m_Parent->GetRouter()->pubkey()};
m_CurrentPath = m_Parent->GetRouter()->pathContext().GetByUpstream(us, nextPath);
2018-11-14 13:23:08 +01:00
return true;
}
2018-11-14 19:02:27 +01:00
void
Endpoint::Tick(llarp_time_t now)
{
(void)now;
m_RxRate = 0;
m_TxRate = 0;
}
bool
Endpoint::IsExpired(llarp_time_t now) const
{
auto path = GetCurrentPath();
if (path)
{
return path->Expired(now);
}
// if we don't have an underlying path we are considered expired
return true;
}
2018-11-14 19:02:27 +01:00
bool
Endpoint::ExpiresSoon(llarp_time_t now, llarp_time_t dlt) const
{
2021-04-08 12:59:12 +02:00
if (m_CurrentPath)
2021-04-07 15:20:59 +02:00
return m_CurrentPath->ExpiresSoon(now, dlt);
2018-11-14 19:02:27 +01:00
return true;
}
bool
Endpoint::LooksDead(llarp_time_t now, llarp_time_t timeout) const
2018-11-28 13:32:38 +01:00
{
if (ExpiresSoon(now, timeout))
2018-11-28 13:32:38 +01:00
return true;
auto path = GetCurrentPath();
2021-04-07 14:52:17 +02:00
if (not path)
return true;
auto lastPing = path->LastRemoteActivityAt();
if (lastPing == 0s || (now > lastPing && now - lastPing > timeout))
return now > m_LastActive && now - m_LastActive > timeout;
else if (lastPing > 0s) // NOLINT
2018-12-27 16:31:24 +01:00
return now > lastPing && now - lastPing > timeout;
2020-02-24 20:40:45 +01:00
return lastPing > 0s;
2018-11-28 13:32:38 +01:00
}
2018-11-14 13:23:08 +01:00
bool
Endpoint::QueueOutboundTraffic(
PathID_t path, std::vector<byte_t> buf, uint64_t counter, service::ProtocolType t)
2018-11-14 13:23:08 +01:00
{
const service::ConvoTag tag{path.as_array()};
2021-03-26 14:16:43 +01:00
if (t == service::ProtocolType::QUIC)
{
auto quic = m_Parent->GetQUICTunnel();
if (not quic)
return false;
m_TxRate += buf.size();
quic->receive_packet(tag, std::move(buf));
2021-04-07 12:51:44 +02:00
m_LastActive = m_Parent->Now();
2021-03-30 16:16:25 +02:00
return true;
}
2018-11-29 22:19:20 +01:00
// queue overflow
if (m_UpstreamQueue.size() > MaxUpstreamQueueSize)
2018-11-29 22:19:20 +01:00
return false;
llarp::net::IPPacket pkt{std::move(buf)};
if (pkt.empty())
2018-11-14 13:23:08 +01:00
return false;
if (pkt.IsV6() && m_Parent->SupportsV6())
2019-06-11 21:57:52 +02:00
{
huint128_t dst;
if (m_RewriteSource)
2019-06-11 21:57:52 +02:00
dst = m_Parent->GetIfAddr();
else
dst = pkt.dstv6();
2019-06-12 00:29:45 +02:00
pkt.UpdateIPv6Address(m_IP, dst);
2019-06-11 21:57:52 +02:00
}
else if (pkt.IsV4() && !m_Parent->SupportsV6())
2019-06-11 21:57:52 +02:00
{
huint32_t dst;
if (m_RewriteSource)
dst = net::TruncateV6(m_Parent->GetIfAddr());
2019-06-11 21:57:52 +02:00
else
dst = pkt.dstv4();
pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(m_IP)), xhtonl(dst));
2019-06-11 21:57:52 +02:00
}
2018-11-14 13:23:08 +01:00
else
2019-06-11 21:57:52 +02:00
{
return false;
}
m_TxRate += pkt.size();
m_UpstreamQueue.emplace(std::move(pkt), counter);
2018-11-28 13:32:38 +01:00
m_LastActive = m_Parent->Now();
2018-11-14 19:02:27 +01:00
return true;
2018-11-14 13:23:08 +01:00
}
bool
Endpoint::QueueInboundTraffic(std::vector<byte_t> buf, service::ProtocolType type)
{
if (type != service::ProtocolType::QUIC)
2021-03-26 14:57:28 +01:00
{
llarp::net::IPPacket pkt{std::move(buf)};
if (pkt.empty())
2021-03-26 14:57:28 +01:00
return false;
huint128_t src;
if (m_RewriteSource)
src = m_Parent->GetIfAddr();
else
src = pkt.srcv6();
if (pkt.IsV6())
pkt.UpdateIPv6Address(src, m_IP);
else
pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(src)), xhtonl(net::TruncateV6(m_IP)));
buf = pkt.steal();
2021-03-26 14:57:28 +01:00
}
2019-12-06 21:33:43 +01:00
const uint8_t queue_idx = buf.size() / llarp::routing::ExitPadSize;
if (m_DownstreamQueues.find(queue_idx) == m_DownstreamQueues.end())
2019-05-07 17:08:49 +02:00
m_DownstreamQueues.emplace(queue_idx, InboundTrafficQueue_t{});
2019-05-08 15:08:21 +02:00
auto& queue = m_DownstreamQueues.at(queue_idx);
if (queue.size() == 0)
{
queue.emplace_back();
queue.back().protocol = type;
return queue.back().PutBuffer(std::move(buf), m_Counter++);
}
auto& msg = queue.back();
if (msg.Size() + buf.size() > llarp::routing::ExitPadSize)
2018-11-29 14:12:35 +01:00
{
queue.emplace_back();
queue.back().protocol = type;
return queue.back().PutBuffer(std::move(buf), m_Counter++);
2018-11-29 14:12:35 +01:00
}
msg.protocol = type;
return msg.PutBuffer(std::move(buf), m_Counter++);
2018-11-28 17:38:20 +01:00
}
bool
2018-11-29 22:19:20 +01:00
Endpoint::Flush()
2018-11-28 17:38:20 +01:00
{
2018-11-29 22:19:20 +01:00
// flush upstream queue
while (m_UpstreamQueue.size())
2018-11-29 22:19:20 +01:00
{
m_Parent->QueueOutboundTraffic(
const_cast<net::IPPacket&>(m_UpstreamQueue.top().pkt).steal());
2018-11-29 22:19:20 +01:00
m_UpstreamQueue.pop();
}
// flush downstream queue
2018-11-28 17:38:20 +01:00
auto path = GetCurrentPath();
bool sent = path != nullptr;
if (path)
2018-11-28 17:38:20 +01:00
{
for (auto& item : m_DownstreamQueues)
2018-11-28 17:38:20 +01:00
{
auto& queue = item.second;
while (queue.size())
2018-11-28 17:38:20 +01:00
{
auto& msg = queue.front();
msg.S = path->NextSeqNo();
if (path->SendRoutingMessage(msg, m_Parent->GetRouter()))
{
m_RxRate += msg.Size();
sent = true;
}
queue.pop_front();
2018-11-28 17:38:20 +01:00
}
}
}
for (auto& item : m_DownstreamQueues)
item.second.clear();
2018-11-28 17:38:20 +01:00
return sent;
}
} // namespace exit
} // namespace llarp