diff --git a/src/core/libraries/np/np_web_api2/np_web_api2.cpp b/src/core/libraries/np/np_web_api2/np_web_api2.cpp index 74758aef8..110a5e79c 100644 --- a/src/core/libraries/np/np_web_api2/np_web_api2.cpp +++ b/src/core/libraries/np/np_web_api2/np_web_api2.cpp @@ -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, diff --git a/src/core/libraries/np/np_web_api2/np_web_api2.h b/src/core/libraries/np/np_web_api2/np_web_api2.h index 1e970d08e..d016001a2 100644 --- a/src/core/libraries/np/np_web_api2/np_web_api2.h +++ b/src/core/libraries/np/np_web_api2/np_web_api2.h @@ -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 \ No newline at end of file diff --git a/src/core/libraries/np/np_web_api2/np_web_api2_context.cpp b/src/core/libraries/np/np_web_api2/np_web_api2_context.cpp index 37a54740f..a67a4d2f6 100644 --- a/src/core/libraries/np/np_web_api2/np_web_api2_context.cpp +++ b/src/core/libraries/np/np_web_api2/np_web_api2_context.cpp @@ -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(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 \ No newline at end of file diff --git a/src/core/libraries/np/np_web_api2/np_web_api2_context.h b/src/core/libraries/np/np_web_api2/np_web_api2_context.h index 0a6cb3bec..2f5ced338 100644 --- a/src/core/libraries/np/np_web_api2/np_web_api2_context.h +++ b/src/core/libraries/np/np_web_api2/np_web_api2_context.h @@ -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 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 \ No newline at end of file diff --git a/src/core/libraries/np/np_web_api2/np_web_api2_internal.cpp b/src/core/libraries/np/np_web_api2/np_web_api2_internal.cpp index 3c4ffc297..cbd265194 100644 --- a/src/core/libraries/np/np_web_api2/np_web_api2_internal.cpp +++ b/src/core/libraries/np/np_web_api2/np_web_api2_internal.cpp @@ -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 \ No newline at end of file diff --git a/src/core/libraries/np/np_web_api2/np_web_api2_internal.h b/src/core/libraries/np/np_web_api2/np_web_api2_internal.h index 672f18856..0274288d6 100644 --- a/src/core/libraries/np/np_web_api2/np_web_api2_internal.h +++ b/src/core/libraries/np/np_web_api2/np_web_api2_internal.h @@ -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 \ No newline at end of file