PageRenderTime 228ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llmessage/llsdmessage.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 166 lines | 59 code | 16 blank | 91 comment | 0 complexity | d19a409cb5d2d0548f18288d199a0d61 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llsdmessage.h
  3. * @author Nat Goodspeed
  4. * @date 2008-10-30
  5. * @brief API intended to unify sending capability, UDP and TCP messages:
  6. * https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes
  7. *
  8. * $LicenseInfo:firstyear=2008&license=viewerlgpl$
  9. * Second Life Viewer Source Code
  10. * Copyright (C) 2010, Linden Research, Inc.
  11. *
  12. * This library is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU Lesser General Public
  14. * License as published by the Free Software Foundation;
  15. * version 2.1 of the License only.
  16. *
  17. * This library is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * Lesser General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Lesser General Public
  23. * License along with this library; if not, write to the Free Software
  24. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  25. *
  26. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  27. * $/LicenseInfo$
  28. */
  29. #if ! defined(LL_LLSDMESSAGE_H)
  30. #define LL_LLSDMESSAGE_H
  31. #include "llerror.h" // LOG_CLASS()
  32. #include "llevents.h" // LLEventPumps
  33. #include "llhttpclient.h"
  34. #include <string>
  35. #include <stdexcept>
  36. class LLSD;
  37. /**
  38. * Class managing the messaging API described in
  39. * https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes
  40. */
  41. class LLSDMessage
  42. {
  43. LOG_CLASS(LLSDMessage);
  44. public:
  45. LLSDMessage();
  46. /// Exception if you specify arguments badly
  47. struct ArgError: public std::runtime_error
  48. {
  49. ArgError(const std::string& what):
  50. std::runtime_error(std::string("ArgError: ") + what) {}
  51. };
  52. /**
  53. * The response idiom used by LLSDMessage -- LLEventPump names on which to
  54. * post reply or error -- is designed for the case in which your
  55. * reply/error handlers are methods on the same class as the method
  56. * sending the message. Any state available to the sending method that
  57. * must be visible to the reply/error methods can conveniently be stored
  58. * on that class itself, if it's not already.
  59. *
  60. * The LLHTTPClient::Responder idiom requires a separate instance of a
  61. * separate class so that it can dispatch to the code of interest by
  62. * calling canonical virtual methods. Interesting state must be copied
  63. * into that new object.
  64. *
  65. * With some trepidation, because existing response code is packaged in
  66. * LLHTTPClient::Responder subclasses, we provide this adapter class
  67. * <i>for transitional purposes only.</i> Instantiate a new heap
  68. * ResponderAdapter with your new LLHTTPClient::ResponderPtr. Pass
  69. * ResponderAdapter::getReplyName() and/or getErrorName() in your
  70. * LLSDMessage (or LLViewerRegion::getCapAPI()) request event. The
  71. * ResponderAdapter will call the appropriate Responder method, then
  72. * @c delete itself.
  73. */
  74. class ResponderAdapter
  75. {
  76. public:
  77. /**
  78. * Bind the new LLHTTPClient::Responder subclass instance.
  79. *
  80. * Passing the constructor a name other than the default is only
  81. * interesting if you suspect some usage will lead to an exception or
  82. * log message.
  83. */
  84. ResponderAdapter(LLHTTPClient::ResponderPtr responder,
  85. const std::string& name="ResponderAdapter");
  86. /// EventPump name on which LLSDMessage should post reply event
  87. std::string getReplyName() const { return mReplyPump.getName(); }
  88. /// EventPump name on which LLSDMessage should post error event
  89. std::string getErrorName() const { return mErrorPump.getName(); }
  90. private:
  91. // We have two different LLEventStreams, though we route them both to
  92. // the same listener, so that we can bind an extra flag identifying
  93. // which case (reply or error) reached that listener.
  94. bool listener(const LLSD&, bool success);
  95. LLHTTPClient::ResponderPtr mResponder;
  96. LLEventStream mReplyPump, mErrorPump;
  97. };
  98. /**
  99. * Force our implementation file to be linked with caller. The .cpp file
  100. * contains a static instance of this class, which must be linked into the
  101. * executable to support the canonical listener. But since the primary
  102. * interface to that static instance is via a named LLEventPump rather
  103. * than by direct reference, the linker doesn't necessarily perceive the
  104. * necessity to bring in the translation unit. Referencing this dummy
  105. * method forces the issue.
  106. */
  107. static void link();
  108. private:
  109. friend class LLCapabilityListener;
  110. /// Responder used for internal purposes by LLSDMessage and
  111. /// LLCapabilityListener. Others should use higher-level APIs.
  112. class EventResponder: public LLHTTPClient::Responder
  113. {
  114. public:
  115. /**
  116. * LLHTTPClient::Responder that dispatches via named LLEventPump instances.
  117. * We bind LLEventPumps, even though it's an LLSingleton, for testability.
  118. * We bind the string names of the desired LLEventPump instances rather
  119. * than actually obtain()ing them so we only obtain() the one we're going
  120. * to use. If the caller doesn't bother to listen() on it, the other pump
  121. * may never materialize at all.
  122. * @a target and @a message are only to clarify error processing.
  123. * For a capability message, @a target should be the region description,
  124. * @a message should be the capability name.
  125. * For a service with a visible URL, pass the URL as @a target and the HTTP verb
  126. * (e.g. "POST") as @a message.
  127. */
  128. EventResponder(LLEventPumps& pumps,
  129. const LLSD& request,
  130. const std::string& target, const std::string& message,
  131. const std::string& replyPump, const std::string& errorPump):
  132. mPumps(pumps),
  133. mReqID(request),
  134. mTarget(target),
  135. mMessage(message),
  136. mReplyPump(replyPump),
  137. mErrorPump(errorPump)
  138. {}
  139. virtual void result(const LLSD& data);
  140. virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
  141. private:
  142. LLEventPumps& mPumps;
  143. LLReqID mReqID;
  144. const std::string mTarget, mMessage, mReplyPump, mErrorPump;
  145. };
  146. private:
  147. bool httpListener(const LLSD&);
  148. LLEventStream mEventPump;
  149. };
  150. #endif /* ! defined(LL_LLSDMESSAGE_H) */