From eb2dd8bf5ddbcbbc847c406ad1d418b8be8ea99d Mon Sep 17 00:00:00 2001 From: archshift Date: Wed, 13 May 2015 01:00:00 -0700 Subject: [PATCH] Fixes based on verification of behavior on hardware --- src/core/hle/service/http/http.cpp | 15 +++++++---- src/core/hle/service/http/http.h | 3 ++- src/core/hle/service/http/http_c.cpp | 37 +++++++++++++++------------- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/core/hle/service/http/http.cpp b/src/core/hle/service/http/http.cpp index b89ce2b13..b834c489e 100644 --- a/src/core/hle/service/http/http.cpp +++ b/src/core/hle/service/http/http.cpp @@ -25,7 +25,7 @@ static int BufWriter(u8 *data, size_t size, size_t nmemb, std::vector* out_b } HttpContext::HttpContext() { - state = REQUEST_STATE_NONE; + state = REQUEST_STATE_NOT_STARTED; cancel_request = false; req_type = REQUEST_TYPE_NONE; request_hdrs = nullptr; @@ -76,24 +76,28 @@ void MakeRequest(HttpContext* context) { res = curl_easy_setopt(connection, CURLOPT_HEADERDATA, &response_hdrs); res = curl_easy_setopt(connection, CURLOPT_WRITEDATA, &response_data); - mres = curl_multi_add_handle(manager, connection); + curl_multi_add_handle(manager, connection); int still_running = 0; int repeats = 0; - mres = curl_multi_perform(manager, &still_running); + curl_multi_perform(manager, &still_running); do { // Number of file descriptors. If this is zero, nothing happened to // the active connection. int numfds; + // Set the timeout to 1sec. if (curl_multi_wait(manager, NULL, 0, 1000, &numfds) != CURLM_OK) break; if (numfds == 0) { + // We allow one repeat try--after which, we start to sleep the + // thread until the timeout runs out. if (repeats++ > 1) - std::this_thread::sleep_for(std::chrono::milliseconds(25)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } else { + // While the file descriptor is responding, there's no need to check for repeats. repeats = 0; } @@ -103,7 +107,7 @@ void MakeRequest(HttpContext* context) { break; } - mres = curl_multi_perform(manager, &still_running); + curl_multi_perform(manager, &still_running); } while (still_running != 0); { @@ -124,6 +128,7 @@ void MakeRequest(HttpContext* context) { } void AddRequestHeader(const std::string& name, const std::string& value, curl_slist** hdr_list) { + // TODO: header value is empty std::string header = Common::StringFromFormat("%s: %s", name.c_str(), value.c_str()); *hdr_list = curl_slist_append(*hdr_list, header.c_str()); } diff --git a/src/core/hle/service/http/http.h b/src/core/hle/service/http/http.h index 59a3ffee3..ee0955a3e 100644 --- a/src/core/hle/service/http/http.h +++ b/src/core/hle/service/http/http.h @@ -34,9 +34,10 @@ enum RequestType : u32 { /// Current state of the HTTP request (API-exposed). enum RequestState : u32 { - REQUEST_STATE_NONE = 0, // TODO: Verify + REQUEST_STATE_NOT_STARTED = 1, REQUEST_STATE_IN_PROGRESS = 5, REQUEST_STATE_READY = 8, + REQUEST_STATE_TIMEOUT = 10, }; /** A helper struct that contains all the required information for a HTTP request. diff --git a/src/core/hle/service/http/http_c.cpp b/src/core/hle/service/http/http_c.cpp index dd14af66a..d73175eca 100644 --- a/src/core/hle/service/http/http_c.cpp +++ b/src/core/hle/service/http/http_c.cpp @@ -47,7 +47,7 @@ static void CloseContext(Service::Interface* self) { ContextHandle handle = static_cast(cmd_buff[1]); auto map_it = context_map.find(handle); if (map_it == context_map.end()) { - cmd_buff[1] = -1; // TODO: Find proper result code for invalid handle + cmd_buff[1] = 0xD8E007F7; return; } @@ -67,7 +67,7 @@ static void CancelConnection(Service::Interface* self) { auto map_it = context_map.find(handle); if (map_it == context_map.end()) { - cmd_buff[1] = -1; // TODO: Find proper result code for invalid handle + cmd_buff[1] = 0xD8E007F7; return; } map_it->second->cancel_request = true; @@ -82,7 +82,7 @@ static void GetRequestState(Service::Interface* self) { auto map_it = context_map.find(handle); if (map_it == context_map.end()) { - cmd_buff[1] = -1; // TODO: Find proper result code for invalid handle + cmd_buff[1] = 0xD8E007F7; return; } @@ -99,15 +99,13 @@ static void GetDownloadSizeState(Service::Interface* self) { auto map_it = context_map.find(handle); if (map_it == context_map.end()) { - cmd_buff[1] = -1; // TODO: Find proper result code for invalid handle + cmd_buff[1] = 0xD8E007F7; return; } HttpContext* response = map_it->second.get(); std::lock_guard lock(response->mutex); - // TODO: Request not done yet - cmd_buff[1] = RESULT_SUCCESS.raw; cmd_buff[2] = (u32) response->downloaded_size; // TODO: invalid content-length? @@ -121,12 +119,13 @@ static void BeginRequest(Service::Interface* self) { auto map_it = context_map.find(handle); if (map_it == context_map.end()) { - cmd_buff[1] = -1; // TODO: Find proper result code for invalid handle + cmd_buff[1] = 0xD8E007F7; return; } HttpContext* context = map_it->second.get(); std::lock_guard lock(context->mutex); + context->req_thread = Common::make_unique(MakeRequest, context); context->state = REQUEST_STATE_IN_PROGRESS; @@ -142,14 +141,14 @@ static void ReceiveData(Service::Interface* self) { auto map_it = context_map.find(handle); if (map_it == context_map.end()) { - cmd_buff[1] = -1; // TODO: Find proper result code for invalid handle + cmd_buff[1] = 0xD8E007F7; return; } std::lock_guard lock(map_it->second->mutex); const std::vector& data = map_it->second->response_data; if (buf_size < data.size()) { - cmd_buff[1] = 0xd840a02b; + cmd_buff[1] = 0xD840A02B; return; } @@ -164,21 +163,25 @@ static void AddRequestHeader(Service::Interface* self) { u32 hdr_name_len = cmd_buff[2]; u32 hdr_val_len = cmd_buff[3]; char* hdr_name_buf = reinterpret_cast(Memory::GetPointer(cmd_buff[5])); - char* hdr_val_buf = reinterpret_cast(Memory::GetPointer(cmd_buff[7])); + char* hdr_val_buf = reinterpret_cast(Memory::GetPointer(cmd_buff[7])); - // TODO: something is NULL - // TODO: header value is empty - // TODO: header name is empty + std::string hdr_name = std::string(hdr_name_buf, hdr_name_len); + std::string hdr_val = std::string(hdr_val_buf, hdr_val_len); + + if (hdr_name.empty()) { + cmd_buff[1] = 0xD8E0A002; + return; + } auto map_it = context_map.find(handle); if (map_it == context_map.end()) { - cmd_buff[1] = -1; // TODO: Find proper result code for invalid handle + cmd_buff[1] = 0xD8E007F7; return; } std::lock_guard lock(map_it->second->mutex); - AddRequestHeader(std::string(hdr_name_buf, hdr_name_len).c_str(), - std::string(hdr_val_buf, hdr_val_len).c_str(), + AddRequestHeader(hdr_name.c_str(), + hdr_val.c_str(), &map_it->second->request_hdrs); cmd_buff[1] = RESULT_SUCCESS.raw; } @@ -190,7 +193,7 @@ static void GetResponseStatusCode(Service::Interface* self) { auto map_it = context_map.find(handle); if (map_it == context_map.end()) { - cmd_buff[1] = -1; // TODO: Find proper result code for invalid handle + cmd_buff[1] = 0xD8E007F7; return; }