Skip to content

sceNetInet socket remap #19827

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Turn the socket manager into a class
  • Loading branch information
hrydgard committed Jan 8, 2025
commit 155a9f9dbcd35320234acd8f886325be4d6b3f88
30 changes: 16 additions & 14 deletions Core/HLE/SocketManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,50 @@

#include <mutex>

// We use this array from 1 and forward. It's probably not a good idea to return 0 as a socket.
InetSocket g_inetSockets[256];
SocketManager g_socketManager;
static std::mutex g_socketMutex; // TODO: Remove once the adhoc thread is gone

int AllocInetSocket() {
InetSocket *SocketManager::AllocSocket(int *index) {
std::lock_guard<std::mutex> guard(g_socketMutex);
for (int i = MIN_VALID_INET_SOCKET; i < ARRAY_SIZE(g_inetSockets); i++) {
if (g_inetSockets[i].state == SocketState::Unused) {
return i;
for (int i = MIN_VALID_INET_SOCKET; i < ARRAY_SIZE(inetSockets_); i++) {
if (inetSockets_[i].state == SocketState::Unused) {
*index = i;
return inetSockets_ + i;
}
}
_dbg_assert_(false);

ERROR_LOG(Log::sceNet, "Ran out of socket handles! This is BAD.");
*index = 0;
return 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we returned -1 in the case of failure to create a socket? just like a posix socket syscall:

On success, a file descriptor for the new socket is returned. On
error, -1 is returned, and errno is set to indicate the error.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The caller is responsible for the actual syscall return value. But yeah this will be made clearer in an upcoming commit.

(either way, haven't hit this yet)

}

bool GetInetSocket(int sock, InetSocket **inetSocket) {
bool SocketManager::GetInetSocket(int sock, InetSocket **inetSocket) {
std::lock_guard<std::mutex> guard(g_socketMutex);
if (sock < MIN_VALID_INET_SOCKET || sock >= ARRAY_SIZE(g_inetSockets) || g_inetSockets[sock].state == SocketState::Unused) {
if (sock < MIN_VALID_INET_SOCKET || sock >= ARRAY_SIZE(inetSockets_) || inetSockets_[sock].state == SocketState::Unused) {
*inetSocket = nullptr;
return false;
}
*inetSocket = &g_inetSockets[sock];
*inetSocket = inetSockets_ + sock;
return true;
}

// Simplified mappers, only really useful in select/poll
SOCKET GetHostSocketFromInetSocket(int sock) {
SOCKET SocketManager::GetHostSocketFromInetSocket(int sock) {
std::lock_guard<std::mutex> guard(g_socketMutex);
if (sock < MIN_VALID_INET_SOCKET || sock >= ARRAY_SIZE(g_inetSockets) || g_inetSockets[sock].state == SocketState::Unused) {
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 g_inetSockets[sock].sock;
return inetSockets_[sock].sock;
}

void CloseAllSockets() {
for (auto &sock : g_inetSockets) {
void SocketManager::CloseAll() {
for (auto &sock : inetSockets_) {
if (sock.state != SocketState::Unused) {
closesocket(sock.sock);
}
Expand Down
34 changes: 22 additions & 12 deletions Core/HLE/SocketManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,32 @@ enum class SocketState {
struct InetSocket {
Copy link
Collaborator

@anr2me anr2me Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should store non-blocking state here too, and probably some other value that can be set using SetSockOpt too just like non-blocking state, but non-blocking state alone should be sufficient (at least for TCP/UDP socket, while PDP/PTP sockets might need some additional info to be stored, you can checked the AdhocSocket struct for this), since we will need to retrieve the non-blocking state in order to simulate blocking mode later.

PS: Sockets are in blocking mode by default after creation, thus the default value should be nonblocking = false.

Copy link
Collaborator

@anr2me anr2me Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, since we have stored the socket protocol here, we can replace these code at sceNetInet.cpp by forwarding only TCP or UDP instead of forwarding both protocol:

// Enable Port-forwarding
	// TODO: Check the socket type/protocol for SOCK_STREAM/SOCK_DGRAM or IPPROTO_TCP/IPPROTO_UDP instead of forwarding both protocol
	// InetSocket* sock = pspSockets.Get<InetSocket>(socket, error);
	// UPnP_Add((sock->type == SOCK_STREAM)? IP_PROTOCOL_TCP: IP_PROTOCOL_UDP, port, port);	
	unsigned short port = ntohs(saddr.in.sin_port);
	UPnP_Add(IP_PROTOCOL_UDP, port, port);
	UPnP_Add(IP_PROTOCOL_TCP, port, port);

I opened both TCP and UDP because i use the native socket directly and there is noway to retrieve the socket protocol (at least the easy way as i remembered).

Edit: oops, you already did this >.<

SOCKET sock; // native socket
SocketState state;
// NOTE: These are the PSP types for now
// NOTE: These are the PSP types. Can be converted to the host types if needed.
int domain;
int type;
int protocol;
// These are the host types for convenience.
int hostDomain;
int hostType;
int hostProtocol;
};

#define MIN_VALID_INET_SOCKET 61
#define VALID_INET_SOCKET_COUNT 256
class SocketManager {
public:
enum {
VALID_INET_SOCKET_COUNT = 256,
MIN_VALID_INET_SOCKET = 61,
};

extern InetSocket g_inetSockets[VALID_INET_SOCKET_COUNT];
InetSocket *AllocSocket(int *index);
bool GetInetSocket(int sock, InetSocket **inetSocket);
SOCKET GetHostSocketFromInetSocket(int sock);
void CloseAll();

int AllocInetSocket();
bool GetInetSocket(int sock, InetSocket **inetSocket);
SOCKET GetHostSocketFromInetSocket(int sock);
void CloseAllSockets();
// For debugger
const InetSocket *Sockets() {
return inetSockets_;
}

private:
// We use this array from MIN_VALID_INET_SOCKET and forward. It's probably not a good idea to return 0 as a socket.
InetSocket inetSockets_[VALID_INET_SOCKET_COUNT];
};

extern SocketManager g_socketManager;
1 change: 1 addition & 0 deletions Core/HLE/proAdhoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ SceNetAdhocctlPeerInfo* findFriendByIP(uint32_t ip) {
return peer;
}

// fd is a host socket
int IsSocketReady(int fd, bool readfd, bool writefd, int* errorcode, int timeoutUS) {
fd_set readfds, writefds;
timeval tval;
Expand Down
62 changes: 31 additions & 31 deletions Core/HLE/sceNetInet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void __NetInetShutdown() {
}

netInetInited = false;
CloseAllSockets();
g_socketManager.CloseAll();
}

static int sceNetInetInit() {
Expand Down Expand Up @@ -123,7 +123,7 @@ static int sceNetInetGetpeername(int socket, u32 namePtr, u32 namelenPtr) {
}

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand Down Expand Up @@ -157,7 +157,7 @@ static int sceNetInetGetsockname(int socket, u32 namePtr, u32 namelenPtr) {
}

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand Down Expand Up @@ -205,9 +205,9 @@ int sceNetInetSelect(int nfds, u32 readfdsPtr, u32 writefdsPtr, u32 exceptfdsPtr
// Save the mapping during setup.
SOCKET hostSockets[256]{};

for (int i = MIN_VALID_INET_SOCKET; i < nfds; i++) {
for (int i = SocketManager::MIN_VALID_INET_SOCKET; i < nfds; i++) {
if (readfds && (NetInetFD_ISSET(i, readfds))) {
SOCKET sock = GetHostSocketFromInetSocket(i);
SOCKET sock = g_socketManager.GetHostSocketFromInetSocket(i);
hostSockets[i] = sock;
DEBUG_LOG(Log::sceNet, "Input Read FD #%i (host: %d)", i, sock);
if (rdcnt < FD_SETSIZE) {
Expand All @@ -216,7 +216,7 @@ int sceNetInetSelect(int nfds, u32 readfdsPtr, u32 writefdsPtr, u32 exceptfdsPtr
}
}
if (writefds && (NetInetFD_ISSET(i, writefds))) {
SOCKET sock = GetHostSocketFromInetSocket(i);
SOCKET sock = g_socketManager.GetHostSocketFromInetSocket(i);
hostSockets[i] = sock;
DEBUG_LOG(Log::sceNet, "Input Write FD #%i (host: %d)", i, sock);
if (wrcnt < FD_SETSIZE) {
Expand All @@ -225,7 +225,7 @@ int sceNetInetSelect(int nfds, u32 readfdsPtr, u32 writefdsPtr, u32 exceptfdsPtr
}
}
if (exceptfds && (NetInetFD_ISSET(i, exceptfds))) {
SOCKET sock = GetHostSocketFromInetSocket(i);
SOCKET sock = g_socketManager.GetHostSocketFromInetSocket(i);
hostSockets[i] = sock;
DEBUG_LOG(Log::sceNet, "Input Except FD #%i (host: %d)", i, sock);
if (excnt < FD_SETSIZE) {
Expand Down Expand Up @@ -254,7 +254,7 @@ int sceNetInetSelect(int nfds, u32 readfdsPtr, u32 writefdsPtr, u32 exceptfdsPtr
if (readfds != NULL) NetInetFD_ZERO(readfds);
if (writefds != NULL) NetInetFD_ZERO(writefds);
if (exceptfds != NULL) NetInetFD_ZERO(exceptfds);
for (int i = MIN_VALID_INET_SOCKET; i < nfds; i++) {
for (int i = SocketManager::MIN_VALID_INET_SOCKET; i < nfds; i++) {
if (readfds && hostSockets[i] != 0 && FD_ISSET(hostSockets[i], &rdfds)) {
NetInetFD_SET(i, readfds);
}
Expand Down Expand Up @@ -296,7 +296,7 @@ int sceNetInetPoll(u32 fdsPtr, u32 nfds, int timeout) { // timeout in milisecond
if (fdarray[i].fd > maxfd) {
maxfd = fdarray[i].fd;
}
SOCKET hostSocket = GetHostSocketFromInetSocket(fdarray[i].fd);
SOCKET hostSocket = g_socketManager.GetHostSocketFromInetSocket(fdarray[i].fd);
FD_SET(hostSocket, &readfds);
FD_SET(hostSocket, &writefds);
FD_SET(hostSocket, &exceptfds);
Expand All @@ -317,7 +317,7 @@ int sceNetInetPoll(u32 fdsPtr, u32 nfds, int timeout) { // timeout in milisecond

retval = 0;
for (int i = 0; i < (s32)nfds; i++) {
SOCKET hostSocket = GetHostSocketFromInetSocket(fdarray[i].fd);
SOCKET hostSocket = g_socketManager.GetHostSocketFromInetSocket(fdarray[i].fd);
if ((fdarray[i].events & (INET_POLLRDNORM | INET_POLLIN)) && FD_ISSET(hostSocket, &readfds))
fdarray[i].revents |= (INET_POLLRDNORM | INET_POLLIN); //POLLIN_SET
if ((fdarray[i].events & (INET_POLLWRNORM | INET_POLLOUT)) && FD_ISSET(hostSocket, &writefds))
Expand All @@ -337,7 +337,7 @@ static int sceNetInetRecv(int socket, u32 bufPtr, u32 bufLen, u32 flags) {
DEBUG_LOG(Log::sceNet, "UNTESTED sceNetInetRecv(%i, %08x, %i, %08x) at %08x", socket, bufPtr, bufLen, flags, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand All @@ -364,7 +364,7 @@ static int sceNetInetSend(int socket, u32 bufPtr, u32 bufLen, u32 flags) {
DEBUG_LOG(Log::sceNet, "UNTESTED sceNetInetSend(%i, %08x, %i, %08x) at %08x", socket, bufPtr, bufLen, flags, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand Down Expand Up @@ -404,20 +404,19 @@ static int sceNetInetSocket(int domain, int type, int protocol) {

// Register the socket.

int socket = AllocInetSocket();
int socket;

InetSocket *inetSock = g_socketManager.AllocSocket(&socket);
if (socket < 0) {
// Alloc already logged. Let's bail.
return hleLogError(Log::sceNet, ERROR_NET_INTERNAL);
}
InetSocket *inetSock = &g_inetSockets[socket];

inetSock->state = SocketState::UsedNetInet;
inetSock->sock = hostSock;
inetSock->domain = domain;
inetSock->type = type;
inetSock->protocol = protocol;
inetSock->hostDomain = hostDomain;
inetSock->hostType = hostType;
inetSock->hostProtocol = hostProtocol;

// Ignore SIGPIPE when supported (ie. BSD/MacOS)
setSockNoSIGPIPE(hostSock, 1);
Expand All @@ -427,14 +426,15 @@ static int sceNetInetSocket(int domain, int type, int protocol) {
setSockReuseAddrPort(hostSock);
// Disable Connection Reset error on UDP to avoid strange behavior
setUDPConnReset(hostSock, false);

return hleLogSuccessI(Log::sceNet, socket);
}

static int sceNetInetSetsockopt(int socket, int level, int optname, u32 optvalPtr, int optlen) {
WARN_LOG(Log::sceNet, "UNTESTED %s(%i, %i, %i, %08x, %i) at %08x", __FUNCTION__, socket, level, optname, optvalPtr, optlen, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand Down Expand Up @@ -495,7 +495,7 @@ static int sceNetInetGetsockopt(int socket, int level, int optname, u32 optvalPt
WARN_LOG(Log::sceNet, "UNTESTED %s(%i, %i, %i, %08x, %08x) at %08x", __FUNCTION__, socket, level, optname, optvalPtr, optlenPtr, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand Down Expand Up @@ -560,7 +560,7 @@ static int sceNetInetBind(int socket, u32 namePtr, int namelen) {
WARN_LOG(Log::sceNet, "UNTESTED %s(%i, %08x, %i) at %08x", __FUNCTION__, socket, namePtr, namelen, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand Down Expand Up @@ -614,7 +614,7 @@ static int sceNetInetConnect(int socket, u32 sockAddrPtr, int sockAddrLen) {
WARN_LOG(Log::sceNet, "UNTESTED %s(%i, %08x, %i) at %08x", __FUNCTION__, socket, sockAddrPtr, sockAddrLen, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand Down Expand Up @@ -652,7 +652,7 @@ static int sceNetInetListen(int socket, int backlog) {
WARN_LOG(Log::sceNet, "UNTESTED %s(%i, %i) at %08x", __FUNCTION__, socket, backlog, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand All @@ -669,7 +669,7 @@ static int sceNetInetAccept(int socket, u32 addrPtr, u32 addrLenPtr) {
WARN_LOG(Log::sceNet, "UNTESTED %s(%i, %08x, %08x) at %08x", __FUNCTION__, socket, addrPtr, addrLenPtr, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand Down Expand Up @@ -702,7 +702,7 @@ static int sceNetInetShutdown(int socket, int how) {
WARN_LOG(Log::sceNet, "UNTESTED %s(%i, %i) at %08x", __FUNCTION__, socket, how, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand All @@ -722,7 +722,7 @@ static int sceNetInetSocketAbort(int socket) {
WARN_LOG(Log::sceNet, "UNTESTED %s(%i)", __FUNCTION__, socket);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand All @@ -735,7 +735,7 @@ static int sceNetInetClose(int socket) {
WARN_LOG(Log::sceNet, "UNTESTED %s(%i) at %08x", __FUNCTION__, socket, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand All @@ -754,7 +754,7 @@ static int sceNetInetCloseWithRST(int socket) {
WARN_LOG(Log::sceNet, "UNTESTED %s(%i) at %08x", __FUNCTION__, socket, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand All @@ -777,7 +777,7 @@ static int sceNetInetRecvfrom(int socket, u32 bufferPtr, int len, int flags, u32
DEBUG_LOG(Log::sceNet, "UNTESTED %s(%i, %08x, %i, %08x, %08x, %08x) at %08x", __FUNCTION__, socket, bufferPtr, len, flags, fromPtr, fromlenPtr, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand Down Expand Up @@ -825,7 +825,7 @@ static int sceNetInetSendto(int socket, u32 bufferPtr, int len, int flags, u32 t
DEBUG_LOG(Log::sceNet, "UNTESTED %s(%i, %08x, %i, %08x, %08x, %d) at %08x", __FUNCTION__, socket, bufferPtr, len, flags, toPtr, tolen, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand Down Expand Up @@ -909,7 +909,7 @@ static int sceNetInetSendmsg(int socket, u32 msghdrPtr, int flags) {
}

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand Down Expand Up @@ -1103,7 +1103,7 @@ static int sceNetInetRecvmsg(int socket, u32 msghdrPtr, int flags) {
ERROR_LOG(Log::sceNet, "UNIMPL %s(%i, %08x, %08x) at %08x", __FUNCTION__, socket, msghdrPtr, flags, currentMIPS->pc);

InetSocket *inetSock;
if (!GetInetSocket(socket, &inetSock)) {
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
}

Expand Down