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