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.
This commit is contained in:
parent
2a5eca11cd
commit
febc36223b
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<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";
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue