From cb1bc956b2ae2f33327095bc3bab49128bc87252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 24 Feb 2022 18:28:41 +0100 Subject: [PATCH] Network: Fix posix implementation --- src/Nazara/Network/Posix/IpAddressImpl.cpp | 100 +++++++-------------- src/Nazara/Network/Posix/SocketImpl.cpp | 28 ++---- src/Nazara/Network/Win32/IpAddressImpl.cpp | 12 +-- 3 files changed, 39 insertions(+), 101 deletions(-) diff --git a/src/Nazara/Network/Posix/IpAddressImpl.cpp b/src/Nazara/Network/Posix/IpAddressImpl.cpp index 0fd890144..0f82e8d1e 100644 --- a/src/Nazara/Network/Posix/IpAddressImpl.cpp +++ b/src/Nazara/Network/Posix/IpAddressImpl.cpp @@ -13,64 +13,6 @@ namespace Nz { - namespace Detail - { - using addrinfoImpl = addrinfo; - - int GetAddressInfo(const std::string& hostname, const std::string& service, const addrinfoImpl* hints, addrinfoImpl** results) - { - return getaddrinfo(hostname.c_str(), service.c_str(), hints, results); - } - - int GetHostnameInfo(sockaddr* socketAddress, socklen_t socketLen, std::string* hostname, std::string* service, int flags) - { - std::array hostnameBuffer; - std::array serviceBuffer; - - int result = getnameinfo(socketAddress, socketLen, hostnameBuffer.data(), hostnameBuffer.size(), serviceBuffer.data(), serviceBuffer.size(), flags); - if (result == 0) - { - if (hostname) - hostname->assign(hostnameBuffer.data()); - - if (service) - service->assign(serviceBuffer.data()); - } - - return result; - } - - void FreeAddressInfo(addrinfoImpl* results) - { - freeaddrinfo(results); - } - - IpAddress::IPv4 convertSockaddrToIPv4(const in_addr& addr) - { - union byteToInt - { - UInt8 b[sizeof(uint32_t)]; - uint32_t i; - }; - - byteToInt hostOrder; - hostOrder.i = ntohl(addr.s_addr); - - return { {hostOrder.b[3], hostOrder.b[2], hostOrder.b[1], hostOrder.b[0]} }; - } - - IpAddress::IPv6 convertSockaddr6ToIPv6(const in6_addr& addr) - { - auto& rawIpV6 = addr.s6_addr; - - IpAddress::IPv6 ipv6; - for (unsigned int i = 0; i < 8; ++i) - ipv6[i] = Nz::UInt16(rawIpV6[i * 2]) << 8 | rawIpV6[i * 2 + 1]; - - return ipv6; - } - } - IpAddress IpAddressImpl::FromAddrinfo(const addrinfo* info) { switch (info->ai_family) @@ -109,14 +51,21 @@ namespace Nz IpAddress IpAddressImpl::FromSockAddr(const sockaddr_in* addressv4) { - IpAddress::IPv4 ip4Address = Detail::convertSockaddrToIPv4(addressv4->sin_addr); - return IpAddress(ip4Address, ntohs(addressv4->sin_port)); + IpAddress::IPv4 ipv4; + std::memcpy(&ipv4[0], &addressv4->sin_addr.s_addr, sizeof(uint32_t)); //< addr.s_addr is in big-endian so its already correctly ordered + + return IpAddress(ipv4, ntohs(addressv4->sin_port)); } IpAddress IpAddressImpl::FromSockAddr(const sockaddr_in6* addressv6) { - IpAddress::IPv6 ip6Address = Detail::convertSockaddr6ToIPv6(addressv6->sin6_addr); - return IpAddress(ip6Address, ntohs(addressv6->sin6_port)); + auto& rawIpV6 = addressv6->sin6_addr.s6_addr; + + IpAddress::IPv6 ipv6; + for (unsigned int i = 0; i < 8; ++i) + ipv6[i] = UInt16(rawIpV6[i * 2]) << 8 | rawIpV6[i * 2 + 1]; + + return IpAddress(ipv6, ntohs(addressv6->sin6_port)); } bool IpAddressImpl::ResolveAddress(const IpAddress& ipAddress, std::string* hostname, std::string* service, ResolveError* error) @@ -124,7 +73,10 @@ namespace Nz SockAddrBuffer socketAddress; socklen_t socketAddressLen = ToSockAddr(ipAddress, socketAddress.data()); - if (Detail::GetHostnameInfo(reinterpret_cast(socketAddress.data()), socketAddressLen, hostname, service, NI_NUMERICSERV) != 0) + std::array hostnameBuffer; + std::array serviceBuffer; + + if (getnameinfo(reinterpret_cast(socketAddress.data()), socketAddressLen, hostnameBuffer.data(), hostnameBuffer.size(), serviceBuffer.data(), serviceBuffer.size(), NI_NUMERICSERV) != 0) { if (error) *error = TranslateEAIErrorToResolveError(errno); @@ -132,6 +84,12 @@ namespace Nz return false; } + if (hostname) + hostname->assign(hostnameBuffer.data()); + + if (service) + service->assign(serviceBuffer.data()); + if (error) *error = ResolveError::NoError; @@ -142,14 +100,14 @@ namespace Nz { std::vector results; - Detail::addrinfoImpl hints; - std::memset(&hints, 0, sizeof(Detail::addrinfoImpl)); + addrinfo hints; + std::memset(&hints, 0, sizeof(addrinfo)); hints.ai_family = SocketImpl::TranslateNetProtocolToAF(procol); hints.ai_flags = AI_CANONNAME; hints.ai_socktype = SOCK_STREAM; - Detail::addrinfoImpl* servinfo; - if (Detail::GetAddressInfo(hostname, service, &hints, &servinfo) != 0) + addrinfo* servinfo; + if (getaddrinfo(hostname.c_str(), service.c_str(), &hints, &servinfo) != 0) { if (error) *error = TranslateEAIErrorToResolveError(errno); @@ -159,18 +117,20 @@ namespace Nz CallOnExit onExit([servinfo]() { - Detail::FreeAddressInfo(servinfo); + freeaddrinfo(servinfo); }); // loop through all the results and connect to the first we can - for (Detail::addrinfoImpl* p = servinfo; p != nullptr; p = p->ai_next) + for (addrinfo* p = servinfo; p != nullptr; p = p->ai_next) { HostnameInfo result; result.address = FromAddrinfo(p); - result.canonicalName = p->ai_canonname; result.protocol = TranslatePFToNetProtocol(p->ai_family); result.socketType = TranslateSockToNetProtocol(p->ai_socktype); + if (p->ai_canonname) + result.canonicalName = p->ai_canonname; + results.push_back(result); } diff --git a/src/Nazara/Network/Posix/SocketImpl.cpp b/src/Nazara/Network/Posix/SocketImpl.cpp index fd8529ab9..1b194bce4 100644 --- a/src/Nazara/Network/Posix/SocketImpl.cpp +++ b/src/Nazara/Network/Posix/SocketImpl.cpp @@ -211,8 +211,8 @@ namespace Nz { NazaraAssert(handle != InvalidHandle, "Invalid handle"); - u_long availableBytes; - if (ioctl(handle, FIONREAD, &availableBytes) == -1) + int availableBytes; + if (ioctl(handle, FIONREAD, &availableBytes) != 0) { if (error) *error = TranslateErrorToSocketError(errno); @@ -223,7 +223,7 @@ namespace Nz if (error) *error = SocketError::NoError; - return availableBytes; + return SafeCast(availableBytes); } bool SocketImpl::QueryBroadcasting(SocketHandle handle, SocketError* error) @@ -266,25 +266,9 @@ namespace Nz std::size_t SocketImpl::QueryMaxDatagramSize(SocketHandle handle, SocketError* error) { - int code; - socklen_t codeLength = sizeof(code); - -#if defined(NAZARA_PLATFORM_MACOSX) - return 0; //No IP_MTU on macosx -#else - if (getsockopt(handle, IPPROTO_IP, IP_MTU, &code, &codeLength) == -1) - { - if (error) - *error = TranslateErrorToSocketError(errno); - - return 0; - } -#endif - - if (error) - *error = SocketError::NoError; - - return code; + // There's no SO_MAX_MSG_SIZE on POSIX + // We could use IP_MTU but it requires a connected socket + return std::min(QuerySendBufferSize(handle, error), 65507); //< Max IPv4 value (IPv6 is 65527) } bool SocketImpl::QueryNoDelay(SocketHandle handle, SocketError* error) diff --git a/src/Nazara/Network/Win32/IpAddressImpl.cpp b/src/Nazara/Network/Win32/IpAddressImpl.cpp index 5541eb855..b0cb828e2 100644 --- a/src/Nazara/Network/Win32/IpAddressImpl.cpp +++ b/src/Nazara/Network/Win32/IpAddressImpl.cpp @@ -57,9 +57,6 @@ namespace Nz std::string TranslateCanonicalName(const wchar_t* str) { - if (!str) - return {}; - return FromWideString(str); } #else @@ -95,9 +92,6 @@ namespace Nz std::string TranslateCanonicalName(const char* str) { - if (!str) - return {}; - return str; } #endif @@ -225,13 +219,13 @@ namespace Nz for (Detail::addrinfoImpl* p = servinfo; p != nullptr; p = p->ai_next) { - HostnameInfo result; + HostnameInfo& result = results.emplace_back(); result.address = FromAddrinfo(p); - result.canonicalName = Detail::TranslateCanonicalName(p->ai_canonname); result.protocol = TranslatePFToNetProtocol(p->ai_family); result.socketType = TranslateSockToNetProtocol(p->ai_socktype); - results.push_back(result); + if (p->ai_canonname) + result.canonicalName = Detail::TranslateCanonicalName(p->ai_canonname); } if (error)