#include "Common/Net/SocketCompat.h" #include "Core/HLE/NetInetConstants.h" #include "Core/HLE/SocketManager.h" #include "Common/Log.h" #include SocketManager g_socketManager; static std::mutex g_socketMutex; // TODO: Remove once the adhoc thread is gone InetSocket *SocketManager::CreateSocket(int *index, SocketState state, int domain, int type, int protocol) { _dbg_assert_(state != SocketState::Unused); int hostDomain = convertSocketDomainPSP2Host(domain); int hostType = convertSocketTypePSP2Host(type); int hostProtocol = convertSocketProtoPSP2Host(protocol); SOCKET hostSock = ::socket(hostDomain, hostType, hostProtocol); if (hostSock < 0) { return nullptr; } std::lock_guard guard(g_socketMutex); for (int i = MIN_VALID_INET_SOCKET; i < ARRAY_SIZE(inetSockets_); i++) { if (inetSockets_[i].state == SocketState::Unused) { *index = i; InetSocket *inetSock = inetSockets_ + i; inetSock->sock = hostSock; inetSock->state = state; inetSock->domain = domain; inetSock->type = type; inetSock->protocol = protocol; return inetSock; } } _dbg_assert_(false); ERROR_LOG(Log::sceNet, "Ran out of socket handles! This is BAD."); closesocket(hostSock); *index = 0; return nullptr; } bool SocketManager::Close(InetSocket *inetSocket) { _dbg_assert_(inetSocket->state != SocketState::Unused); if (closesocket(inetSocket->sock) != 0) { ERROR_LOG(Log::sceNet, "closesocket(%d) failed", inetSocket->sock); return false; } inetSocket->state = SocketState::Unused; inetSocket->sock = 0; return true; } bool SocketManager::GetInetSocket(int sock, InetSocket **inetSocket) { std::lock_guard guard(g_socketMutex); if (sock < MIN_VALID_INET_SOCKET || sock >= ARRAY_SIZE(inetSockets_) || inetSockets_[sock].state == SocketState::Unused) { *inetSocket = nullptr; return false; } *inetSocket = inetSockets_ + sock; return true; } // Simplified mappers, only really useful in select/poll SOCKET SocketManager::GetHostSocketFromInetSocket(int sock) { std::lock_guard guard(g_socketMutex); if (sock < MIN_VALID_INET_SOCKET || sock >= ARRAY_SIZE(inetSockets_) || inetSockets_[sock].state == SocketState::Unused) { _dbg_assert_(false); return -1; } if (sock == 0) { // Map 0 to 0, special case. return 0; } return inetSockets_[sock].sock; } void SocketManager::CloseAll() { for (auto &sock : inetSockets_) { if (sock.state != SocketState::Unused) { closesocket(sock.sock); } sock.state = SocketState::Unused; sock.sock = 0; } }