diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index 4dac67c609..9e13eecf23 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -1982,6 +1982,19 @@ int setSockReuseAddrPort(int sock) { return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt)); } +int setUDPConnReset(int udpsock, bool enabled) { + // On Windows: Connection Reset error on UDP could cause a strange behavior https://stackoverflow.com/questions/34242622/windows-udp-sockets-recvfrom-fails-with-error-10054 +#if defined(_WIN32) +#if !defined(SIO_UDP_CONNRESET) +#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR, 12) +#endif + BOOL bNewBehavior = enabled; + DWORD dwBytesReturned = 0; + return WSAIoctl(udpsock, SIO_UDP_CONNRESET, &bNewBehavior, sizeof bNewBehavior, NULL, 0, &dwBytesReturned, NULL, NULL); +#endif + return -1; +} + #if !defined(TCP_KEEPIDLE) #define TCP_KEEPIDLE TCP_KEEPALIVE //TCP_KEEPIDLE on Linux is equivalent to TCP_KEEPALIVE on macOS #endif diff --git a/Core/HLE/proAdhoc.h b/Core/HLE/proAdhoc.h index 651c85f958..660c0ff1c6 100644 --- a/Core/HLE/proAdhoc.h +++ b/Core/HLE/proAdhoc.h @@ -1317,6 +1317,11 @@ int setSockNoSIGPIPE(int sock, int flag); */ int setSockReuseAddrPort(int sock); +/* +* Set Socket Connection Reset on UDP (which could cause a strange behavior) +*/ +int setUDPConnReset(int udpsock, bool enabled); + /* * Set Socket KeepAlive (opt = SO_KEEPALIVE) */ diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 291caf3aff..cf20be7067 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -1240,6 +1240,9 @@ static int sceNetAdhocPdpCreate(const char *mac, int port, int bufferSize, u32 f // Enable Port Re-use, this will allow binding to an already used port, but only one of them can read the data (shared receive buffer?) setSockReuseAddrPort(usocket); + // Disable Connection Reset error on UDP to avoid strange behavior https://stackoverflow.com/questions/34242622/windows-udp-sockets-recvfrom-fails-with-error-10054 + setUDPConnReset(usocket, false); + // Binding Information for local Port sockaddr_in addr; addr.sin_family = AF_INET; @@ -2923,7 +2926,7 @@ static int sceNetAdhocGetPdpStat(u32 structSize, u32 structAddr) { // Valid Socket Entry auto sock = adhocSockets[j]; if (sock != NULL && sock->type == SOCK_PDP) { - // Set available bytes to be received. With FIOREAD There might be lingering 1 byte in recv buffer when remote peer's socket got closed (ie. Warriors Orochi 2) + // Set available bytes to be received. With FIOREAD There might be ghosting 1 byte in recv buffer when remote peer's socket got closed (ie. Warriors Orochi 2) Attempting to recv this ghost 1 byte will result to socket error 10054 (may need to disable SIO_UDP_CONNRESET error) sock->data.pdp.rcv_sb_cc = getAvailToRecv(sock->data.pdp.id); // Copy Socket Data from Internal Memory