summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2026-10-17 19:12:45 +0200
committerGitHub <noreply@github.com>2026-10-17 19:12:45 +0200
commit1cf8f6d92c95504b3fa41cdf92e1706cfb0d9928 (patch)
tree52c2ed85a220a794df847ad846d2afe2994bd937 /Source
parent2282f5f94f011d33b3b431e252d9613d92f6c87c (diff)
parent44ceefe2ec34203c92b5dddf2d71056359b6fb1a (diff)
Merge pull request #14397 from sepalani/tri-accept
AMMediaboard: Change accept non-blocking logic
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/HW/DVD/AMMediaboard.cpp86
1 files changed, 48 insertions, 38 deletions
diff --git a/Source/Core/Core/HW/DVD/AMMediaboard.cpp b/Source/Core/Core/HW/DVD/AMMediaboard.cpp
index 0fb7126b57..272e5a12ff 100644
--- a/Source/Core/Core/HW/DVD/AMMediaboard.cpp
+++ b/Source/Core/Core/HW/DVD/AMMediaboard.cpp
@@ -376,22 +376,6 @@ static GuestSocket socket_(int af, int type, int protocol)
return guest_socket;
}
-static GuestSocket accept_(int fd, sockaddr* addr, socklen_t* len)
-{
- const auto guest_socket = GetAvailableGuestSocket();
- if (guest_socket == INVALID_GUEST_SOCKET)
- return INVALID_GUEST_SOCKET;
-
- const s32 host_fd = accept(fd, addr, len);
- if (host_fd < 0)
- return INVALID_GUEST_SOCKET;
-
- Common::SetPlatformSocketOptions(host_fd);
-
- s_sockets[u32(guest_socket)] = host_fd;
- return guest_socket;
-}
-
static inline void PrintMBBuffer(u32 address, u32 length)
{
const auto& system = Core::System::GetInstance();
@@ -829,25 +813,52 @@ static GuestSocket NetDIMMAccept(GuestSocket guest_socket, u8* guest_addr_ptr,
}
const auto host_socket = GetHostSocket(guest_socket);
- WSAPOLLFD pfds[1]{{.fd = host_socket, .events = POLLIN}};
-
- // FYI: Currently using a 0ms timeout to make accept calls always non-blocking.
- constexpr auto timeout = std::chrono::milliseconds{0};
-
- DEBUG_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: {}({})", host_socket, int(guest_socket));
+ if (host_socket == SOCKET_ERROR)
+ {
+ ERROR_LOG_FMT(AMMEDIABOARD_NET, "NetDIMMAccept: fd is not open: {}({})", host_socket,
+ int(guest_socket));
- const int poll_result = PlatformPoll(pfds, timeout);
+ // TODO: Not hardware tested.
+ s_last_error = SSC_EBADF;
+ return INVALID_GUEST_SOCKET;
+ }
- if (poll_result < 0) [[unlikely]]
+ const auto client_sock = GetAvailableGuestSocket();
+ if (client_sock == INVALID_GUEST_SOCKET)
{
- // Poll failure.
- ERROR_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: PlatformPoll: {}", Common::StrNetworkError());
-
- s_last_error = SOCKET_ERROR;
+ ERROR_LOG_FMT(AMMEDIABOARD_NET,
+ "NetDIMMAccept: accept( {}({}) ) failed, descriptor table is full", host_socket,
+ int(guest_socket));
+ // TODO: Not hardware tested.
+ s_last_error = SSC_AEMFILE;
return INVALID_GUEST_SOCKET;
}
- if ((pfds[0].revents & POLLIN) == 0)
+ // There is no easy way to check if the accept's socket is valid:
+ // - getsockopt's SO_ACCEPTCONN isn't available on all systems
+ // - poll/select result might be empty even if accept is called beforehand
+ //
+ // Might impact performance when accept is called too often.
+ // TODO: Find a better way.
+ {
+ // Set socket to non-blocking
+ u_long val = 1;
+ ioctlsocket(host_socket, FIONBIO, &val);
+ }
+ Common::ScopeGuard guard{[&] {
+ // Restore blocking mode
+ u_long val = 0;
+ ioctlsocket(host_socket, FIONBIO, &val);
+ }};
+
+ sockaddr_in addr{};
+ socklen_t addrlen = sizeof(addr);
+ const s32 res = accept(host_socket, reinterpret_cast<sockaddr*>(&addr), &addrlen);
+ const int err = WSAGetLastError();
+
+ DEBUG_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: {}({})", host_socket, int(guest_socket));
+
+ if (res < 0 && err == WSAEWOULDBLOCK)
{
// Timeout.
DEBUG_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: Timeout.");
@@ -856,21 +867,20 @@ static GuestSocket NetDIMMAccept(GuestSocket guest_socket, u8* guest_addr_ptr,
return INVALID_GUEST_SOCKET;
}
- sockaddr_in addr;
- socklen_t addrlen = sizeof(addr);
- const auto client_sock = accept_(host_socket, reinterpret_cast<sockaddr*>(&addr), &addrlen);
-
- if (client_sock == INVALID_GUEST_SOCKET)
+ if (res < 0)
{
- ERROR_LOG_FMT(AMMEDIABOARD, "AMMBCommandAccept: accept( {}({}) ) failed: {}", host_socket,
- int(guest_socket), Common::StrNetworkError());
+ ERROR_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: accept( {}({}) ) failed with error {}: {}",
+ host_socket, int(guest_socket), err, Common::DecodeNetworkError(err));
+
s_last_error = SOCKET_ERROR;
return INVALID_GUEST_SOCKET;
}
+ Common::SetPlatformSocketOptions(res);
+ s_sockets[u32(client_sock)] = res;
s_last_error = SSC_SUCCESS;
- NOTICE_LOG_FMT(AMMEDIABOARD, "AMMBCommandAccept: {}:{}",
+ NOTICE_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: {}:{}",
Common::IPAddressToString(std::bit_cast<Common::IPAddress>(addr.sin_addr)),
ntohs(addr.sin_port));
@@ -889,7 +899,7 @@ static GuestSocket NetDIMMAccept(GuestSocket guest_socket, u8* guest_addr_ptr,
guest_addr.ip_address = adjusted_ipv4port->ip_address;
guest_addr.port = adjusted_ipv4port->port;
- NOTICE_LOG_FMT(AMMEDIABOARD, "AMMBCommandAccept: Translating result to: {}:{}",
+ NOTICE_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: Translating result to: {}:{}",
Common::IPAddressToString(guest_addr.ip_address), ntohs(guest_addr.port));
}