Commit 273771ff authored by Max Kellermann's avatar Max Kellermann Committed by Max Kellermann

net/SocketAddress: add CastTo()

parent 32ce9ce9
......@@ -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())) {}
......@@ -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 {
......
......@@ -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
{
......
......@@ -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 {
......
/*
* 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:
......
/*
* 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;
}
......
......@@ -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);
}
......
/*
* 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
......
/*
* 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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment