10#include <umock/netdb.hpp>
33 const ::sockaddr_storage* a_ss2)
noexcept {
35 if (a_ss1 ==
nullptr && a_ss2 ==
nullptr)
37 if (a_ss1 ==
nullptr || a_ss2 ==
nullptr)
40 switch (a_ss1->ss_family) {
42 if (a_ss2->ss_family != AF_UNSPEC)
50 const ::sockaddr_in6*
const s6_addr1 =
51 reinterpret_cast<const ::sockaddr_in6*
>(a_ss1);
52 const ::sockaddr_in6*
const s6_addr2 =
53 reinterpret_cast<const ::sockaddr_in6*
>(a_ss2);
55 if (a_ss2->ss_family != AF_INET6 ||
56 ::memcmp(&s6_addr1->sin6_addr, &s6_addr2->sin6_addr,
57 sizeof(in6_addr)) != 0 ||
58 s6_addr1->sin6_port != s6_addr2->sin6_port ||
59 s6_addr1->sin6_scope_id != s6_addr2->sin6_scope_id)
64 const ::sockaddr_in*
const s_addr1 =
65 reinterpret_cast<const ::sockaddr_in*
>(a_ss1);
66 const ::sockaddr_in*
const s_addr2 =
67 reinterpret_cast<const ::sockaddr_in*
>(a_ss2);
69 if (a_ss2->ss_family != AF_INET ||
70 s_addr1->sin_addr.s_addr != s_addr2->sin_addr.s_addr ||
71 s_addr1->sin_port != s_addr2->sin_port)
89int to_port(std::string_view a_port_str, in_port_t*
const a_port_num)
noexcept {
90 TRACE(
"Executing to_port() with port=\"a_port_str\"")
103 if (a_port_str.empty()) {
104 if (a_port_num !=
nullptr)
111 for (
char ch : a_port_str) {
112 if (!std::isdigit(
static_cast<unsigned char>(ch))) {
114 }
else if (ch !=
'0') {
120 if (a_port_str.length() > 5) {
132 std::string port_str(a_port_str);
133 int port = atoi(port_str.c_str());
136 std::from_chars(a_port_str.data(), a_port_str.data() + a_port_str.size(),
141 }
else if (a_port_num !=
nullptr) {
144 *a_port_num =
static_cast<in_port_t
>(port);
186 std::string& a_serv) {
187 TRACE(
"Executing split_addr_port()")
190 if (a_addr_str.empty()) {
197 std::string_view addr_str;
198 std::string serv_str;
201 if (a_addr_str.length() < 2) {
204 addr_str = a_addr_str;
206 }
else if (a_addr_str.front() ==
'[') {
208 if ((pos = a_addr_str.find(
"]:")) != std::string::npos) {
209 addr_str = a_addr_str.substr(0, pos + 1);
210 serv_str = a_addr_str.substr(pos + 2);
211 if (serv_str.empty())
214 addr_str = a_addr_str;
217 }
else if (a_addr_str.front() ==
':' && a_addr_str[1] ==
':') {
219 addr_str = a_addr_str;
221 }
else if (a_addr_str.front() ==
':') {
224 switch (
to_port(a_addr_str.substr(1), &port)) {
227 serv_str = a_addr_str.substr(1);
231 serv_str = std::to_string(port);
237 }
else if (a_addr_str.find_first_of(
'.') != std::string::npos) {
239 if ((pos = a_addr_str.find_last_of(
':')) != std::string::npos) {
240 addr_str = a_addr_str.substr(0, pos);
241 serv_str = a_addr_str.substr(pos + 1);
242 if (serv_str.empty())
246 addr_str = a_addr_str;
248 }
else if (std::ranges::count(a_addr_str,
':') == 1) {
250 pos = a_addr_str.find_last_of(
':');
251 addr_str = a_addr_str.substr(0, pos);
252 serv_str = a_addr_str.substr(pos + 1);
253 if (serv_str.empty())
258 switch (
to_port(a_addr_str, &port)) {
262 addr_str = a_addr_str;
266 serv_str = std::to_string(port);
277 if (addr_str.length() >= 4 && addr_str.front() ==
'[' &&
278 addr_str.back() ==
']' && std::ranges::count(addr_str,
':') >= 2) {
283 a_addr = addr_str.substr(1, addr_str.length() - 2);
307 throw std::range_error(
308 UPnPsdk_LOGEXCEPT(
"MSG1127")
"Number string from \"" +
309 std::string(a_addr_str) +
"\" for port is out of range 0..65535.");
316SSockaddr::SSockaddr(){
317 TRACE2(
this,
" Construct SSockaddr()")
321SSockaddr::~SSockaddr() {
322 TRACE2(
this,
" Destruct SSockaddr()")
324 ::memset(&m_sa_union, 0xAA, sizeof(m_sa_union));
336 TRACE2(
this,
" Construct copy SSockaddr()")
337 m_sa_union = that.m_sa_union;
344 " Executing SSockaddr::operator=(SSockaddr) (struct assign op).")
345 std::swap(m_sa_union, that.m_sa_union);
353 TRACE2(
this,
" Executing SSockaddr::operator=(a_addr_str)")
355 if (a_addr_str.empty()) {
357 ::memset(&m_sa_union, 0,
sizeof(m_sa_union));
358 m_sa_union.ss.ss_family = AF_UNSPEC;
361 std::string ai_addr_str;
362 std::string ai_port_str;
369 if (ai_addr_str.empty()) {
372 throw std::invalid_argument(
373 UPnPsdk_LOGEXCEPT(
"MSG1043")
"Invalid netaddress \"" +
374 std::string(a_addr_str) +
"\".\n");
375 m_sa_union.sin6.sin6_port = htons(
port);
382 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
383 hints.ai_family = AF_UNSPEC;
384 ::addrinfo* res{
nullptr};
387 int ret = umock::netdb_h.getaddrinfo(ai_addr_str.c_str(),
388 ai_port_str.c_str(), &hints, &res);
390 umock::netdb_h.freeaddrinfo(res);
391 throw std::invalid_argument(
392 UPnPsdk_LOGEXCEPT(
"MSG1156")
"Invalid netaddress \"" +
393 std::string(a_addr_str) +
"\".\n");
395 if (ai_port_str.empty()) {
397 in_port_t
port = m_sa_union.sin6.sin6_port;
398 ::memcpy(&m_sa_union, res->ai_addr,
sizeof(m_sa_union));
399 m_sa_union.sin6.sin6_port =
port;
401 ::memcpy(&m_sa_union, res->ai_addr,
sizeof(m_sa_union));
403 umock::netdb_h.freeaddrinfo(res);
414 m_sa_union.sin6.sin6_port = htons(a_port);
421 ::memcpy(&m_sa_union, &a_ss,
sizeof(m_sa_union));
427 return sockaddrcmp(&a_saddr.
ss, &
ss);
438 switch (m_sa_union.ss.ss_family) {
445 UPnPsdk_LOGERR(
"MSG1129")
"Unsupported address family "
446 << std::to_string(m_sa_union.ss.ss_family)
447 <<
". Continue with unspecified netaddress \"\".\n";
453 char addrStr[39 + 1 +
456 int ret = ::getnameinfo(&m_sa_union.sa,
sizeof(m_sa_union.ss), addrStr,
457 sizeof(addrStr),
nullptr, 0, NI_NUMERICHOST);
465 "MSG1036")
"Failed to get netaddress with address family "
466 << std::to_string(m_sa_union.ss.ss_family) <<
": "
467 << ::gai_strerror(ret)
468 <<
". Continue with unspecified netaddress \"\".\n";
475 if (m_sa_union.ss.ss_family == AF_INET6)
476 return '[' + std::string(addrStr) +
']';
478 return std::string(addrStr);
494 switch (m_sa_union.ss.ss_family) {
499 std::to_string(ntohs(m_sa_union.sin6.sin6_port));
511 TRACE2(
this,
" Executing SSockaddr::port()")
515 return ntohs(m_sa_union.sin6.sin6_port);
521 TRACE2(
this,
" Executing SSockaddr::sizeof_saddr()")
522 switch (m_sa_union.ss.ss_family) {
524 return sizeof(m_sa_union.sin6);
526 return sizeof(m_sa_union.sin);
528 return sizeof(m_sa_union.ss);
541 m_sa_union.ss.ss_family == AF_INET6 &&
542 (IN6_IS_ADDR_LOOPBACK(&m_sa_union.sin6.sin6_addr) ||
543 (ntohl(
static_cast<uint32_t
>(m_sa_union.sin6.sin6_addr.s6_addr[12])) >=
545 ntohl(
static_cast<uint32_t
>(m_sa_union.sin6.sin6_addr.s6_addr[12])) <=
548 (m_sa_union.ss.ss_family == AF_INET &&
550 ntohl(m_sa_union.sin.sin_addr.s_addr) >= 2130706432 &&
551 ntohl(m_sa_union.sin.sin_addr.s_addr) <= 2147483647));
bool sockaddrcmp(const ::sockaddr_storage *a_ss1, const ::sockaddr_storage *a_ss2) noexcept
logical compare two sockaddr structures
int to_port(std::string_view a_port_str, in_port_t *const a_port_num=nullptr) noexcept
Free function to check if a string represents a valid port number.
UPnPsdk_API::std::ostream & operator<<(::std::ostream &os, SSockaddr &saddr)
output the netaddress
void split_addr_port(std::string_view a_addr_str, std::string &a_addr, std::string &a_serv)
Free function to split inet address and port(service)
Reengineered Object Oriented UPnP+ program code.
Declaration of the Sockaddr class and some free helper functions.
Trivial ::sockaddr structures enhanced with methods.
const std::string netaddrp() noexcept
Get the assosiated netaddress with port.
bool operator==(const SSockaddr &) const
Test if another socket address is logical equal to this.
bool is_loopback() const
Get if the socket address is a loopback address.
SSockaddr & operator=(SSockaddr)
Copy assignment operator, needs user defined copy contructor.
in_port_t port() const
Get the numeric port.
const std::string netaddr() noexcept
Get the assosiated netaddress without port.
sockaddr_storage & ss
Reference to sockaddr_storage struct.
socklen_t sizeof_saddr() const
Get sizeof the current filled (sin6 or sin) Sockaddr Structure.
Define macro for synced logging to the console for detailed info and debug.