diff --git a/Common/Net/HTTPClient.cpp b/Common/Net/HTTPClient.cpp index 83509bab62..c3f56ef3b4 100644 --- a/Common/Net/HTTPClient.cpp +++ b/Common/Net/HTTPClient.cpp @@ -18,6 +18,7 @@ #include "Common/Data/Encoding/Compression.h" #include "Common/Net/NetBuffer.h" #include "Common/Log.h" +#include "Core/HLE/sceNet.h" namespace net { @@ -63,8 +64,10 @@ 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 err; - if (!net::DNSResolve(host, port_str, &resolved_, err, type)) { + if (!net::DNSResolve(processedHostname.c_str(), port_str, &resolved_, err, type)) { WARN_LOG(Log::IO, "Failed to resolve host '%s': '%s' (%s)", host, err.c_str(), DNSTypeAsString(type)); // Zero port so that future calls fail. port_ = 0; diff --git a/Core/HLE/sceHttp.cpp b/Core/HLE/sceHttp.cpp index 33b0784e23..74d548b5db 100644 --- a/Core/HLE/sceHttp.cpp +++ b/Core/HLE/sceHttp.cpp @@ -747,8 +747,6 @@ static int sceHttpCreateConnectionWithURL(int templateID, const char *url, int e if (!baseURL.Valid()) return hleLogError(Log::sceNet, SCE_HTTP_ERROR_INVALID_URL, "invalid url"); - // TODO: Here we should look up baseURL.Host() in DNS. - httpObjects.emplace_back(std::make_shared(templateID, baseURL.Host().c_str(), baseURL.Protocol().c_str(), baseURL.Port(), enableKeepalive)); int retid = (int)httpObjects.size(); return hleLogDebug(Log::sceNet, retid); diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 4f0e5b73f7..3801b7a86f 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -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; diff --git a/Core/HLE/sceNet.h b/Core/HLE/sceNet.h index e53782f609..832ec75d82 100644 --- a/Core/HLE/sceNet.h +++ b/Core/HLE/sceNet.h @@ -125,6 +125,7 @@ bool IsNetworkConnected(); void StartInfraJsonDownload(); // Polls the fetch, if returns true, jsonOutput should be looked at. If it's empty, something went very wrong as we fallback on the asset file. bool PollInfraJsonDownload(std::string *jsonOutput); +std::string ProcessHostnameWithInfraDNS(const std::string& hostname); bool LoadAutoDNS(std::string_view json); void DeleteAutoDNSCacheFile(); diff --git a/Core/HLE/sceNetResolver.cpp b/Core/HLE/sceNetResolver.cpp index 756f823635..b4547b9289 100644 --- a/Core/HLE/sceNetResolver.cpp +++ b/Core/HLE/sceNetResolver.cpp @@ -86,72 +86,23 @@ static int sceNetResolverTerm() { // Note: timeouts are in seconds static int NetResolver_StartNtoA(NetResolver *resolver, u32 hostnamePtr, u32 inAddrPtr, int timeout, int retry) { - addrinfo *resolved = nullptr; - - std::string err; std::string hostname = std::string(safe_string(Memory::GetCharPointer(hostnamePtr))); - - SockAddrIN4 addr{}; - addr.in.sin_addr.s_addr = INADDR_NONE; - - // 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()); - hostname = alias; - } - - if (g_Config.bInfrastructureAutoDNS) { - // Also look up into the preconfigured fixed DNS JSON. - auto fixedDNSIter = GetInfraDNSConfig().fixedDNS.find(hostname); - 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(), hostname.c_str()); - hostname = 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, hostname.c_str(), &resolvedAddr)) { - INFO_LOG(Log::sceNet, "Not looking up '%s', already an IP address.", hostname.c_str()); - Memory::Write_U32(resolvedAddr, inAddrPtr); - return 0; - } + + // Process hostname with infra-DNS + std::string processedHostname = ProcessHostnameWithInfraDNS(hostname); // Flag resolver as in-progress - not relevant for sync functions but potentially relevant for async resolver->isRunning = true; - - // 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(), hostname.c_str(), &resolvedAddr)) { - char temp[32]; - inet_ntop(AF_INET, &resolvedAddr, temp, sizeof(temp)); + addrinfo *resolved = nullptr; + std::string err; + if (!net::DNSResolve(processedHostname, "", &resolved, err)) { + ERROR_LOG(Log::sceNet, "OS DNS Error Resolving %s (%s)", processedHostname.c_str(), err.c_str()); resolver->isRunning = false; - Memory::Write_U32(resolvedAddr, inAddrPtr); - INFO_LOG(Log::sceNet, "Direct lookup of '%s' from '%s' succeeded: %s (%08x)", hostname.c_str(), dnsServer.c_str(), temp, resolvedAddr); - return 0; - } - - WARN_LOG(Log::sceNet, "Direct DNS lookup of '%s' at DNS server '%s' failed. Trying OS DNS...", hostname.c_str(), g_Config.sInfrastructureDNSServer.c_str()); - - // Attempt to execute an OS DNS resolution - if (!net::DNSResolve(hostname, "", &resolved, err)) { - // TODO: Return an error based on the outputted "err" (unfortunately it's already converted to string) - ERROR_LOG(Log::sceNet, "OS DNS Error Resolving %s (%s)\n", hostname.c_str(), err.c_str()); return SCE_NET_RESOLVER_ERROR_INVALID_HOST; } - // If successful, write to memory + // Process results + SockAddrIN4 addr{}; if (resolved) { for (auto ptr = resolved; ptr != nullptr; ptr = ptr->ai_next) { switch (ptr->ai_family) { @@ -161,9 +112,7 @@ static int NetResolver_StartNtoA(NetResolver *resolver, u32 hostnamePtr, u32 inA } } net::DNSResolveFree(resolved); - Memory::Write_U32(addr.in.sin_addr.s_addr, inAddrPtr); - resolver->isRunning = false; INFO_LOG(Log::sceNet, "%s - Hostname: %s => IPv4: %s", __FUNCTION__, hostname.c_str(), ip2str(addr.in.sin_addr, false).c_str()); }