mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-04-07 09:01:29 -06:00
Merge 45df9c72f0 into 3066887ff4
This commit is contained in:
commit
2aa9f4c424
@ -59,6 +59,8 @@ add_library(citra_common STATIC
|
||||
microprofile.cpp
|
||||
microprofile.h
|
||||
microprofileui.h
|
||||
network.cpp
|
||||
network.h
|
||||
param_package.cpp
|
||||
param_package.h
|
||||
play_time_manager.cpp
|
||||
|
||||
69
src/common/network.cpp
Normal file
69
src/common/network.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright 2020 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/network.h"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace Common {
|
||||
|
||||
URLInfo SplitUrl(const std::string& url) {
|
||||
const std::string prefix = "://";
|
||||
constexpr int default_http_port = 80;
|
||||
constexpr int default_https_port = 443;
|
||||
|
||||
std::string host;
|
||||
int port = -1;
|
||||
std::string path;
|
||||
|
||||
const auto scheme_end = url.find(prefix);
|
||||
const auto prefix_end = scheme_end == std::string::npos ? 0 : scheme_end + prefix.length();
|
||||
bool is_https = scheme_end != std::string::npos && url.starts_with("https");
|
||||
const auto path_index = url.find("/", prefix_end);
|
||||
|
||||
if (path_index == std::string::npos) {
|
||||
// If no path is specified after the host, set it to "/"
|
||||
host = url.substr(prefix_end);
|
||||
path = "/";
|
||||
} else {
|
||||
host = url.substr(prefix_end, path_index - prefix_end);
|
||||
path = url.substr(path_index);
|
||||
}
|
||||
|
||||
const auto port_start = host.find(":");
|
||||
if (port_start != std::string::npos) {
|
||||
std::string port_str = host.substr(port_start + 1);
|
||||
host = host.substr(0, port_start);
|
||||
char* p_end = nullptr;
|
||||
port = std::strtol(port_str.c_str(), &p_end, 10);
|
||||
if (*p_end) {
|
||||
port = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (port == -1) {
|
||||
port = is_https ? default_https_port : default_http_port;
|
||||
}
|
||||
return URLInfo{
|
||||
.is_https = is_https,
|
||||
.host = host,
|
||||
.port = port,
|
||||
.path = path,
|
||||
};
|
||||
}
|
||||
|
||||
static std::optional<URLInfo> get_proxy(const char* specific) {
|
||||
// Try scheme-specific proxy first, then generic proxy
|
||||
const char* proxy_url = std::getenv(specific);
|
||||
if (!proxy_url) proxy_url = std::getenv("all_proxy");
|
||||
// No proxy in use
|
||||
if (!proxy_url) return std::nullopt;
|
||||
|
||||
URLInfo proxy_info = SplitUrl(proxy_url);
|
||||
return proxy_info;
|
||||
}
|
||||
|
||||
std::optional<URLInfo> http_proxy = get_proxy("http_proxy");
|
||||
std::optional<URLInfo> https_proxy = get_proxy("https_proxy");
|
||||
|
||||
} // namespace Common
|
||||
25
src/common/network.h
Normal file
25
src/common/network.h
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
namespace Common {
|
||||
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
|
||||
// is_https: true; host: citra-emu.org; port: 443; path: /index.html
|
||||
URLInfo SplitUrl(const std::string& url);
|
||||
|
||||
extern std::optional<URLInfo> http_proxy;
|
||||
extern std::optional<URLInfo> https_proxy;
|
||||
|
||||
}
|
||||
@ -6,6 +6,7 @@
|
||||
#include "common/archives.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/network.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc.h"
|
||||
@ -186,12 +187,64 @@ void Module::Interface::RegisterDisconnectEvent(Kernel::HLERequestContext& ctx)
|
||||
|
||||
void Module::Interface::GetConnectingProxyEnable(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
constexpr bool proxy_enabled = false;
|
||||
const bool proxy_enabled = Common::https_proxy.has_value();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(proxy_enabled);
|
||||
}
|
||||
|
||||
void Module::Interface::GetConnectingProxyAuthType(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
const int proxy_auth = 0;
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(proxy_auth);
|
||||
LOG_WARNING(Service_AC, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Module::Interface::GetConnectingProxyPort(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
const int proxy_port = Common::https_proxy->port;
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(proxy_port);
|
||||
}
|
||||
|
||||
void Module::Interface::GetConnectingProxyHost(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
const std::string& proxy_host = Common::https_proxy->host;
|
||||
|
||||
std::vector<u8> buffer(proxy_host.begin(), proxy_host.end());
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushStaticBuffer(std::move(buffer), 0);
|
||||
}
|
||||
|
||||
void Module::Interface::GetConnectingProxyUserName(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
const std::string proxy_user = "";
|
||||
|
||||
std::vector<u8> buffer(proxy_user.begin(), proxy_user.end());
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushStaticBuffer(std::move(buffer), 0);
|
||||
LOG_WARNING(Service_AC, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Module::Interface::GetConnectingProxyPassword(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
const std::string proxy_pass = "";
|
||||
|
||||
std::vector<u8> buffer(proxy_pass.begin(), proxy_pass.end());
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushStaticBuffer(std::move(buffer), 0);
|
||||
LOG_WARNING(Service_AC, "(STUBBED) called");
|
||||
}
|
||||
|
||||
|
||||
@ -160,6 +160,52 @@ public:
|
||||
*/
|
||||
void GetConnectingProxyEnable(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* AC::GetConnectingProxyAuthType service function
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
* 2 : int, proxy auth type enum
|
||||
*/
|
||||
void GetConnectingProxyAuthType(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* AC::GetConnectingProxyPort service function
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
* 2 : short, proxy port number
|
||||
*/
|
||||
void GetConnectingProxyPort(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* AC::GetConnectingProxyHost service function
|
||||
* Inputs:
|
||||
* 64 : Buffer size << 14 | 2
|
||||
* 65 : Output pointer to buffer
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void GetConnectingProxyHost(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* AC::GetConnectingProxyUserName service function
|
||||
* Inputs:
|
||||
* 64 : Buffer size << 14 | 2
|
||||
* 65 : Output pointer to buffer
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void GetConnectingProxyUserName(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* AC::GetConnectingProxyPassword service function
|
||||
* Inputs:
|
||||
* 64 : Buffer size << 14 | 2
|
||||
* 65 : Output pointer to buffer
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void GetConnectingProxyPassword(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* AC::IsConnected service function
|
||||
* Outputs:
|
||||
|
||||
@ -29,6 +29,11 @@ AC_I::AC_I(std::shared_ptr<Module> ac) : Module::Interface(std::move(ac), "ac:i"
|
||||
{0x002F, &AC_I::GetNZoneBeaconNotFoundEvent, "GetNZoneBeaconNotFoundEvent"},
|
||||
{0x0030, &AC_I::RegisterDisconnectEvent, "RegisterDisconnectEvent"},
|
||||
{0x0036, &AC_I::GetConnectingProxyEnable, "GetConnectingProxyEnable"},
|
||||
{0x0037, &AC_I::GetConnectingProxyAuthType, "GetConnectingProxyAuthType"},
|
||||
{0x0038, &AC_I::GetConnectingProxyPort, "GetConnectingProxyPort"},
|
||||
{0x0039, &AC_I::GetConnectingProxyHost, "GetConnectingProxyHost"},
|
||||
{0x003A, &AC_I::GetConnectingProxyUserName, "GetConnectingProxyUserName"},
|
||||
{0x003B, &AC_I::GetConnectingProxyPassword, "GetConnectingProxyPassword"},
|
||||
{0x003C, nullptr, "GetAPSSIDList"},
|
||||
{0x003E, &AC_I::IsConnected, "IsConnected"},
|
||||
{0x0040, &AC_I::SetClientVersion, "SetClientVersion"},
|
||||
|
||||
@ -29,6 +29,11 @@ AC_U::AC_U(std::shared_ptr<Module> ac) : Module::Interface(std::move(ac), "ac:u"
|
||||
{0x002F, &AC_U::GetNZoneBeaconNotFoundEvent, "GetNZoneBeaconNotFoundEvent"},
|
||||
{0x0030, &AC_U::RegisterDisconnectEvent, "RegisterDisconnectEvent"},
|
||||
{0x0036, &AC_U::GetConnectingProxyEnable, "GetConnectingProxyEnable"},
|
||||
{0x0037, &AC_U::GetConnectingProxyAuthType, "GetConnectingProxyAuthType"},
|
||||
{0x0038, &AC_U::GetConnectingProxyPort, "GetConnectingProxyPort"},
|
||||
{0x0039, &AC_U::GetConnectingProxyHost, "GetConnectingProxyHost"},
|
||||
{0x003A, &AC_U::GetConnectingProxyUserName, "GetConnectingProxyUserName"},
|
||||
{0x003B, &AC_U::GetConnectingProxyPassword, "GetConnectingProxyPassword"},
|
||||
{0x003C, nullptr, "GetAPSSIDList"},
|
||||
{0x003E, &AC_U::IsConnected, "IsConnected"},
|
||||
{0x0040, &AC_U::SetClientVersion, "SetClientVersion"},
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include <fmt/format.h>
|
||||
#include "common/archives.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/network.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/core.h"
|
||||
@ -111,53 +112,6 @@ constexpr Result ErrorIncompatibleSendPostData = // 0xD8A0A036
|
||||
Result(ErrCodes::IncompatibleSendPostData, ErrorModule::HTTP, ErrorSummary::InvalidState,
|
||||
ErrorLevel::Permanent);
|
||||
|
||||
// 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
|
||||
static URLInfo SplitUrl(const std::string& url) {
|
||||
const std::string prefix = "://";
|
||||
constexpr int default_http_port = 80;
|
||||
constexpr int default_https_port = 443;
|
||||
|
||||
std::string host;
|
||||
int port = -1;
|
||||
std::string path;
|
||||
|
||||
const auto scheme_end = url.find(prefix);
|
||||
const auto prefix_end = scheme_end == std::string::npos ? 0 : scheme_end + prefix.length();
|
||||
bool is_https = scheme_end != std::string::npos && url.starts_with("https");
|
||||
const auto path_index = url.find("/", prefix_end);
|
||||
|
||||
if (path_index == std::string::npos) {
|
||||
// If no path is specified after the host, set it to "/"
|
||||
host = url.substr(prefix_end);
|
||||
path = "/";
|
||||
} else {
|
||||
host = url.substr(prefix_end, path_index - prefix_end);
|
||||
path = url.substr(path_index);
|
||||
}
|
||||
|
||||
const auto port_start = host.find(":");
|
||||
if (port_start != std::string::npos) {
|
||||
std::string port_str = host.substr(port_start + 1);
|
||||
host = host.substr(0, port_start);
|
||||
char* p_end = nullptr;
|
||||
port = std::strtol(port_str.c_str(), &p_end, 10);
|
||||
if (*p_end) {
|
||||
port = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (port == -1) {
|
||||
port = is_https ? default_https_port : default_http_port;
|
||||
}
|
||||
return URLInfo{
|
||||
.is_https = is_https,
|
||||
.host = host,
|
||||
.port = port,
|
||||
.path = path,
|
||||
};
|
||||
}
|
||||
|
||||
static std::size_t WriteHeaders(httplib::Stream& stream,
|
||||
std::span<const Context::RequestHeader> headers) {
|
||||
std::size_t write_len = 0;
|
||||
@ -290,7 +244,7 @@ void Context::MakeRequest() {
|
||||
{RequestMethod::PutEmpty, "PUT"},
|
||||
};
|
||||
|
||||
URLInfo url_info = SplitUrl(url);
|
||||
Common::URLInfo url_info = Common::SplitUrl(url);
|
||||
|
||||
httplib::Request request;
|
||||
std::vector<Context::RequestHeader> pending_headers;
|
||||
@ -371,7 +325,7 @@ void Context::MakeRequest() {
|
||||
}
|
||||
}
|
||||
|
||||
void Context::MakeRequestNonSSL(httplib::Request& request, const URLInfo& url_info,
|
||||
void Context::MakeRequestNonSSL(httplib::Request& request, const Common::URLInfo& url_info,
|
||||
std::vector<Context::RequestHeader>& pending_headers) {
|
||||
httplib::Error error{-1};
|
||||
std::unique_ptr<httplib::Client> client =
|
||||
@ -382,6 +336,10 @@ void Context::MakeRequestNonSSL(httplib::Request& request, const URLInfo& url_in
|
||||
return HandleHeaderWrite(pending_headers, strm, httplib_headers);
|
||||
});
|
||||
|
||||
if (Common::http_proxy) {
|
||||
client->set_proxy(Common::http_proxy->host, Common::http_proxy->port);
|
||||
}
|
||||
|
||||
if (!client->send(request, response, error)) {
|
||||
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
||||
state = RequestState::Completed;
|
||||
@ -391,7 +349,7 @@ void Context::MakeRequestNonSSL(httplib::Request& request, const URLInfo& url_in
|
||||
}
|
||||
}
|
||||
|
||||
void Context::MakeRequestSSL(httplib::Request& request, const URLInfo& url_info,
|
||||
void Context::MakeRequestSSL(httplib::Request& request, const Common::URLInfo& url_info,
|
||||
std::vector<Context::RequestHeader>& pending_headers) {
|
||||
httplib::Error error{-1};
|
||||
X509* cert = nullptr;
|
||||
@ -440,6 +398,10 @@ void Context::MakeRequestSSL(httplib::Request& request, const URLInfo& url_info,
|
||||
return HandleHeaderWrite(pending_headers, strm, httplib_headers);
|
||||
});
|
||||
|
||||
if (Common::https_proxy) {
|
||||
client->set_proxy(Common::https_proxy->host, Common::https_proxy->port);
|
||||
}
|
||||
|
||||
if (!client->send(request, response, error)) {
|
||||
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
||||
state = RequestState::Completed;
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include <boost/serialization/weak_ptr.hpp>
|
||||
#include <httplib.h>
|
||||
#include "common/network.h"
|
||||
#include "common/thread.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/shared_memory.h"
|
||||
@ -89,13 +90,6 @@ enum class ClientCertID : u32 {
|
||||
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.
|
||||
/// There can only be at most one client certificate context attached to an HTTP context at any
|
||||
/// given time.
|
||||
@ -296,9 +290,9 @@ public:
|
||||
void ParseAsciiPostData();
|
||||
std::string ParseMultipartFormData();
|
||||
void MakeRequest();
|
||||
void MakeRequestNonSSL(httplib::Request& request, const URLInfo& url_info,
|
||||
void MakeRequestNonSSL(httplib::Request& request, const Common::URLInfo& url_info,
|
||||
std::vector<Context::RequestHeader>& pending_headers);
|
||||
void MakeRequestSSL(httplib::Request& request, const URLInfo& url_info,
|
||||
void MakeRequestSSL(httplib::Request& request, const Common::URLInfo& url_info,
|
||||
std::vector<Context::RequestHeader>& pending_headers);
|
||||
bool ContentProvider(size_t offset, size_t length, httplib::DataSink& sink);
|
||||
bool ChunkedContentProvider(size_t offset, httplib::DataSink& sink);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user