fix(libSceNet): sceNetEpollControl takes 2 as MOD and 3 as DEL
sceNetEpollControl used Linux's EPOLL_CTL numbering (1 ADD, 2 DEL, 3 MOD). The SCE values are 1 ADD, 2 MOD, 3 DEL (shadPS4 net_types.h, ORBIS_NET_EPOLL_CTL_*). A title removing a socket with op 3 and a null event got EINVAL, and op 2 deleted the registration it meant to modify. PPSA01289 (Sackboy: A Big Adventure) removes its UDP socket from its epoll this way before closing it, every time its network session is torn down. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
bab7b32852
commit
22827bf6ad
|
|
@ -70,6 +70,9 @@ constexpr int NET_AF_INET6 = 28;
|
|||
constexpr int NET_SOCK_STREAM = 1;
|
||||
constexpr int NET_SOCK_DGRAM = 2;
|
||||
constexpr int NET_SOCK_RAW = 3;
|
||||
constexpr int NET_EPOLL_CTL_ADD = 1;
|
||||
constexpr int NET_EPOLL_CTL_MOD = 2;
|
||||
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;
|
||||
|
|
@ -958,13 +961,13 @@ int APS5_VABI sceNetEpollControl(int eid, int op, int id, const NetEpollEvent* e
|
|||
if (g_epolls.count(eid) == 0) {
|
||||
return fail(NET_EBADF);
|
||||
}
|
||||
if (op < 1 || op > 3) return fail(NET_EINVAL);
|
||||
if (op != 2 && !event) return fail(NET_EINVAL);
|
||||
if (op != 2 && g_socks.count(id) == 0) return fail(NET_EBADF);
|
||||
if (op != NET_EPOLL_CTL_ADD && op != NET_EPOLL_CTL_MOD && op != NET_EPOLL_CTL_DEL) return fail(NET_EINVAL);
|
||||
if (op != NET_EPOLL_CTL_DEL && !event) return fail(NET_EINVAL);
|
||||
if (op != NET_EPOLL_CTL_DEL && g_socks.count(id) == 0) return fail(NET_EBADF);
|
||||
auto& registrations = g_epoll_socks[eid];
|
||||
if (op == 1) {
|
||||
if (op == NET_EPOLL_CTL_ADD) {
|
||||
if (!registrations.emplace(id, *event).second) return fail(NET_EADDRINUSE);
|
||||
} else if (op == 2) {
|
||||
} else if (op == NET_EPOLL_CTL_DEL) {
|
||||
if (registrations.erase(id) == 0) return fail(NET_ENOENT);
|
||||
} else {
|
||||
auto registration = registrations.find(id);
|
||||
|
|
|
|||
|
|
@ -400,6 +400,12 @@ int main() {
|
|||
Require(sceNetEpollWait(epoll, &ready, 1, 1000000) == 1 && (ready.events & 1) && ready.ident == static_cast<std::uint64_t>(accepted));
|
||||
Require(sceNetShutdown(accepted, 1) == 0);
|
||||
Require(Failed(sceNetSend(accepted, request, sizeof(request), 0), 32));
|
||||
registration.data.u32 = 78;
|
||||
Require(sceNetEpollControl(epoll, 2, accepted, ®istration) == 0);
|
||||
Require(Failed(sceNetEpollControl(epoll, 2, accepted, nullptr), 22));
|
||||
Require(sceNetEpollControl(epoll, 3, accepted, nullptr) == 0);
|
||||
Require(Failed(sceNetEpollControl(epoll, 3, accepted, nullptr), 2));
|
||||
Require(Failed(sceNetEpollControl(epoll, 2, accepted, ®istration), 2));
|
||||
Require(sceNetEpollDestroy(epoll) == 0);
|
||||
Require(sceNetSocketClose(accepted) == 0);
|
||||
bool send_failed = false;
|
||||
|
|
|
|||
Loading…
Reference in New Issue