Merge pull request #20695 from hrydgard/dns-fixes

Infra DNS resolver code cleanup
This commit is contained in:
Henrik Rydgård
2025-08-06 08:47:51 +02:00
committed by GitHub
23 changed files with 96 additions and 85 deletions
+1 -1
View File
@@ -21,7 +21,7 @@
bool LoadRemoteFileList(const Path &url, const std::string &userAgent, bool *cancel, std::vector<File::FileInfo> &files) {
_dbg_assert_(url.Type() == PathType::HTTP);
http::Client http;
http::Client http(nullptr);
Buffer result;
int code = 500;
std::vector<std::string> responseHeaders;
+1 -2
View File
@@ -5,7 +5,6 @@
#include <cstring>
#include <iostream>
#include "Core/Config.h"
#include "Common/System/System.h"
#include "Common/System/Display.h"
#include "Common/Log.h"
@@ -171,7 +170,7 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
#endif
#endif
if ((flags_ & VulkanInitFlags::VALIDATE) && g_Config.sCustomDriver.empty()) {
if ((flags_ & VulkanInitFlags::VALIDATE) && info.customDriver.empty()) {
if (IsInstanceExtensionAvailable(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
// Enable the validation layers
for (size_t i = 0; i < ARRAY_SIZE(validationLayers); i++) {
+1
View File
@@ -184,6 +184,7 @@ public:
const char *app_name;
int app_ver;
VulkanInitFlags flags;
std::string customDriver;
};
VkResult CreateInstance(const CreateInfo &info);
+1 -1
View File
@@ -193,7 +193,7 @@ bool GhidraClient::FetchTypes() {
}
bool GhidraClient::FetchResource(const std::string &path, std::string &outResult) {
http::Client http;
http::Client http(nullptr);
if (!http.Resolve(host_.c_str(), port_)) {
pendingResult_.error = "can't resolve host";
return false;
+9 -5
View File
@@ -63,7 +63,11 @@ bool Connection::Resolve(const char *host, int port, DNSType type) {
char port_str[16];
snprintf(port_str, sizeof(port_str), "%d", port);
std::string processedHostname = ProcessHostnameWithInfraDNS(std::string(host));
std::string processedHostname(host);
if (customResolve_) {
processedHostname = customResolve_(host);
}
std::string err;
if (!net::DNSResolve(processedHostname.c_str(), port_str, &resolved_, err, type)) {
@@ -211,7 +215,7 @@ namespace http {
constexpr const char *DEFAULT_USERAGENT = "PPSSPP";
constexpr const char *HTTP_VERSION = "1.1";
Client::Client() {
Client::Client(net::ResolveFunc func) : Connection(func) {
userAgent_ = DEFAULT_USERAGENT;
httpVersion_ = HTTP_VERSION;
}
@@ -488,8 +492,8 @@ int Client::ReadResponseEntity(net::Buffer *readbuf, const std::vector<std::stri
return 0;
}
HTTPRequest::HTTPRequest(RequestMethod method, std::string_view url, std::string_view postData, std::string_view postMime, const Path &outfile, RequestFlags flags, std::string_view name)
: Request(method, url, name, &cancelled_, flags), postData_(postData), postMime_(postMime) {
HTTPRequest::HTTPRequest(RequestMethod method, std::string_view url, std::string_view postData, std::string_view postMime, const Path &outfile, RequestFlags flags, net::ResolveFunc customResolve, std::string_view name)
: Request(method, url, name, &cancelled_, flags), postData_(postData), postMime_(postMime), customResolve_(customResolve) {
outfile_ = outfile;
}
@@ -525,7 +529,7 @@ int HTTPRequest::Perform(const std::string &url) {
return -1;
}
http::Client client;
http::Client client(customResolve_);
if (!userAgent_.empty()) {
client.SetUserAgent(userAgent_);
}
+10 -3
View File
@@ -4,6 +4,7 @@
#include <memory>
#include <thread>
#include <cstdint>
#include <string>
#include "Common/File/Path.h"
#include "Common/Net/NetBuffer.h"
@@ -12,10 +13,14 @@
namespace net {
typedef std::function<std::string(const std::string &)> ResolveFunc;
class Connection {
public:
virtual ~Connection();
explicit Connection(ResolveFunc func) : customResolve_(func) {}
// Inits the sockaddr_in.
bool Resolve(const char *host, int port, DNSType type = DNSType::ANY);
@@ -35,9 +40,10 @@ protected:
private:
uintptr_t sock_ = -1;
ResolveFunc customResolve_;
};
} // namespace net
} // namespace net
namespace http {
@@ -55,7 +61,7 @@ public:
class Client : public net::Connection {
public:
Client();
Client(net::ResolveFunc func);
~Client();
// Return value is the HTTP return code. 200 means OK. < 0 means some local error.
@@ -95,7 +101,7 @@ protected:
// Really an asynchronous request.
class HTTPRequest : public Request {
public:
HTTPRequest(RequestMethod method, std::string_view url, std::string_view postData, std::string_view postMime, const Path &outfile, RequestFlags flags = RequestFlags::ProgressBar | RequestFlags::ProgressBarDelayed, std::string_view name = "");
HTTPRequest(RequestMethod method, std::string_view url, std::string_view postData, std::string_view postMime, const Path &outfile, RequestFlags flags, net::ResolveFunc customResolve, std::string_view name = "");
~HTTPRequest();
void Start() override;
@@ -115,6 +121,7 @@ private:
std::string postMime_;
bool completed_ = false;
bool failed_ = false;
net::ResolveFunc customResolve_;
};
// Fake request for cache hits.
+5 -5
View File
@@ -59,7 +59,7 @@ Path RequestManager::UrlToCachePath(const std::string_view url) {
return http::UrlToCachePath(cacheDir_, url);
}
std::shared_ptr<Request> CreateRequest(RequestMethod method, std::string_view url, std::string_view postdata, std::string_view postMime, const Path &outfile, RequestFlags flags, std::string_view name) {
static std::shared_ptr<Request> CreateRequest(RequestMethod method, std::string_view url, std::string_view postdata, std::string_view postMime, const Path &outfile, RequestFlags flags, net::ResolveFunc customResolve, std::string_view name) {
if (IsHttpsUrl(url) && System_GetPropertyBool(SYSPROP_SUPPORTS_HTTPS)) {
#ifndef HTTPS_NOT_AVAILABLE
return std::make_shared<HTTPSRequest>(method, url, postdata, postMime, outfile, flags, name);
@@ -67,7 +67,7 @@ std::shared_ptr<Request> CreateRequest(RequestMethod method, std::string_view ur
return std::shared_ptr<Request>();
#endif
} else {
return std::make_shared<HTTPRequest>(method, url, postdata, postMime, outfile, flags, name);
return std::make_shared<HTTPRequest>(method, url, postdata, postMime, outfile, flags, customResolve, name);
}
}
@@ -105,7 +105,7 @@ std::shared_ptr<Request> RequestManager::StartDownload(std::string_view url, con
}
}
std::shared_ptr<Request> dl = CreateRequest(RequestMethod::GET, url, "", "", outfile, flags, "");
std::shared_ptr<Request> dl = CreateRequest(RequestMethod::GET, url, "", "", outfile, flags, nullptr, "");
// OK, didn't get it from cache, so let's continue with the download, putting it in the cache.
if (enableCache) {
@@ -131,7 +131,7 @@ std::shared_ptr<Request> RequestManager::StartDownloadWithCallback(
std::function<void(Request &)> callback,
std::string_view name,
const char *acceptMime) {
std::shared_ptr<Request> dl = CreateRequest(RequestMethod::GET, url, "", "", outfile, flags, name);
std::shared_ptr<Request> dl = CreateRequest(RequestMethod::GET, url, "", "", outfile, flags, nullptr, name);
if (!userAgent_.empty())
dl->SetUserAgent(userAgent_);
@@ -150,7 +150,7 @@ std::shared_ptr<Request> RequestManager::AsyncPostWithCallback(
RequestFlags flags,
std::function<void(Request &)> callback,
std::string_view name) {
std::shared_ptr<Request> dl = CreateRequest(RequestMethod::POST, url, postData, postMime, Path(), flags, name);
std::shared_ptr<Request> dl = CreateRequest(RequestMethod::POST, url, postData, postMime, Path(), flags, nullptr, name);
if (!userAgent_.empty())
dl->SetUserAgent(userAgent_);
dl->SetCallback(callback);
+1 -52
View File
@@ -1,7 +1,4 @@
#include "Core/Config.h"
#include "Core/HLE/sceNet.h"
#include "ppsspp_config.h"
#include "Common/Net/Resolve.h"
#include <cstdio>
#include <cstdlib>
@@ -15,6 +12,7 @@
#include "Common/StringUtils.h"
#include "Common/Data/Encoding/Utf8.h"
#include "Common/Net/SocketCompat.h"
#include "Common/Net/Resolve.h"
#ifndef HTTPS_NOT_AVAILABLE
#include "ext/naett/naett.h"
@@ -504,53 +502,4 @@ bool DirectDNSLookupIPV4(const char *dns_server_ip, const char *domain, uint32_t
return true;
}
std::string ProcessHostnameWithInfraDNS(const std::string& hostname) {
std::string resolvedHostname = hostname;
// Resolve any aliases. First check the ini file, then check the hardcoded DNS config.
auto aliasIter = g_Config.mHostToAlias.find(hostname);
if (aliasIter != g_Config.mHostToAlias.end()) {
const std::string& alias = aliasIter->second;
INFO_LOG(Log::sceNet, "%s - Resolved alias %s from hostname %s", __FUNCTION__, alias.c_str(), hostname.c_str());
resolvedHostname = alias;
}
if (g_Config.bInfrastructureAutoDNS) {
// Also look up into the preconfigured fixed DNS JSON.
auto fixedDNSIter = GetInfraDNSConfig().fixedDNS.find(resolvedHostname);
if (fixedDNSIter != GetInfraDNSConfig().fixedDNS.end()) {
const std::string& domainIP = fixedDNSIter->second;
INFO_LOG(Log::sceNet, "%s - Resolved IP %s from fixed DNS lookup with '%s'", __FUNCTION__, domainIP.c_str(), resolvedHostname.c_str());
resolvedHostname = domainIP;
}
}
// Check if hostname is already an IPv4 address, if so we do not need further lookup. This usually happens
// after the mHostToAlias or fixedDNSIter lookups, which effectively both are hardcoded DNS.
uint32_t resolvedAddr;
if (inet_pton(AF_INET, resolvedHostname.c_str(), &resolvedAddr)) {
INFO_LOG(Log::sceNet, "Not looking up '%s', already an IP address.", resolvedHostname.c_str());
return resolvedHostname;
}
// Now use the configured primary DNS server to do a lookup.
// If auto DNS, use the server from that config.
std::string dnsServer;
if (g_Config.bInfrastructureAutoDNS && !GetInfraDNSConfig().dns.empty()) {
dnsServer = GetInfraDNSConfig().dns;
} else {
dnsServer = g_Config.sInfrastructureDNSServer;
}
if (net::DirectDNSLookupIPV4(dnsServer.c_str(), resolvedHostname.c_str(), &resolvedAddr)) {
char temp[32];
inet_ntop(AF_INET, &resolvedAddr, temp, sizeof(temp));
INFO_LOG(Log::sceNet, "Direct lookup of '%s' from '%s' succeeded: %s", resolvedHostname.c_str(), dnsServer.c_str(), temp);
return std::string(temp);
}
WARN_LOG(Log::sceNet, "Direct DNS lookup of '%s' at DNS server '%s' failed. Will try OS DNS...", resolvedHostname.c_str(), dnsServer.c_str());
return resolvedHostname;
}
} // namespace net
-1
View File
@@ -26,6 +26,5 @@ int inet_pton(int af, const char* src, void* dst);
// Does a DNS lookup without involving the OS, so you can hit any DNS server.
bool DirectDNSLookupIPV4(const char *dnsServer, const char *host, uint32_t *ipv4_addr);
std::string ProcessHostnameWithInfraDNS(const std::string& hostname);
} // namespace net
+1 -2
View File
@@ -7,12 +7,11 @@
#include "Common/UI/UI.h"
#include "Common/UI/View.h"
#include "Common/UI/ViewGroup.h"
#include "Common/Data/Collections/TinySet.h"
#include "Common/Log.h"
#include "Common/TimeUtil.h"
#include "Core/KeyMap.h"
void Screen::focusChanged(ScreenFocusChange focusChange) {
const char *eventName = "";
switch (focusChange) {
+1 -2
View File
@@ -14,8 +14,7 @@
#include "Common/Math/lin/matrix4x4.h"
#include "Common/Input/InputState.h"
#include "Common/Input/KeyCodes.h"
// The deps below need to be inverted, or we need to move this file (probably better)
#include "Core/HLE/sceDisplay.h"
#include "Core/HLE/sceCtrl.h"
+1 -1
View File
@@ -23,7 +23,7 @@
#include "Core/FileLoaders/HTTPFileLoader.h"
HTTPFileLoader::HTTPFileLoader(const ::Path &filename)
: url_(filename.ToString()), progress_(&cancel_), filename_(filename) {
: url_(filename.ToString()), progress_(&cancel_), filename_(filename), client_(nullptr) { // no custom resolver support
}
void HTTPFileLoader::Prepare() {
+4 -3
View File
@@ -27,6 +27,7 @@
#include "Core/HLE/FunctionWrappers.h"
#include "Core/HLE/sceKernelMemory.h"
#include "Core/HLE/sceHttp.h"
#include "Core/HLE/sceNet.h"
#include "Core/Debugger/MemBlockInfo.h"
#include "Common/StringUtils.h"
#include "Common/LogReporting.h"
@@ -80,7 +81,7 @@ HTTPConnection::HTTPConnection(int templateID, const char* hostString, const cha
this->enableKeepalive = enableKeepalive;
}
HTTPRequest::HTTPRequest(int connectionID, int method, const char* url, u64 contentLength) {
HTTPRequest::HTTPRequest(int connectionID, int method, const char *url, u64 contentLength, net::ResolveFunc customResolver) : client(customResolver) {
// Copy base data as initial base value for this
// Since dynamic_cast/dynamic_pointer_cast/typeid requires RTTI to be enabled (ie. /GR instead of /GR- on msvc, enabled by default on most compilers), so we can only use static_cast here
HTTPConnection::operator=(static_cast<HTTPConnection&>(*httpObjects[connectionID - 1LL]));
@@ -558,7 +559,7 @@ static int sceHttpCreateRequest(int connectionID, int method, const char *path,
if (method < PSPHttpMethod::PSP_HTTP_METHOD_GET || method > PSPHttpMethod::PSP_HTTP_METHOD_HEAD)
return hleLogError(Log::sceNet, SCE_HTTP_ERROR_UNKNOWN_METHOD, "unknown method");
httpObjects.emplace_back(std::make_shared<HTTPRequest>(connectionID, method, path? path:"", contentLength));
httpObjects.emplace_back(std::make_shared<HTTPRequest>(connectionID, method, path ? path : "", contentLength, &ProcessHostnameWithInfraDNS));
int retid = (int)httpObjects.size();
return hleLogDebug(Log::sceNet, retid);
}
@@ -729,7 +730,7 @@ static int sceHttpCreateRequestWithURL(int connectionID, int method, const char
if (!baseURL.Valid())
return hleLogError(Log::sceNet, SCE_HTTP_ERROR_INVALID_URL, "invalid url");
httpObjects.emplace_back(std::make_shared<HTTPRequest>(connectionID, method, url ? url : "", contentLength));
httpObjects.emplace_back(std::make_shared<HTTPRequest>(connectionID, method, url ? url : "", contentLength, &ProcessHostnameWithInfraDNS));
int retid = (int)httpObjects.size();
return hleLogDebug(Log::sceNet, retid);
}
+1 -1
View File
@@ -268,7 +268,7 @@ private:
std::string responseContent_;
public:
HTTPRequest(int connectionID, int method, const char* url, u64 contentLength);
HTTPRequest(int connectionID, int method, const char* url, u64 contentLength, net::ResolveFunc customResolver);
~HTTPRequest();
virtual const char* className() override { return name_HTTPRequest; }
+49
View File
@@ -464,6 +464,55 @@ bool PollInfraJsonDownload(std::string *jsonOutput) {
return true;
}
std::string ProcessHostnameWithInfraDNS(const std::string &hostname) {
std::string resolvedHostname = hostname;
// Resolve any aliases. First check the ini file, then check the hardcoded DNS config.
auto aliasIter = g_Config.mHostToAlias.find(hostname);
if (aliasIter != g_Config.mHostToAlias.end()) {
const std::string& alias = aliasIter->second;
INFO_LOG(Log::sceNet, "%s - Resolved alias %s from hostname %s", __FUNCTION__, alias.c_str(), hostname.c_str());
resolvedHostname = alias;
}
if (g_Config.bInfrastructureAutoDNS) {
// Also look up into the preconfigured fixed DNS JSON.
auto fixedDNSIter = GetInfraDNSConfig().fixedDNS.find(resolvedHostname);
if (fixedDNSIter != GetInfraDNSConfig().fixedDNS.end()) {
const std::string& domainIP = fixedDNSIter->second;
INFO_LOG(Log::sceNet, "%s - Resolved IP %s from fixed DNS lookup with '%s'", __FUNCTION__, domainIP.c_str(), resolvedHostname.c_str());
resolvedHostname = domainIP;
}
}
// Check if hostname is already an IPv4 address, if so we do not need further lookup. This usually happens
// after the mHostToAlias or fixedDNSIter lookups, which effectively both are hardcoded DNS.
uint32_t resolvedAddr;
if (inet_pton(AF_INET, resolvedHostname.c_str(), &resolvedAddr)) {
INFO_LOG(Log::sceNet, "Not looking up '%s', already an IP address.", resolvedHostname.c_str());
return resolvedHostname;
}
// Now use the configured primary DNS server to do a lookup.
// If auto DNS, use the server from that config.
std::string dnsServer;
if (g_Config.bInfrastructureAutoDNS && !GetInfraDNSConfig().dns.empty()) {
dnsServer = GetInfraDNSConfig().dns;
} else {
dnsServer = g_Config.sInfrastructureDNSServer;
}
if (net::DirectDNSLookupIPV4(dnsServer.c_str(), resolvedHostname.c_str(), &resolvedAddr)) {
char temp[32];
inet_ntop(AF_INET, &resolvedAddr, temp, sizeof(temp));
INFO_LOG(Log::sceNet, "Direct lookup of '%s' from '%s' succeeded: %s", resolvedHostname.c_str(), dnsServer.c_str(), temp);
return std::string(temp);
}
WARN_LOG(Log::sceNet, "Direct DNS lookup of '%s' at DNS server '%s' failed. Will try OS DNS...", resolvedHostname.c_str(), dnsServer.c_str());
return resolvedHostname;
}
void InitLocalhostIP() {
// The entire 127.*.*.* is reserved for loopback.
uint32_t localIP = 0x7F000001 + PPSSPP_ID - 1;
+1
View File
@@ -127,6 +127,7 @@ void StartInfraJsonDownload();
bool PollInfraJsonDownload(std::string *jsonOutput);
bool LoadAutoDNS(std::string_view json);
void DeleteAutoDNSCacheFile();
std::string ProcessHostnameWithInfraDNS(const std::string &hostname);
// These return false if allowed to be consistent with the similar function for achievements.
bool NetworkWarnUserIfOnlineAndCantSavestate();
+1 -1
View File
@@ -89,7 +89,7 @@ static int NetResolver_StartNtoA(NetResolver *resolver, u32 hostnamePtr, u32 inA
std::string hostname = std::string(safe_string(Memory::GetCharPointer(hostnamePtr)));
// Process hostname with infra-DNS
std::string processedHostname = net::ProcessHostnameWithInfraDNS(hostname);
std::string processedHostname = ProcessHostnameWithInfraDNS(hostname);
// Flag resolver as in-progress - not relevant for sync functions but potentially relevant for async
resolver->isRunning = true;
+2 -1
View File
@@ -22,6 +22,7 @@
#include "Core/CoreTiming.h"
#include "Core/HLE/HLE.h"
#include "Core/HLE/FunctionWrappers.h"
#include "Core/HLE/sceNet.h"
#include "Core/HLE/sceNp.h"
#include "Core/HLE/sceNp2.h"
@@ -157,7 +158,7 @@ static int sceNpMatching2ContextStart(int ctxId)
// TODO: use sceNpGetUserProfile and check server availability using sceNpService_76867C01
//npMatching2Ctx.started = true;
Url url("http://static-resource.np.community.playstation.net/np/resource/psp-title/" + std::string(npTitleId.data) + "_00/matching/" + std::string(npTitleId.data) + "_00-matching.xml");
http::Client client;
http::Client client(&ProcessHostnameWithInfraDNS);
bool cancelled = false;
net::RequestProgress progress(&cancelled);
if (!client.Resolve(url.Host().c_str(), url.Port())) {
+2 -2
View File
@@ -246,7 +246,7 @@ static int sceUriBuild(u32 workAreaAddr, u32 workAreaSizeAddr, int workAreaSize,
}
if (workAreaAddr == 0) {
return hleLogDebug(Log::sceNet, -1, "size query, required size: %d", requiredSize);
return hleLogDebug(Log::sceNet, 0, "size query, required size: %d", requiredSize);
}
if (requiredSize > workAreaSize) {
@@ -305,7 +305,7 @@ static int sceUriEscape(u32 escapedAddr, u32 escapedLengthAddr, int escapedBuffe
}
if (escapedAddr == 0) {
return hleLogError(Log::sceNet, -1, "size query, required size: %d", requiredSize);
return hleLogDebug(Log::sceNet, 0, "size query, required size: %d", requiredSize);
}
if (requiredSize > escapedBufferLength) {
+1 -1
View File
@@ -76,7 +76,7 @@ static ServerStatus RetrieveStatus() {
// relay that address to a mobile device searching for the server.
static bool RegisterServer(int port) {
bool success = false;
http::Client http;
http::Client http(nullptr);
bool cancelled = false;
net::RequestProgress progress(&cancelled);
Buffer theVoid = Buffer::Void();
+1
View File
@@ -72,6 +72,7 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, in
info.app_name = "PPSSPP";
info.app_ver = gitVer.ToInteger();
info.flags = FlagsFromConfig();
info.customDriver = g_Config.sCustomDriver;
if (VK_SUCCESS != vulkan_->CreateInstance(info)) {
*error_message = vulkan_->InitError();
delete vulkan_;
+1 -1
View File
@@ -106,7 +106,7 @@ std::string RemoteSubdir() {
}
bool RemoteISOConnectScreen::FindServer(std::string &resultHost, int &resultPort) {
http::Client http;
http::Client http(nullptr);
Buffer result;
int code = 500;
bool hadTimeouts = false;
+1
View File
@@ -71,6 +71,7 @@ bool AndroidVulkanContext::InitAPI() {
info.app_name = "PPSSPP";
info.app_ver = gitVer.ToInteger();
info.flags = FlagsFromConfig();
info.customDriver = g_Config.sCustomDriver;
if (!g_Vulkan->CreateInstanceAndDevice(info)) {
delete g_Vulkan;
g_Vulkan = nullptr;