mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-01 20:18:15 +01:00
errno: - A thread that hasn't made a call yet reads 0x80410001 from GetErrno, as the PSP has no errno record for it until then. errno is saved in savestates now, in a new sceNet section version. - socket(), close() and setsockopt() clear it when they succeed. - Running out of descriptors is EMFILE, at 255 like the PSP, and an unconnected UDP socket sending without an address EDESTADDRREQ, which Winsock calls ENOTCONN. - On Windows, ENOBUFS, EPROTOTYPE, ENOPROTOOPT, EMSGSIZE, ENETRESET and EDESTADDRREQ now map to the PSP's errnos. They only did elsewhere. All from pspautotests net/inet/errors, options and errnothread. The socket table: - Descriptor numbers are handed out round-robin up to 255, as on the PSP (net/inet/states), rather than the lowest free one. - Closing frees the slot even if the host's close fails, and Close and CloseAll take the lock the rest of SocketManager does. - accept no longer leaks the host socket when it runs out of numbers. - bind no longer asks UPnP to forward port 0, and closing the socket removes its forward, unless another socket still uses the port. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
67 lines
1.8 KiB
C++
67 lines
1.8 KiB
C++
#pragma once
|
|
|
|
#include "Common/CommonTypes.h"
|
|
#include "Common/Net/SocketCompat.h"
|
|
|
|
// Keep track of who's using a socket.
|
|
enum class SocketState {
|
|
Unused = 0,
|
|
UsedNetInet,
|
|
UsedProAdhoc,
|
|
};
|
|
|
|
const char *SocketStateToString(SocketState state);
|
|
|
|
// Internal socket state tracking
|
|
struct InetSocket {
|
|
SOCKET sock; // native socket
|
|
SocketState state;
|
|
// NOTE: These are the PSP types. Can be converted to the host types if needed.
|
|
int domain;
|
|
int type;
|
|
int protocol;
|
|
bool nonblocking;
|
|
// SO_RCVTIMEO and SO_SNDTIMEO, for the blocking calls we wait for in emulated time. 0 is forever.
|
|
u32 recvTimeoutUs;
|
|
u32 sendTimeoutUs;
|
|
// The port bind() asked UPnP to forward, removed on close. 0 if none.
|
|
u16 upnpPort;
|
|
// Metadata for debug use only.
|
|
std::string addr;
|
|
int port;
|
|
};
|
|
|
|
// Only use this for sockets whose ID are exposed to the game.
|
|
// Don't really need to bother with the others, as the game doesn't know about them.
|
|
class SocketManager {
|
|
public:
|
|
enum {
|
|
VALID_INET_SOCKET_COUNT = 256,
|
|
MIN_VALID_INET_SOCKET = 1,
|
|
};
|
|
|
|
InetSocket *CreateSocket(int *index, int *returned_errno, SocketState state, int domain, int type, int protocol);
|
|
// for accept()
|
|
InetSocket *AdoptSocket(int *index, SOCKET hostSocket, const InetSocket *derive);
|
|
|
|
bool GetInetSocket(int sock, InetSocket **inetSocket);
|
|
SOCKET GetHostSocketFromInetSocket(int sock);
|
|
bool Close(InetSocket *inetSocket);
|
|
void CloseAll();
|
|
|
|
// For debugger
|
|
const InetSocket *Sockets() {
|
|
return inetSockets_;
|
|
}
|
|
|
|
private:
|
|
int FindFreeSlot();
|
|
|
|
// The last number handed out. Numbers go round-robin from there.
|
|
int lastSlot_ = 0;
|
|
// 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;
|