// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team // SPDX-License-Identifier: GPL-3.0+ #pragma once #include "common/Pcsx2Defs.h" #include <atomic> #include <functional> #include <memory> #include <mutex> #include <string> #include <string_view> #include <variant> #include <vector> class ProgressCallback; class HTTPDownloader { public: enum : s32 { HTTP_STATUS_CANCELLED = -3, HTTP_STATUS_TIMEOUT = -2, HTTP_STATUS_ERROR = -1, HTTP_STATUS_OK = 200 }; struct Request { using Data = std::vector<u8>; using Callback = std::function<void(s32 status_code, const std::string& content_type, Data data)>; enum class Type { Get, Post, }; enum class State { Pending, Cancelled, Started, Receiving, Complete, }; HTTPDownloader* parent; Callback callback; ProgressCallback* progress; std::string url; std::string post_data; std::string content_type; Data data; u64 start_time; s32 status_code = 0; u32 content_length = 0; u32 last_progress_update = 0; Type type = Type::Get; std::atomic<State> state{State::Pending}; }; HTTPDownloader(); virtual ~HTTPDownloader(); static std::unique_ptr<HTTPDownloader> Create(std::string user_agent = DEFAULT_USER_AGENT); static std::string GetExtensionForContentType(const std::string& content_type); void SetTimeout(float timeout); void SetMaxActiveRequests(u32 max_active_requests); void CreateRequest(std::string url, Request::Callback callback, ProgressCallback* progress = nullptr); void CreatePostRequest(std::string url, std::string post_data, Request::Callback callback, ProgressCallback* progress = nullptr); void PollRequests(); void WaitForAllRequests(); bool HasAnyRequests(); static const char DEFAULT_USER_AGENT[]; protected: virtual Request* InternalCreateRequest() = 0; virtual void InternalPollRequests() = 0; virtual bool StartRequest(Request* request) = 0; virtual void CloseRequest(Request* request) = 0; void LockedAddRequest(Request* request); u32 LockedGetActiveRequestCount(); void LockedPollRequests(std::unique_lock<std::mutex>& lock); float m_timeout; u32 m_max_active_requests; std::mutex m_pending_http_request_lock; std::vector<Request*> m_pending_http_requests; };