/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuNetError.cpp Date-Initial: 2022-2-1 (rejected net, to replace knet) Date-Revisited: 2022-8-17 Author: Reece ***/ #include "Networking.hpp" #include "AuNetError.hpp" #if defined(AURORA_IS_MODERNNT_DERIVED) #if !defined(STATUS_BUFFER_TOO_SMALL) #define STATUS_BUFFER_TOO_SMALL ((AuUInt) 0xc0000023) #endif #if !defined(STATUS_ACCESS_DENIED) #define STATUS_ACCESS_DENIED ((AuUInt) 0xc0000022) #endif #endif namespace Aurora::IO::Net { void NetError_SetCurrent(NetError &error) { #if defined(AURORA_IS_MODERNNT_DERIVED) NetError_SetOsError(error, ::WSAGetLastError()); #elif defined(AURORA_IS_POSIX_DERIVED) NetError_SetOsError(error, errno); #endif } void NetError_SetOsError(NetError &error, AuUInt value) { error.osError = value; #if defined(AURORA_IS_MODERNNT_DERIVED) switch (value) { case WSA_INVALID_HANDLE: case WSA_INVALID_PARAMETER: case WSAEDESTADDRREQ: case WSAEPROTOTYPE: case WSAEFAULT: case WSAEINVAL: case WSAEBADF: case WSAENOTSOCK: error.netError = ENetworkError::eIllegalArgument; break; case WSAETIMEDOUT: error.netError = ENetworkError::eTimeout; break; case WSAEMSGSIZE: case WSAENOBUFS: case (AuUInt)STATUS_BUFFER_TOO_SMALL: error.netError = ENetworkError::eSocketBufferOverflow; break; case WSA_OPERATION_ABORTED: case WSAESHUTDOWN: case WSAENOTCONN: case WSAEDISCON: error.netError = ENetworkError::eSocketClosed; break; case WSAEACCES: case WSAEPROTONOSUPPORT: case WSAEPFNOSUPPORT: case WSAEAFNOSUPPORT: case (AuUInt)STATUS_ACCESS_DENIED: error.netError = ENetworkError::ePermissionDenied; break; case WSA_IO_INCOMPLETE: case WSAEINTR: case WSAEALREADY: case WSAECANCELLED: case WSAEINPROGRESS: error.netError = ENetworkError::eAsyncError; break; case WSAEADDRINUSE: error.netError = ENetworkError::eServiceTaken; break; case WSAEADDRNOTAVAIL: case WSAEHOSTUNREACH: case WSAEHOSTDOWN: error.netError = ENetworkError::eEndpointRefused; break; case WSAECONNREFUSED: error.netError = ENetworkError::eServiceRefused; break; case WSAECONNABORTED: error.netError = ENetworkError::eConnectionReset; break; case WSAENETUNREACH: error.netError = ENetworkError::eUnreachable; break; case WSAENETDOWN: case WSAVERNOTSUPPORTED: case WSANOTINITIALISED: error.netError = ENetworkError::eNoNetwork; break; case WSA_NOT_ENOUGH_MEMORY: case WSAEWOULDBLOCK: error.netError = ENetworkError::eResourceConstraint; break; default: error.netError = ENetworkError::eUnknown; break; case WSA_IO_PENDING: error.netError = ENetworkError::eEnumInvalid; break; } #elif defined(AURORA_IS_POSIX_DERIVED) switch (value) { case EACCES: case EPERM: error.netError = ENetworkError::ePermissionDenied; break; case EAFNOSUPPORT: case EPROTONOSUPPORT: case EPROTOTYPE: error.netError = ENetworkError::eBadAddress; break; case EMFILE: case ENFILE: case ENOBUFS: error.netError = ENetworkError::eResourceConstraint; break; case ECONNRESET: error.netError = ENetworkError::eConnectionReset; break; case ESHUTDOWN: case ENOTCONN: error.netError = ENetworkError::eSocketClosed; break; case ENOTSOCK: case EFAULT: case EINVAL: case EBADF: error.netError = ENetworkError::eIllegalArgument; break; case EADDRINUSE: error.netError = ENetworkError::eServiceTaken; break; case EADDRNOTAVAIL: case EHOSTUNREACH: case EHOSTDOWN: error.netError = ENetworkError::eEndpointRefused; break; case ECONNREFUSED: error.netError = ENetworkError::eServiceRefused; break; case ECONNABORTED: error.netError = ENetworkError::eConnectionReset; break; case ENETUNREACH: error.netError = ENetworkError::eUnreachable; break; case EMSGSIZE: // "However, the receiving program did not have // "enough free file descriptor slots to accept them" - recvfrom error.netError = ENetworkError::eResourceConstraint; break; } #endif } static AuString StringifyOSError(AuUInt32 dwErrorCode) { #if defined(AURORA_IS_MODERNNT_DERIVED) LPSTR messageBuffer {}; size_t size = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); if (!messageBuffer) { return {}; } AuString message(messageBuffer, size); ::LocalFree(messageBuffer); return message; #else return ::strerror(dwErrorCode); #endif } AUKN_SYM AuString NetErrorToExtendedString(const NetError &error) { return fmt::format("error: {}, code: 0x{:x}, os: {}", NetErrorToString(error), error.osError, StringifyOSError(error.osError)); } AUKN_SYM AuString NetErrorToString(const NetError &error) { return ENetworkErrorToString(error.netError); } }