mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 19:36:55 +02:00
network: handle SO_NBIO on non-Windows hosts (#954)
* network: handle SO_NBIO on non-Windows hosts Setsockopt only translated the guest SOL_SOCKET/SO_NBIO (0x1200) option under _WIN32; other hosts rejected it with ENOPROTOOPT. FMOD Studio's Live Update listener sets SO_NBIO, so on Linux its socket setup failed and the Studio async manager latched FMOD_ERR_NET_CONNECT. Every blocking Studio call then failed: loadBankFile returned FMOD_ERR_NOTREADY for all banks, leaving the game silent and stuck on the splash screen waiting for RuntimeManager.HaveAllBanksLoaded (PPSA28997). Toggle O_NONBLOCK with fcntl on non-Windows hosts. * network: map connection errors from POSIX socket calls ConvertHostSocketError only covered a handful of errno values on non-Windows hosts, so anything else reached the guest as EIO. With SO_NBIO now honoured there, a nonblocking connect() that is still in progress returned EIO instead of EINPROGRESS (and EALREADY on retry). Map the same connection and network errors the Windows branch already translates. * network: share nonblocking socket error handling --------- Co-authored-by: nmzik <Nmzik@mail.ru>
This commit is contained in:
+29
-7
@@ -997,14 +997,31 @@ static int ConvertHostSocketError(int error) {
|
||||
case EAGAIN: posix_error = Posix::POSIX_EWOULDBLOCK; break;
|
||||
case EBADF: posix_error = Posix::POSIX_EBADF; break;
|
||||
case EFAULT: posix_error = Posix::POSIX_EFAULT; break;
|
||||
case EINTR: posix_error = Posix::POSIX_EINTR; break;
|
||||
case EINVAL: posix_error = Posix::POSIX_EINVAL; break;
|
||||
case EISCONN: posix_error = Posix::POSIX_EISCONN; break;
|
||||
case EMFILE: posix_error = Posix::POSIX_EMFILE; break;
|
||||
case EMSGSIZE: posix_error = Posix::POSIX_EMSGSIZE; break;
|
||||
case ENFILE: posix_error = Posix::POSIX_ENFILE; break;
|
||||
case ENOBUFS: posix_error = Posix::POSIX_ENOBUFS; break;
|
||||
case ENOMEM: posix_error = Posix::POSIX_ENOMEM; break;
|
||||
case ENETDOWN: posix_error = Posix::POSIX_ENETDOWN; break;
|
||||
case ENETRESET: posix_error = Posix::POSIX_ENETRESET; break;
|
||||
case ENETUNREACH: posix_error = Posix::POSIX_ENETUNREACH; break;
|
||||
case ENOTCONN: posix_error = Posix::POSIX_ENOTCONN; break;
|
||||
case ENOTSOCK: posix_error = Posix::POSIX_ENOTSOCK; break;
|
||||
case EOPNOTSUPP: posix_error = Posix::POSIX_EOPNOTSUPP; break;
|
||||
case EPIPE: posix_error = Posix::POSIX_EPIPE; break;
|
||||
case EPROTONOSUPPORT: posix_error = Posix::POSIX_EPROTONOSUPPORT; break;
|
||||
case ESHUTDOWN: posix_error = Posix::POSIX_ESHUTDOWN; break;
|
||||
case ETIMEDOUT: posix_error = Posix::POSIX_ETIMEDOUT; break;
|
||||
case ECONNABORTED: posix_error = Posix::POSIX_ECONNABORTED; break;
|
||||
case ECONNREFUSED: posix_error = Posix::POSIX_ECONNREFUSED; break;
|
||||
case ECONNRESET: posix_error = Posix::POSIX_ECONNRESET; break;
|
||||
case EDESTADDRREQ: posix_error = Posix::POSIX_EDESTADDRREQ; break;
|
||||
case EHOSTUNREACH: posix_error = Posix::POSIX_EHOSTUNREACH; break;
|
||||
case EINPROGRESS: posix_error = Posix::POSIX_EINPROGRESS; break;
|
||||
case EALREADY: posix_error = Posix::POSIX_EALREADY; break;
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
@@ -2098,17 +2115,22 @@ int KYTY_SYSV_ABI Setsockopt(int s, int level, int optname, const void* optval,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
constexpr int ORBIS_SO_NBIO = 0x1200;
|
||||
if (ConvertSocketOptionLevel(level) == SOL_SOCKET && optname == ORBIS_SO_NBIO &&
|
||||
optlen >= sizeof(int)) {
|
||||
u_long enabled = (*static_cast<const int*>(optval) != 0 ? 1 : 0);
|
||||
if (ioctlsocket(socket, FIONBIO, &enabled) == SOCKET_ERROR) {
|
||||
return SetHostSocketError();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
const bool enabled = *static_cast<const int*>(optval) != 0;
|
||||
#if defined(_WIN32)
|
||||
u_long mode = enabled ? 1 : 0;
|
||||
const bool failed = ioctlsocket(socket, FIONBIO, &mode) == SOCKET_ERROR;
|
||||
#else
|
||||
const int flags = ::fcntl(socket, F_GETFL, 0);
|
||||
const bool failed =
|
||||
flags < 0 ||
|
||||
::fcntl(socket, F_SETFL, enabled ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK)) != 0;
|
||||
#endif
|
||||
return failed ? SetHostSocketError() : 0;
|
||||
}
|
||||
#if !defined(_WIN32)
|
||||
// Guest TCP options: IPPROTO_TCP=6, TCP_NODELAY=1.
|
||||
if (level != 6 || optname != 1) {
|
||||
return SetGuestSocketError(Posix::POSIX_ENOPROTOOPT);
|
||||
|
||||
Reference in New Issue
Block a user