fix and format.

* start moving quic code to use lokinet internals
pull/1576/head
Jeff Becker 3 years ago
parent 39d31df059
commit 4446f2fc16
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -12,6 +12,14 @@
namespace llarp::uv
{
std::shared_ptr<uvw::Loop>
Loop::MaybeGetLoop(const EventLoop_ptr& ptr)
{
if (auto* uv = dynamic_cast<Loop*>(ptr.get()))
return uv->m_Impl;
return nullptr;
}
class UVWakeup final : public EventLoopWakeup
{
std::shared_ptr<uvw::AsyncHandle> async;

@ -71,6 +71,9 @@ namespace llarp::uv
std::function<void(void)> PumpLL;
static std::shared_ptr<uvw::Loop>
MaybeGetLoop(const EventLoop_ptr&);
bool
inEventLoop() const override;

@ -1,46 +1,39 @@
#include "address.hpp"
extern "C"
{
#include <arpa/inet.h>
}
#include <netinet/in.h>
#include <cstring>
#include <iostream>
namespace llarp::quic
{
using namespace std::literals;
Address::Address(std::array<uint8_t, 4> ip, uint16_t port)
{
s.in.sin_family = AF_INET;
std::memcpy(&s.in.sin_addr.s_addr, ip.data(), ip.size());
s.in.sin_port = htons(port);
a.addrlen = sizeof(s.in);
}
Address::Address(service::ConvoTag tag) : saddr{tag.ToV6()}
{}
Address::Address(const sockaddr_any* addr, size_t addrlen)
{
assert(addrlen == sizeof(sockaddr_in)); // FIXME: IPv6 support
std::memmove(&s, addr, addrlen);
a.addrlen = addrlen;
}
Address&
Address::operator=(const Address& addr)
Address::operator=(const Address& other)
{
std::memmove(&s, &addr.s, sizeof(s));
a.addrlen = addr.a.addrlen;
std::memmove(&saddr, &other.saddr, sizeof(saddr));
a.addrlen = other.a.addrlen;
return *this;
}
service::ConvoTag
Address::Tag() const
{
service::ConvoTag tag{};
tag.FromV6(saddr);
return tag;
}
std::string
Address::to_string() const
{
if (a.addrlen != sizeof(sockaddr_in))
if (a.addrlen != sizeof(sockaddr_in6))
return "(unknown-addr)";
char buf[INET_ADDRSTRLEN] = {0};
inet_ntop(AF_INET, &s.in.sin_addr, buf, INET_ADDRSTRLEN);
return buf + ":"s + std::to_string(ntohs(s.in.sin_port));
char buf[INET6_ADDRSTRLEN] = {0};
inet_ntop(AF_INET6, &saddr.sin6_addr, buf, INET6_ADDRSTRLEN);
return buf;
}
std::ostream&

@ -3,18 +3,14 @@
#include <array>
#include <cassert>
#include <cstring>
#include <memory>
#include <string>
#include <iosfwd>
#include <ngtcp2/ngtcp2.h>
extern "C"
{
#include <netinet/in.h>
#include <sys/socket.h>
}
// FIXME: replace use of this with a llarp::SockAddr
#include <llarp/net/sock_addr.hpp>
#include <llarp/service/convotag.hpp>
namespace llarp::quic
{
@ -28,44 +24,50 @@ namespace llarp::quic
class Address
{
sockaddr_any s{};
ngtcp2_addr a{0, &s.sa, nullptr};
sockaddr_in6 saddr{};
ngtcp2_addr a{0, reinterpret_cast<sockaddr*>(&saddr), nullptr};
public:
Address() = default;
Address(std::array<uint8_t, 4> ip, uint16_t port);
Address(const sockaddr_any* addr, size_t addrlen);
Address(const Address& addr)
Address(service::ConvoTag tag);
Address(const Address& other)
{
*this = addr;
*this = other;
}
service::ConvoTag
Tag() const;
Address&
operator=(const Address& addr);
operator=(const Address&);
// Implicit conversion to sockaddr* and ngtcp2_addr& so that an Address can be passed wherever
// one of those is expected.
operator sockaddr*()
{
return a.addr;
return reinterpret_cast<sockaddr*>(&saddr);
}
operator const sockaddr*() const
{
return a.addr;
}
constexpr socklen_t
sockaddr_size() const
{
return a.addrlen;
return reinterpret_cast<const sockaddr*>(&saddr);
}
operator ngtcp2_addr&()
{
return a;
}
operator const ngtcp2_addr&() const
{
return a;
}
size_t
sockaddr_size() const
{
return sizeof(sockaddr_in6);
}
std::string
to_string() const;
};
@ -76,7 +78,7 @@ namespace llarp::quic
struct Path
{
private:
Address local_{}, remote_{};
Address local_, remote_;
public:
ngtcp2_path path{
@ -87,12 +89,10 @@ namespace llarp::quic
const Address& remote = remote_;
Path() = default;
Path(const Address& local, const Address& remote) : local_{local}, remote_{remote}
{}
Path(const Address& local, const sockaddr_any* remote_addr, size_t remote_len)
: local_{local}, remote_{remote_addr, remote_len}
Path(const Address& laddr, const Address& raddr) : local_{laddr}, remote_{raddr}
{}
Path(const Path& p) : local_{p.local_}, remote_{p.remote_}
Path(const Path& p) : Path{p.local, p.remote}
{}
Path&
@ -120,6 +120,7 @@ namespace llarp::quic
std::ostream&
operator<<(std::ostream& o, const Address& a);
std::ostream&
operator<<(std::ostream& o, const Path& p);

@ -4,17 +4,18 @@
#include <llarp/util/logging/logger.hpp>
#include <oxenmq/variant.h>
#include <llarp/service/address.hpp>
#include <llarp/service/endpoint.hpp>
#include <llarp/ev/ev_libuv.hpp>
namespace llarp::quic
{
Client::Client(
Address remote,
std::shared_ptr<uvw::Loop> loop_,
uint16_t tunnel_port,
std::optional<Address> local_)
: Endpoint{std::move(local_), std::move(loop_)}
Client::Client(service::ConvoTag tag, service::Endpoint* parent, uint16_t tunnel_port)
: Endpoint{parent, uv::Loop::MaybeGetLoop(parent->Loop())}
{
// Our UDP socket is now set up, so now we initiate contact with the remote QUIC
Address remote{std::move(tag)};
Path path{local, remote};
llarp::LogDebug("Connecting to ", remote);
@ -32,8 +33,7 @@ namespace llarp::quic
//
// - delay_stream_timer
auto connptr =
std::make_shared<Connection>(*this, ConnectionID::random(), path, tunnel_port);
auto connptr = std::make_shared<Connection>(*this, ConnectionID::random(), path, tunnel_port);
auto& conn = *connptr;
conns.emplace(conn.base_cid, connptr);

@ -12,11 +12,7 @@ namespace llarp::quic
// Constructs a client that establishes an outgoing connection to `remote` to tunnel packets to
// `tunnel_port` on the remote's lokinet address. `local` can be used to optionally bind to a
// local IP and/or port for the connection.
Client(
Address remote,
std::shared_ptr<uvw::Loop> loop,
uint16_t tunnel_port,
std::optional<Address> local = std::nullopt);
Client(service::ConvoTag remote, service::Endpoint* parent, uint16_t tunnel_port);
// Returns a reference to the client's connection to the server. Returns a nullptr if there is
// no connection.

@ -17,7 +17,8 @@
#include <oxenmq/hex.h>
#include <oxenmq/bt_serialize.h>
extern "C" {
extern "C"
{
#include <sodium/randombytes.h>
}
@ -36,11 +37,13 @@ namespace llarp::quic
return o << oxenmq::to_hex(c.data, c.data + c.datalen);
}
ConnectionID ConnectionID::random(size_t size) {
ConnectionID r;
r.datalen = std::min(size, ConnectionID::max_size());
randombytes_buf(r.data, r.datalen);
return r;
ConnectionID
ConnectionID::random(size_t size)
{
ConnectionID r;
r.datalen = std::min(size, ConnectionID::max_size());
randombytes_buf(r.data, r.datalen);
return r;
}
namespace
@ -322,7 +325,8 @@ namespace llarp::quic
{
va_list ap;
va_start(ap, fmt);
if (char* msg; vasprintf(&msg, sizeof(ngtcp_debug_out), fmt, ap) >= 0) {
if (char* msg; vasprintf(&msg, sizeof(ngtcp_debug_out), fmt, ap) >= 0)
{
LogTraceExplicit("external/ngtcp2/*.c", 0, msg);
std::free(msg);
}
@ -341,33 +345,8 @@ namespace llarp::quic
{
LogDebug("Sending packet: ", buffer_printer{send_data});
rv = endpoint.send_packet(path.remote, send_data, send_pkt_info.ecn);
if (rv.blocked())
{
if (!wpoll)
{
wpoll = endpoint.loop->resource<uvw::PollHandle>(endpoint.socket_fd());
wpoll->on<uvw::PollEvent>([this](const auto&, auto&) { send(); });
}
if (!wpoll_active)
{
wpoll->start(uvw::PollHandle::Event::WRITABLE);
wpoll_active = true;
}
}
else if (!rv)
{
// FIXME: disconnect here?
LogWarn("packet send failed: ", rv.str());
LogError("FIXME - should disconnect");
}
else if (wpoll_active)
{
wpoll->stop();
wpoll_active = false;
}
}
return rv;
// We succeeded
//
// FIXME2: probably don't want to do these things *here*, because this is called from the stream
@ -546,8 +525,6 @@ namespace llarp::quic
Connection::~Connection()
{
if (wpoll)
wpoll->close();
if (io_trigger)
io_trigger->close();
}
@ -581,7 +558,8 @@ namespace llarp::quic
if (!ts)
ts = get_timestamp();
LogTrace("send_buffer size=", send_buffer.size(), ", datalen=", datalen, ", flags=", flags);
LogTrace(
"send_buffer size=", send_buffer.size(), ", datalen=", datalen, ", flags=", flags);
nwrite = ngtcp2_conn_writev_stream(
conn.get(),
&path.path,
@ -1134,7 +1112,8 @@ namespace llarp::quic
if (rv == 0)
{
rv = ngtcp2_conn_set_remote_transport_params(*this, &params);
LogDebug("Set remote transport params ", rv == 0 ? "success" : "fail: "s + ngtcp2_strerror(rv));
LogDebug(
"Set remote transport params ", rv == 0 ? "success" : "fail: "s + ngtcp2_strerror(rv));
}
if (rv != 0)

@ -12,7 +12,8 @@
#include <unordered_set>
#include <map>
extern "C" {
extern "C"
{
#include <ngtcp2/ngtcp2.h>
#include <sodium/randombytes.h>
}
@ -133,10 +134,6 @@ namespace llarp::quic
io_result
send();
// Poll for writability; activated if we block while trying to send a packet.
std::shared_ptr<uvw::PollHandle> wpoll;
bool wpoll_active = false;
// Internal base method called invoked during construction to set up common client/server
// settings. dest_cid and path must already be set.
std::tuple<ngtcp2_settings, ngtcp2_transport_params, ngtcp2_callbacks>

@ -1,8 +1,10 @@
#include "endpoint.hpp"
#include "client.hpp"
#include "server.hpp"
#include "uvw/async.h"
#include <llarp/crypto/crypto.hpp>
#include <llarp/util/logging/buffer.hpp>
#include <llarp/service/endpoint.hpp>
#include <iostream>
#include <random>
@ -19,69 +21,11 @@ extern "C"
namespace llarp::quic
{
Endpoint::Endpoint(std::optional<Address> addr, std::shared_ptr<uvw::Loop> loop_)
: loop{std::move(loop_)}
Endpoint::Endpoint(service::Endpoint* parent_, std::shared_ptr<uvw::Loop> loop_)
: parent{parent_}, loop{std::move(loop_)}
{
randombytes_buf(static_secret.data(), static_secret.size());
// Create and bind the UDP socket. We can't use libuv's UDP socket here because it doesn't
// give us the ability to set up the ECN field as QUIC requires.
auto fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
if (fd == -1)
throw std::runtime_error{"Failed to open socket: "s + strerror(errno)};
if (addr)
{
assert(addr->sockaddr_size() == sizeof(sockaddr_in)); // FIXME: IPv4-only for now
auto rv = bind(fd, *addr, addr->sockaddr_size());
if (rv == -1)
throw std::runtime_error{
"Failed to bind UDP socket to " + addr->to_string() + ": " + strerror(errno)};
}
// Get our address via the socket in case `addr` is using anyaddr/anyport.
sockaddr_any sa;
socklen_t salen = sizeof(sa);
// FIXME: if I didn't call bind above then do I need to call bind() before this (with
// anyaddr/anyport)?
getsockname(fd, &sa.sa, &salen);
assert(salen == sizeof(sockaddr_in)); // FIXME: IPv4-only for now
local = {&sa, salen};
LogDebug("Bound to ", local, addr ? "" : " (auto-selected)");
// Set up the socket to provide us with incoming ECN (IP_TOS) info
// NB: This is for IPv4; on AF_INET6 this would be IPPROTO_IPV6, IPV6_RECVTCLASS
if (uint8_t want_tos = 1;
- 1
== setsockopt(
fd, IPPROTO_IP, IP_RECVTOS, &want_tos, static_cast<socklen_t>(sizeof(want_tos))))
throw std::runtime_error{"Failed to set ECN on socket: "s + strerror(errno)};
// Wire up our recv buffer structures into what recvmmsg() wants
buf.resize(max_buf_size * msgs.size());
for (size_t i = 0; i < msgs.size(); i++)
{
auto& iov = msgs_iov[i];
iov.iov_base = buf.data() + max_buf_size * i;
iov.iov_len = max_buf_size;
#ifdef LOKINET_HAVE_RECVMMSG
auto& mh = msgs[i].msg_hdr;
#else
auto& mh = msgs[i];
#endif
mh.msg_name = &msgs_addr[i];
mh.msg_namelen = sizeof(msgs_addr[i]);
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
mh.msg_control = msgs_cmsg[i].data();
mh.msg_controllen = msgs_cmsg[i].size();
}
// Let uv do its stuff
poll = loop->resource<uvw::PollHandle>(fd);
poll->on<uvw::PollEvent>([this](const auto&, auto&) { on_readable(); });
poll->start(uvw::PollHandle::Event::READABLE);
// Set up a callback every 250ms to clean up stale sockets, etc.
expiry_timer = loop->resource<uvw::TimerHandle>();
expiry_timer->on<uvw::TimerEvent>([this](const auto&, auto&) { check_timeouts(); });
@ -92,101 +36,10 @@ namespace llarp::quic
Endpoint::~Endpoint()
{
if (poll)
poll->close();
if (expiry_timer)
expiry_timer->close();
}
int
Endpoint::socket_fd() const
{
return poll->fd();
}
void
Endpoint::on_readable()
{
LogDebug("poll callback on readable");
#ifdef LOKINET_HAVE_RECVMMSG
// NB: recvmmsg is linux-specific but ought to offer some performance benefits
int n_msg = recvmmsg(socket_fd(), msgs.data(), msgs.size(), 0, nullptr);
if (n_msg == -1)
{
if (errno != EAGAIN && errno != ENOTCONN)
LogWarn("Error recv'ing from ", local.to_string(), ": ", strerror(errno));
return;
}
LogDebug("Recv'd ", n_msg, " messages");
for (int i = 0; i < n_msg; i++)
{
auto& [msg_hdr, msg_len] = msgs[i];
bstring_view data{buf.data() + i * max_buf_size, msg_len};
#else
for (size_t i = 0; i < N_msgs; i++)
{
auto& msg_hdr = msgs[0];
auto n_bytes = recvmsg(socket_fd(), &msg_hdr, 0);
if (n_bytes == -1 && errno != EAGAIN && errno != ENOTCONN)
LogWarn("Error recv'ing from ", local.to_string(), ": ", strerror(errno));
if (n_bytes <= 0)
return;
auto msg_len = static_cast<unsigned int>(n_bytes);
bstring_view data{buf.data(), msg_len};
#endif
LogDebug(
"header [",
msg_hdr.msg_namelen,
"]: ",
buffer_printer{reinterpret_cast<char*>(msg_hdr.msg_name), msg_hdr.msg_namelen});
if (!msg_hdr.msg_name || msg_hdr.msg_namelen != sizeof(sockaddr_in))
{ // FIXME: IPv6 support?
LogWarn("Invalid/unknown source address, dropping packet");
continue;
}
Packet pkt{
Path{local, reinterpret_cast<const sockaddr_any*>(msg_hdr.msg_name), msg_hdr.msg_namelen},
data,
ngtcp2_pkt_info{.ecn = 0}};
// Go look for the ECN header field on the incoming packet
for (auto cmsg = CMSG_FIRSTHDR(&msg_hdr); cmsg; cmsg = CMSG_NXTHDR(&msg_hdr, cmsg))
{
// IPv4; for IPv6 these would be IPPROTO_IPV6 and IPV6_TCLASS
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TOS && cmsg->cmsg_len)
{
pkt.info.ecn = *reinterpret_cast<uint8_t*>(CMSG_DATA(cmsg));
}
}
LogDebug(
i,
"[",
pkt.path,
",ecn=0x",
std::hex,
+pkt.info.ecn,
std::dec,
"]: received ",
msg_len,
" bytes");
handle_packet(pkt);
LogDebug("Done handling packet");
#ifdef LOKINET_HAVE_RECVMMSG // Help editor's { } matching:
}
#else
}
#endif
}
std::optional<ConnectionID>
Endpoint::handle_packet_init(const Packet& p)
{
@ -272,15 +125,6 @@ namespace llarp::quic
assert(ecn <= std::numeric_limits<uint8_t>::max());
if (ecn_curr != ecn)
{
if (-1
== setsockopt(socket_fd(), IPPROTO_IP, IP_TOS, &ecn, static_cast<socklen_t>(sizeof(ecn))))
LogWarn("setsockopt failed to set IP_TOS: ", strerror(errno));
// IPv6 version:
// int tclass = this->ecn;
// setsockopt(socket_fd(), IPPROTO_IPV6, IPV6_TCLASS, &tclass,
// static_cast<socklen_t>(sizeof(tclass)));
ecn_curr = ecn;
}
}
@ -288,31 +132,9 @@ namespace llarp::quic
io_result
Endpoint::send_packet(const Address& to, bstring_view data, uint32_t ecn)
{
iovec msg_iov;
msg_iov.iov_base = const_cast<std::byte*>(data.data());
msg_iov.iov_len = data.size();
msghdr msg{};
msg.msg_name = &const_cast<sockaddr&>(reinterpret_cast<const sockaddr&>(to));
msg.msg_namelen = sizeof(sockaddr_in);
msg.msg_iov = &msg_iov;
msg.msg_iovlen = 1;
auto fd = socket_fd();
update_ecn(ecn);
ssize_t nwrite = 0;
do
{
nwrite = sendmsg(fd, &msg, 0);
} while (nwrite == -1 && errno == EINTR);
if (nwrite == -1)
{
LogWarn("sendmsg failed: ", strerror(errno));
return {errno};
}
parent->SendTo(to.Tag(), data, service::ProtocolType::QUIC);
LogDebug(
"[",
to.to_string(),
@ -321,7 +143,7 @@ namespace llarp::quic
+ecn_curr,
std::dec,
"]: sent ",
nwrite,
data.size(),
" bytes");
return {};
}

@ -6,23 +6,31 @@
#include "null_crypto.hpp"
#include "packet.hpp"
#include "stream.hpp"
#include "uvw/async.h"
#include <chrono>
#include <map>
#include <memory>
#include <queue>
#include <unordered_map>
#include <variant>
#include <vector>
#include <uvw/loop.h>
#include <uvw/poll.h>
#include <uvw/timer.h>
// True if we support recvmmsg/sendmmsg
#if defined(__linux__) && !defined(LOKINET_NO_RECVMMSG)
#define LOKINET_HAVE_RECVMMSG
#endif
#include <llarp/service/convotag.hpp>
namespace llarp::service
{
struct Endpoint;
} // namespace llarp::service
namespace llarp::net
{
struct IPPacket;
}
namespace llarp::quic
{
@ -33,29 +41,17 @@ namespace llarp::quic
class Endpoint
{
protected:
// Address we are listening on
Address local;
/// the service endpoint we are owned by
service::Endpoint* const parent;
// The current outgoing IP ecn value for the socket
uint8_t ecn_curr = 0;
std::shared_ptr<uvw::PollHandle> poll;
/// local "address" just a blank
Address local{};
std::shared_ptr<uvw::TimerHandle> expiry_timer;
std::shared_ptr<uvw::Loop> loop;
// How many messages (at most) we recv per callback:
static constexpr int N_msgs = 8;
#ifdef LOKINET_HAVE_RECVMMSG
static constexpr int N_mmsg = N_msgs;
std::array<mmsghdr, N_mmsg> msgs;
#else
static constexpr int N_mmsg = 1;
std::array<msghdr, N_mmsg> msgs;
#endif
std::array<iovec, N_mmsg> msgs_iov;
std::array<sockaddr_any, N_mmsg> msgs_addr;
std::array<std::array<uint8_t, CMSG_SPACE(1)>, N_mmsg> msgs_cmsg;
std::vector<std::byte> buf;
// Max theoretical size of a UDP packet is 2^16-1 minus IP/UDP header overhead
static constexpr size_t max_buf_size = 64 * 1024;
// Max size of a UDP packet that we'll send
@ -101,21 +97,10 @@ namespace llarp::quic
friend class Connection;
// Wires up an endpoint connection.
//
// `bind` - address we should bind to. Required for a server, optional for a client. If
// omitted, no explicit bind is performed (which means the socket will be implicitly bound to
// some OS-determined random high bind port).
// `loop` - the uv loop pointer managing polling of this endpoint
Endpoint(std::optional<Address> bind, std::shared_ptr<uvw::Loop> loop);
Endpoint(service::Endpoint* ep, std::shared_ptr<uvw::Loop> loop);
virtual ~Endpoint();
int
socket_fd() const;
void
on_readable();
// Version & connection id info that we can potentially extract when decoding a packet
struct version_info
{

@ -13,8 +13,10 @@
namespace llarp::quic
{
Server::Server(
Address listen, std::shared_ptr<uvw::Loop> loop, stream_open_callback_t stream_open)
: Endpoint{std::move(listen), std::move(loop)}, stream_open_callback{std::move(stream_open)}
service::Endpoint* parent,
std::shared_ptr<uvw::Loop> loop,
stream_open_callback_t stream_open)
: Endpoint{parent, std::move(loop)}, stream_open_callback{std::move(stream_open)}
{}
void

@ -12,7 +12,8 @@ namespace llarp::quic
using stream_open_callback_t =
std::function<bool(Server& server, Stream& stream, uint16_t port)>;
Server(Address listen, std::shared_ptr<uvw::Loop> loop, stream_open_callback_t stream_opened);
Server(
service::Endpoint*, std::shared_ptr<uvw::Loop> loop, stream_open_callback_t stream_opened);
// Stream callback: takes the server, the (just-created) stream, and the connection port.
// Returns true if the stream should be allowed or false to reject the stream. The callback

@ -125,7 +125,8 @@ namespace llarp::quic
{
// No wrap needs, it fits before the end:
std::copy(data.begin(), data.end(), buffer.begin() + wpos);
LogTrace("Wrote ", data.size(), " bytes to buffer range [", wpos, ",", wpos + data.size(), ")");
LogTrace(
"Wrote ", data.size(), " bytes to buffer range [", wpos, ",", wpos + data.size(), ")");
}
size += data.size();
LogTrace("New stream buffer: ", size, "/", buffer.size(), " bytes beginning at ", start);

@ -84,8 +84,7 @@ namespace llarp::quic::tunnel
});
tcp.on<uvw::EndEvent>([](auto&, uvw::TCPHandle& c) {
// This fires on eof, most likely because the other side of the TCP connection closed it.
LogError(
"EOF on connection with ", c.peer().ip, ":", c.peer().port, ", closing quic stream");
LogError("EOF on connection with ", c.peer().ip, ":", c.peer().port, ", closing quic stream");
c.data<llarp::quic::Stream>()->close();
});
tcp.on<uvw::ErrorEvent>([](const uvw::ErrorEvent& e, uvw::TCPHandle& tcp) {
@ -109,4 +108,4 @@ namespace llarp::quic::tunnel
stream.data_callback = on_incoming_data;
}
} // namespace tunnel
} // namespace llarp::quic::tunnel

@ -13,6 +13,7 @@
#include <uvw.hpp>
/*
using namespace std::literals;
namespace llarp::quic::tunnel
@ -139,3 +140,4 @@ namespace llarp::quic::tunnel
}
} // namespace llarp::quic::tunnel
*/

@ -8,6 +8,7 @@
#include <uvw/tcp.h>
/*
using namespace std::literals;
namespace llarp::quic::tunnel
@ -75,13 +76,7 @@ namespace llarp::quic::tunnel
loop,
[loop, localhost, allowed_ports](
llarp::quic::Server&, llarp::quic::Stream& stream, uint16_t port) {
LogDebug(
"New incoming quic stream ",
stream.id(),
" to reach ",
localhost,
":",
port);
LogDebug("New incoming quic stream ", stream.id(), " to reach ", localhost, ":", port);
if (port == 0 || !(allowed_ports.empty() || allowed_ports.count(port)))
{
LogWarn(
@ -129,13 +124,7 @@ namespace llarp::quic::tunnel
tcp.closeReset();
return;
}
LogDebug(
"Connected to ",
peer.ip,
":",
peer.port,
" for quic ",
stream->id());
LogDebug("Connected to ", peer.ip, ":", peer.port, " for quic ", stream->id());
tcp.erase(error_handler);
tunnel::install_stream_forwarding(tcp, *stream);
assert(stream->used() == 0);
@ -165,3 +154,5 @@ namespace llarp::quic::tunnel
}
} // namespace llarp::quic::tunnel
*/

@ -1,8 +1,8 @@
#pragma once
#include <net/sock_addr.hpp>
#include <service/address.hpp>
#include <ev/ev.hpp>
#include "address.hpp"
#include <llarp/net/sock_addr.hpp>
#include <llarp/ev/ev.hpp>
#include <memory>
@ -21,7 +21,7 @@ namespace llarp::quic::tunnel
{
public:
using AcceptCallback = std::function<AcceptResult(
const llarp::service::Address& remote, uint16_t port, llarp::SockAddr& connect_to)>;
const Address& remote, uint16_t port, llarp::SockAddr& connect_to)>;
private:
AcceptCallback accept;

@ -0,0 +1,30 @@
#include "convotag.hpp"
#include "net/ip.hpp"
namespace llarp::service
{
void
ConvoTag::Randomize()
{
llarp::AlignedBuffer<16>::Randomize();
/// ensure we are in the fc00 range
llarp::AlignedBuffer<16>::operator[](0) = 0xfc;
}
sockaddr_in6
ConvoTag::ToV6() const
{
const auto* ptr = reinterpret_cast<const uint64_t*>(m_data.data());
sockaddr_in6 saddr{};
saddr.sin6_family = AF_INET6;
saddr.sin6_addr = net::HUIntToIn6(huint128_t{ptr[0], ptr[1]});
return saddr;
}
void
ConvoTag::FromV6(sockaddr_in6 saddr)
{
std::copy_n(saddr.sin6_addr.s6_addr, m_data.size(), m_data.data());
}
} // namespace llarp::service

@ -0,0 +1,35 @@
#pragma once
#include <llarp/util/aligned.hpp>
#include <llarp/net/net_int.hpp>
#include <llarp/net/net.hpp>
namespace llarp::service
{
struct ConvoTag final : AlignedBuffer<16>
{
void
Randomize() override;
sockaddr_in6
ToV6() const;
void
FromV6(sockaddr_in6 saddr);
};
} // namespace llarp::service
namespace std
{
template <>
struct hash<llarp::service::ConvoTag>
{
size_t
operator()(const llarp::service::ConvoTag& tag) const
{
std::hash<std::string_view> h{};
return h(std::string_view{reinterpret_cast<const char*>(tag.data()), tag.size()});
}
};
} // namespace std

@ -3,7 +3,7 @@
#include <llarp/crypto/types.hpp>
#include <llarp/path/path.hpp>
#include "intro_set.hpp"
#include <llarp/util/aligned.hpp>
#include "convotag.hpp"
#include <memory>
#include <set>
@ -12,8 +12,6 @@ namespace llarp
{
namespace service
{
struct ConvoTag final : AlignedBuffer<16>
{};
struct ProtocolMessage;
struct RecvDataEvent
@ -80,17 +78,3 @@ namespace llarp
};
} // namespace service
} // namespace llarp
namespace std
{
template <>
struct hash<llarp::service::ConvoTag>
{
size_t
operator()(const llarp::service::ConvoTag& tag) const
{
std::hash<std::string_view> h{};
return h(std::string_view{reinterpret_cast<const char*>(tag.data()), tag.size()});
}
};
} // namespace std

@ -200,7 +200,7 @@ namespace llarp
m_data.fill(0);
}
void
virtual void
Randomize()
{
randombytes(data(), SIZE);

@ -2,7 +2,8 @@
#include <iomanip>
#include <iostream>
namespace llarp {
namespace llarp
{
std::ostream&
operator<<(std::ostream& o, const buffer_printer& bp)
{
@ -42,4 +43,4 @@ namespace llarp {
o.fill(oldfill);
return o;
}
}
} // namespace llarp

@ -26,13 +26,15 @@ namespace llarp
: buf{reinterpret_cast<const std::byte*>(buf.data()), buf.size()}
{}
// Constructed from any type of lvalue string<T> for a single-byte T (char, std::byte, uint8_t, etc.)
// Constructed from any type of lvalue string<T> for a single-byte T (char, std::byte, uint8_t,
// etc.)
template <typename T, typename = std::enable_if_t<sizeof(T) == 1>>
explicit buffer_printer(const std::basic_string<T>& buf)
: buffer_printer(std::basic_string_view<T>{buf})
{}
// *Not* constructable from a string<T> rvalue (because we only hold a view and do not take ownership).
// *Not* constructable from a string<T> rvalue (because we only hold a view and do not take
// ownership).
template <typename T, typename = std::enable_if_t<sizeof(T) == 1>>
explicit buffer_printer(std::basic_string<T>&& buf) = delete;
@ -49,4 +51,4 @@ namespace llarp
};
std::ostream&
operator<<(std::ostream& o, const buffer_printer& bp);
}
} // namespace llarp

@ -93,7 +93,8 @@ namespace llarp
log.logStream->AppendLog(lvl, fname, lineno, log.nodeName, ss.str());
}
inline void _log_noop() noexcept
inline void
_log_noop() noexcept
{}
} // namespace llarp

@ -23,11 +23,11 @@ namespace llarp
// print numeric values rather than std::ostream's default of printing it as a raw char.
using PlainT = std::remove_reference_t<TArg>;
if constexpr (is_same_any_v<PlainT, char, unsigned char, signed char, uint8_t, std::byte>)
ss << +std::forward<TArg>(arg); // Promote to int
ss << +std::forward<TArg>(arg); // Promote to int
else
ss << std::forward<TArg>(arg);
ss << std::forward<TArg>(arg);
if constexpr (sizeof...(TArgs))
LogAppend(ss, std::forward<TArgs>(args)...);
LogAppend(ss, std::forward<TArgs>(args)...);
}
inline std::string

Loading…
Cancel
Save