wire up snode traffic to quic

pull/1576/head
Jeff Becker 3 years ago
parent 58bec09232
commit 59891d5d5f
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -0,0 +1,48 @@
#pragma once
#include "llarp/service/address.hpp"
#include "llarp/service/convotag.hpp"
#include "llarp/service/protocol_type.hpp"
#include "router_id.hpp"
#include "ev/ev.hpp"
#include <functional>
#include <memory>
#include <string>
#include <optional>
#include "oxenmq/variant.h"
namespace llarp
{
class EndpointBase
{
public:
virtual ~EndpointBase() = default;
using AddressVariant_t = std::variant<service::Address, RouterID>;
virtual std::optional<AddressVariant_t>
GetEndpointWithConvoTag(service::ConvoTag tag) const = 0;
virtual std::optional<service::ConvoTag>
GetBestConvoTagFor(AddressVariant_t addr) const = 0;
virtual bool
EnsurePathTo(
AddressVariant_t addr,
std::function<void(std::optional<service::ConvoTag>)> hook,
llarp_time_t timeout) = 0;
virtual void
LookupNameAsync(
std::string name, std::function<void(std::optional<AddressVariant_t>)> resultHandler) = 0;
virtual const EventLoop_ptr&
Loop() = 0;
virtual bool
SendToOrQueue(
service::ConvoTag tag, const llarp_buffer_t& payload, service::ProtocolType t) = 0;
};
} // namespace llarp

@ -108,8 +108,10 @@ namespace llarp
}
bool
Endpoint::QueueOutboundTraffic(ManagedBuffer buf, uint64_t counter)
Endpoint::QueueOutboundTraffic(ManagedBuffer buf, uint64_t counter, service::ProtocolType t)
{
if (t == service::ProtocolType::QUIC)
return false;
// queue overflow
if (m_UpstreamQueue.size() > MaxUpstreamQueueSize)
return false;

@ -3,6 +3,7 @@
#include <llarp/crypto/types.hpp>
#include <llarp/net/ip_packet.hpp>
#include <llarp/path/path.hpp>
#include <llarp/service/protocol_type.hpp>
#include <llarp/util/time.hpp>
#include <queue>
@ -65,7 +66,7 @@ namespace llarp
/// queue outbound traffic
/// does ip rewrite here
bool
QueueOutboundTraffic(ManagedBuffer pkt, uint64_t counter);
QueueOutboundTraffic(ManagedBuffer pkt, uint64_t counter, service::ProtocolType t);
/// update local path id and cascade information to parent
/// return true if success

@ -4,6 +4,7 @@
#include <llarp/nodedb.hpp>
#include <llarp/path/path_context.hpp>
#include <llarp/path/path.hpp>
#include <llarp/quic/tunnel.hpp>
#include <llarp/router/abstractrouter.hpp>
#include <llarp/util/meta/memfn.hpp>
#include <utility>
@ -18,13 +19,14 @@ namespace llarp
AbstractRouter* r,
size_t numpaths,
size_t hoplen,
bool bundleRC)
: llarp::path::Builder(r, numpaths, hoplen)
, m_ExitRouter(routerId)
, m_WritePacket(std::move(writepkt))
, m_Counter(0)
, m_LastUse(r->Now())
, m_BundleRC(bundleRC)
quic::TunnelManager* quictun)
: llarp::path::Builder{r, numpaths, hoplen}
, m_ExitRouter{routerId}
, m_WritePacket{std::move(writepkt)}
, m_Counter{0}
, m_LastUse{r->Now()}
, m_BundleRC{false}
, m_QUIC{quictun}
{
CryptoManager::instance()->identity_keygen(m_ExitIdentity);
}
@ -180,8 +182,21 @@ namespace llarp
}
bool
BaseSession::HandleTraffic(llarp::path::Path_ptr, const llarp_buffer_t& buf, uint64_t counter)
BaseSession::HandleTraffic(
llarp::path::Path_ptr path,
const llarp_buffer_t& buf,
uint64_t counter,
service::ProtocolType t)
{
if (t == service::ProtocolType::QUIC)
{
if (buf.sz < 4 or not m_QUIC)
return false;
service::ConvoTag tag{path->TXID().as_array()};
m_QUIC->receive_packet(tag, buf);
return true;
}
if (m_WritePacket)
{
llarp::net::IPPacket pkt;
@ -321,8 +336,8 @@ namespace llarp
size_t numpaths,
size_t hoplen,
bool useRouterSNodeKey,
bool bundleRC)
: BaseSession(snodeRouter, writepkt, r, numpaths, hoplen, bundleRC)
quic::TunnelManager* quictun)
: BaseSession{snodeRouter, writepkt, r, numpaths, hoplen, quictun}
{
if (useRouterSNodeKey)
{

@ -12,6 +12,11 @@
namespace llarp
{
namespace quic
{
class TunnelManager;
}
namespace exit
{
struct BaseSession;
@ -34,7 +39,7 @@ namespace llarp
AbstractRouter* r,
size_t numpaths,
size_t hoplen,
bool bundleRC);
quic::TunnelManager* quictun);
~BaseSession() override;
@ -131,7 +136,11 @@ namespace llarp
HandleGotExit(llarp::path::Path_ptr p, llarp_time_t b);
bool
HandleTraffic(llarp::path::Path_ptr p, const llarp_buffer_t& buf, uint64_t seqno);
HandleTraffic(
llarp::path::Path_ptr p,
const llarp_buffer_t& buf,
uint64_t seqno,
service::ProtocolType t);
private:
std::set<RouterID> m_SnodeBlacklist;
@ -160,6 +169,7 @@ namespace llarp
std::vector<SessionReadyFunc> m_PendingCallbacks;
const bool m_BundleRC;
quic::TunnelManager* const m_QUIC;
void
CallPendingCallbacks(bool success);
@ -173,8 +183,8 @@ namespace llarp
AbstractRouter* r,
size_t numpaths,
size_t hoplen,
bool bundleRC)
: BaseSession(snodeRouter, writepkt, r, numpaths, hoplen, bundleRC)
quic::TunnelManager* quictun)
: BaseSession{snodeRouter, writepkt, r, numpaths, hoplen, quictun}
{}
~ExitSession() override = default;
@ -204,7 +214,7 @@ namespace llarp
size_t numpaths,
size_t hoplen,
bool useRouterSNodeKey,
bool bundleRC);
quic::TunnelManager* quictun);
~SNodeSession() override = default;

