Skip to content

Commit

Permalink
Merge pull request #13095 from unknownbrackets/downloads
Browse files Browse the repository at this point in the history
http: Check cancel flag more often
  • Loading branch information
hrydgard committed Jul 5, 2020
2 parents ef250e3 + 4d47715 commit f2ca7b7
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 22 deletions.
31 changes: 24 additions & 7 deletions ext/native/base/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,22 @@ bool Buffer::FlushToFile(const char *filename) {
return true;
}

bool Buffer::FlushSocket(uintptr_t sock, double timeout) {
bool Buffer::FlushSocket(uintptr_t sock, double timeout, bool *cancelled) {
static constexpr float CANCEL_INTERVAL = 0.25f;
for (size_t pos = 0, end = data_.size(); pos < end; ) {
if (timeout >= 0.0 && !fd_util::WaitUntilReady(sock, timeout, true)) {
ELOG("FlushSocket timed out");
return false;
bool ready = false;
double leftTimeout = timeout;
while (!ready && (leftTimeout >= 0 || cancelled)) {
if (cancelled && *cancelled)
return false;
ready = fd_util::WaitUntilReady(sock, CANCEL_INTERVAL, true);
if (!ready && leftTimeout >= 0.0) {
leftTimeout -= CANCEL_INTERVAL;
if (leftTimeout < 0) {
ELOG("FlushSocket timed out");
return false;
}
}
}
int sent = send(sock, &data_[pos], (int)(end - pos), MSG_NOSIGNAL);
if (sent < 0) {
Expand Down Expand Up @@ -199,6 +210,7 @@ bool Buffer::ReadAll(int fd, int hintSize) {
}

bool Buffer::ReadAllWithProgress(int fd, int knownSize, float *progress, bool *cancelled) {
static constexpr float CANCEL_INTERVAL = 0.25f;
std::vector<char> buf;
if (knownSize >= 65536 * 16) {
buf.resize(65536);
Expand All @@ -210,8 +222,12 @@ bool Buffer::ReadAllWithProgress(int fd, int knownSize, float *progress, bool *c

int total = 0;
while (true) {
if (cancelled && *cancelled)
return false;
bool ready = false;
while (!ready && cancelled) {
if (*cancelled)
return false;
ready = fd_util::WaitUntilReady(fd, CANCEL_INTERVAL, false);
}
int retval = recv(fd, &buf[0], (int)buf.size(), 0);
if (retval == 0) {
return true;
Expand All @@ -222,7 +238,8 @@ bool Buffer::ReadAllWithProgress(int fd, int knownSize, float *progress, bool *c
char *p = Append((size_t)retval);
memcpy(p, &buf[0], retval);
total += retval;
*progress = (float)total / (float)knownSize;
if (progress)
*progress = (float)total / (float)knownSize;
}
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/native/base/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class Buffer {
// written.
bool Flush(int fd);
bool FlushToFile(const char *filename);
bool FlushSocket(uintptr_t sock, double timeout = -1.0); // Windows portability
bool FlushSocket(uintptr_t sock, double timeout = -1.0, bool *cancelled = nullptr); // Windows portability

bool ReadAll(int fd, int hintSize = 0);
bool ReadAllWithProgress(int fd, int knownSize, float *progress, bool *cancelled);
Expand Down
34 changes: 23 additions & 11 deletions ext/native/net/http_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,13 @@ int Client::GET(const char *resource, Buffer *output, std::vector<std::string> &
const char *otherHeaders =
"Accept: */*\r\n"
"Accept-Encoding: gzip\r\n";
int err = SendRequest("GET", resource, otherHeaders, progress);
int err = SendRequest("GET", resource, otherHeaders, progress, cancelled);
if (err < 0) {
return err;
}

Buffer readbuf;
int code = ReadResponseHeaders(&readbuf, responseHeaders, progress);
int code = ReadResponseHeaders(&readbuf, responseHeaders, progress, cancelled);
if (code < 0) {
return code;
}
Expand Down Expand Up @@ -283,11 +283,11 @@ int Client::POST(const char *resource, const std::string &data, Buffer *output,
return POST(resource, data, "", output, progress);
}

int Client::SendRequest(const char *method, const char *resource, const char *otherHeaders, float *progress) {
return SendRequestWithData(method, resource, "", otherHeaders, progress);
int Client::SendRequest(const char *method, const char *resource, const char *otherHeaders, float *progress, bool *cancelled) {
return SendRequestWithData(method, resource, "", otherHeaders, progress, cancelled);
}

int Client::SendRequestWithData(const char *method, const char *resource, const std::string &data, const char *otherHeaders, float *progress) {
int Client::SendRequestWithData(const char *method, const char *resource, const std::string &data, const char *otherHeaders, float *progress, bool *cancelled) {
if (progress) {
*progress = 0.01f;
}
Expand All @@ -314,12 +314,24 @@ int Client::SendRequestWithData(const char *method, const char *resource, const
return 0;
}

int Client::ReadResponseHeaders(Buffer *readbuf, std::vector<std::string> &responseHeaders, float *progress) {
int Client::ReadResponseHeaders(Buffer *readbuf, std::vector<std::string> &responseHeaders, float *progress, bool *cancelled) {
// Snarf all the data we can into RAM. A little unsafe but hey.
if (dataTimeout_ >= 0.0 && !fd_util::WaitUntilReady(sock(), dataTimeout_, false)) {
ELOG("HTTP headers timed out");
return -1;
}
static constexpr float CANCEL_INTERVAL = 0.25f;
bool ready = false;
double leftTimeout = dataTimeout_;
while (!ready) {
if (cancelled && *cancelled)
return -1;
ready = fd_util::WaitUntilReady(sock(), CANCEL_INTERVAL, false);
if (!ready && leftTimeout >= 0.0) {
leftTimeout -= CANCEL_INTERVAL;
if (leftTimeout < 0) {
ELOG("HTTP headers timed out");
return -1;
}
}
};
// Let's hope all the headers are available in a single packet...
if (readbuf->Read(sock(), 4096) < 0) {
ELOG("Failed to read HTTP headers :(");
return -1;
Expand Down Expand Up @@ -396,7 +408,7 @@ int Client::ReadResponseEntity(Buffer *readbuf, const std::vector<std::string> &

if (!contentLength || !progress) {
// No way to know how far along we are. Let's just not update the progress counter.
if (!readbuf->ReadAll(sock(), contentLength))
if (!readbuf->ReadAllWithProgress(sock(), contentLength, nullptr, cancelled))
return -1;
} else {
// Let's read in chunks, updating progress between each.
Expand Down
6 changes: 3 additions & 3 deletions ext/native/net/http_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ class Client : public net::Connection {

// HEAD, PUT, DELETE aren't implemented yet, but can be done with SendRequest.

int SendRequest(const char *method, const char *resource, const char *otherHeaders = nullptr, float *progress = nullptr);
int SendRequestWithData(const char *method, const char *resource, const std::string &data, const char *otherHeaders = nullptr, float *progress = nullptr);
int ReadResponseHeaders(Buffer *readbuf, std::vector<std::string> &responseHeaders, float *progress = nullptr);
int SendRequest(const char *method, const char *resource, const char *otherHeaders = nullptr, float *progress = nullptr, bool *cancelled = nullptr);
int SendRequestWithData(const char *method, const char *resource, const std::string &data, const char *otherHeaders = nullptr, float *progress = nullptr, bool *cancelled = nullptr);
int ReadResponseHeaders(Buffer *readbuf, std::vector<std::string> &responseHeaders, float *progress = nullptr, bool *cancelled = nullptr);
// If your response contains a response, you must read it.
int ReadResponseEntity(Buffer *readbuf, const std::vector<std::string> &responseHeaders, Buffer *output, float *progress = nullptr, bool *cancelled = nullptr);

Expand Down

0 comments on commit f2ca7b7

Please sign in to comment.