summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorSepalani <sepalani@hotmail.fr>2022-05-27 14:07:59 +0400
committerSepalani <sepalani@hotmail.fr>2022-06-08 19:06:42 +0400
commitd7135daff5d3c6aab91b4600875d234dff367f82 (patch)
tree60369d294a106bd9ca43385f50617d820e751298 /Source/Core
parentc53a4c8c1a23a8e8bc164030fd6ea705b8ffa3dd (diff)
Socket: Fix some errors related to non-blocking connect
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/IOS/Network/Socket.cpp32
-rw-r--r--Source/Core/Core/IOS/Network/Socket.h1
2 files changed, 33 insertions, 0 deletions
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<char*>(&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;