diff options
Diffstat (limited to 'indra/viewer_components')
| -rw-r--r-- | indra/viewer_components/updater/llupdatedownloader.cpp | 104 | ||||
| -rw-r--r-- | indra/viewer_components/updater/llupdatedownloader.h | 5 | ||||
| -rw-r--r-- | indra/viewer_components/updater/llupdaterservice.cpp | 2 | 
3 files changed, 77 insertions, 34 deletions
| 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 <stdexcept> +#include <boost/format.hpp>  #include <boost/lexical_cast.hpp>  #include <curl/curl.h>  #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<const char *> (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();  } diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h index 8754ea329c..7bfb430879 100644 --- a/indra/viewer_components/updater/llupdatedownloader.h +++ b/indra/viewer_components/updater/llupdatedownloader.h @@ -56,6 +56,9 @@ public:  	// Returns true if a download is in progress.  	bool isDownloading(void); +	// Resume a partial download. +	void resume(void); +	  private:  	boost::shared_ptr<Implementation> mImplementation;  }; @@ -68,7 +71,7 @@ class LLUpdateDownloader::Client {  public:  	// The download has completed successfully. -	virtual void downloadComplete(void) = 0; +	virtual void downloadComplete(LLSD const & data) = 0;  	// The download failed.  	virtual void downloadError(std::string const & message) = 0; diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 1e0c393539..dc48606cbc 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -99,7 +99,7 @@ public:  	virtual void upToDate(void);  	// LLUpdateDownloader::Client -	void downloadComplete(void) { retry(); } +	void downloadComplete(LLSD const & data) { retry(); }  	void downloadError(std::string const & message) { retry(); }	  	bool onMainLoop(LLSD const & event);	 | 