@ -7,6 +7,8 @@
#include <llarp/util/str.hpp>
#include <llarp/util/bits.hpp>
#include <llarp/quic/tunnel.hpp>
#include <cassert>
#include "service/protocol_type.hpp"
@ -19,14 +21,114 @@ namespace llarp
, m_Resolver(std::make_shared<dns::Proxy>(r->loop(), this))
, m_Name(std::move(name))
, m_LocalResolverAddr("127.0.0.1", 53)
, m_QUIC{std::make_shared<quic::TunnelManager>(*this)}
, m_InetToNetwork(name + "_exit_rx", r->loop(), r->loop())
{
m_ShouldInitTun = true;
m_QUIC = std::make_shared<quic::TunnelManager>(*this);
}
ExitEndpoint::~ExitEndpoint() = default;
void
ExitEndpoint::LookupNameAsync(
std::string, std::function<void(std::optional<AddressVariant_t>)> resultHandler)
{
// TODO: implement me
resultHandler(std::nullopt);
}
std::optional<EndpointBase::AddressVariant_t>
ExitEndpoint::GetEndpointWithConvoTag(service::ConvoTag tag) const
{
for (const auto& [rid, session] : m_SNodeSessions)
{
PathID_t pathID{tag.as_array()};
if (session->GetPathByID(pathID))
return rid;
}
return std::nullopt;
}
std::optional<service::ConvoTag>
ExitEndpoint::GetBestConvoTagFor(AddressVariant_t addr) const
{
if (auto* rid = std::get_if<RouterID>(&addr))
{
auto itr = m_SNodeSessions.find(*rid);
if (itr == m_SNodeSessions.end())
return std::nullopt;
if (auto path = itr->second->GetPathByRouter(*rid))
{
return service::ConvoTag{path->TXID().as_array()};
}
return std::nullopt;
}
else
return std::nullopt;
}
const EventLoop_ptr&
ExitEndpoint::Loop()
{
return m_Router->loop();
}
bool
ExitEndpoint::SendToOrQueue(
service::ConvoTag tag, const llarp_buffer_t& payload, service::ProtocolType type)
{
if (auto maybeAddr = GetEndpointWithConvoTag(tag))
{
if (std::holds_alternative<service::Address>(*maybeAddr))
return false;
if (auto* rid = std::get_if<RouterID>(&*maybeAddr))
{
std::vector<byte_t> data{};
data.resize(payload.sz);
std::copy_n(payload.base, data.size(), data.data());
ObtainSNodeSession(*rid, [data, type](auto session) {
if (session and session->IsReady())
{
session->SendPacketToRemote(data, type);
}
});
}
return true;
}
else
return false;
}
bool
ExitEndpoint::EnsurePathTo(
AddressVariant_t addr,
std::function<void(std::optional<service::ConvoTag>)> hook,
llarp_time_t)
{
if (std::holds_alternative<service::Address>(addr))
return false;
if (auto* rid = std::get_if<RouterID>(&addr))
{
ObtainSNodeSession(
*rid, [hook, routerID = *rid](std::shared_ptr<exit::BaseSession> session) {
if (session and session->IsReady())
{
if (auto path = session->GetPathByRouter(routerID))
{
hook(service::ConvoTag{path->TXID().as_array()});
}
else
hook(std::nullopt);
}
else
hook(std::nullopt);
});
}
return true;
}
util::StatusObject
ExitEndpoint::ExtractStatus() const
{
@ -236,7 +338,6 @@ namespace llarp
auto itr = m_SNodeSessions.find(pk);
if (itr != m_SNodeSessions.end())
{
// TODO: quic (?)
itr->second->SendPacketToRemote(pkt.ConstBuffer(), service::ProtocolType::TrafficV4);
return;
}
@ -576,13 +677,19 @@ namespace llarp
2,
1,
true,
false);
GetQUICTunnel());
// this is a new service node make an outbound session to them
m_SNodeSessions.emplace(other, session);
}
return ip;
}
quic::TunnelManager*
ExitEndpoint::GetQUICTunnel()
{
return m_QUIC.get();
}
bool
ExitEndpoint::AllocateNewExit(const PubKey pk, const PathID_t& path, bool wantInternet)
{

@ -10,11 +10,35 @@ namespace llarp
struct AbstractRouter;
namespace handlers
{
struct ExitEndpoint : public dns::IQueryHandler
struct ExitEndpoint : public dns::IQueryHandler, public EndpointBase
{
ExitEndpoint(std::string name, AbstractRouter* r);
~ExitEndpoint() override;
std::optional<AddressVariant_t>
GetEndpointWithConvoTag(service::ConvoTag tag) const override;
std::optional<service::ConvoTag>
GetBestConvoTagFor(AddressVariant_t addr) const override;
bool
EnsurePathTo(
AddressVariant_t addr,
std::function<void(std::optional<service::ConvoTag>)> hook,
llarp_time_t timeout) override;
void
LookupNameAsync(
std::string name,
std::function<void(std::optional<AddressVariant_t>)> resultHandler) override;
const EventLoop_ptr&
Loop() override;
bool
SendToOrQueue(
service::ConvoTag tag, const llarp_buffer_t& payload, service::ProtocolType t) override;
void
Tick(llarp_time_t now);
@ -104,6 +128,9 @@ namespace llarp
void
Flush();
quic::TunnelManager*
GetQUICTunnel();
private:
huint128_t
GetIPForIdent(const PubKey pk);
@ -168,6 +195,8 @@ namespace llarp
IpAddress m_LocalResolverAddr;
std::vector<IpAddress> m_UpstreamResolvers;
std::shared_ptr<quic::TunnelManager> m_QUIC;
using Pkt_t = net::IPPacket;
using PacketQueue_t = util::CoDelQueue<
Pkt_t,

@ -823,7 +823,8 @@ namespace llarp
if (pkt.size() <= 8)
return false;
uint64_t counter = bufbe64toh(pkt.data());
if (m_ExitTrafficHandler(self, llarp_buffer_t(pkt.data() + 8, pkt.size() - 8), counter))
if (m_ExitTrafficHandler(
self, llarp_buffer_t(pkt.data() + 8, pkt.size() - 8), counter, msg.protocol))
{
MarkActive(r->Now());
EnterState(ePathEstablished, r->Now());

@ -80,7 +80,8 @@ namespace llarp
using DataHandlerFunc = std::function<bool(Path_ptr, const service::ProtocolFrame&)>;
using ExitUpdatedFunc = std::function<bool(Path_ptr)>;
using ExitClosedFunc = std::function<bool(Path_ptr)>;
using ExitTrafficHandlerFunc = std::function<bool(Path_ptr, const llarp_buffer_t&, uint64_t)>;
using ExitTrafficHandlerFunc =
std::function<bool(Path_ptr, const llarp_buffer_t&, uint64_t, service::ProtocolType)>;
/// (path, backoff) backoff is 0 on success
using ObtainedExitHandler = std::function<bool(Path_ptr, llarp_time_t)>;

@ -6,7 +6,9 @@
namespace llarp
{
struct PathID_t final : public AlignedBuffer<PATHIDSIZE>
{};
{
using AlignedBuffer<PATHIDSIZE>::AlignedBuffer;
};
} // namespace llarp

@ -416,7 +416,7 @@ namespace llarp
continue;
uint64_t counter = bufbe64toh(pkt.data());
sent &= endpoint->QueueOutboundTraffic(
ManagedBuffer(llarp_buffer_t(pkt.data() + 8, pkt.size() - 8)), counter);
ManagedBuffer(llarp_buffer_t(pkt.data() + 8, pkt.size() - 8)), counter, msg.protocol);
}
return sent;
}

@ -13,7 +13,7 @@
namespace llarp::quic
{
Client::Client(service::Endpoint& ep, const SockAddr& remote, uint16_t pseudo_port) : Endpoint{ep}
Client::Client(EndpointBase& ep, const SockAddr& remote, uint16_t pseudo_port) : Endpoint{ep}
{
default_stream_buffer_size =
0; // We steal uvw's provided buffers so don't need an outgoing data buffer

@ -1,7 +1,7 @@
#pragma once
#include "endpoint.hpp"
#include "service/endpoint.hpp"
#include "llarp/endpoint_base.hpp"
#include <optional>
@ -20,7 +20,7 @@ namespace llarp::quic
// `remote.getPort()` on the remote's lokinet address. `pseudo_port` is *our* unique local
// identifier which we include in outgoing packets (so that the remote server knows where to
// send the back to *this* client).
Client(service::Endpoint& ep, const SockAddr& remote, uint16_t pseudo_port);
Client(EndpointBase& ep, const SockAddr& remote, uint16_t pseudo_port);
// Returns a reference to the client's connection to the server. Returns a nullptr if there is
// no connection.

@ -331,6 +331,7 @@ namespace llarp::quic
#pragma GCC diagnostic pop
} // namespace
#if 0
#ifndef NDEBUG
extern "C" inline void
ngtcp_trace_logger([[maybe_unused]] void* user_data, const char* fmt, ...)
@ -344,6 +345,7 @@ namespace llarp::quic
}
va_end(ap);
}
#endif
#endif
io_result
@ -409,9 +411,10 @@ namespace llarp::quic
cb.update_key = update_key;
ngtcp2_settings_default(&settings);
#if 0
#ifndef NDEBUG
settings.log_printf = ngtcp_trace_logger;
#endif
#endif
settings.initial_ts = get_timestamp();
// FIXME: IPv6

