PageRenderTime 65ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llcapabilitylistener.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 202 lines | 141 code | 14 blank | 47 comment | 11 complexity | b44d7c77ae0ce0ee1f526d096d326493 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llcapabilitylistener.cpp
  3. * @author Nat Goodspeed
  4. * @date 2009-01-07
  5. * @brief Implementation for llcapabilitylistener.
  6. *
  7. * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  8. * Second Life Viewer Source Code
  9. * Copyright (C) 2010, Linden Research, Inc.
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation;
  14. * version 2.1 of the License only.
  15. *
  16. * This library is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with this library; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  26. * $/LicenseInfo$
  27. */
  28. // Precompiled header
  29. #include "llviewerprecompiledheaders.h"
  30. // associated header
  31. #include "llcapabilitylistener.h"
  32. // STL headers
  33. #include <map>
  34. // std headers
  35. // external library headers
  36. #include <boost/bind.hpp>
  37. // other Linden headers
  38. #include "stringize.h"
  39. #include "llcapabilityprovider.h"
  40. #include "message.h"
  41. class LLCapabilityListener::CapabilityMappers: public LLSingleton<LLCapabilityListener::CapabilityMappers>
  42. {
  43. public:
  44. void registerMapper(const LLCapabilityListener::CapabilityMapper*);
  45. void unregisterMapper(const LLCapabilityListener::CapabilityMapper*);
  46. const LLCapabilityListener::CapabilityMapper* find(const std::string& cap) const;
  47. struct DupCapMapper: public std::runtime_error
  48. {
  49. DupCapMapper(const std::string& what):
  50. std::runtime_error(std::string("DupCapMapper: ") + what)
  51. {}
  52. };
  53. private:
  54. friend class LLSingleton<LLCapabilityListener::CapabilityMappers>;
  55. CapabilityMappers();
  56. typedef std::map<std::string, const LLCapabilityListener::CapabilityMapper*> CapabilityMap;
  57. CapabilityMap mMap;
  58. };
  59. LLCapabilityListener::LLCapabilityListener(const std::string& name,
  60. LLMessageSystem* messageSystem,
  61. const LLCapabilityProvider& provider,
  62. const LLUUID& agentID,
  63. const LLUUID& sessionID):
  64. mEventPump(name),
  65. mMessageSystem(messageSystem),
  66. mProvider(provider),
  67. mAgentID(agentID),
  68. mSessionID(sessionID)
  69. {
  70. mEventPump.listen("self", boost::bind(&LLCapabilityListener::capListener, this, _1));
  71. }
  72. bool LLCapabilityListener::capListener(const LLSD& request)
  73. {
  74. // Extract what we want from the request object. We do it all up front
  75. // partly to document what we expect.
  76. LLSD::String cap(request["message"]);
  77. LLSD payload(request["payload"]);
  78. LLSD::String reply(request["reply"]);
  79. LLSD::String error(request["error"]);
  80. LLSD::Real timeout(request["timeout"]);
  81. // If the LLSD doesn't even have a "message" key, we doubt it was intended
  82. // for this listener.
  83. if (cap.empty())
  84. {
  85. LL_ERRS("capListener") << "capability request event without 'message' key to '"
  86. << getCapAPI().getName()
  87. << "' on region\n" << mProvider.getDescription()
  88. << LL_ENDL;
  89. return false; // in case fatal-error function isn't
  90. }
  91. // Establish default timeout. This test relies on LLSD::asReal() returning
  92. // exactly 0.0 for an undef value.
  93. if (! timeout)
  94. {
  95. timeout = HTTP_REQUEST_EXPIRY_SECS;
  96. }
  97. // Look up the url for the requested capability name.
  98. std::string url = mProvider.getCapability(cap);
  99. if (! url.empty())
  100. {
  101. // This capability is supported by the region to which we're talking.
  102. LLHTTPClient::post(url, payload,
  103. new LLSDMessage::EventResponder(LLEventPumps::instance(),
  104. request,
  105. mProvider.getDescription(),
  106. cap, reply, error),
  107. LLSD(), // headers
  108. timeout);
  109. }
  110. else
  111. {
  112. // Capability not supported -- do we have a registered mapper?
  113. const CapabilityMapper* mapper = CapabilityMappers::instance().find(cap);
  114. if (! mapper) // capability neither supported nor mapped
  115. {
  116. LL_ERRS("capListener") << "unsupported capability '" << cap << "' request to '"
  117. << getCapAPI().getName() << "' on region\n"
  118. << mProvider.getDescription()
  119. << LL_ENDL;
  120. }
  121. else if (! mapper->getReplyName().empty()) // mapper expects reply support
  122. {
  123. LL_ERRS("capListener") << "Mapper for capability '" << cap
  124. << "' requires unimplemented support for reply message '"
  125. << mapper->getReplyName()
  126. << "' on '" << getCapAPI().getName() << "' on region\n"
  127. << mProvider.getDescription()
  128. << LL_ENDL;
  129. }
  130. else
  131. {
  132. LL_INFOS("capListener") << "fallback invoked for capability '" << cap
  133. << "' request to '" << getCapAPI().getName()
  134. << "' on region\n" << mProvider.getDescription()
  135. << LL_ENDL;
  136. mapper->buildMessage(mMessageSystem, mAgentID, mSessionID, cap, payload);
  137. mMessageSystem->sendReliable(mProvider.getHost());
  138. }
  139. }
  140. return false;
  141. }
  142. LLCapabilityListener::CapabilityMapper::CapabilityMapper(const std::string& cap, const std::string& reply):
  143. mCapName(cap),
  144. mReplyName(reply)
  145. {
  146. LLCapabilityListener::CapabilityMappers::instance().registerMapper(this);
  147. }
  148. LLCapabilityListener::CapabilityMapper::~CapabilityMapper()
  149. {
  150. LLCapabilityListener::CapabilityMappers::instance().unregisterMapper(this);
  151. }
  152. LLSD LLCapabilityListener::CapabilityMapper::readResponse(LLMessageSystem* messageSystem) const
  153. {
  154. return LLSD();
  155. }
  156. LLCapabilityListener::CapabilityMappers::CapabilityMappers() {}
  157. void LLCapabilityListener::CapabilityMappers::registerMapper(const LLCapabilityListener::CapabilityMapper* mapper)
  158. {
  159. // Try to insert a new map entry by which we can look up the passed mapper
  160. // instance.
  161. std::pair<CapabilityMap::iterator, bool> inserted =
  162. mMap.insert(CapabilityMap::value_type(mapper->getCapName(), mapper));
  163. // If we already have a mapper for that name, insert() merely located the
  164. // existing iterator and returned false. It is a coding error to try to
  165. // register more than one mapper for the same capability name.
  166. if (! inserted.second)
  167. {
  168. throw DupCapMapper(std::string("Duplicate capability name ") + mapper->getCapName());
  169. }
  170. }
  171. void LLCapabilityListener::CapabilityMappers::unregisterMapper(const LLCapabilityListener::CapabilityMapper* mapper)
  172. {
  173. CapabilityMap::iterator found = mMap.find(mapper->getCapName());
  174. if (found != mMap.end())
  175. {
  176. mMap.erase(found);
  177. }
  178. }
  179. const LLCapabilityListener::CapabilityMapper*
  180. LLCapabilityListener::CapabilityMappers::find(const std::string& cap) const
  181. {
  182. CapabilityMap::const_iterator found = mMap.find(cap);
  183. if (found != mMap.end())
  184. {
  185. return found->second;
  186. }
  187. return NULL;
  188. }