From e65c5bfdb6c7b58753eb845cbf3de83c961ebc29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 4 Sep 2025 17:11:50 +0200 Subject: [PATCH] Break out the http::RequestManager from HTTPClient.h --- Common/Common.vcxproj | 2 + Common/Common.vcxproj.filters | 6 + Common/Net/HTTPClient.h | 16 --- Common/Net/HTTPRequest.cpp | 151 ---------------------- Common/Net/HTTPRequest.h | 51 -------- Common/Net/HTTPRequestManager.cpp | 164 ++++++++++++++++++++++++ Common/Net/HTTPRequestManager.h | 75 +++++++++++ Core/Config.cpp | 2 +- Core/HLE/sceNet.cpp | 1 + Core/Reporting.cpp | 1 + Core/RetroAchievements.cpp | 1 + Core/Util/GameManager.cpp | 1 + UI/DevScreens.cpp | 2 +- UI/NativeApp.cpp | 4 +- UI/Store.cpp | 2 +- UWP/CommonUWP/CommonUWP.vcxproj | 2 + UWP/CommonUWP/CommonUWP.vcxproj.filters | 6 + android/jni/Android.mk | 1 + libretro/Makefile.common | 1 + 19 files changed, 266 insertions(+), 223 deletions(-) create mode 100644 Common/Net/HTTPRequestManager.cpp create mode 100644 Common/Net/HTTPRequestManager.h diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index c4a706bfaa..9dd8b7ff04 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -453,6 +453,7 @@ + @@ -909,6 +910,7 @@ + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 1b17924f6a..207752c73d 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -692,6 +692,9 @@ Net + + Net + @@ -1296,6 +1299,9 @@ Net + + Net + diff --git a/Common/Net/HTTPClient.h b/Common/Net/HTTPClient.h index 397e3d1683..875c3b091c 100644 --- a/Common/Net/HTTPClient.h +++ b/Common/Net/HTTPClient.h @@ -92,20 +92,4 @@ private: net::ResolveFunc customResolve_; }; -// Fake request for cache hits. -// The download manager uses this when caching was requested, and a new-enough file was present in the cache directory. -// This is simply a finished request, that can still be queried like a normal one so users don't know it came from the cache. -class CachedRequest : public Request { -public: - CachedRequest(RequestMethod method, std::string_view url, std::string_view name, bool *cancelled, RequestFlags flags, std::string_view responseData) - : Request(method, url, name, cancelled, flags) - { - buffer_.Append(responseData); - } - void Start() override {} - void Join() override {} - bool Done() override { return true; } - bool Failed() const override { return false; } -}; - } // namespace http diff --git a/Common/Net/HTTPRequest.cpp b/Common/Net/HTTPRequest.cpp index 21ddf14516..fc00f0f9f6 100644 --- a/Common/Net/HTTPRequest.cpp +++ b/Common/Net/HTTPRequest.cpp @@ -36,155 +36,4 @@ Request::Request(RequestMethod method, std::string_view url, std::string_view na }; } -static bool IsHttpsUrl(std::string_view url) { - return startsWith(url, "https:"); -} - -Path UrlToCachePath(const Path &cacheDir, std::string_view url) { - std::string fn = "DLCACHE_"; - for (auto c : url) { - if (isalnum(c) || c == '.' || c == '-' || c == '_') { - fn.push_back(tolower(c)); - } else { - fn.push_back('_'); - } - } - return cacheDir / fn; -} - -Path RequestManager::UrlToCachePath(const std::string_view url) { - if (cacheDir_.empty()) { - return Path(); - } - return http::UrlToCachePath(cacheDir_, url); -} - -static std::shared_ptr 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(method, url, postdata, postMime, outfile, flags, name); -#else - return std::shared_ptr(); -#endif - } else { - return std::make_shared(method, url, postdata, postMime, outfile, flags, customResolve, name); - } -} - -std::shared_ptr RequestManager::StartDownload(std::string_view url, const Path &outfile, RequestFlags flags, const char *acceptMime) { - const bool enableCache = !cacheDir_.empty() && (flags & RequestFlags::Cached24H); - - // Come up with a cache file path. - Path cacheFile = UrlToCachePath(url); - - if (enableCache) { - _dbg_assert_(outfile.empty()); // It's automatically replaced below - - // TODO: This should be done on the thread, maybe. But let's keep it simple for now. - time_t cacheFileTime; - if (File::GetModifTimeT(cacheFile, &cacheFileTime)) { - time_t now = (time_t)time_now_unix_utc(); - if (cacheFileTime > now - 24 * 60 * 60) { - // The file is new enough. Let's construct a fake, already finished download so we don't need - // to modify the calling code. - std::string contents; - if (File::ReadBinaryFileToString(cacheFile, &contents)) { - INFO_LOG(Log::sceNet, "Returning cached file for %.*s: %s", (int)url.size(), url.data(), cacheFile.c_str()); - // All is well, but we've indented a bit much here. - std::shared_ptr dl(new CachedRequest(RequestMethod::GET, url, "infra-dns.json", nullptr, flags, contents)); - newDownloads_.push_back(dl); - return dl; - } else { - INFO_LOG(Log::sceNet, "Failed reading from cache, proceeding with request"); - } - } else { - INFO_LOG(Log::sceNet, "Cached file too old, proceeding with request"); - } - } else { - INFO_LOG(Log::sceNet, "Failed to check time modified. Proceeding with request."); - } - } - - std::shared_ptr 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) { - dl->OverrideOutFile(cacheFile); - dl->AddFlag(RequestFlags::KeepInMemory); - } - - if (!userAgent_.empty()) { - dl->SetUserAgent(userAgent_); - } - if (acceptMime) { - dl->SetAccept(acceptMime); - } - newDownloads_.push_back(dl); - dl->Start(); - return dl; -} - -std::shared_ptr RequestManager::StartDownloadWithCallback( - std::string_view url, - const Path &outfile, - RequestFlags flags, - std::function callback, - std::string_view name, - const char *acceptMime) { - std::shared_ptr dl = CreateRequest(RequestMethod::GET, url, "", "", outfile, flags, nullptr, name); - - if (!userAgent_.empty()) - dl->SetUserAgent(userAgent_); - if (acceptMime) - dl->SetAccept(acceptMime); - dl->SetCallback(callback); - newDownloads_.push_back(dl); - dl->Start(); - return dl; -} - -std::shared_ptr RequestManager::AsyncPostWithCallback( - std::string_view url, - std::string_view postData, - std::string_view postMime, - RequestFlags flags, - std::function callback, - std::string_view name) { - std::shared_ptr dl = CreateRequest(RequestMethod::POST, url, postData, postMime, Path(), flags, nullptr, name); - if (!userAgent_.empty()) - dl->SetUserAgent(userAgent_); - dl->SetCallback(callback); - newDownloads_.push_back(dl); - dl->Start(); - return dl; -} - -void RequestManager::Update() { - for (auto &iter : newDownloads_) { - downloads_.push_back(iter); - } - newDownloads_.clear(); - -restart: - for (size_t i = 0; i < downloads_.size(); i++) { - auto dl = downloads_[i]; - if (dl->Done()) { - dl->RunCallback(); - dl->Join(); - downloads_.erase(downloads_.begin() + i); - goto restart; - } - } -} - -void RequestManager::CancelAll() { - for (size_t i = 0; i < downloads_.size(); i++) { - downloads_[i]->Cancel(); - } - for (size_t i = 0; i < downloads_.size(); i++) { - downloads_[i]->Join(); - } - downloads_.clear(); -} - } // namespace diff --git a/Common/Net/HTTPRequest.h b/Common/Net/HTTPRequest.h index 31867eb4a4..999e34e5bf 100644 --- a/Common/Net/HTTPRequest.h +++ b/Common/Net/HTTPRequest.h @@ -96,57 +96,6 @@ private: std::function callback_; }; -using std::shared_ptr; - -class RequestManager { -public: - ~RequestManager() { - CancelAll(); - } - - // NOTE: This is the only version that supports the cache flag (for now). - std::shared_ptr StartDownload(std::string_view url, const Path &outfile, RequestFlags flags, const char *acceptMime = nullptr); - - std::shared_ptr StartDownloadWithCallback( - std::string_view url, - const Path &outfile, - RequestFlags flags, - std::function callback, - std::string_view name = "", - const char *acceptMime = nullptr); - - std::shared_ptr AsyncPostWithCallback( - std::string_view url, - std::string_view postData, - std::string_view postMime, // Use postMime = "application/x-www-form-urlencoded" for standard form-style posts, such as used by retroachievements. For encoding form data manually we have MultipartFormDataEncoder. - RequestFlags flags, - std::function callback, - std::string_view name = ""); - - // Drops finished downloads from the list. - void Update(); - void CancelAll(); - - void SetUserAgent(std::string_view userAgent) { - userAgent_ = userAgent; - } - - void SetCacheDir(const Path &path) { - cacheDir_ = path; - } - - Path UrlToCachePath(const std::string_view url); - -private: - std::vector> downloads_; - // These get copied to downloads_ in Update(). It's so that callbacks can add new downloads - // while running. - std::vector> newDownloads_; - - std::string userAgent_; - Path cacheDir_; -}; - inline const char *RequestMethodToString(RequestMethod method) { switch (method) { case RequestMethod::GET: return "GET"; diff --git a/Common/Net/HTTPRequestManager.cpp b/Common/Net/HTTPRequestManager.cpp new file mode 100644 index 0000000000..40102472e0 --- /dev/null +++ b/Common/Net/HTTPRequestManager.cpp @@ -0,0 +1,164 @@ +#include "Common/StringUtils.h" +#include "Common/System/System.h" +#include "Common/System/Request.h" +#include "Common/Net/HTTPClient.h" +#include "Common/Net/HTTPRequest.h" +#include "Common/Net/HTTPRequestManager.h" +#include "Common/Net/HTTPNaettRequest.h" +#include "Common/File/FileUtil.h" +#include "Common/TimeUtil.h" + +namespace http { + +static bool IsHttpsUrl(std::string_view url) { + return startsWith(url, "https:"); +} + +Path UrlToCachePath(const Path &cacheDir, std::string_view url) { + std::string fn = "DLCACHE_"; + for (auto c : url) { + if (isalnum(c) || c == '.' || c == '-' || c == '_') { + fn.push_back(tolower(c)); + } else { + fn.push_back('_'); + } + } + return cacheDir / fn; +} + +Path RequestManager::UrlToCachePath(const std::string_view url) { + if (cacheDir_.empty()) { + return Path(); + } + return http::UrlToCachePath(cacheDir_, url); +} + +static std::shared_ptr 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(method, url, postdata, postMime, outfile, flags, name); +#else + return std::shared_ptr(); +#endif + } else { + return std::make_shared(method, url, postdata, postMime, outfile, flags, customResolve, name); + } +} + +std::shared_ptr RequestManager::StartDownload(std::string_view url, const Path &outfile, RequestFlags flags, const char *acceptMime) { + const bool enableCache = !cacheDir_.empty() && (flags & RequestFlags::Cached24H); + + // Come up with a cache file path. + Path cacheFile = UrlToCachePath(url); + + if (enableCache) { + _dbg_assert_(outfile.empty()); // It's automatically replaced below + + // TODO: This should be done on the thread, maybe. But let's keep it simple for now. + time_t cacheFileTime; + if (File::GetModifTimeT(cacheFile, &cacheFileTime)) { + time_t now = (time_t)time_now_unix_utc(); + if (cacheFileTime > now - 24 * 60 * 60) { + // The file is new enough. Let's construct a fake, already finished download so we don't need + // to modify the calling code. + std::string contents; + if (File::ReadBinaryFileToString(cacheFile, &contents)) { + INFO_LOG(Log::sceNet, "Returning cached file for %.*s: %s", (int)url.size(), url.data(), cacheFile.c_str()); + // All is well, but we've indented a bit much here. + std::shared_ptr dl(new CachedRequest(RequestMethod::GET, url, "infra-dns.json", nullptr, flags, contents)); + newDownloads_.push_back(dl); + return dl; + } else { + INFO_LOG(Log::sceNet, "Failed reading from cache, proceeding with request"); + } + } else { + INFO_LOG(Log::sceNet, "Cached file too old, proceeding with request"); + } + } else { + INFO_LOG(Log::sceNet, "Failed to check time modified. Proceeding with request."); + } + } + + std::shared_ptr 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) { + dl->OverrideOutFile(cacheFile); + dl->AddFlag(RequestFlags::KeepInMemory); + } + + if (!userAgent_.empty()) { + dl->SetUserAgent(userAgent_); + } + if (acceptMime) { + dl->SetAccept(acceptMime); + } + newDownloads_.push_back(dl); + dl->Start(); + return dl; +} + +std::shared_ptr RequestManager::StartDownloadWithCallback( + std::string_view url, + const Path &outfile, + RequestFlags flags, + std::function callback, + std::string_view name, + const char *acceptMime) { + std::shared_ptr dl = CreateRequest(RequestMethod::GET, url, "", "", outfile, flags, nullptr, name); + + if (!userAgent_.empty()) + dl->SetUserAgent(userAgent_); + if (acceptMime) + dl->SetAccept(acceptMime); + dl->SetCallback(callback); + newDownloads_.push_back(dl); + dl->Start(); + return dl; +} + +std::shared_ptr RequestManager::AsyncPostWithCallback( + std::string_view url, + std::string_view postData, + std::string_view postMime, + RequestFlags flags, + std::function callback, + std::string_view name) { + std::shared_ptr dl = CreateRequest(RequestMethod::POST, url, postData, postMime, Path(), flags, nullptr, name); + if (!userAgent_.empty()) + dl->SetUserAgent(userAgent_); + dl->SetCallback(callback); + newDownloads_.push_back(dl); + dl->Start(); + return dl; +} + +void RequestManager::Update() { + for (auto &iter : newDownloads_) { + downloads_.push_back(iter); + } + newDownloads_.clear(); + +restart: + for (size_t i = 0; i < downloads_.size(); i++) { + auto dl = downloads_[i]; + if (dl->Done()) { + dl->RunCallback(); + dl->Join(); + downloads_.erase(downloads_.begin() + i); + goto restart; + } + } +} + +void RequestManager::CancelAll() { + for (size_t i = 0; i < downloads_.size(); i++) { + downloads_[i]->Cancel(); + } + for (size_t i = 0; i < downloads_.size(); i++) { + downloads_[i]->Join(); + } + downloads_.clear(); +} + +} // namespace http diff --git a/Common/Net/HTTPRequestManager.h b/Common/Net/HTTPRequestManager.h new file mode 100644 index 0000000000..05e59db875 --- /dev/null +++ b/Common/Net/HTTPRequestManager.h @@ -0,0 +1,75 @@ +#pragma once + +#include +#include +#include "Common/Net/HTTPRequest.h" +#include "Common/Net/NetBuffer.h" + +namespace http { + +class RequestManager { +public: + ~RequestManager() { + CancelAll(); + } + + // NOTE: This is the only version that supports the cache flag (for now). + std::shared_ptr StartDownload(std::string_view url, const Path &outfile, RequestFlags flags, const char *acceptMime = nullptr); + + std::shared_ptr StartDownloadWithCallback( + std::string_view url, + const Path &outfile, + RequestFlags flags, + std::function callback, + std::string_view name = "", + const char *acceptMime = nullptr); + + std::shared_ptr AsyncPostWithCallback( + std::string_view url, + std::string_view postData, + std::string_view postMime, // Use postMime = "application/x-www-form-urlencoded" for standard form-style posts, such as used by retroachievements. For encoding form data manually we have MultipartFormDataEncoder. + RequestFlags flags, + std::function callback, + std::string_view name = ""); + + // Drops finished downloads from the list. + void Update(); + void CancelAll(); + + void SetUserAgent(std::string_view userAgent) { + userAgent_ = userAgent; + } + + void SetCacheDir(const Path &path) { + cacheDir_ = path; + } + + Path UrlToCachePath(const std::string_view url); + +private: + std::vector> downloads_; + // These get copied to downloads_ in Update(). It's so that callbacks can add new downloads + // while running. + std::vector> newDownloads_; + + std::string userAgent_; + Path cacheDir_; +}; + +// Fake request for cache hits. +// The download manager uses this when caching was requested, and a new-enough file was present in the cache directory. +// This is simply a finished request, that can still be queried like a normal one so users don't know it came from the cache. +class CachedRequest : public Request { +public: + CachedRequest(RequestMethod method, std::string_view url, std::string_view name, bool *cancelled, RequestFlags flags, std::string_view responseData) + : Request(method, url, name, cancelled, flags) + { + buffer_.Append(responseData); + } + void Start() override {} + void Join() override {} + bool Done() override { return true; } + bool Failed() const override { return false; } +}; + +} // namespace http diff --git a/Core/Config.cpp b/Core/Config.cpp index 88571f0d88..8ce0adb176 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -41,11 +41,11 @@ #include "Common/File/VFS/VFS.h" #include "Common/Log/LogManager.h" #include "Common/Math/CrossSIMD.h" +#include "Common/Net/HTTPRequestManager.h" #include "Common/OSVersion.h" #include "Common/System/Display.h" #include "Common/System/System.h" #include "Common/StringUtils.h" -#include "Common/Thread/ThreadUtil.h" #include "Common/GPU/Vulkan/VulkanLoader.h" #include "Common/VR/PPSSPPVR.h" #include "Common/System/OSD.h" diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 4ad3332a27..dbb7c49bfd 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -25,6 +25,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/File/VFS/VFS.h" #include "Common/File/FileUtil.h" +#include "Common/Net/HTTPRequestManager.h" #include "Common/System/OSD.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" diff --git a/Core/Reporting.cpp b/Core/Reporting.cpp index 8a20ccd6ed..79bfef2580 100644 --- a/Core/Reporting.cpp +++ b/Core/Reporting.cpp @@ -40,6 +40,7 @@ extern "C" { #include "Common/System/OSD.h" #include "Common/Data/Text/I18n.h" #include "Common/Net/HTTPClient.h" +#include "Common/Net/HTTPRequestManager.h" #include "Common/Net/Resolve.h" #include "Common/Net/URL.h" #include "Common/Thread/ThreadUtil.h" diff --git a/Core/RetroAchievements.cpp b/Core/RetroAchievements.cpp index cc64ffbdd6..5e8a0937e3 100644 --- a/Core/RetroAchievements.cpp +++ b/Core/RetroAchievements.cpp @@ -31,6 +31,7 @@ #include "Common/Log.h" #include "Common/File/Path.h" #include "Common/Net/HTTPRequest.h" +#include "Common/Net/HTTPRequestManager.h" #include "Common/System/OSD.h" #include "Common/System/System.h" #include "Common/System/NativeApp.h" diff --git a/Core/Util/GameManager.cpp b/Core/Util/GameManager.cpp index 4c6313f6da..758d76ffe6 100644 --- a/Core/Util/GameManager.cpp +++ b/Core/Util/GameManager.cpp @@ -38,6 +38,7 @@ #include "Common/Log.h" #include "Common/System/OSD.h" #include "Common/File/FileUtil.h" +#include "Common/Net/HTTPRequestManager.h" #include "Common/StringUtils.h" #include "Common/Thread/ThreadUtil.h" #include "Core/Config.h" diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index c6b296aee5..f11a60f0b5 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -39,7 +39,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/Data/Text/Parsers.h" #include "Common/Data/Encoding/Utf8.h" -#include "Common/Net/HTTPClient.h" +#include "Common/Net/HTTPRequestManager.h" #include "Common/UI/Context.h" #include "Common/UI/View.h" #include "Common/UI/ViewGroup.h" diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 55e89c5867..3855e55ec4 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -45,7 +45,7 @@ #include "Windows/CaptureDevice.h" #endif -#include "Common/Net/HTTPClient.h" +#include "Common/Net/HTTPRequestManager.h" #include "Common/Net/Resolve.h" #include "Common/Net/URL.h" #include "Common/Render/TextureAtlas.h" @@ -77,7 +77,6 @@ #include "Common/File/VFS/DirectoryReader.h" #include "Common/CPUDetect.h" #include "Common/File/FileUtil.h" -#include "Common/TimeUtil.h" #include "Common/StringUtils.h" #include "Common/Log/LogManager.h" #include "Common/MemArena.h" @@ -87,6 +86,7 @@ #include "Common/VR/PPSSPPVR.h" #include "Common/Thread/ThreadManager.h" #include "Common/Audio/AudioBackend.h" +#include "Common/TimeUtil.h" #include "Core/ControlMapper.h" #include "Core/Config.h" diff --git a/UI/Store.cpp b/UI/Store.cpp index 6d0ce1758d..8b2e020ccb 100644 --- a/UI/Store.cpp +++ b/UI/Store.cpp @@ -28,7 +28,7 @@ #include "Common/Data/Format/JSONReader.h" #include "Common/StringUtils.h" #include "Common/Render/ManagedTexture.h" -#include "Common/Net/NetBuffer.h" +#include "Common/Net/HTTPRequestManager.h" #include "Core/Config.h" #include "Core/System.h" #include "Core/Util/GameManager.h" diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index 2d95008f9d..460dc66dfa 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -102,6 +102,7 @@ + @@ -289,6 +290,7 @@ + diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters index e2c9ed7cf6..893c2dae20 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj.filters +++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters @@ -523,6 +523,9 @@ Net + + Net + @@ -1005,6 +1008,9 @@ Net + + Net + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 48849ec3a6..cd6a44e55a 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -340,6 +340,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Common/Net/HTTPClient.cpp \ $(SRC)/Common/Net/HTTPHeaders.cpp \ $(SRC)/Common/Net/HTTPRequest.cpp \ + $(SRC)/Common/Net/HTTPRequestManager.cpp \ $(SRC)/Common/Net/HTTPNaettRequest.cpp \ $(SRC)/Common/Net/HTTPServer.cpp \ $(SRC)/Common/Net/NetBuffer.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 68c260b285..cf662f76c3 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -447,6 +447,7 @@ SOURCES_CXX += \ $(COMMONDIR)/Net/HTTPServer.cpp \ $(COMMONDIR)/Net/HTTPRequest.cpp \ $(COMMONDIR)/Net/HTTPNaettRequest.cpp \ + $(COMMONDIR)/Net/HTTPRequestManager.cpp \ $(COMMONDIR)/Net/NetBuffer.cpp \ $(COMMONDIR)/Net/Resolve.cpp \ $(COMMONDIR)/Net/Sinks.cpp \