sceNpWebApi2AbortRequest, sceNpWebApi2DeleteRequest

This commit is contained in:
Stephen Miller 2026-06-29 09:48:41 -05:00
parent 248781ce5f
commit 3f7af4421b
7 changed files with 184 additions and 16 deletions

View File

@ -8,7 +8,7 @@
namespace Libraries::Http2 {
s32 PS4_SYSV_ABI sceHttp2AbortRequest() {
s32 PS4_SYSV_ABI sceHttp2AbortRequest(s32 req_id) {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
@ -66,7 +66,7 @@ s32 PS4_SYSV_ABI sceHttp2DeleteCookieBox() {
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceHttp2DeleteRequest() {
s32 PS4_SYSV_ABI sceHttp2DeleteRequest(s32 req_id) {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}

View File

@ -27,7 +27,7 @@ using OrbisHttp2PreSendCallback = PS4_SYSV_ABI s32 (*)(s32 request_id, s32 ssl_i
OrbisHttp2PreSendCallbackData* data,
void* user_arg);
s32 PS4_SYSV_ABI sceHttp2AbortRequest();
s32 PS4_SYSV_ABI sceHttp2AbortRequest(s32 req_id);
s32 PS4_SYSV_ABI sceHttp2AddCookie();
s32 PS4_SYSV_ABI sceHttp2AddRequestHeader(s32 template_or_req_id, const char* name,
const char* value, u32 mode);
@ -41,7 +41,7 @@ s32 PS4_SYSV_ABI sceHttp2CreateRequestWithURL(s32 tmpl_id, const char* method, c
s32 PS4_SYSV_ABI sceHttp2CreateTemplate(s32 ctx_id, const char* user_agent, s32 http_ver,
s32 auto_proxy_conf);
s32 PS4_SYSV_ABI sceHttp2DeleteCookieBox();
s32 PS4_SYSV_ABI sceHttp2DeleteRequest();
s32 PS4_SYSV_ABI sceHttp2DeleteRequest(s32 req_id);
s32 PS4_SYSV_ABI sceHttp2DeleteTemplate();
s32 PS4_SYSV_ABI sceHttp2GetAllResponseHeaders(s32 req_id, char** header, u64* header_size);
s32 PS4_SYSV_ABI sceHttp2GetAuthEnabled();

View File

@ -13,8 +13,8 @@
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;
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,
@ -111,8 +111,8 @@ s32 PS4_SYSV_ABI sceNpWebApi2CreateUserContext(s32 lib_ctx_id,
}
s32 PS4_SYSV_ABI sceNpWebApi2DeleteRequest(s64 request_id) {
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called, request_id = {:#x}", request_id);
return ORBIS_OK;
LOG_INFO(Lib_NpWebApi2, "called, request_id = {:#x}", request_id);
return deleteRequest(request_id);
}
s32 PS4_SYSV_ABI sceNpWebApi2DeleteUserContext(s32 user_ctx_id) {
@ -285,8 +285,8 @@ sceNpWebApi2SendMultipartRequest(s64 request_id, s32 part_index, void* data, u64
return ORBIS_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
}
LOG_INFO(Lib_NpWebApi2, "called, request_id = {:#x}, part_index = {}, data_size = {:#x}",
request_id, part_index, data_size);
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);
}

View File

@ -272,4 +272,44 @@ s32 Request::GetAllHttpResponseHeaders() {
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

View File

@ -77,15 +77,17 @@ public:
return type == LibraryContextType::Presence;
}
void RemoveUserContext(s32 user_ctx_id) {
std::scoped_lock lk{lock};
if (user_contexts.contains(user_ctx_id)) {
user_contexts.erase(user_ctx_id);
}
}
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};
user_contexts.erase(user_ctx_id);
}
private:
s32 id{};
s32 http_ctx_id{};
@ -142,8 +144,15 @@ public:
return http_template_id;
}
s32 Initialize();
void RemoveRequest(s64 request_id) {
parent_ctx->Lock();
if (requests.contains(request_id)) {
requests.erase(request_id);
}
parent_ctx->Unlock();
}
s32 Initialize();
s32 CreateRequest(const char* api_group, const char* path, const char* method,
const OrbisNpWebApi2ContentParameter* content_parameter, bool multipart,
Request** request);
@ -250,10 +259,32 @@ public:
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);
s32 CreateHttpRequest(s32 http_template_id, const char* url);
s32 SendHttpRequest(void* data, u64 data_size);
s32 GetAllHttpResponseHeaders();
s32 Abort();
s32 Delete(s32* http_request_id);
private:
s64 id{};
@ -264,10 +295,12 @@ private:
s32 http_request_id{};
s32 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{};

View File

@ -3,6 +3,7 @@
#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_web_api2/np_web_api2_context.h"
@ -247,6 +248,7 @@ s32 sendRequest(s64 request_id, s32 part_index, void* data, u64 data_size,
}
request->Lock();
request->SetState(0);
s32 result = checkRequestStatus(request, user_ctx, lib_ctx);
request->Unlock();
if (result != 0) {
@ -279,6 +281,7 @@ s32 sendRequest(s64 request_id, s32 part_index, void* data, u64 data_size,
}
request->Lock();
request->SetState(3);
result = checkRequestStatus(request, user_ctx, lib_ctx);
request->Unlock();
if (result != 0) {
@ -313,6 +316,7 @@ s32 sendRequest(s64 request_id, s32 part_index, void* data, u64 data_size,
}
request->Lock();
request->SetState(0);
s32 result2 = checkRequestStatus(request, user_ctx, lib_ctx);
request->Unlock();
if (result2 != 0) {
@ -327,4 +331,92 @@ s32 sendRequest(s64 request_id, s32 part_index, void* data, u64 data_size,
return result;
}
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();
Libraries::Http2::sceHttp2DeleteRequest(http_request_id);
return ORBIS_OK;
}
}; // namespace Libraries::Np::NpWebApi2

View File

@ -15,4 +15,7 @@ s32 createRequest(s32 user_ctx_id, const char* api_group, const char* path, cons
s32 addHttpRequestHeader(s64 request_id, const char* field_name, const char* field_value);
s32 sendRequest(s64 request_id, s32 part_index, void* data, u64 data_size,
OrbisNpWebApi2ResponseInformationOption* resp_info_option);
s32 abortRequest(s64 request_id);
s32 deleteRequest(s64 request_id);
}; // namespace Libraries::Np::NpWebApi2