Apply suggestions
This commit is contained in:
parent
13418013a4
commit
b8c3f0648b
@ -65,13 +65,6 @@ const ResultCode ERROR_WRONG_CERT_HANDLE = // 0xD8A0A0C9
|
|||||||
const ResultCode ERROR_CERT_ALREADY_SET = // 0xD8A0A03D
|
const ResultCode ERROR_CERT_ALREADY_SET = // 0xD8A0A03D
|
||||||
ResultCode(61, ErrorModule::HTTP, ErrorSummary::InvalidState, ErrorLevel::Permanent);
|
ResultCode(61, ErrorModule::HTTP, ErrorSummary::InvalidState, ErrorLevel::Permanent);
|
||||||
|
|
||||||
struct URLInfo {
|
|
||||||
bool is_https;
|
|
||||||
std::string host;
|
|
||||||
int port;
|
|
||||||
std::string path;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Splits URL into its components. Example: https://citra-emu.org:443/index.html
|
// Splits URL into its components. Example: https://citra-emu.org:443/index.html
|
||||||
// is_https: true; host: citra-emu.org; port: 443; path: /index.html
|
// is_https: true; host: citra-emu.org; port: 443; path: /index.html
|
||||||
static URLInfo SplitUrl(const std::string& url) {
|
static URLInfo SplitUrl(const std::string& url) {
|
||||||
@ -166,7 +159,6 @@ void Context::MakeRequest() {
|
|||||||
URLInfo url_info = SplitUrl(url);
|
URLInfo url_info = SplitUrl(url);
|
||||||
|
|
||||||
httplib::Request request;
|
httplib::Request request;
|
||||||
httplib::Error error{-1};
|
|
||||||
std::vector<Context::RequestHeader> pending_headers;
|
std::vector<Context::RequestHeader> pending_headers;
|
||||||
request.method = request_method_strings.at(method);
|
request.method = request_method_strings.at(method);
|
||||||
request.path = url_info.path;
|
request.path = url_info.path;
|
||||||
@ -178,11 +170,6 @@ void Context::MakeRequest() {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto header_writter = [&pending_headers](httplib::Stream& strm,
|
|
||||||
httplib::Headers& httplib_headers) {
|
|
||||||
return HandleHeaderWrite(pending_headers, strm, httplib_headers);
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto& header : headers) {
|
for (const auto& header : headers) {
|
||||||
pending_headers.push_back(header);
|
pending_headers.push_back(header);
|
||||||
}
|
}
|
||||||
@ -200,59 +187,67 @@ void Context::MakeRequest() {
|
|||||||
|
|
||||||
state = RequestState::InProgress;
|
state = RequestState::InProgress;
|
||||||
|
|
||||||
// Sadly, we have to duplicate code, the class hierarchy in httplib is not very useful...
|
|
||||||
if (url_info.is_https) {
|
if (url_info.is_https) {
|
||||||
X509* cert = nullptr;
|
MakeRequestSSL(request, url_info, pending_headers);
|
||||||
EVP_PKEY* key = nullptr;
|
|
||||||
{
|
|
||||||
std::unique_ptr<httplib::SSLClient> client;
|
|
||||||
if (uses_default_client_cert) {
|
|
||||||
const unsigned char* tmpCertPtr = clcert_data->certificate.data();
|
|
||||||
const unsigned char* tmpKeyPtr = clcert_data->private_key.data();
|
|
||||||
cert = d2i_X509(nullptr, &tmpCertPtr, (long)clcert_data->certificate.size());
|
|
||||||
key = d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &tmpKeyPtr,
|
|
||||||
(long)clcert_data->private_key.size());
|
|
||||||
client =
|
|
||||||
std::make_unique<httplib::SSLClient>(url_info.host, url_info.port, cert, key);
|
|
||||||
} else if (auto client_cert = ssl_config.client_cert_ctx.lock()) {
|
|
||||||
const unsigned char* tmpCertPtr = client_cert->certificate.data();
|
|
||||||
const unsigned char* tmpKeyPtr = client_cert->private_key.data();
|
|
||||||
cert = d2i_X509(nullptr, &tmpCertPtr, (long)client_cert->certificate.size());
|
|
||||||
key = d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &tmpKeyPtr,
|
|
||||||
(long)client_cert->private_key.size());
|
|
||||||
client =
|
|
||||||
std::make_unique<httplib::SSLClient>(url_info.host, url_info.port, cert, key);
|
|
||||||
} else {
|
|
||||||
client = std::make_unique<httplib::SSLClient>(url_info.host, url_info.port);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(B3N30): Check for SSLOptions-Bits and set the verify method accordingly
|
|
||||||
// https://www.3dbrew.org/wiki/SSL_Services#SSLOpt
|
|
||||||
// Hack: Since for now RootCerts are not implemented we set the VerifyMode to None.
|
|
||||||
client->enable_server_certificate_verification(false);
|
|
||||||
|
|
||||||
client->set_header_writer(header_writter);
|
|
||||||
|
|
||||||
if (!client->send(request, response, error)) {
|
|
||||||
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
|
||||||
state = RequestState::TimedOut;
|
|
||||||
} else {
|
|
||||||
LOG_DEBUG(Service_HTTP, "Request successful");
|
|
||||||
// TODO(B3N30): Verify this state on HW
|
|
||||||
state = RequestState::ReadyToDownloadContent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cert) {
|
|
||||||
X509_free(cert);
|
|
||||||
}
|
|
||||||
if (key) {
|
|
||||||
EVP_PKEY_free(key);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
std::unique_ptr<httplib::Client> client =
|
MakeRequestNonSSL(request, url_info, pending_headers);
|
||||||
std::make_unique<httplib::Client>(url_info.host, url_info.port);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
client->set_header_writer(header_writter);
|
void Context::MakeRequestNonSSL(httplib::Request& request, const URLInfo& url_info,
|
||||||
|
std::vector<Context::RequestHeader>& pending_headers) {
|
||||||
|
httplib::Error error{-1};
|
||||||
|
std::unique_ptr<httplib::Client> client =
|
||||||
|
std::make_unique<httplib::Client>(url_info.host, url_info.port);
|
||||||
|
|
||||||
|
client->set_header_writer(
|
||||||
|
[&pending_headers](httplib::Stream& strm, httplib::Headers& httplib_headers) {
|
||||||
|
return HandleHeaderWrite(pending_headers, strm, httplib_headers);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!client->send(request, response, error)) {
|
||||||
|
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
||||||
|
state = RequestState::TimedOut;
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG(Service_HTTP, "Request successful");
|
||||||
|
// TODO(B3N30): Verify this state on HW
|
||||||
|
state = RequestState::ReadyToDownloadContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Context::MakeRequestSSL(httplib::Request& request, const URLInfo& url_info,
|
||||||
|
std::vector<Context::RequestHeader>& pending_headers) {
|
||||||
|
httplib::Error error{-1};
|
||||||
|
X509* cert = nullptr;
|
||||||
|
EVP_PKEY* key = nullptr;
|
||||||
|
{
|
||||||
|
std::unique_ptr<httplib::SSLClient> client;
|
||||||
|
if (uses_default_client_cert) {
|
||||||
|
const unsigned char* tmpCertPtr = clcert_data->certificate.data();
|
||||||
|
const unsigned char* tmpKeyPtr = clcert_data->private_key.data();
|
||||||
|
cert = d2i_X509(nullptr, &tmpCertPtr, (long)clcert_data->certificate.size());
|
||||||
|
key = d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &tmpKeyPtr,
|
||||||
|
(long)clcert_data->private_key.size());
|
||||||
|
client = std::make_unique<httplib::SSLClient>(url_info.host, url_info.port, cert, key);
|
||||||
|
} else if (auto client_cert = ssl_config.client_cert_ctx.lock()) {
|
||||||
|
const unsigned char* tmpCertPtr = client_cert->certificate.data();
|
||||||
|
const unsigned char* tmpKeyPtr = client_cert->private_key.data();
|
||||||
|
cert = d2i_X509(nullptr, &tmpCertPtr, (long)client_cert->certificate.size());
|
||||||
|
key = d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &tmpKeyPtr,
|
||||||
|
(long)client_cert->private_key.size());
|
||||||
|
client = std::make_unique<httplib::SSLClient>(url_info.host, url_info.port, cert, key);
|
||||||
|
} else {
|
||||||
|
client = std::make_unique<httplib::SSLClient>(url_info.host, url_info.port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(B3N30): Check for SSLOptions-Bits and set the verify method accordingly
|
||||||
|
// https://www.3dbrew.org/wiki/SSL_Services#SSLOpt
|
||||||
|
// Hack: Since for now RootCerts are not implemented we set the VerifyMode to None.
|
||||||
|
client->enable_server_certificate_verification(false);
|
||||||
|
|
||||||
|
client->set_header_writer(
|
||||||
|
[&pending_headers](httplib::Stream& strm, httplib::Headers& httplib_headers) {
|
||||||
|
return HandleHeaderWrite(pending_headers, strm, httplib_headers);
|
||||||
|
});
|
||||||
|
|
||||||
if (!client->send(request, response, error)) {
|
if (!client->send(request, response, error)) {
|
||||||
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
||||||
@ -263,6 +258,12 @@ void Context::MakeRequest() {
|
|||||||
state = RequestState::ReadyToDownloadContent;
|
state = RequestState::ReadyToDownloadContent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cert) {
|
||||||
|
X509_free(cert);
|
||||||
|
}
|
||||||
|
if (key) {
|
||||||
|
EVP_PKEY_free(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTP_C::Initialize(Kernel::HLERequestContext& ctx) {
|
void HTTP_C::Initialize(Kernel::HLERequestContext& ctx) {
|
||||||
|
@ -61,6 +61,13 @@ enum class ClientCertID : u32 {
|
|||||||
Default = 0x40, // Default client cert
|
Default = 0x40, // Default client cert
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct URLInfo {
|
||||||
|
bool is_https;
|
||||||
|
std::string host;
|
||||||
|
int port;
|
||||||
|
std::string path;
|
||||||
|
};
|
||||||
|
|
||||||
/// Represents a client certificate along with its private key, stored as a byte array of DER data.
|
/// 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
|
/// There can only be at most one client certificate context attached to an HTTP context at any
|
||||||
/// given time.
|
/// given time.
|
||||||
@ -134,8 +141,6 @@ public:
|
|||||||
Context(const Context&) = delete;
|
Context(const Context&) = delete;
|
||||||
Context& operator=(const Context&) = delete;
|
Context& operator=(const Context&) = delete;
|
||||||
|
|
||||||
void MakeRequest();
|
|
||||||
|
|
||||||
struct Proxy {
|
struct Proxy {
|
||||||
std::string url;
|
std::string url;
|
||||||
std::string username;
|
std::string username;
|
||||||
@ -215,6 +220,12 @@ public:
|
|||||||
size_t current_copied_data;
|
size_t current_copied_data;
|
||||||
bool uses_default_client_cert{};
|
bool uses_default_client_cert{};
|
||||||
httplib::Response response;
|
httplib::Response response;
|
||||||
|
|
||||||
|
void MakeRequest();
|
||||||
|
void MakeRequestNonSSL(httplib::Request& request, const URLInfo& url_info,
|
||||||
|
std::vector<Context::RequestHeader>& pending_headers);
|
||||||
|
void MakeRequestSSL(httplib::Request& request, const URLInfo& url_info,
|
||||||
|
std::vector<Context::RequestHeader>& pending_headers);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SessionData : public Kernel::SessionRequestHandler::SessionDataBase {
|
struct SessionData : public Kernel::SessionRequestHandler::SessionDataBase {
|
||||||
|
Loading…
Reference in New Issue
Block a user