@@ -187,13 +187,13 @@ void HttpThread()
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
}
curl_easy_setopt(curl, CURLOPT_URL, request->uri.c_str());
/* Setup our (C-style) callback function which we pipe back into the callback. */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, +[](char *ptr, size_t size, size_t nmemb, void *userdata) -> size_t {
Debug(net, 4, "HTTP callback: {} bytes", size * nmemb);
Debug(net, 6, "HTTP callback: {} bytes", size * nmemb);
HTTPThreadSafeCallback *callback = static_cast<HTTPThreadSafeCallback *>(userdata);
/* Copy the buffer out of CURL. OnReceiveData() will free it when done. */
std::unique_ptr<char[]> buffer = std::make_unique<char[]>(size * nmemb);
memcpy(buffer.get(), ptr, size * nmemb);
callback->OnReceiveData(std::move(buffer), size * nmemb);
@@ -162,13 +162,13 @@ void NetworkHTTPRequest::WinHttpCallback
* The buffer will be free'd by OnReceiveData() in the next step. */
char *buffer = size == 0 ? nullptr : new char[size];
WinHttpReadData(this->request, buffer, size, 0);
} break;
case WINHTTP_CALLBACK_STATUS_READ_COMPLETE:
Debug(net, 4, "HTTP callback: {} bytes", length);
Debug(net, 6, "HTTP callback: {} bytes", length);
this->callback.OnReceiveData(std::unique_ptr<char[]>(static_cast<char *>(info)), length);
if (length == 0) {
/* Next step: no more data available: request is finished. */
this->finished = true;
@@ -608,14 +608,12 @@ void ClientNetworkContentSocketHandler::
/* Ignore any latent data coming from a connection we closed. */
if (this->http_response_index == -2) {
return;
this->lastActivity = std::chrono::steady_clock::now();
if (this->http_response_index == -1) {
if (data != nullptr) {
/* Append the rest of the response. */
this->http_response.insert(this->http_response.end(), data.get(), data.get() + length);
} else {
@@ -796,31 +794,40 @@ void ClientNetworkContentSocketHandler::
/**
* Disconnect from the content server.
*/
NetworkRecvStatus ClientNetworkContentSocketHandler::CloseConnection(bool)
{
this->isCancelled = true;
NetworkContentSocketHandler::CloseConnection();
if (this->sock == INVALID_SOCKET) return NETWORK_RECV_STATUS_OKAY;
this->CloseSocket();
this->OnDisconnect();
return NETWORK_RECV_STATUS_OKAY;
* Cancel the current download.
void ClientNetworkContentSocketHandler::Cancel(void)
this->CloseConnection();
* Check whether we received/can send some data from/to the content server and
* when that's the case handle it appropriately
void ClientNetworkContentSocketHandler::SendReceive()
if (this->sock == INVALID_SOCKET || this->isConnecting) return;
/* Close the connection to the content server after inactivity; there can still be downloads pending via HTTP. */
if (std::chrono::steady_clock::now() > this->lastActivity + IDLE_TIMEOUT) {
if (this->CanSendReceive()) {
@@ -110,12 +110,13 @@ public:
ClientNetworkContentSocketHandler();
~ClientNetworkContentSocketHandler();
void Connect();
void SendReceive();
NetworkRecvStatus CloseConnection(bool error = true) override;
void Cancel();
void RequestContentList(ContentType type);
void RequestContentList(uint count, const ContentID *content_ids);
void RequestContentList(ContentVector *cv, bool send_md5sum = true);
void DownloadSelectedContent(uint &files, uint &bytes, bool fallback = false);
@@ -288,13 +288,13 @@ public:
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
if (widget == WID_NCDS_CANCELOK) {
if (this->downloaded_bytes != this->total_bytes) {
_network_content_client.CloseConnection();
_network_content_client.Cancel();
this->Close();
/* If downloading succeeded, close the online content window. This will close
* the current window as well. */
CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST);
Status change: