diff --git a/src/core/hle/service/http/http.cpp b/src/core/hle/service/http/http.cpp index 4e06cefa5..aeb4fcf1b 100644 --- a/src/core/hle/service/http/http.cpp +++ b/src/core/hle/service/http/http.cpp @@ -39,8 +39,7 @@ static CURLcode SetConnectionType(CURL* connection, RequestType type) { case REQUEST_TYPE_PUT_: return curl_easy_setopt(connection, CURLOPT_UPLOAD, 1); case REQUEST_TYPE_DELETE: - // TODO - break; + break; // TODO case REQUEST_TYPE_HEAD: return curl_easy_setopt(connection, CURLOPT_NOBODY, 1); } @@ -90,7 +89,7 @@ void MakeRequest(HttpContext* context) { { std::lock_guard lock(context->mutex); - if (context->should_quit) + if (context->cancel_request) break; } @@ -127,7 +126,7 @@ void Init() { void ClearInstance() { for (auto& pair : context_map) { - pair.second->should_quit = true; + pair.second->cancel_request = true; if (pair.second->req_thread != nullptr) pair.second->req_thread->join(); } diff --git a/src/core/hle/service/http/http.h b/src/core/hle/service/http/http.h index 472f296f5..ea9d13737 100644 --- a/src/core/hle/service/http/http.h +++ b/src/core/hle/service/http/http.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "core/hle/result.h" @@ -19,6 +20,7 @@ namespace HTTP { typedef u32 ContextHandle; +/// HTTP operation that will be performed by the request (API-exposed). enum RequestType : u32 { REQUEST_TYPE_NONE = 0, REQUEST_TYPE_GET = 1, @@ -30,28 +32,36 @@ enum RequestType : u32 { REQUEST_TYPE_PUT_ = 7 }; +/// Current state of the HTTP request (API-exposed). enum RequestState : u32 { - REQUEST_STATE_DEFAULT, // TODO REQUEST_STATE_IN_PROGRESS = 5, REQUEST_STATE_READY = 8, }; +/** A helper struct that contains all the required information for a HTTP request. + * This struct, as it can be accessed by multiple threads, contains a mutex that + * must be locked whenever any of the struct's members are being accessed. This is + * to prevent any possible race conditions. + */ struct HttpContext { std::mutex mutex; - bool should_quit; - RequestState state; + //--- Ongoing request management + RequestState state; //< API-exposed current state of the HTTP request std::unique_ptr req_thread; + bool cancel_request; //< True if the request's thread should be canceled ASAP - std::string url; - RequestType req_type; - curl_slist* request_hdrs; + //--- Request data + std::string url; //< URL to the target server. + RequestType req_type; //< Type of request that will be performed + curl_slist* request_hdrs; //< Buffer for request headers to be sent to the server. - std::vector response_hdrs; - std::vector response_data; - long response_code; - double content_length; - double downloaded_size; + //--- Response data + std::vector response_hdrs; //< Buffer for response headers returned by the server. + std::vector response_data; //< Buffer for response body returned by the server. + long response_code; //< The three-digit HTTP response code returned by the server. + double content_length; //< The total size in bytes that will be downloaded this request. + double downloaded_size; //< The amount in bytes that has been downloaded so far. ~HttpContext(); }; @@ -59,7 +69,14 @@ struct HttpContext { extern std::unordered_map> context_map; extern ContextHandle next_handle; +/** Makes an HTTP request using libcurl. Ideally called as part of a new thread. + * @param context A pointer to the HttpContext that will be used by this request. This pointer must remain valid. + */ void MakeRequest(HttpContext* context); + +/** Appends a name-value pair to a curl_slist* + * @param hdr_list A reference to the curl_slist* + */ void AddRequestHeader(const std::string& name, const std::string& value, curl_slist** hdr_list); /// Initialize the HTTP service diff --git a/src/core/hle/service/http/http_c.cpp b/src/core/hle/service/http/http_c.cpp index c659bf9a3..dd14af66a 100644 --- a/src/core/hle/service/http/http_c.cpp +++ b/src/core/hle/service/http/http_c.cpp @@ -29,9 +29,7 @@ static void CreateContext(Service::Interface* self) { char* url_ptr = reinterpret_cast(Memory::GetPointer(cmd_buff[4])); LOG_DEBUG(Service, "request url=%s req_type=%u", url_ptr, req_type); - - // TODO: give HttpContext a proper constructor - std::unique_ptr context(new HttpContext{}); + auto context = Common::make_unique(); context->req_type = req_type; context->url = std::string(url_ptr, url_len); @@ -53,7 +51,7 @@ static void CloseContext(Service::Interface* self) { return; } - map_it->second->should_quit = true; + map_it->second->cancel_request = true; if (map_it->second->req_thread != nullptr) map_it->second->req_thread->join(); @@ -72,7 +70,7 @@ static void CancelConnection(Service::Interface* self) { cmd_buff[1] = -1; // TODO: Find proper result code for invalid handle return; } - map_it->second->should_quit = true; + map_it->second->cancel_request = true; cmd_buff[1] = RESULT_SUCCESS.raw; }