sceNpWebApi2CreateRequest, sceNpWebApi2CreateMultipartRequest

This commit is contained in:
Stephen Miller 2026-06-28 12:27:51 -05:00
parent 8f65dca21c
commit 8f04464ada
6 changed files with 164 additions and 10 deletions

View File

@ -36,14 +36,54 @@ 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 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() {
LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called");
return ORBIS_OK;
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,

View File

@ -15,7 +15,7 @@ struct OrbisNpWebApi2IntInitializeArgs {
s32 lib_http_ctx_id;
s32 reserved;
u64 pool_size;
char* name;
const char* name;
u64 struct_size;
};
@ -23,7 +23,7 @@ struct OrbisNpWebApi2IntInitialize2Args {
s32 lib_http_ctx_id;
s32 reserved;
u64 pool_size;
char* name;
const char* name;
u32 push_config_group;
s32 reserved2;
u64 struct_size;
@ -36,5 +36,11 @@ struct OrbisNpWebApi2MemoryPoolStats {
s32 reserved;
};
struct OrbisNpWebApi2ContentParameter {
u64 content_length;
const char* content_type;
u8 reserved[16];
};
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Np::NpWebApi2

View File

@ -10,6 +10,7 @@
namespace Libraries::Np::NpWebApi2 {
s32 g_current_user_context_id{};
s64 g_current_request_id{};
s32 LibraryContext::CreateUserContext(Libraries::UserService::OrbisUserServiceUserId user_id) {
if (this->user_contexts.size() >= 0x10000) {
@ -104,4 +105,30 @@ s32 UserContext::Initialize() {
return result;
}
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_user_context_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;
}
}; // namespace Libraries::Np::NpWebApi2

View File

@ -82,7 +82,7 @@ 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) {};
: parent_ctx(parent), id(user_ctx_id), user_id(user_id) {}
void Lock() {
parent_ctx->Lock();
@ -114,6 +114,10 @@ public:
s32 Initialize();
s32 CreateRequest(const char* api_group, const char* path, const char* method,
const OrbisNpWebApi2ContentParameter* content_parameter, bool multipart,
Request** request);
private:
s32 id{};
Libraries::UserService::OrbisUserServiceUserId user_id{};
@ -121,8 +125,37 @@ private:
s32 http_template_id{};
LibraryContext* parent_ctx{};
std::string user_agent{};
std::map<s64, Request*> requests{};
};
class Request {};
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) {}
s64 GetId() {
return id;
}
s32 Initialize();
private:
s64 id{};
s32 user_count{};
s32 http_request_id{};
LibraryContext* parent_ctx{};
std::string api_group{};
std::string path{};
std::string method{};
std::string content_type{};
bool multipart_supported{};
};
}; // namespace Libraries::Np::NpWebApi2

View File

@ -78,6 +78,7 @@ s32 createUserContext(s32 lib_ctx_id, Libraries::UserService::OrbisUserServiceUs
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;
}
@ -101,4 +102,48 @@ s32 createUserContext(s32 lib_ctx_id, Libraries::UserService::OrbisUserServiceUs
return user_ctx_id;
}
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;
}
}; // namespace Libraries::Np::NpWebApi2

View File

@ -8,4 +8,7 @@ namespace Libraries::Np::NpWebApi2 {
s32 createLibraryContext(s32 http_ctx_id, u64 pool_size, const char* name);
s32 getMemoryPoolStats(s32 lib_ctx_id, OrbisNpWebApi2MemoryPoolStats* stats);
s32 createUserContext(s32 lib_ctx_id, Libraries::UserService::OrbisUserServiceUserId user_id);
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);
}; // namespace Libraries::Np::NpWebApi2