Skip to content

Commit c9e02d5

Browse files
committed
Introduce union based type punning for GCC 6 compat
1 parent 90a734f commit c9e02d5

3 files changed

Lines changed: 37 additions & 40 deletions

File tree

cmake/EnableWarnings.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ function(enable_warnings target)
4040
ALL
4141
-Wno-unused-command-line-argument
4242
CXX
43+
-fno-strict-aliasing
4344
-pedantic-errors
4445
-Qunused-arguments
4546
-Wcast-qual

libs/network/include/s25util/Socket.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ struct addrinfo;
4343
#include <string>
4444
#include <vector>
4545

46+
/// used for type punning
47+
union address_t
48+
{
49+
sockaddr sa;
50+
sockaddr_in sa_in;
51+
sockaddr_in6 sa_in6;
52+
sockaddr_storage sa_stor;
53+
};
54+
4655
/// liefert Ip-Adresse(n) für einen Hostnamen.
4756
struct HostAddr
4857
{
@@ -71,7 +80,7 @@ class ResolvedAddr
7180

7281
class PeerAddr
7382
{
74-
sockaddr_storage addr;
83+
address_t addr;
7584

7685
public:
7786
/// Uninitilized value!

libs/network/src/Socket.cpp

Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,13 @@ ResolvedAddr::ResolvedAddr(const HostAddr& hostAddr, bool resolveAll) : lookup((
9696

9797
if(hostAddr.ipv6)
9898
{
99-
auto* addr6 = (sockaddr_in6*)addr->ai_addr;
99+
auto* addr6 = reinterpret_cast<sockaddr_in6*>(addr->ai_addr);
100100
addr6->sin6_family = AF_INET6;
101101
addr6->sin6_port = htons(s25util::fromStringClassic<unsigned short>(hostAddr.port));
102102
addr6->sin6_addr = in6addr_loopback;
103103
} else
104104
{
105-
auto* addr4 = (sockaddr_in*)addr->ai_addr;
105+
auto* addr4 = reinterpret_cast<sockaddr_in*>(addr->ai_addr);
106106
addr4->sin_family = AF_INET;
107107
addr4->sin_port = htons(s25util::fromStringClassic<unsigned short>(hostAddr.port));
108108
addr4->sin_addr.s_addr = inet_addr("127.0.0.1");
@@ -125,9 +125,9 @@ ResolvedAddr::~ResolvedAddr()
125125

126126
PeerAddr::PeerAddr(unsigned short port)
127127
{
128-
addr.ss_family = AF_INET;
129-
reinterpret_cast<sockaddr_in&>(addr).sin_addr.s_addr = INADDR_BROADCAST;
130-
reinterpret_cast<sockaddr_in&>(addr).sin_port = htons(port);
128+
addr.sa_in.sin_family = AF_INET;
129+
addr.sa_in.sin_addr.s_addr = INADDR_BROADCAST;
130+
addr.sa_in.sin_port = htons(port);
131131
}
132132

133133
std::string PeerAddr::GetIp() const
@@ -137,12 +137,12 @@ std::string PeerAddr::GetIp() const
137137

138138
sockaddr* PeerAddr::GetAddr()
139139
{
140-
return reinterpret_cast<sockaddr*>(&addr);
140+
return &addr.sa;
141141
}
142142

143143
const sockaddr* PeerAddr::GetAddr() const
144144
{
145-
return reinterpret_cast<const sockaddr*>(&addr);
145+
return &addr.sa;
146146
}
147147

148148
Socket::Socket()
@@ -786,15 +786,15 @@ int Socket::BytesWaiting(unsigned* received) const
786786
*/
787787
std::string Socket::GetPeerIP() const
788788
{
789-
sockaddr_storage peer;
790-
socklen_t length = sizeof(sockaddr_storage);
789+
address_t peer;
790+
socklen_t length = sizeof(peer);
791791

792792
// Remotehost-Adresse holen
793-
if(getpeername(socket_, (sockaddr*)&peer, &length) == SOCKET_ERROR)
793+
if(getpeername(socket_, &peer.sa, &length) == SOCKET_ERROR)
794794
return "";
795795

796796
// in Text verwandeln
797-
return IpToString((sockaddr*)&peer);
797+
return IpToString(&peer.sa);
798798
}
799799

800800
/**
@@ -804,15 +804,15 @@ std::string Socket::GetPeerIP() const
804804
*/
805805
std::string Socket::GetSockIP() const
806806
{
807-
sockaddr_storage peer;
808-
socklen_t length = sizeof(sockaddr_storage);
807+
address_t peer;
808+
socklen_t length = sizeof(peer);
809809

810810
// Localhost-Adresse holen
811-
if(getsockname(socket_, (sockaddr*)&peer, &length) == SOCKET_ERROR)
811+
if(getsockname(socket_, &peer.sa, &length) == SOCKET_ERROR)
812812
return "";
813813

814814
// in Text verwandeln
815-
return IpToString((sockaddr*)&peer);
815+
return IpToString(&peer.sa);
816816
}
817817

818818
/**
@@ -832,44 +832,31 @@ SOCKET Socket::GetSocket() const
832832
std::string Socket::IpToString(const sockaddr* addr)
833833
{
834834
std::array<char, 256> temp{};
835-
836-
#ifdef _WIN32
837-
union
838-
{
839-
sockaddr base;
840-
sockaddr_in ipv4;
841-
sockaddr_in6 ipv6;
842-
} copy;
843-
std::memset(&copy, 0, sizeof(copy));
835+
address_t addrCopy{};
844836
size_t size;
845837
if(addr->sa_family == AF_INET)
846838
{
847839
size = sizeof(sockaddr_in);
848-
std::memcpy(&copy.ipv4, addr, size);
849-
copy.ipv4.sin_port = 0;
840+
std::memcpy(&addrCopy.sa_in, addr, size);
850841
} else
851842
{
852843
size = sizeof(sockaddr_in6);
853-
std::memcpy(&copy.ipv6, addr, size);
854-
copy.ipv6.sin6_port = 0;
844+
std::memcpy(&addrCopy.sa_in6, addr, size);
855845
}
856846

857-
DWORD le = GetLastError();
858-
DWORD templen = sizeof(temp);
859-
WSAAddressToStringA(&copy.base, static_cast<DWORD>(size), nullptr, temp.data(), &templen);
847+
#ifdef _WIN32
848+
const auto le = GetLastError();
849+
DWORD templen = temp.size();
850+
WSAAddressToStringA(&addrCopy.sa, static_cast<DWORD>(size), nullptr, temp.data(), &templen);
860851
SetLastError(le);
861852
#else
862853
const void* ip;
863-
864854
if(addr->sa_family == AF_INET)
865-
{
866-
ip = &(((const sockaddr_in*)addr)->sin_addr);
867-
} else
868-
{
869-
ip = &(((const sockaddr_in6*)addr)->sin6_addr);
870-
}
855+
ip = &addrCopy.sa_in.sin_addr;
856+
else
857+
ip = &addrCopy.sa_in6.sin6_addr;
871858

872-
inet_ntop(addr->sa_family, ip, temp.data(), sizeof(temp));
859+
inet_ntop(addr->sa_family, ip, temp.data(), temp.size());
873860
#endif
874861

875862
return temp.data();

0 commit comments

Comments
 (0)