diff --git a/CMakeLists.txt b/CMakeLists.txt
index dddcf33403..f11a7d71cb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -710,6 +710,8 @@ add_library(Common STATIC
Common/Net/HTTPClient.h
Common/Net/HTTPHeaders.cpp
Common/Net/HTTPHeaders.h
+ Common/Net/HTTPRequest.cpp
+ Common/Net/HTTPRequest.h
Common/Net/HTTPServer.cpp
Common/Net/HTTPServer.h
Common/Net/NetBuffer.cpp
diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj
index 2e5a95a43b..c26c2295a3 100644
--- a/Common/Common.vcxproj
+++ b/Common/Common.vcxproj
@@ -494,6 +494,7 @@
+
@@ -938,6 +939,7 @@
+
diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters
index deb16350c3..8c8aedeb5f 100644
--- a/Common/Common.vcxproj.filters
+++ b/Common/Common.vcxproj.filters
@@ -512,6 +512,9 @@
System
+
+ Net
+
@@ -959,6 +962,9 @@
System
+
+ Net
+
@@ -1107,4 +1113,4 @@
ext\basis_universal
-
\ No newline at end of file
+
diff --git a/Common/Net/HTTPClient.cpp b/Common/Net/HTTPClient.cpp
index 9974fd6888..b5c47f6695 100644
--- a/Common/Net/HTTPClient.cpp
+++ b/Common/Net/HTTPClient.cpp
@@ -589,86 +589,4 @@ void HTTPDownload::Do() {
completed_ = true;
}
-std::shared_ptr Downloader::StartDownload(const std::string &url, const Path &outfile, ProgressBarMode mode, const char *acceptMime) {
- std::shared_ptr dl(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 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 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 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 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 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 4235d0e13c..10113c3a9c 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,65 +90,6 @@ protected:
double dataTimeout_ = 900.0;
};
-enum class RequestMethod {
- GET,
- POST,
-};
-
-enum class ProgressBarMode {
- NONE,
- VISIBLE,
- DELAYED,
-};
-
-class Download {
-public:
- Download(const std::string &url, const std::string &name, bool *cancelled) : url_(url), name_(name), progress_(cancelled) {}
- virtual ~Download() {}
-
- virtual void SetAccept(const char *mime) = 0;
- virtual void SetUserAgent(const std::string &userAgent) = 0;
-
- // 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() const = 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;
-
- virtual Buffer &buffer() = 0;
- virtual const Buffer &buffer() const = 0;
-
-protected:
- std::function callback_;
- std::string url_;
- std::string name_;
- net::RequestProgress progress_;
-
-private:
-};
-
// Really an asynchronous request.
class HTTPDownload : public Download {
public:
@@ -208,48 +150,4 @@ private:
bool joined_ = false;
};
-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/HTTPRequest.cpp b/Common/Net/HTTPRequest.cpp
new file mode 100644
index 0000000000..c993bd4566
--- /dev/null
+++ b/Common/Net/HTTPRequest.cpp
@@ -0,0 +1,89 @@
+#include "Common/Net/HTTPRequest.h"
+#include "Common/Net/HTTPClient.h"
+#include "Common/TimeUtil.h"
+
+namespace http {
+
+std::shared_ptr RequestManager::StartDownload(const std::string &url, const Path &outfile, ProgressBarMode mode, const char *acceptMime) {
+ std::shared_ptr dl(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(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(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 0000000000..ae09baa9ce
--- /dev/null
+++ b/Common/Net/HTTPRequest.h
@@ -0,0 +1,117 @@
+#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(const std::string &url, const std::string &name, bool *cancelled) : url_(url), name_(name), progress_(cancelled) {}
+ virtual ~Download() {}
+
+ virtual void SetAccept(const char *mime) = 0;
+ virtual void SetUserAgent(const std::string &userAgent) = 0;
+
+ // 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() const = 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_;
+ std::string url_;
+ std::string name_;
+ net::RequestProgress progress_;
+
+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:
+ 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/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj
index e5a72c7d32..39bf0aece7 100644
--- a/UWP/CommonUWP/CommonUWP.vcxproj
+++ b/UWP/CommonUWP/CommonUWP.vcxproj
@@ -114,6 +114,7 @@
+
@@ -273,6 +274,7 @@
+
diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters
index 2dfc1ae397..49b74be9b8 100644
--- a/UWP/CommonUWP/CommonUWP.vcxproj.filters
+++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters
@@ -444,6 +444,9 @@
System
+
+ Net
+
@@ -841,6 +844,9 @@
System
+
+ Net
+
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
index bfb6874e63..cffe34f588 100644
--- a/android/jni/Android.mk
+++ b/android/jni/Android.mk
@@ -238,6 +238,7 @@ 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/HTTPServer.cpp \
$(SRC)/Common/Net/NetBuffer.cpp \
$(SRC)/Common/Net/Resolve.cpp \
diff --git a/libretro/Makefile.common b/libretro/Makefile.common
index 29bc7de7e4..bad6f6c73c 100644
--- a/libretro/Makefile.common
+++ b/libretro/Makefile.common
@@ -351,6 +351,7 @@ SOURCES_CXX += \
$(COMMONDIR)/Net/HTTPClient.cpp \
$(COMMONDIR)/Net/HTTPHeaders.cpp \
$(COMMONDIR)/Net/HTTPServer.cpp \
+ $(COMMONDIR)/Net/HTTPRequest.cpp \
$(COMMONDIR)/Net/NetBuffer.cpp \
$(COMMONDIR)/Net/Resolve.cpp \
$(COMMONDIR)/Net/Sinks.cpp \