summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <mk@cm4all.com>2020-11-30 21:35:43 +0100
committerMax Kellermann <max@musicpd.org>2020-11-30 21:51:07 +0100
commit273771ffecfcc575b3941ef51751326fd7f592e8 (patch)
tree312b9e7f07a587b02ff1b71ea3dc7cc95d20a43b
parent32ce9ce91946886cd0b443a3f4c1fc5f5ab07254 (diff)
net/SocketAddress: add CastTo()
-rw-r--r--src/net/IPv4Address.cxx14
-rw-r--r--src/net/IPv4Address.hxx4
-rw-r--r--src/net/IPv6Address.cxx14
-rw-r--r--src/net/IPv6Address.hxx4
-rw-r--r--src/net/SocketAddress.cxx8
-rw-r--r--src/net/SocketAddress.hxx15
-rw-r--r--src/net/StaticSocketAddress.hxx13
-rw-r--r--src/net/ToString.cxx4
-rw-r--r--src/net/ToString.hxx2
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