1#include "SockAddress.h"
11void copyNumericAddress( std::string_view address,
char (&buffer)[INET6_ADDRSTRLEN])
16 if( address.empty() ||
17 address.size() >=
sizeof(buffer) ||
18 address.find(
'\0') != std::string_view::npos)
23 std::memcpy( buffer, address.data(), address.size());
24 buffer[address.size()] =
'\0';
27void checkInetPtonResult(
int result,
const char* invalidMessage)
29 if (result == 1)
return;
39SockAddress::SockAddress( AddressFamily family, std::string_view address,
unsigned short port)
41 char text[INET6_ADDRSTRLEN];
43 copyNumericAddress(address, text);
45 switch (nativeFamily(family))
50 addr.sin_family = AF_INET;
51 addr.sin_port = htons(port);
52 const int result = ::inet_pton(AF_INET, text, &addr.sin_addr);
53 checkInetPtonResult(result,
"Invalid IPv4 address");
54 store(addr,
sizeof(addr));
60 addr.sin6_family = AF_INET6;
61 addr.sin6_port = htons(port);
62 const int result = ::inet_pton(AF_INET6, text, &addr.sin6_addr);
63 checkInetPtonResult(result,
"Invalid IPv6 address");
64 store(addr,
sizeof(addr));
68 throw SocketException(
"Unsupported address family",
false);
72SockAddress::SockAddress( AddressFamily family,
unsigned short port)
74 switch (nativeFamily(family))
79 addr.sin_family = AF_INET;
80 addr.sin_port = htons(port);
81 addr.sin_addr.s_addr = htonl(INADDR_ANY);
82 store( addr,
sizeof(addr));
88 addr.sin6_family = AF_INET6;
89 addr.sin6_port = htons(port);
90 addr.sin6_addr = in6addr_any;
91 store( addr,
sizeof(addr));
95 throw SocketException(
"Unsupported address family",
false);
99SockAddress::SockAddress( std::string_view path)
102 addr.sun_family = AF_UNIX;
107 path.size() >=
sizeof(addr.sun_path) ||
108 path.find(
'\0') != std::string_view::npos)
110 throw SocketException(
"Invalid Unix socket path",
false);
113 std::memcpy( addr.sun_path, path.data(), path.size());
114 addr.sun_path[path.size()] =
'\0';
116 const auto length =
static_cast<socklen_t
>( offsetof(sockaddr_un, sun_path) + path.size() + 1);
117 store( addr, length);
120sockaddr* SockAddress::data() noexcept
122 return reinterpret_cast<sockaddr*
>(&m_storage);
125const sockaddr* SockAddress::data() const noexcept
127 return reinterpret_cast<const sockaddr*
>(&m_storage);
130socklen_t SockAddress::length() const noexcept
135sa_family_t SockAddress::family() const noexcept
137 return m_storage.ss_family;
140bool SockAddress::empty() const noexcept
142 return m_storage.ss_family == AF_UNSPEC;
145socklen_t* SockAddress::lengthPtr() noexcept
148 m_length =
sizeof(m_storage);
152unsigned short SockAddress::port() const noexcept
159 std::memcpy( &addr, &m_storage,
sizeof(addr));
160 return ntohs(addr.sin_port);
165 std::memcpy( &addr, &m_storage,
sizeof(addr));
166 return ntohs(addr.sin6_port);
173std::string SockAddress::address()
const
175 char buffer[INET6_ADDRSTRLEN];
182 std::memcpy(&addr, &m_storage,
sizeof(addr));
184 if (::inet_ntop( AF_INET, &addr.sin_addr, buffer,
sizeof(buffer)) ==
nullptr)
185 throw SocketException(
"Address conversion failed (inet_ntop)");
192 std::memcpy(&addr, &m_storage,
sizeof(addr));
194 if (::inet_ntop( AF_INET6, &addr.sin6_addr, buffer,
sizeof(buffer)) ==
nullptr)
195 throw SocketException(
"Address conversion failed (inet_ntop)");
202 std::memcpy(&addr, &m_storage,
sizeof(addr));
204 constexpr std::size_t offset = offsetof(sockaddr_un, sun_path);
205 if (m_length <= offset)
return {};
207 std::size_t length =
static_cast<std::size_t
>(m_length) - offset;
209 if (length >
sizeof(addr.sun_path))
210 length =
sizeof(addr.sun_path);
214 if (length != 0 && addr.sun_path[length - 1] ==
'\0')
217 return std::string(addr.sun_path, length);
222 throw SocketException(
"Unsupported address family",
false);
226sa_family_t SockAddress::nativeFamily( AddressFamily family)
noexcept
230 case AddressFamily::IPv4:
return AF_INET;
231 case AddressFamily::IPv6:
return AF_INET6;
Signals a problem with the execution of a socket call.