Skip to content
Snippets Groups Projects
Commit 169fe36f authored by Andrew A. de Laix's avatar Andrew A. de Laix
Browse files
parents a13acfc9 02c362b8
No related branches found
No related tags found
No related merge requests found
...@@ -46,11 +46,12 @@ class LLUpdateDownloader::Implementation: ...@@ -46,11 +46,12 @@ class LLUpdateDownloader::Implementation:
void cancel(void); void cancel(void);
void download(LLURI const & uri, std::string const & hash); void download(LLURI const & uri, std::string const & hash);
bool isDownloading(void); bool isDownloading(void);
void onHeader(void * header, size_t size); size_t onHeader(void * header, size_t size);
void onBody(void * header, size_t size); size_t onBody(void * header, size_t size);
void resume(void); void resume(void);
private: private:
bool mCancelled;
LLUpdateDownloader::Client & mClient; LLUpdateDownloader::Client & mClient;
CURL * mCurl; CURL * mCurl;
LLSD mDownloadData; LLSD mDownloadData;
...@@ -137,22 +138,21 @@ namespace { ...@@ -137,22 +138,21 @@ namespace {
size_t write_function(void * data, size_t blockSize, size_t blocks, void * downloader) size_t write_function(void * data, size_t blockSize, size_t blocks, void * downloader)
{ {
size_t bytes = blockSize * blocks; size_t bytes = blockSize * blocks;
reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onBody(data, bytes); return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onBody(data, bytes);
return bytes;
} }
size_t header_function(void * data, size_t blockSize, size_t blocks, void * downloader) size_t header_function(void * data, size_t blockSize, size_t blocks, void * downloader)
{ {
size_t bytes = blockSize * blocks; size_t bytes = blockSize * blocks;
reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onHeader(data, bytes); return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onHeader(data, bytes);
return bytes;
} }
} }
LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client): LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client):
LLThread("LLUpdateDownloader"), LLThread("LLUpdateDownloader"),
mCancelled(false),
mClient(client), mClient(client),
mCurl(0), mCurl(0),
mDownloadRecordPath(LLUpdateDownloader::downloadMarkerPath()) mDownloadRecordPath(LLUpdateDownloader::downloadMarkerPath())
...@@ -170,7 +170,7 @@ LLUpdateDownloader::Implementation::~Implementation() ...@@ -170,7 +170,7 @@ LLUpdateDownloader::Implementation::~Implementation()
void LLUpdateDownloader::Implementation::cancel(void) void LLUpdateDownloader::Implementation::cancel(void)
{ {
llassert(!"not implemented"); mCancelled = true;
} }
...@@ -230,12 +230,12 @@ void LLUpdateDownloader::Implementation::resume(void) ...@@ -230,12 +230,12 @@ void LLUpdateDownloader::Implementation::resume(void)
} }
void LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size)
{ {
char const * headerPtr = reinterpret_cast<const char *> (buffer); char const * headerPtr = reinterpret_cast<const char *> (buffer);
std::string header(headerPtr, headerPtr + size); std::string header(headerPtr, headerPtr + size);
size_t colonPosition = header.find(':'); size_t colonPosition = header.find(':');
if(colonPosition == std::string::npos) return; // HTML response; ignore. if(colonPosition == std::string::npos) return size; // HTML response; ignore.
if(header.substr(0, colonPosition) == "Content-Length") { if(header.substr(0, colonPosition) == "Content-Length") {
try { try {
...@@ -255,20 +255,25 @@ void LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) ...@@ -255,20 +255,25 @@ void LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size)
} else { } else {
; // No op. ; // No op.
} }
return size;
} }
void LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size) size_t LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size)
{ {
if(mCancelled) return 0; // Forces a write error which will halt curl thread.
mDownloadStream.write(reinterpret_cast<const char *>(buffer), size); mDownloadStream.write(reinterpret_cast<const char *>(buffer), size);
return size;
} }
void LLUpdateDownloader::Implementation::run(void) void LLUpdateDownloader::Implementation::run(void)
{ {
CURLcode code = curl_easy_perform(mCurl); CURLcode code = curl_easy_perform(mCurl);
LLFile::remove(mDownloadRecordPath);
if(code == CURLE_OK) { if(code == CURLE_OK) {
LLFile::remove(mDownloadRecordPath);
if(validateDownload()) { if(validateDownload()) {
LL_INFOS("UpdateDownload") << "download successful" << LL_ENDL; LL_INFOS("UpdateDownload") << "download successful" << LL_ENDL;
mClient.downloadComplete(mDownloadData); mClient.downloadComplete(mDownloadData);
...@@ -278,9 +283,13 @@ void LLUpdateDownloader::Implementation::run(void) ...@@ -278,9 +283,13 @@ void LLUpdateDownloader::Implementation::run(void)
if(filePath.size() != 0) LLFile::remove(filePath); if(filePath.size() != 0) LLFile::remove(filePath);
mClient.downloadError("failed hash check"); mClient.downloadError("failed hash check");
} }
} else if(mCancelled && (code == CURLE_WRITE_ERROR)) {
LL_INFOS("UpdateDownload") << "download canceled by user" << LL_ENDL;
// Do not call back client.
} else { } else {
LL_WARNS("UpdateDownload") << "download failed with error '" << LL_WARNS("UpdateDownload") << "download failed with error '" <<
curl_easy_strerror(code) << "'" << LL_ENDL; curl_easy_strerror(code) << "'" << LL_ENDL;
LLFile::remove(mDownloadRecordPath);
mClient.downloadError("curl error"); mClient.downloadError("curl error");
} }
} }
...@@ -378,6 +387,10 @@ bool LLUpdateDownloader::Implementation::validateDownload(void) ...@@ -378,6 +387,10 @@ bool LLUpdateDownloader::Implementation::validateDownload(void)
LL_INFOS("UpdateDownload") << "checking hash..." << LL_ENDL; LL_INFOS("UpdateDownload") << "checking hash..." << LL_ENDL;
char digest[33]; char digest[33];
LLMD5(fileStream).hex_digest(digest); LLMD5(fileStream).hex_digest(digest);
if(hash != digest) {
LL_WARNS("UpdateDownload") << "download hash mismatch; expeted " << hash <<
" but download is " << digest << LL_ENDL;
}
return hash == digest; return hash == digest;
} else { } else {
return true; // No hash check provided. return true; // No hash check provided.
......
...@@ -47,7 +47,8 @@ class LLUpdateDownloader ...@@ -47,7 +47,8 @@ class LLUpdateDownloader
LLUpdateDownloader(Client & client); LLUpdateDownloader(Client & client);
// Cancel any in progress download; a no op if none is in progress. // Cancel any in progress download; a no op if none is in progress. The
// client will not receive a complete or error callback.
void cancel(void); void cancel(void);
// Start a new download. // Start a new download.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment