/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. #include "linden_common.h"
  26. #include <stdexcept>
  27. #include <boost/format.hpp>
  28. #include "llhttpclient.h"
  29. #include "llsd.h"
  30. #include "llupdatechecker.h"
  31. #include "lluri.h"
  32. #if LL_WINDOWS
  33. #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
  34. #endif
  35. class LLUpdateChecker::CheckError:
  36. public std::runtime_error
  37. {
  38. public:
  39. CheckError(const char * message):
  40. std::runtime_error(message)
  41. {
  42. ; // No op.
  43. }
  44. };
  45. class LLUpdateChecker::Implementation:
  46. public LLHTTPClient::Responder
  47. {
  48. public:
  49. Implementation(Client & client);
  50. ~Implementation();
  51. void check(std::string const & protocolVersion, std::string const & hostUrl,
  52. std::string const & servicePath, std::string channel, std::string version);
  53. // Responder:
  54. virtual void completed(U32 status,
  55. const std::string & reason,
  56. const LLSD& content);
  57. virtual void error(U32 status, const std::string & reason);
  58. private:
  59. static const char * sProtocolVersion;
  60. Client & mClient;
  61. LLHTTPClient mHttpClient;
  62. bool mInProgress;
  63. std::string mVersion;
  64. std::string buildUrl(std::string const & protocolVersion, std::string const & hostUrl,
  65. std::string const & servicePath, std::string channel, std::string version);
  66. LOG_CLASS(LLUpdateChecker::Implementation);
  67. };
  68. // LLUpdateChecker
  69. //-----------------------------------------------------------------------------
  70. LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
  71. mImplementation(new LLUpdateChecker::Implementation(client))
  72. {
  73. ; // No op.
  74. }
  75. void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl,
  76. std::string const & servicePath, std::string channel, std::string version)
  77. {
  78. mImplementation->check(protocolVersion, hostUrl, servicePath, channel, version);
  79. }
  80. // LLUpdateChecker::Implementation
  81. //-----------------------------------------------------------------------------
  82. const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.0";
  83. LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client):
  84. mClient(client),
  85. mInProgress(false)
  86. {
  87. ; // No op.
  88. }
  89. LLUpdateChecker::Implementation::~Implementation()
  90. {
  91. ; // No op.
  92. }
  93. void LLUpdateChecker::Implementation::check(std::string const & protocolVersion, std::string const & hostUrl,
  94. std::string const & servicePath, std::string channel, std::string version)
  95. {
  96. llassert(!mInProgress);
  97. if(protocolVersion != sProtocolVersion) throw CheckError("unsupported protocol");
  98. mInProgress = true;
  99. mVersion = version;
  100. std::string checkUrl = buildUrl(protocolVersion, hostUrl, servicePath, channel, version);
  101. LL_INFOS("UpdateCheck") << "checking for updates at " << checkUrl << llendl;
  102. // The HTTP client will wrap a raw pointer in a boost::intrusive_ptr causing the
  103. // passed object to be silently and automatically deleted. We pass a self-
  104. // referential intrusive pointer to which we add a reference to keep the
  105. // client from deleting the update checker implementation instance.
  106. LLHTTPClient::ResponderPtr temporaryPtr(this);
  107. boost::intrusive_ptr_add_ref(temporaryPtr.get());
  108. mHttpClient.get(checkUrl, temporaryPtr);
  109. }
  110. void LLUpdateChecker::Implementation::completed(U32 status,
  111. const std::string & reason,
  112. const LLSD & content)
  113. {
  114. mInProgress = false;
  115. if(status != 200) {
  116. LL_WARNS("UpdateCheck") << "html error " << status << " (" << reason << ")" << llendl;
  117. mClient.error(reason);
  118. } else if(!content.asBoolean()) {
  119. LL_INFOS("UpdateCheck") << "up to date" << llendl;
  120. mClient.upToDate();
  121. } else if(content["required"].asBoolean()) {
  122. LL_INFOS("UpdateCheck") << "version invalid" << llendl;
  123. LLURI uri(content["url"].asString());
  124. mClient.requiredUpdate(content["version"].asString(), uri, content["hash"].asString());
  125. } else {
  126. LL_INFOS("UpdateCheck") << "newer version " << content["version"].asString() << " available" << llendl;
  127. LLURI uri(content["url"].asString());
  128. mClient.optionalUpdate(content["version"].asString(), uri, content["hash"].asString());
  129. }
  130. }
  131. void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
  132. {
  133. mInProgress = false;
  134. LL_WARNS("UpdateCheck") << "update check failed; " << reason << llendl;
  135. mClient.error(reason);
  136. }
  137. std::string LLUpdateChecker::Implementation::buildUrl(std::string const & protocolVersion, std::string const & hostUrl,
  138. std::string const & servicePath, std::string channel, std::string version)
  139. {
  140. #ifdef LL_WINDOWS
  141. static const char * platform = "win";
  142. #elif LL_DARWIN
  143. static const char * platform = "mac";
  144. #else
  145. static const char * platform = "lnx";
  146. #endif
  147. LLSD path;
  148. path.append(servicePath);
  149. path.append(protocolVersion);
  150. path.append(channel);
  151. path.append(version);
  152. path.append(platform);
  153. return LLURI::buildHTTP(hostUrl, path).asString();
  154. }