From bec511d872b11fb9ef3763b8f3dfa504d6ccb541 Mon Sep 17 00:00:00 2001 From: KernelPanicNT <76663133+KernelPanicNT@users.noreply.github.com> Date: Wed, 14 Oct 2026 13:55:38 +0000 Subject: [PATCH] feat(libSceNpWebApi2): add web trace tags and abort push event handles offline sceNpWebApi2AddWebTraceTag follows shadPS4: a null value returns INVALID_ARGUMENT and any other value is added as the X-Psn-WebTrace-Tag header through sceNpWebApi2AddHttpRequestHeader. sceNpWebApi2PushEventAbortHandle returns success for a known library context, since push event handles are not tracked and nothing waits on one offline. An unknown context throws, as in sceNpWebApi2PushEventSetHandleTimeout, because its PS5 error code is unknown. Co-Authored-By: Claude Opus 5.5 --- core/libs/prx/libSceNpWebApi2/Export.cpp | 10 +++++----- core/libs/tests/GuestNpWebApi2.cpp | 7 +++++++ docs/dev/debt/libSceNpWebApi2.md | 3 ++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/core/libs/prx/libSceNpWebApi2/Export.cpp b/core/libs/prx/libSceNpWebApi2/Export.cpp index f36474b481b..149c6e051e8 100644 --- a/core/libs/prx/libSceNpWebApi2/Export.cpp +++ b/core/libs/prx/libSceNpWebApi2/Export.cpp @@ -36,9 +36,9 @@ int APS5_VABI sceNpWebApi2AddHttpRequestHeader(int64_t request_id, const char* f return 0; } -int APS5_VABI sceNpWebApi2AddWebTraceTag() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceNpWebApi2AddWebTraceTag(int64_t request_id, const char* value) { + if (!value) return SCE_NP_WEBAPI2_ERROR_INVALID_ARGUMENT; + return sceNpWebApi2AddHttpRequestHeader(request_id, "X-Psn-WebTrace-Tag", value); } void APS5_VABI sceNpWebApi2CheckTimeout(void) { @@ -119,9 +119,9 @@ int APS5_VABI sceNpWebApi2PushEventCreateHandle(int lib_ctx_id) { } int APS5_VABI sceNpWebApi2PushEventAbortHandle(int libCtxId, int handleId) { - (void)libCtxId; (void)handleId; - NotImplemented_nid_no_patch(__func__); + std::lock_guard lock(g_poolsMutex); + if (!g_pools.contains(libCtxId)) throw std::invalid_argument("sceNpWebApi2PushEventAbortHandle: unknown context"); return 0; } diff --git a/core/libs/tests/GuestNpWebApi2.cpp b/core/libs/tests/GuestNpWebApi2.cpp index b01b7e19025..7dbcb290002 100644 --- a/core/libs/tests/GuestNpWebApi2.cpp +++ b/core/libs/tests/GuestNpWebApi2.cpp @@ -21,6 +21,8 @@ int APS5_VABI sceNpWebApi2CreateUserContext(int, int); int APS5_VABI sceNpWebApi2CreateRequest(int, const char*, const char*, const char*, const void*, std::int64_t*); int APS5_VABI sceNpWebApi2SetRequestTimeout(std::int64_t, std::uint32_t); int APS5_VABI sceNpWebApi2DeleteRequest(std::int64_t); +int APS5_VABI sceNpWebApi2AddWebTraceTag(std::int64_t, const char*); +int APS5_VABI sceNpWebApi2PushEventAbortHandle(int, int); } static void Require(bool value) { if (!value) std::abort(); } @@ -47,14 +49,19 @@ int main() { const int handle = sceNpWebApi2PushEventCreateHandle(context); Require(handle > 0); Require(sceNpWebApi2PushEventSetHandleTimeout(context, handle, 30000) == 0); + Require(sceNpWebApi2PushEventAbortHandle(context, handle) == 0); + Require(sceNpWebApi2PushEventAbortHandle(other, handle + 100) == 0); const int user = sceNpWebApi2CreateUserContext(context, 1); std::int64_t request = 0; Require(user > 0 && sceNpWebApi2CreateRequest(user, "sessionManager", "/v1/sessions", "GET", nullptr, &request) == 0); Require(sceNpWebApi2SetRequestTimeout(request, 30000000) == 0); + Require(sceNpWebApi2AddWebTraceTag(request, "trace-tag") == 0); + Require(sceNpWebApi2AddWebTraceTag(request, nullptr) == static_cast(0x80553402)); Require(sceNpWebApi2DeleteRequest(request) == 0); Require(sceNpWebApi2Terminate(context) == 0); Require(Throws([&] { sceNpWebApi2GetMemoryPoolStats(context, &stats); })); Require(Throws([&] { sceNpWebApi2PushEventSetHandleTimeout(context, handle, 30000); })); + Require(Throws([&] { sceNpWebApi2PushEventAbortHandle(context, handle); })); Require(sceNpWebApi2Terminate(other) == 0); return 0; } diff --git a/docs/dev/debt/libSceNpWebApi2.md b/docs/dev/debt/libSceNpWebApi2.md index 9e8e3461c64..875ba59cb94 100644 --- a/docs/dev/debt/libSceNpWebApi2.md +++ b/docs/dev/debt/libSceNpWebApi2.md @@ -6,6 +6,7 @@ ### Unknown function info -- [sceNpWebApi2PushEventAbortHandle](../../../core/libs/prx/libSceNpWebApi2/Export.cpp) (libSceNpWebApi2, NID `1OLgvahaSco`) is a throwing stub. The two signed 32-bit handle arguments and return type follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/443f022450f6857256e780daa3d5a14029a748f7/src/core/libraries/np/np_web_api2/np_web_api2.cpp) (PS4); the PS5 signature and abort behavior are unverified. PPSA01736 imports it. +- [sceNpWebApi2PushEventAbortHandle](../../../core/libs/prx/libSceNpWebApi2/Export.cpp) (libSceNpWebApi2, NID `1OLgvahaSco`) - PPSA01736 imports it. The two signed 32-bit arguments and the return type follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/f47bbd5d6e9f49d3fd11cb4fd50533a835976a08/src/core/libraries/np/np_web_api2/np_web_api2.cpp#L229-L232) (PS4); the PS5 signature is unverified. A known library context returns success: push event handles are not tracked (`sceNpWebApi2PushEventDeleteHandle` accepts any handle) and nothing waits on one offline, so there is nothing to abort. An unknown library context throws, as in `sceNpWebApi2PushEventSetHandleTimeout`, since its PS5 error code is unknown; shadPS4 returns `LIB_CONTEXT_NOT_FOUND` there and `HANDLE_NOT_FOUND` for an unknown handle +- [sceNpWebApi2AddWebTraceTag](../../../core/libs/prx/libSceNpWebApi2/Export.cpp) (libSceNpWebApi2) - the `(int64_t requestId, const char* value)` signature and behaviour follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/f47bbd5d6e9f49d3fd11cb4fd50533a835976a08/src/core/libraries/np/np_web_api2/np_web_api2.cpp#L38-L45) (PS4): a null value returns `INVALID_ARGUMENT`, and any other value is added as the `X-Psn-WebTrace-Tag` header through `sceNpWebApi2AddHttpRequestHeader`, which accepts every request id here. The PS5 signature is unverified - [sceNpWebApi2GetMemoryPoolStats](../../../core/libs/prx/libSceNpWebApi2/Export.cpp) (libSceNpWebApi2) - imported by PPSA21703's Unity PSN plugin. The signature `(int libCtxId, stats*)` and the layout of the Http2 statistics above (measured on a PS5 for Http2, Ssl and Net) are assumed for this library, not measured. The pool size is the one given to `sceNpWebApi2Initialize`, and the peak and current use are 0. The error codes are unknown, so a null output or an unknown context throws - [sceNpWebApi2PushEventSetHandleTimeout](../../../core/libs/prx/libSceNpWebApi2/Export.cpp) (libSceNpWebApi2) - imported by PPSA01317, which fails to load without it. The signature `(int libCtxId, int handleId, uint32_t timeout)` follows `sceNpWebApiSetHandleTimeout` of the PS4 libSceNpWebApi in [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/main/src/core/libraries/np/np_web_api.cpp) and is unverified on the PS5. An unknown library context throws, as in `sceNpWebApi2GetMemoryPoolStats`, since its error code is unknown. The handle is not checked, as push event handles are not tracked (`sceNpWebApi2PushEventDeleteHandle` accepts any handle), and the timeout is not kept, as nothing waits on a handle offline