From d7135daff5d3c6aab91b4600875d234dff367f82 Mon Sep 17 00:00:00 2001 From: Sepalani Date: Fri, 27 May 2022 14:07:59 +0400 Subject: [PATCH] Socket: Fix some errors related to non-blocking connect --- Source/Core/Core/IOS/Network/Socket.cpp | 32 +++++++++++++++++++++++++ Source/Core/Core/IOS/Network/Socket.h | 1 + 2 files changed, 33 insertions(+) diff --git a/Source/Core/Core/IOS/Network/Socket.cpp b/Source/Core/Core/IOS/Network/Socket.cpp index 29af6231d0..dcccf5977f 100644 --- a/Source/Core/Core/IOS/Network/Socket.cpp +++ b/Source/Core/Core/IOS/Network/Socket.cpp @@ -575,6 +575,16 @@ void WiiSocket::Update(bool read, bool write, bool except) { case IOCTLV_SO_SENDTO: { + // The Wii allows a socket with a connection in progress to use + // sendto(). This might not be supported by the operating system. + // We have to enforce it manually. + connecting_state = GetConnectingState(); + if (nonBlock && IsTCP() && connecting_state == ConnectingState::Connecting) + { + ReturnValue = -SO_EAGAIN; + break; + } + u32 flags = Memory::Read_U32(BufferIn2 + 0x04); u32 has_destaddr = Memory::Read_U32(BufferIn2 + 0x08); @@ -612,6 +622,16 @@ void WiiSocket::Update(bool read, bool write, bool except) } case IOCTLV_SO_RECVFROM: { + // The Wii allows a socket with a connection in progress to use + // recvfrom(). This might not be supported by the operating system. + // We have to enforce it manually. + connecting_state = GetConnectingState(); + if (nonBlock && IsTCP() && connecting_state == ConnectingState::Connecting) + { + ReturnValue = -SO_EAGAIN; + break; + } + u32 flags = Memory::Read_U32(BufferIn + 0x04); // Not a string, Windows requires a char* for recvfrom char* data = (char*)Memory::GetPointer(BufferOut); @@ -791,6 +811,18 @@ WiiSocket::ConnectingState WiiSocket::GetConnectingState() const return connecting_state; } +bool WiiSocket::IsTCP() const +{ + const auto state = Common::SaveNetworkErrorState(); + Common::ScopeGuard guard([&state] { Common::RestoreNetworkErrorState(state); }); + + int socket_type; + socklen_t option_length = sizeof(socket_type); + return getsockopt(fd, SOL_SOCKET, SO_TYPE, reinterpret_cast(&socket_type), + &option_length) == 0 && + socket_type == SOCK_STREAM; +} + const WiiSocket::Timeout& WiiSocket::GetTimeout() { if (!timeout.has_value()) diff --git a/Source/Core/Core/IOS/Network/Socket.h b/Source/Core/Core/IOS/Network/Socket.h index 9e2509fcc0..143391cd89 100644 --- a/Source/Core/Core/IOS/Network/Socket.h +++ b/Source/Core/Core/IOS/Network/Socket.h @@ -223,6 +223,7 @@ private: void UpdateConnectingState(s32 connect_rv); ConnectingState GetConnectingState() const; bool IsValid() const { return fd >= 0; } + bool IsTCP() const; s32 fd = -1; s32 wii_fd = -1;