@ -22,7 +22,7 @@ extern "C"
namespace llarp::quic
{
Endpoint::Endpoint(service::Endpoint& ep) : service_endpoint{ep}
Endpoint::Endpoint(EndpointBase& ep) : service_endpoint{ep}
{
randombytes_buf(static_secret.data(), static_secret.size());

@ -18,10 +18,10 @@
#include <uvw/async.h>
#include <uvw/timer.h>
namespace llarp::service
namespace llarp
{
struct Endpoint;
} // namespace llarp::service
class EndpointBase;
} // namespace llarp
namespace llarp::quic
{
@ -51,7 +51,7 @@ namespace llarp::quic
protected:
/// the service endpoint we are owned by
service::Endpoint& service_endpoint;
EndpointBase& service_endpoint;
/// local "address" is the IPv6 unspecified address since we don't have (or care about) the
/// actual local address for building quic packets. The port of this address must be set to our
@ -105,7 +105,7 @@ namespace llarp::quic
friend class Connection;
explicit Endpoint(service::Endpoint& service_endpoint_);
explicit Endpoint(EndpointBase& service_endpoint_);
virtual ~Endpoint();

@ -1,7 +1,7 @@
#pragma once
#include "endpoint.hpp"
#include "llarp/endpoint_base.hpp"
#include <functional>
namespace llarp::quic
@ -11,7 +11,7 @@ namespace llarp::quic
public:
using stream_open_callback_t = std::function<bool(Stream& stream, uint16_t port)>;
Server(service::Endpoint& service_endpoint) : Endpoint{service_endpoint}
Server(EndpointBase& service_endpoint) : Endpoint{service_endpoint}
{}
// Stream callback: takes the server, the (just-created) stream, and the connection port.

@ -184,7 +184,7 @@ namespace llarp::quic
} // namespace
TunnelManager::TunnelManager(service::Endpoint& se) : service_endpoint_{se}
TunnelManager::TunnelManager(EndpointBase& se) : service_endpoint_{se}
{
// Cleanup callback to clear out closed tunnel connections
service_endpoint_.Loop()->call_every(500ms, timer_keepalive_, [this] {

@ -1,6 +1,6 @@
#pragma once
#include <llarp/service/endpoint.hpp>
#include <llarp/endpoint_base.hpp>
#include "stream.hpp"
#include "address.hpp"
#include "client.hpp"
@ -49,7 +49,7 @@ namespace llarp::quic
// includes the resolution time.
std::chrono::milliseconds open_timeout = 10s;
TunnelManager(service::Endpoint& endpoint);
TunnelManager(EndpointBase& endpoint);
/// Adds an incoming listener callback. When a new incoming quic connection is initiated to us
/// by some remote we invoke these callback(s) in order of registration. Each one has three
@ -132,7 +132,7 @@ namespace llarp::quic
receive_packet(const service::ConvoTag& tag, const llarp_buffer_t& buf);
private:
service::Endpoint& service_endpoint_;
EndpointBase& service_endpoint_;
struct ClientTunnel
{

@ -9,6 +9,8 @@ namespace llarp::service
{
struct ConvoTag final : AlignedBuffer<16>
{
using AlignedBuffer<16>::AlignedBuffer;
void
Randomize() override;

@ -1304,7 +1304,7 @@ namespace llarp
numDesiredPaths,
numHops,
false,
ShouldBundleRC());
GetQUICTunnel());
m_state->m_SNodeSessions.emplace(snode, std::make_pair(session, tag));
}

@ -23,6 +23,7 @@
#include <variant>
#include <oxenmq/variant.h>
#include "endpoint_types.hpp"
#include "llarp/endpoint_base.hpp"
#include "auth.hpp"
@ -55,7 +56,10 @@ namespace llarp
static constexpr auto INTROSET_LOOKUP_RETRY_COOLDOWN = 3s;
struct Endpoint : public path::Builder, public ILookupHolder, public IDataHandler
struct Endpoint : public path::Builder,
public ILookupHolder,
public IDataHandler,
public EndpointBase
{
static const size_t MAX_OUTBOUND_CONTEXT_COUNT = 4;

Loading…
Cancel
Save