mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +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…
	
	Add table
		Add a link
		
	
		Reference in a new issue