Network: Add ResolveError handling

Former-commit-id: 0dc3d109284e8b475577bf44cbaeb503c4baae73
This commit is contained in:
Lynix 2015-11-10 13:24:25 +01:00
parent 5f0aa64555
commit 4ad1a47064
5 changed files with 83 additions and 14 deletions

View File

@ -9,6 +9,22 @@
namespace Nz
{
enum ResolveError
{
ResolveError_NoError,
ResolveError_Internal, //< An internal error occured
ResolveError_ResourceError, //< The operating system lacks the resources to proceed (insufficient memory)
ResolveError_NonRecoverable, //< An nonrecoverable error occured
ResolveError_NotFound, //< No such host is known
ResolveError_NotInitialized, //< Nazara network has not been initialized
ResolveError_ProtocolNotSupported, //< A specified protocol is not supported by the server
ResolveError_TemporaryFailure, //< A temporary failure occured, try again
ResolveError_Unknown, //< The last operation failed with an unlisted error code
ResolveError_Max = ResolveError_TemporaryFailure
};
enum NetProtocol
{
NetProtocol_Any,

View File

@ -55,8 +55,8 @@ namespace Nz
IpAddress& operator=(const IpAddress&) = default;
IpAddress& operator=(IpAddress&&) = default;
static String ResolveAddress(const IpAddress& address, String* service = nullptr);
static std::vector<HostnameInfo> ResolveHostname(NetProtocol procol, const String& hostname, const String& protocol = "http");
static String ResolveAddress(const IpAddress& address, String* service = nullptr, ResolveError* error = nullptr);
static std::vector<HostnameInfo> ResolveHostname(NetProtocol procol, const String& hostname, const String& protocol = "http", ResolveError* error = nullptr);
inline friend std::ostream& operator<<(std::ostream& out, const IpAddress& address);

View File

@ -142,17 +142,17 @@ namespace Nz
return stream;
}
String IpAddress::ResolveAddress(const IpAddress& address, String* service)
String IpAddress::ResolveAddress(const IpAddress& address, String* service, ResolveError* error)
{
String hostname;
IpAddressImpl::ResolveAddress(address, &hostname, service);
IpAddressImpl::ResolveAddress(address, &hostname, service, error);
return hostname;
}
std::vector<HostnameInfo> IpAddress::ResolveHostname(NetProtocol protocol, const String& hostname, const String& service)
std::vector<HostnameInfo> IpAddress::ResolveHostname(NetProtocol protocol, const String& hostname, const String& service, ResolveError* error)
{
return IpAddressImpl::ResolveHostname(protocol, hostname, service);
return IpAddressImpl::ResolveHostname(protocol, hostname, service, error);
}
IpAddress IpAddress::AnyIpV4(0, 0, 0, 0);

View File

@ -147,15 +147,26 @@ namespace Nz
return IpAddress(rawIpV6[0], rawIpV6[1], rawIpV6[2], rawIpV6[3], rawIpV6[4], rawIpV6[5], rawIpV6[6], rawIpV6[7], ntohs(addressv6->sin6_port));
}
bool IpAddressImpl::ResolveAddress(const IpAddress& ipAddress, String* hostname, String* service)
bool IpAddressImpl::ResolveAddress(const IpAddress& ipAddress, String* hostname, String* service, ResolveError* error)
{
SockAddrBuffer socketAddress;
socklen_t socketAddressLen = ToSockAddr(ipAddress, socketAddress.data());
return Detail::GetHostnameInfo(reinterpret_cast<sockaddr*>(socketAddress.data()), socketAddressLen, hostname, service) == 0;
if (Detail::GetHostnameInfo(reinterpret_cast<sockaddr*>(socketAddress.data()), socketAddressLen, hostname, service) != 0)
{
if (error)
*error = TranslateWSAErrorToResolveError(WSAGetLastError());
return false;
}
if (error)
*error = ResolveError_NoError;
return true;
}
std::vector<HostnameInfo> IpAddressImpl::ResolveHostname(NetProtocol procol, const String& hostname, const String& service)
std::vector<HostnameInfo> IpAddressImpl::ResolveHostname(NetProtocol procol, const String& hostname, const String& service, ResolveError* error)
{
std::vector<HostnameInfo> results;
@ -165,10 +176,11 @@ namespace Nz
hints.ai_socktype = SOCK_STREAM;
Detail::addrinfoImpl* servinfo;
int rv;
if ((rv = Detail::GetAddressInfo(hostname, service, &hints, &servinfo)) != 0)
if (Detail::GetAddressInfo(hostname, service, &hints, &servinfo) != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
if (error)
*error = TranslateWSAErrorToResolveError(WSAGetLastError());
return results;
}
@ -190,6 +202,9 @@ namespace Nz
results.push_back(result);
}
if (error)
*error = ResolveError_NoError;
return results;
}
@ -237,4 +252,41 @@ namespace Nz
NazaraError("Invalid ip address");
return 0;
}
ResolveError IpAddressImpl::TranslateWSAErrorToResolveError(int error)
{
switch (error)
{
case 0:
return ResolveError_NoError;
// Engine error
case WSAEFAULT:
case WSAEINVAL:
return ResolveError_Internal;
case WSAEAFNOSUPPORT:
case WSAESOCKTNOSUPPORT:
case WSASERVICE_NOT_FOUND:
return ResolveError_ProtocolNotSupported;
case WSAHOST_NOT_FOUND:
return ResolveError_NotFound;
case WSANO_RECOVERY:
return ResolveError_NonRecoverable;
case WSANOTINITIALISED:
return ResolveError_NotInitialized;
case WSA_NOT_ENOUGH_MEMORY:
return ResolveError_ResourceError;
case WSATRY_AGAIN:
return ResolveError_TemporaryFailure;
}
NazaraWarning("Unhandled WinSock error: " + Error::GetLastSystemError(error) + " (" + String::Number(error) + ')');
return ResolveError_Unknown;
}
}

View File

@ -22,9 +22,10 @@ namespace Nz
static IpAddress FromSockAddr(const sockaddr_in* addressv4);
static IpAddress FromSockAddr(const sockaddr_in6* addressv6);
static bool ResolveAddress(const IpAddress& ipAddress, String* hostname, String* service);
static std::vector<HostnameInfo> ResolveHostname(NetProtocol procol, const String& hostname, const String& service);
static bool ResolveAddress(const IpAddress& ipAddress, String* hostname, String* service, ResolveError* error);
static std::vector<HostnameInfo> ResolveHostname(NetProtocol procol, const String& hostname, const String& service, ResolveError* error);
static socklen_t ToSockAddr(const IpAddress& ipAddress, void* buffer);
static ResolveError TranslateWSAErrorToResolveError(int error);
};
}