diff options
author | Max Kellermann <mk@cm4all.com> | 2020-11-30 21:35:43 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2020-11-30 21:51:07 +0100 |
commit | 273771ffecfcc575b3941ef51751326fd7f592e8 (patch) | |
tree | 312b9e7f07a587b02ff1b71ea3dc7cc95d20a43b | |
parent | 32ce9ce91946886cd0b443a3f4c1fc5f5ab07254 (diff) |
net/SocketAddress: add CastTo()
-rw-r--r-- | src/net/IPv4Address.cxx | 14 | ||||
-rw-r--r-- | src/net/IPv4Address.hxx | 4 | ||||
-rw-r--r-- | src/net/IPv6Address.cxx | 14 | ||||
-rw-r--r-- | src/net/IPv6Address.hxx | 4 | ||||
-rw-r--r-- | src/net/SocketAddress.cxx | 8 | ||||
-rw-r--r-- | src/net/SocketAddress.hxx | 15 | ||||
-rw-r--r-- | src/net/StaticSocketAddress.hxx | 13 | ||||
-rw-r--r-- | src/net/ToString.cxx | 4 | ||||
-rw-r--r-- | src/net/ToString.hxx | 2 |
9 files changed, 44 insertions, 34 deletions
diff --git a/src/net/IPv4Address.cxx b/src/net/IPv4Address.cxx index eeb4f553e..2ff4799ea 100644 --- a/src/net/IPv4Address.cxx +++ b/src/net/IPv4Address.cxx @@ -31,15 +31,9 @@ #include <cassert> -static const struct sockaddr_in * -CastToIPv4(const struct sockaddr *p) noexcept +IPv4Address::IPv4Address(SocketAddress src) noexcept + :address(src.CastTo<struct sockaddr_in>()) { - 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); + assert(!src.IsNull()); + assert(src.GetFamily() == AF_INET); } - -IPv4Address::IPv4Address(SocketAddress src) noexcept - :address(*CastToIPv4(src.GetAddress())) {} diff --git a/src/net/IPv4Address.hxx b/src/net/IPv4Address.hxx index 3f33529cf..58fa89897 100644 --- a/src/net/IPv4Address.hxx +++ b/src/net/IPv4Address.hxx @@ -171,9 +171,7 @@ public: * only legal after verifying SocketAddress::GetFamily(). */ static constexpr const IPv4Address &Cast(const SocketAddress src) noexcept { - /* this reinterpret_cast works because this class is - just a wrapper for struct sockaddr_in */ - return *(const IPv4Address *)(const void *)src.GetAddress(); + return Cast(src.CastTo<struct sockaddr_in>()); } constexpr operator SocketAddress() const noexcept { diff --git a/src/net/IPv6Address.cxx b/src/net/IPv6Address.cxx index 1071c1a77..fcc78dbf6 100644 --- a/src/net/IPv6Address.cxx +++ b/src/net/IPv6Address.cxx @@ -34,19 +34,13 @@ #include <string.h> -static const struct sockaddr_in6 * -CastToIPv6(const struct sockaddr *p) noexcept +IPv6Address::IPv6Address(SocketAddress src) noexcept + :address(src.CastTo<struct sockaddr_in6>()) { - 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); + assert(!src.IsNull()); + assert(src.GetFamily() == AF_INET6); } -IPv6Address::IPv6Address(SocketAddress src) noexcept - :address(*CastToIPv6(src.GetAddress())) {} - bool IPv6Address::IsAny() const noexcept { diff --git a/src/net/IPv6Address.hxx b/src/net/IPv6Address.hxx index 8b53339f5..eaa2db867 100644 --- a/src/net/IPv6Address.hxx +++ b/src/net/IPv6Address.hxx @@ -140,9 +140,7 @@ public: * only legal after verifying SocketAddress::GetFamily(). */ static constexpr const IPv6Address &Cast(const SocketAddress src) noexcept { - /* this reinterpret_cast works because this class is - just a wrapper for struct sockaddr_in6 */ - return *(const IPv6Address *)(const void *)src.GetAddress(); + return Cast(src.CastTo<struct sockaddr_in6>()); } constexpr operator SocketAddress() const noexcept { diff --git a/src/net/SocketAddress.cxx b/src/net/SocketAddress.cxx index 81691982b..1ac78c412 100644 --- a/src/net/SocketAddress.cxx +++ b/src/net/SocketAddress.cxx @@ -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 * modification, are permitted provided that the following conditions @@ -63,7 +63,7 @@ SocketAddress::GetLocalRaw() const noexcept /* not applicable */ 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 path = sun->sun_path; const size_t header_size = path - start; @@ -159,10 +159,10 @@ SocketAddress::GetSteadyPart() const noexcept #ifdef HAVE_TCP case AF_INET: - return ::GetSteadyPart(*(const struct sockaddr_in *)(const void *)GetAddress()); + return ::GetSteadyPart(CastTo<struct sockaddr_in>()); case AF_INET6: - return ::GetSteadyPart(*(const struct sockaddr_in6 *)(const void *)GetAddress()); + return ::GetSteadyPart(CastTo<struct sockaddr_in6>()); #endif default: diff --git a/src/net/SocketAddress.hxx b/src/net/SocketAddress.hxx index cd9a23156..8e9691e8e 100644 --- a/src/net/SocketAddress.hxx +++ b/src/net/SocketAddress.hxx @@ -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 * modification, are permitted provided that the following conditions @@ -82,6 +82,19 @@ public: 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 { return size; } diff --git a/src/net/StaticSocketAddress.hxx b/src/net/StaticSocketAddress.hxx index c86a2a171..85c4e98b6 100644 --- a/src/net/StaticSocketAddress.hxx +++ b/src/net/StaticSocketAddress.hxx @@ -68,6 +68,19 @@ public: 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 { return sizeof(address); } diff --git a/src/net/ToString.cxx b/src/net/ToString.cxx index 7d89cd3a8..87f40569a 100644 --- a/src/net/ToString.cxx +++ b/src/net/ToString.cxx @@ -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 * modification, are permitted provided that the following conditions @@ -85,7 +85,7 @@ ToString(SocketAddress address) noexcept #ifdef HAVE_UN if (address.GetFamily() == AF_LOCAL) /* return path of local socket */ - return LocalAddressToString(*(const sockaddr_un *)address.GetAddress(), + return LocalAddressToString(address.CastTo<struct sockaddr_un>(), address.GetSize()); #endif diff --git a/src/net/ToString.hxx b/src/net/ToString.hxx index fd89020c5..dba482642 100644 --- a/src/net/ToString.hxx +++ b/src/net/ToString.hxx @@ -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 * modification, are permitted provided that the following conditions |