PageRenderTime 32ms CodeModel.GetById 1ms app.highlight 25ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/viewer_components/updater/llupdatechecker.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 194 lines | 121 code | 40 blank | 33 comment | 9 complexity | e5196e358f08ab12d08febe3e221611a MD5 | raw file
  1/** 
  2 * @file llupdaterservice.cpp
  3 *
  4 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
  5 * Second Life Viewer Source Code
  6 * Copyright (C) 2010, Linden Research, Inc.
  7 * 
  8 * This library is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU Lesser General Public
 10 * License as published by the Free Software Foundation;
 11 * version 2.1 of the License only.
 12 * 
 13 * This library is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16 * Lesser General Public License for more details.
 17 * 
 18 * You should have received a copy of the GNU Lesser General Public
 19 * License along with this library; if not, write to the Free Software
 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 21 * 
 22 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 23 * $/LicenseInfo$
 24 */
 25
 26#include "linden_common.h"
 27#include <stdexcept>
 28#include <boost/format.hpp>
 29#include "llhttpclient.h"
 30#include "llsd.h"
 31#include "llupdatechecker.h"
 32#include "lluri.h"
 33
 34
 35#if LL_WINDOWS
 36#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
 37#endif
 38
 39
 40class LLUpdateChecker::CheckError:
 41	public std::runtime_error
 42{
 43public:
 44	CheckError(const char * message):
 45		std::runtime_error(message)
 46	{
 47		; // No op.
 48	}
 49};
 50
 51
 52class LLUpdateChecker::Implementation:
 53	public LLHTTPClient::Responder
 54{
 55public:
 56	Implementation(Client & client);
 57	~Implementation();
 58	void check(std::string const & protocolVersion, std::string const & hostUrl, 
 59			   std::string const & servicePath, std::string channel, std::string version);
 60	
 61	// Responder:
 62	virtual void completed(U32 status,
 63						   const std::string & reason,
 64						   const LLSD& content);
 65	virtual void error(U32 status, const std::string & reason);
 66	
 67private:	
 68	static const char * sProtocolVersion;
 69	
 70	Client & mClient;
 71	LLHTTPClient mHttpClient;
 72	bool mInProgress;
 73	std::string mVersion;
 74	
 75	std::string buildUrl(std::string const & protocolVersion, std::string const & hostUrl, 
 76						 std::string const & servicePath, std::string channel, std::string version);
 77
 78	LOG_CLASS(LLUpdateChecker::Implementation);
 79};
 80
 81
 82
 83// LLUpdateChecker
 84//-----------------------------------------------------------------------------
 85
 86
 87LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
 88	mImplementation(new LLUpdateChecker::Implementation(client))
 89{
 90	; // No op.
 91}
 92
 93
 94void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl, 
 95							std::string const & servicePath, std::string channel, std::string version)
 96{
 97	mImplementation->check(protocolVersion, hostUrl, servicePath, channel, version);
 98}
 99
100
101
102// LLUpdateChecker::Implementation
103//-----------------------------------------------------------------------------
104
105
106const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.0";
107
108
109LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client):
110	mClient(client),
111	mInProgress(false)
112{
113	; // No op.
114}
115
116
117LLUpdateChecker::Implementation::~Implementation()
118{
119	; // No op.
120}
121
122
123void LLUpdateChecker::Implementation::check(std::string const & protocolVersion, std::string const & hostUrl, 
124											std::string const & servicePath, std::string channel, std::string version)
125{
126	llassert(!mInProgress);
127	
128	if(protocolVersion != sProtocolVersion) throw CheckError("unsupported protocol");
129		
130	mInProgress = true;
131	mVersion = version;
132	std::string checkUrl = buildUrl(protocolVersion, hostUrl, servicePath, channel, version);
133	LL_INFOS("UpdateCheck") << "checking for updates at " << checkUrl << llendl;
134	
135	// The HTTP client will wrap a raw pointer in a boost::intrusive_ptr causing the
136	// passed object to be silently and automatically deleted.  We pass a self-
137	// referential intrusive pointer to which we add a reference to keep the
138	// client from deleting the update checker implementation instance.
139	LLHTTPClient::ResponderPtr temporaryPtr(this);
140	boost::intrusive_ptr_add_ref(temporaryPtr.get());
141	mHttpClient.get(checkUrl, temporaryPtr);
142}
143
144void LLUpdateChecker::Implementation::completed(U32 status,
145							  const std::string & reason,
146							  const LLSD & content)
147{
148	mInProgress = false;	
149	
150	if(status != 200) {
151		LL_WARNS("UpdateCheck") << "html error " << status << " (" << reason << ")" << llendl;
152		mClient.error(reason);
153	} else if(!content.asBoolean()) {
154		LL_INFOS("UpdateCheck") << "up to date" << llendl;
155		mClient.upToDate();
156	} else if(content["required"].asBoolean()) {
157		LL_INFOS("UpdateCheck") << "version invalid" << llendl;
158		LLURI uri(content["url"].asString());
159		mClient.requiredUpdate(content["version"].asString(), uri, content["hash"].asString());
160	} else {
161		LL_INFOS("UpdateCheck") << "newer version " << content["version"].asString() << " available" << llendl;
162		LLURI uri(content["url"].asString());
163		mClient.optionalUpdate(content["version"].asString(), uri, content["hash"].asString());
164	}
165}
166
167
168void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
169{
170	mInProgress = false;
171	LL_WARNS("UpdateCheck") << "update check failed; " << reason << llendl;
172	mClient.error(reason);
173}
174
175
176std::string LLUpdateChecker::Implementation::buildUrl(std::string const & protocolVersion, std::string const & hostUrl, 
177													  std::string const & servicePath, std::string channel, std::string version)
178{	
179#ifdef LL_WINDOWS
180	static const char * platform = "win";
181#elif LL_DARWIN
182	static const char * platform = "mac";
183#else
184	static const char * platform = "lnx";
185#endif
186	
187	LLSD path;
188	path.append(servicePath);
189	path.append(protocolVersion);
190	path.append(channel);
191	path.append(version);
192	path.append(platform);
193	return LLURI::buildHTTP(hostUrl, path).asString();
194}