Replaced types for each address family with union
This commit is contained in:
parent
36f3c7a8ec
commit
8ce26c24c1
6
main.cpp
6
main.cpp
@ -6,7 +6,9 @@ import ru.landgrafhomyak.BGTU.networks_1.sockets;
|
||||
int main() {
|
||||
LdH::Sockets::init_sockets();
|
||||
|
||||
auto server = LdH::Sockets::listen_tcp(LdH::Sockets::IPv4Address::parse("127.0.0.1"), 8081, 1);
|
||||
std::cout << LdH::Sockets::Address::parse("google.com", "443").to_string() << std::endl;
|
||||
|
||||
auto server = LdH::Sockets::listen_tcp(LdH::Sockets::Address::parse("127.0.0.1", "8081"), 1);
|
||||
|
||||
auto server_thread = LdH::fork("server", [&] {
|
||||
auto server_stream = server.wait_for_connection();
|
||||
@ -16,7 +18,7 @@ int main() {
|
||||
server_stream.sock.close();
|
||||
});
|
||||
auto client_thread = LdH::fork("client", [&] {
|
||||
auto client = LdH::Sockets::connect_tcp(LdH::Sockets::IPv4Address::parse("127.0.0.1"), 8081);
|
||||
auto client = LdH::Sockets::connect_tcp(LdH::Sockets::Address::parse("127.0.0.1", "8081"));
|
||||
char buffer[10] = "hello\n";
|
||||
client.write(10, buffer);
|
||||
client.close();
|
||||
|
||||
@ -4,31 +4,13 @@ import std;
|
||||
import ru.landgrafhomyak.BGTU.networks_1.exceptions;
|
||||
import ru.landgrafhomyak.BGTU.networks_1.streams;
|
||||
|
||||
|
||||
namespace LdH::Sockets::Berkeley {
|
||||
export
|
||||
struct sized_ptr {
|
||||
std::size_t size;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
template<class addr_t, class af_t>
|
||||
concept _raw_addr = std::default_initializable<addr_t> && std::destructible<addr_t> &&
|
||||
std::copyable<addr_t> && std::movable<addr_t> &&
|
||||
requires { { addr_t::any() } -> std::same_as<addr_t>; } &&
|
||||
requires(char const *raw) { { addr_t::parse(raw) } -> std::same_as<addr_t>; } &&
|
||||
requires(addr_t self) { { self.raw_ptr() } -> std::same_as<sized_ptr>; } &&
|
||||
requires { { addr_t::af_value() } -> std::same_as<af_t>; };
|
||||
|
||||
|
||||
export
|
||||
template<class ctx_t>
|
||||
concept BerkeleySocketsContext = requires { typename ctx_t::addr; } &&
|
||||
requires { typename ctx_t::af_t; } &&
|
||||
requires { typename ctx_t::af; } &&
|
||||
requires { { ctx_t::af::inet() } -> std::same_as<typename ctx_t::af_t>; } &&
|
||||
requires { { ctx_t::af::inet6() } -> std::same_as<typename ctx_t::af_t>; } &&
|
||||
requires { { ctx_t::af::ipx() } -> std::same_as<typename ctx_t::af_t>; } &&
|
||||
concept BerkeleySocketsContext = requires { typename ctx_t::address_t; } &&
|
||||
std::default_initializable<typename ctx_t::address_t> && std::copyable<typename ctx_t::address_t> && std::destructible<typename ctx_t::address_t> &&
|
||||
requires(char const *h, char const *s) { { ctx_t::address_t::parse(h, s) } -> std::same_as<typename ctx_t::address_t>; } &&
|
||||
requires(typename ctx_t::address_t s) { { s.to_string() } -> std::same_as<std::string>; } &&
|
||||
requires { typename ctx_t::sock_type_t; } &&
|
||||
requires { typename ctx_t::sock_type; } &&
|
||||
requires { { ctx_t::sock_type::stream() } -> std::same_as<typename ctx_t::sock_type_t>; } &&
|
||||
@ -38,143 +20,72 @@ namespace LdH::Sockets::Berkeley {
|
||||
requires { { ctx_t::proto::tcp() } -> std::same_as<typename ctx_t::proto_t>; } &&
|
||||
requires { { ctx_t::proto::udp() } -> std::same_as<typename ctx_t::proto_t>; } &&
|
||||
requires { { ctx_t::proto::icmp() } -> std::same_as<typename ctx_t::proto_t>; } &&
|
||||
requires { typename ctx_t::addr::ipv4; requires _raw_addr<typename ctx_t::addr::ipv4, typename ctx_t::af_t>; } &&
|
||||
requires { typename ctx_t::addr::ipv6; requires _raw_addr<typename ctx_t::addr::ipv6, typename ctx_t::af_t>; } &&
|
||||
requires { typename ctx_t::socket_t; } &&
|
||||
std::default_initializable<typename ctx_t::socket_t> && std::movable<typename ctx_t::socket_t> && std::destructible<typename ctx_t::socket_t> &&
|
||||
requires(typename ctx_t::af_t a, typename ctx_t::sock_type_t t, typename ctx_t::proto_t p) { { ctx_t::socket_t::create(a, t, p) } -> std::same_as<typename ctx_t::socket_t>; } &&
|
||||
requires(typename ctx_t::address_t a, typename ctx_t::sock_type_t t, typename ctx_t::proto_t p) { { ctx_t::socket_t::create(a, t, p) } -> std::same_as<typename ctx_t::socket_t>; } &&
|
||||
requires(typename ctx_t::socket_t s, std::size_t q) { { s.listen(q) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, typename ctx_t::addr::ipv4 a, std::uint_least16_t p) { { s.connect(a, p) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, typename ctx_t::addr::ipv6 a, std::uint_least16_t p) { { s.connect(a, p) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, typename ctx_t::addr::ipv4 a, std::uint_least16_t p) { { s.bind(a, p) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, typename ctx_t::addr::ipv6 a, std::uint_least16_t p) { { s.bind(a, p) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, typename ctx_t::address_t e) { { s.connect(e) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, typename ctx_t::address_t e) { { s.bind(e) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s) { { s.close() } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, std::size_t c, char const *d) { { s.send_stream(c, d) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, std::size_t c, char *d) { { s.recv_stream(c, d) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, typename ctx_t::addr::ipv4 *a) { { s.accept(a) } -> std::same_as<typename ctx_t::socket_t>; } &&
|
||||
requires(typename ctx_t::socket_t s, typename ctx_t::addr::ipv6 *a) { { s.accept(a) } -> std::same_as<typename ctx_t::socket_t>; };
|
||||
requires(typename ctx_t::socket_t s, typename ctx_t::address_t *a) { { s.accept(a) } -> std::same_as<typename ctx_t::socket_t>; };
|
||||
|
||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||
class _addr_internals;
|
||||
|
||||
export
|
||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||
class Address;
|
||||
|
||||
template<class addr_t>
|
||||
class _addr_internals {
|
||||
};
|
||||
|
||||
template<class raw_t>
|
||||
class _addr_wrapper {
|
||||
private:
|
||||
bool _has_value;
|
||||
raw_t _value;
|
||||
|
||||
_addr_wrapper(bool has_value, raw_t value) : _has_value{has_value}, _value{value} {
|
||||
}
|
||||
|
||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||
friend
|
||||
class Address;
|
||||
|
||||
template<class addr_t>
|
||||
friend
|
||||
class _addr_internals;
|
||||
|
||||
public:
|
||||
_addr_wrapper() : _has_value{false}, _value{} {
|
||||
}
|
||||
|
||||
_addr_wrapper(_addr_wrapper const &other) noexcept = default;
|
||||
|
||||
_addr_wrapper(_addr_wrapper &&other) noexcept : _has_value{other._has_value}, _value{other._value} {
|
||||
other._has_value = false;
|
||||
}
|
||||
|
||||
_addr_wrapper &operator=(_addr_wrapper const &other) = default;
|
||||
|
||||
_addr_wrapper &operator=(_addr_wrapper &&other) noexcept {
|
||||
this->_has_value = other._has_value;
|
||||
other._has_value = false;
|
||||
this->_value = std::move(other._value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~_addr_wrapper() noexcept = default;
|
||||
|
||||
static _addr_wrapper parse(char const *raw) {
|
||||
return {true, raw_t::parse(raw)};
|
||||
}
|
||||
|
||||
static _addr_wrapper parse(std::string const &raw) {
|
||||
return {true, raw_t::parse(raw.c_str())};
|
||||
}
|
||||
|
||||
static _addr_wrapper any() {
|
||||
return _addr_wrapper{raw_t::any()};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export
|
||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||
using IPv4Address = _addr_wrapper<typename ctx_t::addr::ipv4>;
|
||||
|
||||
export
|
||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||
using IPv6Address = _addr_wrapper<typename ctx_t::addr::ipv6>;
|
||||
|
||||
|
||||
template<class _raw_addr_t>
|
||||
class _addr_internals<_addr_wrapper<_raw_addr_t> > {
|
||||
public:
|
||||
using raw_t = _raw_addr_t;
|
||||
|
||||
static _addr_wrapper<_raw_addr_t> empty() {
|
||||
return _addr_wrapper<_raw_addr_t>{false, _raw_addr_t{}};
|
||||
}
|
||||
|
||||
static _addr_wrapper<_raw_addr_t> wrap(_raw_addr_t value) {
|
||||
return _addr_wrapper<_raw_addr_t>{true, value};
|
||||
}
|
||||
|
||||
static _raw_addr_t raw_of(_addr_wrapper<_raw_addr_t> const &value) {
|
||||
return value._value;
|
||||
}
|
||||
|
||||
static bool has_value(_addr_wrapper<_raw_addr_t> const &value) {
|
||||
return value._has_value;
|
||||
}
|
||||
};
|
||||
|
||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||
class Address {
|
||||
private:
|
||||
enum _type_t {
|
||||
_type_EMPTY,
|
||||
_type_IPv4,
|
||||
_type_IPv6,
|
||||
};
|
||||
bool _has_value;
|
||||
ctx_t::address_t _value;
|
||||
|
||||
_type_t _type;
|
||||
explicit Address(bool has_value, ctx_t::address_t value) : _has_value{has_value}, _value{value} {
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
} empty;
|
||||
|
||||
ctx_t::ipv4 ipv4;
|
||||
ctx_t::ipv6 ipv6;
|
||||
} _value;
|
||||
template<class ctx_t2> requires BerkeleySocketsContext<ctx_t2>
|
||||
friend class _addr_internals;
|
||||
|
||||
public:
|
||||
Address() : _type{_type_EMPTY}, _value{.empty{}} {
|
||||
Address() : _has_value{false}, _value{} {
|
||||
}
|
||||
|
||||
Address(IPv4Address<ctx_t> const &value) : _type{_type_IPv4}, _value{.ipv4 = value._value} {
|
||||
Address(Address const &other) noexcept = default;
|
||||
|
||||
Address(Address &&other) noexcept : _has_value{other._has_value}, _value{other._value} {
|
||||
other._has_value = false;
|
||||
}
|
||||
|
||||
Address(IPv6Address<ctx_t> const &value) : _type{_type_IPv6}, _value{.ipv6 = value._value} {
|
||||
Address &operator=(Address const &other) = default;
|
||||
|
||||
Address &operator=(Address &&other) noexcept {
|
||||
this->_has_value = other._has_value;
|
||||
this->_value = std::move(other._value);
|
||||
other._has_value = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Address() {
|
||||
this->_has_value = false;
|
||||
}
|
||||
|
||||
static Address parse(char const *host, char const *service) {
|
||||
return Address{true, ctx_t::address_t::parse(host, service)};
|
||||
}
|
||||
|
||||
std::string to_string() {
|
||||
return this->_value.to_string();
|
||||
}
|
||||
};
|
||||
|
||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||
class _addr_internals {
|
||||
public:
|
||||
static bool has_value(Address<ctx_t> const &v) { return v._has_value; }
|
||||
static ctx_t::address_t unwrap(Address<ctx_t> const &v) { return v._value; }
|
||||
static Address<ctx_t> wrap(ctx_t::address_t const &raw) { return Address<ctx_t>{true, raw}; }
|
||||
};
|
||||
|
||||
enum _socket_state_t {
|
||||
_socket_state_UNINITIALIZED,
|
||||
@ -210,25 +121,21 @@ namespace LdH::Sockets::Berkeley {
|
||||
while (true) {
|
||||
switch (current) {
|
||||
case _socket_state_UNINITIALIZED:
|
||||
if (this->_state.compare_exchange_weak(current, _socket_state_AVAILABLE))
|
||||
return current;
|
||||
continue;
|
||||
case _socket_state_MOVED:
|
||||
if (this->_state.compare_exchange_weak(current, _socket_state_AVAILABLE))
|
||||
return current;
|
||||
continue;
|
||||
case _socket_state_CLOSED:
|
||||
if (this->_state.compare_exchange_weak(current, _socket_state_AVAILABLE))
|
||||
return current;
|
||||
goto DONE;
|
||||
continue;
|
||||
default:
|
||||
LdH::abort("Variable already initialized");
|
||||
}
|
||||
}
|
||||
|
||||
DONE:
|
||||
this->_state.store(other._state.exchange(_socket_state_MOVED));
|
||||
this->_value = std::move(other._value);
|
||||
|
||||
return *this;;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -320,10 +227,10 @@ namespace LdH::Sockets::Berkeley {
|
||||
};
|
||||
|
||||
export
|
||||
template<class ctx_t, class> requires BerkeleySocketsContext<ctx_t>
|
||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||
class StreamSocketsServer;
|
||||
|
||||
template<class sock_t>
|
||||
template<class>
|
||||
class _socket_internals {
|
||||
};
|
||||
|
||||
@ -336,7 +243,7 @@ namespace LdH::Sockets::Berkeley {
|
||||
}
|
||||
|
||||
|
||||
template<class ctx_t2, class> requires BerkeleySocketsContext<ctx_t2>
|
||||
template<class ctx_t2> requires BerkeleySocketsContext<ctx_t2>
|
||||
friend
|
||||
class StreamSocketsServer;
|
||||
|
||||
@ -348,7 +255,7 @@ namespace LdH::Sockets::Berkeley {
|
||||
public:
|
||||
StreamSocket() = default;
|
||||
|
||||
explicit StreamSocket(StreamSocket &&other) noexcept = default;
|
||||
StreamSocket(StreamSocket &&other) noexcept = default;
|
||||
|
||||
StreamSocket &operator=(StreamSocket &&other) noexcept = default;
|
||||
|
||||
@ -382,17 +289,17 @@ namespace LdH::Sockets::Berkeley {
|
||||
|
||||
|
||||
export
|
||||
template<class addr_t, class sock_t>
|
||||
template<class ctx_t, class sock_t>
|
||||
class SocketWithAddress {
|
||||
public:
|
||||
addr_t addr;
|
||||
Address<ctx_t> addr;
|
||||
sock_t sock;
|
||||
|
||||
SocketWithAddress(addr_t addr, sock_t &&sock) : addr{addr}, sock{std::move(sock)} {
|
||||
SocketWithAddress(Address<ctx_t> addr, sock_t &&sock) : addr{addr}, sock{std::move(sock)} {
|
||||
}
|
||||
};
|
||||
|
||||
template<class ctx_t, class addr_t> requires BerkeleySocketsContext<ctx_t>
|
||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||
class StreamSocketsServer : public _berkeley_socket_commons<ctx_t> {
|
||||
private:
|
||||
explicit StreamSocketsServer(ctx_t::socket_t &&value) : _berkeley_socket_commons<ctx_t>{std::move(value)} {
|
||||
@ -405,18 +312,18 @@ namespace LdH::Sockets::Berkeley {
|
||||
public:
|
||||
StreamSocketsServer() = default;
|
||||
|
||||
explicit StreamSocketsServer(StreamSocketsServer &&other) noexcept = default;
|
||||
StreamSocketsServer(StreamSocketsServer &&other) noexcept = default;
|
||||
|
||||
StreamSocketsServer &operator=(StreamSocketsServer &&other) noexcept = default;
|
||||
|
||||
[[nodiscard]]
|
||||
SocketWithAddress<addr_t, StreamSocket<ctx_t> > wait_for_connection() {
|
||||
SocketWithAddress<ctx_t, StreamSocket<ctx_t> > wait_for_connection() {
|
||||
this->_start_reading("Socket already waiting for connections");
|
||||
|
||||
typename _addr_internals<addr_t>::raw_t addr{};
|
||||
typename ctx_t::address_t addr{};
|
||||
typename ctx_t::socket_t raw = this->_value.accept(&addr);
|
||||
this->_finish_reading();
|
||||
return SocketWithAddress<addr_t, StreamSocket<ctx_t> >{_addr_internals<addr_t>::wrap(addr), StreamSocket<ctx_t>{std::move(raw)}};
|
||||
return SocketWithAddress<ctx_t, StreamSocket<ctx_t> >{_addr_internals<ctx_t>::wrap(addr), _socket_internals<StreamSocket<ctx_t> >::wrap(std::move(raw))};
|
||||
}
|
||||
|
||||
void close() {
|
||||
@ -427,34 +334,34 @@ namespace LdH::Sockets::Berkeley {
|
||||
};
|
||||
|
||||
|
||||
template<class ctx_t, class addr_t>
|
||||
class _socket_internals<StreamSocketsServer<ctx_t, addr_t> > {
|
||||
template<class ctx_t>
|
||||
class _socket_internals<StreamSocketsServer<ctx_t> > {
|
||||
public:
|
||||
static StreamSocketsServer<ctx_t, addr_t> wrap(ctx_t::socket_t &&raw) {
|
||||
return StreamSocketsServer<ctx_t, addr_t>{std::move(raw)};
|
||||
static StreamSocketsServer<ctx_t> wrap(ctx_t::socket_t &&raw) {
|
||||
return StreamSocketsServer<ctx_t>{std::move(raw)};
|
||||
}
|
||||
};
|
||||
|
||||
export
|
||||
template<class ctx_t, class addr_t> requires BerkeleySocketsContext<ctx_t>
|
||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||
[[nodiscard]]
|
||||
StreamSocket<ctx_t> connect_tcp(addr_t addr, std::uint_least16_t port) {
|
||||
if (!_addr_internals<addr_t>::has_value(addr))
|
||||
StreamSocket<ctx_t> connect_tcp(Address<ctx_t> addr) {
|
||||
if (!_addr_internals<ctx_t>::has_value(addr))
|
||||
LdH::abort("Address not initialized");
|
||||
typename ctx_t::socket_t sock = ctx_t::socket_t::create(_addr_internals<addr_t>::raw_t::af_value(), ctx_t::sock_type::stream(), ctx_t::proto::tcp());
|
||||
sock.connect(_addr_internals<addr_t>::raw_of(addr), port);
|
||||
typename ctx_t::socket_t sock = ctx_t::socket_t::create(_addr_internals<ctx_t>::unwrap(addr), ctx_t::sock_type::stream(), ctx_t::proto::tcp());
|
||||
sock.connect(_addr_internals<ctx_t>::unwrap(addr));
|
||||
return _socket_internals<StreamSocket<ctx_t> >::wrap(std::move(sock));
|
||||
}
|
||||
|
||||
export
|
||||
template<class ctx_t, class addr_t> requires BerkeleySocketsContext<ctx_t>
|
||||
template<class ctx_t> requires BerkeleySocketsContext<ctx_t>
|
||||
[[nodiscard]]
|
||||
StreamSocketsServer<ctx_t, addr_t> listen_tcp(addr_t addr, std::uint_least16_t port, std::size_t queue_size) {
|
||||
if (!_addr_internals<addr_t>::has_value(addr))
|
||||
StreamSocketsServer<ctx_t> listen_tcp(Address<ctx_t> addr, std::size_t queue_size) {
|
||||
if (!_addr_internals<ctx_t>::has_value(addr))
|
||||
LdH::abort("Address not initialized");
|
||||
typename ctx_t::socket_t sock = ctx_t::socket_t::create(_addr_internals<addr_t>::raw_t::af_value(), ctx_t::sock_type::stream(), ctx_t::proto::tcp());
|
||||
sock.bind(_addr_internals<addr_t>::raw_of(addr), port);
|
||||
typename ctx_t::socket_t sock = ctx_t::socket_t::create(_addr_internals<ctx_t>::unwrap(addr), ctx_t::sock_type::stream(), ctx_t::proto::tcp());
|
||||
sock.bind(_addr_internals<ctx_t>::unwrap(addr));
|
||||
sock.listen(queue_size);
|
||||
return _socket_internals<StreamSocketsServer<ctx_t, addr_t> >::wrap(std::move(sock));
|
||||
return _socket_internals<StreamSocketsServer<ctx_t> >::wrap(std::move(sock));
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,57 +19,49 @@ namespace LdH::Sockets {
|
||||
}
|
||||
|
||||
|
||||
template<class _value_t, INT _family, _value_t (_any_constructor)()>
|
||||
class _in_addr_wrapper {
|
||||
public:
|
||||
_value_t _value;
|
||||
|
||||
private:
|
||||
_in_addr_wrapper(_value_t v) : _value{v} {
|
||||
}
|
||||
|
||||
public:
|
||||
_in_addr_wrapper() = default;
|
||||
|
||||
_in_addr_wrapper(_in_addr_wrapper const &other) = default;
|
||||
|
||||
_in_addr_wrapper(_in_addr_wrapper &&other) = default;
|
||||
|
||||
_in_addr_wrapper &operator=(_in_addr_wrapper const &other) = default;
|
||||
|
||||
_in_addr_wrapper &operator=(_in_addr_wrapper &&other) = default;
|
||||
|
||||
static _in_addr_wrapper any() { return _in_addr_wrapper{_any_constructor()}; }
|
||||
|
||||
static _in_addr_wrapper parse(char const *raw) {
|
||||
_value_t val;
|
||||
switch (inet_pton(_family, raw, &val)) {
|
||||
case 1:
|
||||
break;
|
||||
case 0:
|
||||
throw LdH::Exception{"Wrong IP address value"};
|
||||
default:
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
break;
|
||||
}
|
||||
return _in_addr_wrapper{val};
|
||||
}
|
||||
|
||||
Berkeley::sized_ptr raw_ptr() {
|
||||
return {sizeof(_value_t), &(this->_value)};
|
||||
}
|
||||
|
||||
static INT af_value() { return _family; };
|
||||
};
|
||||
|
||||
|
||||
struct _WinsockContext {
|
||||
struct addr {
|
||||
using ipv4 = _in_addr_wrapper<in_addr, AF_INET, [] { return in4addr_any; }>;
|
||||
using ipv6 = _in_addr_wrapper<in6_addr, AF_INET6, [] { return in6addr_any; }>;
|
||||
class address_t {
|
||||
public:
|
||||
sockaddr_storage _value;
|
||||
|
||||
private:
|
||||
address_t(sockaddr_storage value) : _value{value} {
|
||||
}
|
||||
|
||||
public:
|
||||
address_t() = default;
|
||||
|
||||
address_t(address_t const &) = default;
|
||||
|
||||
address_t(address_t &&) = default;
|
||||
|
||||
address_t &operator=(address_t const &) = default;
|
||||
|
||||
address_t &operator=(address_t &&) = default;
|
||||
|
||||
static address_t parse(char const *addr, char const *service) {
|
||||
addrinfo *p;
|
||||
if (0 != getaddrinfo(addr, service, nullptr, &p)) {
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
sockaddr_storage out;
|
||||
ZeroMemory(&out, sizeof(sockaddr_storage));
|
||||
CopyMemory(&out, p->ai_addr, p->ai_addrlen);
|
||||
freeaddrinfo(p);
|
||||
return address_t{out};
|
||||
}
|
||||
|
||||
std::string to_string() {
|
||||
char buffer[1024];
|
||||
DWORD buf_size = 1024;
|
||||
if (0 != WSAAddressToStringA(reinterpret_cast<sockaddr *>(&(this->_value)), sizeof(sockaddr_storage), nullptr, buffer, &buf_size)) {
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
|
||||
return std::string{buffer, buf_size - 1};
|
||||
}
|
||||
};
|
||||
|
||||
using af_t = int;
|
||||
using sock_type_t = int;
|
||||
using proto_t = int;
|
||||
|
||||
@ -116,8 +108,8 @@ namespace LdH::Sockets {
|
||||
|
||||
~socket_t() = default;
|
||||
|
||||
static socket_t create(int af, int type, int proto) {
|
||||
SOCKET sock = ::socket(af, type, proto);
|
||||
static socket_t create(address_t const &addr, int type, int proto) {
|
||||
SOCKET sock = ::socket(addr._value.ss_family, type, proto);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
@ -132,74 +124,24 @@ namespace LdH::Sockets {
|
||||
this->_value = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
void connect(addr::ipv4 addr, std::uint_least16_t port) {
|
||||
sockaddr_in combined;
|
||||
ZeroMemory(&combined, sizeof(combined));
|
||||
combined.sin_family = AF_INET;
|
||||
combined.sin_port = htons(port);
|
||||
combined.sin_addr = addr._value;
|
||||
|
||||
if (0 != ::connect(this->_value, reinterpret_cast<sockaddr *>(&combined), sizeof(combined)))
|
||||
void connect(address_t addr) {
|
||||
if (0 != ::connect(this->_value, reinterpret_cast<sockaddr *>(&(addr._value)), sizeof(sockaddr)))
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
|
||||
void connect(addr::ipv6 addr, std::uint_least16_t port) {
|
||||
sockaddr_in6 combined;
|
||||
ZeroMemory(&combined, sizeof(combined));
|
||||
combined.sin6_family = AF_INET6;
|
||||
combined.sin6_port = htons(port);
|
||||
combined.sin6_addr = addr._value;
|
||||
|
||||
if (0 != ::connect(this->_value, reinterpret_cast<sockaddr *>(&combined), sizeof(combined)))
|
||||
void bind(address_t addr) {
|
||||
if (0 != ::bind(this->_value, reinterpret_cast<sockaddr *>(&(addr._value)), sizeof(sockaddr)))
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
|
||||
void bind(addr::ipv4 addr, std::uint_least16_t port) {
|
||||
sockaddr_in combined;
|
||||
ZeroMemory(&combined, sizeof(combined));
|
||||
combined.sin_family = AF_INET;
|
||||
combined.sin_port = htons(port);
|
||||
combined.sin_addr = addr._value;
|
||||
|
||||
if (0 != ::bind(this->_value, reinterpret_cast<sockaddr *>(&combined), sizeof(combined)))
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
|
||||
void bind(addr::ipv6 addr, std::uint_least16_t port) {
|
||||
sockaddr_in6 combined;
|
||||
ZeroMemory(&combined, sizeof(combined));
|
||||
combined.sin6_family = AF_INET6;
|
||||
combined.sin6_port = htons(port);
|
||||
combined.sin6_addr = addr._value;
|
||||
|
||||
if (0 != ::bind(this->_value, reinterpret_cast<sockaddr *>(&combined), sizeof(combined)))
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
|
||||
socket_t accept(addr::ipv4 *addr) {
|
||||
sockaddr_in raw_addr;
|
||||
raw_addr.sin_family = AF_INET;
|
||||
int size_i = sizeof(sockaddr_in);
|
||||
SOCKET sock = ::accept(this->_value, reinterpret_cast<sockaddr *>(&raw_addr), &size_i);
|
||||
socket_t accept(address_t *addr) {
|
||||
SOCKET sock = ::accept(this->_value, reinterpret_cast<sockaddr *>(&(addr->_value)), nullptr);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
addr->_value = raw_addr.sin_addr;
|
||||
return socket_t{sock};
|
||||
}
|
||||
|
||||
socket_t accept(addr::ipv6 *addr) {
|
||||
sockaddr_in6 raw_addr;
|
||||
int size_i = sizeof(sockaddr_in6);
|
||||
SOCKET sock = ::accept(this->_value, reinterpret_cast<sockaddr *>(&raw_addr), &size_i);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
addr->_value = raw_addr.sin6_addr;
|
||||
return socket_t{sock};
|
||||
}
|
||||
|
||||
|
||||
void listen(std::size_t queue_size) {
|
||||
if (0 != ::listen(this->_value, queue_size)) {
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
@ -236,36 +178,23 @@ namespace LdH::Sockets {
|
||||
static_assert(Berkeley::BerkeleySocketsContext<_WinsockContext>);
|
||||
|
||||
|
||||
export using IPv4Address = Berkeley::IPv4Address<_WinsockContext>;
|
||||
export using IPv6Address = Berkeley::IPv6Address<_WinsockContext>;
|
||||
export using Address = Berkeley::Address<_WinsockContext>;
|
||||
|
||||
export
|
||||
template<class addr_t, class sock_t>
|
||||
using SocketWithAddress = Berkeley::SocketWithAddress<addr_t, sock_t>;
|
||||
template<class sock_t>
|
||||
using SocketWithAddress = Berkeley::SocketWithAddress<_WinsockContext, sock_t>;
|
||||
|
||||
export using StreamSocket = Berkeley::StreamSocket<_WinsockContext>;
|
||||
|
||||
export
|
||||
template<class addr_t>
|
||||
using StreamSocketsServer = Berkeley::StreamSocketsServer<_WinsockContext, addr_t>;
|
||||
export using StreamSocketsServer = Berkeley::StreamSocketsServer<_WinsockContext>;
|
||||
|
||||
export
|
||||
StreamSocket connect_tcp(IPv4Address addr, std::uint_least16_t port) {
|
||||
return Berkeley::connect_tcp<_WinsockContext, IPv4Address>(addr, port);
|
||||
StreamSocket connect_tcp(Address addr) {
|
||||
return Berkeley::connect_tcp<_WinsockContext>(addr);
|
||||
}
|
||||
|
||||
export
|
||||
StreamSocket connect_tcp(IPv6Address addr, std::uint_least16_t port) {
|
||||
return Berkeley::connect_tcp<_WinsockContext, IPv6Address>(addr, port);
|
||||
}
|
||||
|
||||
export
|
||||
StreamSocketsServer<IPv4Address> listen_tcp(IPv4Address addr, std::uint_least16_t port, std::size_t queue_size) {
|
||||
return Berkeley::listen_tcp<_WinsockContext, IPv4Address>(addr, port, queue_size);
|
||||
}
|
||||
|
||||
export
|
||||
StreamSocketsServer<IPv6Address> listen_tcp(IPv6Address addr, std::uint_least16_t port, std::size_t queue_size) {
|
||||
return Berkeley::listen_tcp<_WinsockContext, IPv6Address>(addr, port, queue_size);
|
||||
StreamSocketsServer listen_tcp(Address addr, std::size_t queue_size) {
|
||||
return Berkeley::listen_tcp<_WinsockContext>(addr, queue_size);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user