diff --git a/.gitmodules b/.gitmodules index 2ca84d342b7a..af29087557de 100644 --- a/.gitmodules +++ b/.gitmodules @@ -47,3 +47,6 @@ [submodule "ext/rcheevos"] path = ext/rcheevos url = https://github.com/RetroAchievements/rcheevos.git +[submodule "ext/naett"] + path = ext/naett + url = https://github.com/hrydgard/naett.git diff --git a/CMakeLists.txt b/CMakeLists.txt index dddcf33403ab..452b74f1a8bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,6 +219,16 @@ else() set(CoreLinkType STATIC) endif() +if(NOT ANDROID AND NOT WIN32 AND NOT APPLE) + set(HTTPS_NOT_AVAILABLE ON) +endif() + +# Made this flag negative because it's hopefully quite temporary and didn't +# want to have to update all build systems. +if(HTTPS_NOT_AVAILABLE) + add_definitions(-DHTTPS_NOT_AVAILABLE) +endif() + # Work around for some misfeature of the current glslang build system include_directories(ext/glslang) @@ -710,6 +720,10 @@ add_library(Common STATIC Common/Net/HTTPClient.h Common/Net/HTTPHeaders.cpp Common/Net/HTTPHeaders.h + Common/Net/HTTPNaettRequest.cpp + Common/Net/HTTPNaettRequest.h + Common/Net/HTTPRequest.cpp + Common/Net/HTTPRequest.h Common/Net/HTTPServer.cpp Common/Net/HTTPServer.h Common/Net/NetBuffer.cpp @@ -2223,6 +2237,10 @@ endif() target_link_libraries(${CoreLibName} Common native kirk cityhash sfmt19937 xbrz xxhash rcheevos ${GlslangLibs} ${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS}) +if(NOT HTTPS_NOT_AVAILABLE) + target_link_libraries(${CoreLibName} naett) +endif() + target_compile_features(${CoreLibName} PUBLIC cxx_std_17) if(FFmpeg_FOUND) diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 2e5a95a43b5a..2b80aaa4d227 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -399,6 +399,7 @@ + @@ -490,10 +491,12 @@ + + @@ -847,6 +850,7 @@ + @@ -934,10 +938,12 @@ + + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index deb16350c311..5527848423d1 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -512,6 +512,15 @@ System + + Net + + + ext\naett + + + Net + @@ -959,6 +968,15 @@ System + + Net + + + ext\naett + + + Net + @@ -1069,6 +1087,9 @@ {d6d5f6e0-1c72-496b-af11-6d52d5123033} + + {34f45db9-5c08-49cb-b349-b9e760ce3213} + diff --git a/Common/Net/HTTPClient.cpp b/Common/Net/HTTPClient.cpp index 83f4bf20831b..9fc37de0821b 100644 --- a/Common/Net/HTTPClient.cpp +++ b/Common/Net/HTTPClient.cpp @@ -444,42 +444,21 @@ int Client::ReadResponseEntity(net::Buffer *readbuf, const std::vector Downloader::StartDownload(const std::string &url, const Path &outfile, ProgressBarMode mode, const char *acceptMime) { - std::shared_ptr dl(new Download(RequestMethod::GET, url, "", "", outfile, mode)); - - if (!userAgent_.empty()) - dl->SetUserAgent(userAgent_); - if (acceptMime) - dl->SetAccept(acceptMime); - newDownloads_.push_back(dl); - dl->Start(); - return dl; -} - -std::shared_ptr Downloader::StartDownloadWithCallback( - const std::string &url, - const Path &outfile, - ProgressBarMode mode, - std::function callback, - const std::string &name, - const char *acceptMime) { - std::shared_ptr dl(new Download(RequestMethod::GET, url, "", "", outfile, mode, 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 Downloader::AsyncPostWithCallback( - const std::string &url, - const std::string &postData, - const std::string &postMime, - ProgressBarMode mode, - std::function callback, - const std::string &name) { - std::shared_ptr dl(new Download(RequestMethod::POST, url, postData, postMime, Path(), mode, name)); - if (!userAgent_.empty()) - dl->SetUserAgent(userAgent_); - dl->SetCallback(callback); - newDownloads_.push_back(dl); - dl->Start(); - return dl; -} - -void Downloader::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 Downloader::WaitForAll() { - // TODO: Should lock? Though, OK if called from main thread, where Update() is called from. - while (!downloads_.empty()) { - Update(); - sleep_ms(10); - } -} - -void Downloader::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(); -} - } // http diff --git a/Common/Net/HTTPClient.h b/Common/Net/HTTPClient.h index 88b76f116ea7..df6bcd6c2a95 100644 --- a/Common/Net/HTTPClient.h +++ b/Common/Net/HTTPClient.h @@ -8,6 +8,7 @@ #include "Common/File/Path.h" #include "Common/Net/NetBuffer.h" #include "Common/Net/Resolve.h" +#include "Common/Net/HTTPRequest.h" namespace net { @@ -89,140 +90,52 @@ class Client : public net::Connection { double dataTimeout_ = 900.0; }; -enum class RequestMethod { - GET, - POST, -}; - -enum class ProgressBarMode { - NONE, - VISIBLE, - DELAYED, -}; - // Really an asynchronous request. -class Download { +class HTTPDownload : public Download { public: - Download(RequestMethod method, const std::string &url, const std::string &postData, const std::string &postMime, const Path &outfile, ProgressBarMode progressBarMode = ProgressBarMode::DELAYED, const std::string &name = ""); - ~Download(); + HTTPDownload(RequestMethod method, const std::string &url, const std::string &postData, const std::string &postMime, const Path &outfile, ProgressBarMode progressBarMode = ProgressBarMode::DELAYED, const std::string &name = ""); + ~HTTPDownload(); - void SetAccept(const char *mime) { - acceptMime_ = mime; - } - - void SetUserAgent(const std::string &userAgent) { - userAgent_ = userAgent; - } + void Start() override; + void Join() override; - void Start(); - - void Join(); - - // Returns 1.0 when done. That one value can be compared exactly - or just use Done(). - float Progress() const { return progress_.progress; } - float SpeedKBps() const { return progress_.kBps; } - - bool Done() const { return completed_; } - bool Failed() const { return failed_; } + bool Done() override { return completed_; } + bool Failed() const override { return failed_; } // NOTE! The value of ResultCode is INVALID until Done() returns true. - int ResultCode() const { return resultCode_; } + int ResultCode() const override { return resultCode_; } - std::string url() const { return url_; } - const Path &outfile() const { return outfile_; } + const Path &outfile() const override { return outfile_; } // If not downloading to a file, access this to get the result. - Buffer &buffer() { return buffer_; } - const Buffer &buffer() const { return buffer_; } + Buffer &buffer() override { return buffer_; } + const Buffer &buffer() const override { return buffer_; } - void Cancel() { + void Cancel() override { cancelled_ = true; } - bool IsCancelled() const { + bool IsCancelled() const override { return cancelled_; } - // NOTE: Completion callbacks (which these are) are deferred until RunCallback is called. This is so that - // the call will end up on the thread that calls g_DownloadManager.Update(). - void SetCallback(std::function callback) { - callback_ = callback; - } - void RunCallback() { - if (callback_) { - callback_(*this); - } - } - private: void Do(); // Actually does the download. Runs on thread. int Perform(const std::string &url); std::string RedirectLocation(const std::string &baseUrl); void SetFailed(int code); - RequestMethod method_; - net::RequestProgress progress_; std::string postData_; - std::string userAgent_; Buffer buffer_; std::vector responseHeaders_; - std::string url_; Path outfile_; std::thread thread_; - const char *acceptMime_ = "*/*"; std::string postMime_; int resultCode_ = 0; bool completed_ = false; bool failed_ = false; bool cancelled_ = false; - ProgressBarMode progressBarMode_; bool joined_ = false; - std::string name_; - std::function callback_; -}; - -using std::shared_ptr; - -class Downloader { -public: - ~Downloader() { - CancelAll(); - } - - std::shared_ptr StartDownload(const std::string &url, const Path &outfile, ProgressBarMode mode, const char *acceptMime = nullptr); - - std::shared_ptr StartDownloadWithCallback( - const std::string &url, - const Path &outfile, - ProgressBarMode mode, - std::function callback, - const std::string &name = "", - const char *acceptMime = nullptr); - - std::shared_ptr AsyncPostWithCallback( - const std::string &url, - const std::string &postData, - const std::string &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. - ProgressBarMode mode, - std::function callback, - const std::string &name = ""); - - // Drops finished downloads from the list. - void Update(); - void CancelAll(); - - void WaitForAll(); - void SetUserAgent(const std::string &userAgent) { - userAgent_ = userAgent; - } - -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_; }; } // http diff --git a/Common/Net/HTTPNaettRequest.cpp b/Common/Net/HTTPNaettRequest.cpp new file mode 100644 index 000000000000..87ca991ee9af --- /dev/null +++ b/Common/Net/HTTPNaettRequest.cpp @@ -0,0 +1,127 @@ +#ifndef HTTPS_NOT_AVAILABLE + +#include + +#include "Common/Net/HTTPRequest.h" +#include "Common/Net/HTTPNaettRequest.h" +#include "Common/Thread/ThreadUtil.h" +#include "Common/StringUtils.h" +#include "Common/Log.h" + +#include "ext/naett/naett.h" + +namespace http { + +HTTPSDownload::HTTPSDownload(RequestMethod method, const std::string &url, const std::string &postData, const std::string &postMime, const Path &outfile, ProgressBarMode progressBarMode, const std::string &name) + : Download(method, url, name, &cancelled_, progressBarMode), method_(method), postData_(postData), postMime_(postMime), outfile_(outfile) { +} + +HTTPSDownload::~HTTPSDownload() { + Join(); +} + +void HTTPSDownload::Start() { + _dbg_assert_(!req_); + _dbg_assert_(!res_); + + std::vector options; + options.push_back(naettMethod(method_ == RequestMethod::GET ? "GET" : "POST")); + options.push_back(naettHeader("Accept", acceptMime_)); + options.push_back(naettUserAgent(userAgent_.c_str())); + if (!postMime_.empty()) { + options.push_back(naettHeader("Content-Type", postMime_.c_str())); + } + if (method_ == RequestMethod::POST) { + if (!postData_.empty()) { + // Note: Naett does not take ownership over the body. + options.push_back(naettBody(postData_.data(), (int)postData_.size())); + } + } else { + _dbg_assert_(postData_.empty()); + } + // 30 s timeout - not sure what's reasonable? + options.push_back(naettTimeout(30 * 1000)); // milliseconds + + const naettOption **opts = (const naettOption **)options.data(); + req_ = naettRequestWithOptions(url_.c_str(), (int)options.size(), opts); + res_ = naettMake(req_); + + progress_.Update(0, 0, false); +} + +void HTTPSDownload::Join() { + if (!res_ || !req_) + return; // No pending operation. + // Tear down. + if (completed_ && res_) { + _dbg_assert_(req_); + naettClose(res_); + naettFree(req_); + res_ = nullptr; + req_ = nullptr; + } else { + ERROR_LOG(IO, "HTTPSDownload::Join not implemented"); + } +} + +bool HTTPSDownload::Done() { + if (completed_) + return true; + + if (!naettComplete(res_)) { + int total = 0; + int size = naettGetTotalBytesRead(res_, &total); + progress_.Update(size, total, false); + return false; + } + + // -1000 is a code specified by us to represent cancellation, that is unlikely to ever collide with naett error codes. + resultCode_ = IsCancelled() ? -1000 : naettGetStatus(res_); + if (resultCode_ < 0) { + // It's a naett error. Translate and handle. + switch (resultCode_) { + case naettConnectionError: // -1 + ERROR_LOG(IO, "Connection error"); + break; + case naettProtocolError: // -2 + ERROR_LOG(IO, "Protocol error"); + break; + case naettReadError: // -3 + ERROR_LOG(IO, "Read error"); + break; + case naettWriteError: // -4 + ERROR_LOG(IO, "Write error"); + break; + case naettGenericError: // -5 + ERROR_LOG(IO, "Generic error"); + break; + default: + ERROR_LOG(IO, "Unhandled naett error %d", resultCode_); + break; + } + failed_ = true; + progress_.Update(0, 0, true); + } else if (resultCode_ == 200) { + int bodyLength; + const void *body = naettGetBody(res_, &bodyLength); + char *dest = buffer_.Append(bodyLength); + memcpy(dest, body, bodyLength); + if (!outfile_.empty() && !buffer_.FlushToFile(outfile_)) { + ERROR_LOG(IO, "Failed writing download to '%s'", outfile_.c_str()); + } + progress_.Update(bodyLength, bodyLength, true); + } else { + WARN_LOG(IO, "Naett request failed: %d", resultCode_); + failed_ = true; + progress_.Update(0, 0, true); + } + + completed_ = true; + + // The callback will be called later. + return true; +} + +} // namespace http + +#endif // HTTPS_NOT_AVAILABLE diff --git a/Common/Net/HTTPNaettRequest.h b/Common/Net/HTTPNaettRequest.h new file mode 100644 index 000000000000..4fa5c93d165f --- /dev/null +++ b/Common/Net/HTTPNaettRequest.h @@ -0,0 +1,63 @@ +#pragma once + +#include + +#include "Common/Net/HTTPRequest.h" + +#ifndef HTTPS_NOT_AVAILABLE + +#include "ext/naett/naett.h" + +namespace http { + +// Really an asynchronous request. +class HTTPSDownload : public Download { +public: + HTTPSDownload(RequestMethod method, const std::string &url, const std::string &postData, const std::string &postMime, const Path &outfile, ProgressBarMode progressBarMode = ProgressBarMode::DELAYED, const std::string &name = ""); + ~HTTPSDownload(); + + void Start() override; + void Join() override; + + // Also acts as a Poll. + bool Done() override; + bool Failed() const override { return failed_; } + + // NOTE! The value of ResultCode is INVALID until Done() returns true. + int ResultCode() const override { return resultCode_; } + + const Path &outfile() const override { return outfile_; } + + // If not downloading to a file, access this to get the result. + Buffer &buffer() override { return buffer_; } + const Buffer &buffer() const override { return buffer_; } + + void Cancel() override { + cancelled_ = true; + } + + bool IsCancelled() const override { + return cancelled_; + } + +private: + RequestMethod method_; + std::string postData_; + Buffer buffer_; + std::vector responseHeaders_; + Path outfile_; + std::string postMime_; + int resultCode_ = 0; + bool completed_ = false; + bool failed_ = false; + bool cancelled_ = false; + bool joined_ = false; + + // Naett state + naettReq *req_ = nullptr; + naettRes *res_ = nullptr; +}; + +} // namespace http + +#endif // HTTPS_NOT_AVAILABLE diff --git a/Common/Net/HTTPRequest.cpp b/Common/Net/HTTPRequest.cpp new file mode 100644 index 000000000000..e982ff81f9a5 --- /dev/null +++ b/Common/Net/HTTPRequest.cpp @@ -0,0 +1,147 @@ +#include "Common/Net/HTTPRequest.h" +#include "Common/Net/HTTPClient.h" +#include "Common/Net/HTTPNaettRequest.h" +#include "Common/TimeUtil.h" +#include "Common/StringUtils.h" +#include "Common/Log.h" +#include "Common/System/OSD.h" + +namespace http { + +Download::Download(RequestMethod method, const std::string &url, const std::string &name, bool *cancelled, ProgressBarMode mode) : method_(method), url_(url), name_(name), progress_(cancelled), progressBarMode_(mode) { + progress_.callback = [=](int64_t bytes, int64_t contentLength, bool done) { + std::string message; + if (!name_.empty()) { + message = name_; + } else { + std::size_t pos = url_.rfind('/'); + if (pos != std::string::npos) { + message = url_.substr(pos + 1); + } else { + message = url_; + } + } + if (progressBarMode_ != ProgressBarMode::NONE) { + if (!done) { + g_OSD.SetProgressBar(url_, std::move(message), 0.0f, (float)contentLength, (float)bytes, progressBarMode_ == ProgressBarMode::DELAYED ? 3.0f : 0.0f); // delay 3 seconds before showing. + } else { + g_OSD.RemoveProgressBar(url_, Failed() ? false : true, 0.5f); + } + } + }; +} + +bool RequestManager::IsHttpsUrl(const std::string &url) { + return startsWith(url, "https:"); +} + +std::shared_ptr RequestManager::StartDownload(const std::string &url, const Path &outfile, ProgressBarMode mode, const char *acceptMime) { + std::shared_ptr dl; + if (IsHttpsUrl(url)) { +#ifndef HTTPS_NOT_AVAILABLE + dl.reset(new HTTPSDownload(RequestMethod::GET, url, "", "", outfile, mode)); +#else + return std::shared_ptr(); +#endif + } else { + dl.reset(new HTTPDownload(RequestMethod::GET, url, "", "", outfile, mode)); + } + + if (!userAgent_.empty()) + dl->SetUserAgent(userAgent_); + if (acceptMime) + dl->SetAccept(acceptMime); + newDownloads_.push_back(dl); + dl->Start(); + return dl; +} + +std::shared_ptr RequestManager::StartDownloadWithCallback( + const std::string &url, + const Path &outfile, + ProgressBarMode mode, + std::function callback, + const std::string &name, + const char *acceptMime) { + std::shared_ptr dl; + if (IsHttpsUrl(url)) { +#ifndef HTTPS_NOT_AVAILABLE + dl.reset(new HTTPSDownload(RequestMethod::GET, url, "", "", outfile, mode, name)); +#else + return std::shared_ptr(); +#endif + } else { + dl.reset(new HTTPDownload(RequestMethod::GET, url, "", "", outfile, mode, 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( + const std::string &url, + const std::string &postData, + const std::string &postMime, + ProgressBarMode mode, + std::function callback, + const std::string &name) { + std::shared_ptr dl; + if (IsHttpsUrl(url)) { +#ifndef HTTPS_NOT_AVAILABLE + dl.reset(new HTTPSDownload(RequestMethod::POST, url, postData, postMime, Path(), mode, name)); +#else + return std::shared_ptr(); +#endif + } else { + dl.reset(new HTTPDownload(RequestMethod::POST, url, postData, postMime, Path(), mode, 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::WaitForAll() { + // TODO: Should lock? Though, OK if called from main thread, where Update() is called from. + while (!downloads_.empty()) { + Update(); + sleep_ms(10); + } +} + +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 new file mode 100644 index 000000000000..0e7686009b19 --- /dev/null +++ b/Common/Net/HTTPRequest.h @@ -0,0 +1,129 @@ +#pragma once + +#include +#include +#include + +#include "Common/File/Path.h" +#include "Common/Net/NetBuffer.h" + +namespace http { + +enum class RequestMethod { + GET, + POST, +}; + +enum class ProgressBarMode { + NONE, + VISIBLE, + DELAYED, +}; + +// Abstract request. +class Download { +public: + Download(RequestMethod method, const std::string &url, const std::string &name, bool *cancelled, ProgressBarMode mode); + virtual ~Download() {} + + void SetAccept(const char *mime) { + acceptMime_ = mime; + } + + void SetUserAgent(const std::string &userAgent) { + userAgent_ = userAgent; + } + + // NOTE: Completion callbacks (which these are) are deferred until RunCallback is called. This is so that + // the call will end up on the thread that calls g_DownloadManager.Update(). + void SetCallback(std::function callback) { + callback_ = callback; + } + void RunCallback() { + if (callback_) { + callback_(*this); + } + } + + virtual void Start() = 0; + virtual void Join() = 0; + + virtual bool Done() = 0; + virtual bool Failed() const = 0; + + virtual int ResultCode() const = 0; + + // Returns 1.0 when done. That one value can be compared exactly - or just use Done(). + float Progress() const { return progress_.progress; } + float SpeedKBps() const { return progress_.kBps; } + std::string url() const { return url_; } + virtual const Path &outfile() const = 0; + + virtual void Cancel() = 0; + virtual bool IsCancelled() const = 0; + + // Response + virtual Buffer &buffer() = 0; + virtual const Buffer &buffer() const = 0; + +protected: + std::function callback_; + RequestMethod method_; + std::string url_; + std::string name_; + const char *acceptMime_ = "*/*"; + std::string userAgent_; + + net::RequestProgress progress_; + ProgressBarMode progressBarMode_; + +private: +}; + +using std::shared_ptr; + +class RequestManager { +public: + ~RequestManager() { + CancelAll(); + } + + std::shared_ptr StartDownload(const std::string &url, const Path &outfile, ProgressBarMode mode, const char *acceptMime = nullptr); + + std::shared_ptr StartDownloadWithCallback( + const std::string &url, + const Path &outfile, + ProgressBarMode mode, + std::function callback, + const std::string &name = "", + const char *acceptMime = nullptr); + + std::shared_ptr AsyncPostWithCallback( + const std::string &url, + const std::string &postData, + const std::string &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. + ProgressBarMode mode, + std::function callback, + const std::string &name = ""); + + // Drops finished downloads from the list. + void Update(); + void CancelAll(); + + void WaitForAll(); + void SetUserAgent(const std::string &userAgent) { + userAgent_ = userAgent; + } + +private: + bool IsHttpsUrl(const std::string &url); + + 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_; +}; + +} // namespace net diff --git a/Common/Net/NetBuffer.cpp b/Common/Net/NetBuffer.cpp index 3cdbbcd189e6..06310a6c8388 100644 --- a/Common/Net/NetBuffer.cpp +++ b/Common/Net/NetBuffer.cpp @@ -22,6 +22,18 @@ namespace net { +void RequestProgress::Update(int64_t downloaded, int64_t totalBytes, bool done) { + if (totalBytes) { + progress = (double)downloaded / (double)totalBytes; + } else { + progress = 0.01f; + } + + if (callback) { + callback(downloaded, totalBytes, done); + } +} + bool Buffer::FlushSocket(uintptr_t sock, double timeout, bool *cancelled) { static constexpr float CANCEL_INTERVAL = 0.25f; for (size_t pos = 0, end = data_.size(); pos < end; ) { diff --git a/Common/Net/NetBuffer.h b/Common/Net/NetBuffer.h index 85b1421d2849..32525ad3f754 100644 --- a/Common/Net/NetBuffer.h +++ b/Common/Net/NetBuffer.h @@ -12,16 +12,7 @@ class RequestProgress { RequestProgress() {} explicit RequestProgress(bool *c) : cancelled(c) {} - void Update(int64_t downloaded, int64_t totalBytes, bool done) { - if (totalBytes) { - progress = (double)downloaded / (double)totalBytes; - } else { - progress = 0.01f; - } - if (callback) { - callback(downloaded, totalBytes, done); - } - } + void Update(int64_t downloaded, int64_t totalBytes, bool done); float progress = 0.0f; float kBps = 0.0f; diff --git a/Common/Net/Resolve.cpp b/Common/Net/Resolve.cpp index 76f0055f50fb..2438fc5b3360 100644 --- a/Common/Net/Resolve.cpp +++ b/Common/Net/Resolve.cpp @@ -30,8 +30,18 @@ #include "Common/Log.h" #include "Common/TimeUtil.h" +#ifndef HTTPS_NOT_AVAILABLE +#include "ext/naett/naett.h" +#endif + +#if PPSSPP_PLATFORM(ANDROID) +#include +extern JavaVM *gJvm; +#endif + namespace net { +static bool g_naettInitialized; void Init() { @@ -40,6 +50,17 @@ void Init() WSADATA wsaData = {0}; WSAStartup(MAKEWORD(2, 2), &wsaData); #endif + if (!g_naettInitialized) { +#ifndef HTTPS_NOT_AVAILABLE +#if PPSSPP_PLATFORM(ANDROID) + _assert_(gJvm != nullptr); + naettInit(gJvm); +#else + naettInit(NULL); +#endif +#endif + g_naettInitialized = true; + } } void Shutdown() diff --git a/Common/Render/Text/draw_text_android.cpp b/Common/Render/Text/draw_text_android.cpp index cab0bdca7e15..d1e6244cb27e 100644 --- a/Common/Render/Text/draw_text_android.cpp +++ b/Common/Render/Text/draw_text_android.cpp @@ -1,4 +1,5 @@ #include "ppsspp_config.h" + #include "Common/Log.h" #include "Common/StringUtils.h" #include "Common/System/Display.h" diff --git a/Common/System/Request.cpp b/Common/System/Request.cpp index dbfcff7c62b0..8e78352908a5 100644 --- a/Common/System/Request.cpp +++ b/Common/System/Request.cpp @@ -1,3 +1,5 @@ +#include "ppsspp_config.h" + #include #include "Common/System/Request.h" @@ -6,6 +8,17 @@ #include "Common/File/Path.h" #include "Common/TimeUtil.h" +#if PPSSPP_PLATFORM(ANDROID) + +// Maybe not the most natural place for this, but not sure what would be. It needs to be in the Common project +// unless we want to make another System_ function to retrieve it. + +#include + +JavaVM *gJvm = nullptr; + +#endif + RequestManager g_requestManager; const char *RequestTypeAsString(SystemRequestType type) { diff --git a/Common/System/System.h b/Common/System/System.h index fd1ca445a512..17eeda194d05 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -136,6 +136,8 @@ enum SystemProperty { SYSPROP_CAN_CREATE_SHORTCUT, + SYSPROP_SUPPORTS_HTTPS, + // Available as Int: SYSPROP_SYSTEMVERSION, SYSPROP_DISPLAY_XRES, diff --git a/Common/UI/IconCache.cpp b/Common/UI/IconCache.cpp index f5b28881a0c2..830655e3dfc0 100644 --- a/Common/UI/IconCache.cpp +++ b/Common/UI/IconCache.cpp @@ -239,6 +239,7 @@ bool IconCache::InsertIcon(const std::string &key, IconFormat format, std::strin } if (data.empty()) { + _dbg_assert_(false); ERROR_LOG(G3D, "Can't insert empty data into icon cache"); return false; } diff --git a/Core/Config.cpp b/Core/Config.cpp index 316157d3e5d0..70eb254f2e24 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -57,7 +57,7 @@ #include "GPU/Common/FramebufferManagerCommon.h" // TODO: Find a better place for this. -http::Downloader g_DownloadManager; +http::RequestManager g_DownloadManager; Config g_Config; @@ -1174,7 +1174,7 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { if (iRunCount % 10 == 0 && bCheckForNewVersion) { const char *versionUrl = "http://www.ppsspp.org/version.json"; const char *acceptMime = "application/json, text/*; q=0.9, */*; q=0.8"; - g_DownloadManager.StartDownloadWithCallback(versionUrl, Path(), http::ProgressBarMode::NONE, &DownloadCompletedCallback, acceptMime); + g_DownloadManager.StartDownloadWithCallback(versionUrl, Path(), http::ProgressBarMode::NONE, &DownloadCompletedCallback, "version", acceptMime); } INFO_LOG(LOADER, "Loading controller config: %s", controllerIniFilename_.c_str()); diff --git a/Core/Config.h b/Core/Config.h index bd1b4223a186..98edbd35b5c5 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -42,7 +42,7 @@ enum ChatPositions { namespace http { class Download; - class Downloader; + class RequestManager; } struct UrlEncoder; @@ -595,6 +595,6 @@ struct Config { std::string CreateRandMAC(); // TODO: Find a better place for this. -extern http::Downloader g_DownloadManager; +extern http::RequestManager g_DownloadManager; extern Config g_Config; diff --git a/Core/RetroAchievements.cpp b/Core/RetroAchievements.cpp index 84302c812315..3821470ada8a 100644 --- a/Core/RetroAchievements.cpp +++ b/Core/RetroAchievements.cpp @@ -349,8 +349,10 @@ void Initialize() { // Provide a logging function to simplify debugging rc_client_enable_logging(g_rcClient, RC_CLIENT_LOG_LEVEL_VERBOSE, log_message_callback); - // Disable SSL for now. - rc_client_set_host(g_rcClient, "http://retroachievements.org"); + if (!System_GetPropertyBool(SYSPROP_SUPPORTS_HTTPS)) { + // Disable SSL if not supported by our platform implementation. + rc_client_set_host(g_rcClient, "http://retroachievements.org"); + } rc_client_set_event_handler(g_rcClient, event_handler_callback); diff --git a/Core/Util/PortManager.cpp b/Core/Util/PortManager.cpp index 2e70d892331f..cfb81e9dbd0b 100644 --- a/Core/Util/PortManager.cpp +++ b/Core/Util/PortManager.cpp @@ -49,11 +49,10 @@ std::recursive_mutex upnpLock; std::deque upnpReqs; PortManager::PortManager(): - urls(0), - datas(0), m_InitState(UPNP_INITSTATE_NONE), m_LocalPort(UPNP_LOCAL_PORT_ANY), m_leaseDuration("43200") { + // Don't call net::Init or similar here, we don't want stuff like that to happen before main. } PortManager::~PortManager() { diff --git a/Core/Util/PortManager.h b/Core/Util/PortManager.h index f284788a38f0..31b9f67f9552 100644 --- a/Core/Util/PortManager.h +++ b/Core/Util/PortManager.h @@ -108,8 +108,8 @@ class PortManager { // Uninitialize/Reset the state void Terminate(); - struct UPNPUrls* urls = NULL; - struct IGDdatas* datas = NULL; + struct UPNPUrls* urls = nullptr; + struct IGDdatas* datas = nullptr; int m_InitState = UPNP_INITSTATE_NONE; int m_LocalPort = UPNP_LOCAL_PORT_ANY; diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index f46af287ad02..955592a492c8 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -529,6 +529,10 @@ bool System_GetPropertyBool(SystemProperty prop) { return true; case SYSPROP_SUPPORTS_OPEN_FILE_IN_EDITOR: return true; // FileUtil.cpp: OpenFileInEditor +#ifndef HTTPS_NOT_AVAILABLE + case SYSPROP_SUPPORTS_HTTPS: + return true; +#endif #if PPSSPP_PLATFORM(MAC) case SYSPROP_HAS_FOLDER_BROWSER: case SYSPROP_HAS_FILE_BROWSER: diff --git a/UI/Store.cpp b/UI/Store.cpp index 0ad19143f653..dbe14d46ddea 100644 --- a/UI/Store.cpp +++ b/UI/Store.cpp @@ -35,7 +35,12 @@ #include "UI/EmuScreen.h" #include "UI/Store.h" -const std::string storeBaseUrl = "http://store.ppsspp.org/"; +const char *storeBaseUrlHttp = "http://store.ppsspp.org/"; +const char *storeBaseUrlHttps = "https://store.ppsspp.org/"; + +static std::string StoreBaseUrl() { + return System_GetPropertyBool(SYSPROP_SUPPORTS_HTTPS) ? storeBaseUrlHttps : storeBaseUrlHttp; +} // baseUrl is assumed to have a trailing slash, and not contain any subdirectories. std::string ResolveUrl(std::string baseUrl, std::string url) { @@ -53,16 +58,20 @@ std::string ResolveUrl(std::string baseUrl, std::string url) { class HttpImageFileView : public UI::View { public: - HttpImageFileView(http::Downloader *downloader, const std::string &path, UI::ImageSizeMode sizeMode = UI::IS_DEFAULT, bool useIconCache = true, UI::LayoutParams *layoutParams = nullptr) - : UI::View(layoutParams), path_(path), sizeMode_(sizeMode), downloader_(downloader), useIconCache_(useIconCache) { + HttpImageFileView(http::RequestManager *requestManager, const std::string &path, UI::ImageSizeMode sizeMode = UI::IS_DEFAULT, bool useIconCache = true, UI::LayoutParams *layoutParams = nullptr) + : UI::View(layoutParams), path_(path), sizeMode_(sizeMode), requestManager_(requestManager), useIconCache_(useIconCache) { if (useIconCache && g_iconCache.MarkPending(path_)) { const char *acceptMime = "image/png, image/jpeg, image/*; q=0.9, */*; q=0.8"; - downloader_->StartDownloadWithCallback(path_, Path(), http::ProgressBarMode::DELAYED, [&](http::Download &download) { + requestManager_->StartDownloadWithCallback(path_, Path(), http::ProgressBarMode::DELAYED, [&](http::Download &download) { if (download.ResultCode() == 200) { std::string data; download.buffer().TakeAll(&data); - g_iconCache.InsertIcon(path_, IconFormat::PNG, std::move(data)); + if (!data.empty()) { + g_iconCache.InsertIcon(path_, IconFormat::PNG, std::move(data)); + } else { + g_iconCache.Cancel(path_); + } } else { g_iconCache.Cancel(path_); } @@ -96,7 +105,7 @@ class HttpImageFileView : public UI::View { std::string path_; // or cache key uint32_t color_ = 0xFFFFFFFF; UI::ImageSizeMode sizeMode_; - http::Downloader *downloader_; + http::RequestManager *requestManager_; std::shared_ptr download_; std::string textureData_; @@ -165,7 +174,7 @@ void HttpImageFileView::Draw(UIContext &dc) { if (!texture_ && !textureFailed_ && !path_.empty() && !download_) { auto cb = std::bind(&HttpImageFileView::DownloadCompletedCallback, this, std::placeholders::_1); const char *acceptMime = "image/png, image/jpeg, image/*; q=0.9, */*; q=0.8"; - downloader_->StartDownloadWithCallback(path_, Path(), http::ProgressBarMode::NONE, cb, acceptMime); + requestManager_->StartDownloadWithCallback(path_, Path(), http::ProgressBarMode::NONE, cb, acceptMime); } if (!textureData_.empty()) { @@ -275,7 +284,7 @@ void ProductView::CreateViews() { Clear(); if (!entry_.iconURL.empty()) { - Add(new HttpImageFileView(&g_DownloadManager, ResolveUrl(storeBaseUrl, entry_.iconURL), IS_FIXED))->SetFixedSize(144, 88); + Add(new HttpImageFileView(&g_DownloadManager, ResolveUrl(StoreBaseUrl(), entry_.iconURL), IS_FIXED))->SetFixedSize(144, 88); } Add(new TextView(entry_.name)); Add(new TextView(entry_.author)); @@ -346,7 +355,7 @@ void ProductView::Update() { std::string ProductView::DownloadURL() { if (entry_.downloadURL.empty()) { // Construct the URL. - return storeBaseUrl + "files/" + entry_.file + ".zip"; + return StoreBaseUrl() + "files/" + entry_.file + ".zip"; } else { // Use the provided URL, for external hosting. return entry_.downloadURL; @@ -401,7 +410,7 @@ StoreScreen::StoreScreen() { lang_ = g_Config.sLanguageIni; loading_ = true; - std::string indexPath = storeBaseUrl + "index.json"; + std::string indexPath = StoreBaseUrl() + "index.json"; const char *acceptMime = "application/json, */*; q=0.8"; listing_ = g_DownloadManager.StartDownload(indexPath, Path(), http::ProgressBarMode::DELAYED, acceptMime); } diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index e5a72c7d3278..3e9878bf65ae 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -114,6 +114,8 @@ + + @@ -259,6 +261,7 @@ + @@ -273,6 +276,8 @@ + + @@ -398,6 +403,7 @@ + diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters index 2dfc1ae39763..2eedf9e8c653 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj.filters +++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters @@ -94,6 +94,9 @@ {8b92cc15-8e3e-45b1-ba80-ad39b1a9cdc8} + + {403c3154-5e8a-4da1-ba82-8f69bef25e14} + @@ -444,6 +447,15 @@ System + + Net + + + Net + + + ext\naett + @@ -841,6 +853,15 @@ System + + Net + + + Net + + + ext\naett + diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index f345af5f1a47..881a31cab516 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -249,7 +249,7 @@ stdcpp17 - uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/x86/lib true Windows @@ -289,7 +289,7 @@ stdcpp17 - uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/x86_64/lib true $(OutDir)$(ProjectName).pdb @@ -325,7 +325,7 @@ stdcpp17 - uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) + winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/aarch64/lib true $(OutDir)$(ProjectName).pdb @@ -359,7 +359,7 @@ stdcpp17 - uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) + winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/arm/lib true $(OutDir)$(ProjectName).pdb @@ -397,7 +397,7 @@ stdcpp17 - uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/x86/lib;%(AdditionalLibraryDirectories) $(OutDir)$(TargetName)$(TargetExt) true @@ -446,7 +446,7 @@ stdcpp17 - uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/x86_64/lib;%(AdditionalLibraryDirectories) true Windows @@ -489,7 +489,7 @@ stdcpp17 - uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) + winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/aarch64/lib;%(AdditionalLibraryDirectories) true Windows @@ -530,7 +530,7 @@ stdcpp17 - uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) + winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/arm/lib;%(AdditionalLibraryDirectories) true Windows diff --git a/Windows/main.cpp b/Windows/main.cpp index 7fe8de2ddc55..6cbd2e6243e5 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -375,6 +375,8 @@ bool System_GetPropertyBool(SystemProperty prop) { return true; case SYSPROP_SUPPORTS_OPEN_FILE_IN_EDITOR: return true; // FileUtil.cpp: OpenFileInEditor + case SYSPROP_SUPPORTS_HTTPS: + return true; default: return false; } diff --git a/android/jni/Android.mk b/android/jni/Android.mk index bfb6874e63b2..4fe1d0df45d4 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -79,7 +79,10 @@ SPIRV_CROSS_FILES := \ $(SRC)/ext/SPIRV-Cross/spirv_glsl.cpp \ $(SRC)/ext/SPIRV-Cross/spirv_parser.cpp \ $(SRC)/ext/SPIRV-Cross/spirv_cross_parsed_ir.cpp - + +NAETT_FILES := \ + ${SRC}/ext/naett/naett.c + RCHEEVOS_FILES := \ ${SRC}/ext/rcheevos/src/rapi/rc_api_common.c \ ${SRC}/ext/rcheevos/src/rapi/rc_api_editor.c \ @@ -178,6 +181,7 @@ EXEC_AND_LIB_FILES := \ $(VMA_FILES) \ $(SPIRV_CROSS_FILES) \ $(RCHEEVOS_FILES) \ + $(NAETT_FILES) \ $(EXT_FILES) \ $(NATIVE_FILES) \ $(SRC)/Common/Buffer.cpp \ @@ -238,6 +242,8 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Common/Math/lin/matrix4x4.cpp.arm \ $(SRC)/Common/Net/HTTPClient.cpp \ $(SRC)/Common/Net/HTTPHeaders.cpp \ + $(SRC)/Common/Net/HTTPRequest.cpp \ + $(SRC)/Common/Net/HTTPNaettRequest.cpp \ $(SRC)/Common/Net/HTTPServer.cpp \ $(SRC)/Common/Net/NetBuffer.cpp \ $(SRC)/Common/Net/Resolve.cpp \ diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index ca80a429ba71..61c737396c9a 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -158,7 +158,8 @@ static int desiredBackbufferSizeX; static int desiredBackbufferSizeY; // Cache the class loader so we can use it from native threads. Required for TextAndroid. -static JavaVM* gJvm = nullptr; +extern JavaVM *gJvm; + static jobject gClassLoader; static jmethodID gFindClassMethod; @@ -534,6 +535,10 @@ bool System_GetPropertyBool(SystemProperty prop) { } case SYSPROP_HAS_KEYBOARD: return deviceType != DEVICE_TYPE_VR; +#ifndef HTTPS_NOT_AVAILABLE + case SYSPROP_SUPPORTS_HTTPS: + return true; +#endif default: return false; } diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt index 8fc0581d45b0..9bbb9b7a7452 100644 --- a/ext/CMakeLists.txt +++ b/ext/CMakeLists.txt @@ -31,6 +31,9 @@ add_subdirectory(snappy) add_subdirectory(udis86) add_subdirectory(SPIRV-Cross-build) add_subdirectory(rcheevos-build) +if(NOT HTTPS_NOT_AVAILABLE) + add_subdirectory(naett-build) +endif() if(USE_DISCORD AND NOT IOS AND NOT LIBRETRO) add_subdirectory(discord-rpc-build) endif() diff --git a/ext/naett b/ext/naett new file mode 160000 index 000000000000..24438d3d6c6e --- /dev/null +++ b/ext/naett @@ -0,0 +1 @@ +Subproject commit 24438d3d6c6e4639b51237ac34cebf25781d5f0a diff --git a/ext/naett-build/CMakeLists.txt b/ext/naett-build/CMakeLists.txt new file mode 100644 index 000000000000..6b3b4893466e --- /dev/null +++ b/ext/naett-build/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required (VERSION 3.2.0) +project (naett) + +set(SRC_DIR ../naett) + +set(ALL_SOURCE_FILES + ${SRC_DIR}/naett.c + ) + +add_library(naett STATIC ${ALL_SOURCE_FILES}) diff --git a/headless/Headless.vcxproj b/headless/Headless.vcxproj index 695f20dbe4fa..65cc85d5b46c 100644 --- a/headless/Headless.vcxproj +++ b/headless/Headless.vcxproj @@ -191,7 +191,7 @@ Console true - mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9d.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9d.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) 0x00400000 false true @@ -225,7 +225,7 @@ Console true - mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9d.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9d.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) 0x00400000 false true @@ -258,7 +258,7 @@ Console true - ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) + winhttp.lib;ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/aarch64/lib @@ -289,7 +289,7 @@ Console true - ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) + winhttp.lib;ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/arm/lib @@ -323,7 +323,7 @@ true true true - mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) 0x00400000 false true @@ -362,7 +362,7 @@ true true true - mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) 0x00400000 false true @@ -400,7 +400,7 @@ true true true - ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) + winhttp.lib;ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/aarch64/lib;%(AdditionalLibraryDirectories) @@ -435,7 +435,7 @@ true true true - ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) + winhttp.lib;ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/arm/lib;%(AdditionalLibraryDirectories) diff --git a/ios/main.mm b/ios/main.mm index 18d23f851775..4ca2f041ddbd 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -168,7 +168,10 @@ bool System_GetPropertyBool(SystemProperty prop) { #endif case SYSPROP_CAN_JIT: return get_debugged(); - +#ifndef HTTPS_NOT_AVAILABLE + case SYSPROP_SUPPORTS_HTTPS: + return true; +#endif default: return false; } diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 29bc7de7e4b6..8c6a90ca0608 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -224,6 +224,8 @@ SOURCES_C += \ $(EXTDIR)/rcheevos/src/rhash/md5.c COREFLAGS += -DSTACK_LINE_READER_BUFFER_SIZE=1024 +COREFLAGS += -DHTTPS_NOT_AVAILABLE + ifeq ($(PLATFORM_EXT), android) COREFLAGS += -DHAVE_DLFCN_H else ifneq ($(PLATFORM_EXT), win32) @@ -351,6 +353,8 @@ SOURCES_CXX += \ $(COMMONDIR)/Net/HTTPClient.cpp \ $(COMMONDIR)/Net/HTTPHeaders.cpp \ $(COMMONDIR)/Net/HTTPServer.cpp \ + $(COMMONDIR)/Net/HTTPRequest.cpp \ + $(COMMONDIR)/Net/HTTPNaettRequest.cpp \ $(COMMONDIR)/Net/NetBuffer.cpp \ $(COMMONDIR)/Net/Resolve.cpp \ $(COMMONDIR)/Net/Sinks.cpp \ diff --git a/unittest/UnitTests.vcxproj b/unittest/UnitTests.vcxproj index e96bfd789215..7417f4f38b63 100644 --- a/unittest/UnitTests.vcxproj +++ b/unittest/UnitTests.vcxproj @@ -181,7 +181,7 @@ Console true - mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/x86/lib @@ -205,7 +205,7 @@ Console true - mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/x86_64/lib @@ -229,7 +229,7 @@ Console true - mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) + winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/aarch64/lib @@ -254,7 +254,7 @@ Console true - mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) + winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/arm/lib @@ -283,7 +283,7 @@ true true true - mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/x86/lib @@ -313,7 +313,7 @@ true true true - mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/x86_64/lib @@ -343,7 +343,7 @@ true true true - mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) + winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/aarch64/lib @@ -373,7 +373,7 @@ true true true - mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) + winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/arm/lib