From b327fd8b2c954bebc1cef234843b5b6fa0bfbf71 Mon Sep 17 00:00:00 2001 From: Sepalani Date: Sun, 4 Jun 2017 02:51:26 +0100 Subject: [PATCH] IOS/Network: Handle SO_EMFILE --- Source/Core/Core/IOS/Network/Socket.cpp | 46 ++++++++++++++++--------- Source/Core/Core/IOS/Network/Socket.h | 2 +- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/Source/Core/Core/IOS/Network/Socket.cpp b/Source/Core/Core/IOS/Network/Socket.cpp index 772c86dce0..1b3ffbdf26 100644 --- a/Source/Core/Core/IOS/Network/Socket.cpp +++ b/Source/Core/Core/IOS/Network/Socket.cpp @@ -25,12 +25,15 @@ #else #define ERRORCODE(name) name #define EITHER(win32, posix) posix +#define closesocket close #endif namespace IOS { namespace HLE { +constexpr int WII_SOCKET_FD_MAX = 24; + char* WiiSockMan::DecodeError(s32 ErrorCode) { #ifdef _WIN32 @@ -148,11 +151,7 @@ s32 WiiSocket::CloseFd() s32 ReturnValue = 0; if (fd >= 0) { -#ifdef _WIN32 s32 ret = closesocket(fd); -#else - s32 ret = close(fd); -#endif ReturnValue = WiiSockMan::GetNetErrorCode(ret, "CloseFd", false); } else @@ -256,8 +255,7 @@ void WiiSocket::Update(bool read, bool write, bool except) ret = static_cast(accept(fd, nullptr, nullptr)); } - ret = WiiSockMan::GetInstance().AddSocket(ret); - ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_ACCEPT", true); + ReturnValue = WiiSockMan::GetInstance().AddSocket(ret, true); ioctl.Log("IOCTL_SO_ACCEPT", LogTypes::IOS_NET); break; @@ -604,18 +602,36 @@ void WiiSocket::DoSock(Request request, SSL_IOCTL type) pending_sockops.push_back(so); } -s32 WiiSockMan::AddSocket(s32 fd) +s32 WiiSockMan::AddSocket(s32 fd, bool is_rw) { - if (fd >= 0) + const char* caller = is_rw ? "SO_ACCEPT" : "NewSocket"; + + if (fd < 0) + return GetNetErrorCode(fd, caller, is_rw); + + s32 wii_fd; + for (wii_fd = 0; wii_fd < WII_SOCKET_FD_MAX; ++wii_fd) + { + // Find an available socket fd + if (WiiSockets.count(wii_fd) == 0) + break; + } + + if (wii_fd == WII_SOCKET_FD_MAX) + { + // Close host socket + closesocket(fd); + wii_fd = -SO_EMFILE; + ERROR_LOG(IOS_NET, "%s failed: Too many open sockets, ret=%d", caller, wii_fd); + } + else { - s32 wii_fd = 0; - while (WiiSockets.count(wii_fd) > 0) - wii_fd += 1; WiiSocket& sock = WiiSockets[wii_fd]; sock.SetFd(fd); - return wii_fd; } - return fd; + + SetLastNetError(wii_fd); + return wii_fd; } s32 WiiSockMan::NewSocket(s32 af, s32 type, s32 protocol) @@ -625,9 +641,7 @@ s32 WiiSockMan::NewSocket(s32 af, s32 type, s32 protocol) if (protocol != 0) // IPPROTO_IP return -SO_EPROTONOSUPPORT; s32 fd = static_cast(socket(af, type, protocol)); - s32 wii_fd = AddSocket(fd); - s32 ret = GetNetErrorCode(wii_fd, "NewSocket", false); - return ret; + return AddSocket(fd, false); } s32 WiiSockMan::GetHostSocket(s32 wii_fd) const diff --git a/Source/Core/Core/IOS/Network/Socket.h b/Source/Core/Core/IOS/Network/Socket.h index a1fbe61332..bbe2da76f2 100644 --- a/Source/Core/Core/IOS/Network/Socket.h +++ b/Source/Core/Core/IOS/Network/Socket.h @@ -221,7 +221,7 @@ public: static void Convert(sockaddr_in const& from, WiiSockAddrIn& to, s32 addrlen = -1); // NON-BLOCKING FUNCTIONS s32 NewSocket(s32 af, s32 type, s32 protocol); - s32 AddSocket(s32 fd); + s32 AddSocket(s32 fd, bool is_rw); s32 GetHostSocket(s32 wii_fd) const; s32 DeleteSocket(s32 s); s32 GetLastNetError() const { return errno_last; }