From 28124c053aa07ccb8f772c7621959237e5c10ffa Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sat, 21 Jul 2018 18:48:57 -0500 Subject: [PATCH 01/15] Services/HLE: Convert the http:C service to the new service framework. --- src/core/hle/service/http_c.cpp | 124 ++++++++++++++++--------------- src/core/hle/service/http_c.h | 8 +- src/core/hle/service/service.cpp | 2 +- 3 files changed, 69 insertions(+), 65 deletions(-) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index b01d6e031..e61772078 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -2,71 +2,77 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/ipc.h" #include "core/hle/service/http_c.h" namespace Service { namespace HTTP { -const Interface::FunctionInfo FunctionTable[] = { - {0x00010044, nullptr, "Initialize"}, - {0x00020082, nullptr, "CreateContext"}, - {0x00030040, nullptr, "CloseContext"}, - {0x00040040, nullptr, "CancelConnection"}, - {0x00050040, nullptr, "GetRequestState"}, - {0x00060040, nullptr, "GetDownloadSizeState"}, - {0x00070040, nullptr, "GetRequestError"}, - {0x00080042, nullptr, "InitializeConnectionSession"}, - {0x00090040, nullptr, "BeginRequest"}, - {0x000A0040, nullptr, "BeginRequestAsync"}, - {0x000B0082, nullptr, "ReceiveData"}, - {0x000C0102, nullptr, "ReceiveDataTimeout"}, - {0x000D0146, nullptr, "SetProxy"}, - {0x000E0040, nullptr, "SetProxyDefault"}, - {0x000F00C4, nullptr, "SetBasicAuthorization"}, - {0x00100080, nullptr, "SetSocketBufferSize"}, - {0x001100C4, nullptr, "AddRequestHeader"}, - {0x001200C4, nullptr, "AddPostDataAscii"}, - {0x001300C4, nullptr, "AddPostDataBinary"}, - {0x00140082, nullptr, "AddPostDataRaw"}, - {0x00150080, nullptr, "SetPostDataType"}, - {0x001600C4, nullptr, "SendPostDataAscii"}, - {0x00170144, nullptr, "SendPostDataAsciiTimeout"}, - {0x001800C4, nullptr, "SendPostDataBinary"}, - {0x00190144, nullptr, "SendPostDataBinaryTimeout"}, - {0x001A0082, nullptr, "SendPostDataRaw"}, - {0x001B0102, nullptr, "SendPOSTDataRawTimeout"}, - {0x001C0080, nullptr, "SetPostDataEncoding"}, - {0x001D0040, nullptr, "NotifyFinishSendPostData"}, - {0x001E00C4, nullptr, "GetResponseHeader"}, - {0x001F0144, nullptr, "GetResponseHeaderTimeout"}, - {0x00200082, nullptr, "GetResponseData"}, - {0x00210102, nullptr, "GetResponseDataTimeout"}, - {0x00220040, nullptr, "GetResponseStatusCode"}, - {0x002300C0, nullptr, "GetResponseStatusCodeTimeout"}, - {0x00240082, nullptr, "AddTrustedRootCA"}, - {0x00250080, nullptr, "AddDefaultCert"}, - {0x00260080, nullptr, "SelectRootCertChain"}, - {0x002700C4, nullptr, "SetClientCert"}, - {0x002B0080, nullptr, "SetSSLOpt"}, - {0x002C0080, nullptr, "SetSSLClearOpt"}, - {0x002D0000, nullptr, "CreateRootCertChain"}, - {0x002E0040, nullptr, "DestroyRootCertChain"}, - {0x002F0082, nullptr, "RootCertChainAddCert"}, - {0x00300080, nullptr, "RootCertChainAddDefaultCert"}, - {0x00310080, nullptr, "RootCertChainRemoveCert"}, - {0x00320084, nullptr, "OpenClientCertContext"}, - {0x00330040, nullptr, "OpenDefaultClientCertContext"}, - {0x00340040, nullptr, "CloseClientCertContext"}, - {0x00350186, nullptr, "SetDefaultProxy"}, - {0x00360000, nullptr, "ClearDNSCache"}, - {0x00370080, nullptr, "SetKeepAlive"}, - {0x003800C0, nullptr, "SetPostDataTypeSize"}, - {0x00390000, nullptr, "Finalize"}, -}; - -HTTP_C::HTTP_C() { - Register(FunctionTable); +HTTP_C::HTTP_C() : ServiceFramework("http:C", 32) { + static const FunctionInfo functions[] = { + {0x00010044, nullptr, "Initialize"}, + {0x00020082, nullptr, "CreateContext"}, + {0x00030040, nullptr, "CloseContext"}, + {0x00040040, nullptr, "CancelConnection"}, + {0x00050040, nullptr, "GetRequestState"}, + {0x00060040, nullptr, "GetDownloadSizeState"}, + {0x00070040, nullptr, "GetRequestError"}, + {0x00080042, nullptr, "InitializeConnectionSession"}, + {0x00090040, nullptr, "BeginRequest"}, + {0x000A0040, nullptr, "BeginRequestAsync"}, + {0x000B0082, nullptr, "ReceiveData"}, + {0x000C0102, nullptr, "ReceiveDataTimeout"}, + {0x000D0146, nullptr, "SetProxy"}, + {0x000E0040, nullptr, "SetProxyDefault"}, + {0x000F00C4, nullptr, "SetBasicAuthorization"}, + {0x00100080, nullptr, "SetSocketBufferSize"}, + {0x001100C4, nullptr, "AddRequestHeader"}, + {0x001200C4, nullptr, "AddPostDataAscii"}, + {0x001300C4, nullptr, "AddPostDataBinary"}, + {0x00140082, nullptr, "AddPostDataRaw"}, + {0x00150080, nullptr, "SetPostDataType"}, + {0x001600C4, nullptr, "SendPostDataAscii"}, + {0x00170144, nullptr, "SendPostDataAsciiTimeout"}, + {0x001800C4, nullptr, "SendPostDataBinary"}, + {0x00190144, nullptr, "SendPostDataBinaryTimeout"}, + {0x001A0082, nullptr, "SendPostDataRaw"}, + {0x001B0102, nullptr, "SendPOSTDataRawTimeout"}, + {0x001C0080, nullptr, "SetPostDataEncoding"}, + {0x001D0040, nullptr, "NotifyFinishSendPostData"}, + {0x001E00C4, nullptr, "GetResponseHeader"}, + {0x001F0144, nullptr, "GetResponseHeaderTimeout"}, + {0x00200082, nullptr, "GetResponseData"}, + {0x00210102, nullptr, "GetResponseDataTimeout"}, + {0x00220040, nullptr, "GetResponseStatusCode"}, + {0x002300C0, nullptr, "GetResponseStatusCodeTimeout"}, + {0x00240082, nullptr, "AddTrustedRootCA"}, + {0x00250080, nullptr, "AddDefaultCert"}, + {0x00260080, nullptr, "SelectRootCertChain"}, + {0x002700C4, nullptr, "SetClientCert"}, + {0x00290080, nullptr, "SetClientCertContext"}, + {0x002A0040, nullptr, "GetSSLError"}, + {0x002B0080, nullptr, "SetSSLOpt"}, + {0x002C0080, nullptr, "SetSSLClearOpt"}, + {0x002D0000, nullptr, "CreateRootCertChain"}, + {0x002E0040, nullptr, "DestroyRootCertChain"}, + {0x002F0082, nullptr, "RootCertChainAddCert"}, + {0x00300080, nullptr, "RootCertChainAddDefaultCert"}, + {0x00310080, nullptr, "RootCertChainRemoveCert"}, + {0x00320084, nullptr, "OpenClientCertContext"}, + {0x00330040, nullptr, "OpenDefaultClientCertContext"}, + {0x00340040, nullptr, "CloseClientCertContext"}, + {0x00350186, nullptr, "SetDefaultProxy"}, + {0x00360000, nullptr, "ClearDNSCache"}, + {0x00370080, nullptr, "SetKeepAlive"}, + {0x003800C0, nullptr, "SetPostDataTypeSize"}, + {0x00390000, nullptr, "Finalize"}, + }; + RegisterHandlers(functions); } +void InstallInterfaces(SM::ServiceManager& service_manager) { + std::make_shared()->InstallAsService(service_manager); +} } // namespace HTTP } // namespace Service diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h index cff279c02..82923b14b 100644 --- a/src/core/hle/service/http_c.h +++ b/src/core/hle/service/http_c.h @@ -9,14 +9,12 @@ namespace Service { namespace HTTP { -class HTTP_C final : public Interface { +class HTTP_C final : public ServiceFramework { public: HTTP_C(); - - std::string GetPortName() const override { - return "http:C"; - } }; +void InstallInterfaces(SM::ServiceManager& service_manager); + } // namespace HTTP } // namespace Service diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index c036f3611..0031a8314 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -256,7 +256,7 @@ void Init(std::shared_ptr& sm) { QTM::InstallInterfaces(*sm); CSND::InstallInterfaces(*sm); - AddService(new HTTP::HTTP_C); + HTTP::InstallInterfaces(*sm); PM::InstallInterfaces(*sm); AddService(new SOC::SOC_U); SSL::InstallInterfaces(*sm); From 1f865fd524d32ddf627ac636bd2c6ee490ea78d0 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sat, 21 Jul 2018 18:54:06 -0500 Subject: [PATCH 02/15] Services/HTTP: Stubbed the Initialize function. --- src/core/hle/service/http_c.cpp | 19 ++++++++++++++++++- src/core/hle/service/http_c.h | 17 +++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index e61772078..72c48a8d3 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -9,9 +9,26 @@ namespace Service { namespace HTTP { +void HTTP_C::Initialize(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x1, 1, 4); + const u32 shmem_size = rp.Pop(); + rp.PopPID(); + shared_memory = rp.PopObject(); + if (shared_memory) { + shared_memory->name = "HTTP_C:shared_memory"; + } + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + // This returns 0xd8a0a046 if no network connection is available. + // Just assume we are always connected. + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_HTTP, "(STUBBED) called, shared memory size: {}", shmem_size); +} + HTTP_C::HTTP_C() : ServiceFramework("http:C", 32) { static const FunctionInfo functions[] = { - {0x00010044, nullptr, "Initialize"}, + {0x00010044, &HTTP_C::Initialize, "Initialize"}, {0x00020082, nullptr, "CreateContext"}, {0x00030040, nullptr, "CloseContext"}, {0x00040040, nullptr, "CancelConnection"}, diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h index 82923b14b..34b0aa54f 100644 --- a/src/core/hle/service/http_c.h +++ b/src/core/hle/service/http_c.h @@ -4,6 +4,7 @@ #pragma once +#include "core/hle/kernel/shared_memory.h" #include "core/hle/service/service.h" namespace Service { @@ -12,6 +13,22 @@ namespace HTTP { class HTTP_C final : public ServiceFramework { public: HTTP_C(); + +private: + /** + * HTTP_C::Initialize service function + * Inputs: + * 1 : POST buffer size + * 2 : 0x20 + * 3 : 0x0 (Filled with process ID by ARM11 Kernel) + * 4 : 0x0 + * 5 : POST buffer memory block handle + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void Initialize(Kernel::HLERequestContext& ctx); + + Kernel::SharedPtr shared_memory = nullptr; }; void InstallInterfaces(SM::ServiceManager& service_manager); From fe5a3d22c52aedc1191fbec9f504fc8203100b26 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sat, 21 Jul 2018 19:00:50 -0500 Subject: [PATCH 03/15] Services/HTTP: Added structures to store both client and server certificates. --- src/core/hle/service/http_c.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index 72c48a8d3..5a700f3fb 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/ipc.h" #include "core/hle/service/http_c.h" @@ -9,6 +10,28 @@ namespace Service { namespace HTTP { +/// Represents a client certificate along with its private key, stored as a byte array of DER data. +/// There can only be at most one client certificate context attached to an HTTP context at any +/// given time. +struct ClientCertContext { + u32 handle; + std::vector certificate; + std::vector private_key; +}; + +/// Represents a root certificate chain, it contains a list of DER-encoded certificates for +/// verifying HTTP requests. An HTTP context can have at most one root certificate chain attached to +/// it, but the chain may contain an arbitrary number of certificates in it. +struct RootCertChain { + struct RootCACert { + u32 handle; + std::vector certificate; + }; + + u32 handle; + std::vector certificates; +}; + void HTTP_C::Initialize(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x1, 1, 4); const u32 shmem_size = rp.Pop(); From 87ec3934a6995a9aff29d1977bf3497f24b5bf53 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sat, 21 Jul 2018 19:10:00 -0500 Subject: [PATCH 04/15] Services/HTTP: Added structures to represent an HTTP context. More fields will probably need to be added to these structures in the future. --- src/core/hle/service/http_c.cpp | 63 +++++++++++++++++++++++++++++++++ src/core/hle/service/http_c.h | 10 ++++++ 2 files changed, 73 insertions(+) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index 5a700f3fb..f2e77f2a7 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -2,7 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include +#include #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/ipc.h" #include "core/hle/service/http_c.h" @@ -10,6 +12,24 @@ namespace Service { namespace HTTP { +enum class RequestMethod : u8 { + Get = 0x1, + Post = 0x2, + Head = 0x3, + Put = 0x4, + Delete = 0x5, + PostEmpty = 0x6, + PutEmpty = 0x7, +}; + +enum class RequestState : u8 { + NotStarted = 0x1, // Request has not started yet. + InProgress = 0x5, // Request in progress, sending request over the network. + ReadyToDownloadContent = 0x7, // Ready to download the content. (needs verification) + ReadyToDownload = 0x8, // Ready to download? + TimedOut = 0xA, // Request timed out? +}; + /// Represents a client certificate along with its private key, stored as a byte array of DER data. /// There can only be at most one client certificate context attached to an HTTP context at any /// given time. @@ -32,6 +52,49 @@ struct RootCertChain { std::vector certificates; }; +/// Represents an HTTP context. +struct Context { + struct Proxy { + std::string url; + std::string username; + std::string password; + u16 port; + }; + + struct BasicAuth { + std::string username; + std::string password; + }; + + struct RequestHeader { + std::string name; + std::string value; + }; + + struct PostData { + // TODO(Subv): Support Binary and Raw POST elements. + std::string name; + std::string value; + }; + + struct SSLConfig { + u32 options; + std::weak_ptr client_cert_ctx; + std::weak_ptr root_ca_chain; + }; + + u32 handle; + std::string url; + RequestMethod method; + RequestState state = RequestState::NotStarted; + boost::optional proxy; + boost::optional basic_auth; + SSLConfig ssl_config{}; + u32 socket_buffer_size; + std::vector headers; + std::vector post_data; +}; + void HTTP_C::Initialize(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x1, 1, 4); const u32 shmem_size = rp.Pop(); diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h index 34b0aa54f..14d869336 100644 --- a/src/core/hle/service/http_c.h +++ b/src/core/hle/service/http_c.h @@ -4,12 +4,16 @@ #pragma once +#include #include "core/hle/kernel/shared_memory.h" #include "core/hle/service/service.h" namespace Service { namespace HTTP { +struct Context; +struct ClientCertContext; + class HTTP_C final : public ServiceFramework { public: HTTP_C(); @@ -29,6 +33,12 @@ private: void Initialize(Kernel::HLERequestContext& ctx); Kernel::SharedPtr shared_memory = nullptr; + + std::unordered_map contexts; + u32 context_counter = 0; + + std::unordered_map client_certs; + u32 client_certs_counter = 0; }; void InstallInterfaces(SM::ServiceManager& service_manager); From 70e69796950417215d3c38fd3f7ff28a1476700d Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 21 Jul 2018 19:30:40 -0500 Subject: [PATCH 05/15] Services/HTTP: Implemented the CreateContext function handler. --- src/core/hle/service/http_c.cpp | 37 ++++++++++++++++++++++++++++++++- src/core/hle/service/http_c.h | 13 ++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index f2e77f2a7..e4eab02de 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -13,6 +13,7 @@ namespace Service { namespace HTTP { enum class RequestMethod : u8 { + None = 0x0, Get = 0x1, Post = 0x2, Head = 0x3, @@ -22,6 +23,9 @@ enum class RequestMethod : u8 { PutEmpty = 0x7, }; +/// The number of request methods, any valid method must be less than this. +constexpr u32 TotalRequestMethods = 8; + enum class RequestState : u8 { NotStarted = 0x1, // Request has not started yet. InProgress = 0x5, // Request in progress, sending request over the network. @@ -112,10 +116,41 @@ void HTTP_C::Initialize(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_HTTP, "(STUBBED) called, shared memory size: {}", shmem_size); } +void HTTP_C::CreateContext(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x2, 2, 2); + const u32 url_size = rp.Pop(); + std::string url(url_size, '\0'); + RequestMethod method = rp.PopEnum(); + + Kernel::MappedBuffer& buffer = rp.PopMappedBuffer(); + buffer.Read(&url[0], 0, url_size - 1); + + LOG_DEBUG(Service_HTTP, "called, url_size={}, url={}, method={}", url_size, url, + static_cast(method)); + + // TODO(Subv): Find the right error code for this case. + ASSERT_MSG(method == RequestMethod::None && static_cast(method) < TotalRequestMethods, + "Invalid request method {}", static_cast(method)); + + Context context{}; + context.url = std::move(url); + context.method = method; + context.state = RequestState::NotStarted; + // TODO(Subv): Find a correct default value for this field. + context.socket_buffer_size = 0; + context.handle = ++context_counter; + contexts[context_counter] = std::move(context); + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); + rb.Push(RESULT_SUCCESS); + rb.Push(context_counter); + rb.PushMappedBuffer(buffer); +} + HTTP_C::HTTP_C() : ServiceFramework("http:C", 32) { static const FunctionInfo functions[] = { {0x00010044, &HTTP_C::Initialize, "Initialize"}, - {0x00020082, nullptr, "CreateContext"}, + {0x00020082, &HTTP_C::CreateContext, "CreateContext"}, {0x00030040, nullptr, "CloseContext"}, {0x00040040, nullptr, "CancelConnection"}, {0x00050040, nullptr, "GetRequestState"}, diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h index 14d869336..bf9d1f865 100644 --- a/src/core/hle/service/http_c.h +++ b/src/core/hle/service/http_c.h @@ -32,6 +32,19 @@ private: */ void Initialize(Kernel::HLERequestContext& ctx); + /** + * HTTP_C::CreateContext service function + * Inputs: + * 1 : URL buffer size, including null-terminator + * 2 : RequestMethod + * 3 : (URLSize << 4) | 10 + * 4 : URL data pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : HTTP context handle + */ + void CreateContext(Kernel::HLERequestContext& ctx); + Kernel::SharedPtr shared_memory = nullptr; std::unordered_map contexts; From 34baa882c8f6788aa76d1e7cdd5ffd1f5454bbf1 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 21 Jul 2018 19:50:13 -0500 Subject: [PATCH 06/15] Services/HTTP: Corrected the error code for an invalid request method. --- src/core/hle/service/http_c.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index e4eab02de..32862e8f1 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -12,6 +12,17 @@ namespace Service { namespace HTTP { +namespace ErrCodes { +enum { + InvalidRequestMethod = 32, + InvalidContext = 102, +}; +} + +const ResultCode ERROR_CONTEXT_ERROR = // 0xD8A0A066 + ResultCode(ErrCodes::InvalidContext, ErrorModule::HTTP, ErrorSummary::InvalidState, + ErrorLevel::Permanent); + enum class RequestMethod : u8 { None = 0x0, Get = 0x1, @@ -128,9 +139,15 @@ void HTTP_C::CreateContext(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_HTTP, "called, url_size={}, url={}, method={}", url_size, url, static_cast(method)); - // TODO(Subv): Find the right error code for this case. - ASSERT_MSG(method == RequestMethod::None && static_cast(method) < TotalRequestMethods, - "Invalid request method {}", static_cast(method)); + if (method == RequestMethod::None || static_cast(method) >= TotalRequestMethods) { + LOG_ERROR(Service_HTTP, "invalid request method={}", static_cast(method)); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(ResultCode(ErrCodes::InvalidContext, ErrorModule::HTTP, ErrorSummary::InvalidState, + ErrorLevel::Permanent)); + rb.PushMappedBuffer(buffer); + return; + } Context context{}; context.url = std::move(url); From 799b45233fcb9f8609a2bfc5220c388fe0e0ef33 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 21 Jul 2018 20:11:20 -0500 Subject: [PATCH 07/15] Services/HTTP: Stubbed the CloseContext service function. It is currently unknown how the real http module handles trying to close contexts for requests that are already in flight. --- src/core/hle/service/http_c.cpp | 26 +++++++++++++++++++++++++- src/core/hle/service/http_c.h | 9 +++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index 32862e8f1..12dae5671 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -164,11 +164,35 @@ void HTTP_C::CreateContext(Kernel::HLERequestContext& ctx) { rb.PushMappedBuffer(buffer); } +void HTTP_C::CloseContext(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x3, 2, 0); + + u32 context_handle = rp.Pop(); + + LOG_WARNING(Service_HTTP, "(STUBBED) called, handle={}", context_handle); + + auto itr = contexts.find(context_handle); + if (itr == contexts.end()) { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(ERROR_CONTEXT_ERROR); + LOG_ERROR(Service_HTTP, "called, context {} not found", context_handle); + return; + } + + // TODO(Subv): What happens if you try to close a context that's currently being used? + ASSERT(itr->second.state == RequestState::NotStarted); + + contexts.erase(itr); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); +} + HTTP_C::HTTP_C() : ServiceFramework("http:C", 32) { static const FunctionInfo functions[] = { {0x00010044, &HTTP_C::Initialize, "Initialize"}, {0x00020082, &HTTP_C::CreateContext, "CreateContext"}, - {0x00030040, nullptr, "CloseContext"}, + {0x00030040, &HTTP_C::CloseContext, "CloseContext"}, {0x00040040, nullptr, "CancelConnection"}, {0x00050040, nullptr, "GetRequestState"}, {0x00060040, nullptr, "GetDownloadSizeState"}, diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h index bf9d1f865..cc4c334a9 100644 --- a/src/core/hle/service/http_c.h +++ b/src/core/hle/service/http_c.h @@ -45,6 +45,15 @@ private: */ void CreateContext(Kernel::HLERequestContext& ctx); + /** + * HTTP_C::CreateContext service function + * Inputs: + * 1 : Context handle + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void CloseContext(Kernel::HLERequestContext& ctx); + Kernel::SharedPtr shared_memory = nullptr; std::unordered_map contexts; From 0606e7010c7789cabacb33050bcb6a170ad7773b Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sun, 22 Jul 2018 12:15:03 +0200 Subject: [PATCH 08/15] Services/HTTP: Implemented the AddRequestHeader service function. --- src/core/hle/service/http_c.cpp | 37 ++++++++++++++++++++++++++++++++- src/core/hle/service/http_c.h | 15 +++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index 12dae5671..3c55b3c84 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -188,6 +188,41 @@ void HTTP_C::CloseContext(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } +void HTTP_C::AddRequestHeader(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x11, 3, 4); + const u32 context_handle = rp.Pop(); + const u32 name_size = rp.Pop(); + const u32 value_size = rp.Pop(); + const std::vector name_buffer = rp.PopStaticBuffer(); + Kernel::MappedBuffer& value_buffer = rp.PopMappedBuffer(); + const std::string name(name_buffer.begin(), name_buffer.end() - 1); + std::string value(value_size - 1, '\0'); + value_buffer.Read(&value[0], 0, value_size - 1); + + auto itr = contexts.find(context_handle); + if (itr == contexts.end()) { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(ERROR_CONTEXT_ERROR); + LOG_ERROR(Service_HTTP, "called, context {} not found", context_handle); + return; + } + + ASSERT(itr->second.state == RequestState::NotStarted); + ASSERT(std::find_if(itr->second.headers.begin(), itr->second.headers.end(), + [&name](const Context::RequestHeader& m) -> bool { + return m.name == name; + }) == itr->second.headers.end()); + + itr->second.headers.push_back(Context::RequestHeader{name, value}); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushMappedBuffer(value_buffer); + + LOG_WARNING(Service_HTTP, "called, name={}, value={}, context_handle={}", name, value, + context_handle); +} + HTTP_C::HTTP_C() : ServiceFramework("http:C", 32) { static const FunctionInfo functions[] = { {0x00010044, &HTTP_C::Initialize, "Initialize"}, @@ -206,7 +241,7 @@ HTTP_C::HTTP_C() : ServiceFramework("http:C", 32) { {0x000E0040, nullptr, "SetProxyDefault"}, {0x000F00C4, nullptr, "SetBasicAuthorization"}, {0x00100080, nullptr, "SetSocketBufferSize"}, - {0x001100C4, nullptr, "AddRequestHeader"}, + {0x001100C4, &HTTP_C::AddRequestHeader, "AddRequestHeader"}, {0x001200C4, nullptr, "AddPostDataAscii"}, {0x001300C4, nullptr, "AddPostDataBinary"}, {0x00140082, nullptr, "AddPostDataRaw"}, diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h index cc4c334a9..a548114ea 100644 --- a/src/core/hle/service/http_c.h +++ b/src/core/hle/service/http_c.h @@ -54,6 +54,21 @@ private: */ void CloseContext(Kernel::HLERequestContext& ctx); + /** + * HTTP_C::AddRequestHeader service function + * Inputs: + * 1 : Context handle + * 2 : Header name buffer size, including null-terminator. + * 3 : Header value buffer size, including null-terminator. + * 4 : (HeaderNameSize<<14) | 0xC02 + * 5 : Header name data pointer + * 6 : (HeaderValueSize<<4) | 10 + * 7 : Header value data pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void AddRequestHeader(Kernel::HLERequestContext& ctx); + Kernel::SharedPtr shared_memory = nullptr; std::unordered_map contexts; From 65c7ed844574be16a65493752662a68585a1eb62 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sun, 22 Jul 2018 15:01:32 +0200 Subject: [PATCH 09/15] Service/HTTP: Moved declarations to the header file --- src/core/hle/service/http_c.cpp | 90 -------------------------------- src/core/hle/service/http_c.h | 91 ++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 92 deletions(-) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index 3c55b3c84..25f9f4e36 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -2,9 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include -#include -#include #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/ipc.h" #include "core/hle/service/http_c.h" @@ -23,93 +20,6 @@ const ResultCode ERROR_CONTEXT_ERROR = // 0xD8A0A066 ResultCode(ErrCodes::InvalidContext, ErrorModule::HTTP, ErrorSummary::InvalidState, ErrorLevel::Permanent); -enum class RequestMethod : u8 { - None = 0x0, - Get = 0x1, - Post = 0x2, - Head = 0x3, - Put = 0x4, - Delete = 0x5, - PostEmpty = 0x6, - PutEmpty = 0x7, -}; - -/// The number of request methods, any valid method must be less than this. -constexpr u32 TotalRequestMethods = 8; - -enum class RequestState : u8 { - NotStarted = 0x1, // Request has not started yet. - InProgress = 0x5, // Request in progress, sending request over the network. - ReadyToDownloadContent = 0x7, // Ready to download the content. (needs verification) - ReadyToDownload = 0x8, // Ready to download? - TimedOut = 0xA, // Request timed out? -}; - -/// Represents a client certificate along with its private key, stored as a byte array of DER data. -/// There can only be at most one client certificate context attached to an HTTP context at any -/// given time. -struct ClientCertContext { - u32 handle; - std::vector certificate; - std::vector private_key; -}; - -/// Represents a root certificate chain, it contains a list of DER-encoded certificates for -/// verifying HTTP requests. An HTTP context can have at most one root certificate chain attached to -/// it, but the chain may contain an arbitrary number of certificates in it. -struct RootCertChain { - struct RootCACert { - u32 handle; - std::vector certificate; - }; - - u32 handle; - std::vector certificates; -}; - -/// Represents an HTTP context. -struct Context { - struct Proxy { - std::string url; - std::string username; - std::string password; - u16 port; - }; - - struct BasicAuth { - std::string username; - std::string password; - }; - - struct RequestHeader { - std::string name; - std::string value; - }; - - struct PostData { - // TODO(Subv): Support Binary and Raw POST elements. - std::string name; - std::string value; - }; - - struct SSLConfig { - u32 options; - std::weak_ptr client_cert_ctx; - std::weak_ptr root_ca_chain; - }; - - u32 handle; - std::string url; - RequestMethod method; - RequestState state = RequestState::NotStarted; - boost::optional proxy; - boost::optional basic_auth; - SSLConfig ssl_config{}; - u32 socket_buffer_size; - std::vector headers; - std::vector post_data; -}; - void HTTP_C::Initialize(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x1, 1, 4); const u32 shmem_size = rp.Pop(); diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h index a548114ea..3ca56e8e9 100644 --- a/src/core/hle/service/http_c.h +++ b/src/core/hle/service/http_c.h @@ -4,15 +4,102 @@ #pragma once +#include #include +#include +#include #include "core/hle/kernel/shared_memory.h" #include "core/hle/service/service.h" namespace Service { namespace HTTP { -struct Context; -struct ClientCertContext; +enum class RequestMethod : u8 { + None = 0x0, + Get = 0x1, + Post = 0x2, + Head = 0x3, + Put = 0x4, + Delete = 0x5, + PostEmpty = 0x6, + PutEmpty = 0x7, +}; + +/// The number of request methods, any valid method must be less than this. +constexpr u32 TotalRequestMethods = 8; + +enum class RequestState : u8 { + NotStarted = 0x1, // Request has not started yet. + InProgress = 0x5, // Request in progress, sending request over the network. + ReadyToDownloadContent = 0x7, // Ready to download the content. (needs verification) + ReadyToDownload = 0x8, // Ready to download? + TimedOut = 0xA, // Request timed out? +}; + +/// Represents a client certificate along with its private key, stored as a byte array of DER data. +/// There can only be at most one client certificate context attached to an HTTP context at any +/// given time. +struct ClientCertContext { + u32 handle; + std::vector certificate; + std::vector private_key; +}; + +/// Represents a root certificate chain, it contains a list of DER-encoded certificates for +/// verifying HTTP requests. An HTTP context can have at most one root certificate chain attached to +/// it, but the chain may contain an arbitrary number of certificates in it. +struct RootCertChain { + struct RootCACert { + u32 handle; + std::vector certificate; + }; + + u32 handle; + std::vector certificates; +}; + +/// Represents an HTTP context. +struct Context { + struct Proxy { + std::string url; + std::string username; + std::string password; + u16 port; + }; + + struct BasicAuth { + std::string username; + std::string password; + }; + + struct RequestHeader { + std::string name; + std::string value; + }; + + struct PostData { + // TODO(Subv): Support Binary and Raw POST elements. + std::string name; + std::string value; + }; + + struct SSLConfig { + u32 options; + std::weak_ptr client_cert_ctx; + std::weak_ptr root_ca_chain; + }; + + u32 handle; + std::string url; + RequestMethod method; + RequestState state = RequestState::NotStarted; + boost::optional proxy; + boost::optional basic_auth; + SSLConfig ssl_config{}; + u32 socket_buffer_size; + std::vector headers; + std::vector post_data; +}; class HTTP_C final : public ServiceFramework { public: From 32155cd683081f3ac0366e4136d41668a61e9043 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sun, 22 Jul 2018 15:10:43 +0200 Subject: [PATCH 10/15] Service/HTTP: stubbed InitializeConnectionSession --- src/core/hle/service/http_c.cpp | 27 +++++++++++++++++++++++++-- src/core/hle/service/http_c.h | 11 +++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index 25f9f4e36..eefcf8fcc 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -98,6 +98,29 @@ void HTTP_C::CloseContext(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } +void HTTP_C::InitializeConnectionSession(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x8, 1, 2); + const u32 context_handle = rp.Pop(); + rp.PopPID(); + + auto itr = contexts.find(context_handle); + if (itr == contexts.end()) { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(ERROR_CONTEXT_ERROR); + LOG_ERROR(Service_HTTP, "called, context {} not found", context_handle); + return; + } + + // TODO(Subv): What happens if you try to initalize a context that's currently being used? + ASSERT(itr->second.state == RequestState::NotStarted); + + // TODO(B3N30): Check what gets initalized + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_HTTP, "(STUBBED) called, context_id={}", context_handle); +} + void HTTP_C::AddRequestHeader(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x11, 3, 4); const u32 context_handle = rp.Pop(); @@ -123,7 +146,7 @@ void HTTP_C::AddRequestHeader(Kernel::HLERequestContext& ctx) { return m.name == name; }) == itr->second.headers.end()); - itr->second.headers.push_back(Context::RequestHeader{name, value}); + itr->second.headers.emplace_back(name, value); IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); rb.Push(RESULT_SUCCESS); @@ -142,7 +165,7 @@ HTTP_C::HTTP_C() : ServiceFramework("http:C", 32) { {0x00050040, nullptr, "GetRequestState"}, {0x00060040, nullptr, "GetDownloadSizeState"}, {0x00070040, nullptr, "GetRequestError"}, - {0x00080042, nullptr, "InitializeConnectionSession"}, + {0x00080042, &HTTP_C::InitializeConnectionSession, "InitializeConnectionSession"}, {0x00090040, nullptr, "BeginRequest"}, {0x000A0040, nullptr, "BeginRequestAsync"}, {0x000B0082, nullptr, "ReceiveData"}, diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h index 3ca56e8e9..eace3ff06 100644 --- a/src/core/hle/service/http_c.h +++ b/src/core/hle/service/http_c.h @@ -141,6 +141,17 @@ private: */ void CloseContext(Kernel::HLERequestContext& ctx); + /** + * HTTP_C::InitializeConnectionSession service function + * Inputs: + * 1 : HTTP context handle + * 2 : 0x20, processID translate-header for the ARM11-kernel + * 3 : processID set by the ARM11-kernel + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void InitializeConnectionSession(Kernel::HLERequestContext& ctx); + /** * HTTP_C::AddRequestHeader service function * Inputs: From 5af6a1d8eef94912852222b7b3f5b8d156fcc433 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sun, 22 Jul 2018 16:48:06 +0200 Subject: [PATCH 11/15] Revert stubbed InitializeConnectionSession --- src/core/hle/service/http_c.cpp | 25 +------------------------ src/core/hle/service/http_c.h | 11 ----------- 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index eefcf8fcc..1cd2f61a4 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -98,29 +98,6 @@ void HTTP_C::CloseContext(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } -void HTTP_C::InitializeConnectionSession(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp(ctx, 0x8, 1, 2); - const u32 context_handle = rp.Pop(); - rp.PopPID(); - - auto itr = contexts.find(context_handle); - if (itr == contexts.end()) { - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(ERROR_CONTEXT_ERROR); - LOG_ERROR(Service_HTTP, "called, context {} not found", context_handle); - return; - } - - // TODO(Subv): What happens if you try to initalize a context that's currently being used? - ASSERT(itr->second.state == RequestState::NotStarted); - - // TODO(B3N30): Check what gets initalized - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HTTP, "(STUBBED) called, context_id={}", context_handle); -} - void HTTP_C::AddRequestHeader(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x11, 3, 4); const u32 context_handle = rp.Pop(); @@ -165,7 +142,7 @@ HTTP_C::HTTP_C() : ServiceFramework("http:C", 32) { {0x00050040, nullptr, "GetRequestState"}, {0x00060040, nullptr, "GetDownloadSizeState"}, {0x00070040, nullptr, "GetRequestError"}, - {0x00080042, &HTTP_C::InitializeConnectionSession, "InitializeConnectionSession"}, + {0x00080042, nullptr, "InitializeConnectionSession"}, {0x00090040, nullptr, "BeginRequest"}, {0x000A0040, nullptr, "BeginRequestAsync"}, {0x000B0082, nullptr, "ReceiveData"}, diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h index eace3ff06..3ca56e8e9 100644 --- a/src/core/hle/service/http_c.h +++ b/src/core/hle/service/http_c.h @@ -141,17 +141,6 @@ private: */ void CloseContext(Kernel::HLERequestContext& ctx); - /** - * HTTP_C::InitializeConnectionSession service function - * Inputs: - * 1 : HTTP context handle - * 2 : 0x20, processID translate-header for the ARM11-kernel - * 3 : processID set by the ARM11-kernel - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ - void InitializeConnectionSession(Kernel::HLERequestContext& ctx); - /** * HTTP_C::AddRequestHeader service function * Inputs: From 2d09355a25c86bf90549d320cd0557cb4894db5b Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sun, 22 Jul 2018 18:14:23 +0200 Subject: [PATCH 12/15] Make Service::HTTP::Context non-copyable --- src/core/hle/service/http_c.cpp | 14 +++++++------- src/core/hle/service/http_c.h | 11 ++++++++++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index 1cd2f61a4..e5af90b7c 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -59,14 +59,14 @@ void HTTP_C::CreateContext(Kernel::HLERequestContext& ctx) { return; } - Context context{}; - context.url = std::move(url); - context.method = method; - context.state = RequestState::NotStarted; + ++context_counter; + contexts.emplace(context_counter, Context()); + contexts[context_counter].url = std::move(url); + contexts[context_counter].method = method; + contexts[context_counter].state = RequestState::NotStarted; // TODO(Subv): Find a correct default value for this field. - context.socket_buffer_size = 0; - context.handle = ++context_counter; - contexts[context_counter] = std::move(context); + contexts[context_counter].socket_buffer_size = 0; + contexts[context_counter].handle = ++context_counter; IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); rb.Push(RESULT_SUCCESS); diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h index 3ca56e8e9..e2d89e10d 100644 --- a/src/core/hle/service/http_c.h +++ b/src/core/hle/service/http_c.h @@ -59,7 +59,15 @@ struct RootCertChain { }; /// Represents an HTTP context. -struct Context { +class Context final { +public: + Context() = default; + Context(const Context&) = delete; + Context& operator=(const Context&) = delete; + + Context(Context&& other) = default; + Context& operator=(Context&&) = default; + struct Proxy { std::string url; std::string username; @@ -73,6 +81,7 @@ struct Context { }; struct RequestHeader { + RequestHeader(std::string name, std::string value) : name(name), value(value){}; std::string name; std::string value; }; From 2f50bf0007f943e294613c0111b617d26261a52c Mon Sep 17 00:00:00 2001 From: B3n30 Date: Mon, 23 Jul 2018 18:02:35 +0200 Subject: [PATCH 13/15] Service/HTTP_C: Fix error in CreateContext --- src/core/hle/service/http_c.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index e5af90b7c..bba46265d 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -59,14 +59,13 @@ void HTTP_C::CreateContext(Kernel::HLERequestContext& ctx) { return; } - ++context_counter; - contexts.emplace(context_counter, Context()); + contexts.emplace(++context_counter, Context()); contexts[context_counter].url = std::move(url); contexts[context_counter].method = method; contexts[context_counter].state = RequestState::NotStarted; // TODO(Subv): Find a correct default value for this field. contexts[context_counter].socket_buffer_size = 0; - contexts[context_counter].handle = ++context_counter; + contexts[context_counter].handle = context_counter; IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); rb.Push(RESULT_SUCCESS); From daac1349dba122bec9a8a78fc0220ea49ca7c165 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Mon, 23 Jul 2018 21:14:41 +0200 Subject: [PATCH 14/15] Service/HTTP_C: Add some comments; Fixed header in CloseContext --- src/core/hle/service/http_c.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index bba46265d..72dc2a450 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -40,10 +40,11 @@ void HTTP_C::Initialize(Kernel::HLERequestContext& ctx) { void HTTP_C::CreateContext(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x2, 2, 2); const u32 url_size = rp.Pop(); - std::string url(url_size, '\0'); RequestMethod method = rp.PopEnum(); - Kernel::MappedBuffer& buffer = rp.PopMappedBuffer(); + + // Copy the buffer into a string without the \0 at the end of the buffer + std::string url(url_size, '\0'); buffer.Read(&url[0], 0, url_size - 1); LOG_DEBUG(Service_HTTP, "called, url_size={}, url={}, method={}", url_size, url, @@ -74,7 +75,7 @@ void HTTP_C::CreateContext(Kernel::HLERequestContext& ctx) { } void HTTP_C::CloseContext(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp(ctx, 0x3, 2, 0); + IPC::RequestParser rp(ctx, 0x3, 1, 0); u32 context_handle = rp.Pop(); @@ -104,7 +105,11 @@ void HTTP_C::AddRequestHeader(Kernel::HLERequestContext& ctx) { const u32 value_size = rp.Pop(); const std::vector name_buffer = rp.PopStaticBuffer(); Kernel::MappedBuffer& value_buffer = rp.PopMappedBuffer(); + + // Copy the name_buffer into a string without the \0 at the end const std::string name(name_buffer.begin(), name_buffer.end() - 1); + + // Copy thr value_buffer into a string without the \0 at the end std::string value(value_size - 1, '\0'); value_buffer.Read(&value[0], 0, value_size - 1); From 050d116cb6e5dead69cea9bcecb3f2eae85431da Mon Sep 17 00:00:00 2001 From: B3n30 Date: Tue, 24 Jul 2018 23:38:19 +0200 Subject: [PATCH 15/15] Fixed include in http_c,h; added ERROR_CONTEXT_ERROR to CreateContext --- src/core/hle/service/http_c.cpp | 3 +-- src/core/hle/service/http_c.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index 72dc2a450..b4611c748 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -54,8 +54,7 @@ void HTTP_C::CreateContext(Kernel::HLERequestContext& ctx) { LOG_ERROR(Service_HTTP, "invalid request method={}", static_cast(method)); IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - rb.Push(ResultCode(ErrCodes::InvalidContext, ErrorModule::HTTP, ErrorSummary::InvalidState, - ErrorLevel::Permanent)); + rb.Push(ERROR_CONTEXT_ERROR); rb.PushMappedBuffer(buffer); return; } diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h index e2d89e10d..8b77fb8af 100644 --- a/src/core/hle/service/http_c.h +++ b/src/core/hle/service/http_c.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include