mirror of
https://github.com/PabloMK7/citra
synced 2024-11-15 05:08:23 +00:00
http/soc: Various implementations and fixes (#6828)
This commit is contained in:
parent
baf3ea4beb
commit
970f2284d8
17 changed files with 322 additions and 202 deletions
|
@ -247,6 +247,8 @@ add_library(citra_core STATIC
|
|||
hle/service/cam/cam_s.h
|
||||
hle/service/cam/cam_u.cpp
|
||||
hle/service/cam/cam_u.h
|
||||
hle/service/cam/y2r_u.cpp
|
||||
hle/service/cam/y2r_u.h
|
||||
hle/service/cecd/cecd.cpp
|
||||
hle/service/cecd/cecd.h
|
||||
hle/service/cecd/cecd_ndm.cpp
|
||||
|
@ -279,8 +281,8 @@ add_library(citra_core STATIC
|
|||
hle/service/dlp/dlp_srvr.h
|
||||
hle/service/dsp/dsp_dsp.cpp
|
||||
hle/service/dsp/dsp_dsp.h
|
||||
hle/service/err_f.cpp
|
||||
hle/service/err_f.h
|
||||
hle/service/err/err_f.cpp
|
||||
hle/service/err/err_f.h
|
||||
hle/service/frd/frd.cpp
|
||||
hle/service/frd/frd.h
|
||||
hle/service/frd/frd_a.cpp
|
||||
|
@ -307,8 +309,8 @@ add_library(citra_core STATIC
|
|||
hle/service/hid/hid_spvr.h
|
||||
hle/service/hid/hid_user.cpp
|
||||
hle/service/hid/hid_user.h
|
||||
hle/service/http_c.cpp
|
||||
hle/service/http_c.h
|
||||
hle/service/http/http_c.cpp
|
||||
hle/service/http/http_c.h
|
||||
hle/service/ir/extra_hid.cpp
|
||||
hle/service/ir/extra_hid.h
|
||||
hle/service/ir/ir.cpp
|
||||
|
@ -323,8 +325,8 @@ add_library(citra_core STATIC
|
|||
hle/service/ldr_ro/cro_helper.h
|
||||
hle/service/ldr_ro/ldr_ro.cpp
|
||||
hle/service/ldr_ro/ldr_ro.h
|
||||
hle/service/mic_u.cpp
|
||||
hle/service/mic_u.h
|
||||
hle/service/mic/mic_u.cpp
|
||||
hle/service/mic/mic_u.h
|
||||
hle/service/mvd/mvd.cpp
|
||||
hle/service/mvd/mvd.h
|
||||
hle/service/mvd/mvd_std.cpp
|
||||
|
@ -421,12 +423,10 @@ add_library(citra_core STATIC
|
|||
hle/service/sm/sm.h
|
||||
hle/service/sm/srv.cpp
|
||||
hle/service/sm/srv.h
|
||||
hle/service/soc_u.cpp
|
||||
hle/service/soc_u.h
|
||||
hle/service/ssl_c.cpp
|
||||
hle/service/ssl_c.h
|
||||
hle/service/y2r_u.cpp
|
||||
hle/service/y2r_u.h
|
||||
hle/service/soc/soc_u.cpp
|
||||
hle/service/soc/soc_u.h
|
||||
hle/service/ssl/ssl_c.cpp
|
||||
hle/service/ssl/ssl_c.h
|
||||
hw/aes/arithmetic128.cpp
|
||||
hw/aes/arithmetic128.h
|
||||
hw/aes/ccm.cpp
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include "core/hle/service/fs/archive.h"
|
||||
#include "core/hle/service/gsp/gsp.h"
|
||||
#include "core/hle/service/ir/ir_rst.h"
|
||||
#include "core/hle/service/mic_u.h"
|
||||
#include "core/hle/service/mic/mic_u.h"
|
||||
#include "core/hle/service/plgldr/plgldr.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "core/hle/service/ac/ac.h"
|
||||
#include "core/hle/service/ac/ac_i.h"
|
||||
#include "core/hle/service/ac/ac_u.h"
|
||||
#include "core/hle/service/soc_u.h"
|
||||
#include "core/hle/service/soc/soc_u.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Service::AC {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/service/y2r_u.h"
|
||||
#include "core/hle/service/cam/y2r_u.h"
|
||||
#include "core/hw/y2r.h"
|
||||
|
||||
SERVICE_CONSTRUCT_IMPL(Service::Y2R::Y2R_U)
|
|
@ -14,7 +14,7 @@
|
|||
#include "core/hle/ipc.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/err_f.h"
|
||||
#include "core/hle/service/err/err_f.h"
|
||||
#undef exception_info // We use 'exception_info' as a plain identifier, but MSVC defines this in one
|
||||
// of its many headers.
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
#include "core/hle/kernel/ipc.h"
|
||||
#include "core/hle/romfs.h"
|
||||
#include "core/hle/service/fs/archive.h"
|
||||
#include "core/hle/service/http_c.h"
|
||||
#include "core/hle/service/http/http_c.h"
|
||||
#include "core/hw/aes/key.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::HTTP::HTTP_C)
|
||||
|
@ -55,11 +55,31 @@ const ResultCode ERROR_WRONG_CERT_HANDLE = // 0xD8A0A0C9
|
|||
const ResultCode ERROR_CERT_ALREADY_SET = // 0xD8A0A03D
|
||||
ResultCode(61, ErrorModule::HTTP, ErrorSummary::InvalidState, ErrorLevel::Permanent);
|
||||
|
||||
static std::pair<std::string, std::string> SplitUrl(const std::string& url) {
|
||||
const std::string prefix = "://";
|
||||
const auto scheme_end = url.find(prefix);
|
||||
const auto prefix_end = scheme_end == std::string::npos ? 0 : scheme_end + prefix.length();
|
||||
|
||||
const auto path_index = url.find("/", prefix_end);
|
||||
std::string host;
|
||||
std::string path;
|
||||
if (path_index == std::string::npos) {
|
||||
// If no path is specified after the host, set it to "/"
|
||||
host = url;
|
||||
path = "/";
|
||||
} else {
|
||||
host = url.substr(0, path_index);
|
||||
path = url.substr(path_index);
|
||||
}
|
||||
return std::make_pair(host, path);
|
||||
}
|
||||
|
||||
void Context::MakeRequest() {
|
||||
ASSERT(state == RequestState::NotStarted);
|
||||
|
||||
#ifdef ENABLE_WEB_SERVICE
|
||||
std::unique_ptr<httplib::Client> client = std::make_unique<httplib::Client>(url.c_str());
|
||||
const auto& [host, path] = SplitUrl(url);
|
||||
const auto client = std::make_unique<httplib::Client>(host);
|
||||
SSL_CTX* ctx = client->ssl_context();
|
||||
if (ctx) {
|
||||
if (auto client_cert = ssl_config.client_cert_ctx.lock()) {
|
||||
|
@ -87,7 +107,7 @@ void Context::MakeRequest() {
|
|||
httplib::Request request;
|
||||
httplib::Error error;
|
||||
request.method = request_method_strings.at(method);
|
||||
request.path = url;
|
||||
request.path = path;
|
||||
// TODO(B3N30): Add post data body
|
||||
request.progress = [this](u64 current, u64 total) -> bool {
|
||||
// TODO(B3N30): Is there a state that shows response header are available
|
||||
|
@ -101,7 +121,7 @@ void Context::MakeRequest() {
|
|||
}
|
||||
|
||||
if (!client->send(request, response, error)) {
|
||||
LOG_ERROR(Service_HTTP, "Request failed: {}", error);
|
||||
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
||||
state = RequestState::TimedOut;
|
||||
} else {
|
||||
LOG_DEBUG(Service_HTTP, "Request successful");
|
||||
|
@ -185,33 +205,7 @@ void HTTP_C::BeginRequest(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_WARNING(Service_HTTP, "(STUBBED) called, context_id={}", context_handle);
|
||||
|
||||
auto* session_data = GetSessionData(ctx.Session());
|
||||
ASSERT(session_data);
|
||||
|
||||
if (!session_data->initialized) {
|
||||
LOG_ERROR(Service_HTTP, "Tried to make a request on an uninitialized session");
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// This command can only be called with a bound context
|
||||
if (!session_data->current_http_context) {
|
||||
LOG_ERROR(Service_HTTP, "Tried to make a request without a bound context");
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ResultCode(ErrorDescription::NotImplemented, ErrorModule::HTTP,
|
||||
ErrorSummary::Internal, ErrorLevel::Permanent));
|
||||
return;
|
||||
}
|
||||
|
||||
if (session_data->current_http_context != context_handle) {
|
||||
LOG_ERROR(
|
||||
Service_HTTP,
|
||||
"Tried to make a request on a mismatched session input context={} session context={}",
|
||||
context_handle, *session_data->current_http_context);
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
if (!PerformStateChecks(ctx, rp, context_handle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -238,33 +232,7 @@ void HTTP_C::BeginRequestAsync(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_WARNING(Service_HTTP, "(STUBBED) called, context_id={}", context_handle);
|
||||
|
||||
auto* session_data = GetSessionData(ctx.Session());
|
||||
ASSERT(session_data);
|
||||
|
||||
if (!session_data->initialized) {
|
||||
LOG_ERROR(Service_HTTP, "Tried to make a request on an uninitialized session");
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// This command can only be called with a bound context
|
||||
if (!session_data->current_http_context) {
|
||||
LOG_ERROR(Service_HTTP, "Tried to make a request without a bound context");
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ResultCode(ErrorDescription::NotImplemented, ErrorModule::HTTP,
|
||||
ErrorSummary::Internal, ErrorLevel::Permanent));
|
||||
return;
|
||||
}
|
||||
|
||||
if (session_data->current_http_context != context_handle) {
|
||||
LOG_ERROR(
|
||||
Service_HTTP,
|
||||
"Tried to make a request on a mismatched session input context={} session context={}",
|
||||
context_handle, *session_data->current_http_context);
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
if (!PerformStateChecks(ctx, rp, context_handle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -285,6 +253,44 @@ void HTTP_C::BeginRequestAsync(Kernel::HLERequestContext& ctx) {
|
|||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void HTTP_C::ReceiveData(Kernel::HLERequestContext& ctx) {
|
||||
ReceiveDataImpl(ctx, false);
|
||||
}
|
||||
|
||||
void HTTP_C::ReceiveDataTimeout(Kernel::HLERequestContext& ctx) {
|
||||
ReceiveDataImpl(ctx, true);
|
||||
}
|
||||
|
||||
void HTTP_C::ReceiveDataImpl(Kernel::HLERequestContext& ctx, bool timeout) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
const Context::Handle context_handle = rp.Pop<u32>();
|
||||
[[maybe_unused]] const u32 buffer_size = rp.Pop<u32>();
|
||||
u64 timeout_nanos = 0;
|
||||
if (timeout) {
|
||||
timeout_nanos = rp.Pop<u64>();
|
||||
LOG_WARNING(Service_HTTP, "(STUBBED) called, timeout={}", timeout_nanos);
|
||||
} else {
|
||||
LOG_WARNING(Service_HTTP, "(STUBBED) called");
|
||||
}
|
||||
|
||||
if (!PerformStateChecks(ctx, rp, context_handle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto itr = contexts.find(context_handle);
|
||||
ASSERT(itr != contexts.end());
|
||||
|
||||
if (timeout) {
|
||||
itr->second.request_future.wait_for(std::chrono::nanoseconds(timeout_nanos));
|
||||
// TODO (flTobi): Return error on timeout
|
||||
} else {
|
||||
itr->second.request_future.wait();
|
||||
}
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void HTTP_C::CreateContext(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
const u32 url_size = rp.Pop<u32>();
|
||||
|
@ -297,14 +303,8 @@ void HTTP_C::CreateContext(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_DEBUG(Service_HTTP, "called, url_size={}, url={}, method={}", url_size, url, method);
|
||||
|
||||
auto* session_data = GetSessionData(ctx.Session());
|
||||
ASSERT(session_data);
|
||||
|
||||
if (!session_data->initialized) {
|
||||
LOG_ERROR(Service_HTTP, "Tried to create a context on an uninitialized session");
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
rb.PushMappedBuffer(buffer);
|
||||
auto* session_data = EnsureSessionInitialized(ctx, rp);
|
||||
if (!session_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -365,13 +365,8 @@ void HTTP_C::CloseContext(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_WARNING(Service_HTTP, "(STUBBED) called, handle={}", context_handle);
|
||||
|
||||
auto* session_data = GetSessionData(ctx.Session());
|
||||
ASSERT(session_data);
|
||||
|
||||
if (!session_data->initialized) {
|
||||
LOG_ERROR(Service_HTTP, "Tried to close a context on an uninitialized session");
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
auto* session_data = EnsureSessionInitialized(ctx, rp);
|
||||
if (!session_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -416,36 +411,7 @@ void HTTP_C::AddRequestHeader(Kernel::HLERequestContext& ctx) {
|
|||
LOG_DEBUG(Service_HTTP, "called, name={}, value={}, context_handle={}", name, value,
|
||||
context_handle);
|
||||
|
||||
auto* session_data = GetSessionData(ctx.Session());
|
||||
ASSERT(session_data);
|
||||
|
||||
if (!session_data->initialized) {
|
||||
LOG_ERROR(Service_HTTP, "Tried to add a request header on an uninitialized session");
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
rb.PushMappedBuffer(value_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
// This command can only be called with a bound context
|
||||
if (!session_data->current_http_context) {
|
||||
LOG_ERROR(Service_HTTP, "Command called without a bound context");
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||
rb.Push(ResultCode(ErrorDescription::NotImplemented, ErrorModule::HTTP,
|
||||
ErrorSummary::Internal, ErrorLevel::Permanent));
|
||||
rb.PushMappedBuffer(value_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (session_data->current_http_context != context_handle) {
|
||||
LOG_ERROR(Service_HTTP,
|
||||
"Tried to add a request header on a mismatched session input context={} session "
|
||||
"context={}",
|
||||
context_handle, *session_data->current_http_context);
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
rb.PushMappedBuffer(value_buffer);
|
||||
if (!PerformStateChecks(ctx, rp, context_handle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -492,36 +458,7 @@ void HTTP_C::AddPostDataAscii(Kernel::HLERequestContext& ctx) {
|
|||
LOG_DEBUG(Service_HTTP, "called, name={}, value={}, context_handle={}", name, value,
|
||||
context_handle);
|
||||
|
||||
auto* session_data = GetSessionData(ctx.Session());
|
||||
ASSERT(session_data);
|
||||
|
||||
if (!session_data->initialized) {
|
||||
LOG_ERROR(Service_HTTP, "Tried to add post data on an uninitialized session");
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
rb.PushMappedBuffer(value_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
// This command can only be called with a bound context
|
||||
if (!session_data->current_http_context) {
|
||||
LOG_ERROR(Service_HTTP, "Command called without a bound context");
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||
rb.Push(ResultCode(ErrorDescription::NotImplemented, ErrorModule::HTTP,
|
||||
ErrorSummary::Internal, ErrorLevel::Permanent));
|
||||
rb.PushMappedBuffer(value_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (session_data->current_http_context != context_handle) {
|
||||
LOG_ERROR(Service_HTTP,
|
||||
"Tried to add post data on a mismatched session input context={} session "
|
||||
"context={}",
|
||||
context_handle, *session_data->current_http_context);
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
rb.PushMappedBuffer(value_buffer);
|
||||
if (!PerformStateChecks(ctx, rp, context_handle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -549,6 +486,46 @@ void HTTP_C::AddPostDataAscii(Kernel::HLERequestContext& ctx) {
|
|||
rb.PushMappedBuffer(value_buffer);
|
||||
}
|
||||
|
||||
void HTTP_C::GetResponseStatusCode(Kernel::HLERequestContext& ctx) {
|
||||
GetResponseStatusCodeImpl(ctx, false);
|
||||
}
|
||||
|
||||
void HTTP_C::GetResponseStatusCodeTimeout(Kernel::HLERequestContext& ctx) {
|
||||
GetResponseStatusCodeImpl(ctx, true);
|
||||
}
|
||||
|
||||
void HTTP_C::GetResponseStatusCodeImpl(Kernel::HLERequestContext& ctx, bool timeout) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
const Context::Handle context_handle = rp.Pop<u32>();
|
||||
u64 timeout_nanos = 0;
|
||||
if (timeout) {
|
||||
timeout_nanos = rp.Pop<u64>();
|
||||
LOG_INFO(Service_HTTP, "called, timeout={}", timeout_nanos);
|
||||
} else {
|
||||
LOG_INFO(Service_HTTP, "called");
|
||||
}
|
||||
|
||||
if (!PerformStateChecks(ctx, rp, context_handle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto itr = contexts.find(context_handle);
|
||||
ASSERT(itr != contexts.end());
|
||||
|
||||
if (timeout) {
|
||||
itr->second.request_future.wait_for(std::chrono::nanoseconds(timeout));
|
||||
// TODO (flTobi): Return error on timeout
|
||||
} else {
|
||||
itr->second.request_future.wait();
|
||||
}
|
||||
|
||||
const u32 response_code = itr->second.response.status;
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(response_code);
|
||||
}
|
||||
|
||||
void HTTP_C::SetClientCertContext(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
const u32 context_handle = rp.Pop<u32>();
|
||||
|
@ -557,32 +534,7 @@ void HTTP_C::SetClientCertContext(Kernel::HLERequestContext& ctx) {
|
|||
LOG_DEBUG(Service_HTTP, "called with context_handle={} client_cert_handle={}", context_handle,
|
||||
client_cert_handle);
|
||||
|
||||
auto* session_data = GetSessionData(ctx.Session());
|
||||
ASSERT(session_data);
|
||||
|
||||
if (!session_data->initialized) {
|
||||
LOG_ERROR(Service_HTTP, "Tried to set client cert on an uninitialized session");
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// This command can only be called with a bound context
|
||||
if (!session_data->current_http_context) {
|
||||
LOG_ERROR(Service_HTTP, "Tried to set client cert without a bound context");
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ResultCode(ErrorDescription::NotImplemented, ErrorModule::HTTP,
|
||||
ErrorSummary::Internal, ErrorLevel::Permanent));
|
||||
return;
|
||||
}
|
||||
|
||||
if (session_data->current_http_context != context_handle) {
|
||||
LOG_ERROR(Service_HTTP,
|
||||
"Tried to add set client cert on a mismatched session input context={} session "
|
||||
"context={}",
|
||||
context_handle, *session_data->current_http_context);
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
if (!PerformStateChecks(ctx, rp, context_handle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -683,13 +635,8 @@ void HTTP_C::OpenDefaultClientCertContext(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_DEBUG(Service_HTTP, "called, cert_id={} cert_handle={}", cert_id, client_certs_counter);
|
||||
|
||||
auto* session_data = GetSessionData(ctx.Session());
|
||||
ASSERT(session_data);
|
||||
|
||||
if (!session_data->initialized) {
|
||||
LOG_ERROR(Service_HTTP, "Command called without Initialize");
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
auto* session_data = EnsureSessionInitialized(ctx, rp);
|
||||
if (!session_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -792,6 +739,85 @@ void HTTP_C::Finalize(Kernel::HLERequestContext& ctx) {
|
|||
LOG_WARNING(Service_HTTP, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void HTTP_C::GetDownloadSizeState(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
const Context::Handle context_handle = rp.Pop<u32>();
|
||||
|
||||
LOG_INFO(Service_HTTP, "called");
|
||||
|
||||
const auto* session_data = EnsureSessionInitialized(ctx, rp);
|
||||
if (!session_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto itr = contexts.find(context_handle);
|
||||
ASSERT(itr != contexts.end());
|
||||
|
||||
// On the real console, the current downloaded progress and the total size of the content gets
|
||||
// returned. Since we do not support chunked downloads on the host, always return the content
|
||||
// length if the download is complete and 0 otherwise.
|
||||
u32 content_length = 0;
|
||||
const bool is_complete = itr->second.request_future.wait_for(std::chrono::milliseconds(0)) ==
|
||||
std::future_status::ready;
|
||||
if (is_complete) {
|
||||
const auto& headers = itr->second.response.headers;
|
||||
const auto& it = headers.find("Content-Length");
|
||||
if (it != headers.end()) {
|
||||
content_length = std::stoi(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(content_length);
|
||||
rb.Push(content_length);
|
||||
}
|
||||
|
||||
SessionData* HTTP_C::EnsureSessionInitialized(Kernel::HLERequestContext& ctx,
|
||||
IPC::RequestParser rp) {
|
||||
auto* session_data = GetSessionData(ctx.Session());
|
||||
ASSERT(session_data);
|
||||
|
||||
if (!session_data->initialized) {
|
||||
LOG_ERROR(Service_HTTP, "Tried to make a request on an uninitialized session");
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return session_data;
|
||||
}
|
||||
|
||||
bool HTTP_C::PerformStateChecks(Kernel::HLERequestContext& ctx, IPC::RequestParser rp,
|
||||
Context::Handle context_handle) {
|
||||
const auto* session_data = EnsureSessionInitialized(ctx, rp);
|
||||
if (!session_data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This command can only be called with a bound context
|
||||
if (!session_data->current_http_context) {
|
||||
LOG_ERROR(Service_HTTP, "Tried to make a request without a bound context");
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ResultCode(ErrorDescription::NotImplemented, ErrorModule::HTTP,
|
||||
ErrorSummary::Internal, ErrorLevel::Permanent));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (session_data->current_http_context != context_handle) {
|
||||
LOG_ERROR(
|
||||
Service_HTTP,
|
||||
"Tried to make a request on a mismatched session input context={} session context={}",
|
||||
context_handle, *session_data->current_http_context);
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ERROR_STATE_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HTTP_C::DecryptClCertA() {
|
||||
static constexpr u32 iv_length = 16;
|
||||
|
||||
|
@ -875,13 +901,13 @@ HTTP_C::HTTP_C() : ServiceFramework("http:C", 32) {
|
|||
{0x0003, &HTTP_C::CloseContext, "CloseContext"},
|
||||
{0x0004, nullptr, "CancelConnection"},
|
||||
{0x0005, nullptr, "GetRequestState"},
|
||||
{0x0006, nullptr, "GetDownloadSizeState"},
|
||||
{0x0006, &HTTP_C::GetDownloadSizeState, "GetDownloadSizeState"},
|
||||
{0x0007, nullptr, "GetRequestError"},
|
||||
{0x0008, &HTTP_C::InitializeConnectionSession, "InitializeConnectionSession"},
|
||||
{0x0009, &HTTP_C::BeginRequest, "BeginRequest"},
|
||||
{0x000A, &HTTP_C::BeginRequestAsync, "BeginRequestAsync"},
|
||||
{0x000B, nullptr, "ReceiveData"},
|
||||
{0x000C, nullptr, "ReceiveDataTimeout"},
|
||||
{0x000B, &HTTP_C::ReceiveData, "ReceiveData"},
|
||||
{0x000C, &HTTP_C::ReceiveDataTimeout, "ReceiveDataTimeout"},
|
||||
{0x000D, nullptr, "SetProxy"},
|
||||
{0x000E, nullptr, "SetProxyDefault"},
|
||||
{0x000F, nullptr, "SetBasicAuthorization"},
|
||||
|
@ -903,8 +929,8 @@ HTTP_C::HTTP_C() : ServiceFramework("http:C", 32) {
|
|||
{0x001F, nullptr, "GetResponseHeaderTimeout"},
|
||||
{0x0020, nullptr, "GetResponseData"},
|
||||
{0x0021, nullptr, "GetResponseDataTimeout"},
|
||||
{0x0022, nullptr, "GetResponseStatusCode"},
|
||||
{0x0023, nullptr, "GetResponseStatusCodeTimeout"},
|
||||
{0x0022, &HTTP_C::GetResponseStatusCode, "GetResponseStatusCode"},
|
||||
{0x0023, &HTTP_C::GetResponseStatusCodeTimeout, "GetResponseStatusCodeTimeout"},
|
||||
{0x0024, nullptr, "AddTrustedRootCA"},
|
||||
{0x0025, nullptr, "AddDefaultCert"},
|
||||
{0x0026, nullptr, "SelectRootCertChain"},
|
|
@ -30,6 +30,10 @@ namespace Core {
|
|||
class System;
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
class RequestParser;
|
||||
}
|
||||
|
||||
namespace Service::HTTP {
|
||||
|
||||
enum class RequestMethod : u8 {
|
||||
|
@ -288,6 +292,17 @@ private:
|
|||
*/
|
||||
void CloseContext(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* HTTP_C::GetDownloadSizeState service function
|
||||
* Inputs:
|
||||
* 1 : Context handle
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
* 2 : Total content data downloaded so far
|
||||
* 3 : Total content size from the "Content-Length" response header
|
||||
*/
|
||||
void GetDownloadSizeState(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* HTTP_C::InitializeConnectionSession service function
|
||||
* Inputs:
|
||||
|
@ -302,7 +317,7 @@ private:
|
|||
/**
|
||||
* HTTP_C::BeginRequest service function
|
||||
* Inputs:
|
||||
* 1 : Context handle
|
||||
* 1 : Context handle
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
|
@ -311,12 +326,43 @@ private:
|
|||
/**
|
||||
* HTTP_C::BeginRequestAsync service function
|
||||
* Inputs:
|
||||
* 1 : Context handle
|
||||
* 1 : Context handle
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void BeginRequestAsync(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* HTTP_C::ReceiveData service function
|
||||
* Inputs:
|
||||
* 1 : Context handle
|
||||
* 2 : Buffer size
|
||||
* 3 : (OutSize<<4) | 12
|
||||
* 4 : Output data pointer
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void ReceiveData(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* HTTP_C::ReceiveDataTimeout service function
|
||||
* Inputs:
|
||||
* 1 : Context handle
|
||||
* 2 : Buffer size
|
||||
* 3-4 : u64 nanoseconds delay
|
||||
* 5 : (OutSize<<4) | 12
|
||||
* 6 : Output data pointer
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void ReceiveDataTimeout(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* ReceiveDataImpl:
|
||||
* Implements ReceiveData and ReceiveDataTimeout service functions
|
||||
*/
|
||||
void ReceiveDataImpl(Kernel::HLERequestContext& ctx, bool timeout);
|
||||
|
||||
/**
|
||||
* HTTP_C::AddRequestHeader service function
|
||||
* Inputs:
|
||||
|
@ -347,6 +393,33 @@ private:
|
|||
*/
|
||||
void AddPostDataAscii(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* HTTP_C::GetResponseStatusCode service function
|
||||
* Inputs:
|
||||
* 1 : Context handle
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
* 2 : HTTP response status code
|
||||
*/
|
||||
void GetResponseStatusCode(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* HTTP_C::GetResponseStatusCode service function
|
||||
* Inputs:
|
||||
* 1 : Context handle
|
||||
* 2-3 : u64 nanoseconds timeout
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
* 2 : HTTP response status code
|
||||
*/
|
||||
void GetResponseStatusCodeTimeout(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* GetResponseStatusCodeImpl:
|
||||
* Implements GetResponseStatusCode and GetResponseStatusCodeTimeout service functions
|
||||
*/
|
||||
void GetResponseStatusCodeImpl(Kernel::HLERequestContext& ctx, bool timeout);
|
||||
|
||||
/**
|
||||
* HTTP_C::SetClientCertContext service function
|
||||
* Inputs:
|
||||
|
@ -408,6 +481,12 @@ private:
|
|||
*/
|
||||
void Finalize(Kernel::HLERequestContext& ctx);
|
||||
|
||||
[[nodiscard]] SessionData* EnsureSessionInitialized(Kernel::HLERequestContext& ctx,
|
||||
IPC::RequestParser rp);
|
||||
|
||||
[[nodiscard]] bool PerformStateChecks(Kernel::HLERequestContext& ctx, IPC::RequestParser rp,
|
||||
Context::Handle context_handle);
|
||||
|
||||
void DecryptClCertA();
|
||||
|
||||
std::shared_ptr<Kernel::SharedMemory> shared_memory = nullptr;
|
|
@ -16,7 +16,7 @@
|
|||
#include "core/hle/kernel/handle_table.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/shared_memory.h"
|
||||
#include "core/hle/service/mic_u.h"
|
||||
#include "core/hle/service/mic/mic_u.h"
|
||||
|
||||
SERVICE_CONSTRUCT_IMPL(Service::MIC::MIC_U)
|
||||
SERIALIZE_EXPORT_IMPL(Service::MIC::MIC_U)
|
|
@ -19,22 +19,23 @@
|
|||
#include "core/hle/service/apt/apt.h"
|
||||
#include "core/hle/service/boss/boss.h"
|
||||
#include "core/hle/service/cam/cam.h"
|
||||
#include "core/hle/service/cam/y2r_u.h"
|
||||
#include "core/hle/service/cecd/cecd.h"
|
||||
#include "core/hle/service/cfg/cfg.h"
|
||||
#include "core/hle/service/csnd/csnd_snd.h"
|
||||
#include "core/hle/service/dlp/dlp.h"
|
||||
#include "core/hle/service/dsp/dsp_dsp.h"
|
||||
#include "core/hle/service/err_f.h"
|
||||
#include "core/hle/service/err/err_f.h"
|
||||
#include "core/hle/service/frd/frd.h"
|
||||
#include "core/hle/service/fs/archive.h"
|
||||
#include "core/hle/service/fs/fs_user.h"
|
||||
#include "core/hle/service/gsp/gsp.h"
|
||||
#include "core/hle/service/gsp/gsp_lcd.h"
|
||||
#include "core/hle/service/hid/hid.h"
|
||||
#include "core/hle/service/http_c.h"
|
||||
#include "core/hle/service/http/http_c.h"
|
||||
#include "core/hle/service/ir/ir.h"
|
||||
#include "core/hle/service/ldr_ro/ldr_ro.h"
|
||||
#include "core/hle/service/mic_u.h"
|
||||
#include "core/hle/service/mic/mic_u.h"
|
||||
#include "core/hle/service/mvd/mvd.h"
|
||||
#include "core/hle/service/ndm/ndm_u.h"
|
||||
#include "core/hle/service/news/news.h"
|
||||
|
@ -50,9 +51,8 @@
|
|||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
#include "core/hle/service/sm/srv.h"
|
||||
#include "core/hle/service/soc_u.h"
|
||||
#include "core/hle/service/ssl_c.h"
|
||||
#include "core/hle/service/y2r_u.h"
|
||||
#include "core/hle/service/soc/soc_u.h"
|
||||
#include "core/hle/service/ssl/ssl_c.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Service {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/shared_memory.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/soc_u.h"
|
||||
#include "core/hle/service/soc/soc_u.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
|
@ -868,7 +868,7 @@ void SOC_U::Accept(Kernel::HLERequestContext& ctx) {
|
|||
rb.Push(ERR_INVALID_HANDLE);
|
||||
return;
|
||||
}
|
||||
[[maybe_unused]] const auto max_addr_len = static_cast<socklen_t>(rp.Pop<u32>());
|
||||
const auto max_addr_len = rp.Pop<u32>();
|
||||
rp.PopPID();
|
||||
sockaddr addr;
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
|
@ -889,6 +889,11 @@ void SOC_U::Accept(Kernel::HLERequestContext& ctx) {
|
|||
std::memcpy(ctr_addr_buf.data(), &ctr_addr, sizeof(ctr_addr));
|
||||
}
|
||||
|
||||
if (ctr_addr_buf.size() > max_addr_len) {
|
||||
LOG_WARNING(Frontend, "CTRSockAddr is too long, truncating data.");
|
||||
ctr_addr_buf.resize(max_addr_len);
|
||||
}
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 2);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(ret);
|
||||
|
@ -1264,7 +1269,7 @@ void SOC_U::GetSockName(Kernel::HLERequestContext& ctx) {
|
|||
rb.Push(ERR_INVALID_HANDLE);
|
||||
return;
|
||||
}
|
||||
[[maybe_unused]] const auto max_addr_len = rp.Pop<u32>();
|
||||
const auto max_addr_len = rp.Pop<u32>();
|
||||
rp.PopPID();
|
||||
|
||||
sockaddr dest_addr;
|
||||
|
@ -1278,6 +1283,11 @@ void SOC_U::GetSockName(Kernel::HLERequestContext& ctx) {
|
|||
if (ret != 0)
|
||||
ret = TranslateError(GET_ERRNO);
|
||||
|
||||
if (dest_addr_buff.size() > max_addr_len) {
|
||||
LOG_WARNING(Frontend, "CTRSockAddr is too long, truncating data.");
|
||||
dest_addr_buff.resize(max_addr_len);
|
||||
}
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 2);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(ret);
|
||||
|
@ -1358,7 +1368,7 @@ void SOC_U::GetPeerName(Kernel::HLERequestContext& ctx) {
|
|||
rb.Push(ERR_INVALID_HANDLE);
|
||||
return;
|
||||
}
|
||||
[[maybe_unused]] const auto max_addr_len = rp.Pop<u32>();
|
||||
const auto max_addr_len = rp.Pop<u32>();
|
||||
rp.PopPID();
|
||||
|
||||
sockaddr dest_addr;
|
||||
|
@ -1374,6 +1384,11 @@ void SOC_U::GetPeerName(Kernel::HLERequestContext& ctx) {
|
|||
result = TranslateError(GET_ERRNO);
|
||||
}
|
||||
|
||||
if (dest_addr_buff.size() > max_addr_len) {
|
||||
LOG_WARNING(Frontend, "CTRSockAddr is too long, truncating data.");
|
||||
dest_addr_buff.resize(max_addr_len);
|
||||
}
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 2);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(result);
|
|
@ -7,7 +7,7 @@
|
|||
#include "core/core.h"
|
||||
#include "core/hle/ipc.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/ssl_c.h"
|
||||
#include "core/hle/service/ssl/ssl_c.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::SSL::SSL_C)
|
||||
namespace Service::SSL {
|
|
@ -12,7 +12,7 @@
|
|||
#include "common/microprofileui.h"
|
||||
#include "common/vector_math.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/y2r_u.h"
|
||||
#include "core/hle/service/cam/y2r_u.h"
|
||||
#include "core/hw/y2r.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
|
|
Loading…
Reference in a new issue