2020-05-04 21:17:16 +00:00
|
|
|
#pragma once
|
|
|
|
|
2020-05-18 20:07:53 +00:00
|
|
|
#ifndef _WIN32
|
2020-05-04 21:36:08 +00:00
|
|
|
#include <netinet/in.h>
|
2020-05-18 20:07:53 +00:00
|
|
|
#include <arpa/inet.h>
|
|
|
|
#else
|
|
|
|
#include <winsock2.h>
|
|
|
|
#include <ws2tcpip.h>
|
|
|
|
#include <wspiapi.h>
|
|
|
|
#endif
|
2020-05-04 21:36:08 +00:00
|
|
|
|
2023-10-19 21:59:57 +00:00
|
|
|
#include <oxenc/variant.h>
|
|
|
|
#include <llarp/util/formattable.hpp>
|
2020-05-04 21:17:16 +00:00
|
|
|
#include <string_view>
|
|
|
|
#include <string>
|
2023-10-19 21:59:57 +00:00
|
|
|
|
2021-03-09 22:24:35 +00:00
|
|
|
#include "net_int.hpp"
|
2020-05-04 21:17:16 +00:00
|
|
|
|
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
/// A simple SockAddr wrapper which provides a sockaddr_in (IPv4). Memory management is handled
|
|
|
|
/// in constructor and destructor (if needed) and copying is disabled.
|
|
|
|
struct SockAddr
|
|
|
|
{
|
2020-05-06 20:38:44 +00:00
|
|
|
SockAddr();
|
2021-03-09 16:02:41 +00:00
|
|
|
// IPv4 constructors:
|
|
|
|
SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, huint16_t port = {0});
|
2021-03-23 19:19:39 +00:00
|
|
|
SockAddr(nuint32_t ip, nuint16_t port = {0});
|
|
|
|
SockAddr(huint32_t ip, huint16_t port = {0});
|
2021-03-09 16:02:41 +00:00
|
|
|
|
|
|
|
// IPv6 (or IPv4 if given a special IPv4-mapped IPv6 addr) in host order (including port).
|
|
|
|
SockAddr(huint128_t ip, huint16_t port = {0});
|
|
|
|
// IPv6 (or IPv4 if given a special IPv4-mapped IPv6 addr) in network order. NB: port is also
|
|
|
|
// in network order!
|
|
|
|
SockAddr(nuint128_t ip, nuint16_t port = {0});
|
|
|
|
|
|
|
|
// String ctors
|
2020-05-04 21:17:16 +00:00
|
|
|
SockAddr(std::string_view addr);
|
2021-05-30 17:29:00 +00:00
|
|
|
SockAddr(std::string_view addr, huint16_t port); // port is in native (host) order
|
2020-05-04 21:36:08 +00:00
|
|
|
|
2020-05-06 20:38:44 +00:00
|
|
|
SockAddr(const SockAddr&);
|
|
|
|
SockAddr&
|
2020-05-08 22:52:00 +00:00
|
|
|
operator=(const SockAddr&);
|
2020-05-06 20:38:44 +00:00
|
|
|
|
|
|
|
SockAddr(const sockaddr& addr);
|
2020-05-08 22:52:00 +00:00
|
|
|
SockAddr&
|
|
|
|
operator=(const sockaddr& addr);
|
|
|
|
|
2020-05-06 20:38:44 +00:00
|
|
|
SockAddr(const sockaddr_in& addr);
|
2020-05-08 22:52:00 +00:00
|
|
|
SockAddr&
|
|
|
|
operator=(const sockaddr_in& addr);
|
|
|
|
|
|
|
|
SockAddr(const sockaddr_in6& addr);
|
|
|
|
SockAddr&
|
|
|
|
operator=(const sockaddr_in6& addr);
|
|
|
|
|
2020-05-11 16:14:07 +00:00
|
|
|
SockAddr(const in6_addr& addr);
|
|
|
|
SockAddr&
|
|
|
|
operator=(const in6_addr& addr);
|
|
|
|
|
2022-07-16 00:41:14 +00:00
|
|
|
explicit operator const sockaddr*() const;
|
|
|
|
explicit operator const sockaddr_in*() const;
|
|
|
|
explicit operator const sockaddr_in6*() const;
|
2020-05-06 20:38:44 +00:00
|
|
|
|
QUIC lokinet integration refactor
Refactors how quic packets get handled: the actual tunnels now live in
tunnel.hpp's TunnelManager which holds and manages all the quic<->tcp
tunnelling. service::Endpoint now holds a TunnelManager rather than a
quic::Server. We only need one quic server, but we need a separate quic
client instance per outgoing quic tunnel, and TunnelManager handles all
that glue now.
Adds QUIC packet handling to get to the right tunnel code. This
required multiplexing incoming quic packets, as follows:
Adds a very small quic tunnel packet header of 4 bytes:
[1, SPORT, ECN] for client->server packets, where SPORT is our
source "port" (really: just a uint16_t unique quic instance
identifier)
or
[2, DPORT, ECN] for server->client packets where the DPORT is the SPORT
from above.
(This also reworks ECN bits to get properly carried over lokinet.)
We don't need a destination/source port for the server-side because
there is only ever one quic server (and we know we're going to it when
the first byte of the header is 1).
Removes the config option for quic exposing ports; a full lokinet will
simply accept anything incoming on quic and tunnel it to the requested
port on the the local endpoint IP (this handler will come in a following
commit).
Replace ConvoTags with full addresses: we need to carry the port, as
well, which the ConvoTag can't give us, so change those to more general
SockAddrs from which we can extract both the ConvoTag *and* the port.
Add a pending connection queue along with new quic-side handlers to call
when a stream becomes available (TunnelManager uses this to wire up
pending incoming conns with quic streams as streams open up).
Completely get rid of tunnel_server/tunnel_client.cpp code; it is now
moved to tunnel.hpp.
Add listen()/forget() methods in TunnelManager for setting up quic
listening sockets (for liblokinet usage).
Add open()/close() methods in TunnelManager for spinning up new quic
clients for outgoing quic connections.
2021-03-23 19:26:32 +00:00
|
|
|
size_t
|
|
|
|
sockaddr_len() const;
|
|
|
|
|
2020-05-11 17:55:36 +00:00
|
|
|
bool
|
|
|
|
operator<(const SockAddr& other) const;
|
|
|
|
|
|
|
|
bool
|
|
|
|
operator==(const SockAddr& other) const;
|
|
|
|
|
2022-04-07 20:44:23 +00:00
|
|
|
bool
|
|
|
|
operator!=(const SockAddr& other) const
|
|
|
|
{
|
|
|
|
return not(*this == other);
|
|
|
|
};
|
|
|
|
|
2020-05-08 17:23:21 +00:00
|
|
|
void
|
2021-02-24 23:34:42 +00:00
|
|
|
fromString(std::string_view str, bool allow_port = true);
|
2020-05-08 17:23:21 +00:00
|
|
|
|
|
|
|
std::string
|
2022-07-16 00:41:14 +00:00
|
|
|
ToString() const;
|
2020-05-08 17:23:21 +00:00
|
|
|
|
2023-05-29 21:45:16 +00:00
|
|
|
/// convert ip address to string; ipv6_brackets - if true or omitted we add [...] around the
|
|
|
|
/// IPv6 address, otherwise we return it bare.
|
2021-05-30 17:29:00 +00:00
|
|
|
std::string
|
2023-05-29 21:45:16 +00:00
|
|
|
hostString(bool ipv6_brackets = true) const;
|
2021-05-30 17:29:00 +00:00
|
|
|
|
2022-05-20 17:10:04 +00:00
|
|
|
inline int
|
|
|
|
Family() const
|
|
|
|
{
|
|
|
|
if (isIPv6())
|
|
|
|
return AF_INET6;
|
|
|
|
return AF_INET;
|
|
|
|
}
|
|
|
|
|
2020-05-08 17:23:21 +00:00
|
|
|
/// Returns true if this is an empty SockAddr, defined by having no IP address set. An empty IP
|
|
|
|
/// address with a valid port is still considered empty.
|
|
|
|
///
|
|
|
|
/// @return true if this is empty, false otherwise
|
2020-05-06 20:38:44 +00:00
|
|
|
bool
|
|
|
|
isEmpty() const;
|
|
|
|
|
2020-05-08 17:23:21 +00:00
|
|
|
void
|
|
|
|
setIPv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d);
|
|
|
|
|
2022-07-09 15:05:52 +00:00
|
|
|
inline void
|
|
|
|
setIP(std::variant<nuint32_t, nuint128_t> ip)
|
|
|
|
{
|
|
|
|
if (auto* v4 = std::get_if<nuint32_t>(&ip))
|
|
|
|
setIPv4(*v4);
|
|
|
|
if (auto* v6 = std::get_if<nuint128_t>(&ip))
|
|
|
|
setIPv6(*v6);
|
|
|
|
}
|
|
|
|
|
2021-03-02 18:18:22 +00:00
|
|
|
void
|
2021-03-09 16:02:41 +00:00
|
|
|
setIPv4(nuint32_t ip);
|
2021-03-02 18:18:22 +00:00
|
|
|
|
2020-05-08 17:23:21 +00:00
|
|
|
void
|
2021-03-09 16:02:41 +00:00
|
|
|
setIPv4(huint32_t ip);
|
2020-05-08 17:23:21 +00:00
|
|
|
|
2021-03-09 16:02:41 +00:00
|
|
|
void
|
|
|
|
setIPv6(huint128_t ip);
|
|
|
|
|
|
|
|
void
|
|
|
|
setIPv6(nuint128_t ip);
|
|
|
|
|
|
|
|
void
|
|
|
|
setPort(huint16_t port);
|
|
|
|
|
|
|
|
void
|
|
|
|
setPort(nuint16_t port);
|
|
|
|
|
|
|
|
// Port is a native (host) value
|
|
|
|
void
|
|
|
|
setPort(uint16_t port)
|
|
|
|
{
|
|
|
|
setPort(huint16_t{port});
|
|
|
|
}
|
|
|
|
|
2022-07-28 16:07:38 +00:00
|
|
|
/// get the port of this sockaddr in network order
|
|
|
|
net::port_t
|
|
|
|
port() const;
|
|
|
|
|
|
|
|
/// port is always returned in host order
|
|
|
|
inline uint16_t
|
|
|
|
getPort() const
|
|
|
|
{
|
|
|
|
return ToHost(port()).h;
|
|
|
|
}
|
2020-05-08 17:23:21 +00:00
|
|
|
|
2021-03-23 19:19:39 +00:00
|
|
|
/// True if this stores an IPv6 address, false if IPv4.
|
|
|
|
bool
|
|
|
|
isIPv6() const;
|
|
|
|
|
|
|
|
/// !isIPv6()
|
|
|
|
bool
|
|
|
|
isIPv4() const;
|
|
|
|
|
2021-03-02 18:18:22 +00:00
|
|
|
/// in network order
|
2021-03-09 16:02:41 +00:00
|
|
|
nuint128_t
|
|
|
|
getIPv6() const;
|
|
|
|
nuint32_t
|
2021-03-02 18:18:22 +00:00
|
|
|
getIPv4() const;
|
2022-07-09 15:05:52 +00:00
|
|
|
|
2022-05-20 17:10:04 +00:00
|
|
|
std::variant<nuint32_t, nuint128_t>
|
|
|
|
getIP() const;
|
2021-02-16 15:59:18 +00:00
|
|
|
|
2021-03-09 16:02:41 +00:00
|
|
|
/// in host order
|
|
|
|
huint128_t
|
|
|
|
asIPv6() const;
|
2021-02-22 15:01:05 +00:00
|
|
|
huint32_t
|
|
|
|
asIPv4() const;
|
|
|
|
|
2020-05-06 20:38:44 +00:00
|
|
|
private:
|
2020-05-08 17:23:21 +00:00
|
|
|
bool m_empty = true;
|
|
|
|
sockaddr_in6 m_addr;
|
2020-10-27 21:34:09 +00:00
|
|
|
sockaddr_in m_addr4;
|
2020-05-08 17:23:21 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
init();
|
2020-05-08 22:52:00 +00:00
|
|
|
|
|
|
|
void
|
2021-02-24 23:34:42 +00:00
|
|
|
applyIPv4MapBytes();
|
2020-05-04 21:17:16 +00:00
|
|
|
};
|
2020-05-06 20:38:44 +00:00
|
|
|
|
2022-07-16 00:41:14 +00:00
|
|
|
template <>
|
|
|
|
inline constexpr bool IsToStringFormattable<SockAddr> = true;
|
2020-05-06 20:38:44 +00:00
|
|
|
|
2020-05-04 21:17:16 +00:00
|
|
|
} // namespace llarp
|
2021-03-09 18:39:40 +00:00
|
|
|
|
|
|
|
namespace std
|
|
|
|
{
|
|
|
|
template <>
|
|
|
|
struct hash<llarp::SockAddr>
|
|
|
|
{
|
|
|
|
size_t
|
|
|
|
operator()(const llarp::SockAddr& addr) const noexcept
|
|
|
|
{
|
|
|
|
const std::hash<uint16_t> port{};
|
|
|
|
const std::hash<llarp::huint128_t> ip{};
|
|
|
|
return (port(addr.getPort()) << 3) ^ ip(addr.asIPv6());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} // namespace std
|