mirror of
https://github.com/stenzek/duckstation.git
synced 2026-07-11 01:24:11 +02:00
HTTPDownloader: Add owner tracking to requests
Allow finer-grained cancellation.
This commit is contained in:
@@ -882,9 +882,9 @@ uint32_t Achievements::ClientReadMemory(uint32_t address, uint8_t* buffer, uint3
|
||||
void Achievements::ClientServerCall(const rc_api_request_t* request, rc_client_server_callback_t callback,
|
||||
void* callback_data, rc_client_t* client)
|
||||
{
|
||||
HTTPDownloader::Request::Callback hd_callback = [callback, callback_data](s32 status_code, const Error& error,
|
||||
const std::string& content_type,
|
||||
HTTPDownloader::Request::Data data) {
|
||||
HTTPDownloader::Request::Callback hd_callback = [callback, callback_data](s32 status_code, Error& error,
|
||||
std::string& content_type,
|
||||
HTTPDownloader::Request::Data& data) {
|
||||
if (status_code != HTTPDownloader::HTTP_STATUS_OK)
|
||||
ERROR_LOG("Server call failed: {}", error.GetDescription());
|
||||
|
||||
@@ -904,12 +904,12 @@ void Achievements::ClientServerCall(const rc_api_request_t* request, rc_client_s
|
||||
{
|
||||
// const auto pd = std::string_view(request->post_data);
|
||||
// Log_DevFmt("Server POST: {}", pd.substr(0, std::min<size_t>(pd.length(), 10)));
|
||||
downloader->CreatePostRequest(request->url, request->post_data, std::move(hd_callback), nullptr, headers,
|
||||
downloader->CreatePostRequest(request->url, request->post_data, &s_state, std::move(hd_callback), nullptr, headers,
|
||||
SERVER_CALL_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
downloader->CreateRequest(request->url, std::move(hd_callback), nullptr, headers, SERVER_CALL_TIMEOUT);
|
||||
downloader->CreateRequest(request->url, &s_state, std::move(hd_callback), nullptr, headers, SERVER_CALL_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1855,10 +1855,10 @@ bool GameList::DownloadCovers(const std::vector<std::string>& url_templates, boo
|
||||
std::string filename = Path::URLDecode(url);
|
||||
if (HTTPDownloader* const downloader = HTTPCache::GetDownloader(error))
|
||||
{
|
||||
downloader->CreateRequest(std::move(url), [use_serial, &save_callback, entry_path = std::move(entry_path),
|
||||
filename = std::move(filename)](s32 status_code, const Error& error,
|
||||
const std::string& content_type,
|
||||
HTTPDownloader::Request::Data data) {
|
||||
downloader->CreateRequest(
|
||||
std::move(url), &s_state,
|
||||
[use_serial, &save_callback, entry_path = std::move(entry_path), filename = std::move(filename)](
|
||||
s32 status_code, Error& error, std::string& content_type, HTTPDownloader::Request::Data& data) {
|
||||
if (status_code != HTTPDownloader::HTTP_STATUS_OK || data.empty())
|
||||
{
|
||||
ERROR_LOG("Download for {} failed: {}", Path::GetFileName(filename), error.GetDescription());
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
#include "core/core.h"
|
||||
|
||||
#include "util/http_downloader.h"
|
||||
#include "util/http_cache.h"
|
||||
#include "util/http_downloader.h"
|
||||
#include "util/translation.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
@@ -359,22 +359,23 @@ void AutoUpdaterDialog::queueUpdateCheck(bool display_errors, bool ignore_skippe
|
||||
}
|
||||
|
||||
ensureHttpPollingActive();
|
||||
m_http->CreateRequest(LATEST_TAG_URL,
|
||||
[this, display_errors](s32 status_code, const Error& error, const std::string& content_type,
|
||||
std::vector<u8> response) {
|
||||
getLatestTagComplete(status_code, error, std::move(response), display_errors);
|
||||
});
|
||||
m_http->CreateRequest(
|
||||
LATEST_TAG_URL, this,
|
||||
[this, display_errors](s32 status_code, Error& error, std::string& content_type, std::vector<u8>& response) {
|
||||
getLatestTagComplete(status_code, error, response, display_errors);
|
||||
});
|
||||
}
|
||||
|
||||
void AutoUpdaterDialog::queueGetLatestRelease()
|
||||
{
|
||||
ensureHttpPollingActive();
|
||||
std::string url = fmt::format(LATEST_RELEASE_URL, getCurrentUpdateTag());
|
||||
m_http->CreateRequest(std::move(url), std::bind(&AutoUpdaterDialog::getLatestReleaseComplete, this,
|
||||
std::placeholders::_1, std::placeholders::_2, std::placeholders::_4));
|
||||
m_http->CreateRequest(std::move(url), this,
|
||||
std::bind(&AutoUpdaterDialog::getLatestReleaseComplete, this, std::placeholders::_1,
|
||||
std::placeholders::_2, std::placeholders::_4));
|
||||
}
|
||||
|
||||
void AutoUpdaterDialog::getLatestTagComplete(s32 status_code, const Error& error, std::vector<u8> response,
|
||||
void AutoUpdaterDialog::getLatestTagComplete(s32 status_code, Error& error, std::vector<u8>& response,
|
||||
bool display_errors)
|
||||
{
|
||||
if (handleCancelledRequest(status_code))
|
||||
@@ -441,7 +442,7 @@ void AutoUpdaterDialog::getLatestTagComplete(s32 status_code, const Error& error
|
||||
emit updateCheckCompleted(false);
|
||||
}
|
||||
|
||||
void AutoUpdaterDialog::getLatestReleaseComplete(s32 status_code, const Error& error, std::vector<u8> response)
|
||||
void AutoUpdaterDialog::getLatestReleaseComplete(s32 status_code, Error& error, std::vector<u8>& response)
|
||||
{
|
||||
if (handleCancelledRequest(status_code))
|
||||
return;
|
||||
@@ -521,11 +522,12 @@ void AutoUpdaterDialog::queueGetChanges()
|
||||
{
|
||||
ensureHttpPollingActive();
|
||||
std::string url = fmt::format(CHANGES_URL, g_scm_hash_str, getCurrentUpdateTag());
|
||||
m_http->CreateRequest(std::move(url), std::bind(&AutoUpdaterDialog::getChangesComplete, this, std::placeholders::_1,
|
||||
std::placeholders::_2, std::placeholders::_4));
|
||||
m_http->CreateRequest(std::move(url), this,
|
||||
std::bind(&AutoUpdaterDialog::getChangesComplete, this, std::placeholders::_1,
|
||||
std::placeholders::_2, std::placeholders::_4));
|
||||
}
|
||||
|
||||
void AutoUpdaterDialog::getChangesComplete(s32 status_code, const Error& error, std::vector<u8> response)
|
||||
void AutoUpdaterDialog::getChangesComplete(s32 status_code, Error& error, std::vector<u8>& response)
|
||||
{
|
||||
std::string_view error_message;
|
||||
|
||||
@@ -607,8 +609,8 @@ void AutoUpdaterDialog::downloadUpdateClicked()
|
||||
|
||||
ensureHttpPollingActive();
|
||||
m_http->CreateRequest(
|
||||
m_download_url.toStdString(),
|
||||
[this](s32 status_code, const Error& error, const std::string&, std::vector<u8> response) {
|
||||
m_download_url.toStdString(), this,
|
||||
[this](s32 status_code, Error& error, std::string&, std::vector<u8>& response) {
|
||||
m_download_progress_callback->SetStatusText(TRANSLATE_SV("AutoUpdaterWindow", "Processing Update..."));
|
||||
m_download_progress_callback->SetProgressRange(1);
|
||||
m_download_progress_callback->SetProgressValue(1);
|
||||
|
||||
@@ -71,11 +71,11 @@ private:
|
||||
|
||||
bool updateNeeded() const;
|
||||
|
||||
void getLatestTagComplete(s32 status_code, const Error& error, std::vector<u8> response, bool display_errors);
|
||||
void getLatestReleaseComplete(s32 status_code, const Error& error, std::vector<u8> response);
|
||||
void getLatestTagComplete(s32 status_code, Error& error, std::vector<u8>& response, bool display_errors);
|
||||
void getLatestReleaseComplete(s32 status_code, Error& error, std::vector<u8>& response);
|
||||
|
||||
void queueGetChanges();
|
||||
void getChangesComplete(s32 status_code, const Error& error, std::vector<u8> response);
|
||||
void getChangesComplete(s32 status_code, Error& error, std::vector<u8>& response);
|
||||
|
||||
bool processUpdate(const std::vector<u8>& update_data);
|
||||
|
||||
|
||||
@@ -738,7 +738,7 @@ void QtHost::DownloadFile(QWidget* parent, std::string url, std::string path,
|
||||
|
||||
QtAsyncTaskWithProgressDialog::create(
|
||||
parent, TRANSLATE_SV("QtHost", "File Download"), status_text, false, true, 0, 0, 0.0f, true,
|
||||
[url = std::move(url), path = std::move(path),
|
||||
[parent, url = std::move(url), path = std::move(path),
|
||||
completion_callback = std::move(completion_callback)](ProgressCallback* const progress) mutable {
|
||||
Error error;
|
||||
bool result = false;
|
||||
@@ -746,9 +746,8 @@ void QtHost::DownloadFile(QWidget* parent, std::string url, std::string path,
|
||||
{
|
||||
result = true;
|
||||
downloader->CreateRequest(
|
||||
std::move(url),
|
||||
[&result, &error, &path](s32 status_code, const Error& http_error, const std::string&,
|
||||
std::vector<u8> hdata) {
|
||||
std::move(url), parent,
|
||||
[&result, &error, &path](s32 status_code, Error& http_error, std::string&, std::vector<u8>& hdata) {
|
||||
if (status_code != HTTPDownloader::HTTP_STATUS_OK)
|
||||
{
|
||||
error.SetString(http_error.GetDescription());
|
||||
@@ -766,7 +765,7 @@ void QtHost::DownloadFile(QWidget* parent, std::string url, std::string path,
|
||||
}
|
||||
|
||||
// Block until completion.
|
||||
HTTPCache::WaitForAllRequests();
|
||||
HTTPCache::WaitForAllRequestsFromOwner(parent);
|
||||
|
||||
QtAsyncTaskWithProgressDialog::CompletionCallback ret;
|
||||
if (completion_callback)
|
||||
|
||||
+29
-5
@@ -135,12 +135,36 @@ void HTTPCache::WaitForAllRequests()
|
||||
s_locals.downloader->WaitForAllRequests();
|
||||
}
|
||||
|
||||
void HTTPCache::WaitForAllRequestsFromOwner(const void* owner)
|
||||
{
|
||||
if (s_locals.downloader)
|
||||
s_locals.downloader->WaitForAllRequestsFromOwner(owner);
|
||||
}
|
||||
|
||||
void HTTPCache::WaitForAllRequestsWithYield(std::function<void()> before_sleep_cb, std::function<void()> after_sleep_cb)
|
||||
{
|
||||
if (s_locals.downloader)
|
||||
s_locals.downloader->WaitForAllRequestsWithYield(std::move(before_sleep_cb), std::move(after_sleep_cb));
|
||||
}
|
||||
|
||||
void HTTPCache::WaitForAllRequestsFromOwnerWithYield(const void* owner, std::function<void()> before_sleep_cb,
|
||||
std::function<void()> after_sleep_cb)
|
||||
{
|
||||
if (s_locals.downloader)
|
||||
{
|
||||
s_locals.downloader->WaitForAllRequestsFromOwnerWithYield(owner, std::move(before_sleep_cb),
|
||||
std::move(after_sleep_cb));
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPCache::CancelRequestsForOwner(const void* owner)
|
||||
{
|
||||
if (!s_locals.downloader)
|
||||
return;
|
||||
|
||||
s_locals.downloader->CancelRequestsForOwner(owner);
|
||||
}
|
||||
|
||||
HTTPDownloader* HTTPCache::GetDownloader(Error* create_error)
|
||||
{
|
||||
if (s_locals.downloader) [[likely]]
|
||||
@@ -261,11 +285,11 @@ bool HTTPCache::QueueDownload(std::string_view url, FetchCallback callback, Erro
|
||||
|
||||
DEV_LOG("Cache miss for URL '{}', downloading...", url);
|
||||
|
||||
downloader->CreateRequest(std::string(url), [url = std::string(url)](s32 status_code, const Error& error,
|
||||
const std::string& content_type,
|
||||
HTTPDownloader::Request::Data data) {
|
||||
DownloadCallback(url, status_code, error, content_type, std::move(data));
|
||||
});
|
||||
downloader->CreateRequest(std::string(url), &s_locals,
|
||||
[url = std::string(url)](s32 status_code, Error& error, std::string& content_type,
|
||||
HTTPDownloader::Request::Data& data) {
|
||||
DownloadCallback(url, status_code, error, content_type, std::move(data));
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+10
-4
@@ -53,6 +53,11 @@ std::string GetUserAgent();
|
||||
/// Shuts down the HTTP cache, releasing the downloader and cache archive.
|
||||
void Shutdown();
|
||||
|
||||
/// Returns a pointer to the shared HTTP downloader, creating it on first use.
|
||||
/// If @p create_error is non-null, creation details are written there on failure; if null, creation
|
||||
/// is skipped after the first failed attempt.
|
||||
HTTPDownloader* GetDownloader(Error* create_error = nullptr);
|
||||
|
||||
/// Returns true if idle updates are necessary (e.g. outstanding requests).
|
||||
bool IsDownloaderActive();
|
||||
|
||||
@@ -61,14 +66,15 @@ void PollRequests();
|
||||
|
||||
/// Waits for all requests to finish.
|
||||
void WaitForAllRequests();
|
||||
void WaitForAllRequestsFromOwner(const void* owner);
|
||||
|
||||
/// Waits for all requests to finish, periodically yielding to allow other tasks to run.
|
||||
void WaitForAllRequestsWithYield(std::function<void()> before_sleep_cb, std::function<void()> after_sleep_cb);
|
||||
void WaitForAllRequestsFromOwnerWithYield(const void* owner, std::function<void()> before_sleep_cb,
|
||||
std::function<void()> after_sleep_cb);
|
||||
|
||||
/// Returns a locked pointer to the shared HTTP downloader, creating it on first use.
|
||||
/// If @p create_error is non-null, creation details are written there on failure; if null, creation
|
||||
/// is skipped after the first failed attempt.
|
||||
HTTPDownloader* GetDownloader(Error* create_error = nullptr);
|
||||
/// Cancels all outstanding requests for the specified owner.
|
||||
void CancelRequestsForOwner(const void* owner);
|
||||
|
||||
/// Returns a locked pointer to the shared cache archive, opening it on first use.
|
||||
CacheArchivePtr GetCacheArchive();
|
||||
|
||||
@@ -24,9 +24,10 @@ HTTPDownloader::HTTPDownloader()
|
||||
|
||||
HTTPDownloader::~HTTPDownloader() = default;
|
||||
|
||||
HTTPDownloader::Request::Request(HTTPDownloader* parent, Type type, std::string url, std::string post_data,
|
||||
Callback callback, ProgressCallback* progress, u16 timeout_seconds)
|
||||
: parent(parent), callback(std::move(callback)), progress(progress), url(std::move(url)),
|
||||
HTTPDownloader::Request::Request(HTTPDownloader* parent, const void* owner, Type type, std::string url,
|
||||
std::string post_data, Callback callback, ProgressCallback* progress,
|
||||
u16 timeout_seconds)
|
||||
: parent(parent), owner(owner), callback(std::move(callback)), progress(progress), url(std::move(url)),
|
||||
post_data(std::move(post_data)), type(type), timeout_seconds(timeout_seconds)
|
||||
{
|
||||
// set progress state to indeterminate until we know the size
|
||||
@@ -47,23 +48,24 @@ void HTTPDownloader::SetMaxActiveRequests(u32 max_active_requests)
|
||||
m_max_active_requests = max_active_requests;
|
||||
}
|
||||
|
||||
void HTTPDownloader::CreateRequest(std::string url, Request::Callback callback,
|
||||
void HTTPDownloader::CreateRequest(std::string url, const void* owner, Request::Callback callback,
|
||||
ProgressCallback* progress /* = nullptr */, HeaderList additional_headers /* = */,
|
||||
std::optional<u16> timeout_seconds /* = */)
|
||||
{
|
||||
Request* req = InternalCreateRequest(Request::Type::Get, std::move(url), {}, std::move(callback), progress,
|
||||
Request* req = InternalCreateRequest(Request::Type::Get, std::move(url), {}, owner, std::move(callback), progress,
|
||||
timeout_seconds.value_or(m_default_timeout), additional_headers);
|
||||
DebugAssert(req);
|
||||
StartOrAddRequest(req);
|
||||
}
|
||||
|
||||
void HTTPDownloader::CreatePostRequest(std::string url, std::string post_data, Request::Callback callback,
|
||||
ProgressCallback* progress /* = nullptr */,
|
||||
void HTTPDownloader::CreatePostRequest(std::string url, std::string post_data, const void* owner,
|
||||
Request::Callback callback, ProgressCallback* progress /* = nullptr */,
|
||||
HeaderList additional_headers /* = */,
|
||||
std::optional<u16> timeout_seconds /* = */)
|
||||
{
|
||||
Request* req = InternalCreateRequest(Request::Type::Post, std::move(url), std::move(post_data), std::move(callback),
|
||||
progress, timeout_seconds.value_or(m_default_timeout), additional_headers);
|
||||
Request* req =
|
||||
InternalCreateRequest(Request::Type::Post, std::move(url), std::move(post_data), owner, std::move(callback),
|
||||
progress, timeout_seconds.value_or(m_default_timeout), additional_headers);
|
||||
DebugAssert(req);
|
||||
StartOrAddRequest(req);
|
||||
}
|
||||
@@ -112,7 +114,7 @@ void HTTPDownloader::LockedPollRequests(std::unique_lock<std::mutex>& lock)
|
||||
lock.unlock();
|
||||
|
||||
req->error.SetStringFmt("Request timed out after {} seconds.", req->timeout_seconds);
|
||||
req->callback(HTTP_STATUS_TIMEOUT, req->error, std::string(), Request::Data());
|
||||
req->callback(HTTP_STATUS_TIMEOUT, req->error, req->content_type, req->data);
|
||||
|
||||
CloseRequest(req);
|
||||
|
||||
@@ -130,7 +132,7 @@ void HTTPDownloader::LockedPollRequests(std::unique_lock<std::mutex>& lock)
|
||||
lock.unlock();
|
||||
|
||||
req->error.SetStringView("Request was cancelled.");
|
||||
req->callback(HTTP_STATUS_CANCELLED, req->error, std::string(), Request::Data());
|
||||
req->callback(HTTP_STATUS_CANCELLED, req->error, req->content_type, req->data);
|
||||
|
||||
CloseRequest(req);
|
||||
|
||||
@@ -168,7 +170,7 @@ void HTTPDownloader::LockedPollRequests(std::unique_lock<std::mutex>& lock)
|
||||
else if (req->status_code < 0)
|
||||
DEV_LOG("Request failed with error {}", req->error.GetDescription());
|
||||
|
||||
req->callback(req->status_code, req->error, req->content_type, std::move(req->data));
|
||||
req->callback(req->status_code, req->error, req->content_type, req->data);
|
||||
CloseRequest(req);
|
||||
lock.lock();
|
||||
}
|
||||
@@ -240,6 +242,51 @@ void HTTPDownloader::WaitForAllRequestsWithYield(std::function<void()> before_sl
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPDownloader::WaitForAllRequestsFromOwner(const void* owner)
|
||||
{
|
||||
if (!owner)
|
||||
{
|
||||
WaitForAllRequests();
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock lock(m_pending_http_request_lock);
|
||||
while (std::ranges::any_of(m_pending_http_requests, [owner](const Request* req) { return req->owner == owner; }))
|
||||
{
|
||||
// Don't burn too much CPU.
|
||||
Timer::NanoSleep(WAIT_FOR_ALL_REQUESTS_POLL_INTERVAL_NS);
|
||||
LockedPollRequests(lock);
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPDownloader::WaitForAllRequestsFromOwnerWithYield(const void* owner, std::function<void()> before_sleep_cb,
|
||||
std::function<void()> after_sleep_cb)
|
||||
{
|
||||
if (!owner)
|
||||
{
|
||||
WaitForAllRequestsWithYield(std::move(before_sleep_cb), std::move(after_sleep_cb));
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock lock(m_pending_http_request_lock);
|
||||
while (std::ranges::any_of(m_pending_http_requests, [owner](const Request* req) { return req->owner == owner; }))
|
||||
{
|
||||
// Don't burn too much CPU.
|
||||
if (before_sleep_cb)
|
||||
{
|
||||
lock.unlock();
|
||||
before_sleep_cb();
|
||||
}
|
||||
Timer::NanoSleep(WAIT_FOR_ALL_REQUESTS_POLL_INTERVAL_NS);
|
||||
if (after_sleep_cb)
|
||||
{
|
||||
after_sleep_cb();
|
||||
lock.lock();
|
||||
}
|
||||
LockedPollRequests(lock);
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPDownloader::LockedAddRequest(Request* request)
|
||||
{
|
||||
m_pending_http_requests.push_back(request);
|
||||
@@ -263,7 +310,21 @@ bool HTTPDownloader::HasAnyRequests()
|
||||
return !m_pending_http_requests.empty();
|
||||
}
|
||||
|
||||
bool HTTPDownloader::HasAnyRequestsFromOwner(const void* owner)
|
||||
{
|
||||
if (!owner)
|
||||
return HasAnyRequests();
|
||||
|
||||
std::unique_lock lock(m_pending_http_request_lock);
|
||||
return std::ranges::any_of(m_pending_http_requests, [owner](const Request* req) { return req->owner == owner; });
|
||||
}
|
||||
|
||||
void HTTPDownloader::CancelAllRequests()
|
||||
{
|
||||
CancelRequestsForOwner(nullptr);
|
||||
}
|
||||
|
||||
void HTTPDownloader::CancelRequestsForOwner(const void* owner)
|
||||
{
|
||||
std::unique_lock lock(m_pending_http_request_lock);
|
||||
|
||||
@@ -277,6 +338,12 @@ void HTTPDownloader::CancelAllRequests()
|
||||
for (size_t index = 0; index < m_pending_http_requests.size();)
|
||||
{
|
||||
Request* req = m_pending_http_requests[index];
|
||||
if (owner && req->owner != owner)
|
||||
{
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const Request::State req_state = req->state.load(std::memory_order_acquire);
|
||||
|
||||
// can't cancel a request in pending stage
|
||||
@@ -296,7 +363,7 @@ void HTTPDownloader::CancelAllRequests()
|
||||
lock.unlock();
|
||||
|
||||
req->error.SetStringView("Request was cancelled.");
|
||||
req->callback(HTTP_STATUS_CANCELLED, req->error, std::string(), Request::Data());
|
||||
req->callback(HTTP_STATUS_CANCELLED, req->error, req->content_type, req->data);
|
||||
|
||||
CloseRequest(req);
|
||||
|
||||
|
||||
@@ -36,8 +36,7 @@ public:
|
||||
struct Request
|
||||
{
|
||||
using Data = std::vector<u8>;
|
||||
using Callback =
|
||||
std::function<void(s32 status_code, const Error& error, const std::string& content_type, Data data)>;
|
||||
using Callback = std::function<void(s32 status_code, Error& error, std::string& content_type, Data& data)>;
|
||||
|
||||
enum class Type : u8
|
||||
{
|
||||
@@ -54,11 +53,12 @@ public:
|
||||
Complete,
|
||||
};
|
||||
|
||||
Request(HTTPDownloader* parent, Type type, std::string url, std::string post_data, Callback callback,
|
||||
ProgressCallback* progress, u16 timeout_seconds);
|
||||
Request(HTTPDownloader* parent, const void* owner, Type type, std::string url, std::string post_data,
|
||||
Callback callback, ProgressCallback* progress, u16 timeout_seconds);
|
||||
virtual ~Request();
|
||||
|
||||
HTTPDownloader* parent;
|
||||
const void* owner;
|
||||
Callback callback;
|
||||
ProgressCallback* progress;
|
||||
std::string url;
|
||||
@@ -85,19 +85,25 @@ public:
|
||||
void SetDefaultTimeout(u16 timeout_seconds);
|
||||
void SetMaxActiveRequests(u32 max_active_requests);
|
||||
|
||||
void CreateRequest(std::string url, Request::Callback callback, ProgressCallback* progress = nullptr,
|
||||
HeaderList additional_headers = {}, std::optional<u16> timeout_seconds = {});
|
||||
void CreatePostRequest(std::string url, std::string post_data, Request::Callback callback,
|
||||
void CreateRequest(std::string url, const void* owner, Request::Callback callback,
|
||||
ProgressCallback* progress = nullptr, HeaderList additional_headers = {},
|
||||
std::optional<u16> timeout_seconds = {});
|
||||
void CreatePostRequest(std::string url, std::string post_data, const void* owner, Request::Callback callback,
|
||||
ProgressCallback* progress = nullptr, HeaderList additional_headers = {},
|
||||
std::optional<u16> timeout_seconds = {});
|
||||
bool PollRequests();
|
||||
void WaitForAllRequests();
|
||||
void WaitForAllRequestsWithYield(std::function<void()> before_sleep_cb, std::function<void()> after_sleep_cb);
|
||||
void WaitForAllRequestsFromOwner(const void* owner);
|
||||
void WaitForAllRequestsFromOwnerWithYield(const void* owner, std::function<void()> before_sleep_cb,
|
||||
std::function<void()> after_sleep_cb);
|
||||
bool HasAnyRequests();
|
||||
bool HasAnyRequestsFromOwner(const void* owner);
|
||||
void CancelAllRequests();
|
||||
void CancelRequestsForOwner(const void* owner);
|
||||
|
||||
protected:
|
||||
virtual Request* InternalCreateRequest(Request::Type type, std::string url, std::string post_data,
|
||||
virtual Request* InternalCreateRequest(Request::Type type, std::string url, std::string post_data, const void* owner,
|
||||
Request::Callback callback, ProgressCallback* progress, u16 timeout_seconds,
|
||||
HeaderList additional_headers) = 0;
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@ public:
|
||||
bool Initialize(std::string user_agent, Error* error);
|
||||
|
||||
protected:
|
||||
Request* InternalCreateRequest(Request::Type type, std::string url, std::string post_data, Request::Callback callback,
|
||||
ProgressCallback* progress, u16 timeout_seconds,
|
||||
Request* InternalCreateRequest(Request::Type type, std::string url, std::string post_data, const void* owner,
|
||||
Request::Callback callback, ProgressCallback* progress, u16 timeout_seconds,
|
||||
HeaderList additional_headers) override;
|
||||
bool StartRequest(HTTPDownloader::Request* request) override;
|
||||
void CloseRequest(HTTPDownloader::Request* request) override;
|
||||
@@ -171,12 +171,13 @@ HTTPDownloaderCurl::Request::~Request()
|
||||
}
|
||||
|
||||
HTTPDownloader::Request* HTTPDownloaderCurl::InternalCreateRequest(Request::Type type, std::string url,
|
||||
std::string post_data, Request::Callback callback,
|
||||
std::string post_data, const void* owner,
|
||||
Request::Callback callback,
|
||||
ProgressCallback* progress, u16 timeout_seconds,
|
||||
HeaderList additional_headers)
|
||||
{
|
||||
Request* req =
|
||||
new Request(this, type, std::move(url), std::move(post_data), std::move(callback), progress, timeout_seconds);
|
||||
Request* req = new Request(this, owner, type, std::move(url), std::move(post_data), std::move(callback), progress,
|
||||
timeout_seconds);
|
||||
|
||||
for (const char* header : additional_headers)
|
||||
req->header_list = curl_slist_append(req->header_list, header);
|
||||
@@ -303,7 +304,7 @@ bool HTTPDownloaderCurl::StartRequest(HTTPDownloader::Request* request)
|
||||
{
|
||||
ERROR_LOG("curl_easy_init() failed");
|
||||
req->error.SetStringView("curl_easy_init() failed");
|
||||
req->callback(HTTP_STATUS_ERROR, req->error, std::string(), req->data);
|
||||
req->callback(HTTP_STATUS_ERROR, req->error, req->content_type, req->data);
|
||||
delete req;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ public:
|
||||
bool Initialize(std::string user_agent, Error* error);
|
||||
|
||||
protected:
|
||||
Request* InternalCreateRequest(Request::Type type, std::string url, std::string post_data, Request::Callback callback,
|
||||
ProgressCallback* progress, u16 timeout_seconds,
|
||||
Request* InternalCreateRequest(Request::Type type, std::string url, std::string post_data, const void* owner,
|
||||
Request::Callback callback, ProgressCallback* progress, u16 timeout_seconds,
|
||||
HeaderList additional_headers) override;
|
||||
bool StartRequest(HTTPDownloader::Request* request) override;
|
||||
void CloseRequest(HTTPDownloader::Request* request) override;
|
||||
@@ -261,12 +261,13 @@ void CALLBACK HTTPDownloaderWinHttp::HTTPStatusCallback(HINTERNET hRequest, DWOR
|
||||
}
|
||||
|
||||
HTTPDownloader::Request* HTTPDownloaderWinHttp::InternalCreateRequest(Request::Type type, std::string url,
|
||||
std::string post_data, Request::Callback callback,
|
||||
std::string post_data, const void* owner,
|
||||
Request::Callback callback,
|
||||
ProgressCallback* progress, u16 timeout_seconds,
|
||||
HeaderList additional_headers)
|
||||
{
|
||||
Request* req =
|
||||
new Request(this, type, std::move(url), std::move(post_data), std::move(callback), progress, timeout_seconds);
|
||||
Request* req = new Request(this, owner, type, std::move(url), std::move(post_data), std::move(callback), progress,
|
||||
timeout_seconds);
|
||||
|
||||
if (!additional_headers.empty())
|
||||
{
|
||||
@@ -307,7 +308,7 @@ bool HTTPDownloaderWinHttp::StartRequest(HTTPDownloader::Request* request)
|
||||
const DWORD err = GetLastError();
|
||||
ERROR_LOG("WinHttpCrackUrl() failed: {}", err);
|
||||
req->error.SetWin32("WinHttpCrackUrl() failed: ", err);
|
||||
req->callback(HTTP_STATUS_ERROR, req->error, std::string(), req->data);
|
||||
req->callback(HTTP_STATUS_ERROR, req->error, req->content_type, req->data);
|
||||
delete req;
|
||||
return false;
|
||||
}
|
||||
@@ -321,7 +322,7 @@ bool HTTPDownloaderWinHttp::StartRequest(HTTPDownloader::Request* request)
|
||||
const DWORD err = GetLastError();
|
||||
ERROR_LOG("Failed to start HTTP request for '{}': {}", req->url, err);
|
||||
req->error.SetWin32("WinHttpConnect() failed: ", err);
|
||||
req->callback(HTTP_STATUS_ERROR, req->error, std::string(), req->data);
|
||||
req->callback(HTTP_STATUS_ERROR, req->error, req->content_type, req->data);
|
||||
delete req;
|
||||
return false;
|
||||
}
|
||||
@@ -335,7 +336,7 @@ bool HTTPDownloaderWinHttp::StartRequest(HTTPDownloader::Request* request)
|
||||
const DWORD err = GetLastError();
|
||||
ERROR_LOG("WinHttpOpenRequest() failed: {}", err);
|
||||
req->error.SetWin32("WinHttpOpenRequest() failed: ", err);
|
||||
req->callback(HTTP_STATUS_ERROR, req->error, std::string(), req->data);
|
||||
req->callback(HTTP_STATUS_ERROR, req->error, req->content_type, req->data);
|
||||
WinHttpCloseHandle(req->hConnection);
|
||||
delete req;
|
||||
return false;
|
||||
@@ -349,7 +350,7 @@ bool HTTPDownloaderWinHttp::StartRequest(HTTPDownloader::Request* request)
|
||||
const DWORD err = GetLastError();
|
||||
ERROR_LOG("WinHttpAddRequestHeaders() failed: {}", err);
|
||||
req->error.SetWin32("WinHttpAddRequestHeaders() failed: ", err);
|
||||
req->callback(HTTP_STATUS_ERROR, req->error, std::string(), req->data);
|
||||
req->callback(HTTP_STATUS_ERROR, req->error, req->content_type, req->data);
|
||||
WinHttpCloseHandle(req->hRequest);
|
||||
WinHttpCloseHandle(req->hConnection);
|
||||
delete req;
|
||||
|
||||
Reference in New Issue
Block a user