llsdmessage.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:6k
源码类别:

游戏引擎

开发平台:

C++ Builder

  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=viewergpl$
  8.  * 
  9.  * Copyright (c) 2008-2010, Linden Research, Inc.
  10.  * 
  11.  * Second Life Viewer Source Code
  12.  * The source code in this file ("Source Code") is provided by Linden Lab
  13.  * to you under the terms of the GNU General Public License, version 2.0
  14.  * ("GPL"), unless you have obtained a separate licensing agreement
  15.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  16.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18.  * 
  19.  * There are special exceptions to the terms and conditions of the GPL as
  20.  * it is applied to this Source Code. View the full text of the exception
  21.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  22.  * online at
  23.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24.  * 
  25.  * By copying, modifying or distributing this software, you acknowledge
  26.  * that you have read and understood your obligations described above,
  27.  * and agree to abide by those obligations.
  28.  * 
  29.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31.  * COMPLETENESS OR PERFORMANCE.
  32.  * $/LicenseInfo$
  33.  */
  34. #if LL_WINDOWS
  35. #pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
  36. #endif
  37. // Precompiled header
  38. #include "linden_common.h"
  39. // associated header
  40. #include "llsdmessage.h"
  41. // STL headers
  42. // std headers
  43. // external library headers
  44. // other Linden headers
  45. #include "llevents.h"
  46. #include "llsdserialize.h"
  47. #include "llhttpclient.h"
  48. #include "llmessageconfig.h"
  49. #include "llhost.h"
  50. #include "message.h"
  51. #include "llsdutil.h"
  52. // Declare a static LLSDMessage instance to ensure that we have a listener as
  53. // soon as someone tries to post on our canonical LLEventPump name.
  54. static LLSDMessage httpListener;
  55. LLSDMessage::LLSDMessage():
  56.     // Instantiating our own local LLEventPump with a string name the
  57.     // constructor is NOT allowed to tweak is a way of ensuring Singleton
  58.     // semantics: attempting to instantiate a second LLSDMessage object would
  59.     // throw LLEventPump::DupPumpName.
  60.     mEventPump("LLHTTPClient")
  61. {
  62.     mEventPump.listen("self", boost::bind(&LLSDMessage::httpListener, this, _1));
  63. }
  64. bool LLSDMessage::httpListener(const LLSD& request)
  65. {
  66.     // Extract what we want from the request object. We do it all up front
  67.     // partly to document what we expect.
  68.     LLSD::String url(request["url"]);
  69.     LLSD payload(request["payload"]);
  70.     LLSD::String reply(request["reply"]);
  71.     LLSD::String error(request["error"]);
  72.     LLSD::Real timeout(request["timeout"]);
  73.     // If the LLSD doesn't even have a "url" key, we doubt it was intended for
  74.     // this listener.
  75.     if (url.empty())
  76.     {
  77.         std::ostringstream out;
  78.         out << "request event without 'url' key to '" << mEventPump.getName() << "'";
  79.         throw ArgError(out.str());
  80.     }
  81.     // Establish default timeout. This test relies on LLSD::asReal() returning
  82.     // exactly 0.0 for an undef value.
  83.     if (! timeout)
  84.     {
  85.         timeout = HTTP_REQUEST_EXPIRY_SECS;
  86.     }
  87.     LLHTTPClient::post(url, payload,
  88.                        new LLSDMessage::EventResponder(LLEventPumps::instance(),
  89.                                                        request,
  90.                                                        url, "POST", reply, error),
  91.                        LLSD(),      // headers
  92.                        timeout);
  93.     return false;
  94. }
  95. void LLSDMessage::EventResponder::result(const LLSD& data)
  96. {
  97.     // If our caller passed an empty replyPump name, they're not
  98.     // listening: this is a fire-and-forget message. Don't bother posting
  99.     // to the pump whose name is "".
  100.     if (! mReplyPump.empty())
  101.     {
  102.         LLSD response(data);
  103.         mReqID.stamp(response);
  104.         mPumps.obtain(mReplyPump).post(response);
  105.     }
  106.     else                            // default success handling
  107.     {
  108.         LL_INFOS("LLSDMessage::EventResponder")
  109.             << "'" << mMessage << "' to '" << mTarget << "' succeeded"
  110.             << LL_ENDL;
  111.     }
  112. }
  113. void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
  114. {
  115.     // If our caller passed an empty errorPump name, they're not
  116.     // listening: "default error handling is acceptable." Only post to an
  117.     // explicit pump name.
  118.     if (! mErrorPump.empty())
  119.     {
  120.         LLSD info(mReqID.makeResponse());
  121.         info["target"]  = mTarget;
  122.         info["message"] = mMessage;
  123.         info["status"]  = LLSD::Integer(status);
  124.         info["reason"]  = reason;
  125.         info["content"] = content;
  126.         mPumps.obtain(mErrorPump).post(info);
  127.     }
  128.     else                        // default error handling
  129.     {
  130.         // convention seems to be to use llinfos, but that seems a bit casual?
  131.         LL_WARNS("LLSDMessage::EventResponder")
  132.             << "'" << mMessage << "' to '" << mTarget
  133.             << "' failed with code " << status << ": " << reason << 'n'
  134.             << ll_pretty_print_sd(content)
  135.             << LL_ENDL;
  136.     }
  137. }
  138. LLSDMessage::ResponderAdapter::ResponderAdapter(LLHTTPClient::ResponderPtr responder,
  139.                                                 const std::string& name):
  140.     mResponder(responder),
  141.     mReplyPump(name + ".reply", true), // tweak name for uniqueness
  142.     mErrorPump(name + ".error", true)
  143. {
  144.     mReplyPump.listen("self", boost::bind(&ResponderAdapter::listener, this, _1, true));
  145.     mErrorPump.listen("self", boost::bind(&ResponderAdapter::listener, this, _1, false));
  146. }
  147. bool LLSDMessage::ResponderAdapter::listener(const LLSD& payload, bool success)
  148. {
  149.     if (success)
  150.     {
  151.         mResponder->result(payload);
  152.     }
  153.     else
  154.     {
  155.         mResponder->errorWithContent(payload["status"].asInteger(), payload["reason"], payload["content"]);
  156.     }
  157.     /*---------------- MUST BE LAST STATEMENT BEFORE RETURN ----------------*/
  158.     delete this;
  159.     // Destruction of mResponder will usually implicitly free its referent as well
  160.     /*------------------------- NOTHING AFTER THIS -------------------------*/
  161.     return false;
  162. }
  163. void LLSDMessage::link()
  164. {
  165. }