mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-07-09 17:25:37 -06:00
sceNpWebApi2SendRequest
This commit is contained in:
parent
2fd87eac6d
commit
248781ce5f
@ -18,7 +18,8 @@ s32 PS4_SYSV_ABI sceHttp2AddCookie() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2AddRequestHeader() {
|
||||
s32 PS4_SYSV_ABI sceHttp2AddRequestHeader(s32 template_or_req_id, const char* name,
|
||||
const char* value, u32 mode) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
@ -48,12 +49,13 @@ s32 PS4_SYSV_ABI sceHttp2CreateCookieBox() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2CreateRequestWithURL() {
|
||||
s32 PS4_SYSV_ABI sceHttp2CreateRequestWithURL(s32 tmpl_id, const char* method, const char* url,
|
||||
u64 content_length) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2CreateTemplate(s32 ctx_id, char* user_agent, s32 http_ver,
|
||||
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");
|
||||
return ORBIS_OK;
|
||||
@ -74,7 +76,7 @@ s32 PS4_SYSV_ABI sceHttp2DeleteTemplate() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2GetAllResponseHeaders() {
|
||||
s32 PS4_SYSV_ABI sceHttp2GetAllResponseHeaders(s32 req_id, char** header, u64* header_size) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
@ -114,7 +116,7 @@ s32 PS4_SYSV_ABI sceHttp2GetResponseContentLength() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2GetStatusCode() {
|
||||
s32 PS4_SYSV_ABI sceHttp2GetStatusCode(s32 request_id, s32* status_code) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
@ -145,7 +147,7 @@ s32 PS4_SYSV_ABI sceHttp2RemoveRequestHeader() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2SendRequest() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SendRequest(s32 req_id, const void* data, u64 size) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
@ -236,7 +238,7 @@ s32 PS4_SYSV_ABI sceHttp2SetRedirectCallback() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2SetRequestContentLength() {
|
||||
s32 PS4_SYSV_ABI sceHttp2SetRequestContentLength(s32 req_id, u64 content_length) {
|
||||
LOG_ERROR(Lib_Http2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
@ -29,19 +29,21 @@ using OrbisHttp2PreSendCallback = PS4_SYSV_ABI s32 (*)(s32 request_id, s32 ssl_i
|
||||
|
||||
s32 PS4_SYSV_ABI sceHttp2AbortRequest();
|
||||
s32 PS4_SYSV_ABI sceHttp2AddCookie();
|
||||
s32 PS4_SYSV_ABI sceHttp2AddRequestHeader();
|
||||
s32 PS4_SYSV_ABI sceHttp2AddRequestHeader(s32 template_or_req_id, const char* name,
|
||||
const char* value, u32 mode);
|
||||
s32 PS4_SYSV_ABI sceHttp2AuthCacheFlush();
|
||||
s32 PS4_SYSV_ABI sceHttp2CookieExport();
|
||||
s32 PS4_SYSV_ABI sceHttp2CookieFlush();
|
||||
s32 PS4_SYSV_ABI sceHttp2CookieImport();
|
||||
s32 PS4_SYSV_ABI sceHttp2CreateCookieBox();
|
||||
s32 PS4_SYSV_ABI sceHttp2CreateRequestWithURL();
|
||||
s32 PS4_SYSV_ABI sceHttp2CreateTemplate(s32 ctx_id, char* user_agent, s32 http_ver,
|
||||
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 sceHttp2DeleteCookieBox();
|
||||
s32 PS4_SYSV_ABI sceHttp2DeleteRequest();
|
||||
s32 PS4_SYSV_ABI sceHttp2DeleteTemplate();
|
||||
s32 PS4_SYSV_ABI sceHttp2GetAllResponseHeaders();
|
||||
s32 PS4_SYSV_ABI sceHttp2GetAllResponseHeaders(s32 req_id, char** header, u64* header_size);
|
||||
s32 PS4_SYSV_ABI sceHttp2GetAuthEnabled();
|
||||
s32 PS4_SYSV_ABI sceHttp2GetAutoRedirect();
|
||||
s32 PS4_SYSV_ABI sceHttp2GetCookie();
|
||||
@ -49,13 +51,13 @@ s32 PS4_SYSV_ABI sceHttp2GetCookieBox();
|
||||
s32 PS4_SYSV_ABI sceHttp2GetCookieStats();
|
||||
s32 PS4_SYSV_ABI sceHttp2GetMemoryPoolStats();
|
||||
s32 PS4_SYSV_ABI sceHttp2GetResponseContentLength();
|
||||
s32 PS4_SYSV_ABI sceHttp2GetStatusCode();
|
||||
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 PS4_SYSV_ABI sceHttp2ReadDataAsync();
|
||||
s32 PS4_SYSV_ABI sceHttp2RedirectCacheFlush();
|
||||
s32 PS4_SYSV_ABI sceHttp2RemoveRequestHeader();
|
||||
s32 PS4_SYSV_ABI sceHttp2SendRequest();
|
||||
s32 PS4_SYSV_ABI sceHttp2SendRequest(s32 req_id, const void* data, u64 size);
|
||||
s32 PS4_SYSV_ABI sceHttp2SendRequestAsync();
|
||||
s32 PS4_SYSV_ABI sceHttp2SetAuthEnabled();
|
||||
s32 PS4_SYSV_ABI sceHttp2SetAuthInfoCallback();
|
||||
@ -74,7 +76,7 @@ s32 PS4_SYSV_ABI sceHttp2SetPreSendCallback(s32 template_id, OrbisHttp2PreSendCa
|
||||
void* user_arg);
|
||||
s32 PS4_SYSV_ABI sceHttp2SetRecvTimeOut();
|
||||
s32 PS4_SYSV_ABI sceHttp2SetRedirectCallback();
|
||||
s32 PS4_SYSV_ABI sceHttp2SetRequestContentLength();
|
||||
s32 PS4_SYSV_ABI sceHttp2SetRequestContentLength(s32 req_id, u64 content_length);
|
||||
s32 PS4_SYSV_ABI sceHttp2SetResolveRetry();
|
||||
s32 PS4_SYSV_ABI sceHttp2SetResolveTimeOut();
|
||||
s32 PS4_SYSV_ABI sceHttp2SetSendTimeOut();
|
||||
|
||||
@ -277,18 +277,24 @@ s32 PS4_SYSV_ABI sceNpWebApi2ReadData(s64 request_id, void* data, u64 size) {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNpWebApi2SendMultipartRequest() {
|
||||
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
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_INFO(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() {
|
||||
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
|
||||
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() {
|
||||
|
||||
@ -42,5 +42,13 @@ struct OrbisNpWebApi2ContentParameter {
|
||||
u8 reserved[16];
|
||||
};
|
||||
|
||||
struct OrbisNpWebApi2ResponseInformationOption {
|
||||
s32 http_status;
|
||||
s32 reserved;
|
||||
char* error_object;
|
||||
u64 error_object_size;
|
||||
u64 response_data_size;
|
||||
};
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Np::NpWebApi2
|
||||
@ -5,6 +5,7 @@
|
||||
#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 {
|
||||
@ -144,7 +145,7 @@ Request* UserContext::GetRequest(s64 request_id) {
|
||||
return request;
|
||||
}
|
||||
|
||||
bool IsInternalHeader(const char* header_name) {
|
||||
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); });
|
||||
@ -177,4 +178,98 @@ s32 Request::AddHttpRequestHeader(const char* field_name, const char* field_valu
|
||||
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;
|
||||
}
|
||||
|
||||
}; // namespace Libraries::Np::NpWebApi2
|
||||
@ -1,6 +1,7 @@
|
||||
// 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_push_event.h"
|
||||
#include "core/libraries/system/userservice.h"
|
||||
@ -137,6 +138,10 @@ public:
|
||||
return user_id;
|
||||
}
|
||||
|
||||
s32 GetHttpTemplateId() {
|
||||
return http_template_id;
|
||||
}
|
||||
|
||||
s32 Initialize();
|
||||
|
||||
s32 CreateRequest(const char* api_group, const char* path, const char* method,
|
||||
@ -164,7 +169,8 @@ public:
|
||||
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) {}
|
||||
multipart_supported(multipart), content_type(content_parameter->content_type),
|
||||
content_length(content_parameter->content_length) {}
|
||||
|
||||
void Lock() {
|
||||
parent_ctx->Lock();
|
||||
@ -190,23 +196,84 @@ public:
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
private:
|
||||
s64 id{};
|
||||
u64 content_length{};
|
||||
char* http_response_headers{};
|
||||
u64 http_response_header_size{};
|
||||
s32 user_count{};
|
||||
s32 http_request_id{};
|
||||
s32 timeout{};
|
||||
s32 sent_data{};
|
||||
bool multipart_supported{};
|
||||
bool sent{};
|
||||
bool aborted{};
|
||||
bool expired{};
|
||||
u64 end_time{};
|
||||
LibraryContext* parent_ctx{};
|
||||
std::string api_group{};
|
||||
std::string path{};
|
||||
std::string method{};
|
||||
std::string content_type{};
|
||||
bool multipart_supported{};
|
||||
bool sent{};
|
||||
|
||||
struct HttpRequestHeader {
|
||||
std::string field_name;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/emulator_settings.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"
|
||||
@ -185,4 +186,145 @@ s32 addHttpRequestHeader(s64 request_id, const char* field_name, const char* fie
|
||||
return result;
|
||||
}
|
||||
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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;
|
||||
}
|
||||
|
||||
}; // namespace Libraries::Np::NpWebApi2
|
||||
@ -1,6 +1,7 @@
|
||||
// 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 {
|
||||
@ -12,4 +13,6 @@ s32 createRequest(s32 user_ctx_id, const char* api_group, const char* path, cons
|
||||
const OrbisNpWebApi2ContentParameter* content_parameter, bool multipart,
|
||||
s64* request_id);
|
||||
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);
|
||||
}; // namespace Libraries::Np::NpWebApi2
|
||||
Loading…
Reference in New Issue
Block a user