From be151807222ffa5972256aa9a392e8a319eae5ee Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 2 Nov 2010 15:59:10 -0700 Subject: start of the downloader service. --- .../updater/llupdatedownloader.cpp | 168 +++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 indra/viewer_components/updater/llupdatedownloader.cpp (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp new file mode 100644 index 0000000000..4adf9c42b1 --- /dev/null +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -0,0 +1,168 @@ +/** + * @file llupdatedownloader.cpp + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "lldir.h" +#include "llfile.h" +#include "llsd.h" +#include "llsdserialize.h" +#include "llthread.h" +#include "llupdatedownloader.h" + + +class LLUpdateDownloader::Implementation: + public LLThread +{ +public: + Implementation(LLUpdateDownloader::Client & client); + void cancel(void); + void download(LLURI const & uri); + bool isDownloading(void); + +private: + static const char * sSecondLifeUpdateRecord; + + LLUpdateDownloader::Client & mClient; + std::string mDownloadRecordPath; + + void resumeDownloading(LLSD const & downloadData); + void run(void); + bool shouldResumeOngoingDownload(LLURI const & uri, LLSD & downloadData); + void startDownloading(LLURI const & uri); +}; + + + +// LLUpdateDownloader +//----------------------------------------------------------------------------- + + +LLUpdateDownloader::LLUpdateDownloader(Client & client): + mImplementation(new LLUpdateDownloader::Implementation(client)) +{ + ; // No op. +} + + +void LLUpdateDownloader::cancel(void) +{ + mImplementation->cancel(); +} + + +void LLUpdateDownloader::download(LLURI const & uri) +{ + mImplementation->download(uri); +} + + +bool LLUpdateDownloader::isDownloading(void) +{ + return mImplementation->isDownloading(); +} + + + +// LLUpdateDownloader::Implementation +//----------------------------------------------------------------------------- + + +const char * LLUpdateDownloader::Implementation::sSecondLifeUpdateRecord = + "SecondLifeUpdateDownload.xml"; + + +LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client): + LLThread("LLUpdateDownloader"), + mClient(client), + mDownloadRecordPath(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, sSecondLifeUpdateRecord)) +{ + ; // No op. +} + + +void LLUpdateDownloader::Implementation::cancel(void) +{ +} + + +void LLUpdateDownloader::Implementation::download(LLURI const & uri) +{ + LLSD downloadData; + if(shouldResumeOngoingDownload(uri, downloadData)){ + + } else { + + } +} + + +bool LLUpdateDownloader::Implementation::isDownloading(void) +{ + return false; +} + + +void resumeDownloading(LLSD const & downloadData) +{ +} + + +bool LLUpdateDownloader::Implementation::shouldResumeOngoingDownload(LLURI const & uri, LLSD & downloadData) +{ + if(!LLFile::isfile(mDownloadRecordPath)) return false; + + llifstream dataStream(mDownloadRecordPath); + LLSDSerialize parser; + parser.fromXMLDocument(downloadData, dataStream); + + if(downloadData["url"].asString() != uri.asString()) return false; + + std::string downloadedFilePath = downloadData["path"].asString(); + if(LLFile::isfile(downloadedFilePath)) { + llstat fileStatus; + LLFile::stat(downloadedFilePath, &fileStatus); + downloadData["bytes_downloaded"] = LLSD(LLSD::Integer(fileStatus.st_size)); + return true; + } else { + return false; + } + + return true; +} + + +void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri) +{ + LLSD downloadData; + downloadData["url"] = uri.asString(); + LLSD path = uri.pathArray(); + std::string fileName = path[path.size() - 1].asString(); + std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName); + llofstream dataStream(mDownloadRecordPath); + LLSDSerialize parser; + parser.toPrettyXML(downloadData, dataStream); + + llofstream downloadStream(filePath); +} -- cgit v1.2.3 From 7622ab9249506539894d0e33d4c2a8fd9fb3e3ac Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Thu, 4 Nov 2010 11:33:02 -0700 Subject: just barely working udate downloading service; missing little nicities like error checking and sill stuff like that. --- .../updater/llupdatedownloader.cpp | 128 +++++++++++++++++++-- 1 file changed, 120 insertions(+), 8 deletions(-) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 4adf9c42b1..21e4ce94cc 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -24,6 +24,8 @@ */ #include "linden_common.h" +#include +#include #include "lldir.h" #include "llfile.h" #include "llsd.h" @@ -37,20 +39,27 @@ class LLUpdateDownloader::Implementation: { public: Implementation(LLUpdateDownloader::Client & client); + ~Implementation(); void cancel(void); void download(LLURI const & uri); bool isDownloading(void); - + void onHeader(void * header, size_t size); + void onBody(void * header, size_t size); private: static const char * sSecondLifeUpdateRecord; LLUpdateDownloader::Client & mClient; + CURL * mCurl; + llofstream mDownloadStream; std::string mDownloadRecordPath; + void initializeCurlGet(std::string const & url); void resumeDownloading(LLSD const & downloadData); void run(void); bool shouldResumeOngoingDownload(LLURI const & uri, LLSD & downloadData); void startDownloading(LLURI const & uri); + + LOG_CLASS(LLUpdateDownloader::Implementation); }; @@ -89,6 +98,23 @@ bool LLUpdateDownloader::isDownloading(void) //----------------------------------------------------------------------------- +namespace { + size_t write_function(void * data, size_t blockSize, size_t blocks, void * downloader) + { + size_t bytes = blockSize * blocks; + reinterpret_cast(downloader)->onBody(data, bytes); + return bytes; + } + + size_t header_function(void * data, size_t blockSize, size_t blocks, void * downloader) + { + size_t bytes = blockSize * blocks; + reinterpret_cast(downloader)->onHeader(data, bytes); + return bytes; + } +} + + const char * LLUpdateDownloader::Implementation::sSecondLifeUpdateRecord = "SecondLifeUpdateDownload.xml"; @@ -96,35 +122,116 @@ const char * LLUpdateDownloader::Implementation::sSecondLifeUpdateRecord = LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client): LLThread("LLUpdateDownloader"), mClient(client), + mCurl(0), mDownloadRecordPath(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, sSecondLifeUpdateRecord)) { - ; // No op. + CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case. + llassert(code = CURLE_OK); // TODO: real error handling here. } -void LLUpdateDownloader::Implementation::cancel(void) +LLUpdateDownloader::Implementation::~Implementation() { + if(mCurl) curl_easy_cleanup(mCurl); } +void LLUpdateDownloader::Implementation::cancel(void) +{ + llassert(!"not implemented"); +} + + void LLUpdateDownloader::Implementation::download(LLURI const & uri) { LLSD downloadData; if(shouldResumeOngoingDownload(uri, downloadData)){ - + startDownloading(uri); // TODO: Implement resume. } else { - + startDownloading(uri); } } bool LLUpdateDownloader::Implementation::isDownloading(void) { - return false; + return !isStopped(); +} + +void LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) +{ + char const * headerPtr = reinterpret_cast (buffer); + std::string header(headerPtr, headerPtr + size); + size_t colonPosition = header.find(':'); + if(colonPosition == std::string::npos) return; // HTML response; ignore. + + if(header.substr(0, colonPosition) == "Content-Length") { + try { + size_t firstDigitPos = header.find_first_of("0123456789", colonPosition); + size_t lastDigitPos = header.find_last_of("0123456789"); + std::string contentLength = header.substr(firstDigitPos, lastDigitPos - firstDigitPos + 1); + size_t size = boost::lexical_cast(contentLength); + LL_INFOS("UpdateDownload") << "download size is " << size << LL_ENDL; + + LLSD downloadData; + llifstream idataStream(mDownloadRecordPath); + LLSDSerialize parser; + parser.fromXMLDocument(downloadData, idataStream); + idataStream.close(); + downloadData["size"] = LLSD(LLSD::Integer(size)); + llofstream odataStream(mDownloadRecordPath); + parser.toPrettyXML(downloadData, odataStream); + } catch (std::exception const & e) { + LL_WARNS("UpdateDownload") << "unable to read content length (" + << e.what() << ")" << LL_ENDL; + } + } else { + ; // No op. + } +} + + +void LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size) +{ + mDownloadStream.write(reinterpret_cast(buffer), size); +} + + +void LLUpdateDownloader::Implementation::run(void) +{ + CURLcode code = curl_easy_perform(mCurl); + if(code == CURLE_OK) { + LL_INFOS("UpdateDownload") << "download successful" << LL_ENDL; + mClient.downloadComplete(); + } else { + LL_WARNS("UpdateDownload") << "download failed with error " << code << LL_ENDL; + mClient.downloadError("curl error"); + } +} + + +void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url) +{ + if(mCurl == 0) { + mCurl = curl_easy_init(); + } else { + curl_easy_reset(mCurl); + } + + llassert(mCurl != 0); // TODO: real error handling here. + + CURLcode code; + code = curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true); + code = curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function); + code = curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, this); + code = curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, &header_function); + code = curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, this); + code = curl_easy_setopt(mCurl, CURLOPT_HTTPGET, true); + code = curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str()); } -void resumeDownloading(LLSD const & downloadData) +void LLUpdateDownloader::Implementation::resumeDownloading(LLSD const & downloadData) { } @@ -160,9 +267,14 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri) LLSD path = uri.pathArray(); std::string fileName = path[path.size() - 1].asString(); std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName); + LL_INFOS("UpdateDownload") << "downloading " << filePath << LL_ENDL; + LL_INFOS("UpdateDownload") << "from " << uri.asString() << LL_ENDL; + downloadData["path"] = filePath; llofstream dataStream(mDownloadRecordPath); LLSDSerialize parser; parser.toPrettyXML(downloadData, dataStream); - llofstream downloadStream(filePath); + mDownloadStream.open(filePath, std::ios_base::out | std::ios_base::binary); + initializeCurlGet(uri.asString()); + start(); } -- cgit v1.2.3 From dfeb7abe5f690bbd3a908c84c53bbea20a5adb7c Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Thu, 4 Nov 2010 14:08:14 -0700 Subject: checker working with v1.0 update protocol. --- indra/viewer_components/updater/llupdatedownloader.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 21e4ce94cc..087d79f804 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -222,6 +222,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u CURLcode code; code = curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true); + code = curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true); code = curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function); code = curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, this); code = curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, &header_function); -- cgit v1.2.3 From 191e164a503b72c7feae0a46ad0422740b365556 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Thu, 4 Nov 2010 15:49:19 -0700 Subject: some better error handling. --- .../updater/llupdatedownloader.cpp | 122 +++++++++++++-------- 1 file changed, 79 insertions(+), 43 deletions(-) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 087d79f804..23772e021e 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -24,6 +24,7 @@ */ #include "linden_common.h" +#include #include #include #include "lldir.h" @@ -41,33 +42,56 @@ public: Implementation(LLUpdateDownloader::Client & client); ~Implementation(); void cancel(void); - void download(LLURI const & uri); + void download(LLURI const & uri, std::string const & hash); bool isDownloading(void); void onHeader(void * header, size_t size); void onBody(void * header, size_t size); private: - static const char * sSecondLifeUpdateRecord; - LLUpdateDownloader::Client & mClient; CURL * mCurl; + LLSD mDownloadData; llofstream mDownloadStream; std::string mDownloadRecordPath; void initializeCurlGet(std::string const & url); void resumeDownloading(LLSD const & downloadData); void run(void); - bool shouldResumeOngoingDownload(LLURI const & uri, LLSD & downloadData); - void startDownloading(LLURI const & uri); + void startDownloading(LLURI const & uri, std::string const & hash); + void throwOnCurlError(CURLcode code); LOG_CLASS(LLUpdateDownloader::Implementation); }; +namespace { + class DownloadError: + public std::runtime_error + { + public: + DownloadError(const char * message): + std::runtime_error(message) + { + ; // No op. + } + }; + + + const char * gSecondLifeUpdateRecord = "SecondLifeUpdateDownload.xml"; +}; + + // LLUpdateDownloader //----------------------------------------------------------------------------- + +std::string LLUpdateDownloader::downloadMarkerPath(void) +{ + return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, gSecondLifeUpdateRecord); +} + + LLUpdateDownloader::LLUpdateDownloader(Client & client): mImplementation(new LLUpdateDownloader::Implementation(client)) { @@ -81,9 +105,9 @@ void LLUpdateDownloader::cancel(void) } -void LLUpdateDownloader::download(LLURI const & uri) +void LLUpdateDownloader::download(LLURI const & uri, std::string const & hash) { - mImplementation->download(uri); + mImplementation->download(uri, hash); } @@ -115,15 +139,11 @@ namespace { } -const char * LLUpdateDownloader::Implementation::sSecondLifeUpdateRecord = - "SecondLifeUpdateDownload.xml"; - - LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client): LLThread("LLUpdateDownloader"), mClient(client), mCurl(0), - mDownloadRecordPath(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, sSecondLifeUpdateRecord)) + mDownloadRecordPath(LLUpdateDownloader::downloadMarkerPath()) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case. llassert(code = CURLE_OK); // TODO: real error handling here. @@ -142,13 +162,15 @@ void LLUpdateDownloader::Implementation::cancel(void) } -void LLUpdateDownloader::Implementation::download(LLURI const & uri) +void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash) { - LLSD downloadData; - if(shouldResumeOngoingDownload(uri, downloadData)){ - startDownloading(uri); // TODO: Implement resume. - } else { - startDownloading(uri); + if(isDownloading()) mClient.downloadError("download in progress"); + + mDownloadData = LLSD(); + try { + startDownloading(uri, hash); + } catch(DownloadError const & e) { + mClient.downloadError(e.what()); } } @@ -173,14 +195,10 @@ void LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) size_t size = boost::lexical_cast(contentLength); LL_INFOS("UpdateDownload") << "download size is " << size << LL_ENDL; - LLSD downloadData; - llifstream idataStream(mDownloadRecordPath); - LLSDSerialize parser; - parser.fromXMLDocument(downloadData, idataStream); - idataStream.close(); - downloadData["size"] = LLSD(LLSD::Integer(size)); + mDownloadData["size"] = LLSD(LLSD::Integer(size)); llofstream odataStream(mDownloadRecordPath); - parser.toPrettyXML(downloadData, odataStream); + LLSDSerialize parser; + parser.toPrettyXML(mDownloadData, odataStream); } catch (std::exception const & e) { LL_WARNS("UpdateDownload") << "unable to read content length (" << e.what() << ")" << LL_ENDL; @@ -218,17 +236,16 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u curl_easy_reset(mCurl); } - llassert(mCurl != 0); // TODO: real error handling here. + if(mCurl == 0) throw DownloadError("failed to initialize curl"); - CURLcode code; - code = curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true); - code = curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true); - code = curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function); - code = curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, this); - code = curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, &header_function); - code = curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, this); - code = curl_easy_setopt(mCurl, CURLOPT_HTTPGET, true); - code = curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str()); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true)); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true)); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function)); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, this)); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, &header_function)); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, this)); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPGET, true)); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str())); } @@ -236,7 +253,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(LLSD const & download { } - +/* bool LLUpdateDownloader::Implementation::shouldResumeOngoingDownload(LLURI const & uri, LLSD & downloadData) { if(!LLFile::isfile(mDownloadRecordPath)) return false; @@ -259,23 +276,42 @@ bool LLUpdateDownloader::Implementation::shouldResumeOngoingDownload(LLURI const return true; } + */ -void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri) +void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std::string const & hash) { - LLSD downloadData; - downloadData["url"] = uri.asString(); + mDownloadData["url"] = uri.asString(); + mDownloadData["hash"] = hash; LLSD path = uri.pathArray(); + if(path.size() == 0) throw DownloadError("no file path"); std::string fileName = path[path.size() - 1].asString(); std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName); - LL_INFOS("UpdateDownload") << "downloading " << filePath << LL_ENDL; - LL_INFOS("UpdateDownload") << "from " << uri.asString() << LL_ENDL; - downloadData["path"] = filePath; + mDownloadData["path"] = filePath; + + LL_INFOS("UpdateDownload") << "downloading " << filePath << "\n" + << "from " << uri.asString() << LL_ENDL; + llofstream dataStream(mDownloadRecordPath); LLSDSerialize parser; - parser.toPrettyXML(downloadData, dataStream); + parser.toPrettyXML(mDownloadData, dataStream); mDownloadStream.open(filePath, std::ios_base::out | std::ios_base::binary); initializeCurlGet(uri.asString()); start(); } + + +void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code) +{ + if(code != CURLE_OK) { + const char * errorString = curl_easy_strerror(code); + if(errorString != 0) { + throw DownloadError(curl_easy_strerror(code)); + } else { + throw DownloadError("unknown curl error"); + } + } else { + ; // No op. + } +} -- cgit v1.2.3 From 4d1e45f20f924f070d0f0139878c2c96e698fb07 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Thu, 4 Nov 2010 17:14:12 -0700 Subject: added hash validation of downloaded file. --- .../updater/llupdatedownloader.cpp | 41 +++++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 23772e021e..59e929d99f 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -29,6 +29,7 @@ #include #include "lldir.h" #include "llfile.h" +#include "llmd5.h" #include "llsd.h" #include "llsdserialize.h" #include "llthread.h" @@ -58,6 +59,7 @@ private: void run(void); void startDownloading(LLURI const & uri, std::string const & hash); void throwOnCurlError(CURLcode code); + bool validateDownload(void); LOG_CLASS(LLUpdateDownloader::Implementation); }; @@ -130,6 +132,7 @@ namespace { return bytes; } + size_t header_function(void * data, size_t blockSize, size_t blocks, void * downloader) { size_t bytes = blockSize * blocks; @@ -219,10 +222,18 @@ void LLUpdateDownloader::Implementation::run(void) { CURLcode code = curl_easy_perform(mCurl); if(code == CURLE_OK) { - LL_INFOS("UpdateDownload") << "download successful" << LL_ENDL; - mClient.downloadComplete(); + if(validateDownload()) { + LL_INFOS("UpdateDownload") << "download successful" << LL_ENDL; + mClient.downloadComplete(); + } else { + LL_INFOS("UpdateDownload") << "download failed hash check" << LL_ENDL; + std::string filePath = mDownloadData["path"].asString(); + if(filePath.size() != 0) LLFile::remove(filePath); + mClient.downloadError("failed hash check"); + } } else { - LL_WARNS("UpdateDownload") << "download failed with error " << code << LL_ENDL; + LL_WARNS("UpdateDownload") << "download failed with error '" << + curl_easy_strerror(code) << "'" << LL_ENDL; mClient.downloadError("curl error"); } } @@ -253,6 +264,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(LLSD const & download { } + /* bool LLUpdateDownloader::Implementation::shouldResumeOngoingDownload(LLURI const & uri, LLSD & downloadData) { @@ -289,8 +301,9 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName); mDownloadData["path"] = filePath; - LL_INFOS("UpdateDownload") << "downloading " << filePath << "\n" - << "from " << uri.asString() << LL_ENDL; + LL_INFOS("UpdateDownload") << "downloading " << filePath + << " from " << uri.asString() << LL_ENDL; + LL_INFOS("UpdateDownload") << "hash of file is " << hash << LL_ENDL; llofstream dataStream(mDownloadRecordPath); LLSDSerialize parser; @@ -315,3 +328,21 @@ void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code) ; // No op. } } + + +bool LLUpdateDownloader::Implementation::validateDownload(void) +{ + std::string filePath = mDownloadData["path"].asString(); + llifstream fileStream(filePath); + if(!fileStream) return false; + + std::string hash = mDownloadData["hash"].asString(); + if(hash.size() != 0) { + LL_INFOS("UpdateDownload") << "checking hash..." << LL_ENDL; + char digest[33]; + LLMD5(fileStream).hex_digest(digest); + return hash == digest; + } else { + return true; // No hash check provided. + } +} -- cgit v1.2.3 From 9d7cdc17e311ba5f1f62112e316c531b68f67046 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Fri, 5 Nov 2010 11:12:54 -0700 Subject: resume feature (untested). --- .../updater/llupdatedownloader.cpp | 104 ++++++++++++++------- 1 file changed, 72 insertions(+), 32 deletions(-) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 59e929d99f..102f2f9eec 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -25,6 +25,7 @@ #include "linden_common.h" #include +#include #include #include #include "lldir.h" @@ -47,6 +48,8 @@ public: bool isDownloading(void); void onHeader(void * header, size_t size); void onBody(void * header, size_t size); + void resume(void); + private: LLUpdateDownloader::Client & mClient; CURL * mCurl; @@ -54,8 +57,8 @@ private: llofstream mDownloadStream; std::string mDownloadRecordPath; - void initializeCurlGet(std::string const & url); - void resumeDownloading(LLSD const & downloadData); + void initializeCurlGet(std::string const & url, bool processHeader); + void resumeDownloading(size_t startByte); void run(void); void startDownloading(LLURI const & uri, std::string const & hash); void throwOnCurlError(CURLcode code); @@ -119,6 +122,12 @@ bool LLUpdateDownloader::isDownloading(void) } +void LLUpdateDownloader::resume(void) +{ + mImplementation->resume(); +} + + // LLUpdateDownloader::Implementation //----------------------------------------------------------------------------- @@ -183,6 +192,45 @@ bool LLUpdateDownloader::Implementation::isDownloading(void) return !isStopped(); } + +void LLUpdateDownloader::Implementation::resume(void) +{ + llifstream dataStream(mDownloadRecordPath); + if(!dataStream) { + mClient.downloadError("no download marker"); + return; + } + + LLSDSerialize parser; + parser.fromXMLDocument(mDownloadData, dataStream); + + if(!mDownloadData.asBoolean()) { + mClient.downloadError("no download information in marker"); + return; + } + + std::string filePath = mDownloadData["path"].asString(); + try { + if(LLFile::isfile(filePath)) { + llstat fileStatus; + LLFile::stat(filePath, &fileStatus); + if(fileStatus.st_size != mDownloadData["size"].asInteger()) { + resumeDownloading(fileStatus.st_size); + } else if(!validateDownload()) { + LLFile::remove(filePath); + download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString()); + } else { + mClient.downloadComplete(mDownloadData); + } + } else { + download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString()); + } + } catch(DownloadError & e) { + mClient.downloadError(e.what()); + } +} + + void LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) { char const * headerPtr = reinterpret_cast (buffer); @@ -221,10 +269,11 @@ void LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size) void LLUpdateDownloader::Implementation::run(void) { CURLcode code = curl_easy_perform(mCurl); + LLFile::remove(mDownloadRecordPath); if(code == CURLE_OK) { if(validateDownload()) { LL_INFOS("UpdateDownload") << "download successful" << LL_ENDL; - mClient.downloadComplete(); + mClient.downloadComplete(mDownloadData); } else { LL_INFOS("UpdateDownload") << "download failed hash check" << LL_ENDL; std::string filePath = mDownloadData["path"].asString(); @@ -239,7 +288,7 @@ void LLUpdateDownloader::Implementation::run(void) } -void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url) +void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader) { if(mCurl == 0) { mCurl = curl_easy_init(); @@ -253,42 +302,33 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, this)); - throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, &header_function)); - throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, this)); + if(processHeader) { + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, &header_function)); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, this)); + } throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPGET, true)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str())); } -void LLUpdateDownloader::Implementation::resumeDownloading(LLSD const & downloadData) -{ -} - - -/* -bool LLUpdateDownloader::Implementation::shouldResumeOngoingDownload(LLURI const & uri, LLSD & downloadData) +void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) { - if(!LLFile::isfile(mDownloadRecordPath)) return false; + initializeCurlGet(mDownloadData["url"].asString(), false); - llifstream dataStream(mDownloadRecordPath); - LLSDSerialize parser; - parser.fromXMLDocument(downloadData, dataStream); + // The header 'Range: bytes n-' will request the bytes remaining in the + // source begining with byte n and ending with the last byte. + boost::format rangeHeaderFormat("Range: bytes=%u-"); + rangeHeaderFormat % startByte; + curl_slist * headerList = 0; + headerList = curl_slist_append(headerList, rangeHeaderFormat.str().c_str()); + if(headerList == 0) throw DownloadError("cannot add Range header"); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, headerList)); + curl_slist_free_all(headerList); - if(downloadData["url"].asString() != uri.asString()) return false; - - std::string downloadedFilePath = downloadData["path"].asString(); - if(LLFile::isfile(downloadedFilePath)) { - llstat fileStatus; - LLFile::stat(downloadedFilePath, &fileStatus); - downloadData["bytes_downloaded"] = LLSD(LLSD::Integer(fileStatus.st_size)); - return true; - } else { - return false; - } - - return true; + mDownloadStream.open(mDownloadData["path"].asString(), + std::ios_base::out | std::ios_base::binary | std::ios_base::app); + start(); } - */ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std::string const & hash) @@ -310,7 +350,7 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std parser.toPrettyXML(mDownloadData, dataStream); mDownloadStream.open(filePath, std::ios_base::out | std::ios_base::binary); - initializeCurlGet(uri.asString()); + initializeCurlGet(uri.asString(), true); start(); } -- cgit v1.2.3 From 6f7183cd4422a008554afd854dc631fe575ad8dc Mon Sep 17 00:00:00 2001 From: "Mark Palange (Mani)" Date: Fri, 5 Nov 2010 13:56:36 -0700 Subject: Fixed windows build error. --- indra/viewer_components/updater/llupdatedownloader.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 102f2f9eec..75f896cc76 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -201,8 +201,7 @@ void LLUpdateDownloader::Implementation::resume(void) return; } - LLSDSerialize parser; - parser.fromXMLDocument(mDownloadData, dataStream); + LLSDSerialize::fromXMLDocument(mDownloadData, dataStream); if(!mDownloadData.asBoolean()) { mClient.downloadError("no download information in marker"); @@ -248,8 +247,7 @@ void LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) mDownloadData["size"] = LLSD(LLSD::Integer(size)); llofstream odataStream(mDownloadRecordPath); - LLSDSerialize parser; - parser.toPrettyXML(mDownloadData, odataStream); + LLSDSerialize::toPrettyXML(mDownloadData, odataStream); } catch (std::exception const & e) { LL_WARNS("UpdateDownload") << "unable to read content length (" << e.what() << ")" << LL_ENDL; @@ -346,8 +344,7 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std LL_INFOS("UpdateDownload") << "hash of file is " << hash << LL_ENDL; llofstream dataStream(mDownloadRecordPath); - LLSDSerialize parser; - parser.toPrettyXML(mDownloadData, dataStream); + LLSDSerialize::toPrettyXML(mDownloadData, dataStream); mDownloadStream.open(filePath, std::ios_base::out | std::ios_base::binary); initializeCurlGet(uri.asString(), true); -- cgit v1.2.3 From a13acfc9073b0e29d84e1633fc11ff08e285be8f Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Fri, 5 Nov 2010 15:08:27 -0700 Subject: Fixed build error due to unreferenced local variable. --- indra/viewer_components/updater/llupdatedownloader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 75f896cc76..efb55ab83a 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -158,7 +158,7 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & mDownloadRecordPath(LLUpdateDownloader::downloadMarkerPath()) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case. - llassert(code = CURLE_OK); // TODO: real error handling here. + llverify(code == CURLE_OK); // TODO: real error handling here. } -- cgit v1.2.3 From 02c362b8ccad08f290ca99a738ca6ad1546c7df6 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Fri, 5 Nov 2010 15:56:33 -0700 Subject: implement download cancel (untested). --- .../updater/llupdatedownloader.cpp | 37 +++++++++++++++------- 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 102f2f9eec..eaef230a8f 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -46,11 +46,12 @@ public: void cancel(void); void download(LLURI const & uri, std::string const & hash); bool isDownloading(void); - void onHeader(void * header, size_t size); - void onBody(void * header, size_t size); + size_t onHeader(void * header, size_t size); + size_t onBody(void * header, size_t size); void resume(void); private: + bool mCancelled; LLUpdateDownloader::Client & mClient; CURL * mCurl; LLSD mDownloadData; @@ -137,28 +138,27 @@ namespace { size_t write_function(void * data, size_t blockSize, size_t blocks, void * downloader) { size_t bytes = blockSize * blocks; - reinterpret_cast(downloader)->onBody(data, bytes); - return bytes; + return reinterpret_cast(downloader)->onBody(data, bytes); } size_t header_function(void * data, size_t blockSize, size_t blocks, void * downloader) { size_t bytes = blockSize * blocks; - reinterpret_cast(downloader)->onHeader(data, bytes); - return bytes; + return reinterpret_cast(downloader)->onHeader(data, bytes); } } LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client): LLThread("LLUpdateDownloader"), + mCancelled(false), mClient(client), mCurl(0), mDownloadRecordPath(LLUpdateDownloader::downloadMarkerPath()) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case. - llassert(code = CURLE_OK); // TODO: real error handling here. + llassert(code == CURLE_OK); // TODO: real error handling here. } @@ -170,7 +170,7 @@ LLUpdateDownloader::Implementation::~Implementation() void LLUpdateDownloader::Implementation::cancel(void) { - llassert(!"not implemented"); + mCancelled = true; } @@ -231,12 +231,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 (buffer); std::string header(headerPtr, headerPtr + size); 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") { try { @@ -257,20 +257,25 @@ void LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) } else { ; // 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(buffer), size); + return size; } void LLUpdateDownloader::Implementation::run(void) { CURLcode code = curl_easy_perform(mCurl); - LLFile::remove(mDownloadRecordPath); if(code == CURLE_OK) { + LLFile::remove(mDownloadRecordPath); if(validateDownload()) { LL_INFOS("UpdateDownload") << "download successful" << LL_ENDL; mClient.downloadComplete(mDownloadData); @@ -280,9 +285,13 @@ void LLUpdateDownloader::Implementation::run(void) if(filePath.size() != 0) LLFile::remove(filePath); 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 { LL_WARNS("UpdateDownload") << "download failed with error '" << curl_easy_strerror(code) << "'" << LL_ENDL; + LLFile::remove(mDownloadRecordPath); mClient.downloadError("curl error"); } } @@ -381,6 +390,10 @@ bool LLUpdateDownloader::Implementation::validateDownload(void) LL_INFOS("UpdateDownload") << "checking hash..." << LL_ENDL; char digest[33]; 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; } else { return true; // No hash check provided. -- cgit v1.2.3 From 2cfcdfe2ffd97384324c940447a4197cbf85a38e Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 9 Nov 2010 09:14:50 -0800 Subject: Fix some stream bugs that were affecting windows download and validation. --- indra/viewer_components/updater/llupdatedownloader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index ca1d2d25de..2794f80c47 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -272,6 +272,7 @@ size_t LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size) void LLUpdateDownloader::Implementation::run(void) { CURLcode code = curl_easy_perform(mCurl); + mDownloadStream.close(); if(code == CURLE_OK) { LLFile::remove(mDownloadRecordPath); if(validateDownload()) { @@ -379,7 +380,7 @@ void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code) bool LLUpdateDownloader::Implementation::validateDownload(void) { std::string filePath = mDownloadData["path"].asString(); - llifstream fileStream(filePath); + llifstream fileStream(filePath, std::ios_base::in | std::ios_base::binary); if(!fileStream) return false; std::string hash = mDownloadData["hash"].asString(); -- cgit v1.2.3 From 5da253fdde8737361333161517c1173358bd17ff Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 9 Nov 2010 11:16:28 -0800 Subject: Shut down thread if viewer closed while downloading; fix problem of download marker path failing to expand correctly because it was happening too early in start up. --- indra/viewer_components/updater/llupdatedownloader.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 2794f80c47..208cc48c12 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -154,8 +154,7 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & LLThread("LLUpdateDownloader"), mCancelled(false), mClient(client), - mCurl(0), - mDownloadRecordPath(LLUpdateDownloader::downloadMarkerPath()) + mCurl(0) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case. llverify(code == CURLE_OK); // TODO: real error handling here. @@ -164,6 +163,12 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & LLUpdateDownloader::Implementation::~Implementation() { + if(isDownloading()) { + cancel(); + shutdown(); + } else { + ; // No op. + } if(mCurl) curl_easy_cleanup(mCurl); } @@ -177,7 +182,8 @@ void LLUpdateDownloader::Implementation::cancel(void) void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash) { if(isDownloading()) mClient.downloadError("download in progress"); - + + mDownloadRecordPath = downloadMarkerPath(); mDownloadData = LLSD(); try { startDownloading(uri, hash); @@ -195,6 +201,9 @@ bool LLUpdateDownloader::Implementation::isDownloading(void) void LLUpdateDownloader::Implementation::resume(void) { + if(isDownloading()) mClient.downloadError("download in progress"); + + mDownloadRecordPath = downloadMarkerPath(); llifstream dataStream(mDownloadRecordPath); if(!dataStream) { mClient.downloadError("no download marker"); -- cgit v1.2.3 From 94942671fa81ad0da3682af31b715ca49f8e3bef Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Wed, 10 Nov 2010 15:23:26 -0800 Subject: fix resume crash. --- .../viewer_components/updater/llupdatedownloader.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 208cc48c12..21555dc3ff 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -57,6 +57,7 @@ private: LLSD mDownloadData; llofstream mDownloadStream; std::string mDownloadRecordPath; + curl_slist * mHeaderList; void initializeCurlGet(std::string const & url, bool processHeader); void resumeDownloading(size_t startByte); @@ -154,7 +155,8 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & LLThread("LLUpdateDownloader"), mCancelled(false), mClient(client), - mCurl(0) + mCurl(0), + mHeaderList(0) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case. llverify(code == CURLE_OK); // TODO: real error handling here. @@ -302,6 +304,11 @@ void LLUpdateDownloader::Implementation::run(void) LLFile::remove(mDownloadRecordPath); mClient.downloadError("curl error"); } + + if(mHeaderList) { + curl_slist_free_all(mHeaderList); + mHeaderList = 0; + } } @@ -330,17 +337,18 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) { + LL_INFOS("UpdateDownload") << "resuming download from " << mDownloadData["url"].asString() + << " at byte " << startByte << LL_ENDL; + initializeCurlGet(mDownloadData["url"].asString(), false); // The header 'Range: bytes n-' will request the bytes remaining in the // source begining with byte n and ending with the last byte. boost::format rangeHeaderFormat("Range: bytes=%u-"); rangeHeaderFormat % startByte; - curl_slist * headerList = 0; - headerList = curl_slist_append(headerList, rangeHeaderFormat.str().c_str()); - if(headerList == 0) throw DownloadError("cannot add Range header"); - throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, headerList)); - curl_slist_free_all(headerList); + mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str()); + if(mHeaderList == 0) throw DownloadError("cannot add Range header"); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mHeaderList)); mDownloadStream.open(mDownloadData["path"].asString(), std::ios_base::out | std::ios_base::binary | std::ios_base::app); -- cgit v1.2.3 From 1368a94f014884588b343802eef5fd2c7888390a Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Fri, 12 Nov 2010 12:23:30 -0800 Subject: do not resume or install if current viewer version doesn't match the recorded version which started the process. --- indra/viewer_components/updater/llupdatedownloader.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 21555dc3ff..ab441aa747 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -35,6 +35,7 @@ #include "llsdserialize.h" #include "llthread.h" #include "llupdatedownloader.h" +#include "llupdaterservice.h" class LLUpdateDownloader::Implementation: @@ -360,6 +361,7 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std { mDownloadData["url"] = uri.asString(); mDownloadData["hash"] = hash; + mDownloadData["current_version"] = ll_get_version(); LLSD path = uri.pathArray(); if(path.size() == 0) throw DownloadError("no file path"); std::string fileName = path[path.size() - 1].asString(); -- cgit v1.2.3 From 64876ea9459ed0e0f1673c5ec9ae67abea2280e2 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 16 Nov 2010 09:43:23 -0800 Subject: better error checking when writing downloaded file. --- indra/viewer_components/updater/llupdatedownloader.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index ab441aa747..eccc25aeee 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -275,9 +275,14 @@ size_t LLUpdateDownloader::Implementation::onHeader(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. + if((size == 0) || (buffer == 0)) return 0; mDownloadStream.write(reinterpret_cast(buffer), size); - return size; + if(mDownloadStream.bad()) { + return 0; + } else { + return size; + } } -- cgit v1.2.3 From 74a60346b2f04157862786d31d7181885092b766 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 16 Nov 2010 16:22:37 -0800 Subject: remove downloaded file on error. --- indra/viewer_components/updater/llupdatedownloader.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index eccc25aeee..4820f1f452 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -308,6 +308,7 @@ void LLUpdateDownloader::Implementation::run(void) LL_WARNS("UpdateDownload") << "download failed with error '" << curl_easy_strerror(code) << "'" << LL_ENDL; LLFile::remove(mDownloadRecordPath); + if(mDownloadData.has("path")) LLFile::remove(mDownloadData["path"].asString()); mClient.downloadError("curl error"); } -- cgit v1.2.3 From 8c2026d6b71f133deafa6b0e19baf69632a2510a Mon Sep 17 00:00:00 2001 From: "Mark Palange (Mani)" Date: Thu, 18 Nov 2010 21:57:27 -0800 Subject: CHOP-135 Bug fixes. --- indra/viewer_components/updater/llupdatedownloader.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/viewer_components/updater/llupdatedownloader.cpp') diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 4820f1f452..c17a50e242 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -204,7 +204,11 @@ bool LLUpdateDownloader::Implementation::isDownloading(void) void LLUpdateDownloader::Implementation::resume(void) { - if(isDownloading()) mClient.downloadError("download in progress"); + mCancelled = false; + + if(isDownloading()) { + mClient.downloadError("download in progress"); + } mDownloadRecordPath = downloadMarkerPath(); llifstream dataStream(mDownloadRecordPath); -- cgit v1.2.3