mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-07-09 17:25:37 -06:00
Lib.NpWebApi2: Library implementation (#4677)
* Fix error definitions
* sceNpWebApi2Initialize, sceNpWebApi2InitializeForPresence, sceNpWebApi2IntInitialize, sceNpWebApi2IntInitialize2
Defines classes for various existing objects in the library, and adds support for creating library context objects.
* sceNpGetSdkVersion
* sceNpWebApi2CreateUserContext
* Clang
* More clang
* sceNpWebApi2GetMemoryPoolStats
* stuff
* sceNpWebApi2CreateRequest, sceNpWebApi2CreateMultipartRequest
* sceNpWebApi2AddHttpRequestHeader
* Why bother with pointers when deque exists?
* sceNpWebApi2SendRequest
* sceNpWebApi2AbortRequest, sceNpWebApi2DeleteRequest
* Stub libSceHttp2 calls using libSceHttp
Also some bug fixes to make sure requests actually work properly.
* Clean things I'm not doing yet
Probably done enough to be worth pushing, as now most games just complain from missing endpoints.
* Update np_web_api2_context.h
* sceNpWebApi2DeleteUserContext
* sceNpWebApi2SetRequestTimeout
* sceNpWebApi2GetHttpResponseHeaderValue, sceNpWebApi2GetHttpResponseHeaderValueLength
* sceNpWebApi2ReadData
* Revert "Clean things I'm not doing yet"
This reverts commit 598f67e8bb.
* sceNpWebApi2PushEventCreateHandle
* Misc stuff
* Started work on sceNpWebApi2PushEventCreateFilter
The actual filter doesn't create yet
* Some touchups
* Define base callback for checking push events
Will fill out once push event stuff is done
* Finish sceNpWebApi2PushEventCreateFilter
* Define remaining parts
* Logging adjustments, copy filter param extd data keys
* sceNpWebApi2PushEventRegisterCallback
* Store data_key vectors
So they're properly deleted on PushEventFilter destructors (which will be important when I implement the proper functions for that)
* sceNpWebApi2PushEventRegisterPushContextCallback
* sceNpWebApi2PushEventUnregisterCallback, sceNpWebApi2PushEventUnregisterPushContextCallback
* sceNpWebApi2PushEventAbortHandle
* sceNpWebApi2PushEventDeleteFilter
* sceNpWebApi2PushEventDeleteHandle
* Clang
* sceNpWebApi2PushEventSetHandleTimeout
* sceNpWebApi2AddWebTraceTag
* sceNpWebApi2PushEventCreatePushContext, sceNpWebApi2PushEventStartPushContextCallback
* Clang
* sceNpWebApi2PushEventDeletePushContext
* sceNpWebApi2Terminate
* Slight fix to sceNpWebApi2DeleteUserContext
* sceNpWebApi2CheckTimeout
This commit is contained in:
parent
474fbe741d
commit
64d198190f
@ -649,8 +649,6 @@ set(NP_LIBS src/core/libraries/np/np_error.h
|
||||
src/core/libraries/np/np_tus.h
|
||||
src/core/libraries/np/trophy_ui.cpp
|
||||
src/core/libraries/np/trophy_ui.h
|
||||
src/core/libraries/np/np_web_api2.cpp
|
||||
src/core/libraries/np/np_web_api2.h
|
||||
src/core/libraries/np/np_party.cpp
|
||||
src/core/libraries/np/np_party.h
|
||||
src/core/libraries/np/np_auth.cpp
|
||||
@ -685,6 +683,14 @@ set(NP_LIBS src/core/libraries/np/np_error.h
|
||||
src/core/libraries/np/np_web_api/np_web_api.h
|
||||
src/core/libraries/np/np_web_api/np_web_api_internal.cpp
|
||||
src/core/libraries/np/np_web_api/np_web_api_internal.h
|
||||
src/core/libraries/np/np_web_api2/np_web_api2.cpp
|
||||
src/core/libraries/np/np_web_api2/np_web_api2.h
|
||||
src/core/libraries/np/np_web_api2/np_web_api2_internal.cpp
|
||||
src/core/libraries/np/np_web_api2/np_web_api2_internal.h
|
||||
src/core/libraries/np/np_web_api2/np_web_api2_context.cpp
|
||||
src/core/libraries/np/np_web_api2/np_web_api2_context.h
|
||||
src/core/libraries/np/np_web_api2/np_web_api2_push_event.cpp
|
||||
src/core/libraries/np/np_web_api2/np_web_api2_push_event.h
|
||||
)
|
||||
|
||||
set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp
|
||||
|
||||
@ -49,7 +49,7 @@
|
||||
#include "core/libraries/np/np_trophy.h"
|
||||
#include "core/libraries/np/np_tus.h"
|
||||
#include "core/libraries/np/np_web_api/np_web_api.h"
|
||||
#include "core/libraries/np/np_web_api2.h"
|
||||
#include "core/libraries/np/np_web_api2/np_web_api2.h"
|
||||
#include "core/libraries/pad/pad.h"
|
||||
#include "core/libraries/playgo/playgo.h"
|
||||
#include "core/libraries/playgo/playgo_dialog.h"
|
||||
|
||||
@ -4,293 +4,359 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "core/libraries/network/http.h"
|
||||
#include "core/libraries/network/http2.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace Libraries::Http2 {
|
||||
|
||||
int PS4_SYSV_ABI _Z5dummyv() {
|
||||
std::map<s32, s32> requests_to_connections{};
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2AbortRequest(s32 req_id) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
s32 result = Libraries::Http::sceHttpAbortRequest(req_id);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to get abort HTTP request, error = {:#x}", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2AddCookie() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2AbortRequest() {
|
||||
s32 PS4_SYSV_ABI sceHttp2AddRequestHeader(s32 template_or_req_id, const char* name,
|
||||
const char* value, u32 mode) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
s32 result = Libraries::Http::sceHttpAddRequestHeader(template_or_req_id, name, value, mode);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to add HTTP response header, error = {:#x}", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2AuthCacheFlush() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2AddCookie() {
|
||||
s32 PS4_SYSV_ABI sceHttp2CookieExport() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2AddRequestHeader() {
|
||||
s32 PS4_SYSV_ABI sceHttp2CookieFlush() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2AuthCacheFlush() {
|
||||
s32 PS4_SYSV_ABI sceHttp2CookieImport() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2CookieExport() {
|
||||
s32 PS4_SYSV_ABI sceHttp2CreateCookieBox() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2CookieFlush() {
|
||||
s32 PS4_SYSV_ABI sceHttp2CreateRequestWithURL(s32 tmpl_id, const char* method, const char* url,
|
||||
u64 content_length) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
// Http1 has a connection thing to go through first
|
||||
s32 conn_id = Libraries::Http::sceHttpCreateConnectionWithURL(tmpl_id, url, true);
|
||||
if (conn_id < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to create HTTP connection, error = {:#x}", conn_id);
|
||||
return conn_id;
|
||||
}
|
||||
s32 req_id =
|
||||
Libraries::Http::sceHttpCreateRequestWithURL2(conn_id, method, url, content_length);
|
||||
if (req_id < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to create HTTP request, error = {:#x}", req_id);
|
||||
return req_id;
|
||||
}
|
||||
requests_to_connections[req_id] = conn_id;
|
||||
return req_id;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2CreateTemplate(s32 ctx_id, const char* user_agent, s32 http_ver,
|
||||
s32 auto_proxy_conf) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
s32 tmpl_id =
|
||||
Libraries::Http::sceHttpCreateTemplate(ctx_id, user_agent, http_ver, auto_proxy_conf);
|
||||
if (tmpl_id < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to create HTTP template, error = {:#x}", tmpl_id);
|
||||
}
|
||||
return tmpl_id;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2DeleteCookieBox() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2CookieImport() {
|
||||
s32 PS4_SYSV_ABI sceHttp2DeleteRequest(s32 req_id) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
s32 result = Libraries::Http::sceHttpDeleteRequest(req_id);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to delete HTTP request, error = {:#x}", result);
|
||||
return result;
|
||||
}
|
||||
s32 conn_id = requests_to_connections[req_id];
|
||||
result = Libraries::Http::sceHttpDeleteConnection(conn_id);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to delete HTTP connection, error = {:#x}", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2DeleteTemplate(s32 tmpl_id) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
s32 result = Libraries::Http::sceHttpDeleteTemplate(tmpl_id);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to delete HTTP template, error = {:#x}", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2GetAllResponseHeaders(s32 req_id, char** header, u64* header_size) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
s32 result = Libraries::Http::sceHttpGetAllResponseHeaders(req_id, header, header_size);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to get HTTP response headers, error = {:#x}", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2GetAuthEnabled() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2CreateCookieBox() {
|
||||
s32 PS4_SYSV_ABI sceHttp2GetAutoRedirect() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2CreateRequestWithURL() {
|
||||
s32 PS4_SYSV_ABI sceHttp2GetCookie() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2CreateTemplate() {
|
||||
s32 PS4_SYSV_ABI sceHttp2GetCookieBox() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2DeleteCookieBox() {
|
||||
s32 PS4_SYSV_ABI sceHttp2GetCookieStats() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2DeleteRequest() {
|
||||
s32 PS4_SYSV_ABI sceHttp2GetMemoryPoolStats() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2DeleteTemplate() {
|
||||
s32 PS4_SYSV_ABI sceHttp2GetResponseContentLength() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2GetAllResponseHeaders() {
|
||||
s32 PS4_SYSV_ABI sceHttp2GetStatusCode(s32 req_id, s32* status_code) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 result = Libraries::Http::sceHttpGetStatusCode(req_id, status_code);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to get HTTP status code, error = {:#x}", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2GetAuthEnabled() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2GetAutoRedirect() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2GetCookie() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2GetCookieBox() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2GetCookieStats() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2GetMemoryPoolStats() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2GetResponseContentLength() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2GetStatusCode() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2Init(int net_id, int ssl_id, size_t pool_size, int max_requests) {
|
||||
s32 PS4_SYSV_ABI sceHttp2Init(s32 net_id, s32 ssl_id, u64 pool_size, s32 max_requests) {
|
||||
LOG_ERROR(Lib_Http2, "(DUMMY) called");
|
||||
static int id = 0;
|
||||
return ++id;
|
||||
s32 ctx_id = Libraries::Http::sceHttpInit(net_id, ssl_id, pool_size);
|
||||
if (ctx_id < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to init HTTP context, error = {:#x}", ctx_id);
|
||||
}
|
||||
return ctx_id;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2ReadData() {
|
||||
s32 PS4_SYSV_ABI sceHttp2ReadData(s32 req_id, void* data, u64 size) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
s32 result = Libraries::Http::sceHttpReadData(req_id, data, size);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to read HTTP data, error = {:#x}", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2ReadDataAsync() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2ReadDataAsync() {
|
||||
s32 PS4_SYSV_ABI sceHttp2RedirectCacheFlush() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2RedirectCacheFlush() {
|
||||
s32 PS4_SYSV_ABI sceHttp2RemoveRequestHeader() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2RemoveRequestHeader() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SendRequest(s32 req_id, const void* data, u64 size) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
s32 result = Libraries::Http::sceHttpSendRequest(req_id, data, size);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to send HTTP request, error = {:#x}", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2SendRequestAsync() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SendRequest() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetAuthEnabled() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SendRequestAsync() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetAuthInfoCallback() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetAuthEnabled() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetAutoRedirect() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetAuthInfoCallback() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetConnectionWaitTimeOut() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetAutoRedirect() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetConnectTimeOut() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetConnectionWaitTimeOut() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetCookieBox() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetConnectTimeOut() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetCookieMaxNum() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetCookieBox() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetCookieMaxNumPerDomain() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetCookieMaxNum() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetCookieMaxSize() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetCookieMaxNumPerDomain() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetCookieRecvCallback() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetCookieMaxSize() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetCookieSendCallback() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetCookieRecvCallback() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetInflateGZIPEnabled() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetCookieSendCallback() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetMinSslVersion() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetInflateGZIPEnabled() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetPreSendCallback(s32 template_id, OrbisHttp2PreSendCallback cb_func,
|
||||
void* user_arg) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetMinSslVersion() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetRecvTimeOut() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetPreSendCallback() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetRedirectCallback() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetRecvTimeOut() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetRequestContentLength(s32 req_id, u64 content_length) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
s32 result = Libraries::Http::sceHttpSetRequestContentLength(req_id, content_length);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_Http2, "Failed to set HTTP request content length, error = {:#x}", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2SetResolveRetry() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetRedirectCallback() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetResolveTimeOut() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetRequestContentLength() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetSendTimeOut() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetResolveRetry() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetSslCallback() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetResolveTimeOut() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetTimeOut() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetSendTimeOut() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SslDisableOption() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetSslCallback() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SslEnableOption() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SetTimeOut() {
|
||||
s32 PS4_SYSV_ABI sceHttp2Term() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SslDisableOption() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2SslEnableOption() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2Term() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttp2WaitAsync() {
|
||||
s32 PS4_SYSV_ABI sceHttp2WaitAsync() {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("AS45QoYHjc4", "libSceHttp2", 1, "libSceHttp2", _Z5dummyv);
|
||||
LIB_FUNCTION("IZ-qjhRqvjk", "libSceHttp2", 1, "libSceHttp2", sceHttp2AbortRequest);
|
||||
LIB_FUNCTION("flPxnowtvWY", "libSceHttp2", 1, "libSceHttp2", sceHttp2AddCookie);
|
||||
LIB_FUNCTION("nrPfOE8TQu0", "libSceHttp2", 1, "libSceHttp2", sceHttp2AddRequestHeader);
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
#include "core/libraries/network/ssl2.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
@ -11,62 +12,38 @@ class SymbolsResolver;
|
||||
|
||||
namespace Libraries::Http2 {
|
||||
|
||||
int PS4_SYSV_ABI _Z5dummyv();
|
||||
int PS4_SYSV_ABI sceHttp2AbortRequest();
|
||||
int PS4_SYSV_ABI sceHttp2AddCookie();
|
||||
int PS4_SYSV_ABI sceHttp2AddRequestHeader();
|
||||
int PS4_SYSV_ABI sceHttp2AuthCacheFlush();
|
||||
int PS4_SYSV_ABI sceHttp2CookieExport();
|
||||
int PS4_SYSV_ABI sceHttp2CookieFlush();
|
||||
int PS4_SYSV_ABI sceHttp2CookieImport();
|
||||
int PS4_SYSV_ABI sceHttp2CreateCookieBox();
|
||||
int PS4_SYSV_ABI sceHttp2CreateRequestWithURL();
|
||||
int PS4_SYSV_ABI sceHttp2CreateTemplate();
|
||||
int PS4_SYSV_ABI sceHttp2DeleteCookieBox();
|
||||
int PS4_SYSV_ABI sceHttp2DeleteRequest();
|
||||
int PS4_SYSV_ABI sceHttp2DeleteTemplate();
|
||||
int PS4_SYSV_ABI sceHttp2GetAllResponseHeaders();
|
||||
int PS4_SYSV_ABI sceHttp2GetAuthEnabled();
|
||||
int PS4_SYSV_ABI sceHttp2GetAutoRedirect();
|
||||
int PS4_SYSV_ABI sceHttp2GetCookie();
|
||||
int PS4_SYSV_ABI sceHttp2GetCookieBox();
|
||||
int PS4_SYSV_ABI sceHttp2GetCookieStats();
|
||||
int PS4_SYSV_ABI sceHttp2GetMemoryPoolStats();
|
||||
int PS4_SYSV_ABI sceHttp2GetResponseContentLength();
|
||||
int PS4_SYSV_ABI sceHttp2GetStatusCode();
|
||||
int PS4_SYSV_ABI sceHttp2Init(int net_id, int ssl_id, size_t pool_size, int max_requests);
|
||||
int PS4_SYSV_ABI sceHttp2ReadData();
|
||||
int PS4_SYSV_ABI sceHttp2ReadDataAsync();
|
||||
int PS4_SYSV_ABI sceHttp2RedirectCacheFlush();
|
||||
int PS4_SYSV_ABI sceHttp2RemoveRequestHeader();
|
||||
int PS4_SYSV_ABI sceHttp2SendRequest();
|
||||
int PS4_SYSV_ABI sceHttp2SendRequestAsync();
|
||||
int PS4_SYSV_ABI sceHttp2SetAuthEnabled();
|
||||
int PS4_SYSV_ABI sceHttp2SetAuthInfoCallback();
|
||||
int PS4_SYSV_ABI sceHttp2SetAutoRedirect();
|
||||
int PS4_SYSV_ABI sceHttp2SetConnectionWaitTimeOut();
|
||||
int PS4_SYSV_ABI sceHttp2SetConnectTimeOut();
|
||||
int PS4_SYSV_ABI sceHttp2SetCookieBox();
|
||||
int PS4_SYSV_ABI sceHttp2SetCookieMaxNum();
|
||||
int PS4_SYSV_ABI sceHttp2SetCookieMaxNumPerDomain();
|
||||
int PS4_SYSV_ABI sceHttp2SetCookieMaxSize();
|
||||
int PS4_SYSV_ABI sceHttp2SetCookieRecvCallback();
|
||||
int PS4_SYSV_ABI sceHttp2SetCookieSendCallback();
|
||||
int PS4_SYSV_ABI sceHttp2SetInflateGZIPEnabled();
|
||||
int PS4_SYSV_ABI sceHttp2SetMinSslVersion();
|
||||
int PS4_SYSV_ABI sceHttp2SetPreSendCallback();
|
||||
int PS4_SYSV_ABI sceHttp2SetRecvTimeOut();
|
||||
int PS4_SYSV_ABI sceHttp2SetRedirectCallback();
|
||||
int PS4_SYSV_ABI sceHttp2SetRequestContentLength();
|
||||
int PS4_SYSV_ABI sceHttp2SetResolveRetry();
|
||||
int PS4_SYSV_ABI sceHttp2SetResolveTimeOut();
|
||||
int PS4_SYSV_ABI sceHttp2SetSendTimeOut();
|
||||
int PS4_SYSV_ABI sceHttp2SetSslCallback();
|
||||
int PS4_SYSV_ABI sceHttp2SetTimeOut();
|
||||
int PS4_SYSV_ABI sceHttp2SslDisableOption();
|
||||
int PS4_SYSV_ABI sceHttp2SslEnableOption();
|
||||
int PS4_SYSV_ABI sceHttp2Term();
|
||||
int PS4_SYSV_ABI sceHttp2WaitAsync();
|
||||
enum OrbisHttp2HttpVersion : u32 {
|
||||
ORBIS_HTTP2_VERSION_1_0 = 1,
|
||||
ORBIS_HTTP2_VERSION_1_1 = 2,
|
||||
ORBIS_HTTP2_VERSION_2_0 = 3,
|
||||
};
|
||||
|
||||
// TODO: Figure out the whole struct. What's here is based on libSceNpWebApi2 use.
|
||||
struct OrbisHttp2PreSendCallbackData {
|
||||
void* unk;
|
||||
void* cert;
|
||||
};
|
||||
using OrbisHttp2PreSendCallback = PS4_SYSV_ABI s32 (*)(s32 request_id, s32 ssl_id,
|
||||
OrbisHttp2PreSendCallbackData* data,
|
||||
void* user_arg);
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2AbortRequest(s32 req_id);
|
||||
s32 PS4_SYSV_ABI sceHttp2AddRequestHeader(s32 template_or_req_id, const char* name,
|
||||
const char* value, u32 mode);
|
||||
s32 PS4_SYSV_ABI sceHttp2CreateRequestWithURL(s32 tmpl_id, const char* method, const char* url,
|
||||
u64 content_length);
|
||||
s32 PS4_SYSV_ABI sceHttp2CreateTemplate(s32 ctx_id, const char* user_agent, s32 http_ver,
|
||||
s32 auto_proxy_conf);
|
||||
s32 PS4_SYSV_ABI sceHttp2DeleteRequest(s32 req_id);
|
||||
s32 PS4_SYSV_ABI sceHttp2DeleteTemplate(s32 tmpl_id);
|
||||
s32 PS4_SYSV_ABI sceHttp2GetAllResponseHeaders(s32 req_id, char** header, u64* header_size);
|
||||
s32 PS4_SYSV_ABI sceHttp2GetStatusCode(s32 request_id, s32* status_code);
|
||||
s32 PS4_SYSV_ABI sceHttp2Init(s32 net_id, s32 ssl_id, u64 pool_size, s32 max_requests);
|
||||
s32 PS4_SYSV_ABI sceHttp2ReadData(s32 req_id, void* data, u64 size);
|
||||
s32 PS4_SYSV_ABI sceHttp2SendRequest(s32 req_id, const void* data, u64 size);
|
||||
s32 PS4_SYSV_ABI sceHttp2SetPreSendCallback(s32 template_id, OrbisHttp2PreSendCallback cb_func,
|
||||
void* user_arg);
|
||||
s32 PS4_SYSV_ABI sceHttp2SetRequestContentLength(s32 req_id, u64 content_length);
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Http2
|
||||
@ -390,6 +390,17 @@ s32 PS4_SYSV_ABI sceNpIntIsValidOnlineId(const OrbisNpOnlineId* id) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void PS4_SYSV_ABI sceNpGetSdkVersion(char* version_buf) {
|
||||
LOG_DEBUG(Lib_NpCommon, "called");
|
||||
// Real library has no parameter checks, so I guess this is purely for internal use?
|
||||
Libraries::Kernel::SwVersionStruct sw_version{};
|
||||
sw_version.struct_size = 0x28;
|
||||
Libraries::Kernel::sceKernelGetSystemSwVersion(&sw_version);
|
||||
u32 sw_hex = sw_version.hex_representation;
|
||||
snprintf(version_buf, 8, "%d.%02d", ((sw_hex >> 0x18) & 0xf) + ((sw_hex >> 0x1c) * 10),
|
||||
((sw_hex >> 0x10) & 0xf) + (((sw_hex >> 0x14) & 0xf) * 10));
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpCalloutInitCtx(OrbisNpCalloutContext* callout_ctx, const char* name,
|
||||
u64 stack_size, s32 priority, u64 affinity_mask) {
|
||||
LOG_DEBUG(Lib_NpCommon, "ctx={:p} name={:p} stack={:#x} priority={} affinity={:#x}",
|
||||
@ -600,6 +611,7 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("ss2xO9IJxKQ", "libSceNpCommon", 1, "libSceNpCommon", sceNpCondTimedwait);
|
||||
LIB_FUNCTION("uEwag-0YZPc", "libSceNpCommon", 1, "libSceNpCommon", sceNpMutexInit);
|
||||
LIB_FUNCTION("uMJFOA62mVU", "libSceNpCommon", 1, "libSceNpCommon", sceNpCondSignal);
|
||||
LIB_FUNCTION("Pglk7zFj0DI", "libSceNpCommon", 1, "libSceNpCommon", sceNpGetSdkVersion);
|
||||
};
|
||||
|
||||
} // namespace Libraries::Np::NpCommon
|
||||
|
||||
@ -62,6 +62,7 @@ u32 PS4_SYSV_ABI sceNpJoinThread(Libraries::Kernel::PthreadT thread, void** ret)
|
||||
s32 PS4_SYSV_ABI sceNpGetSystemClockUsec(s64* usec);
|
||||
s32 PS4_SYSV_ABI sceNpGetPlatformType(const OrbisNpId* np_id);
|
||||
s32 PS4_SYSV_ABI sceNpIntIsValidOnlineId(const OrbisNpOnlineId* id);
|
||||
void PS4_SYSV_ABI sceNpGetSdkVersion(char* version_buf);
|
||||
s32 PS4_SYSV_ABI sceNpCalloutInitCtx(OrbisNpCalloutContext* ctx, const char* name, u64 stack_size,
|
||||
s32 priority, u64 affinity_mask);
|
||||
s32 PS4_SYSV_ABI sceNpCalloutStartOnCtx(OrbisNpCalloutContext* ctx, OrbisNpCalloutEntry* callout,
|
||||
|
||||
@ -553,25 +553,25 @@ constexpr int ORBIS_NP_WEBAPI2_ERROR_REQUEST_NOT_FOUND = 0x80553406;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_NOT_SIGNED_IN = 0x80553407;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_INVALID_CONTENT_PARAMETER = 0x80553408;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_ABORTED = 0x80553409;
|
||||
constexpr int ORBIS_NP_WEBAPI2_USER_CONTEXT_ALREADY_EXIST = 0x8055340a;
|
||||
constexpr int ORBIS_NP_WEBAPI2_PUSH_EVENT_FILTER_NOT_FOUND = 0x8055340b;
|
||||
constexpr int ORBIS_NP_WEBAPI2_PUSH_EVENT_CALLBACK_NOT_FOUND = 0x8055340c;
|
||||
constexpr int ORBIS_NP_WEBAPI2_HANDLE_NOT_FOUND = 0x8055340d;
|
||||
constexpr int ORBIS_NP_WEBAPI2_SIGNED_IN_USER_NOT_FOUND = 0x8055340e;
|
||||
constexpr int ORBIS_NP_WEBAPI2_LIB_CONTEXT_BUSY = 0x8055340f;
|
||||
constexpr int ORBIS_NP_WEBAPI2_USER_CONTEXT_BUSY = 0x80553410;
|
||||
constexpr int ORBIS_NP_WEBAPI2_REQUEST_BUSY = 0x80553411;
|
||||
constexpr int ORBIS_NP_WEBAPI2_INVALID_HTTP_STATUS_CODE = 0x80553412;
|
||||
constexpr int ORBIS_NP_WEBAPI2_PROHIBITED_HTTP_HEADER = 0x80553413;
|
||||
constexpr int ORBIS_NP_WEBAPI2_PROHIBITED_FUNCTION_CALL = 0x80553414;
|
||||
constexpr int ORBIS_NP_WEBAPI2_MULTIPART_PART_NOT_FOUND = 0x80553415;
|
||||
constexpr int ORBIS_NP_WEBAPI2_PARAMETER_TOO_LONG = 0x80553416;
|
||||
constexpr int ORBIS_NP_WEBAPI2_HANDLE_BUSY = 0x80553417;
|
||||
constexpr int ORBIS_NP_WEBAPI2_LIB_CONTEXT_MAX = 0x80553418;
|
||||
constexpr int ORBIS_NP_WEBAPI2_USER_CONTEXT_MAX = 0x80553419;
|
||||
constexpr int ORBIS_NP_WEBAPI2_AFTER_SEND = 0x8055341a;
|
||||
constexpr int ORBIS_NP_WEBAPI2_TIMEOUT = 0x8055341b;
|
||||
constexpr int ORBIS_NP_WEBAPI2_PUSH_CONTEXT_NOT_FOUND = 0x8055341c;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_ALREADY_EXIST = 0x8055340a;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_PUSH_EVENT_FILTER_NOT_FOUND = 0x8055340b;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_PUSH_EVENT_CALLBACK_NOT_FOUND = 0x8055340c;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_HANDLE_NOT_FOUND = 0x8055340d;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_SIGNED_IN_USER_NOT_FOUND = 0x8055340e;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_BUSY = 0x8055340f;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_BUSY = 0x80553410;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_REQUEST_BUSY = 0x80553411;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_INVALID_HTTP_STATUS_CODE = 0x80553412;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_PROHIBITED_HTTP_HEADER = 0x80553413;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_PROHIBITED_FUNCTION_CALL = 0x80553414;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_MULTIPART_PART_NOT_FOUND = 0x80553415;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_PARAMETER_TOO_LONG = 0x80553416;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_HANDLE_BUSY = 0x80553417;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_MAX = 0x80553418;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_MAX = 0x80553419;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_AFTER_SEND = 0x8055341a;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_TIMEOUT = 0x8055341b;
|
||||
constexpr int ORBIS_NP_WEBAPI2_ERROR_PUSH_CONTEXT_NOT_FOUND = 0x8055341c;
|
||||
|
||||
// NP Session Management Client (0x80553600 - 0x8055361e)
|
||||
constexpr int ORBIS_NP_SESSION_MANAGEMENT_CLIENT_ERROR_ALREADY_INITIALIZED = 0x80553600;
|
||||
|
||||
@ -1,331 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/emulator_settings.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "core/libraries/np/np_error.h"
|
||||
#include "core/libraries/np/np_web_api2.h"
|
||||
#include "core/libraries/system/userservice.h"
|
||||
|
||||
namespace Libraries::Np::NpWebApi2 {
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2AbortRequest(s64 request_id) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called, request_id = {:#x}", request_id);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2AddHttpRequestHeader() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2AddMultipartPart() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2AddWebTraceTag() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void PS4_SYSV_ABI sceNpWebApi2CheckTimeout() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2CreateMultipartRequest() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2CreateRequest() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2CreateUserContext(s32 lib_ctx_id,
|
||||
UserService::OrbisUserServiceUserId user_id) {
|
||||
if (lib_ctx_id >= 0x8000) {
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_LIB_CONTEXT_ID;
|
||||
}
|
||||
if (user_id == UserService::ORBIS_USER_SERVICE_USER_ID_INVALID) {
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called, lib_ctx_id = {:#x}, user_id = {:#x}", lib_ctx_id,
|
||||
user_id);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2DeleteRequest(s64 request_id) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called, request_id = {:#x}", request_id);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2DeleteUserContext(s32 user_ctx_id) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called, user_ctx_id = {:#x}", user_ctx_id);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2GetHttpResponseHeaderValue() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2GetHttpResponseHeaderValueLength() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2GetMemoryPoolStats(s32 lib_ctx_id,
|
||||
OrbisNpWebApi2MemoryPoolStats* stats) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called, lib_ctx_id = {:#x}", lib_ctx_id);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2Initialize(s32 lib_http_ctx_id, u64 pool_size) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called, lib_http_ctx_id = {:#x}, pool_size = {:#x}",
|
||||
lib_http_ctx_id, pool_size);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2InitializeForPresence(s32 lib_http_ctx_id, u64 pool_size) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called, lib_http_ctx_id = {:#x}, pool_size = {:#x}",
|
||||
lib_http_ctx_id, pool_size);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2IntCreateRequest() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2IntInitialize(const OrbisNpWebApi2IntInitializeArgs* args) {
|
||||
if (args == nullptr || args->struct_size != sizeof(OrbisNpWebApi2IntInitializeArgs)) {
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
LOG_ERROR(Lib_NpWebApi2,
|
||||
"(STUBBED) called, lib_http_ctx_id = {:#x}, pool_size = {:#x}, name = '{}'",
|
||||
args->lib_http_ctx_id, args->pool_size, args->name);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2IntInitialize2(const OrbisNpWebApi2IntInitialize2Args* args) {
|
||||
if (args == nullptr || args->struct_size != sizeof(OrbisNpWebApi2IntInitialize2Args)) {
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
LOG_ERROR(Lib_NpWebApi2,
|
||||
"(STUBBED) called, lib_http_ctx_id = {:#x}, pool_size = {:#x}, name = '{}', "
|
||||
"group = {:#x}",
|
||||
args->lib_http_ctx_id, args->pool_size, args->name, args->push_config_group);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2IntPushEventCreateCtxIndFilter() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventAbortHandle() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventCreateFilter() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventCreateHandle() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventCreatePushContext() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventDeleteFilter() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventDeleteHandle() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventDeletePushContext() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventRegisterCallback() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventRegisterPushContextCallback() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventSetHandleTimeout() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventStartPushContextCallback() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventUnregisterCallback() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventUnregisterPushContextCallback() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2ReadData(s64 request_id, void* data, u64 size) {
|
||||
if (data == nullptr || size == 0) {
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called, request_id = {:#x}, size = {:#x}", request_id,
|
||||
size);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2SendMultipartRequest() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2SendRequest() {
|
||||
if (!EmulatorSettings.IsShadNetEnabled()) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, returning shadNet signed out.");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_NOT_SIGNED_IN;
|
||||
}
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2SetMultipartContentType() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2SetRequestTimeout(s64 request_id, u32 timeout) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called, request_id = {:#x}, timeout = {}", request_id,
|
||||
timeout);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2Terminate(s32 lib_ctx_id) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called, lib_ctx_id = {:#x}", lib_ctx_id);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI Func_A9A31C5F6FBA6620() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI Func_03D22863300D2B73() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI Func_97296F7578AAD541() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI Func_E0DF39A36F087DB9() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("zpiPsH7dbFQ", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2AbortRequest);
|
||||
LIB_FUNCTION("egOOvrnF6mI", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2AddHttpRequestHeader);
|
||||
LIB_FUNCTION("Io7kh1LHDoM", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2AddMultipartPart);
|
||||
LIB_FUNCTION("MgsTa76wlEk", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2AddWebTraceTag);
|
||||
LIB_FUNCTION("3Tt9zL3tkoc", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2CheckTimeout);
|
||||
LIB_FUNCTION("+nz1Vq-NrDA", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2CreateMultipartRequest);
|
||||
LIB_FUNCTION("3EI-OSJ65Xc", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2CreateRequest);
|
||||
LIB_FUNCTION("sk54bi6FtYM", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2CreateUserContext);
|
||||
LIB_FUNCTION("vvzWO-DvG1s", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2DeleteRequest);
|
||||
LIB_FUNCTION("9X9+cneTGUU", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2DeleteUserContext);
|
||||
LIB_FUNCTION("hksbskNToEA", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2GetHttpResponseHeaderValue);
|
||||
LIB_FUNCTION("HwP3aM+c85c", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2GetHttpResponseHeaderValueLength);
|
||||
LIB_FUNCTION("Xweb+naPZ8Y", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2GetMemoryPoolStats);
|
||||
LIB_FUNCTION("+o9816YQhqQ", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2Initialize);
|
||||
LIB_FUNCTION("dowMWFgowXY", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2InitializeForPresence);
|
||||
LIB_FUNCTION("qmINYLuqzaA", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2IntCreateRequest);
|
||||
LIB_FUNCTION("zXaFo7euxsQ", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2IntInitialize);
|
||||
LIB_FUNCTION("9KSGFMRnp3k", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2IntInitialize2);
|
||||
LIB_FUNCTION("2hlBNB96saE", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2IntPushEventCreateCtxIndFilter);
|
||||
LIB_FUNCTION("1OLgvahaSco", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventAbortHandle);
|
||||
LIB_FUNCTION("MsaFhR+lPE4", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventCreateFilter);
|
||||
LIB_FUNCTION("WV1GwM32NgY", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventCreateHandle);
|
||||
LIB_FUNCTION("NNVf18SlbT8", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventCreatePushContext);
|
||||
LIB_FUNCTION("KJdPcOGmK58", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventDeleteFilter);
|
||||
LIB_FUNCTION("fIATVMo4Y1w", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventDeleteHandle);
|
||||
LIB_FUNCTION("QafxeZM3WK4", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventDeletePushContext);
|
||||
LIB_FUNCTION("fY3QqeNkF8k", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventRegisterCallback);
|
||||
LIB_FUNCTION("lxtHJMwBsaU", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventRegisterPushContextCallback);
|
||||
LIB_FUNCTION("KWkc6Q3tjXc", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventSetHandleTimeout);
|
||||
LIB_FUNCTION("AAj9X+4aGYA", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventStartPushContextCallback);
|
||||
LIB_FUNCTION("hOnIlcGrO6g", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventUnregisterCallback);
|
||||
LIB_FUNCTION("PmyrbbJSFz0", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventUnregisterPushContextCallback);
|
||||
LIB_FUNCTION("OOY9+ObfKec", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2ReadData);
|
||||
LIB_FUNCTION("NKCwS8+5Fx8", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2SendMultipartRequest);
|
||||
LIB_FUNCTION("lQOCF84lvzw", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2SendRequest);
|
||||
LIB_FUNCTION("bltDCAskmfE", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2SetMultipartContentType);
|
||||
LIB_FUNCTION("TjAutbrkr60", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2SetRequestTimeout);
|
||||
LIB_FUNCTION("bEvXpcEk200", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2Terminate);
|
||||
LIB_FUNCTION("qaMcX2+6ZiA", "libSceNpWebApi2", 1, "libSceNpWebApi2", Func_A9A31C5F6FBA6620);
|
||||
LIB_FUNCTION("A9IoYzANK3M", "libSceNpWebApi2AsyncRestricted", 1, "libSceNpWebApi2",
|
||||
Func_03D22863300D2B73);
|
||||
LIB_FUNCTION("lylvdXiq1UE", "libSceNpWebApi2AsyncRestricted", 1, "libSceNpWebApi2",
|
||||
Func_97296F7578AAD541);
|
||||
LIB_FUNCTION("4N85o28Ifbk", "libSceNpWebApi2AsyncRestricted", 1, "libSceNpWebApi2",
|
||||
Func_E0DF39A36F087DB9);
|
||||
};
|
||||
|
||||
} // namespace Libraries::Np::NpWebApi2
|
||||
@ -1,40 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
}
|
||||
|
||||
namespace Libraries::Np::NpWebApi2 {
|
||||
|
||||
struct OrbisNpWebApi2IntInitializeArgs {
|
||||
s32 lib_http_ctx_id;
|
||||
s32 reserved;
|
||||
u64 pool_size;
|
||||
char* name;
|
||||
u64 struct_size;
|
||||
};
|
||||
|
||||
struct OrbisNpWebApi2IntInitialize2Args {
|
||||
s32 lib_http_ctx_id;
|
||||
s32 reserved;
|
||||
u64 pool_size;
|
||||
char* name;
|
||||
u32 push_config_group;
|
||||
s32 reserved2;
|
||||
u64 struct_size;
|
||||
};
|
||||
|
||||
struct OrbisNpWebApi2MemoryPoolStats {
|
||||
u64 pool_size;
|
||||
u64 max_inuse_size;
|
||||
u64 current_inuse_size;
|
||||
s32 reserved;
|
||||
};
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Np::NpWebApi2
|
||||
522
src/core/libraries/np/np_web_api2/np_web_api2.cpp
Normal file
522
src/core/libraries/np/np_web_api2/np_web_api2.cpp
Normal file
@ -0,0 +1,522 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/emulator_settings.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "core/libraries/np/np_error.h"
|
||||
#include "core/libraries/np/np_manager.h"
|
||||
#include "core/libraries/np/np_types.h"
|
||||
#include "core/libraries/np/np_web_api2/np_web_api2.h"
|
||||
#include "core/libraries/np/np_web_api2/np_web_api2_internal.h"
|
||||
#include "core/libraries/system/userservice.h"
|
||||
|
||||
namespace Libraries::Np::NpWebApi2 {
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2AbortRequest(s64 request_id) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, request_id = {:#x}", request_id);
|
||||
return abortRequest(request_id);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2AddHttpRequestHeader(s64 request_id, const char* field_name,
|
||||
const char* field_value) {
|
||||
if (!field_name || !field_value) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
LOG_INFO(Lib_NpWebApi2, "called, request_id = {:#x}, field_name = {}, field_value = {}",
|
||||
request_id, field_name, field_value);
|
||||
return addHttpRequestHeader(request_id, field_name, field_value);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2AddMultipartPart() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2AddWebTraceTag(s64 request_id, const char* value) {
|
||||
if (!value) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
LOG_INFO(Lib_NpWebApi2, "called, request_id = {:#x}, value = {}", request_id, value);
|
||||
return addHttpRequestHeader(request_id, "X-Psn-WebTrace-Tag", value);
|
||||
}
|
||||
|
||||
void PS4_SYSV_ABI sceNpWebApi2CheckTimeout() {
|
||||
LOG_TRACE(Lib_NpWebApi2, "called");
|
||||
return checkTimeout();
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2CreateMultipartRequest(s32 user_ctx_id, const char* api_group,
|
||||
const char* path, const char* method,
|
||||
s64* request_id) {
|
||||
if (!api_group || !path || !method) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
LOG_INFO(Lib_NpWebApi2, "called, user_ctx_id = {:#x}, api_group = {}, path = {}, method = {}",
|
||||
user_ctx_id, api_group, path, method);
|
||||
s64 temp_request_id = 0;
|
||||
s32 result =
|
||||
createRequest(user_ctx_id, api_group, path, method, nullptr, true, &temp_request_id);
|
||||
if (result == 0) {
|
||||
LOG_INFO(Lib_NpWebApi2, "created request_id = {:#x}", temp_request_id);
|
||||
if (request_id) {
|
||||
*request_id = temp_request_id;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2CreateRequest(s32 user_ctx_id, const char* api_group, const char* path,
|
||||
const char* method,
|
||||
const OrbisNpWebApi2ContentParameter* content_parameter,
|
||||
s64* request_id) {
|
||||
if (!api_group || !path || !method) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (content_parameter && content_parameter->content_length != 0 &&
|
||||
!content_parameter->content_type) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid content parameter");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_CONTENT_PARAMETER;
|
||||
}
|
||||
|
||||
LOG_INFO(Lib_NpWebApi2, "called, user_ctx_id = {:#x}, api_group = {}, path = {}, method = {}",
|
||||
user_ctx_id, api_group, path, method);
|
||||
s64 temp_request_id = 0;
|
||||
s32 result = createRequest(user_ctx_id, api_group, path, method, content_parameter, false,
|
||||
&temp_request_id);
|
||||
if (result == 0) {
|
||||
LOG_INFO(Lib_NpWebApi2, "created request_id = {:#x}", temp_request_id);
|
||||
if (request_id) {
|
||||
*request_id = temp_request_id;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2CreateUserContext(s32 lib_ctx_id,
|
||||
UserService::OrbisUserServiceUserId user_id) {
|
||||
if (lib_ctx_id >= 0x8000) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid library context id {:#x}", lib_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_LIB_CONTEXT_ID;
|
||||
}
|
||||
if (user_id == UserService::ORBIS_USER_SERVICE_USER_ID_INVALID) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid user id");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
LOG_DEBUG(Lib_NpWebApi2, "called, lib_ctx_id = {:#x}, user_id = {}", lib_ctx_id, user_id);
|
||||
s32 user_ctx_id = createUserContext(lib_ctx_id, user_id);
|
||||
if (user_ctx_id > 0) {
|
||||
LOG_INFO(Lib_NpWebApi2, "created user_ctx_id = {:#x}", user_ctx_id);
|
||||
}
|
||||
return user_ctx_id;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2DeleteRequest(s64 request_id) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, request_id = {:#x}", request_id);
|
||||
return deleteRequest(request_id);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2DeleteUserContext(s32 user_ctx_id) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, user_ctx_id = {:#x}", user_ctx_id);
|
||||
return deleteUserContext(user_ctx_id);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2GetHttpResponseHeaderValue(s64 request_id, const char* field_name,
|
||||
u64* field_value_length) {
|
||||
if (!field_name || !field_value_length) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
s32 result = getHttpResponseHeaderData(request_id, field_name, nullptr, 0, field_value_length);
|
||||
if (result >= 0) {
|
||||
LOG_INFO(Lib_NpWebApi2,
|
||||
"on request_id = {:#x}, field_name = {} returned field_value_length = {:#x}",
|
||||
request_id, field_name, *field_value_length);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2GetHttpResponseHeaderValueLength(s64 request_id,
|
||||
const char* field_name, char* value,
|
||||
u64 value_size) {
|
||||
if (!field_name || !value || value_size == 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
LOG_INFO(Lib_NpWebApi2, "called, request_id = {:#x}, field_name = {}", request_id, field_name);
|
||||
return getHttpResponseHeaderData(request_id, field_name, value, value_size, nullptr);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2GetMemoryPoolStats(s32 lib_ctx_id,
|
||||
OrbisNpWebApi2MemoryPoolStats* stats) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, lib_ctx_id = {:#x}", lib_ctx_id);
|
||||
return getMemoryPoolStats(lib_ctx_id, stats);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2Initialize(s32 lib_http_ctx_id, u64 pool_size) {
|
||||
LOG_DEBUG(Lib_NpWebApi2, "called, lib_http_ctx_id = {:#x}, pool_size = {:#x}", lib_http_ctx_id,
|
||||
pool_size);
|
||||
|
||||
// Uses a sceLncUtilGetAppStatus check to enable debug mode. For now, default to normal.
|
||||
s32 ctx_id = createLibraryContext(lib_http_ctx_id, 1, pool_size, nullptr);
|
||||
if (ctx_id > 0) {
|
||||
LOG_INFO(Lib_NpWebApi2, "created lib_ctx_id = {:#x}", ctx_id);
|
||||
}
|
||||
return ctx_id;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2InitializeForPresence(s32 lib_http_ctx_id, u64 pool_size) {
|
||||
LOG_DEBUG(Lib_NpWebApi2, "called, lib_http_ctx_id = {:#x}, pool_size = {:#x}", lib_http_ctx_id,
|
||||
pool_size);
|
||||
|
||||
s32 ctx_id = createLibraryContext(lib_http_ctx_id, 3, pool_size, nullptr);
|
||||
if (ctx_id > 0) {
|
||||
LOG_INFO(Lib_NpWebApi2, "created lib_ctx_id = {:#x}", ctx_id);
|
||||
}
|
||||
return ctx_id;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2IntCreateRequest() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2IntInitialize(const OrbisNpWebApi2IntInitializeArgs* args) {
|
||||
if (args == nullptr || args->struct_size != sizeof(OrbisNpWebApi2IntInitializeArgs)) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid arguments");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
LOG_DEBUG(Lib_NpWebApi2, "called, lib_http_ctx_id = {:#x}, pool_size = {:#x}, name = {}",
|
||||
args->lib_http_ctx_id, args->pool_size, args->name ? args->name : "(null)");
|
||||
|
||||
s32 ctx_id = createLibraryContext(args->lib_http_ctx_id, 2, args->pool_size, args->name);
|
||||
if (ctx_id > 0) {
|
||||
LOG_INFO(Lib_NpWebApi2, "created lib_ctx_id = {:#x}", ctx_id);
|
||||
}
|
||||
return ctx_id;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2IntInitialize2(const OrbisNpWebApi2IntInitialize2Args* args) {
|
||||
|
||||
if (args == nullptr || args->struct_size != sizeof(OrbisNpWebApi2IntInitialize2Args)) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid arguments");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
LOG_DEBUG(
|
||||
Lib_NpWebApi2,
|
||||
"called, lib_http_ctx_id = {:#x}, pool_size = {:#x}, name = {}, push_config_group = {:#x}",
|
||||
args->lib_http_ctx_id, args->pool_size, args->name ? args->name : "(null)",
|
||||
args->push_config_group);
|
||||
|
||||
s32 ctx_id = createLibraryContext(args->lib_http_ctx_id, 2, args->pool_size, args->name);
|
||||
if (ctx_id > 0) {
|
||||
LOG_INFO(Lib_NpWebApi2, "created lib_ctx_id = {:#x}", ctx_id);
|
||||
}
|
||||
return ctx_id;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2IntPushEventCreateCtxIndFilter() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventAbortHandle(s32 lib_ctx_id, s32 handle_id) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, lib_ctx_id = {:#x}, handle_id = {:#x}", lib_ctx_id, handle_id);
|
||||
return abortPushEventHandle(lib_ctx_id, handle_id);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventCreateFilter(
|
||||
s32 lib_ctx_id, s32 handle_id, const char* np_service_name,
|
||||
OrbisNpServiceLabel np_service_label,
|
||||
const OrbisNpWebApi2PushEventFilterParameter* filter_param, u64 filter_param_num) {
|
||||
if ((np_service_name && np_service_label == ORBIS_NP_INVALID_SERVICE_LABEL) || !filter_param ||
|
||||
filter_param_num == 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
LOG_DEBUG(Lib_NpWebApi2,
|
||||
"called, lib_ctx_id = {:#x}, handle_id = {:#x}, np_service_name = {}, "
|
||||
"np_service_label = {:#x}, filter_param_num = {:#x}",
|
||||
lib_ctx_id, handle_id, np_service_name ? np_service_name : "(null)",
|
||||
static_cast<u32>(np_service_label), filter_param_num);
|
||||
for (u64 i = 0; i < filter_param_num; i++) {
|
||||
LOG_DEBUG(Lib_NpWebApi2, "filter_param[{}].data_type.val = {}", i,
|
||||
filter_param[i].data_type.val);
|
||||
LOG_DEBUG(Lib_NpWebApi2, "filter_param[{}].extd_data_key_num = {}", i,
|
||||
filter_param[i].extd_data_key_num);
|
||||
for (u64 j = 0; j < filter_param[i].extd_data_key_num && filter_param[i].extd_data_key;
|
||||
j++) {
|
||||
LOG_DEBUG(Lib_NpWebApi2, "filter_param[{}].extd_data_key[{}].val = {}", i, j,
|
||||
filter_param[i].extd_data_key[j].val);
|
||||
}
|
||||
}
|
||||
s32 filter_id = createPushEventFilter(lib_ctx_id, handle_id, np_service_name, np_service_label,
|
||||
filter_param, filter_param_num, false);
|
||||
if (filter_id > 0) {
|
||||
LOG_INFO(Lib_NpWebApi2, "created filter_id = {:#x}", filter_id);
|
||||
}
|
||||
return filter_id;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventCreateHandle(s32 lib_ctx_id) {
|
||||
LOG_DEBUG(Lib_NpWebApi2, "called, lib_ctx_id = {:#x}", lib_ctx_id);
|
||||
s32 handle_id = createPushEventHandle(lib_ctx_id);
|
||||
if (handle_id > 0) {
|
||||
LOG_INFO(Lib_NpWebApi2, "created handle_id = {:#x}", handle_id);
|
||||
}
|
||||
return handle_id;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventCreatePushContext(
|
||||
s32 user_ctx_id, OrbisNpWebApi2PushEventPushContextId* push_ctx_id) {
|
||||
if (!push_ctx_id) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
LOG_DEBUG(Lib_NpWebApi2, "called, user_ctx_id = {:#x}", user_ctx_id);
|
||||
s32 result = createPushContext(user_ctx_id, push_ctx_id);
|
||||
if (result == 0) {
|
||||
s64 raw_id{};
|
||||
std::memcpy(&raw_id, push_ctx_id, sizeof(s64));
|
||||
LOG_INFO(Lib_NpWebApi2, "created push_ctx_id = {:#x}", raw_id);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventDeleteFilter(s32 lib_ctx_id, s32 filter_id) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, lib_ctx_id = {:#x}, filter_id = {:#x}", lib_ctx_id, filter_id);
|
||||
return deletePushEventFilter(lib_ctx_id, filter_id);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventDeleteHandle(s32 lib_ctx_id, s32 handle_id) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, lib_ctx_id = {:#x}, handle_id = {:#x}", lib_ctx_id, handle_id);
|
||||
return deletePushEventHandle(lib_ctx_id, handle_id);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventDeletePushContext(
|
||||
s32 user_ctx_id, OrbisNpWebApi2PushEventPushContextId* push_ctx_id) {
|
||||
if (!push_ctx_id) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
s64 raw_id{};
|
||||
std::memcpy(&raw_id, push_ctx_id, sizeof(s64));
|
||||
LOG_INFO(Lib_NpWebApi2, "called, user_ctx_id = {:#x}, push_ctx_id = {:#x}", user_ctx_id,
|
||||
raw_id);
|
||||
return deletePushContext(user_ctx_id, push_ctx_id);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventRegisterCallback(s32 user_ctx_id, s32 filter_id,
|
||||
OrbisNpWebApi2PushEventCallback cb_func,
|
||||
void* user_arg) {
|
||||
LOG_DEBUG(Lib_NpWebApi2, "called, user_ctx_id = {:#x}, filter_id = {:#x}", user_ctx_id,
|
||||
filter_id);
|
||||
if (!cb_func) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
s32 callback_id = registerPushEventCallback(user_ctx_id, filter_id, cb_func, user_arg);
|
||||
if (callback_id > 0) {
|
||||
LOG_INFO(Lib_NpWebApi2, "created callback_id = {:#x}", callback_id);
|
||||
}
|
||||
return callback_id;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventRegisterPushContextCallback(
|
||||
s32 user_ctx_id, s32 filter_id, OrbisNpWebApi2PushEventPushContextCallback cb_func,
|
||||
void* user_arg) {
|
||||
LOG_DEBUG(Lib_NpWebApi2, "called, user_ctx_id = {:#x}, filter_id = {:#x}", user_ctx_id,
|
||||
filter_id);
|
||||
if (!cb_func) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
s32 callback_id = registerPushContextCallback(user_ctx_id, filter_id, cb_func, user_arg);
|
||||
if (callback_id > 0) {
|
||||
LOG_INFO(Lib_NpWebApi2, "created callback_id = {:#x}", callback_id);
|
||||
}
|
||||
return callback_id;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventSetHandleTimeout(s32 lib_ctx_id, s32 handle_id, u32 timeout) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, lib_ctx_id = {:#x}, handle_id = {:#x}, timeout = {}",
|
||||
lib_ctx_id, handle_id, timeout);
|
||||
return setHandleTimeout(lib_ctx_id, handle_id, timeout);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventStartPushContextCallback(
|
||||
s32 user_ctx_id, const OrbisNpWebApi2PushEventPushContextId* push_ctx_id) {
|
||||
if (!push_ctx_id) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
s64 raw_id{};
|
||||
std::memcpy(&raw_id, push_ctx_id, sizeof(s64));
|
||||
LOG_INFO(Lib_NpWebApi2, "called, user_ctx_id = {:#x}, push_ctx_id = {:#x}", user_ctx_id,
|
||||
raw_id);
|
||||
return startPushContextCallback(user_ctx_id, push_ctx_id);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventUnregisterCallback(s32 user_ctx_id, s32 callback_id) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, user_ctx_id = {:#x}, callback_id = {:#x}", user_ctx_id,
|
||||
callback_id);
|
||||
return unregisterPushEventCallback(user_ctx_id, callback_id);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2PushEventUnregisterPushContextCallback(s32 user_ctx_id,
|
||||
s32 callback_id) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, user_ctx_id = {:#x}, callback_id = {:#x}", user_ctx_id,
|
||||
callback_id);
|
||||
return unregisterPushContextCallback(user_ctx_id, callback_id);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2ReadData(s64 request_id, void* data, u64 size) {
|
||||
if (!data || size == 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
LOG_INFO(Lib_NpWebApi2, "called, request_id = {:#x}, size = {:#x}", request_id, size);
|
||||
return readData(request_id, data, size);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI
|
||||
sceNpWebApi2SendMultipartRequest(s64 request_id, s32 part_index, void* data, u64 data_size,
|
||||
OrbisNpWebApi2ResponseInformationOption* resp_info_option) {
|
||||
if (part_index <= 0 || !data || data_size == 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Invalid parameters");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
LOG_WARNING(Lib_NpWebApi2, "called, request_id = {:#x}, part_index = {}, data_size = {:#x}",
|
||||
request_id, part_index, data_size);
|
||||
return sendRequest(request_id, part_index, data, data_size, resp_info_option);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI
|
||||
sceNpWebApi2SendRequest(s64 request_id, void* data, u64 data_size,
|
||||
OrbisNpWebApi2ResponseInformationOption* resp_info_option) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, request_id = {:#x}, data_size = {:#x}", request_id, data_size);
|
||||
return sendRequest(request_id, 0, data, data_size, resp_info_option);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2SetMultipartContentType() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2SetRequestTimeout(s64 request_id, u32 timeout) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, request_id = {:#x}, timeout = {}", request_id, timeout);
|
||||
return setRequestTimeout(request_id, timeout);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2Terminate(s32 lib_ctx_id) {
|
||||
LOG_INFO(Lib_NpWebApi2, "called, lib_ctx_id = {:#x}", lib_ctx_id);
|
||||
return terminateLibraryContext(lib_ctx_id);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI Func_A9A31C5F6FBA6620() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI Func_03D22863300D2B73() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI Func_97296F7578AAD541() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI Func_E0DF39A36F087DB9() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
Libraries::Np::NpManager::RegisterNpCallback("npwebapi2_push", processPushEvents);
|
||||
|
||||
LIB_FUNCTION("zpiPsH7dbFQ", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2AbortRequest);
|
||||
LIB_FUNCTION("egOOvrnF6mI", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2AddHttpRequestHeader);
|
||||
LIB_FUNCTION("Io7kh1LHDoM", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2AddMultipartPart);
|
||||
LIB_FUNCTION("MgsTa76wlEk", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2AddWebTraceTag);
|
||||
LIB_FUNCTION("3Tt9zL3tkoc", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2CheckTimeout);
|
||||
LIB_FUNCTION("+nz1Vq-NrDA", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2CreateMultipartRequest);
|
||||
LIB_FUNCTION("3EI-OSJ65Xc", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2CreateRequest);
|
||||
LIB_FUNCTION("sk54bi6FtYM", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2CreateUserContext);
|
||||
LIB_FUNCTION("vvzWO-DvG1s", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2DeleteRequest);
|
||||
LIB_FUNCTION("9X9+cneTGUU", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2DeleteUserContext);
|
||||
LIB_FUNCTION("hksbskNToEA", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2GetHttpResponseHeaderValue);
|
||||
LIB_FUNCTION("HwP3aM+c85c", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2GetHttpResponseHeaderValueLength);
|
||||
LIB_FUNCTION("Xweb+naPZ8Y", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2GetMemoryPoolStats);
|
||||
LIB_FUNCTION("+o9816YQhqQ", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2Initialize);
|
||||
LIB_FUNCTION("dowMWFgowXY", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2InitializeForPresence);
|
||||
LIB_FUNCTION("qmINYLuqzaA", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2IntCreateRequest);
|
||||
LIB_FUNCTION("zXaFo7euxsQ", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2IntInitialize);
|
||||
LIB_FUNCTION("9KSGFMRnp3k", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2IntInitialize2);
|
||||
LIB_FUNCTION("2hlBNB96saE", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2IntPushEventCreateCtxIndFilter);
|
||||
LIB_FUNCTION("1OLgvahaSco", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventAbortHandle);
|
||||
LIB_FUNCTION("MsaFhR+lPE4", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventCreateFilter);
|
||||
LIB_FUNCTION("WV1GwM32NgY", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventCreateHandle);
|
||||
LIB_FUNCTION("NNVf18SlbT8", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventCreatePushContext);
|
||||
LIB_FUNCTION("KJdPcOGmK58", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventDeleteFilter);
|
||||
LIB_FUNCTION("fIATVMo4Y1w", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventDeleteHandle);
|
||||
LIB_FUNCTION("QafxeZM3WK4", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventDeletePushContext);
|
||||
LIB_FUNCTION("fY3QqeNkF8k", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventRegisterCallback);
|
||||
LIB_FUNCTION("lxtHJMwBsaU", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventRegisterPushContextCallback);
|
||||
LIB_FUNCTION("KWkc6Q3tjXc", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventSetHandleTimeout);
|
||||
LIB_FUNCTION("AAj9X+4aGYA", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventStartPushContextCallback);
|
||||
LIB_FUNCTION("hOnIlcGrO6g", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventUnregisterCallback);
|
||||
LIB_FUNCTION("PmyrbbJSFz0", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2PushEventUnregisterPushContextCallback);
|
||||
LIB_FUNCTION("OOY9+ObfKec", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2ReadData);
|
||||
LIB_FUNCTION("NKCwS8+5Fx8", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2SendMultipartRequest);
|
||||
LIB_FUNCTION("lQOCF84lvzw", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2SendRequest);
|
||||
LIB_FUNCTION("bltDCAskmfE", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2SetMultipartContentType);
|
||||
LIB_FUNCTION("TjAutbrkr60", "libSceNpWebApi2", 1, "libSceNpWebApi2",
|
||||
sceNpWebApi2SetRequestTimeout);
|
||||
LIB_FUNCTION("bEvXpcEk200", "libSceNpWebApi2", 1, "libSceNpWebApi2", sceNpWebApi2Terminate);
|
||||
LIB_FUNCTION("qaMcX2+6ZiA", "libSceNpWebApi2", 1, "libSceNpWebApi2", Func_A9A31C5F6FBA6620);
|
||||
LIB_FUNCTION("A9IoYzANK3M", "libSceNpWebApi2AsyncRestricted", 1, "libSceNpWebApi2",
|
||||
Func_03D22863300D2B73);
|
||||
LIB_FUNCTION("lylvdXiq1UE", "libSceNpWebApi2AsyncRestricted", 1, "libSceNpWebApi2",
|
||||
Func_97296F7578AAD541);
|
||||
LIB_FUNCTION("4N85o28Ifbk", "libSceNpWebApi2AsyncRestricted", 1, "libSceNpWebApi2",
|
||||
Func_E0DF39A36F087DB9);
|
||||
};
|
||||
|
||||
} // namespace Libraries::Np::NpWebApi2
|
||||
102
src/core/libraries/np/np_web_api2/np_web_api2.h
Normal file
102
src/core/libraries/np/np_web_api2/np_web_api2.h
Normal file
@ -0,0 +1,102 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
#include "core/libraries/np/np_types.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
}
|
||||
|
||||
namespace Libraries::Np::NpWebApi2 {
|
||||
|
||||
struct OrbisNpWebApi2IntInitializeArgs {
|
||||
s32 lib_http_ctx_id;
|
||||
s32 reserved;
|
||||
u64 pool_size;
|
||||
const char* name;
|
||||
u64 struct_size;
|
||||
};
|
||||
|
||||
struct OrbisNpWebApi2IntInitialize2Args {
|
||||
s32 lib_http_ctx_id;
|
||||
s32 reserved;
|
||||
u64 pool_size;
|
||||
const char* name;
|
||||
u32 push_config_group;
|
||||
s32 reserved2;
|
||||
u64 struct_size;
|
||||
};
|
||||
|
||||
struct OrbisNpWebApi2ContentParameter {
|
||||
u64 content_length;
|
||||
const char* content_type;
|
||||
u8 reserved[16];
|
||||
};
|
||||
|
||||
struct OrbisNpWebApi2MemoryPoolStats {
|
||||
u64 pool_size;
|
||||
u64 max_inuse_size;
|
||||
u64 current_inuse_size;
|
||||
s32 reserved;
|
||||
};
|
||||
|
||||
struct OrbisNpWebApi2ResponseInformationOption {
|
||||
s32 http_status;
|
||||
s32 reserved;
|
||||
char* error_object;
|
||||
u64 error_object_size;
|
||||
u64 response_data_size;
|
||||
};
|
||||
|
||||
struct OrbisNpWebApi2PushEventDataType {
|
||||
char val[65];
|
||||
};
|
||||
|
||||
struct OrbisNpWebApi2PushEventExtdDataKey {
|
||||
char val[33];
|
||||
};
|
||||
|
||||
struct OrbisNpWebApi2PushEventFilterParameter {
|
||||
OrbisNpWebApi2PushEventDataType data_type;
|
||||
OrbisNpWebApi2PushEventExtdDataKey* extd_data_key;
|
||||
u64 extd_data_key_num;
|
||||
};
|
||||
|
||||
struct OrbisNpWebApi2PushEventExtdData {
|
||||
OrbisNpWebApi2PushEventExtdDataKey extd_data_key;
|
||||
char* data;
|
||||
u64 data_len;
|
||||
};
|
||||
|
||||
using OrbisNpWebApi2PushEventCallback = void PS4_SYSV_ABI (*)(
|
||||
s32 user_ctx_id, s32 callback_id, const char* np_service_name,
|
||||
OrbisNpServiceLabel np_service_label, const OrbisNpPeerAddressA* to,
|
||||
const OrbisNpOnlineId* to_online_id, const OrbisNpPeerAddressA* from,
|
||||
const OrbisNpOnlineId* from_online_id, const OrbisNpWebApi2PushEventDataType* data_type,
|
||||
const char* data, u64 data_len, const OrbisNpWebApi2PushEventExtdData* extd_data,
|
||||
u64 extd_data_num, void* user_arg);
|
||||
|
||||
enum OrbisNpWebApi2PushEventPushContextCallbackType {
|
||||
Unknown = -1,
|
||||
Received = 0,
|
||||
Dropped = 1,
|
||||
};
|
||||
|
||||
struct OrbisNpWebApi2PushEventPushContextId {
|
||||
char uuid[37];
|
||||
};
|
||||
|
||||
using OrbisNpWebApi2PushEventPushContextCallback = void PS4_SYSV_ABI (*)(
|
||||
s32 user_ctx_id, s32 callback_id, const OrbisNpWebApi2PushEventPushContextId* push_ctx_id,
|
||||
OrbisNpWebApi2PushEventPushContextCallbackType cb_type, const char* np_service_name,
|
||||
OrbisNpServiceLabel np_service_label, const OrbisNpPeerAddressA* to,
|
||||
const OrbisNpOnlineId* to_online_id, const OrbisNpPeerAddressA* from,
|
||||
const OrbisNpOnlineId* from_online_id, const OrbisNpWebApi2PushEventDataType* data_type,
|
||||
const char* data, u64 data_len, const OrbisNpWebApi2PushEventExtdData* extd_data,
|
||||
u64 extd_data_num, void* user_arg);
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Np::NpWebApi2
|
||||
630
src/core/libraries/np/np_web_api2/np_web_api2_context.cpp
Normal file
630
src/core/libraries/np/np_web_api2/np_web_api2_context.cpp
Normal file
@ -0,0 +1,630 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/network/http.h"
|
||||
#include "core/libraries/network/http2.h"
|
||||
#include "core/libraries/np/np_common.h"
|
||||
#include "core/libraries/np/np_error.h"
|
||||
#include "core/libraries/np/np_handler.h"
|
||||
#include "core/libraries/np/np_web_api2/np_web_api2_context.h"
|
||||
|
||||
namespace Libraries::Np::NpWebApi2 {
|
||||
|
||||
u32 g_current_push_event_handle_id{};
|
||||
u32 g_current_push_event_filter_id{};
|
||||
u32 g_current_push_event_callback_id{};
|
||||
u32 g_current_push_context_callback_id{};
|
||||
u32 g_current_user_context_id{};
|
||||
u64 g_current_request_id{};
|
||||
|
||||
void LibraryContext::CheckTimeout() {
|
||||
u64 time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||
std::scoped_lock lk{this->lock};
|
||||
for (auto& [user_ctx_id, user_ctx] : this->user_contexts) {
|
||||
user_ctx->CheckTimeout();
|
||||
}
|
||||
for (auto& [handle_id, handle] : this->push_event_handles) {
|
||||
handle->CheckTimeout(time);
|
||||
}
|
||||
}
|
||||
|
||||
s32 LibraryContext::CreateUserContext(Libraries::UserService::OrbisUserServiceUserId user_id) {
|
||||
std::scoped_lock lk{this->lock};
|
||||
if (this->user_contexts.size() >= 0x10000) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Too many user contexts");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_MAX;
|
||||
}
|
||||
|
||||
s32 actual_user_ctx_id = 0;
|
||||
do {
|
||||
g_current_user_context_id++;
|
||||
if (g_current_user_context_id >= 0x10000) {
|
||||
g_current_user_context_id = 1;
|
||||
}
|
||||
actual_user_ctx_id = (this->id << 0x10) | g_current_user_context_id;
|
||||
} while (this->user_contexts.contains(actual_user_ctx_id));
|
||||
|
||||
this->user_contexts[actual_user_ctx_id] = new UserContext(this, actual_user_ctx_id, user_id);
|
||||
return actual_user_ctx_id;
|
||||
}
|
||||
|
||||
s32 LibraryContext::CreatePushEventHandle() {
|
||||
std::scoped_lock lk{this->lock};
|
||||
if (g_current_push_event_handle_id + 1 < 0xf0000000) {
|
||||
++g_current_push_event_handle_id;
|
||||
} else {
|
||||
g_current_push_event_handle_id = 1;
|
||||
}
|
||||
|
||||
s32 new_handle_id = g_current_push_event_handle_id;
|
||||
this->push_event_handles[new_handle_id] = new PushEventHandle(new_handle_id);
|
||||
return new_handle_id;
|
||||
}
|
||||
|
||||
PushEventHandle* LibraryContext::GetPushEventHandle(s32 handle_id) {
|
||||
std::scoped_lock lk{lock};
|
||||
if (!push_event_handles.contains(handle_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
PushEventHandle* handle = push_event_handles[handle_id];
|
||||
handle->AddUser();
|
||||
return handle;
|
||||
}
|
||||
|
||||
s32 LibraryContext::DeletePushEventHandle(PushEventHandle* handle) {
|
||||
this->Lock();
|
||||
s32 handle_id = handle->GetId();
|
||||
if (handle->IsDeleted()) {
|
||||
this->Unlock();
|
||||
LOG_ERROR(Lib_NpWebApi2, "handle with id {:#x} is already deleted", handle_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_HANDLE_NOT_FOUND;
|
||||
}
|
||||
|
||||
handle->MarkForDeletion();
|
||||
handle->Abort();
|
||||
|
||||
while (handle->IsBusy()) {
|
||||
handle->RemoveUser();
|
||||
this->Unlock();
|
||||
Libraries::Kernel::sceKernelUsleep(50000);
|
||||
this->Lock();
|
||||
handle->AddUser();
|
||||
}
|
||||
|
||||
if (push_event_handles.contains(handle_id)) {
|
||||
push_event_handles.erase(handle_id);
|
||||
}
|
||||
delete handle;
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 LibraryContext::CreatePushEventFilter(
|
||||
s32 handle_id, const char* np_service_name, OrbisNpServiceLabel np_service_label,
|
||||
const OrbisNpWebApi2PushEventFilterParameter* filter_param, u64 filter_param_num,
|
||||
bool internal) {
|
||||
std::scoped_lock lk{this->lock};
|
||||
if (!this->push_event_handles.contains(handle_id)) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No push event handle with id {:#x}", handle_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_HANDLE_NOT_FOUND;
|
||||
}
|
||||
PushEventHandle* handle = this->push_event_handles[handle_id];
|
||||
handle->AddUser();
|
||||
|
||||
if (g_current_push_event_filter_id + 1 < 0xf0000000) {
|
||||
++g_current_push_event_filter_id;
|
||||
} else {
|
||||
g_current_push_event_filter_id = 1;
|
||||
}
|
||||
|
||||
s32 new_filter_id = g_current_push_event_filter_id;
|
||||
this->push_event_filters[new_filter_id] =
|
||||
new PushEventFilter(new_filter_id, np_service_name, np_service_label, internal);
|
||||
PushEventFilter* filter = this->push_event_filters[new_filter_id];
|
||||
s32 result = filter->Initialize(handle, filter_param, filter_param_num);
|
||||
if (result < 0) {
|
||||
// Failed to initialize filter.
|
||||
delete filter;
|
||||
this->push_event_filters.erase(new_filter_id);
|
||||
handle->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
handle->RemoveUser();
|
||||
return new_filter_id;
|
||||
}
|
||||
|
||||
UserContext* LibraryContext::GetUserContext(s32 user_ctx_id) {
|
||||
std::scoped_lock lk{this->lock};
|
||||
if (!this->user_contexts.contains(user_ctx_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = this->user_contexts.at(user_ctx_id);
|
||||
if (user_ctx->IsDeleted()) {
|
||||
return nullptr;
|
||||
}
|
||||
user_ctx->AddUser();
|
||||
return user_ctx;
|
||||
}
|
||||
|
||||
UserContext* LibraryContext::GetUserContextByUserId(
|
||||
Libraries::UserService::OrbisUserServiceUserId user_id) {
|
||||
if (user_id == Libraries::UserService::ORBIS_USER_SERVICE_USER_ID_INVALID) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::scoped_lock lk{this->lock};
|
||||
for (auto& [user_ctx_id, user_ctx] : this->user_contexts) {
|
||||
if (user_ctx->GetUserId() == user_id) {
|
||||
user_ctx->AddUser();
|
||||
return user_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI internalPreSendCallback(s32 http_request_id, s32 ssl_id,
|
||||
Libraries::Http2::OrbisHttp2PreSendCallbackData* data,
|
||||
void* user_arg) {
|
||||
s64 user_ctx_id = reinterpret_cast<s64>(user_arg);
|
||||
LOG_ERROR(Lib_NpWebApi2,
|
||||
"Unimplemented, http_request_id = {:#x}, ssl_id = {:#x}, user_ctx_id = {:#x}",
|
||||
http_request_id, ssl_id, user_ctx_id);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 UserContext::Initialize() {
|
||||
const char* name = this->parent_ctx->GetName();
|
||||
|
||||
char sw_version[8];
|
||||
std::memset(sw_version, 0, sizeof(sw_version));
|
||||
Libraries::Np::NpCommon::sceNpGetSdkVersion(sw_version);
|
||||
|
||||
char user_agent_buf[0x40];
|
||||
std::memset(user_agent_buf, 0, sizeof(user_agent_buf));
|
||||
if (name) {
|
||||
std::snprintf(user_agent_buf, sizeof(user_agent_buf), "NpWebApi2/%s (%s)", sw_version,
|
||||
name);
|
||||
} else {
|
||||
std::snprintf(user_agent_buf, sizeof(user_agent_buf), "NpWebApi2/%s", sw_version);
|
||||
}
|
||||
this->user_agent = std::string{user_agent_buf};
|
||||
|
||||
s32 http_ctx_id = this->parent_ctx->GetHttpCtxId();
|
||||
http_template_id = Libraries::Http2::sceHttp2CreateTemplate(
|
||||
http_ctx_id, user_agent_buf,
|
||||
Libraries::Http2::OrbisHttp2HttpVersion::ORBIS_HTTP2_VERSION_2_0, 0);
|
||||
if (http_template_id < 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Failed to create HTTP template, error = {:#x}", http_template_id);
|
||||
return http_template_id;
|
||||
}
|
||||
|
||||
s32 result = Libraries::Http2::sceHttp2SetPreSendCallback(
|
||||
http_template_id, internalPreSendCallback, reinterpret_cast<void*>(this->id));
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Failed to set pre-send callback, error = {:#x}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void UserContext::CheckTimeout() {
|
||||
parent_ctx->Lock();
|
||||
for (auto& [request_id, request] : requests) {
|
||||
request->CheckTimeout();
|
||||
}
|
||||
parent_ctx->Unlock();
|
||||
}
|
||||
|
||||
s32 UserContext::CreatePushEventCallback(s32 filter_id, OrbisNpWebApi2PushEventCallback cb_func,
|
||||
void* user_arg) {
|
||||
this->Lock();
|
||||
if (g_current_push_event_callback_id + 1 < 0xf0000000) {
|
||||
++g_current_push_event_callback_id;
|
||||
} else {
|
||||
g_current_push_event_callback_id = 1;
|
||||
}
|
||||
|
||||
s32 new_callback_id = g_current_push_event_callback_id;
|
||||
this->push_event_callbacks[new_callback_id] =
|
||||
new PushEventCallback(new_callback_id, filter_id, cb_func, user_arg, false);
|
||||
this->Unlock();
|
||||
return new_callback_id;
|
||||
}
|
||||
|
||||
s32 UserContext::DeletePushEventCallback(s32 callback_id) {
|
||||
this->Lock();
|
||||
if (!this->push_event_callbacks.contains(callback_id)) {
|
||||
this->Unlock();
|
||||
LOG_ERROR(Lib_NpWebApi2, "No push event callback with id {:#x}", callback_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_PUSH_EVENT_CALLBACK_NOT_FOUND;
|
||||
}
|
||||
|
||||
PushEventCallback* callback = this->push_event_callbacks[callback_id];
|
||||
while (callback->is_busy) {
|
||||
this->Unlock();
|
||||
Libraries::Kernel::sceKernelUsleep(100000);
|
||||
this->Lock();
|
||||
}
|
||||
|
||||
delete callback;
|
||||
this->push_event_callbacks.erase(callback_id);
|
||||
this->Unlock();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void UserContext::CreatePushContext(OrbisNpWebApi2PushEventPushContextId* push_ctx_id) {
|
||||
this->Lock();
|
||||
while (this->push_contexts_busy) {
|
||||
this->Unlock();
|
||||
Libraries::Kernel::sceKernelUsleep(10000);
|
||||
this->Lock();
|
||||
}
|
||||
this->push_contexts_busy = true;
|
||||
PushEventPushContext* push_ctx = new PushEventPushContext(5000, this);
|
||||
push_ctx->Initialize();
|
||||
OrbisNpWebApi2PushEventPushContextId* new_id = push_ctx->GetId();
|
||||
std::memcpy(push_ctx_id, new_id, sizeof(*push_ctx_id));
|
||||
|
||||
s64 raw_id = push_ctx->GetFakeId();
|
||||
this->push_contexts[raw_id] = push_ctx;
|
||||
this->push_contexts_busy = false;
|
||||
this->Unlock();
|
||||
}
|
||||
|
||||
PushEventPushContext* UserContext::GetPushContext(
|
||||
const OrbisNpWebApi2PushEventPushContextId* push_ctx_id) {
|
||||
parent_ctx->Lock();
|
||||
s64 raw_id{};
|
||||
std::memcpy(&raw_id, push_ctx_id, sizeof(s64));
|
||||
if (!push_contexts.contains(raw_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
PushEventPushContext* push_ctx = push_contexts[raw_id];
|
||||
parent_ctx->Unlock();
|
||||
return push_ctx;
|
||||
}
|
||||
|
||||
void UserContext::DeletePushContext(PushEventPushContext* push_ctx) {
|
||||
this->Lock();
|
||||
while (this->push_contexts_busy) {
|
||||
this->Unlock();
|
||||
Libraries::Kernel::sceKernelUsleep(10000);
|
||||
this->Lock();
|
||||
}
|
||||
this->push_contexts_busy = true;
|
||||
|
||||
while (push_ctx->CallbackRunning()) {
|
||||
this->Unlock();
|
||||
Libraries::Kernel::sceKernelUsleep(100000);
|
||||
this->Lock();
|
||||
}
|
||||
|
||||
s64 raw_id = push_ctx->GetFakeId();
|
||||
this->push_contexts.erase(raw_id);
|
||||
delete push_ctx;
|
||||
this->push_contexts_busy = false;
|
||||
this->Unlock();
|
||||
}
|
||||
|
||||
s32 UserContext::CreatePushContextCallback(s32 filter_id,
|
||||
OrbisNpWebApi2PushEventPushContextCallback cb_func,
|
||||
void* user_arg) {
|
||||
this->Lock();
|
||||
if (g_current_push_context_callback_id + 1 < 0xf0000000) {
|
||||
++g_current_push_context_callback_id;
|
||||
} else {
|
||||
g_current_push_context_callback_id = 1;
|
||||
}
|
||||
|
||||
s32 new_callback_id = g_current_push_context_callback_id;
|
||||
this->push_context_callbacks[new_callback_id] =
|
||||
new PushEventPushContextCallback(new_callback_id, filter_id, cb_func, user_arg, false);
|
||||
this->Unlock();
|
||||
return new_callback_id;
|
||||
}
|
||||
|
||||
s32 UserContext::DeletePushContextCallback(s32 callback_id) {
|
||||
this->Lock();
|
||||
if (!this->push_context_callbacks.contains(callback_id)) {
|
||||
this->Unlock();
|
||||
LOG_ERROR(Lib_NpWebApi2, "No push event push context callback with id {:#x}", callback_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_PUSH_EVENT_CALLBACK_NOT_FOUND;
|
||||
}
|
||||
|
||||
PushEventPushContextCallback* callback = this->push_context_callbacks[callback_id];
|
||||
while (callback->is_busy) {
|
||||
this->Unlock();
|
||||
Libraries::Kernel::sceKernelUsleep(100000);
|
||||
this->Lock();
|
||||
}
|
||||
|
||||
delete callback;
|
||||
this->push_context_callbacks.erase(callback_id);
|
||||
this->Unlock();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 UserContext::CreateRequest(const char* api_group, const char* path, const char* method,
|
||||
const OrbisNpWebApi2ContentParameter* content_parameter,
|
||||
bool multipart, Request** request) {
|
||||
this->Lock();
|
||||
s64 actual_request_id = 0;
|
||||
do {
|
||||
g_current_request_id++;
|
||||
if (g_current_request_id >> 0x20 != 0) {
|
||||
g_current_request_id = 1;
|
||||
}
|
||||
actual_request_id = (static_cast<s64>(this->id) << 0x20) | g_current_request_id;
|
||||
} while (this->requests.contains(actual_request_id));
|
||||
|
||||
if (content_parameter) {
|
||||
this->requests[actual_request_id] =
|
||||
new Request(this->parent_ctx, actual_request_id, api_group, path, method, multipart,
|
||||
content_parameter);
|
||||
} else {
|
||||
this->requests[actual_request_id] =
|
||||
new Request(this->parent_ctx, actual_request_id, api_group, path, method, multipart);
|
||||
}
|
||||
*request = this->requests[actual_request_id];
|
||||
this->Unlock();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
Request* UserContext::GetRequest(s64 request_id) {
|
||||
this->Lock();
|
||||
if (!this->requests.contains(request_id)) {
|
||||
this->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Request* request = this->requests[request_id];
|
||||
request->AddUser();
|
||||
this->Unlock();
|
||||
return request;
|
||||
}
|
||||
|
||||
bool UserContext::HasBusyRequests() {
|
||||
this->Lock();
|
||||
for (auto& [request_id, request] : this->requests) {
|
||||
request->AddUser();
|
||||
bool busy = request->IsBusy();
|
||||
request->RemoveUser();
|
||||
if (busy) {
|
||||
this->Unlock();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
this->Unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
void UserContext::AbortAllRequests() {
|
||||
this->Lock();
|
||||
for (auto& [request_id, request] : this->requests) {
|
||||
request->Abort();
|
||||
}
|
||||
this->Unlock();
|
||||
}
|
||||
|
||||
void UserContext::Delete() {
|
||||
if (this->http_template_id != 0) {
|
||||
Libraries::Http2::sceHttp2DeleteTemplate(this->http_template_id);
|
||||
}
|
||||
this->parent_ctx->RemoveUserContext(this->id);
|
||||
this->RemoveUser();
|
||||
|
||||
for (auto& [request_id, request] : this->requests) {
|
||||
request->Delete(nullptr);
|
||||
}
|
||||
this->requests.clear();
|
||||
|
||||
for (auto& [push_ctx_id, push_ctx] : this->push_contexts) {
|
||||
delete push_ctx;
|
||||
}
|
||||
this->push_contexts.clear();
|
||||
|
||||
for (auto& [callback_id, callback] : this->push_event_callbacks) {
|
||||
delete callback;
|
||||
}
|
||||
this->push_event_callbacks.clear();
|
||||
|
||||
for (auto& [callback_id, callback] : this->push_context_callbacks) {
|
||||
delete callback;
|
||||
}
|
||||
this->push_context_callbacks.clear();
|
||||
delete this;
|
||||
}
|
||||
|
||||
static bool IsInternalHeader(const char* header_name) {
|
||||
std::string lower_name{header_name};
|
||||
std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(),
|
||||
[](char c) { return std::tolower(c); });
|
||||
// These headers are all skipped if the request's library context
|
||||
// was not created through the IntInitialize functions.
|
||||
return lower_name.compare("content-type") == 0 || lower_name.compare("user-agent") == 0 ||
|
||||
lower_name.compare("authorization") == 0 ||
|
||||
lower_name.compare("x-psn-np-title-id") == 0 ||
|
||||
lower_name.compare("x-psn-np-title-token") == 0 ||
|
||||
lower_name.compare("x-psn-request-id") == 0 ||
|
||||
lower_name.compare("x-psn-sdk-ver") == 0 ||
|
||||
lower_name.compare("x-psn-debug-settings") == 0 || lower_name.compare("npdebug") == 0 ||
|
||||
lower_name.compare("x-psn-trc-check-notification-enabled") == 0 ||
|
||||
lower_name.compare("x-psn-webtrace-enabled") == 0 ||
|
||||
lower_name.compare("x-psn-npwebapi2-context") == 0 ||
|
||||
lower_name.compare("x-psn-fake-rate-limit-enabled") == 0 ||
|
||||
lower_name.compare("x-psn-fake-rate-limit-targets") == 0;
|
||||
}
|
||||
|
||||
s32 Request::AddHttpRequestHeader(const char* field_name, const char* field_value) {
|
||||
if (!this->parent_ctx->IsInternal() && IsInternalHeader(field_name)) {
|
||||
LOG_WARNING(Lib_NpWebApi2, "This is not an internal context, skipping field name {}",
|
||||
field_name);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
this->Lock();
|
||||
this->http_headers.emplace_back(new HttpRequestHeader(field_name, field_value));
|
||||
this->Unlock();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 Request::CreateHttpRequest(s32 http_template_id, const char* url) {
|
||||
const char* method = this->method.empty() ? "UNKNOWN" : this->method.data();
|
||||
s32 http_request_id = Libraries::Http2::sceHttp2CreateRequestWithURL(http_template_id, method,
|
||||
url, this->content_length);
|
||||
if (http_request_id < 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Failed to create Http2 request, error = {:#x}", http_request_id);
|
||||
return http_request_id;
|
||||
}
|
||||
this->http_request_id = http_request_id;
|
||||
s32 result = Libraries::Http2::sceHttp2AddRequestHeader(http_request_id, "Content-Type",
|
||||
this->content_type.data(), 0);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Failed to add Content-Type request header, error = {:#x}",
|
||||
result);
|
||||
return result;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = this->parent_ctx->GetUserContext(this->id >> 0x20);
|
||||
const std::string bearer = NpHandler::GetInstance().GetBearerToken(user_ctx->GetUserId());
|
||||
if (!bearer.empty()) {
|
||||
const std::string auth_value = "Bearer " + bearer;
|
||||
result = Libraries::Http2::sceHttp2AddRequestHeader(http_request_id, "Authorization",
|
||||
auth_value.data(), 0);
|
||||
}
|
||||
if (bearer.empty() || result < 0) {
|
||||
LOG_WARNING(Lib_NpWebApi2, "Failed to add Authorization request header");
|
||||
}
|
||||
|
||||
// This would go on to add several other PSN-specific headers.
|
||||
// As shadNet does not appear to use them, the logic is skipped for now.
|
||||
|
||||
for (HttpRequestHeader* header : this->http_headers) {
|
||||
s32 result = Libraries::Http2::sceHttp2AddRequestHeader(
|
||||
http_request_id, header->field_name.data(), header->field_value.data(), 0);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2,
|
||||
"Failed to add request header, name = {}, value = {}, error = {:#x}",
|
||||
header->field_name.data(), header->field_value.data(), result);
|
||||
user_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
user_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 Request::SendHttpRequest(void* data, u64 data_size) {
|
||||
s32 result = 0;
|
||||
if (this->content_length != 0 && this->sent_data == 0) {
|
||||
// Real library seems to do some calculations, some parts including IPC calls.
|
||||
// Not entirely sure how accurate this is in practice.
|
||||
result = Libraries::Http2::sceHttp2SetRequestContentLength(this->http_request_id,
|
||||
this->content_length);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Failed to set content length, error = {:#x}", result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (!data || data_size == 0 || this->content_length == 0) {
|
||||
result = Libraries::Http2::sceHttp2SendRequest(this->http_request_id, nullptr, 0);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Failed to send request, error = {:#x}", result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
u64 actual_size = std::min<u64>(data_size, this->content_length - this->sent_data);
|
||||
if (this->content_length <= this->sent_data) {
|
||||
// Nothing left to send
|
||||
return result;
|
||||
}
|
||||
result = Libraries::Http2::sceHttp2SendRequest(this->http_request_id, data, actual_size);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Failed to send request, error = {:#x}", result);
|
||||
return result;
|
||||
}
|
||||
this->sent_data += actual_size;
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 Request::GetAllHttpResponseHeaders() {
|
||||
char* header = nullptr;
|
||||
u64 size = 0;
|
||||
s32 result =
|
||||
Libraries::Http2::sceHttp2GetAllResponseHeaders(this->http_request_id, &header, &size);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Failed to get response headers, error = {:#x}", result);
|
||||
return result;
|
||||
}
|
||||
this->http_response_headers = header;
|
||||
this->http_response_header_size = size;
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 Request::ParseHttpResponseHeaders(const char* field_name, char* value, u64 value_size,
|
||||
u64* value_size_out) {
|
||||
const char* temp_val{};
|
||||
u64 temp_size{};
|
||||
s32 result = Libraries::Http::sceHttpParseResponseHeader(this->http_response_headers,
|
||||
this->http_response_header_size,
|
||||
field_name, &temp_val, &temp_size);
|
||||
if (result >= 0) {
|
||||
if (value) {
|
||||
std::memset(value, 0, value_size);
|
||||
u64 size = std::min<u64>(value_size, temp_size);
|
||||
std::memcpy(value, temp_val, size);
|
||||
}
|
||||
if (value_size_out) {
|
||||
*value_size_out = temp_size;
|
||||
}
|
||||
result = ORBIS_OK;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 Request::Abort() {
|
||||
this->Lock();
|
||||
s32 result = 0;
|
||||
if (this->Aborted()) {
|
||||
// Nothing to do.
|
||||
this->Unlock();
|
||||
return result;
|
||||
}
|
||||
this->aborted = true;
|
||||
|
||||
// Real library has multiple states, we don't since our logic is simpler.
|
||||
if (this->send_state == 3) {
|
||||
// In the middle of an Http request, that needs aborting.
|
||||
result = Libraries::Http2::sceHttp2AbortRequest(this->http_request_id);
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Failed to abort http request, error = {:#x}", result);
|
||||
}
|
||||
}
|
||||
this->Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 Request::Delete(s32* http_request) {
|
||||
for (HttpRequestHeader* header : this->http_headers) {
|
||||
delete header;
|
||||
}
|
||||
this->http_headers.clear();
|
||||
|
||||
if (!http_request && this->http_request_id) {
|
||||
Libraries::Http2::sceHttp2DeleteRequest(this->http_request_id);
|
||||
} else {
|
||||
*http_request = this->http_request_id;
|
||||
}
|
||||
while (this->user_count > 0) {
|
||||
Libraries::Kernel::sceKernelUsleep(50000);
|
||||
}
|
||||
delete this;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
}; // namespace Libraries::Np::NpWebApi2
|
||||
463
src/core/libraries/np/np_web_api2/np_web_api2_context.h
Normal file
463
src/core/libraries/np/np_web_api2/np_web_api2_context.h
Normal file
@ -0,0 +1,463 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/libraries/kernel/time.h"
|
||||
#include "core/libraries/np/np_web_api2/np_web_api2.h"
|
||||
#include "core/libraries/np/np_web_api2/np_web_api2_internal.h"
|
||||
#include "core/libraries/np/np_web_api2/np_web_api2_push_event.h"
|
||||
#include "core/libraries/system/userservice.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Libraries::Np::NpWebApi2 {
|
||||
|
||||
class UserContext;
|
||||
class Request;
|
||||
|
||||
class LibraryContext {
|
||||
public:
|
||||
LibraryContext(s32 ctx_id, s32 type, s32 http_ctx_id, u64 pool_size)
|
||||
: id(ctx_id), type(static_cast<LibraryContextType>(type)), http_ctx_id(http_ctx_id),
|
||||
pool_size(pool_size) {}
|
||||
LibraryContext(s32 ctx_id, s32 type, s32 http_ctx_id, u64 pool_size, const char* name)
|
||||
: id(ctx_id), type(static_cast<LibraryContextType>(type)), http_ctx_id(http_ctx_id),
|
||||
pool_size(pool_size), name(name) {}
|
||||
|
||||
void Lock() {
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
void Unlock() {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
void AddUser() {
|
||||
std::scoped_lock lk{lock};
|
||||
user_count++;
|
||||
}
|
||||
|
||||
void RemoveUser() {
|
||||
std::scoped_lock lk{lock};
|
||||
user_count--;
|
||||
}
|
||||
|
||||
s32 GetId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
s32 GetHttpCtxId() {
|
||||
return http_ctx_id;
|
||||
}
|
||||
|
||||
u64 GetPoolSize() {
|
||||
return pool_size;
|
||||
}
|
||||
|
||||
const char* GetName() {
|
||||
return name.empty() ? nullptr : name.data();
|
||||
}
|
||||
|
||||
bool IsDebug() {
|
||||
return type == LibraryContextType::Debug;
|
||||
}
|
||||
|
||||
bool IsNormal() {
|
||||
return type == LibraryContextType::Normal;
|
||||
}
|
||||
|
||||
bool IsInternal() {
|
||||
return type == LibraryContextType::Internal;
|
||||
}
|
||||
|
||||
bool IsPresence() {
|
||||
return type == LibraryContextType::Presence;
|
||||
}
|
||||
|
||||
bool IsDeleted() {
|
||||
return deleting;
|
||||
}
|
||||
|
||||
void MarkForDeletion() {
|
||||
deleting = true;
|
||||
}
|
||||
|
||||
bool IsBusy() {
|
||||
std::scoped_lock lk{lock};
|
||||
return user_count > 1;
|
||||
}
|
||||
|
||||
void CheckTimeout();
|
||||
|
||||
s32 CreatePushEventHandle();
|
||||
PushEventHandle* GetPushEventHandle(s32 handle_id);
|
||||
|
||||
void SetHandleEndTime(s32 handle_id) {
|
||||
std::scoped_lock lk{lock};
|
||||
if (push_event_handles.contains(handle_id)) {
|
||||
auto& handle = push_event_handles[handle_id];
|
||||
handle->SetEndTime();
|
||||
}
|
||||
}
|
||||
|
||||
void AbortAllPushEventHandles() {
|
||||
std::scoped_lock lk{lock};
|
||||
for (auto& [handle_id, handle] : push_event_handles) {
|
||||
abortPushEventHandle(id, handle_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool HasBusyPushEventHandles() {
|
||||
std::scoped_lock lk{lock};
|
||||
for (auto& [handle_id, handle] : push_event_handles) {
|
||||
if (handle->IsBusy()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
s32 DeletePushEventHandle(PushEventHandle* handle);
|
||||
|
||||
void DeleteAllPushEventHandles() {
|
||||
for (auto& [handle_id, handle] : push_event_handles) {
|
||||
delete handle;
|
||||
}
|
||||
push_event_handles.clear();
|
||||
}
|
||||
|
||||
s32 CreatePushEventFilter(s32 handle_id, const char* np_service_name,
|
||||
OrbisNpServiceLabel np_service_label,
|
||||
const OrbisNpWebApi2PushEventFilterParameter* filter_param,
|
||||
u64 filter_param_num, bool internal);
|
||||
|
||||
PushEventFilter* GetPushEventFilter(s32 filter_id) {
|
||||
std::scoped_lock lk{lock};
|
||||
if (!push_event_filters.contains(filter_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
return push_event_filters[filter_id];
|
||||
}
|
||||
|
||||
void DeletePushEventFilter(PushEventFilter* filter) {
|
||||
std::scoped_lock lk{lock};
|
||||
s32 filter_id = filter->GetId();
|
||||
if (push_event_filters.contains(filter_id)) {
|
||||
push_event_filters.erase(filter_id);
|
||||
}
|
||||
delete filter;
|
||||
}
|
||||
|
||||
void DeleteAllPushEventFilters() {
|
||||
for (auto& [filter_id, filter] : push_event_filters) {
|
||||
delete filter;
|
||||
}
|
||||
push_event_filters.clear();
|
||||
}
|
||||
|
||||
s32 CreateUserContext(Libraries::UserService::OrbisUserServiceUserId user_id);
|
||||
UserContext* GetUserContext(s32 user_ctx_id);
|
||||
UserContext* GetUserContextByUserId(Libraries::UserService::OrbisUserServiceUserId user_id);
|
||||
|
||||
void RemoveUserContext(s32 user_ctx_id) {
|
||||
std::scoped_lock lk{lock};
|
||||
if (user_contexts.contains(user_ctx_id)) {
|
||||
user_contexts.erase(user_ctx_id);
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteAllUserContexts() {
|
||||
std::scoped_lock lk{lock};
|
||||
for (auto& [user_ctx_id, user_ctx] : user_contexts) {
|
||||
deleteUserContext(user_ctx_id);
|
||||
}
|
||||
user_contexts.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
s32 id{};
|
||||
s32 http_ctx_id{};
|
||||
s32 user_count{};
|
||||
enum LibraryContextType : s32 {
|
||||
Debug = 0,
|
||||
Normal = 1,
|
||||
Internal = 2,
|
||||
Presence = 3,
|
||||
} type;
|
||||
u64 pool_size{};
|
||||
bool deleting{};
|
||||
std::recursive_mutex lock{};
|
||||
std::string name{};
|
||||
std::map<s32, UserContext*> user_contexts{};
|
||||
std::map<s32, PushEventHandle*> push_event_handles{};
|
||||
std::map<s32, PushEventFilter*> push_event_filters{};
|
||||
};
|
||||
|
||||
class UserContext {
|
||||
public:
|
||||
UserContext(LibraryContext* parent, s32 user_ctx_id,
|
||||
Libraries::UserService::OrbisUserServiceUserId user_id)
|
||||
: parent_ctx(parent), id(user_ctx_id), user_id(user_id) {}
|
||||
|
||||
void Lock() {
|
||||
parent_ctx->Lock();
|
||||
}
|
||||
|
||||
void Unlock() {
|
||||
parent_ctx->Unlock();
|
||||
}
|
||||
|
||||
void AddUser() {
|
||||
Lock();
|
||||
user_count++;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void RemoveUser() {
|
||||
Lock();
|
||||
user_count--;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
bool IsDeleted() {
|
||||
return deleting;
|
||||
}
|
||||
|
||||
void MarkForDeletion() {
|
||||
deleting = true;
|
||||
}
|
||||
|
||||
bool IsBusy() {
|
||||
parent_ctx->Lock();
|
||||
s32 users = user_count;
|
||||
parent_ctx->Unlock();
|
||||
// Assumes caller is a user
|
||||
return users > 1;
|
||||
}
|
||||
|
||||
s32 GetId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
Libraries::UserService::OrbisUserServiceUserId GetUserId() {
|
||||
return user_id;
|
||||
}
|
||||
|
||||
s32 GetHttpTemplateId() {
|
||||
return http_template_id;
|
||||
}
|
||||
|
||||
s32 Initialize();
|
||||
|
||||
void CheckTimeout();
|
||||
|
||||
s32 CreatePushEventCallback(s32 filter_id, OrbisNpWebApi2PushEventCallback cb_func,
|
||||
void* user_arg);
|
||||
s32 DeletePushEventCallback(s32 callback_id);
|
||||
|
||||
void CreatePushContext(OrbisNpWebApi2PushEventPushContextId* push_ctx_id);
|
||||
PushEventPushContext* GetPushContext(const OrbisNpWebApi2PushEventPushContextId* push_ctx_id);
|
||||
void DeletePushContext(PushEventPushContext* push_ctx_id);
|
||||
|
||||
s32 CreatePushContextCallback(s32 filter_id, OrbisNpWebApi2PushEventPushContextCallback cb_func,
|
||||
void* user_arg);
|
||||
s32 DeletePushContextCallback(s32 callback_id);
|
||||
|
||||
s32 CreateRequest(const char* api_group, const char* path, const char* method,
|
||||
const OrbisNpWebApi2ContentParameter* content_parameter, bool multipart,
|
||||
Request** request);
|
||||
Request* GetRequest(s64 request_id);
|
||||
bool HasBusyRequests();
|
||||
void AbortAllRequests();
|
||||
|
||||
void RemoveRequest(s64 request_id) {
|
||||
parent_ctx->Lock();
|
||||
if (requests.contains(request_id)) {
|
||||
requests.erase(request_id);
|
||||
}
|
||||
parent_ctx->Unlock();
|
||||
}
|
||||
|
||||
void Delete();
|
||||
|
||||
private:
|
||||
s32 id{};
|
||||
Libraries::UserService::OrbisUserServiceUserId user_id{};
|
||||
s32 user_count{};
|
||||
s32 http_template_id{};
|
||||
bool deleting{};
|
||||
bool push_contexts_busy{};
|
||||
LibraryContext* parent_ctx{};
|
||||
std::string user_agent{};
|
||||
std::map<s64, Request*> requests{};
|
||||
std::map<s32, PushEventCallback*> push_event_callbacks{};
|
||||
std::map<s64, PushEventPushContext*> push_contexts{};
|
||||
std::map<s32, PushEventPushContextCallback*> push_context_callbacks{};
|
||||
};
|
||||
|
||||
class Request {
|
||||
public:
|
||||
Request(LibraryContext* parent, s64 request_id, const char* api_group, const char* path,
|
||||
const char* method, bool multipart)
|
||||
: parent_ctx(parent), id(request_id), api_group(api_group), path(path), method(method),
|
||||
multipart_supported(multipart) {}
|
||||
Request(LibraryContext* parent, s64 request_id, const char* api_group, const char* path,
|
||||
const char* method, bool multipart,
|
||||
const OrbisNpWebApi2ContentParameter* content_parameter)
|
||||
: parent_ctx(parent), id(request_id), api_group(api_group), path(path), method(method),
|
||||
multipart_supported(multipart), content_type(content_parameter->content_type),
|
||||
content_length(content_parameter->content_length) {}
|
||||
|
||||
void Lock() {
|
||||
parent_ctx->Lock();
|
||||
}
|
||||
|
||||
void Unlock() {
|
||||
parent_ctx->Unlock();
|
||||
}
|
||||
|
||||
void AddUser() {
|
||||
Lock();
|
||||
user_count++;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void RemoveUser() {
|
||||
Lock();
|
||||
user_count--;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
s64 GetId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
s32 GetHttpRequestId() {
|
||||
return http_request_id;
|
||||
}
|
||||
|
||||
bool IsMultipart() {
|
||||
return multipart_supported;
|
||||
}
|
||||
|
||||
bool HasSent() {
|
||||
return sent;
|
||||
}
|
||||
|
||||
void MarkSent() {
|
||||
sent = true;
|
||||
}
|
||||
|
||||
bool Aborted() {
|
||||
return aborted;
|
||||
}
|
||||
|
||||
bool Expired() {
|
||||
return expired;
|
||||
}
|
||||
|
||||
bool OutOfData() {
|
||||
return content_length == sent_data;
|
||||
}
|
||||
|
||||
void SetEndTime() {
|
||||
if (timeout != 0 && end_time == 0) {
|
||||
end_time = Libraries::Kernel::sceKernelGetProcessTime() + timeout;
|
||||
}
|
||||
}
|
||||
|
||||
void ClearEndTime() {
|
||||
end_time = 0;
|
||||
}
|
||||
|
||||
std::string& GetApiGroup() {
|
||||
return api_group;
|
||||
}
|
||||
|
||||
std::string& GetPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string& GetMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
std::string& GetContentType() {
|
||||
return content_type;
|
||||
}
|
||||
|
||||
void SetState(s32 state) {
|
||||
send_state = state;
|
||||
}
|
||||
|
||||
bool IsDeleted() {
|
||||
return deleting;
|
||||
}
|
||||
|
||||
void MarkForDeletion() {
|
||||
deleting = true;
|
||||
}
|
||||
|
||||
bool IsBusy() {
|
||||
parent_ctx->Lock();
|
||||
s32 users = user_count;
|
||||
parent_ctx->Unlock();
|
||||
// Assumes caller is a user
|
||||
return users > 1;
|
||||
}
|
||||
|
||||
s32 AddHttpRequestHeader(const char* field_name, const char* field_value);
|
||||
|
||||
void SetTimeout(u32 new_timeout) {
|
||||
this->timeout = new_timeout;
|
||||
}
|
||||
|
||||
void CheckTimeout() {
|
||||
u64 time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||
if (!expired && end_time != 0 && end_time < time) {
|
||||
expired = true;
|
||||
Abort();
|
||||
}
|
||||
}
|
||||
|
||||
s32 CreateHttpRequest(s32 http_template_id, const char* url);
|
||||
s32 SendHttpRequest(void* data, u64 data_size);
|
||||
s32 GetAllHttpResponseHeaders();
|
||||
s32 ParseHttpResponseHeaders(const char* field_name, char* value, u64 value_size,
|
||||
u64* value_size_out);
|
||||
s32 Abort();
|
||||
s32 Delete(s32* http_request_id);
|
||||
|
||||
private:
|
||||
s64 id{};
|
||||
u64 content_length{};
|
||||
char* http_response_headers{};
|
||||
u64 http_response_header_size{};
|
||||
s32 user_count{};
|
||||
s32 http_request_id{};
|
||||
u32 timeout{};
|
||||
s32 sent_data{};
|
||||
s32 send_state{};
|
||||
bool multipart_supported{};
|
||||
bool sent{};
|
||||
bool aborted{};
|
||||
bool expired{};
|
||||
bool deleting{};
|
||||
u64 end_time{};
|
||||
LibraryContext* parent_ctx{};
|
||||
std::string api_group{};
|
||||
std::string path{};
|
||||
std::string method{};
|
||||
std::string content_type{};
|
||||
|
||||
struct HttpRequestHeader {
|
||||
std::string field_name;
|
||||
std::string field_value;
|
||||
};
|
||||
std::vector<HttpRequestHeader*> http_headers{};
|
||||
};
|
||||
|
||||
}; // namespace Libraries::Np::NpWebApi2
|
||||
932
src/core/libraries/np/np_web_api2/np_web_api2_internal.cpp
Normal file
932
src/core/libraries/np/np_web_api2/np_web_api2_internal.cpp
Normal file
@ -0,0 +1,932 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/emulator_settings.h"
|
||||
#include "core/libraries/kernel/time.h"
|
||||
#include "core/libraries/network/http2.h"
|
||||
#include "core/libraries/np/np_error.h"
|
||||
#include "core/libraries/np/np_types.h"
|
||||
#include "core/libraries/np/np_web_api2/np_web_api2_context.h"
|
||||
#include "core/libraries/np/np_web_api2/np_web_api2_internal.h"
|
||||
#include "core/libraries/system/userservice.h"
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
namespace Libraries::Np::NpWebApi2 {
|
||||
|
||||
std::recursive_mutex g_mutex{};
|
||||
s32 g_current_lib_context_id{};
|
||||
std::map<s32, LibraryContext*> g_lib_contexts{};
|
||||
u64 g_last_timeout_check{};
|
||||
|
||||
s32 createLibraryContext(s32 http_ctx_id, s32 type, u64 pool_size, const char* name) {
|
||||
std::scoped_lock lk{g_mutex};
|
||||
|
||||
if (g_lib_contexts.size() >= 0x8000) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Too many library contexts");
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_MAX;
|
||||
}
|
||||
|
||||
do {
|
||||
g_current_lib_context_id++;
|
||||
if (g_current_lib_context_id >= 0x8000) {
|
||||
g_current_lib_context_id = 1;
|
||||
}
|
||||
} while (g_lib_contexts.contains(g_current_lib_context_id));
|
||||
|
||||
if (!name) {
|
||||
g_lib_contexts[g_current_lib_context_id] =
|
||||
new LibraryContext(g_current_lib_context_id, type, http_ctx_id, pool_size);
|
||||
} else {
|
||||
g_lib_contexts[g_current_lib_context_id] =
|
||||
new LibraryContext(g_current_lib_context_id, type, http_ctx_id, pool_size, name);
|
||||
}
|
||||
return g_current_lib_context_id;
|
||||
}
|
||||
|
||||
LibraryContext* getLibraryContext(s32 lib_ctx_id) {
|
||||
std::scoped_lock lk{g_mutex};
|
||||
|
||||
if (!g_lib_contexts.contains(lib_ctx_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
LibraryContext* lib_ctx = g_lib_contexts.at(lib_ctx_id);
|
||||
if (lib_ctx->IsDeleted()) {
|
||||
return nullptr;
|
||||
}
|
||||
lib_ctx->AddUser();
|
||||
return lib_ctx;
|
||||
}
|
||||
|
||||
s32 getMemoryPoolStats(s32 lib_ctx_id, OrbisNpWebApi2MemoryPoolStats* stats) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context with id {:#x}", lib_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (stats) {
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
stats->pool_size = lib_ctx->GetPoolSize();
|
||||
}
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 createPushEventHandle(s32 lib_ctx_id) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context with id {:#x}", lib_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
s32 result = lib_ctx->CreatePushEventHandle();
|
||||
lib_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 setHandleTimeout(s32 lib_ctx_id, s32 handle_id, u32 timeout) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context with id {:#x}", lib_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
PushEventHandle* handle = lib_ctx->GetPushEventHandle(handle_id);
|
||||
if (!handle) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No handle with id {:#x}", handle_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_HANDLE_NOT_FOUND;
|
||||
}
|
||||
|
||||
lib_ctx->Lock();
|
||||
handle->SetTimeout(timeout);
|
||||
handle->RemoveUser();
|
||||
lib_ctx->Unlock();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 abortPushEventHandle(s32 lib_ctx_id, s32 handle_id) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context with id {:#x}", lib_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
PushEventHandle* handle = lib_ctx->GetPushEventHandle(handle_id);
|
||||
if (!handle) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No handle with id {:#x}", handle_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_HANDLE_NOT_FOUND;
|
||||
}
|
||||
|
||||
lib_ctx->Lock();
|
||||
handle->Abort();
|
||||
lib_ctx->Unlock();
|
||||
handle->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 deletePushEventHandle(s32 lib_ctx_id, s32 handle_id) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context with id {:#x}", lib_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
PushEventHandle* handle = lib_ctx->GetPushEventHandle(handle_id);
|
||||
if (!handle) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No handle with id {:#x}", handle_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_HANDLE_NOT_FOUND;
|
||||
}
|
||||
|
||||
s32 result = lib_ctx->DeletePushEventHandle(handle);
|
||||
lib_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 createPushEventFilter(s32 lib_ctx_id, s32 handle_id, const char* np_service_name,
|
||||
OrbisNpServiceLabel np_service_label,
|
||||
const OrbisNpWebApi2PushEventFilterParameter* filter_param,
|
||||
u64 filter_param_num, bool internal) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context with id {:#x}", lib_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
lib_ctx->SetHandleEndTime(handle_id);
|
||||
s32 result = lib_ctx->CreatePushEventFilter(handle_id, np_service_name, np_service_label,
|
||||
filter_param, filter_param_num, internal);
|
||||
lib_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 deletePushEventFilter(s32 lib_ctx_id, s32 filter_id) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context with id {:#x}", lib_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
PushEventFilter* filter = lib_ctx->GetPushEventFilter(filter_id);
|
||||
if (!filter) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No filter with id {:#x}", filter_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_PUSH_EVENT_FILTER_NOT_FOUND;
|
||||
}
|
||||
|
||||
lib_ctx->DeletePushEventFilter(filter);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 terminateLibraryContext(s32 lib_ctx_id) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context with id {:#x}", lib_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
lib_ctx->Lock();
|
||||
lib_ctx->DeleteAllUserContexts();
|
||||
lib_ctx->AbortAllPushEventHandles();
|
||||
|
||||
if (lib_ctx->IsDeleted()) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Library context with id {:#x} is already deleted", lib_ctx_id);
|
||||
lib_ctx->Unlock();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
lib_ctx->MarkForDeletion();
|
||||
while (lib_ctx->IsBusy() || lib_ctx->HasBusyPushEventHandles()) {
|
||||
lib_ctx->Unlock();
|
||||
Libraries::Kernel::sceKernelUsleep(50000);
|
||||
lib_ctx->Lock();
|
||||
}
|
||||
lib_ctx->Unlock();
|
||||
lib_ctx->RemoveUser();
|
||||
|
||||
g_mutex.lock();
|
||||
g_lib_contexts.erase(lib_ctx_id);
|
||||
g_mutex.unlock();
|
||||
|
||||
lib_ctx->DeleteAllPushEventHandles();
|
||||
lib_ctx->DeleteAllPushEventFilters();
|
||||
delete lib_ctx;
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 createUserContext(s32 lib_ctx_id, Libraries::UserService::OrbisUserServiceUserId user_id) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context with id {:#x}", lib_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContextByUserId(user_id);
|
||||
if (user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "User context already exists for user id {}", user_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_ALREADY_EXIST;
|
||||
}
|
||||
|
||||
s32 user_ctx_id = lib_ctx->CreateUserContext(user_id);
|
||||
if (user_ctx_id < 0) {
|
||||
// user_ctx_id contains an error code, return it.
|
||||
lib_ctx->RemoveUser();
|
||||
return user_ctx_id;
|
||||
}
|
||||
|
||||
user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
user_ctx->RemoveUser();
|
||||
|
||||
s32 result = user_ctx->Initialize();
|
||||
if (result < 0) {
|
||||
// Failed to initialize user_ctx, destroy it.
|
||||
lib_ctx->RemoveUserContext(user_ctx_id);
|
||||
delete user_ctx;
|
||||
}
|
||||
|
||||
lib_ctx->RemoveUser();
|
||||
return user_ctx_id;
|
||||
}
|
||||
|
||||
s32 deleteUserContext(s32 user_ctx_id) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(user_ctx_id >> 0x10);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for user context id {:#x}", user_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
lib_ctx->Lock();
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context with id {:#x}", user_ctx_id);
|
||||
lib_ctx->Unlock();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
user_ctx->AbortAllRequests();
|
||||
if (user_ctx->IsDeleted()) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "User context with id {:#x} is already deleted", user_ctx_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->Unlock();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
user_ctx->MarkForDeletion();
|
||||
while (user_ctx->IsBusy() || user_ctx->HasBusyRequests()) {
|
||||
lib_ctx->Unlock();
|
||||
Libraries::Kernel::sceKernelUsleep(50000);
|
||||
lib_ctx->Lock();
|
||||
}
|
||||
|
||||
user_ctx->Delete();
|
||||
lib_ctx->Unlock();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 registerPushEventCallback(s32 user_ctx_id, s32 filter_id,
|
||||
OrbisNpWebApi2PushEventCallback cb_func, void* user_arg) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(user_ctx_id >> 0x10);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for user context id {:#x}", user_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context with id {:#x}", user_ctx_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!lib_ctx->GetPushEventFilter(filter_id)) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No push event filter with id {:#x}", filter_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_PUSH_EVENT_FILTER_NOT_FOUND;
|
||||
}
|
||||
|
||||
s32 result = user_ctx->CreatePushEventCallback(filter_id, cb_func, user_arg);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 unregisterPushEventCallback(s32 user_ctx_id, s32 callback_id) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(user_ctx_id >> 0x10);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for user context id {:#x}", user_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context with id {:#x}", user_ctx_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
s32 result = user_ctx->DeletePushEventCallback(callback_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 createPushContext(s32 user_ctx_id, OrbisNpWebApi2PushEventPushContextId* push_ctx_id) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(user_ctx_id >> 0x10);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for user context id {:#x}", user_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context with id {:#x}", user_ctx_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
user_ctx->CreatePushContext(push_ctx_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 startPushContextCallback(s32 user_ctx_id,
|
||||
const OrbisNpWebApi2PushEventPushContextId* push_ctx_id) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(user_ctx_id >> 0x10);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for user context id {:#x}", user_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context with id {:#x}", user_ctx_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
PushEventPushContext* push_ctx = user_ctx->GetPushContext(push_ctx_id);
|
||||
if (!push_ctx) {
|
||||
s64 raw_id{};
|
||||
std::memcpy(&raw_id, push_ctx_id, sizeof(s64));
|
||||
LOG_ERROR(Lib_NpWebApi2, "No push context with id {}", raw_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_PUSH_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
push_ctx->Start();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 deletePushContext(s32 user_ctx_id, const OrbisNpWebApi2PushEventPushContextId* push_ctx_id) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(user_ctx_id >> 0x10);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for user context id {:#x}", user_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context with id {:#x}", user_ctx_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
PushEventPushContext* push_ctx = user_ctx->GetPushContext(push_ctx_id);
|
||||
if (!push_ctx) {
|
||||
s64 raw_id{};
|
||||
std::memcpy(&raw_id, push_ctx_id, sizeof(s64));
|
||||
LOG_ERROR(Lib_NpWebApi2, "No push context with id {}", raw_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_PUSH_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
user_ctx->DeletePushContext(push_ctx);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 registerPushContextCallback(s32 user_ctx_id, s32 filter_id,
|
||||
OrbisNpWebApi2PushEventPushContextCallback cb_func,
|
||||
void* user_arg) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(user_ctx_id >> 0x10);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for user context id {:#x}", user_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context with id {:#x}", user_ctx_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!lib_ctx->GetPushEventFilter(filter_id)) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No push event filter with id {:#x}", filter_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_PUSH_EVENT_FILTER_NOT_FOUND;
|
||||
}
|
||||
|
||||
s32 result = user_ctx->CreatePushContextCallback(filter_id, cb_func, user_arg);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 unregisterPushContextCallback(s32 user_ctx_id, s32 callback_id) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(user_ctx_id >> 0x10);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for user context id {:#x}", user_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context with id {:#x}", user_ctx_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
s32 result = user_ctx->DeletePushContextCallback(callback_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
|
||||
void processPushEvents() {
|
||||
// LOG_ERROR(Lib_NpWebApi2, "(STUBBED)");
|
||||
}
|
||||
|
||||
s32 createRequest(s32 user_ctx_id, const char* api_group, const char* path, const char* method,
|
||||
const OrbisNpWebApi2ContentParameter* content_parameter, bool multipart,
|
||||
s64* request_id) {
|
||||
LibraryContext* lib_ctx = getLibraryContext(user_ctx_id >> 0x10);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for user context id {:#x}", user_ctx_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context with id {:#x}", user_ctx_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (std::strlen(api_group) >= 63) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "API group is too long");
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_PARAMETER_TOO_LONG;
|
||||
}
|
||||
|
||||
Request* request{};
|
||||
s32 result =
|
||||
user_ctx->CreateRequest(api_group, path, method, content_parameter, multipart, &request);
|
||||
if (result < 0) {
|
||||
// Request creation failed
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
if (request) {
|
||||
delete request;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (request_id) {
|
||||
*request_id = request->GetId();
|
||||
}
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 addHttpRequestHeader(s64 request_id, const char* field_name, const char* field_value) {
|
||||
s32 lib_ctx_id = static_cast<s32>(request_id >> 0x30);
|
||||
s32 user_ctx_id = static_cast<s32>(request_id >> 0x20);
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for request id {:#x}", request_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context for request id {:#x}", request_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
Request* request = user_ctx->GetRequest(request_id);
|
||||
if (!request) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No request with id {:#x}", request_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_REQUEST_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (request->HasSent()) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Request is already sent");
|
||||
request->RemoveUser();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_AFTER_SEND;
|
||||
}
|
||||
|
||||
s32 result = request->AddHttpRequestHeader(field_name, field_value);
|
||||
request->RemoveUser();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 setRequestTimeout(s64 request_id, u32 timeout) {
|
||||
s32 lib_ctx_id = static_cast<s32>(request_id >> 0x30);
|
||||
s32 user_ctx_id = static_cast<s32>(request_id >> 0x20);
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for request id {:#x}", request_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context for request id {:#x}", request_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
Request* request = user_ctx->GetRequest(request_id);
|
||||
if (!request) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No request with id {:#x}", request_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_REQUEST_NOT_FOUND;
|
||||
}
|
||||
|
||||
request->SetTimeout(timeout);
|
||||
request->RemoveUser();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
static s32 checkRequestStatus(Request* request, UserContext* user_ctx, LibraryContext* lib_ctx) {
|
||||
if (request->Expired()) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Request timed out");
|
||||
request->RemoveUser();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
if (request->Aborted()) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Request aborted");
|
||||
request->RemoveUser();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_ABORTED;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 sendRequest(s64 request_id, s32 part_index, void* data, u64 data_size,
|
||||
OrbisNpWebApi2ResponseInformationOption* resp_info_option) {
|
||||
s32 lib_ctx_id = static_cast<s32>(request_id >> 0x30);
|
||||
s32 user_ctx_id = static_cast<s32>(request_id >> 0x20);
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for request id {:#x}", request_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context for request id {:#x}", request_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
Request* request = user_ctx->GetRequest(request_id);
|
||||
if (!request) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No request with id {:#x}", request_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_REQUEST_NOT_FOUND;
|
||||
}
|
||||
|
||||
request->SetEndTime();
|
||||
if (request->IsMultipart()) {
|
||||
if (part_index == 0) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "part_index 0 is prohibited for multipart requests");
|
||||
request->RemoveUser();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_PROHIBITED_FUNCTION_CALL;
|
||||
}
|
||||
// TODO: Multipart logic
|
||||
}
|
||||
|
||||
if (!request->HasSent()) {
|
||||
request->MarkSent();
|
||||
}
|
||||
|
||||
request->Lock();
|
||||
request->SetState(0);
|
||||
s32 result = checkRequestStatus(request, user_ctx, lib_ctx);
|
||||
request->Unlock();
|
||||
if (result != 0) {
|
||||
// Aborted or timed out.
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!EmulatorSettings.IsShadNetEnabled()) {
|
||||
LOG_INFO(Lib_NpWebApi2, "Cannot send request, you are not signed in to shadNet");
|
||||
request->RemoveUser();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_NOT_SIGNED_IN;
|
||||
}
|
||||
|
||||
if (request->GetHttpRequestId() == 0) {
|
||||
std::string base_url = EmulatorSettings.GetShadNetWebApiServer();
|
||||
s32 template_id = user_ctx->GetHttpTemplateId();
|
||||
// Technically this should be base_url + api_group + path,
|
||||
// but shadNet doesn't seem to use the api_group for endpoints?
|
||||
std::string full_url = base_url + request->GetPath();
|
||||
result = request->CreateHttpRequest(template_id, full_url.data());
|
||||
if (result < 0) {
|
||||
// Underlying request creation failed, return.
|
||||
request->RemoveUser();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
request->Lock();
|
||||
request->SetState(3);
|
||||
result = checkRequestStatus(request, user_ctx, lib_ctx);
|
||||
request->Unlock();
|
||||
if (result != 0) {
|
||||
// Aborted or timed out.
|
||||
return result;
|
||||
}
|
||||
|
||||
if (request->IsMultipart()) {
|
||||
// TODO: Multipart sends
|
||||
// result = request->SendMultipartHttpRequest(data, data_size, part_index);
|
||||
} else {
|
||||
result = request->SendHttpRequest(data, data_size);
|
||||
}
|
||||
|
||||
if (result >= 0 && request->OutOfData()) {
|
||||
result = request->GetAllHttpResponseHeaders();
|
||||
if (result >= 0) {
|
||||
s32 http_request_id = request->GetHttpRequestId();
|
||||
s32 http_status{};
|
||||
result = Libraries::Http2::sceHttp2GetStatusCode(http_request_id, &http_status);
|
||||
if (result >= 0) {
|
||||
if (resp_info_option) {
|
||||
resp_info_option->http_status = http_status;
|
||||
}
|
||||
if (http_status >= 400) {
|
||||
result = http_status | 0x82f00000;
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(Lib_NpWebApi2, "Failed to get http status code, error = {:#x}", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
request->Lock();
|
||||
request->SetState(0);
|
||||
s32 result2 = checkRequestStatus(request, user_ctx, lib_ctx);
|
||||
request->Unlock();
|
||||
if (result2 != 0) {
|
||||
// Aborted or timed out.
|
||||
return result2;
|
||||
}
|
||||
|
||||
request->ClearEndTime();
|
||||
request->RemoveUser();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 getHttpResponseHeaderData(s64 request_id, const char* field_name, char* value, u64 value_size,
|
||||
u64* value_size_out) {
|
||||
s32 lib_ctx_id = static_cast<s32>(request_id >> 0x30);
|
||||
s32 user_ctx_id = static_cast<s32>(request_id >> 0x20);
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for request id {:#x}", request_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context for request id {:#x}", request_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
Request* request = user_ctx->GetRequest(request_id);
|
||||
if (!request) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No request with id {:#x}", request_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_REQUEST_NOT_FOUND;
|
||||
}
|
||||
|
||||
s32 result = request->ParseHttpResponseHeaders(field_name, value, value_size, value_size_out);
|
||||
request->RemoveUser();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 readData(s64 request_id, void* data, u64 size) {
|
||||
s32 lib_ctx_id = static_cast<s32>(request_id >> 0x30);
|
||||
s32 user_ctx_id = static_cast<s32>(request_id >> 0x20);
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for request id {:#x}", request_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context for request id {:#x}", request_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
Request* request = user_ctx->GetRequest(request_id);
|
||||
if (!request) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No request with id {:#x}", request_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_REQUEST_NOT_FOUND;
|
||||
}
|
||||
|
||||
request->SetEndTime();
|
||||
|
||||
request->Lock();
|
||||
request->SetState(3);
|
||||
s32 result = checkRequestStatus(request, user_ctx, lib_ctx);
|
||||
request->Unlock();
|
||||
if (result != 0) {
|
||||
// Aborted or timed out.
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 http_req_id = request->GetHttpRequestId();
|
||||
s32 result2 = Libraries::Http2::sceHttp2ReadData(http_req_id, data, size);
|
||||
|
||||
request->Lock();
|
||||
request->SetState(0);
|
||||
result = checkRequestStatus(request, user_ctx, lib_ctx);
|
||||
request->Unlock();
|
||||
if (result != 0) {
|
||||
// Aborted or timed out.
|
||||
return result;
|
||||
}
|
||||
|
||||
request->ClearEndTime();
|
||||
|
||||
request->RemoveUser();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return result2;
|
||||
}
|
||||
|
||||
s32 abortRequest(s64 request_id) {
|
||||
s32 lib_ctx_id = static_cast<s32>(request_id >> 0x30);
|
||||
s32 user_ctx_id = static_cast<s32>(request_id >> 0x20);
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for request id {:#x}", request_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context for request id {:#x}", request_id);
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
Request* request = user_ctx->GetRequest(request_id);
|
||||
if (!request) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No request with id {:#x}", request_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_REQUEST_NOT_FOUND;
|
||||
}
|
||||
|
||||
request->RemoveUser();
|
||||
s32 result = request->Abort();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->RemoveUser();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 deleteRequest(s64 request_id) {
|
||||
s32 lib_ctx_id = static_cast<s32>(request_id >> 0x30);
|
||||
s32 user_ctx_id = static_cast<s32>(request_id >> 0x20);
|
||||
LibraryContext* lib_ctx = getLibraryContext(lib_ctx_id);
|
||||
if (!lib_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No library context for request id {:#x}", request_id);
|
||||
return ORBIS_NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
lib_ctx->Lock();
|
||||
UserContext* user_ctx = lib_ctx->GetUserContext(user_ctx_id);
|
||||
if (!user_ctx) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No user context for request id {:#x}", request_id);
|
||||
lib_ctx->Unlock();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_USER_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
Request* request = user_ctx->GetRequest(request_id);
|
||||
if (!request) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "No request with id {:#x}", request_id);
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->Unlock();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_REQUEST_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (request->IsDeleted()) {
|
||||
// Already marked for deletion
|
||||
LOG_ERROR(Lib_NpWebApi2, "Request with id {:#x} is already being deleted", request_id);
|
||||
request->RemoveUser();
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->Unlock();
|
||||
lib_ctx->RemoveUser();
|
||||
return ORBIS_NP_WEBAPI2_ERROR_REQUEST_NOT_FOUND;
|
||||
}
|
||||
|
||||
request->MarkForDeletion();
|
||||
request->Abort();
|
||||
while (request->IsBusy()) {
|
||||
lib_ctx->Unlock();
|
||||
Libraries::Kernel::sceKernelUsleep(50000);
|
||||
lib_ctx->Lock();
|
||||
}
|
||||
user_ctx->RemoveRequest(request_id);
|
||||
request->RemoveUser();
|
||||
|
||||
s32 http_request_id = 0;
|
||||
request->Delete(&http_request_id);
|
||||
|
||||
user_ctx->RemoveUser();
|
||||
lib_ctx->Unlock();
|
||||
lib_ctx->RemoveUser();
|
||||
if (http_request_id != 0) {
|
||||
Libraries::Http2::sceHttp2DeleteRequest(http_request_id);
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void checkTimeout() {
|
||||
u64 current_time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||
if (current_time < g_last_timeout_check + 1000) {
|
||||
// Too soon, skip check.
|
||||
return;
|
||||
}
|
||||
|
||||
std::scoped_lock lk{g_mutex};
|
||||
g_last_timeout_check = current_time;
|
||||
for (auto& [lib_ctx_id, lib_ctx] : g_lib_contexts) {
|
||||
lib_ctx->CheckTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace Libraries::Np::NpWebApi2
|
||||
48
src/core/libraries/np/np_web_api2/np_web_api2_internal.h
Normal file
48
src/core/libraries/np/np_web_api2/np_web_api2_internal.h
Normal file
@ -0,0 +1,48 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/libraries/np/np_web_api2/np_web_api2.h"
|
||||
#include "core/libraries/system/userservice.h"
|
||||
|
||||
namespace Libraries::Np::NpWebApi2 {
|
||||
|
||||
s32 createLibraryContext(s32 http_ctx_id, s32 type, u64 pool_size, const char* name);
|
||||
s32 getMemoryPoolStats(s32 lib_ctx_id, OrbisNpWebApi2MemoryPoolStats* stats);
|
||||
s32 createPushEventHandle(s32 lib_ctx_id);
|
||||
s32 setHandleTimeout(s32 lib_ctx_id, s32 handle_id, u32 timeout);
|
||||
s32 abortPushEventHandle(s32 lib_ctx_id, s32 handle_id);
|
||||
s32 deletePushEventHandle(s32 lib_ctx_id, s32 handle_id);
|
||||
s32 createPushEventFilter(s32 lib_ctx_id, s32 handle_id, const char* np_service_name,
|
||||
OrbisNpServiceLabel np_service_label,
|
||||
const OrbisNpWebApi2PushEventFilterParameter* filter_param,
|
||||
u64 filter_param_num, bool internal);
|
||||
s32 deletePushEventFilter(s32 lib_ctx_id, s32 filter_id);
|
||||
s32 terminateLibraryContext(s32 lib_ctx_id);
|
||||
s32 createUserContext(s32 lib_ctx_id, Libraries::UserService::OrbisUserServiceUserId user_id);
|
||||
s32 deleteUserContext(s32 user_ctx_id);
|
||||
s32 registerPushEventCallback(s32 user_ctx_id, s32 filter_id,
|
||||
OrbisNpWebApi2PushEventCallback cb_func, void* user_arg);
|
||||
s32 unregisterPushEventCallback(s32 user_ctx_id, s32 callback_id);
|
||||
s32 createPushContext(s32 user_ctx_id, OrbisNpWebApi2PushEventPushContextId* push_ctx_id);
|
||||
s32 startPushContextCallback(s32 user_ctx_id,
|
||||
const OrbisNpWebApi2PushEventPushContextId* push_ctx_id);
|
||||
s32 deletePushContext(s32 user_ctx_id, const OrbisNpWebApi2PushEventPushContextId* push_ctx_id);
|
||||
s32 registerPushContextCallback(s32 user_ctx_id, s32 filter_id,
|
||||
OrbisNpWebApi2PushEventPushContextCallback cb_func, void* user_arg);
|
||||
s32 unregisterPushContextCallback(s32 user_ctx_id, s32 callback_id);
|
||||
void processPushEvents();
|
||||
s32 createRequest(s32 user_ctx_id, const char* api_group, const char* path, const char* method,
|
||||
const OrbisNpWebApi2ContentParameter* content_parameter, bool multipart,
|
||||
s64* request_id);
|
||||
s32 addHttpRequestHeader(s64 request_id, const char* field_name, const char* field_value);
|
||||
s32 setRequestTimeout(s64 request_id, u32 timeout);
|
||||
s32 sendRequest(s64 request_id, s32 part_index, void* data, u64 data_size,
|
||||
OrbisNpWebApi2ResponseInformationOption* resp_info_option);
|
||||
s32 getHttpResponseHeaderData(s64 request_id, const char* field_name, char* value, u64 value_size,
|
||||
u64* value_size_out);
|
||||
s32 readData(s64 request_id, void* data, u64 size);
|
||||
s32 abortRequest(s64 request_id);
|
||||
s32 deleteRequest(s64 request_id);
|
||||
void checkTimeout();
|
||||
|
||||
}; // namespace Libraries::Np::NpWebApi2
|
||||
64
src/core/libraries/np/np_web_api2/np_web_api2_push_event.cpp
Normal file
64
src/core/libraries/np/np_web_api2/np_web_api2_push_event.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/np/np_error.h"
|
||||
#include "core/libraries/np/np_web_api2/np_web_api2_push_event.h"
|
||||
|
||||
namespace Libraries::Np::NpWebApi2 {
|
||||
|
||||
s64 g_current_push_event_push_context_id{};
|
||||
|
||||
s32 PushEventFilter::Initialize(PushEventHandle* handle,
|
||||
const OrbisNpWebApi2PushEventFilterParameter* filter_param,
|
||||
u64 filter_param_num) {
|
||||
if (handle->IsDeleted()) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "handle {:#x} is invalid", handle->GetId());
|
||||
return ORBIS_NP_WEBAPI2_ERROR_HANDLE_NOT_FOUND;
|
||||
}
|
||||
if (handle->IsTimedout()) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "handle {:#x} has timed out", handle->GetId());
|
||||
return ORBIS_NP_WEBAPI2_ERROR_TIMEOUT;
|
||||
}
|
||||
if (handle->IsAborted()) {
|
||||
LOG_ERROR(Lib_NpWebApi2, "handle {:#x} was aborted", handle->GetId());
|
||||
return ORBIS_NP_WEBAPI2_ERROR_ABORTED;
|
||||
}
|
||||
|
||||
std::vector<std::vector<OrbisNpWebApi2PushEventExtdDataKey>> copy_storage{};
|
||||
for (u64 i = 0; i < filter_param_num; i++) {
|
||||
OrbisNpWebApi2PushEventFilterParameter new_param{};
|
||||
memcpy(&new_param, &filter_param[i], sizeof(OrbisNpWebApi2PushEventFilterParameter));
|
||||
if (filter_param[i].extd_data_key != nullptr && filter_param[i].extd_data_key_num != 0) {
|
||||
std::vector<OrbisNpWebApi2PushEventExtdDataKey> data_keys{};
|
||||
for (u64 j = 0; j < filter_param[i].extd_data_key_num; j++) {
|
||||
OrbisNpWebApi2PushEventExtdDataKey new_key{};
|
||||
memcpy(&new_key, &filter_param[i].extd_data_key[j],
|
||||
sizeof(OrbisNpWebApi2PushEventExtdDataKey));
|
||||
data_keys.emplace_back(new_key);
|
||||
}
|
||||
new_param.extd_data_key = data_keys.data();
|
||||
copy_storage.emplace_back(data_keys);
|
||||
}
|
||||
this->filter_params.emplace_back(new_param);
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void PushEventPushContext::Initialize() {
|
||||
// In the real library, there's a whole process of registering this with NpManager's Push2 API.
|
||||
// For now, we'll just create the uuid for this push context.
|
||||
|
||||
// As for the ID itself, for now we'll cheat a bit.
|
||||
// Real library does a mostly random string, but it's easier to just use an actual index.
|
||||
++g_current_push_event_push_context_id;
|
||||
if (g_current_push_event_push_context_id < 0) {
|
||||
g_current_push_event_push_context_id = 1;
|
||||
}
|
||||
s64 new_id = g_current_push_event_push_context_id;
|
||||
std::memset(&this->id, 0, sizeof(this->id));
|
||||
std::memcpy(&this->id, &new_id, sizeof(s64));
|
||||
}
|
||||
|
||||
}; // namespace Libraries::Np::NpWebApi2
|
||||
168
src/core/libraries/np/np_web_api2/np_web_api2_push_event.h
Normal file
168
src/core/libraries/np/np_web_api2/np_web_api2_push_event.h
Normal file
@ -0,0 +1,168 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/kernel/time.h"
|
||||
#include "core/libraries/np/np_types.h"
|
||||
#include "core/libraries/np/np_web_api2/np_web_api2.h"
|
||||
|
||||
namespace Libraries::Np::NpWebApi2 {
|
||||
|
||||
class UserContext;
|
||||
|
||||
class PushEventHandle {
|
||||
public:
|
||||
PushEventHandle(s32 new_id) : id(new_id) {}
|
||||
|
||||
s32 GetId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
void SetTimeout(u32 new_timeout) {
|
||||
timeout = new_timeout;
|
||||
}
|
||||
|
||||
void AddUser() {
|
||||
user_count++;
|
||||
}
|
||||
|
||||
void RemoveUser() {
|
||||
user_count--;
|
||||
}
|
||||
|
||||
void Abort() {
|
||||
aborted = true;
|
||||
}
|
||||
|
||||
bool IsAborted() {
|
||||
return aborted;
|
||||
}
|
||||
|
||||
void MarkForDeletion() {
|
||||
deleting = true;
|
||||
}
|
||||
|
||||
bool IsDeleted() {
|
||||
return deleting;
|
||||
}
|
||||
|
||||
void SetEndTime() {
|
||||
if (timeout != 0) {
|
||||
end_time = Libraries::Kernel::sceKernelGetProcessTime() + timeout;
|
||||
}
|
||||
}
|
||||
|
||||
void ClearEndTime() {
|
||||
end_time = 0;
|
||||
}
|
||||
|
||||
u64 GetEndTime() {
|
||||
return end_time;
|
||||
}
|
||||
|
||||
bool IsTimedout() {
|
||||
return timed_out;
|
||||
}
|
||||
|
||||
void CheckTimeout(u64 time) {
|
||||
if (!timed_out && end_time != 0 && end_time < time) {
|
||||
timed_out = true;
|
||||
Abort();
|
||||
}
|
||||
}
|
||||
|
||||
bool IsBusy() {
|
||||
return user_count > 1;
|
||||
}
|
||||
|
||||
private:
|
||||
s32 id{};
|
||||
u32 timeout{};
|
||||
s32 user_count{};
|
||||
bool aborted{};
|
||||
bool deleting{};
|
||||
bool timed_out{};
|
||||
u64 end_time{};
|
||||
};
|
||||
|
||||
class PushEventFilter {
|
||||
public:
|
||||
PushEventFilter(s32 new_id, const char* service_name, OrbisNpServiceLabel service_label,
|
||||
bool is_internal)
|
||||
: id(new_id), np_service_name(service_name ? service_name : ""),
|
||||
np_service_label(service_label), internal(is_internal) {}
|
||||
|
||||
s32 Initialize(PushEventHandle* handle,
|
||||
const OrbisNpWebApi2PushEventFilterParameter* filter_param,
|
||||
u64 filter_param_num);
|
||||
|
||||
s32 GetId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
private:
|
||||
s32 id{};
|
||||
OrbisNpServiceLabel np_service_label{};
|
||||
bool internal{};
|
||||
std::vector<OrbisNpWebApi2PushEventFilterParameter> filter_params{};
|
||||
std::vector<std::vector<OrbisNpWebApi2PushEventExtdDataKey>> data_key_copy_storage{};
|
||||
std::string np_service_name{};
|
||||
};
|
||||
|
||||
struct PushEventCallback {
|
||||
s32 id;
|
||||
s32 filter_id;
|
||||
OrbisNpWebApi2PushEventCallback cb_func;
|
||||
void* user_arg;
|
||||
bool is_busy;
|
||||
};
|
||||
|
||||
class PushEventPushContext {
|
||||
public:
|
||||
PushEventPushContext(u32 new_timeout, UserContext* user_ctx)
|
||||
: timeout(new_timeout), parent_user_ctx(user_ctx) {}
|
||||
|
||||
void Initialize();
|
||||
|
||||
OrbisNpWebApi2PushEventPushContextId* GetId() {
|
||||
return &id;
|
||||
}
|
||||
|
||||
// Returns the actual numerical id currently stored in id.
|
||||
s64 GetFakeId() {
|
||||
s64 fake_id{};
|
||||
std::memcpy(&fake_id, &id, sizeof(s64));
|
||||
return fake_id;
|
||||
}
|
||||
|
||||
void Start() {
|
||||
started = true;
|
||||
}
|
||||
|
||||
void SetState(s32 new_state) {
|
||||
state = new_state;
|
||||
}
|
||||
|
||||
bool CallbackRunning() {
|
||||
return state == 2;
|
||||
}
|
||||
|
||||
private:
|
||||
s32 state{};
|
||||
u32 timeout{};
|
||||
UserContext* parent_user_ctx{};
|
||||
u64 end_time{};
|
||||
u64 start_time{};
|
||||
OrbisNpWebApi2PushEventPushContextId id{};
|
||||
bool started{};
|
||||
};
|
||||
|
||||
struct PushEventPushContextCallback {
|
||||
s32 id;
|
||||
s32 filter_id;
|
||||
OrbisNpWebApi2PushEventPushContextCallback cb_func;
|
||||
void* user_arg;
|
||||
bool is_busy;
|
||||
};
|
||||
|
||||
}; // namespace Libraries::Np::NpWebApi2
|
||||
Loading…
Reference in New Issue
Block a user