Merge pull request #4610 from EagleBearerYS/fix/libscenet-sce-socket-timeouts

fix(libSceNet): take 0x1105 and 0x1106 as the send and receive timeouts
This commit is contained in:
Adrià 2026-10-13 17:28:11 +02:00 committed by GitHub
commit 2f6ae9fc88
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 29 additions and 1 deletions

View File

@ -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;

View File

@ -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<std::
Require(sceNetSetsockopt(receiver, 0xffff, 0x1006, &disabled, sizeof(disabled)) == 0);
}
static void CheckMicrosecondTimeouts(int receiver) {
const int receiveTimeout = 50000;
const int sendTimeout = 70000;
Require(sceNetSetsockopt(receiver, 0xffff, 0x1106, &receiveTimeout, sizeof(receiveTimeout)) == 0);
Require(sceNetSetsockopt(receiver, 0xffff, 0x1105, &sendTimeout, sizeof(sendTimeout)) == 0);
for (const auto [option, expected] : {std::array{0x1106, receiveTimeout}, std::array{0x1105, sendTimeout}}) {
int value = -1;
std::uint32_t size = sizeof(value);
Require(sceNetGetsockopt(receiver, 0xffff, option, &value, &size) == 0 && size == sizeof(value) && value == expected);
}
char buffer[8]{};
Require(Failed(sceNetRecv(receiver, buffer, sizeof(buffer), 0), 35));
const int disabled = 0;
Require(sceNetSetsockopt(receiver, 0xffff, 0x1106, &disabled, sizeof(disabled)) == 0);
Require(sceNetSetsockopt(receiver, 0xffff, 0x1105, &disabled, sizeof(disabled)) == 0);
}
static void CheckMessages(int receiver, int sender, const std::array<std::uint8_t, 16>& 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);