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 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 enum NetProtocol
{ {
NetProtocol_Any, NetProtocol_Any,

View File

@ -55,8 +55,8 @@ namespace Nz
IpAddress& operator=(const IpAddress&) = default; IpAddress& operator=(const IpAddress&) = default;
IpAddress& operator=(IpAddress&&) = default; IpAddress& operator=(IpAddress&&) = default;
static String ResolveAddress(const IpAddress& address, String* service = nullptr); 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"); 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); inline friend std::ostream& operator<<(std::ostream& out, const IpAddress& address);

View File

@ -142,17 +142,17 @@ namespace Nz
return stream; return stream;
} }
String IpAddress::ResolveAddress(const IpAddress& address, String* service) String IpAddress::ResolveAddress(const IpAddress& address, String* service, ResolveError* error)
{ {
String hostname; String hostname;
IpAddressImpl::ResolveAddress(address, &hostname, service); IpAddressImpl::ResolveAddress(address, &hostname, service, error);
return hostname; 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); 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)); 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; SockAddrBuffer socketAddress;
socklen_t socketAddressLen = ToSockAddr(ipAddress, socketAddress.data()); 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; std::vector<HostnameInfo> results;
@ -165,10 +176,11 @@ namespace Nz
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
Detail::addrinfoImpl* servinfo; Detail::addrinfoImpl* servinfo;
int rv; if (Detail::GetAddressInfo(hostname, service, &hints, &servinfo) != 0)
if ((rv = Detail::GetAddressInfo(hostname, service, &hints, &servinfo)) != 0)
{ {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); if (error)
*error = TranslateWSAErrorToResolveError(WSAGetLastError());
return results; return results;
} }
@ -190,6 +202,9 @@ namespace Nz
results.push_back(result); results.push_back(result);
} }
if (error)
*error = ResolveError_NoError;
return results; return results;
} }
@ -237,4 +252,41 @@ namespace Nz
NazaraError("Invalid ip address"); NazaraError("Invalid ip address");
return 0; 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_in* addressv4);
static IpAddress FromSockAddr(const sockaddr_in6* addressv6); static IpAddress FromSockAddr(const sockaddr_in6* addressv6);
static bool ResolveAddress(const IpAddress& ipAddress, String* hostname, 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); 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 socklen_t ToSockAddr(const IpAddress& ipAddress, void* buffer);
static ResolveError TranslateWSAErrorToResolveError(int error);
}; };
} }