net/SocketAddress: add CastTo()

This commit is contained in:
Max Kellermann 2020-11-30 21:35:43 +01:00 committed by Max Kellermann
parent 32ce9ce919
commit 273771ffec
9 changed files with 46 additions and 36 deletions

View File

@ -31,15 +31,9 @@
#include <cassert> #include <cassert>
static const struct sockaddr_in *
CastToIPv4(const struct sockaddr *p) noexcept
{
assert(p->sa_family == AF_INET);
/* cast through void to work around the bogus alignment warning */
const void *q = reinterpret_cast<const void *>(p);
return reinterpret_cast<const struct sockaddr_in *>(q);
}
IPv4Address::IPv4Address(SocketAddress src) noexcept IPv4Address::IPv4Address(SocketAddress src) noexcept
:address(*CastToIPv4(src.GetAddress())) {} :address(src.CastTo<struct sockaddr_in>())
{
assert(!src.IsNull());
assert(src.GetFamily() == AF_INET);
}

View File

@ -171,9 +171,7 @@ public:
* only legal after verifying SocketAddress::GetFamily(). * only legal after verifying SocketAddress::GetFamily().
*/ */
static constexpr const IPv4Address &Cast(const SocketAddress src) noexcept { static constexpr const IPv4Address &Cast(const SocketAddress src) noexcept {
/* this reinterpret_cast works because this class is return Cast(src.CastTo<struct sockaddr_in>());
just a wrapper for struct sockaddr_in */
return *(const IPv4Address *)(const void *)src.GetAddress();
} }
constexpr operator SocketAddress() const noexcept { constexpr operator SocketAddress() const noexcept {

View File

@ -34,18 +34,12 @@
#include <string.h> #include <string.h>
static const struct sockaddr_in6 *
CastToIPv6(const struct sockaddr *p) noexcept
{
assert(p->sa_family == AF_INET6);
/* cast through void to work around the bogus alignment warning */
const void *q = reinterpret_cast<const void *>(p);
return reinterpret_cast<const struct sockaddr_in6 *>(q);
}
IPv6Address::IPv6Address(SocketAddress src) noexcept IPv6Address::IPv6Address(SocketAddress src) noexcept
:address(*CastToIPv6(src.GetAddress())) {} :address(src.CastTo<struct sockaddr_in6>())
{
assert(!src.IsNull());
assert(src.GetFamily() == AF_INET6);
}
bool bool
IPv6Address::IsAny() const noexcept IPv6Address::IsAny() const noexcept

View File

@ -140,9 +140,7 @@ public:
* only legal after verifying SocketAddress::GetFamily(). * only legal after verifying SocketAddress::GetFamily().
*/ */
static constexpr const IPv6Address &Cast(const SocketAddress src) noexcept { static constexpr const IPv6Address &Cast(const SocketAddress src) noexcept {
/* this reinterpret_cast works because this class is return Cast(src.CastTo<struct sockaddr_in6>());
just a wrapper for struct sockaddr_in6 */
return *(const IPv6Address *)(const void *)src.GetAddress();
} }
constexpr operator SocketAddress() const noexcept { constexpr operator SocketAddress() const noexcept {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2019 Max Kellermann <max.kellermann@gmail.com> * Copyright 2012-2020 Max Kellermann <max.kellermann@gmail.com>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -63,7 +63,7 @@ SocketAddress::GetLocalRaw() const noexcept
/* not applicable */ /* not applicable */
return nullptr; return nullptr;
const auto sun = (const struct sockaddr_un *)GetAddress(); const auto *sun = &CastTo<struct sockaddr_un>();
const auto start = (const char *)sun; const auto start = (const char *)sun;
const auto path = sun->sun_path; const auto path = sun->sun_path;
const size_t header_size = path - start; const size_t header_size = path - start;
@ -159,10 +159,10 @@ SocketAddress::GetSteadyPart() const noexcept
#ifdef HAVE_TCP #ifdef HAVE_TCP
case AF_INET: case AF_INET:
return ::GetSteadyPart(*(const struct sockaddr_in *)(const void *)GetAddress()); return ::GetSteadyPart(CastTo<struct sockaddr_in>());
case AF_INET6: case AF_INET6:
return ::GetSteadyPart(*(const struct sockaddr_in6 *)(const void *)GetAddress()); return ::GetSteadyPart(CastTo<struct sockaddr_in6>());
#endif #endif
default: default:

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2019 Max Kellermann <max.kellermann@gmail.com> * Copyright 2012-2020 Max Kellermann <max.kellermann@gmail.com>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -82,6 +82,19 @@ public:
return address; return address;
} }
/**
* Cast the "sockaddr" pointer to a different address type,
* e.g. "sockaddr_in". This is only legal after checking
* !IsNull() and GetFamily().
*/
template<typename T>
constexpr const T &CastTo() const noexcept {
/* cast through void to work around the bogus
alignment warning */
const void *q = reinterpret_cast<const void *>(address);
return *reinterpret_cast<const T *>(q);
}
constexpr size_type GetSize() const noexcept { constexpr size_type GetSize() const noexcept {
return size; return size;
} }

View File

@ -68,6 +68,19 @@ public:
return (const struct sockaddr *)(const void *)&address; return (const struct sockaddr *)(const void *)&address;
} }
/**
* Cast the "sockaddr" pointer to a different address type,
* e.g. "sockaddr_in". This is only legal after checking
* GetFamily().
*/
template<typename T>
constexpr const T &CastTo() const noexcept {
/* cast through void to work around the bogus
alignment warning */
const void *q = reinterpret_cast<const void *>(&address);
return *reinterpret_cast<const T *>(q);
}
constexpr size_type GetCapacity() const noexcept { constexpr size_type GetCapacity() const noexcept {
return sizeof(address); return sizeof(address);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2011-2019 Max Kellermann <max.kellermann@gmail.com> * Copyright 2011-2020 Max Kellermann <max.kellermann@gmail.com>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -85,7 +85,7 @@ ToString(SocketAddress address) noexcept
#ifdef HAVE_UN #ifdef HAVE_UN
if (address.GetFamily() == AF_LOCAL) if (address.GetFamily() == AF_LOCAL)
/* return path of local socket */ /* return path of local socket */
return LocalAddressToString(*(const sockaddr_un *)address.GetAddress(), return LocalAddressToString(address.CastTo<struct sockaddr_un>(),
address.GetSize()); address.GetSize());
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2011-2019 Max Kellermann <max.kellermann@gmail.com> * Copyright 2011-2020 Max Kellermann <max.kellermann@gmail.com>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions