Skip to content
Snippets Groups Projects
Commit 7622ab92 authored by Andrew A. de Laix's avatar Andrew A. de Laix
Browse files

just barely working udate downloading service; missing little nicities like...

just barely working udate downloading service; missing little nicities like error checking and sill stuff like that.
parent 0f6c3a16
No related branches found
No related tags found
No related merge requests found
...@@ -120,17 +120,19 @@ void LLUpdateChecker::Implementation::completed(U32 status, ...@@ -120,17 +120,19 @@ void LLUpdateChecker::Implementation::completed(U32 status,
const std::string & reason, const std::string & reason,
const LLSD & content) const LLSD & content)
{ {
mInProgress = false; mInProgress = false;
if(status != 200) { if(status != 200) {
LL_WARNS("UpdateCheck") << "html error " << status << " (" << reason << ")" << llendl; LL_WARNS("UpdateCheck") << "html error " << status << " (" << reason << ")" << llendl;
mClient.error(reason); mClient.error(reason);
} else if(!content["valid"].asBoolean()) { } else if(!content["valid"].asBoolean()) {
LL_INFOS("UpdateCheck") << "version invalid" << llendl; LL_INFOS("UpdateCheck") << "version invalid" << llendl;
mClient.requiredUpdate(content["latest_version"].asString()); LLURI uri(content["download_url"].asString());
mClient.requiredUpdate(content["latest_version"].asString(), uri);
} else if(content["latest_version"].asString() != mVersion) { } else if(content["latest_version"].asString() != mVersion) {
LL_INFOS("UpdateCheck") << "newer version " << content["latest_version"].asString() << " available" << llendl; LL_INFOS("UpdateCheck") << "newer version " << content["latest_version"].asString() << " available" << llendl;
mClient.optionalUpdate(content["latest_version"].asString()); LLURI uri(content["download_url"].asString());
mClient.optionalUpdate(content["latest_version"].asString(), uri);
} else { } else {
LL_INFOS("UpdateCheck") << "up to date" << llendl; LL_INFOS("UpdateCheck") << "up to date" << llendl;
mClient.upToDate(); mClient.upToDate();
...@@ -153,4 +155,3 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & host, ...@@ -153,4 +155,3 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & host,
path.append(version); path.append(version);
return LLURI::buildHTTP(host, path).asString(); return LLURI::buildHTTP(host, path).asString();
} }
...@@ -48,6 +48,9 @@ class LLUpdateChecker { ...@@ -48,6 +48,9 @@ class LLUpdateChecker {
}; };
class LLURI; // From lluri.h
// //
// The client interface implemented by a requestor checking for an update. // The client interface implemented by a requestor checking for an update.
// //
...@@ -58,10 +61,10 @@ class LLUpdateChecker::Client ...@@ -58,10 +61,10 @@ class LLUpdateChecker::Client
virtual void error(std::string const & message) = 0; virtual void error(std::string const & message) = 0;
// A newer version is available, but the current version may still be used. // A newer version is available, but the current version may still be used.
virtual void optionalUpdate(std::string const & newVersion) = 0; virtual void optionalUpdate(std::string const & newVersion, LLURI const & uri) = 0;
// A newer version is available, and the current version is no longer valid. // A newer version is available, and the current version is no longer valid.
virtual void requiredUpdate(std::string const & newVersion) = 0; virtual void requiredUpdate(std::string const & newVersion, LLURI const & uri) = 0;
// The checked version is up to date; no newer version exists. // The checked version is up to date; no newer version exists.
virtual void upToDate(void) = 0; virtual void upToDate(void) = 0;
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
*/ */
#include "linden_common.h" #include "linden_common.h"
#include <boost/lexical_cast.hpp>
#include <curl/curl.h>
#include "lldir.h" #include "lldir.h"
#include "llfile.h" #include "llfile.h"
#include "llsd.h" #include "llsd.h"
...@@ -37,20 +39,27 @@ class LLUpdateDownloader::Implementation: ...@@ -37,20 +39,27 @@ class LLUpdateDownloader::Implementation:
{ {
public: public:
Implementation(LLUpdateDownloader::Client & client); Implementation(LLUpdateDownloader::Client & client);
~Implementation();
void cancel(void); void cancel(void);
void download(LLURI const & uri); void download(LLURI const & uri);
bool isDownloading(void); bool isDownloading(void);
void onHeader(void * header, size_t size);
void onBody(void * header, size_t size);
private: private:
static const char * sSecondLifeUpdateRecord; static const char * sSecondLifeUpdateRecord;
LLUpdateDownloader::Client & mClient; LLUpdateDownloader::Client & mClient;
CURL * mCurl;
llofstream mDownloadStream;
std::string mDownloadRecordPath; std::string mDownloadRecordPath;
void initializeCurlGet(std::string const & url);
void resumeDownloading(LLSD const & downloadData); void resumeDownloading(LLSD const & downloadData);
void run(void); void run(void);
bool shouldResumeOngoingDownload(LLURI const & uri, LLSD & downloadData); bool shouldResumeOngoingDownload(LLURI const & uri, LLSD & downloadData);
void startDownloading(LLURI const & uri); void startDownloading(LLURI const & uri);
LOG_CLASS(LLUpdateDownloader::Implementation);
}; };
...@@ -89,6 +98,23 @@ bool LLUpdateDownloader::isDownloading(void) ...@@ -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<LLUpdateDownloader::Implementation *>(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<LLUpdateDownloader::Implementation *>(downloader)->onHeader(data, bytes);
return bytes;
}
}
const char * LLUpdateDownloader::Implementation::sSecondLifeUpdateRecord = const char * LLUpdateDownloader::Implementation::sSecondLifeUpdateRecord =
"SecondLifeUpdateDownload.xml"; "SecondLifeUpdateDownload.xml";
...@@ -96,35 +122,116 @@ const char * LLUpdateDownloader::Implementation::sSecondLifeUpdateRecord = ...@@ -96,35 +122,116 @@ const char * LLUpdateDownloader::Implementation::sSecondLifeUpdateRecord =
LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client): LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client):
LLThread("LLUpdateDownloader"), LLThread("LLUpdateDownloader"),
mClient(client), mClient(client),
mCurl(0),
mDownloadRecordPath(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, sSecondLifeUpdateRecord)) 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) void LLUpdateDownloader::Implementation::download(LLURI const & uri)
{ {
LLSD downloadData; LLSD downloadData;
if(shouldResumeOngoingDownload(uri, downloadData)){ if(shouldResumeOngoingDownload(uri, downloadData)){
startDownloading(uri); // TODO: Implement resume.
} else { } else {
startDownloading(uri);
} }
} }
bool LLUpdateDownloader::Implementation::isDownloading(void) bool LLUpdateDownloader::Implementation::isDownloading(void)
{ {
return false; return !isStopped();
}
void LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size)
{
char const * headerPtr = reinterpret_cast<const char *> (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<size_t>(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<const char *>(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) ...@@ -160,9 +267,14 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri)
LLSD path = uri.pathArray(); LLSD path = uri.pathArray();
std::string fileName = path[path.size() - 1].asString(); std::string fileName = path[path.size() - 1].asString();
std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName); 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); llofstream dataStream(mDownloadRecordPath);
LLSDSerialize parser; LLSDSerialize parser;
parser.toPrettyXML(downloadData, dataStream); parser.toPrettyXML(downloadData, dataStream);
llofstream downloadStream(filePath); mDownloadStream.open(filePath, std::ios_base::out | std::ios_base::binary);
initializeCurlGet(uri.asString());
start();
} }
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define LL_UPDATE_DOWNLOADER_H #define LL_UPDATE_DOWNLOADER_H
#include <stdexcept>
#include <string> #include <string>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include "lluri.h" #include "lluri.h"
...@@ -38,15 +39,19 @@ ...@@ -38,15 +39,19 @@
class LLUpdateDownloader class LLUpdateDownloader
{ {
public: public:
class BusyError;
class Client; class Client;
class Implementation; class Implementation;
LLUpdateDownloader(Client & client); LLUpdateDownloader(Client & client);
// Cancel any in progress download. // Cancel any in progress download; a no op if none is in progress.
void cancel(void); void cancel(void);
// Start a new download. // Start a new download.
//
// This method will throw a BusyException instance if a download is already
// in progress.
void download(LLURI const & uri); void download(LLURI const & uri);
// Returns true if a download is in progress. // Returns true if a download is in progress.
...@@ -61,12 +66,13 @@ class LLUpdateDownloader ...@@ -61,12 +66,13 @@ class LLUpdateDownloader
// An interface to be implemented by clients initiating a update download. // An interface to be implemented by clients initiating a update download.
// //
class LLUpdateDownloader::Client { class LLUpdateDownloader::Client {
public:
// The download has completed successfully. // The download has completed successfully.
void downloadComplete(void); virtual void downloadComplete(void) = 0;
// The download failed. // The download failed.
void downloadError(std::string const & message); virtual void downloadError(std::string const & message) = 0;
}; };
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "linden_common.h" #include "linden_common.h"
#include "llupdatedownloader.h"
#include "llevents.h" #include "llevents.h"
#include "lltimer.h" #include "lltimer.h"
#include "llupdaterservice.h" #include "llupdaterservice.h"
...@@ -42,7 +43,8 @@ boost::weak_ptr<LLUpdaterServiceImpl> gUpdater; ...@@ -42,7 +43,8 @@ boost::weak_ptr<LLUpdaterServiceImpl> gUpdater;
class LLUpdaterServiceImpl : class LLUpdaterServiceImpl :
public LLPluginProcessParentOwner, public LLPluginProcessParentOwner,
public LLUpdateChecker::Client public LLUpdateChecker::Client,
public LLUpdateDownloader::Client
{ {
static const std::string sListenerName; static const std::string sListenerName;
...@@ -55,6 +57,7 @@ class LLUpdaterServiceImpl : ...@@ -55,6 +57,7 @@ class LLUpdaterServiceImpl :
boost::scoped_ptr<LLPluginProcessParent> mPlugin; boost::scoped_ptr<LLPluginProcessParent> mPlugin;
LLUpdateChecker mUpdateChecker; LLUpdateChecker mUpdateChecker;
LLUpdateDownloader mUpdateDownloader;
LLTimer mTimer; LLTimer mTimer;
void retry(void); void retry(void);
...@@ -83,10 +86,14 @@ class LLUpdaterServiceImpl : ...@@ -83,10 +86,14 @@ class LLUpdaterServiceImpl :
// LLUpdateChecker::Client: // LLUpdateChecker::Client:
virtual void error(std::string const & message); virtual void error(std::string const & message);
virtual void optionalUpdate(std::string const & newVersion); virtual void optionalUpdate(std::string const & newVersion, LLURI const & uri);
virtual void requiredUpdate(std::string const & newVersion); virtual void requiredUpdate(std::string const & newVersion, LLURI const & uri);
virtual void upToDate(void); virtual void upToDate(void);
// LLUpdateDownloader::Client
void downloadComplete(void) { retry(); }
void downloadError(std::string const & message) { retry(); }
bool onMainLoop(LLSD const & event); bool onMainLoop(LLSD const & event);
}; };
...@@ -96,7 +103,8 @@ LLUpdaterServiceImpl::LLUpdaterServiceImpl() : ...@@ -96,7 +103,8 @@ LLUpdaterServiceImpl::LLUpdaterServiceImpl() :
mIsChecking(false), mIsChecking(false),
mCheckPeriod(0), mCheckPeriod(0),
mPlugin(0), mPlugin(0),
mUpdateChecker(*this) mUpdateChecker(*this),
mUpdateDownloader(*this)
{ {
// Create the plugin parent, this is the owner. // Create the plugin parent, this is the owner.
mPlugin.reset(new LLPluginProcessParent(this)); mPlugin.reset(new LLPluginProcessParent(this));
...@@ -179,14 +187,14 @@ void LLUpdaterServiceImpl::error(std::string const & message) ...@@ -179,14 +187,14 @@ void LLUpdaterServiceImpl::error(std::string const & message)
retry(); retry();
} }
void LLUpdaterServiceImpl::optionalUpdate(std::string const & newVersion) void LLUpdaterServiceImpl::optionalUpdate(std::string const & newVersion, LLURI const & uri)
{ {
retry(); mUpdateDownloader.download(uri);
} }
void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion) void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion, LLURI const & uri)
{ {
retry(); mUpdateDownloader.download(uri);
} }
void LLUpdaterServiceImpl::upToDate(void) void LLUpdaterServiceImpl::upToDate(void)
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
// associated header // associated header
#include "../llupdaterservice.h" #include "../llupdaterservice.h"
#include "../llupdatechecker.h" #include "../llupdatechecker.h"
#include "../llupdatedownloader.h"
#include "../../../test/lltut.h" #include "../../../test/lltut.h"
//#define DEBUG_ON //#define DEBUG_ON
...@@ -60,6 +61,9 @@ LLPluginMessage::LLPluginMessage(LLPluginMessage const&) {} ...@@ -60,6 +61,9 @@ LLPluginMessage::LLPluginMessage(LLPluginMessage const&) {}
LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client) LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client)
{} {}
void LLUpdateChecker::check(std::string const & host, std::string channel, std::string version){} void LLUpdateChecker::check(std::string const & host, std::string channel, std::string version){}
LLUpdateDownloader::LLUpdateDownloader(LLUpdateDownloader::Client & client)
{}
void LLUpdateDownloader::download(LLURI const & ){}
/***************************************************************************** /*****************************************************************************
* TUT * TUT
......
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