From dfd68306de6f655a7bd2c68cea0b9299956ce8fc Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 14 Jul 2016 10:17:26 +0600 Subject: CLOUD: Upgrade FolderDownloadRequest::getProgress() Now NetworkReadStream, which is used in DownloadRequest, which is used in FolderDownloadRequest, returns progress information provided by libcurl. --- backends/networking/curl/networkreadstream.cpp | 26 +++++++++++++++++++++++++- backends/networking/curl/networkreadstream.h | 7 +++++++ 2 files changed, 32 insertions(+), 1 deletion(-) (limited to 'backends/networking') diff --git a/backends/networking/curl/networkreadstream.cpp b/backends/networking/curl/networkreadstream.cpp index 41839f79c9..9b34aaa3d5 100644 --- a/backends/networking/curl/networkreadstream.cpp +++ b/backends/networking/curl/networkreadstream.cpp @@ -47,10 +47,17 @@ static size_t curlHeadersCallback(char *d, size_t n, size_t l, void *p) { return 0; } +static int curlProgressCallback(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { + NetworkReadStream *stream = (NetworkReadStream *)p; + if (stream) stream->setProgress(dlnow, dltotal); + return 0; +} + void NetworkReadStream::init(const char *url, curl_slist *headersList, const byte *buffer, uint32 bufferSize, bool uploading, bool usingPatch, bool post) { _eos = _requestComplete = false; _sendingContentsBuffer = nullptr; _sendingContentsSize = _sendingContentsPos = 0; + _progressDownloaded = _progressTotal = 0; _easy = curl_easy_init(); curl_easy_setopt(_easy, CURLOPT_WRITEFUNCTION, curlDataCallback); @@ -62,7 +69,10 @@ void NetworkReadStream::init(const char *url, curl_slist *headersList, const byt curl_easy_setopt(_easy, CURLOPT_URL, url); curl_easy_setopt(_easy, CURLOPT_VERBOSE, 0L); curl_easy_setopt(_easy, CURLOPT_FOLLOWLOCATION, 1L); //probably it's OK to have it always on - curl_easy_setopt(_easy, CURLOPT_HTTPHEADER, headersList); + curl_easy_setopt(_easy, CURLOPT_HTTPHEADER, headersList); + curl_easy_setopt(_easy, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(_easy, CURLOPT_XFERINFOFUNCTION, curlProgressCallback); + curl_easy_setopt(_easy, CURLOPT_XFERINFODATA, this); if (uploading) { curl_easy_setopt(_easy, CURLOPT_UPLOAD, 1L); curl_easy_setopt(_easy, CURLOPT_READDATA, this); @@ -84,6 +94,7 @@ void NetworkReadStream::init(const char *url, curl_slist *headersList, Common::H _eos = _requestComplete = false; _sendingContentsBuffer = nullptr; _sendingContentsSize = _sendingContentsPos = 0; + _progressDownloaded = _progressTotal = 0; _easy = curl_easy_init(); curl_easy_setopt(_easy, CURLOPT_WRITEFUNCTION, curlDataCallback); @@ -96,6 +107,9 @@ void NetworkReadStream::init(const char *url, curl_slist *headersList, Common::H curl_easy_setopt(_easy, CURLOPT_VERBOSE, 0L); curl_easy_setopt(_easy, CURLOPT_FOLLOWLOCATION, 1L); //probably it's OK to have it always on curl_easy_setopt(_easy, CURLOPT_HTTPHEADER, headersList); + curl_easy_setopt(_easy, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(_easy, CURLOPT_XFERINFOFUNCTION, curlProgressCallback); + curl_easy_setopt(_easy, CURLOPT_XFERINFODATA, this); // set POST multipart upload form fields/files struct curl_httppost *formpost = NULL; @@ -201,4 +215,14 @@ uint32 NetworkReadStream::addResponseHeaders(char *buffer, uint32 size) { return size; } +double NetworkReadStream::getProgress() const { + if (_progressTotal < 1) return 0; + return (double)_progressDownloaded / (double)_progressTotal; +} + +void NetworkReadStream::setProgress(uint64 downloaded, uint64 total) { + _progressDownloaded = downloaded; + _progressTotal = total; +} + } // End of namespace Cloud diff --git a/backends/networking/curl/networkreadstream.h b/backends/networking/curl/networkreadstream.h index acd8eee1c9..a3221011ec 100644 --- a/backends/networking/curl/networkreadstream.h +++ b/backends/networking/curl/networkreadstream.h @@ -41,6 +41,7 @@ class NetworkReadStream: public Common::MemoryReadWriteStream { uint32 _sendingContentsSize; uint32 _sendingContentsPos; Common::String _responseHeaders; + uint64 _progressDownloaded, _progressTotal; void init(const char *url, curl_slist *headersList, const byte *buffer, uint32 bufferSize, bool uploading, bool usingPatch, bool post); void init(const char *url, curl_slist *headersList, Common::HashMap formFields, Common::HashMap formFiles); @@ -128,6 +129,12 @@ public: * @returns how many bytes were actually read */ uint32 addResponseHeaders(char *buffer, uint32 size); + + /** Returns a number in range [0, 1], where 1 is "complete". */ + double getProgress() const; + + /** Used in curl progress callback to pass current downloaded/total values. */ + void setProgress(uint64 downloaded, uint64 total); }; } // End of namespace Networking -- cgit v1.2.3