diff options
| author | 2021-03-02 17:08:47 -0800 | |
|---|---|---|
| committer | 2021-03-02 17:08:47 -0800 | |
| commit | f8bfec31095b8ccc7883dbff49472f6c0ce2dec8 (patch) | |
| tree | 0c3fe3ba20f294d1fac2c89019204eec528c57f4 /src | |
| parent | Merge pull request #6020 from bunnei/shutdown-crash-2 (diff) | |
| parent | [network] Error handling reform (diff) | |
| download | yuzu-f8bfec31095b8ccc7883dbff49472f6c0ce2dec8.tar.gz yuzu-f8bfec31095b8ccc7883dbff49472f6c0ce2dec8.tar.xz yuzu-f8bfec31095b8ccc7883dbff49472f6c0ce2dec8.zip | |
Merge pull request #5815 from comex/net-error-reform
Network error handling reform
Diffstat (limited to '')
| -rw-r--r-- | src/common/common_funcs.h | 6 | ||||
| -rw-r--r-- | src/common/misc.cpp | 44 | ||||
| -rw-r--r-- | src/core/network/network.cpp | 173 | ||||
| -rw-r--r-- | src/core/network/network.h | 6 | ||||
| -rw-r--r-- | src/tests/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/tests/core/network/network.cpp | 28 |
6 files changed, 147 insertions, 111 deletions
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index 71b64e32a..4ace2cd33 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h | |||
| @@ -52,9 +52,13 @@ __declspec(dllimport) void __stdcall DebugBreak(void); | |||
| 52 | // Generic function to get last error message. | 52 | // Generic function to get last error message. |
| 53 | // Call directly after the command or use the error num. | 53 | // Call directly after the command or use the error num. |
| 54 | // This function might change the error code. | 54 | // This function might change the error code. |
| 55 | // Defined in Misc.cpp. | 55 | // Defined in misc.cpp. |
| 56 | [[nodiscard]] std::string GetLastErrorMsg(); | 56 | [[nodiscard]] std::string GetLastErrorMsg(); |
| 57 | 57 | ||
| 58 | // Like GetLastErrorMsg(), but passing an explicit error code. | ||
| 59 | // Defined in misc.cpp. | ||
| 60 | [[nodiscard]] std::string NativeErrorToString(int e); | ||
| 61 | |||
| 58 | #define DECLARE_ENUM_FLAG_OPERATORS(type) \ | 62 | #define DECLARE_ENUM_FLAG_OPERATORS(type) \ |
| 59 | [[nodiscard]] constexpr type operator|(type a, type b) noexcept { \ | 63 | [[nodiscard]] constexpr type operator|(type a, type b) noexcept { \ |
| 60 | using T = std::underlying_type_t<type>; \ | 64 | using T = std::underlying_type_t<type>; \ |
diff --git a/src/common/misc.cpp b/src/common/misc.cpp index 1d5393597..495385b9e 100644 --- a/src/common/misc.cpp +++ b/src/common/misc.cpp | |||
| @@ -12,27 +12,41 @@ | |||
| 12 | 12 | ||
| 13 | #include "common/common_funcs.h" | 13 | #include "common/common_funcs.h" |
| 14 | 14 | ||
| 15 | // Generic function to get last error message. | 15 | std::string NativeErrorToString(int e) { |
| 16 | // Call directly after the command or use the error num. | ||
| 17 | // This function might change the error code. | ||
| 18 | std::string GetLastErrorMsg() { | ||
| 19 | static constexpr std::size_t buff_size = 255; | ||
| 20 | char err_str[buff_size]; | ||
| 21 | |||
| 22 | #ifdef _WIN32 | 16 | #ifdef _WIN32 |
| 23 | FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(), | 17 | LPSTR err_str; |
| 24 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err_str, buff_size, nullptr); | 18 | |
| 25 | return std::string(err_str, buff_size); | 19 | DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 26 | #elif defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)) | 20 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 21 | nullptr, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | ||
| 22 | reinterpret_cast<LPSTR>(&err_str), 1, nullptr); | ||
| 23 | if (!res) { | ||
| 24 | return "(FormatMessageA failed to format error)"; | ||
| 25 | } | ||
| 26 | std::string ret(err_str); | ||
| 27 | LocalFree(err_str); | ||
| 28 | return ret; | ||
| 29 | #else | ||
| 30 | char err_str[255]; | ||
| 31 | #if defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)) | ||
| 27 | // Thread safe (GNU-specific) | 32 | // Thread safe (GNU-specific) |
| 28 | const char* str = strerror_r(errno, err_str, buff_size); | 33 | const char* str = strerror_r(e, err_str, sizeof(err_str)); |
| 29 | return std::string(str); | 34 | return std::string(str); |
| 30 | #else | 35 | #else |
| 31 | // Thread safe (XSI-compliant) | 36 | // Thread safe (XSI-compliant) |
| 32 | const int success = strerror_r(errno, err_str, buff_size); | 37 | int second_err = strerror_r(e, err_str, sizeof(err_str)); |
| 33 | if (success != 0) { | 38 | if (second_err != 0) { |
| 34 | return {}; | 39 | return "(strerror_r failed to format error)"; |
| 35 | } | 40 | } |
| 36 | return std::string(err_str); | 41 | return std::string(err_str); |
| 42 | #endif // GLIBC etc. | ||
| 43 | #endif // _WIN32 | ||
| 44 | } | ||
| 45 | |||
| 46 | std::string GetLastErrorMsg() { | ||
| 47 | #ifdef _WIN32 | ||
| 48 | return NativeErrorToString(GetLastError()); | ||
| 49 | #else | ||
| 50 | return NativeErrorToString(errno); | ||
| 37 | #endif | 51 | #endif |
| 38 | } | 52 | } |
diff --git a/src/core/network/network.cpp b/src/core/network/network.cpp index 681e93468..526bfa110 100644 --- a/src/core/network/network.cpp +++ b/src/core/network/network.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <limits> | 7 | #include <limits> |
| 8 | #include <utility> | 8 | #include <utility> |
| 9 | #include <vector> | 9 | #include <vector> |
| 10 | #include "common/common_funcs.h" | ||
| 10 | 11 | ||
| 11 | #ifdef _WIN32 | 12 | #ifdef _WIN32 |
| 12 | #define _WINSOCK_DEPRECATED_NO_WARNINGS // gethostname | 13 | #define _WINSOCK_DEPRECATED_NO_WARNINGS // gethostname |
| @@ -90,15 +91,36 @@ LINGER MakeLinger(bool enable, u32 linger_value) { | |||
| 90 | return value; | 91 | return value; |
| 91 | } | 92 | } |
| 92 | 93 | ||
| 93 | int LastError() { | ||
| 94 | return WSAGetLastError(); | ||
| 95 | } | ||
| 96 | |||
| 97 | bool EnableNonBlock(SOCKET fd, bool enable) { | 94 | bool EnableNonBlock(SOCKET fd, bool enable) { |
| 98 | u_long value = enable ? 1 : 0; | 95 | u_long value = enable ? 1 : 0; |
| 99 | return ioctlsocket(fd, FIONBIO, &value) != SOCKET_ERROR; | 96 | return ioctlsocket(fd, FIONBIO, &value) != SOCKET_ERROR; |
| 100 | } | 97 | } |
| 101 | 98 | ||
| 99 | Errno TranslateNativeError(int e) { | ||
| 100 | switch (e) { | ||
| 101 | case WSAEBADF: | ||
| 102 | return Errno::BADF; | ||
| 103 | case WSAEINVAL: | ||
| 104 | return Errno::INVAL; | ||
| 105 | case WSAEMFILE: | ||
| 106 | return Errno::MFILE; | ||
| 107 | case WSAENOTCONN: | ||
| 108 | return Errno::NOTCONN; | ||
| 109 | case WSAEWOULDBLOCK: | ||
| 110 | return Errno::AGAIN; | ||
| 111 | case WSAECONNREFUSED: | ||
| 112 | return Errno::CONNREFUSED; | ||
| 113 | case WSAEHOSTUNREACH: | ||
| 114 | return Errno::HOSTUNREACH; | ||
| 115 | case WSAENETDOWN: | ||
| 116 | return Errno::NETDOWN; | ||
| 117 | case WSAENETUNREACH: | ||
| 118 | return Errno::NETUNREACH; | ||
| 119 | default: | ||
| 120 | return Errno::OTHER; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 102 | #elif YUZU_UNIX // ^ _WIN32 v YUZU_UNIX | 124 | #elif YUZU_UNIX // ^ _WIN32 v YUZU_UNIX |
| 103 | 125 | ||
| 104 | using SOCKET = int; | 126 | using SOCKET = int; |
| @@ -108,9 +130,6 @@ using ULONG = u64; | |||
| 108 | constexpr SOCKET INVALID_SOCKET = -1; | 130 | constexpr SOCKET INVALID_SOCKET = -1; |
| 109 | constexpr SOCKET SOCKET_ERROR = -1; | 131 | constexpr SOCKET SOCKET_ERROR = -1; |
| 110 | 132 | ||
| 111 | constexpr int WSAEWOULDBLOCK = EAGAIN; | ||
| 112 | constexpr int WSAENOTCONN = ENOTCONN; | ||
| 113 | |||
| 114 | constexpr int SD_RECEIVE = SHUT_RD; | 133 | constexpr int SD_RECEIVE = SHUT_RD; |
| 115 | constexpr int SD_SEND = SHUT_WR; | 134 | constexpr int SD_SEND = SHUT_WR; |
| 116 | constexpr int SD_BOTH = SHUT_RDWR; | 135 | constexpr int SD_BOTH = SHUT_RDWR; |
| @@ -162,10 +181,6 @@ linger MakeLinger(bool enable, u32 linger_value) { | |||
| 162 | return value; | 181 | return value; |
| 163 | } | 182 | } |
| 164 | 183 | ||
| 165 | int LastError() { | ||
| 166 | return errno; | ||
| 167 | } | ||
| 168 | |||
| 169 | bool EnableNonBlock(int fd, bool enable) { | 184 | bool EnableNonBlock(int fd, bool enable) { |
| 170 | int flags = fcntl(fd, F_GETFD); | 185 | int flags = fcntl(fd, F_GETFD); |
| 171 | if (flags == -1) { | 186 | if (flags == -1) { |
| @@ -179,8 +194,43 @@ bool EnableNonBlock(int fd, bool enable) { | |||
| 179 | return fcntl(fd, F_SETFD, flags) == 0; | 194 | return fcntl(fd, F_SETFD, flags) == 0; |
| 180 | } | 195 | } |
| 181 | 196 | ||
| 197 | Errno TranslateNativeError(int e) { | ||
| 198 | switch (e) { | ||
| 199 | case EBADF: | ||
| 200 | return Errno::BADF; | ||
| 201 | case EINVAL: | ||
| 202 | return Errno::INVAL; | ||
| 203 | case EMFILE: | ||
| 204 | return Errno::MFILE; | ||
| 205 | case ENOTCONN: | ||
| 206 | return Errno::NOTCONN; | ||
| 207 | case EAGAIN: | ||
| 208 | return Errno::AGAIN; | ||
| 209 | case ECONNREFUSED: | ||
| 210 | return Errno::CONNREFUSED; | ||
| 211 | case EHOSTUNREACH: | ||
| 212 | return Errno::HOSTUNREACH; | ||
| 213 | case ENETDOWN: | ||
| 214 | return Errno::NETDOWN; | ||
| 215 | case ENETUNREACH: | ||
| 216 | return Errno::NETUNREACH; | ||
| 217 | default: | ||
| 218 | return Errno::OTHER; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 182 | #endif | 222 | #endif |
| 183 | 223 | ||
| 224 | Errno GetAndLogLastError() { | ||
| 225 | #ifdef _WIN32 | ||
| 226 | int e = WSAGetLastError(); | ||
| 227 | #else | ||
| 228 | int e = errno; | ||
| 229 | #endif | ||
| 230 | LOG_ERROR(Network, "Socket operation error: {}", NativeErrorToString(e)); | ||
| 231 | return TranslateNativeError(e); | ||
| 232 | } | ||
| 233 | |||
| 184 | int TranslateDomain(Domain domain) { | 234 | int TranslateDomain(Domain domain) { |
| 185 | switch (domain) { | 235 | switch (domain) { |
| 186 | case Domain::INET: | 236 | case Domain::INET: |
| @@ -290,9 +340,7 @@ Errno SetSockOpt(SOCKET fd, int option, T value) { | |||
| 290 | if (result != SOCKET_ERROR) { | 340 | if (result != SOCKET_ERROR) { |
| 291 | return Errno::SUCCESS; | 341 | return Errno::SUCCESS; |
| 292 | } | 342 | } |
| 293 | const int ec = LastError(); | 343 | return GetAndLogLastError(); |
| 294 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 295 | return Errno::SUCCESS; | ||
| 296 | } | 344 | } |
| 297 | 345 | ||
| 298 | } // Anonymous namespace | 346 | } // Anonymous namespace |
| @@ -308,14 +356,12 @@ NetworkInstance::~NetworkInstance() { | |||
| 308 | std::pair<IPv4Address, Errno> GetHostIPv4Address() { | 356 | std::pair<IPv4Address, Errno> GetHostIPv4Address() { |
| 309 | std::array<char, 256> name{}; | 357 | std::array<char, 256> name{}; |
| 310 | if (gethostname(name.data(), static_cast<int>(name.size()) - 1) == SOCKET_ERROR) { | 358 | if (gethostname(name.data(), static_cast<int>(name.size()) - 1) == SOCKET_ERROR) { |
| 311 | UNIMPLEMENTED_MSG("Unhandled gethostname error"); | 359 | return {IPv4Address{}, GetAndLogLastError()}; |
| 312 | return {IPv4Address{}, Errno::SUCCESS}; | ||
| 313 | } | 360 | } |
| 314 | 361 | ||
| 315 | hostent* const ent = gethostbyname(name.data()); | 362 | hostent* const ent = gethostbyname(name.data()); |
| 316 | if (!ent) { | 363 | if (!ent) { |
| 317 | UNIMPLEMENTED_MSG("Unhandled gethostbyname error"); | 364 | return {IPv4Address{}, GetAndLogLastError()}; |
| 318 | return {IPv4Address{}, Errno::SUCCESS}; | ||
| 319 | } | 365 | } |
| 320 | if (ent->h_addr_list == nullptr) { | 366 | if (ent->h_addr_list == nullptr) { |
| 321 | UNIMPLEMENTED_MSG("No addr provided in hostent->h_addr_list"); | 367 | UNIMPLEMENTED_MSG("No addr provided in hostent->h_addr_list"); |
| @@ -359,9 +405,7 @@ std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) { | |||
| 359 | 405 | ||
| 360 | ASSERT(result == SOCKET_ERROR); | 406 | ASSERT(result == SOCKET_ERROR); |
| 361 | 407 | ||
| 362 | const int ec = LastError(); | 408 | return {-1, GetAndLogLastError()}; |
| 363 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 364 | return {-1, Errno::SUCCESS}; | ||
| 365 | } | 409 | } |
| 366 | 410 | ||
| 367 | Socket::~Socket() { | 411 | Socket::~Socket() { |
| @@ -380,9 +424,7 @@ Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) { | |||
| 380 | return Errno::SUCCESS; | 424 | return Errno::SUCCESS; |
| 381 | } | 425 | } |
| 382 | 426 | ||
| 383 | const int ec = LastError(); | 427 | return GetAndLogLastError(); |
| 384 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 385 | return Errno::SUCCESS; | ||
| 386 | } | 428 | } |
| 387 | 429 | ||
| 388 | std::pair<Socket::AcceptResult, Errno> Socket::Accept() { | 430 | std::pair<Socket::AcceptResult, Errno> Socket::Accept() { |
| @@ -391,9 +433,7 @@ std::pair<Socket::AcceptResult, Errno> Socket::Accept() { | |||
| 391 | const SOCKET new_socket = accept(fd, &addr, &addrlen); | 433 | const SOCKET new_socket = accept(fd, &addr, &addrlen); |
| 392 | 434 | ||
| 393 | if (new_socket == INVALID_SOCKET) { | 435 | if (new_socket == INVALID_SOCKET) { |
| 394 | const int ec = LastError(); | 436 | return {AcceptResult{}, GetAndLogLastError()}; |
| 395 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 396 | return {AcceptResult{}, Errno::SUCCESS}; | ||
| 397 | } | 437 | } |
| 398 | 438 | ||
| 399 | AcceptResult result; | 439 | AcceptResult result; |
| @@ -412,23 +452,14 @@ Errno Socket::Connect(SockAddrIn addr_in) { | |||
| 412 | return Errno::SUCCESS; | 452 | return Errno::SUCCESS; |
| 413 | } | 453 | } |
| 414 | 454 | ||
| 415 | switch (const int ec = LastError()) { | 455 | return GetAndLogLastError(); |
| 416 | case WSAEWOULDBLOCK: | ||
| 417 | LOG_DEBUG(Service, "EAGAIN generated"); | ||
| 418 | return Errno::AGAIN; | ||
| 419 | default: | ||
| 420 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 421 | return Errno::SUCCESS; | ||
| 422 | } | ||
| 423 | } | 456 | } |
| 424 | 457 | ||
| 425 | std::pair<SockAddrIn, Errno> Socket::GetPeerName() { | 458 | std::pair<SockAddrIn, Errno> Socket::GetPeerName() { |
| 426 | sockaddr addr; | 459 | sockaddr addr; |
| 427 | socklen_t addrlen = sizeof(addr); | 460 | socklen_t addrlen = sizeof(addr); |
| 428 | if (getpeername(fd, &addr, &addrlen) == SOCKET_ERROR) { | 461 | if (getpeername(fd, &addr, &addrlen) == SOCKET_ERROR) { |
| 429 | const int ec = LastError(); | 462 | return {SockAddrIn{}, GetAndLogLastError()}; |
| 430 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 431 | return {SockAddrIn{}, Errno::SUCCESS}; | ||
| 432 | } | 463 | } |
| 433 | 464 | ||
| 434 | ASSERT(addrlen == sizeof(sockaddr_in)); | 465 | ASSERT(addrlen == sizeof(sockaddr_in)); |
| @@ -439,9 +470,7 @@ std::pair<SockAddrIn, Errno> Socket::GetSockName() { | |||
| 439 | sockaddr addr; | 470 | sockaddr addr; |
| 440 | socklen_t addrlen = sizeof(addr); | 471 | socklen_t addrlen = sizeof(addr); |
| 441 | if (getsockname(fd, &addr, &addrlen) == SOCKET_ERROR) { | 472 | if (getsockname(fd, &addr, &addrlen) == SOCKET_ERROR) { |
| 442 | const int ec = LastError(); | 473 | return {SockAddrIn{}, GetAndLogLastError()}; |
| 443 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 444 | return {SockAddrIn{}, Errno::SUCCESS}; | ||
| 445 | } | 474 | } |
| 446 | 475 | ||
| 447 | ASSERT(addrlen == sizeof(sockaddr_in)); | 476 | ASSERT(addrlen == sizeof(sockaddr_in)); |
| @@ -454,9 +483,7 @@ Errno Socket::Bind(SockAddrIn addr) { | |||
| 454 | return Errno::SUCCESS; | 483 | return Errno::SUCCESS; |
| 455 | } | 484 | } |
| 456 | 485 | ||
| 457 | const int ec = LastError(); | 486 | return GetAndLogLastError(); |
| 458 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 459 | return Errno::SUCCESS; | ||
| 460 | } | 487 | } |
| 461 | 488 | ||
| 462 | Errno Socket::Listen(s32 backlog) { | 489 | Errno Socket::Listen(s32 backlog) { |
| @@ -464,9 +491,7 @@ Errno Socket::Listen(s32 backlog) { | |||
| 464 | return Errno::SUCCESS; | 491 | return Errno::SUCCESS; |
| 465 | } | 492 | } |
| 466 | 493 | ||
| 467 | const int ec = LastError(); | 494 | return GetAndLogLastError(); |
| 468 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 469 | return Errno::SUCCESS; | ||
| 470 | } | 495 | } |
| 471 | 496 | ||
| 472 | Errno Socket::Shutdown(ShutdownHow how) { | 497 | Errno Socket::Shutdown(ShutdownHow how) { |
| @@ -489,14 +514,7 @@ Errno Socket::Shutdown(ShutdownHow how) { | |||
| 489 | return Errno::SUCCESS; | 514 | return Errno::SUCCESS; |
| 490 | } | 515 | } |
| 491 | 516 | ||
| 492 | switch (const int ec = LastError()) { | 517 | return GetAndLogLastError(); |
| 493 | case WSAENOTCONN: | ||
| 494 | LOG_ERROR(Service, "ENOTCONN generated"); | ||
| 495 | return Errno::NOTCONN; | ||
| 496 | default: | ||
| 497 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 498 | return Errno::SUCCESS; | ||
| 499 | } | ||
| 500 | } | 518 | } |
| 501 | 519 | ||
| 502 | std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) { | 520 | std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) { |
| @@ -509,17 +527,7 @@ std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) { | |||
| 509 | return {static_cast<s32>(result), Errno::SUCCESS}; | 527 | return {static_cast<s32>(result), Errno::SUCCESS}; |
| 510 | } | 528 | } |
| 511 | 529 | ||
| 512 | switch (const int ec = LastError()) { | 530 | return {-1, GetAndLogLastError()}; |
| 513 | case WSAEWOULDBLOCK: | ||
| 514 | LOG_DEBUG(Service, "EAGAIN generated"); | ||
| 515 | return {-1, Errno::AGAIN}; | ||
| 516 | case WSAENOTCONN: | ||
| 517 | LOG_ERROR(Service, "ENOTCONN generated"); | ||
| 518 | return {-1, Errno::NOTCONN}; | ||
| 519 | default: | ||
| 520 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 521 | return {0, Errno::SUCCESS}; | ||
| 522 | } | ||
| 523 | } | 531 | } |
| 524 | 532 | ||
| 525 | std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) { | 533 | std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) { |
| @@ -541,17 +549,7 @@ std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, Sock | |||
| 541 | return {static_cast<s32>(result), Errno::SUCCESS}; | 549 | return {static_cast<s32>(result), Errno::SUCCESS}; |
| 542 | } | 550 | } |
| 543 | 551 | ||
| 544 | switch (const int ec = LastError()) { | 552 | return {-1, GetAndLogLastError()}; |
| 545 | case WSAEWOULDBLOCK: | ||
| 546 | LOG_DEBUG(Service, "EAGAIN generated"); | ||
| 547 | return {-1, Errno::AGAIN}; | ||
| 548 | case WSAENOTCONN: | ||
| 549 | LOG_ERROR(Service, "ENOTCONN generated"); | ||
| 550 | return {-1, Errno::NOTCONN}; | ||
| 551 | default: | ||
| 552 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 553 | return {-1, Errno::SUCCESS}; | ||
| 554 | } | ||
| 555 | } | 553 | } |
| 556 | 554 | ||
| 557 | std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) { | 555 | std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) { |
| @@ -564,18 +562,7 @@ std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) { | |||
| 564 | return {static_cast<s32>(result), Errno::SUCCESS}; | 562 | return {static_cast<s32>(result), Errno::SUCCESS}; |
| 565 | } | 563 | } |
| 566 | 564 | ||
| 567 | const int ec = LastError(); | 565 | return {-1, GetAndLogLastError()}; |
| 568 | switch (ec) { | ||
| 569 | case WSAEWOULDBLOCK: | ||
| 570 | LOG_DEBUG(Service, "EAGAIN generated"); | ||
| 571 | return {-1, Errno::AGAIN}; | ||
| 572 | case WSAENOTCONN: | ||
| 573 | LOG_ERROR(Service, "ENOTCONN generated"); | ||
| 574 | return {-1, Errno::NOTCONN}; | ||
| 575 | default: | ||
| 576 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 577 | return {-1, Errno::SUCCESS}; | ||
| 578 | } | ||
| 579 | } | 566 | } |
| 580 | 567 | ||
| 581 | std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message, | 568 | std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message, |
| @@ -597,9 +584,7 @@ std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message, | |||
| 597 | return {static_cast<s32>(result), Errno::SUCCESS}; | 584 | return {static_cast<s32>(result), Errno::SUCCESS}; |
| 598 | } | 585 | } |
| 599 | 586 | ||
| 600 | const int ec = LastError(); | 587 | return {-1, GetAndLogLastError()}; |
| 601 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 602 | return {-1, Errno::SUCCESS}; | ||
| 603 | } | 588 | } |
| 604 | 589 | ||
| 605 | Errno Socket::Close() { | 590 | Errno Socket::Close() { |
| @@ -642,9 +627,7 @@ Errno Socket::SetNonBlock(bool enable) { | |||
| 642 | if (EnableNonBlock(fd, enable)) { | 627 | if (EnableNonBlock(fd, enable)) { |
| 643 | return Errno::SUCCESS; | 628 | return Errno::SUCCESS; |
| 644 | } | 629 | } |
| 645 | const int ec = LastError(); | 630 | return GetAndLogLastError(); |
| 646 | UNREACHABLE_MSG("Unhandled host socket error={}", ec); | ||
| 647 | return Errno::SUCCESS; | ||
| 648 | } | 631 | } |
| 649 | 632 | ||
| 650 | bool Socket::IsOpened() const { | 633 | bool Socket::IsOpened() const { |
diff --git a/src/core/network/network.h b/src/core/network/network.h index 76b2821f2..bd30f1899 100644 --- a/src/core/network/network.h +++ b/src/core/network/network.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <utility> | 8 | #include <utility> |
| 9 | 9 | ||
| 10 | #include "common/common_funcs.h" | ||
| 10 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 11 | 12 | ||
| 12 | namespace Network { | 13 | namespace Network { |
| @@ -21,6 +22,11 @@ enum class Errno { | |||
| 21 | MFILE, | 22 | MFILE, |
| 22 | NOTCONN, | 23 | NOTCONN, |
| 23 | AGAIN, | 24 | AGAIN, |
| 25 | CONNREFUSED, | ||
| 26 | HOSTUNREACH, | ||
| 27 | NETDOWN, | ||
| 28 | NETUNREACH, | ||
| 29 | OTHER, | ||
| 24 | }; | 30 | }; |
| 25 | 31 | ||
| 26 | /// Address families | 32 | /// Address families |
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 4ea0076e9..d875c4fee 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt | |||
| @@ -5,6 +5,7 @@ add_executable(tests | |||
| 5 | common/param_package.cpp | 5 | common/param_package.cpp |
| 6 | common/ring_buffer.cpp | 6 | common/ring_buffer.cpp |
| 7 | core/core_timing.cpp | 7 | core/core_timing.cpp |
| 8 | core/network/network.cpp | ||
| 8 | tests.cpp | 9 | tests.cpp |
| 9 | video_core/buffer_base.cpp | 10 | video_core/buffer_base.cpp |
| 10 | ) | 11 | ) |
diff --git a/src/tests/core/network/network.cpp b/src/tests/core/network/network.cpp new file mode 100644 index 000000000..b21ad8911 --- /dev/null +++ b/src/tests/core/network/network.cpp | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <catch2/catch.hpp> | ||
| 6 | |||
| 7 | #include "core/network/network.h" | ||
| 8 | #include "core/network/sockets.h" | ||
| 9 | |||
| 10 | TEST_CASE("Network::Errors", "[core]") { | ||
| 11 | Network::NetworkInstance network_instance; // initialize network | ||
| 12 | |||
| 13 | Network::Socket socks[2]; | ||
| 14 | for (Network::Socket& sock : socks) { | ||
| 15 | REQUIRE(sock.Initialize(Network::Domain::INET, Network::Type::STREAM, | ||
| 16 | Network::Protocol::TCP) == Network::Errno::SUCCESS); | ||
| 17 | } | ||
| 18 | |||
| 19 | Network::SockAddrIn addr{ | ||
| 20 | Network::Domain::INET, | ||
| 21 | {127, 0, 0, 1}, | ||
| 22 | 1, // hopefully nobody running this test has something listening on port 1 | ||
| 23 | }; | ||
| 24 | REQUIRE(socks[0].Connect(addr) == Network::Errno::CONNREFUSED); | ||
| 25 | |||
| 26 | std::vector<u8> message{1, 2, 3, 4}; | ||
| 27 | REQUIRE(socks[1].Recv(0, message).second == Network::Errno::NOTCONN); | ||
| 28 | } | ||