diff options
| author | Jordan Woyak <jordan.woyak@gmail.com> | 2026-02-07 20:26:13 -0600 |
|---|---|---|
| committer | Jordan Woyak <jordan.woyak@gmail.com> | 2026-02-15 20:14:15 -0600 |
| commit | bd3739ce089ffb77261a973f6180fda9aa4a41ef (patch) | |
| tree | 217de52bce686bf0d8325e8b461028161670d6fe | |
| parent | 0d7aef298ebd499f95c4b3ee107ffb99d4dec670 (diff) | |
AMMediaboard: Flatten the NetDIMMConnect function.
| -rw-r--r-- | Source/Core/Core/HW/DVD/AMMediaboard.cpp | 112 |
1 files changed, 61 insertions, 51 deletions
diff --git a/Source/Core/Core/HW/DVD/AMMediaboard.cpp b/Source/Core/Core/HW/DVD/AMMediaboard.cpp index 748089b796..7ff732e2fa 100644 --- a/Source/Core/Core/HW/DVD/AMMediaboard.cpp +++ b/Source/Core/Core/HW/DVD/AMMediaboard.cpp @@ -17,6 +17,7 @@ #include "Common/IOFile.h" #include "Common/Logging/Log.h" #include "Common/Network.h" +#include "Common/ScopeGuard.h" #include "Core/Boot/Boot.h" #include "Core/BootManager.h" @@ -675,72 +676,79 @@ static s32 NetDIMMConnect(GuestSocket guest_socket, const GuestSocketAddress& gu const auto host_socket = GetHostSocket(guest_socket); - u_long val = 1; // Set socket to non-blocking - ioctlsocket(host_socket, FIONBIO, &val); + { + u_long val = 1; + ioctlsocket(host_socket, FIONBIO, &val); + } + // Restore blocking mode + Common::ScopeGuard guard{[&] { + u_long val = 0; + ioctlsocket(host_socket, FIONBIO, &val); + }}; - int ret = connect(host_socket, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr)); + const int connect_result = + connect(host_socket, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr)); const int err = WSAGetLastError(); - if (ret == SOCKET_ERROR && err == WSAEWOULDBLOCK) + if (connect_result == 0) [[unlikely]] { - WSAPOLLFD pfds[1]{{.fd = host_socket, .events = POLLOUT}}; + // Immediate success. + s_last_error = SSC_SUCCESS; + return 0; + } - const auto timeout = - duration_cast<std::chrono::milliseconds>(std::chrono::microseconds{s_timeouts[0]}); + if (err != WSAEWOULDBLOCK) + { + // Immediate failure (e.g. WSAECONNREFUSED) + WARN_LOG_FMT(AMMEDIABOARD, "NetDIMMConnect: connect: {} ({})", err, + Common::DecodeNetworkError(err)); - ret = PlatformPoll(pfds, timeout); + s_last_error = SOCKET_ERROR; + return SOCKET_ERROR; + } - if (ret > 0 && (pfds[0].revents & POLLOUT) != 0) - { - int so_error = 0; - socklen_t optlen = sizeof(so_error); - if (getsockopt(host_socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&so_error), - &optlen) == 0 && - so_error == 0) - { - s_last_error = SSC_SUCCESS; - ret = 0; - } - else - { - ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: getsockopt() failed in NetDIMMConnect ({})", - Common::StrNetworkError()); - s_last_error = SOCKET_ERROR; - ret = SOCKET_ERROR; - } - } - else if (ret == 0) - { - // Timeout - s_last_error = SSC_EWOULDBLOCK; - ret = SOCKET_ERROR; - } - else - { - ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: poll() failed in NetDIMMConnect ({})", - Common::StrNetworkError()); - s_last_error = SOCKET_ERROR; - ret = SOCKET_ERROR; - } + WSAPOLLFD pfds[1]{{.fd = host_socket, .events = POLLOUT}}; + + const auto timeout = + duration_cast<std::chrono::milliseconds>(std::chrono::microseconds{s_timeouts[0]}); + + const int poll_result = PlatformPoll(pfds, timeout); + + if (poll_result < 0) [[unlikely]] + { + // Poll failure. + ERROR_LOG_FMT(AMMEDIABOARD, "NetDIMMConnect: PlatformPoll: {}", Common::StrNetworkError()); + + s_last_error = SOCKET_ERROR; + return SOCKET_ERROR; } - else if (ret == SOCKET_ERROR) + + if ((pfds[0].revents & POLLOUT) == 0) { - // Immediate failure (e.g. WSAECONNREFUSED) - ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: NetDIMMConnect failed, connect() = {} ({})", err, - Common::DecodeNetworkError(err)); - s_last_error = ret; + // Timeout. + s_last_error = SSC_EWOULDBLOCK; + return SOCKET_ERROR; } - else + + int so_error = 0; + socklen_t optlen = sizeof(so_error); + const int getsockopt_result = + getsockopt(host_socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&so_error), &optlen); + + if (getsockopt_result != 0) [[unlikely]] + { + // getsockopt failure. + ERROR_LOG_FMT(AMMEDIABOARD, "NetDIMMConnect: getsockopt: {}", Common::StrNetworkError()); + } + else if (so_error == 0) { s_last_error = SSC_SUCCESS; + return 0; } - // Restore blocking mode - val = 0; - ioctlsocket(host_socket, FIONBIO, &val); - - return ret; + s_last_error = SOCKET_ERROR; + return SOCKET_ERROR; } static void AMMBCommandRecv(u32 parameter_offset, u32 network_buffer_base) @@ -1498,6 +1506,8 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: GetLastError( {}({}) ):{}", fd, s_media_buffer_32[2], s_last_error); + // Good enough, assuming it's called for the same socket right after an error. + // TODO: Implement something similar per socket. s_media_buffer[1] = s_media_buffer[8]; s_media_buffer_32[1] = s_last_error; } |
