Network: Fix posix implementation

This commit is contained in:
Jérôme Leclercq 2022-02-24 18:28:41 +01:00
parent d827477de2
commit cb1bc956b2
3 changed files with 39 additions and 101 deletions

View File

@ -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<char, NI_MAXHOST> hostnameBuffer;
std::array<char, NI_MAXSERV> 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<sockaddr*>(socketAddress.data()), socketAddressLen, hostname, service, NI_NUMERICSERV) != 0)
std::array<char, NI_MAXHOST> hostnameBuffer;
std::array<char, NI_MAXSERV> serviceBuffer;
if (getnameinfo(reinterpret_cast<sockaddr*>(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<HostnameInfo> 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);
}

View File

@ -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<std::size_t>(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<std::size_t>(QuerySendBufferSize(handle, error), 65507); //< Max IPv4 value (IPv6 is 65527)
}
bool SocketImpl::QueryNoDelay(SocketHandle handle, SocketError* error)

View File

@ -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)