nsysnet: Various improvements (#1188)

- Do not raise an assert for unimplemented optnames
- recvfrom: src_addr and addrlen can be NULL
- getsockopt: Implement SO_TYPE
This commit is contained in:
GaryOderNichts 2024-04-29 00:24:43 +02:00 committed by GitHub
parent 5be98da0ac
commit fdf239929f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -36,15 +36,46 @@
#define WU_SO_REUSEADDR 0x0004
#define WU_SO_KEEPALIVE 0x0008
#define WU_SO_DONTROUTE 0x0010
#define WU_SO_BROADCAST 0x0020
#define WU_SO_LINGER 0x0080
#define WU_SO_OOBINLINE 0x0100
#define WU_SO_TCPSACK 0x0200
#define WU_SO_WINSCALE 0x0400
#define WU_SO_SNDBUF 0x1001
#define WU_SO_RCVBUF 0x1002
#define WU_SO_SNDLOWAT 0x1003
#define WU_SO_RCVLOWAT 0x1004
#define WU_SO_LASTERROR 0x1007
#define WU_SO_TYPE 0x1008
#define WU_SO_HOPCNT 0x1009
#define WU_SO_MAXMSG 0x1010
#define WU_SO_RXDATA 0x1011
#define WU_SO_TXDATA 0x1012
#define WU_SO_MYADDR 0x1013
#define WU_SO_NBIO 0x1014
#define WU_SO_BIO 0x1015
#define WU_SO_NONBLOCK 0x1016
#define WU_SO_UNKNOWN1019 0x1019 // tcp related
#define WU_SO_UNKNOWN101A 0x101A // tcp related
#define WU_SO_UNKNOWN101B 0x101B // tcp related
#define WU_SO_NOSLOWSTART 0x4000
#define WU_SO_RUSRBUF 0x10000
#define WU_TCP_NODELAY 0x2004
#define WU_TCP_ACKDELAYTIME 0x2001
#define WU_TCP_NOACKDELAY 0x2002
#define WU_TCP_MAXSEG 0x2003
#define WU_TCP_NODELAY 0x2004
#define WU_TCP_UNKNOWN 0x2005 // amount of mss received before sending an ack
#define WU_IP_TOS 3
#define WU_IP_TTL 4
#define WU_IP_MULTICAST_IF 9
#define WU_IP_MULTICAST_TTL 10
#define WU_IP_MULTICAST_LOOP 11
#define WU_IP_ADD_MEMBERSHIP 12
#define WU_IP_DROP_MEMBERSHIP 13
#define WU_IP_UNKNOWN 14
#define WU_SOL_SOCKET -1 // this constant differs from Win32 socket API
@ -548,7 +579,7 @@ void nsysnetExport_setsockopt(PPCInterpreter_t* hCPU)
}
else
{
cemuLog_logDebug(LogType::Force, "setsockopt(): Unsupported optname 0x{:08x}", optname);
cemuLog_logDebug(LogType::Force, "setsockopt(WU_SOL_SOCKET): Unsupported optname 0x{:08x}", optname);
}
}
else if (level == WU_IPPROTO_TCP)
@ -564,18 +595,22 @@ void nsysnetExport_setsockopt(PPCInterpreter_t* hCPU)
assert_dbg();
}
else
assert_dbg();
{
cemuLog_logDebug(LogType::Force, "setsockopt(WU_IPPROTO_TCP): Unsupported optname 0x{:08x}", optname);
}
}
else if (level == WU_IPPROTO_IP)
{
hostLevel = IPPROTO_IP;
if (optname == 0xC)
if (optname == WU_IP_MULTICAST_IF || optname == WU_IP_MULTICAST_TTL ||
optname == WU_IP_MULTICAST_LOOP || optname == WU_IP_ADD_MEMBERSHIP ||
optname == WU_IP_DROP_MEMBERSHIP)
{
// unknown
cemuLog_logDebug(LogType::Socket, "todo: setsockopt() for multicast");
}
else if( optname == 0x4 )
else if(optname == WU_IP_TTL || optname == WU_IP_TOS)
{
cemuLog_logDebug(LogType::Force, "setsockopt with unsupported opname 4 for IPPROTO_IP");
cemuLog_logDebug(LogType::Force, "setsockopt(WU_IPPROTO_IP): Unsupported optname 0x{:08x}", optname);
}
else
assert_dbg();
@ -649,6 +684,16 @@ void nsysnetExport_getsockopt(PPCInterpreter_t* hCPU)
*(uint32*)optval = _swapEndianU32(optvalLE);
// used by Lost Reavers after some loading screens
}
else if (optname == WU_SO_TYPE)
{
if (memory_readU32(optlenMPTR) != 4)
assert_dbg();
int optvalLE = 0;
socklen_t optlenLE = 4;
memory_writeU32(optlenMPTR, 4);
*(uint32*)optval = _swapEndianU32(vs->type);
r = WU_SO_SUCCESS;
}
else if (optname == WU_SO_NONBLOCK)
{
if (memory_readU32(optlenMPTR) != 4)
@ -661,12 +706,12 @@ void nsysnetExport_getsockopt(PPCInterpreter_t* hCPU)
}
else
{
cemu_assert_debug(false);
cemuLog_logDebug(LogType::Force, "getsockopt(WU_SOL_SOCKET): Unsupported optname 0x{:08x}", optname);
}
}
else
{
cemu_assert_debug(false);
cemuLog_logDebug(LogType::Force, "getsockopt(): Unsupported level 0x{:08x}", level);
}
osLib_returnFromFunction(hCPU, r);
@ -1533,7 +1578,7 @@ void nsysnetExport_getaddrinfo(PPCInterpreter_t* hCPU)
void nsysnetExport_recvfrom(PPCInterpreter_t* hCPU)
{
cemuLog_log(LogType::Socket, "recvfrom({},0x{:08x},{},0x{:x})", hCPU->gpr[3], hCPU->gpr[4], hCPU->gpr[5], hCPU->gpr[6]);
cemuLog_log(LogType::Socket, "recvfrom({},0x{:08x},{},0x{:x},0x{:x},0x{:x})", hCPU->gpr[3], hCPU->gpr[4], hCPU->gpr[5], hCPU->gpr[6], hCPU->gpr[7], hCPU->gpr[8]);
ppcDefineParamS32(s, 0);
ppcDefineParamStr(msg, 1);
ppcDefineParamS32(len, 2);
@ -1562,8 +1607,8 @@ void nsysnetExport_recvfrom(PPCInterpreter_t* hCPU)
if (vs->isNonBlocking)
requestIsNonBlocking = vs->isNonBlocking;
socklen_t fromLenHost = *fromLen;
sockaddr fromAddrHost;
socklen_t fromLenHost = sizeof(fromAddrHost);
sint32 wsaError = 0;
while( true )
@ -1605,9 +1650,13 @@ void nsysnetExport_recvfrom(PPCInterpreter_t* hCPU)
if (r < 0)
cemu_assert_debug(false);
cemuLog_logDebug(LogType::Force, "recvfrom returned {} bytes", r);
*fromLen = fromLenHost;
fromAddr->sa_family = _swapEndianU16(fromAddrHost.sa_family);
memcpy(fromAddr->sa_data, fromAddrHost.sa_data, 14);
// fromAddr and fromLen can be NULL
if (fromAddr && fromLen) {
*fromLen = fromLenHost;
fromAddr->sa_family = _swapEndianU16(fromAddrHost.sa_family);
memcpy(fromAddr->sa_data, fromAddrHost.sa_data, 14);
}
_setSockError(0);
osLib_returnFromFunction(hCPU, r);
@ -1657,9 +1706,12 @@ void nsysnetExport_recvfrom(PPCInterpreter_t* hCPU)
assert_dbg();
}
*fromLen = fromLenHost;
fromAddr->sa_family = _swapEndianU16(fromAddrHost.sa_family);
memcpy(fromAddr->sa_data, fromAddrHost.sa_data, 14);
// fromAddr and fromLen can be NULL
if (fromAddr && fromLen) {
*fromLen = fromLenHost;
fromAddr->sa_family = _swapEndianU16(fromAddrHost.sa_family);
memcpy(fromAddr->sa_data, fromAddrHost.sa_data, 14);
}
_translateError(r <= 0 ? -1 : 0, wsaError);