PageRenderTime 44ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llmessage/llsdmessage.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 170 lines | 104 code | 11 blank | 55 comment | 7 complexity | 2497ddeafb85cf4daf8df094a029be49 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llsdmessage.cpp
  3. * @author Nat Goodspeed
  4. * @date 2008-10-31
  5. * @brief Implementation for llsdmessage.
  6. *
  7. * $LicenseInfo:firstyear=2008&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. #if LL_WINDOWS
  29. #pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
  30. #endif
  31. // Precompiled header
  32. #include "linden_common.h"
  33. // associated header
  34. #include "llsdmessage.h"
  35. // STL headers
  36. // std headers
  37. // external library headers
  38. // other Linden headers
  39. #include "llevents.h"
  40. #include "llsdserialize.h"
  41. #include "llhttpclient.h"
  42. #include "llmessageconfig.h"
  43. #include "llhost.h"
  44. #include "message.h"
  45. #include "llsdutil.h"
  46. // Declare a static LLSDMessage instance to ensure that we have a listener as
  47. // soon as someone tries to post on our canonical LLEventPump name.
  48. static LLSDMessage httpListener;
  49. LLSDMessage::LLSDMessage():
  50. // Instantiating our own local LLEventPump with a string name the
  51. // constructor is NOT allowed to tweak is a way of ensuring Singleton
  52. // semantics: attempting to instantiate a second LLSDMessage object would
  53. // throw LLEventPump::DupPumpName.
  54. mEventPump("LLHTTPClient")
  55. {
  56. mEventPump.listen("self", boost::bind(&LLSDMessage::httpListener, this, _1));
  57. }
  58. bool LLSDMessage::httpListener(const LLSD& request)
  59. {
  60. // Extract what we want from the request object. We do it all up front
  61. // partly to document what we expect.
  62. LLSD::String url(request["url"]);
  63. LLSD payload(request["payload"]);
  64. LLSD::String reply(request["reply"]);
  65. LLSD::String error(request["error"]);
  66. LLSD::Real timeout(request["timeout"]);
  67. // If the LLSD doesn't even have a "url" key, we doubt it was intended for
  68. // this listener.
  69. if (url.empty())
  70. {
  71. std::ostringstream out;
  72. out << "request event without 'url' key to '" << mEventPump.getName() << "'";
  73. throw ArgError(out.str());
  74. }
  75. // Establish default timeout. This test relies on LLSD::asReal() returning
  76. // exactly 0.0 for an undef value.
  77. if (! timeout)
  78. {
  79. timeout = HTTP_REQUEST_EXPIRY_SECS;
  80. }
  81. LLHTTPClient::post(url, payload,
  82. new LLSDMessage::EventResponder(LLEventPumps::instance(),
  83. request,
  84. url, "POST", reply, error),
  85. LLSD(), // headers
  86. timeout);
  87. return false;
  88. }
  89. void LLSDMessage::EventResponder::result(const LLSD& data)
  90. {
  91. // If our caller passed an empty replyPump name, they're not
  92. // listening: this is a fire-and-forget message. Don't bother posting
  93. // to the pump whose name is "".
  94. if (! mReplyPump.empty())
  95. {
  96. LLSD response(data);
  97. mReqID.stamp(response);
  98. mPumps.obtain(mReplyPump).post(response);
  99. }
  100. else // default success handling
  101. {
  102. LL_INFOS("LLSDMessage::EventResponder")
  103. << "'" << mMessage << "' to '" << mTarget << "' succeeded"
  104. << LL_ENDL;
  105. }
  106. }
  107. void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
  108. {
  109. // If our caller passed an empty errorPump name, they're not
  110. // listening: "default error handling is acceptable." Only post to an
  111. // explicit pump name.
  112. if (! mErrorPump.empty())
  113. {
  114. LLSD info(mReqID.makeResponse());
  115. info["target"] = mTarget;
  116. info["message"] = mMessage;
  117. info["status"] = LLSD::Integer(status);
  118. info["reason"] = reason;
  119. info["content"] = content;
  120. mPumps.obtain(mErrorPump).post(info);
  121. }
  122. else // default error handling
  123. {
  124. // convention seems to be to use llinfos, but that seems a bit casual?
  125. LL_WARNS("LLSDMessage::EventResponder")
  126. << "'" << mMessage << "' to '" << mTarget
  127. << "' failed with code " << status << ": " << reason << '\n'
  128. << ll_pretty_print_sd(content)
  129. << LL_ENDL;
  130. }
  131. }
  132. LLSDMessage::ResponderAdapter::ResponderAdapter(LLHTTPClient::ResponderPtr responder,
  133. const std::string& name):
  134. mResponder(responder),
  135. mReplyPump(name + ".reply", true), // tweak name for uniqueness
  136. mErrorPump(name + ".error", true)
  137. {
  138. mReplyPump.listen("self", boost::bind(&ResponderAdapter::listener, this, _1, true));
  139. mErrorPump.listen("self", boost::bind(&ResponderAdapter::listener, this, _1, false));
  140. }
  141. bool LLSDMessage::ResponderAdapter::listener(const LLSD& payload, bool success)
  142. {
  143. if (success)
  144. {
  145. mResponder->result(payload);
  146. }
  147. else
  148. {
  149. mResponder->errorWithContent(payload["status"].asInteger(), payload["reason"], payload["content"]);
  150. }
  151. /*---------------- MUST BE LAST STATEMENT BEFORE RETURN ----------------*/
  152. delete this;
  153. // Destruction of mResponder will usually implicitly free its referent as well
  154. /*------------------------- NOTHING AFTER THIS -------------------------*/
  155. return false;
  156. }
  157. void LLSDMessage::link()
  158. {
  159. }