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 -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(p); - return reinterpret_cast(q); -} - IPv4Address::IPv4Address(SocketAddress src) noexcept - :address(*CastToIPv4(src.GetAddress())) {} + :address(src.CastTo()) +{ + assert(!src.IsNull()); + assert(src.GetFamily() == AF_INET); +} 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()); } 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,18 +34,12 @@ #include -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(p); - return reinterpret_cast(q); -} - IPv6Address::IPv6Address(SocketAddress src) noexcept - :address(*CastToIPv6(src.GetAddress())) {} + :address(src.CastTo()) +{ + assert(!src.IsNull()); + assert(src.GetFamily() == AF_INET6); +} 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()); } 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 + * Copyright 2012-2020 Max Kellermann * * 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(); 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()); case AF_INET6: - return ::GetSteadyPart(*(const struct sockaddr_in6 *)(const void *)GetAddress()); + return ::GetSteadyPart(CastTo()); #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 + * Copyright 2012-2020 Max Kellermann * * 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 + constexpr const T &CastTo() const noexcept { + /* cast through void to work around the bogus + alignment warning */ + const void *q = reinterpret_cast(address); + return *reinterpret_cast(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 + constexpr const T &CastTo() const noexcept { + /* cast through void to work around the bogus + alignment warning */ + const void *q = reinterpret_cast(&address); + return *reinterpret_cast(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 + * Copyright 2011-2020 Max Kellermann * * 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(), 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 + * Copyright 2011-2020 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions