From febc36223bfa19b5aa42da07601a69b8088e4012 Mon Sep 17 00:00:00 2001 From: Yunus Shaikh <75296019+yunusshaikh7@users.noreply.github.com> Date: Mon, 12 Oct 2026 15:05:30 +0000 Subject: [PATCH 1/3] fix(libSceNet): take 0x1105 and 0x1106 as the send and receive timeouts sceNetSetsockopt and sceNetGetsockopt answered EOPNOTSUPP for 0x1105 and 0x1106, the SCE send and receive timeouts in microseconds (shadPS4 net_types.h ORBIS_NET_SO_SNDTIMEO/RCVTIMEO, SharpProspero Socket.cs SoSndTimeo/SoRcvTimeo, KytyPS5 network.cpp). A title that set a receive timeout this way then blocked in sceNetRecv for good. Both options now set and read the timeouts that 0x1005 and 0x1006 already do. --- core/libs/prx/libSceNet/Export.cpp | 11 ++++++++++- core/libs/tests/GuestSceNet.cpp | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/core/libs/prx/libSceNet/Export.cpp b/core/libs/prx/libSceNet/Export.cpp index 79214e8e4..39ed00f0f 100644 --- a/core/libs/prx/libSceNet/Export.cpp +++ b/core/libs/prx/libSceNet/Export.cpp @@ -77,6 +77,8 @@ constexpr int NET_EPOLL_CTL_DEL = 3; constexpr int NET_SOL_SOCKET = 0xFFFF; constexpr int NET_SO_SNDTIMEO = 0x1005; constexpr int NET_SO_RCVTIMEO = 0x1006; +constexpr int NET_SO_SCE_SNDTIMEO = 0x1105; +constexpr int NET_SO_SCE_RCVTIMEO = 0x1106; constexpr int NET_SO_NBIO = 0x1200; constexpr int NET_SO_REUSEADDR = 0x4; constexpr int NET_SO_BROADCAST = 0x20; @@ -388,6 +390,12 @@ int receive_error(const Sock& socket) { return native_error(); } +int timeout_option(int optname) { + if (optname == NET_SO_SCE_SNDTIMEO) return NET_SO_SNDTIMEO; + if (optname == NET_SO_SCE_RCVTIMEO) return NET_SO_RCVTIMEO; + return optname; +} + } // namespace extern "C" { @@ -857,6 +865,7 @@ int APS5_VABI sceNetSetsockopt(int s, int level, int optname, const void* optval socket = it->second; } if (level != NET_SOL_SOCKET) return fail(NET_EOPNOTSUPP); + optname = timeout_option(optname); if (!optval || optlen < sizeof(int)) return fail(NET_EINVAL); int value = 0; std::memcpy(&value, optval, sizeof(value)); @@ -915,7 +924,7 @@ int APS5_VABI sceNetGetsockopt(int s, int level, int optname, void* optval, uint } if (level != NET_SOL_SOCKET) return fail(NET_EOPNOTSUPP); int value = 0; - switch (optname) { + switch (timeout_option(optname)) { case NET_SO_NBIO: value = socket.nonblock ? 1 : 0; break; case NET_SO_RCVTIMEO: value = socket.rcv_timeout_us; break; case NET_SO_SNDTIMEO: value = socket.snd_timeout_us; break; diff --git a/core/libs/tests/GuestSceNet.cpp b/core/libs/tests/GuestSceNet.cpp index 993e40205..ed04683ff 100644 --- a/core/libs/tests/GuestSceNet.cpp +++ b/core/libs/tests/GuestSceNet.cpp @@ -45,6 +45,7 @@ int APS5_VABI sceNetEpollControl(int, int, int, const NetEpollEvent*); int APS5_VABI sceNetEpollWait(int, NetEpollEvent*, int, int); int APS5_VABI sceNetEpollDestroy(int); int APS5_VABI sceNetEpollAbort(int, int); +int APS5_VABI sceNetGetsockopt(int, int, int, void*, std::uint32_t*); extern const std::uint32_t sce_net_in6addr_any[4]; extern const std::uint8_t sce_net_in6addr_linklocal_allnodes[16]; int APS5_VABI sceNetResolverCreate(const char*, int, int); @@ -167,6 +168,23 @@ static void CheckReceiveTimeout(int receiver, int sender, const std::array& address) { char head[] = "scatter "; char tail[] = "gather"; @@ -503,6 +521,7 @@ int main() { stdio_readable[0] = 1; Require(select_nid_postfix(1, stdio_readable, nullptr, nullptr, poll_now) == 0 && stdio_readable[0] == 0); CheckReceiveTimeout(udp_receiver, udp_sender, address); + CheckMicrosecondTimeouts(udp_receiver); CheckMessages(udp_receiver, udp_sender, address); Require(sceNetSocketClose(udp_sender) == 0); Require(sceNetSocketClose(udp_receiver) == 0); From ac8106bda24227a563f76e199d1628c63054db37 Mon Sep 17 00:00:00 2001 From: Yunus Shaikh <75296019+yunusshaikh7@users.noreply.github.com> Date: Mon, 12 Oct 2026 11:52:49 -0700 Subject: [PATCH 2/3] refactor(libSceNet): define timeout_option before receive_error #4673 adds a function after receive_error, so defining timeout_option there made the two pull requests conflict. --- core/libs/prx/libSceNet/Export.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/libs/prx/libSceNet/Export.cpp b/core/libs/prx/libSceNet/Export.cpp index 39ed00f0f..75b457392 100644 --- a/core/libs/prx/libSceNet/Export.cpp +++ b/core/libs/prx/libSceNet/Export.cpp @@ -381,6 +381,12 @@ std::int64_t message_length(const NetMsghdr* message) { return static_cast(total); } +int timeout_option(int optname) { + if (optname == NET_SO_SCE_SNDTIMEO) return NET_SO_SNDTIMEO; + if (optname == NET_SO_SCE_RCVTIMEO) return NET_SO_RCVTIMEO; + return optname; +} + int receive_error(const Sock& socket) { #ifdef _WIN32 if (WSAGetLastError() == WSAETIMEDOUT && socket.type != NET_SOCK_STREAM && socket.rcv_timeout_us > 0) return NET_EAGAIN; @@ -390,12 +396,6 @@ int receive_error(const Sock& socket) { return native_error(); } -int timeout_option(int optname) { - if (optname == NET_SO_SCE_SNDTIMEO) return NET_SO_SNDTIMEO; - if (optname == NET_SO_SCE_RCVTIMEO) return NET_SO_RCVTIMEO; - return optname; -} - } // namespace extern "C" { From 60fb52857252c377f37a8a47732c30567ac107e3 Mon Sep 17 00:00:00 2001 From: Yunus Shaikh <75296019+EagleBearerYS@users.noreply.github.com> Date: Tue, 13 Oct 2026 00:34:06 -0700 Subject: [PATCH 3/3] refactor(libSceNet): place the SCE timeout constants and timeout_option apart from new neighbours #4988 adds a constant after NET_SO_RCVTIMEO and #4989 adds a function before receive_error, so defining the SCE timeout constants and timeout_option there made the pull requests conflict. --- core/libs/prx/libSceNet/Export.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/libs/prx/libSceNet/Export.cpp b/core/libs/prx/libSceNet/Export.cpp index 75b457392..956191eaa 100644 --- a/core/libs/prx/libSceNet/Export.cpp +++ b/core/libs/prx/libSceNet/Export.cpp @@ -77,13 +77,13 @@ constexpr int NET_EPOLL_CTL_DEL = 3; constexpr int NET_SOL_SOCKET = 0xFFFF; constexpr int NET_SO_SNDTIMEO = 0x1005; constexpr int NET_SO_RCVTIMEO = 0x1006; -constexpr int NET_SO_SCE_SNDTIMEO = 0x1105; -constexpr int NET_SO_SCE_RCVTIMEO = 0x1106; constexpr int NET_SO_NBIO = 0x1200; constexpr int NET_SO_REUSEADDR = 0x4; constexpr int NET_SO_BROADCAST = 0x20; constexpr int NET_SO_SNDBUF = 0x1001; constexpr int NET_SO_RCVBUF = 0x1002; +constexpr int NET_SO_SCE_SNDTIMEO = 0x1105; +constexpr int NET_SO_SCE_RCVTIMEO = 0x1106; constexpr int NET_MSG_PEEK = 0x2; constexpr int NET_MSG_TRUNC = 0x10; constexpr int NET_UIO_MAXIOV = 1024; @@ -367,6 +367,12 @@ struct NetMsghdr { static_assert(sizeof(NetMsghdr) == 48 && offsetof(NetMsghdr, iov) == 16 && offsetof(NetMsghdr, control) == 32 && offsetof(NetMsghdr, flags) == 44); +int timeout_option(int optname) { + if (optname == NET_SO_SCE_SNDTIMEO) return NET_SO_SNDTIMEO; + if (optname == NET_SO_SCE_RCVTIMEO) return NET_SO_RCVTIMEO; + return optname; +} + std::int64_t message_length(const NetMsghdr* message) { if (!message) return fail(NET_EFAULT); if (message->iov_length < 0 || message->iov_length > NET_UIO_MAXIOV) return fail(NET_EMSGSIZE); @@ -381,12 +387,6 @@ std::int64_t message_length(const NetMsghdr* message) { return static_cast(total); } -int timeout_option(int optname) { - if (optname == NET_SO_SCE_SNDTIMEO) return NET_SO_SNDTIMEO; - if (optname == NET_SO_SCE_RCVTIMEO) return NET_SO_RCVTIMEO; - return optname; -} - int receive_error(const Sock& socket) { #ifdef _WIN32 if (WSAGetLastError() == WSAETIMEDOUT && socket.type != NET_SOCK_STREAM && socket.rcv_timeout_us > 0) return NET_EAGAIN;