2
0
mirror of https://github.com/boostorg/cobalt.git synced 2026-01-19 16:12:15 +00:00
Files
cobalt/doc/reference/io/endpoint.adoc
Klemens Morgenstern 727714ed30 [io] endpoint.
2025-06-24 18:15:10 +08:00

256 lines
7.5 KiB
Plaintext

== cobalt/io/endpoint.hpp
The endpoint header provides a generic asio compatible endpoint type & protocols.
=== protocol_type
[source,cpp]
----
struct protocol_type
{
using family_t = __unspecified__;
using type_t = __unspecified__;
using protocol_t = __unspecified__;
constexpr family_t family() const noexcept;
constexpr type_t type() const noexcept;
constexpr protocol_t protocol() const noexcept;
// explicitly construct protocol type.
constexpr explicit
protocol_type(family_t family = static_cast<family_t>(0),
type_t type = static_cast<type_t>(0),
protocol_t protocol = static_cast<protocol_t>(0)) noexcept;
// allows construction from other procols, e.g. asio
template<typename OtherProtocol>
requires requires (const OtherProtocol & op)
{
{static_cast<family_t>(op.family())};
{static_cast<type_t>(op.type())};
{static_cast<protocol_t>(op.protocol())};
}
constexpr protocol_type(const OtherProtocol & op) noexcept
// make the orderable
friend
constexpr auto operator<=>(const protocol_type & , const protocol_type &) noexcept = default;
};
----
.Example
[source,cpp]
----
protocol_type tcp_v4{AF_INET, SOCK_STREAM, IPPROTO_TCP};
// from asio
protocol_type tcp_v6 = boost::asio::ip::tcp::v6();
----
=== static_protocol
The static protocol provides protocol definitions for compile-time usage.
[source,cpp]
----
template<protocol_type::family_t Family = static_cast<protocol_type::family_t>(0),
protocol_type::type_t Type = static_cast<protocol_type::type_t>(0),
protocol_type::protocol_t Protocol = static_cast<protocol_type::protocol_t>(0)>
struct static_protocol
{
using family_t = protocol_type::family_t ;
using type_t = protocol_type::type_t ;
using protocol_t = protocol_type::protocol_t;
constexpr family_t family() const noexcept {return Family;};
constexpr type_t type() const noexcept {return Type;};
constexpr protocol_t protocol() const noexcept {return Protocol;};
using endpoint = io::endpoint;
};
constexpr static_protocol<...> ip;
constexpr static_protocol<...> ip_v4;
constexpr static_protocol<...> ip_v6;
constexpr static_protocol<...> tcp;
constexpr static_protocol<...> tcp_v4;
constexpr static_protocol<...> tcp_v6;
constexpr static_protocol<...> udp;
constexpr static_protocol<...> udp_v4;
constexpr static_protocol<...> udp_v6;
constexpr static_protocol<...> icmp;
constexpr static_protocol<...> local_stream;
constexpr static_protocol<...> local_datagram;
constexpr static_protocol<...> local_seqpacket;
constexpr static_protocol<...> local_protocol;
----
=== ip_address
[source,cpp]
----
struct ip_address
{
bool is_ipv6() const;
bool is_ipv4() const;
std::uint16_t port() const;
std::array<std::uint8_t, 16u> addr() const;
boost::static_string<45> addr_str() const;
};
struct ip_address_v4
{
std::uint16_t port() const;
std::uint32_t addr() const;
boost::static_string<15> addr_str() const;
};
struct ip_address_v6
{
std::uint16_t port() const;
std::array<std::uint8_t, 16u> addr() const;
boost::static_string<45> addr_str() const;
};
----
=== make_endpoint / get_endpoint
The `make_endpoint_tag` is used with a `tag_invoke` for the `make_endpoint` function.
A user can define another `tag_invoke` functions to support custom endpoints.
[source,cpp]
----
template<protocol_type::family_t Family>
struct make_endpoint_tag {};
template<protocol_type::family_t Family>
struct get_endpoint_tag {};
----
The following functions are provided:
[source,cpp]
----
std::size_t tag_invoke(make_endpoint_tag<AF_UNIX>,
asio::detail::socket_addr_type* base,
std::string_view sv);
const local_endpoint* tag_invoke(get_endpoint_tag<AF_UNIX>,
protocol_type actual,
const endpoint::addr_type * addr);
std::size_t tag_invoke(make_endpoint_tag<AF_INET>,
asio::detail::socket_addr_type* base,
std::uint32_t address,
std::uint16_t port);
std::size_t tag_invoke(make_endpoint_tag<AF_INET>,
asio::detail::socket_addr_type* base,
std::string_view address,
std::uint16_t port);
const ip_address_v4* tag_invoke(get_endpoint_tag<AF_INET>,
protocol_type actual,
const endpoint::addr_type * addr);
std::size_t tag_invoke(make_endpoint_tag<AF_INET6>,
asio::detail::socket_addr_type* base,
std::span<std::uint8_t, 16> address,
std::uint16_t port);
std::size_t tag_invoke(make_endpoint_tag<AF_INET6>,
asio::detail::socket_addr_type* base,
std::string_view address,
std::uint16_t port);
const ip_address_v6* tag_invoke(get_endpoint_tag<AF_INET6>,
protocol_type actual,
const endpoint::addr_type * addr);
std::size_t tag_invoke(make_endpoint_tag<AF_UNSPEC>,
asio::detail::socket_addr_type* base,
std::string_view address,
std::uint16_t port);
const ip_address* tag_invoke(get_endpoint_tag<AF_UNSPEC>,
protocol_type actual,
const endpoint::addr_type * addr);
----
=== endpoint
The endpoint function holds and
[source,cpp]
----
struct endpoint
{
using storage_type = asio::detail::sockaddr_storage_type;
using addr_type = asio::detail::socket_addr_type;
void resize(std::size_t size);
void * data() {return &storage_; }
const void * data() const {return &storage_; }
std::size_t size() const {return size_;}
std::size_t capacity() const {return sizeof(storage_);}
void set_type (protocol_type::type_t type) { type_ = type;}
void set_protocol(protocol_type::protocol_t protocol) { protocol_ = protocol;}
protocol_type protocol() const;
endpoint() = default;
endpoint(const endpoint & ep);
// Construct a endpoint using make_endpoint_tag
template<protocol_type::family_t Family,
protocol_type::type_t Type,
protocol_type::protocol_t Protocol,
typename ... Args>
requires requires (make_endpoint_tag<Family> proto,
addr_type* addr, Args && ... args)
{
{tag_invoke(proto, addr, std::forward<Args>(args)...)} -> std::convertible_to<std::size_t>;
}
endpoint(static_protocol<Family, Type, Protocol> proto, Args && ... args);
// allows constructing an endpoint from an asio type
template<typename OtherEndpoint>
requires requires (OtherEndpoint oe)
{
{oe.protocol()} -> std::convertible_to<protocol_type>;
{oe.data()} -> std::convertible_to<void*>;
{oe.size()} -> std::convertible_to<std::size_t>;
}
endpoint(OtherEndpoint && oe);
};
class bad_endpoint_access : public std::exception
{
public:
bad_endpoint_access() noexcept = default;
char const * what() const noexcept;
};
// Uses `get_endpoint_tag<Protocol> to return a `pointer` to the result.
// Throws `bad_endpoint_access` if it's the wrong type
auto get(const endpoint & ep);
// Uses `get_endpoint_tag<Protocol> to return a `pointer` to the result.
template<static_protocol Protocol>
friend auto get_if(const endpoint * ep);
----
.Example
[source,cpp]
----
cobalt::io::endpoint ep{cobalt::io::tcp_v4, "127.0.0.1", 8080};
----