diff --git a/core/libs/prx/libSceNet/Export.cpp b/core/libs/prx/libSceNet/Export.cpp index 44edcd630..1dac77f64 100644 --- a/core/libs/prx/libSceNet/Export.cpp +++ b/core/libs/prx/libSceNet/Export.cpp @@ -87,6 +87,8 @@ 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; @@ -437,6 +439,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); @@ -943,6 +951,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)); @@ -988,7 +997,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 e75f04bc3..40dbfc727 100644 --- a/core/libs/tests/GuestSceNet.cpp +++ b/core/libs/tests/GuestSceNet.cpp @@ -46,6 +46,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); @@ -250,6 +251,23 @@ static void CheckReceiveTimeout(int receiver, int sender, const std::array& address) { char head[] = "scatter "; char tail[] = "gather"; @@ -662,6 +680,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);