From f6ba7514d2392bfb5bbbe8b003b4b860118fddc5 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Thu, 26 Mar 2015 10:34:19 -0700 Subject: Fix line endings on appearancemgr and added LLCore::Http to llAgent. --- indra/newview/llagent.cpp | 156 +++++++++++++++++++++++++++------------------- 1 file changed, 92 insertions(+), 64 deletions(-) (limited to 'indra/newview/llagent.cpp') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index f151b15e29..ff0e2c42c1 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -95,6 +95,8 @@ #include "lscript_byteformat.h" #include "stringize.h" #include "boost/foreach.hpp" +#include "llhttpsdhandler.h" +#include "llcorehttputil.h" using namespace LLAvatarAppearanceDefines; @@ -323,6 +325,7 @@ bool LLAgent::isMicrophoneOn(const LLSD& sdname) // For a toggled version, see viewer.h for the // TOGGLE_HACKED_GODLIKE_VIEWER define, instead. // ************************************************************ +bool LLAgent::mActive = true; // Constructors and Destructors @@ -361,7 +364,12 @@ LLAgent::LLAgent() : mMaturityPreferenceNumRetries(0U), mLastKnownRequestMaturity(SIM_ACCESS_MIN), mLastKnownResponseMaturity(SIM_ACCESS_MIN), - mTeleportState( TELEPORT_NONE ), + mHttpRequest(), + mHttpHeaders(), + mHttpOptions(), + mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID), + mHttpPriority(0), + mTeleportState(TELEPORT_NONE), mRegionp(NULL), mAgentOriginGlobal(), @@ -459,6 +467,15 @@ void LLAgent::init() mTeleportFailedSlot = LLViewerParcelMgr::getInstance()->setTeleportFailedCallback(boost::bind(&LLAgent::handleTeleportFailed, this)); } + LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp()); + + mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest()); + mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false); + mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false); + mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_AVATAR); + + doOnIdleRepeating(boost::bind(&LLAgent::onIdle, this)); + mInitialized = TRUE; } @@ -467,6 +484,7 @@ void LLAgent::init() //----------------------------------------------------------------------------- void LLAgent::cleanup() { + mActive = false; mRegionp = NULL; if (mTeleportFinishedSlot.connected()) { @@ -498,6 +516,17 @@ LLAgent::~LLAgent() mTeleportSourceSLURL = NULL; } +//----------------------------------------------------------------------------- +// Idle processing +//----------------------------------------------------------------------------- +bool LLAgent::onIdle() +{ + if (!LLAgent::mActive) + return true; + mHttpRequest->update(0L); + return false; +} + // Handle any actions that need to be performed when the main app gains focus // (such as through alt-tab). //----------------------------------------------------------------------------- @@ -2515,66 +2544,61 @@ int LLAgent::convertTextToMaturity(char text) return LLAgentAccess::convertTextToMaturity(text); } -class LLMaturityPreferencesResponder : public LLHTTPClient::Responder +//========================================================================= +class LLMaturityHttpHandler : public LLHttpSDHandler { - LOG_CLASS(LLMaturityPreferencesResponder); public: - LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity); - virtual ~LLMaturityPreferencesResponder(); + LLMaturityHttpHandler(const std::string& capabilityURL, LLAgent *agent, U8 preferred, U8 previous): + LLHttpSDHandler(capabilityURL), + mAgent(agent), + mPreferredMaturity(preferred), + mPreviousMaturity(previous) + { } -protected: - virtual void httpSuccess(); - virtual void httpFailure(); + virtual ~LLMaturityHttpHandler() + { } protected: + virtual void onSuccess(LLCore::HttpResponse * response, LLSD &content); + virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status); private: - U8 parseMaturityFromServerResponse(const LLSD &pContent) const; - - LLAgent *mAgent; - U8 mPreferredMaturity; - U8 mPreviousMaturity; -}; + U8 LLMaturityHttpHandler::parseMaturityFromServerResponse(const LLSD &pContent) const; -LLMaturityPreferencesResponder::LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity) - : LLHTTPClient::Responder(), - mAgent(pAgent), - mPreferredMaturity(pPreferredMaturity), - mPreviousMaturity(pPreviousMaturity) -{ -} + LLAgent * mAgent; + U8 mPreferredMaturity; + U8 mPreviousMaturity; -LLMaturityPreferencesResponder::~LLMaturityPreferencesResponder() -{ -} +}; -void LLMaturityPreferencesResponder::httpSuccess() +//------------------------------------------------------------------------- +void LLMaturityHttpHandler::onSuccess(LLCore::HttpResponse * response, LLSD &content) { - U8 actualMaturity = parseMaturityFromServerResponse(getContent()); + U8 actualMaturity = parseMaturityFromServerResponse(content); if (actualMaturity != mPreferredMaturity) { LL_WARNS() << "while attempting to change maturity preference from '" - << LLViewerRegion::accessToString(mPreviousMaturity) - << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) - << "', the server responded with '" - << LLViewerRegion::accessToString(actualMaturity) - << "' [value:" << static_cast(actualMaturity) - << "], " << dumpResponse() << LL_ENDL; + << LLViewerRegion::accessToString(mPreviousMaturity) + << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) + << "', the server responded with '" + << LLViewerRegion::accessToString(actualMaturity) + << "' [value:" << static_cast(actualMaturity) + << "], " << LL_ENDL; } mAgent->handlePreferredMaturityResult(actualMaturity); } -void LLMaturityPreferencesResponder::httpFailure() +void LLMaturityHttpHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) { - LL_WARNS() << "while attempting to change maturity preference from '" - << LLViewerRegion::accessToString(mPreviousMaturity) - << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) - << "', " << dumpResponse() << LL_ENDL; + LL_WARNS() << "while attempting to change maturity preference from '" + << LLViewerRegion::accessToString(mPreviousMaturity) + << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) + << "', " << LL_ENDL; mAgent->handlePreferredMaturityError(); } -U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent) const +U8 LLMaturityHttpHandler::parseMaturityFromServerResponse(const LLSD &pContent) const { U8 maturity = SIM_ACCESS_MIN; @@ -2595,6 +2619,7 @@ U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &p return maturity; } +//========================================================================= void LLAgent::handlePreferredMaturityResult(U8 pServerMaturity) { @@ -2724,38 +2749,41 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) // Update the last know maturity request mLastKnownRequestMaturity = pPreferredMaturity; - // Create a response handler - LLHTTPClient::ResponderPtr responderPtr = LLHTTPClient::ResponderPtr(new LLMaturityPreferencesResponder(this, pPreferredMaturity, mLastKnownResponseMaturity)); - // If we don't have a region, report it as an error if (getRegion() == NULL) { - responderPtr->failureResult(0U, "region is not defined", LLSD()); + LL_WARNS("Agent") << "Region is not defined, can not change Maturity setting." << LL_ENDL; + return; } - else + std::string url = getRegion()->getCapability("UpdateAgentInformation"); + + // If the capability is not defined, report it as an error + if (url.empty()) { - // Find the capability to send maturity preference - std::string url = getRegion()->getCapability("UpdateAgentInformation"); + LL_WARNS("Agent") << "'UpdateAgentInformation' is not defined for region" << LL_ENDL; + return; + } - // If the capability is not defined, report it as an error - if (url.empty()) - { - responderPtr->failureResult(0U, - "capability 'UpdateAgentInformation' is not defined for region", LLSD()); - } - else - { - // Set new access preference - LLSD access_prefs = LLSD::emptyMap(); - access_prefs["max"] = LLViewerRegion::accessToShortString(pPreferredMaturity); - - LLSD body = LLSD::emptyMap(); - body["access_prefs"] = access_prefs; - LL_INFOS() << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity) - << "' via capability to: " << url << LL_ENDL; - LLSD headers; - LLHTTPClient::post(url, body, responderPtr, headers, 30.0f); - } + LLMaturityHttpHandler * handler = new LLMaturityHttpHandler(url, this, pPreferredMaturity, mLastKnownResponseMaturity); + + LLSD access_prefs = LLSD::emptyMap(); + access_prefs["max"] = LLViewerRegion::accessToShortString(pPreferredMaturity); + + LLSD postData = LLSD::emptyMap(); + postData["access_prefs"] = access_prefs; + LL_INFOS() << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity) + << "' via capability to: " << url << LL_ENDL; + + LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, + mHttpPolicy, mHttpPriority, url, + postData, mHttpOptions, mHttpHeaders, handler); + + if (handle == LLCORE_HTTP_HANDLE_INVALID) + { + delete handler; + LLCore::HttpStatus status = mHttpRequest->getStatus(); + LL_WARNS("Avatar") << "Maturity request post failed Reason " << status.toTerseString() + << " \"" << status.toString() << "\"" << LL_ENDL; } } } -- cgit v1.3 From 97b93179692b764aba7eee571f1b557f6f8070db Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Thu, 26 Mar 2015 13:32:09 -0700 Subject: Create trivial handler for SD Messages, method in LLAgent for posting HTTP requests. --- indra/llmessage/llhttpsdhandler.cpp | 21 +++++++++++++++++++++ indra/llmessage/llhttpsdhandler.h | 20 +++++++++++++++++++- indra/newview/llagent.cpp | 35 +++++++++++++++++++++++++++-------- indra/newview/llagent.h | 15 +++++++++++++++ indra/newview/llappcorehttp.cpp | 6 +++--- indra/newview/llappcorehttp.h | 2 +- indra/newview/llappearancemgr.cpp | 3 ++- 7 files changed, 88 insertions(+), 14 deletions(-) (limited to 'indra/newview/llagent.cpp') diff --git a/indra/llmessage/llhttpsdhandler.cpp b/indra/llmessage/llhttpsdhandler.cpp index 18daf443ee..0d385d6497 100644 --- a/indra/llmessage/llhttpsdhandler.cpp +++ b/indra/llmessage/llhttpsdhandler.cpp @@ -82,3 +82,24 @@ void LLHttpSDHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons delete this; } +//======================================================================== +LLHttpSDGenericHandler::LLHttpSDGenericHandler(const LLURI &uri, const std::string &caps) : + LLHttpSDHandler(uri), + mCaps(caps) +{ +} + +void LLHttpSDGenericHandler::onSuccess(LLCore::HttpResponse * response, LLSD &content) +{ + LL_DEBUGS() << mCaps << " Success." << LL_ENDL; +} + +void LLHttpSDGenericHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) +{ + LL_WARNS() + << "\n--------------------------------------------------------------------------\n" + << mCaps << " Error[" << status.toULong() << "] cannot access cap with url '" + << getUri() << "' because " << status.toString() + << "\n--------------------------------------------------------------------------" + << LL_ENDL; +} diff --git a/indra/llmessage/llhttpsdhandler.h b/indra/llmessage/llhttpsdhandler.h index 7b7da61b3c..b3eb7d6145 100644 --- a/indra/llmessage/llhttpsdhandler.h +++ b/indra/llmessage/llhttpsdhandler.h @@ -30,8 +30,12 @@ #include "httphandler.h" #include "lluri.h" +/// Handler class LLCore's HTTP library. Splitting with separate success and +/// failure routines and parsing the result body into LLSD on success. It +/// is intended to be subclassed for specific capability handling. /// -/// +// *TODO: This class self deletes at the end of onCompleted method. This is +// less than ideal and should be revisited. class LLHttpSDHandler : public LLCore::HttpHandler { public: @@ -52,5 +56,19 @@ private: LLURI mUri; }; +/// A trivial implementation of LLHttpSDHandler. This success and failure +/// methods log the action taken, the URI accessed and the status code retuned +/// in the response. +class LLHttpSDGenericHandler : public LLHttpSDHandler +{ +public: + LLHttpSDGenericHandler(const LLURI &uri, const std::string &action); + +protected: + virtual void onSuccess(LLCore::HttpResponse * response, LLSD &content); + virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status); +private: + std::string mCaps; +}; #endif \ No newline at end of file diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index ff0e2c42c1..81387fb927 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -472,7 +472,7 @@ void LLAgent::init() mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest()); mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false); mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false); - mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_AVATAR); + mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_AGENT); doOnIdleRepeating(boost::bind(&LLAgent::onIdle, this)); @@ -2563,7 +2563,7 @@ protected: virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status); private: - U8 LLMaturityHttpHandler::parseMaturityFromServerResponse(const LLSD &pContent) const; + U8 parseMaturityFromServerResponse(const LLSD &pContent) const; LLAgent * mAgent; U8 mPreferredMaturity; @@ -2774,20 +2774,39 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) LL_INFOS() << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity) << "' via capability to: " << url << LL_ENDL; - LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, - mHttpPolicy, mHttpPriority, url, - postData, mHttpOptions, mHttpHeaders, handler); + LLCore::HttpHandle handle = requestPostCapibility("UpdateAgentInformation", url, postData, handler); if (handle == LLCORE_HTTP_HANDLE_INVALID) { delete handler; - LLCore::HttpStatus status = mHttpRequest->getStatus(); - LL_WARNS("Avatar") << "Maturity request post failed Reason " << status.toTerseString() - << " \"" << status.toString() << "\"" << LL_ENDL; + LL_WARNS("Avatar") << "Maturity request post failed." << LL_ENDL; } } } +LLCore::HttpHandle LLAgent::requestPostCapibility(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr) +{ + LLHttpSDHandler * handler = (usrhndlr) ? usrhndlr : new LLHttpSDGenericHandler(url, cap); + LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, + mHttpPolicy, mHttpPriority, url, + postData, mHttpOptions, mHttpHeaders, handler); + + if (handle == LLCORE_HTTP_HANDLE_INVALID) + { + if (!usrhndlr) + delete handler; + LLCore::HttpStatus status = mHttpRequest->getStatus(); + LL_WARNS("Avatar") << "'" << cap << "' request POST failed. Reason " + << status.toTerseString() << " \"" << status.toString() << "\"" << LL_ENDL; + } + return handle; +} + +//LLCore::HttpHandle LLAgent::httpGetCapibility(const std::string &cap, const LLURI &uri, LLHttpSDHandler *usrhndlr) +//{ +//} + + BOOL LLAgent::getAdminOverride() const { return mAgentAccess->getAdminOverride(); diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 278e4c0fa1..6b636a2dc0 100755 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -63,6 +63,7 @@ class LLSLURL; class LLPauseRequestHandle; class LLUIColor; class LLTeleportRequest; +class LLHttpSDHandler; typedef boost::shared_ptr LLTeleportRequestPtr; @@ -917,6 +918,20 @@ public: ** ** *******************************************************************************/ +/******************************************************************************** + ** ** + ** UTILITY + **/ +public: + /// Utilities for allowing the the agent sub managers to post and get via + /// HTTP using the agent's policy settings and headers. + LLCore::HttpHandle requestPostCapibility(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr = NULL); + //LLCore::HttpHandle httpGetCapibility(const std::string &cap, const LLURI &uri, LLHttpSDHandler *usrhndlr = NULL); + +/** Utility + ** ** + *******************************************************************************/ + /******************************************************************************** ** ** ** DEBUGGING diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index 8da78a45a6..cd9166f7b7 100755 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -103,10 +103,10 @@ static const struct "RenderMaterials", "material manager requests" }, - { // AP_AVATAR + { // AP_AGENT 2, 1, 32, 0, true, - "Avatar", - "Avatar requests" + "Agent", + "Agent requests" } }; diff --git a/indra/newview/llappcorehttp.h b/indra/newview/llappcorehttp.h index 95b56100a6..410d7c6b07 100755 --- a/indra/newview/llappcorehttp.h +++ b/indra/newview/llappcorehttp.h @@ -185,7 +185,7 @@ public: /// Concurrency: mid /// Request rate: low /// Pipelined: yes - AP_AVATAR, + AP_AGENT, AP_COUNT // Must be last }; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index bb4228dbb2..ae758609ab 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3442,6 +3442,7 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() llassert(cof_version >= gAgentAvatarp->mLastUpdateRequestCOFVersion); gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version; + // *TODO: use the unified call in LLAgent (?) LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, mHttpPolicy, mHttpPriority, url, postData, mHttpOptions, mHttpHeaders, handler); @@ -3778,7 +3779,7 @@ LLAppearanceMgr::LLAppearanceMgr(): mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest()); mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false); mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false); - mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_AVATAR); + mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_AGENT); LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); // unlock outfit on save operation completed -- cgit v1.3 From 735364038767694ea29d9b6a168410e6482cc9c2 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Fri, 27 Mar 2015 17:00:02 -0700 Subject: first set of chnages from code review from Nat --- indra/llcorehttp/_httpoprequest.cpp | 10 +- indra/llcorehttp/_httpoprequest.h | 5 +- indra/llcorehttp/_httppolicyglobal.cpp | 4 +- indra/llcorehttp/_httppolicyglobal.h | 6 +- indra/llcorehttp/_httpservice.cpp | 4 +- indra/llcorehttp/_httpservice.h | 6 +- indra/llcorehttp/httpcommon.h | 75 +++++++------- indra/llcorehttp/httpoptions.cpp | 8 +- indra/llcorehttp/httpoptions.h | 90 ++++++++++------- indra/llcorehttp/httprequest.cpp | 10 +- indra/llcorehttp/httprequest.h | 4 +- indra/llmessage/llhttpsdhandler.cpp | 2 +- indra/llmessage/llhttpsdhandler.h | 4 +- indra/newview/llagent.cpp | 11 ++- indra/newview/llagent.h | 4 +- indra/newview/llagentlanguage.cpp | 2 +- indra/newview/llappcorehttp.cpp | 2 +- indra/newview/llappearancemgr.cpp | 6 +- indra/newview/llavatarrenderinfoaccountant.cpp | 131 ++++++++++++++++++++++++- indra/newview/llavatarrenderinfoaccountant.h | 10 +- indra/newview/llmaterialmgr.cpp | 4 +- 21 files changed, 271 insertions(+), 127 deletions(-) (limited to 'indra/newview/llagent.cpp') diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 48e22468cd..5768fe5a90 100755 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -115,9 +115,8 @@ namespace LLCore { -HttpOpRequest::HttpOpRequest(HttpRequest const * const request) +HttpOpRequest::HttpOpRequest() : HttpOperation(), - mRequest(request), mProcFlags(0U), mReqMethod(HOR_GET), mReqBody(NULL), @@ -490,13 +489,13 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) long follow_redirect(1L); long sslPeerV(0L); long sslHostV(0L); - long dnsCacheTimeout(15L); + long dnsCacheTimeout(-1L); if (mReqOptions) { follow_redirect = mReqOptions->getFollowRedirects() ? 1L : 0L; - sslPeerV = mReqOptions->getSSLVerifyHost() ? 0L : 1L; - sslHostV = mReqOptions->getSSLVerifyHost(); + sslPeerV = mReqOptions->getSSLVerifyPeer() ? 1L : 0L; + sslHostV = mReqOptions->getSSLVerifyHost() ? 2L : 0L; dnsCacheTimeout = mReqOptions->getDNSCacheTimeout(); } code = curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, follow_redirect); @@ -516,7 +515,6 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, dnsCacheTimeout); check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT); - if (gpolicy.mUseLLProxy) { // Use the viewer-based thread-safe API which has a diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h index 7a4b7c189e..e71d1d1edf 100755 --- a/indra/llcorehttp/_httpoprequest.h +++ b/indra/llcorehttp/_httpoprequest.h @@ -66,7 +66,7 @@ class HttpOptions; class HttpOpRequest : public HttpOperation { public: - HttpOpRequest(HttpRequest const * const request); + HttpOpRequest(); protected: virtual ~HttpOpRequest(); // Use release() @@ -165,11 +165,10 @@ protected: static const unsigned int PF_SAVE_HEADERS = 0x00000002U; static const unsigned int PF_USE_RETRY_AFTER = 0x00000004U; - HttpRequest::policyCallback mCallbackSSLVerify; + HttpRequest::policyCallback_t mCallbackSSLVerify; public: // Request data - HttpRequest const * const mRequest; EMethod mReqMethod; std::string mReqURL; BufferArray * mReqBody; diff --git a/indra/llcorehttp/_httppolicyglobal.cpp b/indra/llcorehttp/_httppolicyglobal.cpp index c4ef38a815..3d0df96ade 100755 --- a/indra/llcorehttp/_httppolicyglobal.cpp +++ b/indra/llcorehttp/_httppolicyglobal.cpp @@ -106,7 +106,7 @@ HttpStatus HttpPolicyGlobal::set(HttpRequest::EPolicyOption opt, const std::stri return HttpStatus(); } -HttpStatus HttpPolicyGlobal::set(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback value) +HttpStatus HttpPolicyGlobal::set(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback_t value) { switch (opt) { @@ -169,7 +169,7 @@ HttpStatus HttpPolicyGlobal::get(HttpRequest::EPolicyOption opt, std::string * v } -HttpStatus HttpPolicyGlobal::get(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback * value) const +HttpStatus HttpPolicyGlobal::get(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback_t * value) const { switch (opt) { diff --git a/indra/llcorehttp/_httppolicyglobal.h b/indra/llcorehttp/_httppolicyglobal.h index 1696238814..e02da4386a 100755 --- a/indra/llcorehttp/_httppolicyglobal.h +++ b/indra/llcorehttp/_httppolicyglobal.h @@ -60,10 +60,10 @@ private: public: HttpStatus set(HttpRequest::EPolicyOption opt, long value); HttpStatus set(HttpRequest::EPolicyOption opt, const std::string & value); - HttpStatus set(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback value); + HttpStatus set(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback_t value); HttpStatus get(HttpRequest::EPolicyOption opt, long * value) const; HttpStatus get(HttpRequest::EPolicyOption opt, std::string * value) const; - HttpStatus get(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback * value) const; + HttpStatus get(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback_t * value) const; public: long mConnectionLimit; @@ -72,7 +72,7 @@ public: std::string mHttpProxy; long mTrace; long mUseLLProxy; - HttpRequest::policyCallback mSslCtxCallback; + HttpRequest::policyCallback_t mSslCtxCallback; }; // end class HttpPolicyGlobal } // end namespace LLCore diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp index 7b8aac35a8..252db78c89 100755 --- a/indra/llcorehttp/_httpservice.cpp +++ b/indra/llcorehttp/_httpservice.cpp @@ -415,7 +415,7 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ } HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass, - HttpRequest::policyCallback * ret_value) + HttpRequest::policyCallback_t * ret_value) { HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG); @@ -520,7 +520,7 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ } HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass, - HttpRequest::policyCallback value, HttpRequest::policyCallback * ret_value) + HttpRequest::policyCallback_t value, HttpRequest::policyCallback_t * ret_value) { HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG); diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h index 699a8eaa4f..ac518a5de7 100755 --- a/indra/llcorehttp/_httpservice.h +++ b/indra/llcorehttp/_httpservice.h @@ -209,15 +209,15 @@ protected: HttpStatus getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t, std::string * ret_value); HttpStatus getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t, - HttpRequest::policyCallback * ret_value); + HttpRequest::policyCallback_t * ret_value); HttpStatus setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t, long value, long * ret_value); HttpStatus setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t, const std::string & value, std::string * ret_value); HttpStatus setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t, - HttpRequest::policyCallback value, - HttpRequest::policyCallback * ret_value); + HttpRequest::policyCallback_t value, + HttpRequest::policyCallback_t * ret_value); protected: static const OptionDescriptor sOptionDesc[HttpRequest::PO_LAST]; diff --git a/indra/llcorehttp/httpcommon.h b/indra/llcorehttp/httpcommon.h index 64075f5f20..ada5c1bbe7 100755 --- a/indra/llcorehttp/httpcommon.h +++ b/indra/llcorehttp/httpcommon.h @@ -190,6 +190,7 @@ #include "linden_common.h" // Modifies curl/curl.h interfaces #include "boost/intrusive_ptr.hpp" #include "boost/shared_ptr.hpp" +#include "boost/function.hpp" #include namespace LLCore @@ -294,50 +295,50 @@ struct HttpStatus typedef unsigned short type_enum_t; HttpStatus() - { - mDetails = new Details(LLCORE, HE_SUCCESS); - } + { + mDetails = boost::shared_ptr
(new Details(LLCORE, HE_SUCCESS)); + } HttpStatus(type_enum_t type, short status) - { - mDetails = new Details(type, status); - } + { + mDetails = boost::shared_ptr
(new Details(type, status)); + } HttpStatus(int http_status) - { - mDetails = new Details(http_status, - (http_status >= 200 && http_status <= 299) ? HE_SUCCESS : HE_REPLY_ERROR); - llassert(http_status >= 100 && http_status <= 999); - } + { + mDetails = boost::shared_ptr
(new Details(http_status, + (http_status >= 200 && http_status <= 299) ? HE_SUCCESS : HE_REPLY_ERROR)); + llassert(http_status >= 100 && http_status <= 999); + } HttpStatus(int http_status, const std::string &message) - { - mDetails = new Details(http_status, - (http_status >= 200 && http_status <= 299) ? HE_SUCCESS : HE_REPLY_ERROR); - llassert(http_status >= 100 && http_status <= 999); - mDetails->mMessage = message; - } + { + mDetails = boost::shared_ptr
(new Details(http_status, + (http_status >= 200 && http_status <= 299) ? HE_SUCCESS : HE_REPLY_ERROR)); + llassert(http_status >= 100 && http_status <= 999); + mDetails->mMessage = message; + } HttpStatus(const HttpStatus & rhs) - { - mDetails = new Details(*rhs.mDetails); - } + { + mDetails = rhs.mDetails; + } ~HttpStatus() - { - delete mDetails; - } + { + } HttpStatus & operator=(const HttpStatus & rhs) - { - // Don't care if lhs & rhs are the same object - mDetails->mType = rhs.mDetails->mType; - mDetails->mStatus = rhs.mDetails->mStatus; - mDetails->mMessage = rhs.mDetails->mMessage; - mDetails->mErrorData = rhs.mDetails->mErrorData; - - return *this; - } + { + mDetails = rhs.mDetails; + return *this; + } + + HttpStatus & clone(const HttpStatus &rhs) + { + mDetails = boost::shared_ptr
(new Details(*rhs.mDetails)); + return *this; + } static const type_enum_t EXT_CURL_EASY = 0; ///< mStatus is an error from a curl_easy_*() call static const type_enum_t EXT_CURL_MULTI = 1; ///< mStatus is an error from a curl_multi_*() call @@ -365,8 +366,7 @@ struct HttpStatus /// which will do the wrong thing in conditional expressions. bool operator==(const HttpStatus & rhs) const { - return (mDetails->mType == rhs.mDetails->mType) && - (mDetails->mStatus == rhs.mDetails->mStatus); + return (*mDetails == *rhs.mDetails); } bool operator!=(const HttpStatus & rhs) const @@ -474,6 +474,10 @@ private: mErrorData(rhs.mErrorData) {} + bool operator == (const Details &rhs) const + { + return (mType == rhs.mType) && (mStatus == rhs.mStatus); + } type_enum_t mType; short mStatus; @@ -481,8 +485,7 @@ private: void * mErrorData; }; - //boost::unique_ptr
mDetails; - Details * mDetails; + boost::shared_ptr
mDetails; }; // end struct HttpStatus diff --git a/indra/llcorehttp/httpoptions.cpp b/indra/llcorehttp/httpoptions.cpp index 28c2c25e92..a4d08a80df 100755 --- a/indra/llcorehttp/httpoptions.cpp +++ b/indra/llcorehttp/httpoptions.cpp @@ -42,8 +42,8 @@ HttpOptions::HttpOptions() : RefCounted(true), mUseRetryAfter(HTTP_USE_RETRY_AFTER_DEFAULT), mFollowRedirects(false), mVerifyPeer(false), - mVerifyHost(0), - mDNSCacheTimeout(15) + mVerifyHost(false), + mDNSCacheTimeout(-1L) {} @@ -95,9 +95,9 @@ void HttpOptions::setSSLVerifyPeer(bool verify) mVerifyPeer = verify; } -void HttpOptions::setSSLVerifyHost(unsigned int type) +void HttpOptions::setSSLVerifyHost(bool verify) { - mVerifyHost = llclamp(type, 0, 2); + mVerifyHost = verify; } void HttpOptions::setDNSCacheTimeout(int timeout) diff --git a/indra/llcorehttp/httpoptions.h b/indra/llcorehttp/httpoptions.h index 3b9ad9598b..765d2431bb 100755 --- a/indra/llcorehttp/httpoptions.h +++ b/indra/llcorehttp/httpoptions.h @@ -69,72 +69,86 @@ protected: void operator=(const HttpOptions &); // Not defined public: + // Default: false void setWantHeaders(bool wanted); bool getWantHeaders() const - { - return mWantHeaders; - } + { + return mWantHeaders; + } // Default: 0 void setTrace(int long); int getTrace() const - { - return mTracing; - } + { + return mTracing; + } // Default: 30 void setTimeout(unsigned int timeout); unsigned int getTimeout() const - { - return mTimeout; - } + { + return mTimeout; + } // Default: 0 void setTransferTimeout(unsigned int timeout); unsigned int getTransferTimeout() const - { - return mTransferTimeout; - } + { + return mTransferTimeout; + } + /// Sets the number of retries on an LLCore::HTTPRequest before the + /// request fails. // Default: 8 void setRetries(unsigned int retries); unsigned int getRetries() const - { - return mRetries; - } + { + return mRetries; + } // Default: true void setUseRetryAfter(bool use_retry); bool getUseRetryAfter() const - { - return mUseRetryAfter; - } + { + return mUseRetryAfter; + } - // Default: false + /// Instructs the LLCore::HTTPRequest to follow redirects + /// Default: false void setFollowRedirects(bool follow_redirect); bool getFollowRedirects() const - { - return mFollowRedirects; - } - - void setSSLVerifyPeer(bool verify); + { + return mFollowRedirects; + } + + /// Instructs the LLCore::HTTPRequest to verify that the exchanged security + /// certificate is authentic. + /// Default: false + void setSSLVerifyPeer(bool verify); bool getSSLVerifyPeer() const - { - return mVerifyPeer; - } - - void setSSLVerifyHost(unsigned int type); - unsigned int getSSLVerifyHost() const - { - return mVerifyHost; - } - + { + return mVerifyPeer; + } + + /// Instructs the LLCore::HTTPRequest to verify that the name in the + /// security certificate matches the name of the host contacted. + /// Default: false + void setSSLVerifyHost(bool verify); + bool getSSLVerifyHost() const + { + return mVerifyHost; + } + + /// Sets the time for DNS name caching in seconds. Setting this value + /// to 0 will disable name caching. Setting this value to -1 causes the + /// name cache to never time out. + /// Default: -1 void setDNSCacheTimeout(int timeout); int getDNSCacheTimeout() const - { - return mDNSCacheTimeout; - } + { + return mDNSCacheTimeout; + } protected: bool mWantHeaders; @@ -145,7 +159,7 @@ protected: bool mUseRetryAfter; bool mFollowRedirects; bool mVerifyPeer; - unsigned int mVerifyHost; + bool mVerifyHost; int mDNSCacheTimeout; }; // end class HttpOptions diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp index 5f1ed3d43b..df8502b947 100755 --- a/indra/llcorehttp/httprequest.cpp +++ b/indra/llcorehttp/httprequest.cpp @@ -117,7 +117,7 @@ HttpStatus HttpRequest::setStaticPolicyOption(EPolicyOption opt, policy_t pclass return HttpService::instanceOf()->setPolicyOption(opt, pclass, value, ret_value); } -HttpStatus HttpRequest::setStaticPolicyOption(EPolicyOption opt, policy_t pclass, policyCallback value, policyCallback * ret_value) +HttpStatus HttpRequest::setStaticPolicyOption(EPolicyOption opt, policy_t pclass, policyCallback_t value, policyCallback_t * ret_value) { if (HttpService::RUNNING == HttpService::instanceOf()->getState()) { @@ -204,7 +204,7 @@ HttpHandle HttpRequest::requestGet(policy_t policy_id, HttpStatus status; HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID); - HttpOpRequest * op = new HttpOpRequest(this); + HttpOpRequest * op = new HttpOpRequest(); if (! (status = op->setupGet(policy_id, priority, url, options, headers))) { op->release(); @@ -238,7 +238,7 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id, HttpStatus status; HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID); - HttpOpRequest * op = new HttpOpRequest(this); + HttpOpRequest * op = new HttpOpRequest(); if (! (status = op->setupGetByteRange(policy_id, priority, url, offset, len, options, headers))) { op->release(); @@ -271,7 +271,7 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id, HttpStatus status; HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID); - HttpOpRequest * op = new HttpOpRequest(this); + HttpOpRequest * op = new HttpOpRequest(); if (! (status = op->setupPost(policy_id, priority, url, body, options, headers))) { op->release(); @@ -304,7 +304,7 @@ HttpHandle HttpRequest::requestPut(policy_t policy_id, HttpStatus status; HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID); - HttpOpRequest * op = new HttpOpRequest(this); + HttpOpRequest * op = new HttpOpRequest(); if (! (status = op->setupPut(policy_id, priority, url, body, options, headers))) { op->release(); diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h index 4cacb3a20b..f7ce82d412 100755 --- a/indra/llcorehttp/httprequest.h +++ b/indra/llcorehttp/httprequest.h @@ -237,7 +237,7 @@ public: /// Prototype for policy based callbacks. The callback methods will be executed /// on the worker thread so no modifications should be made to the HttpHandler object. - typedef HttpStatus(*policyCallback)(const std::string &, HttpHandler const * const, void *); + typedef boost::function policyCallback_t; /// Set a policy option for a global or class parameter at /// startup time (prior to thread start). @@ -255,7 +255,7 @@ public: static HttpStatus setStaticPolicyOption(EPolicyOption opt, policy_t pclass, const std::string & value, std::string * ret_value); static HttpStatus setStaticPolicyOption(EPolicyOption opt, policy_t pclass, - policyCallback value, policyCallback * ret_value);; + policyCallback_t value, policyCallback_t * ret_value);; /// Set a parameter on a class-based policy option. Calls /// made after the start of the servicing thread are diff --git a/indra/llmessage/llhttpsdhandler.cpp b/indra/llmessage/llhttpsdhandler.cpp index 0d385d6497..72ecfe77e2 100644 --- a/indra/llmessage/llhttpsdhandler.cpp +++ b/indra/llmessage/llhttpsdhandler.cpp @@ -89,7 +89,7 @@ LLHttpSDGenericHandler::LLHttpSDGenericHandler(const LLURI &uri, const std::stri { } -void LLHttpSDGenericHandler::onSuccess(LLCore::HttpResponse * response, LLSD &content) +void LLHttpSDGenericHandler::onSuccess(LLCore::HttpResponse * response, const LLSD &content) { LL_DEBUGS() << mCaps << " Success." << LL_ENDL; } diff --git a/indra/llmessage/llhttpsdhandler.h b/indra/llmessage/llhttpsdhandler.h index b3eb7d6145..a2598c9709 100644 --- a/indra/llmessage/llhttpsdhandler.h +++ b/indra/llmessage/llhttpsdhandler.h @@ -49,7 +49,7 @@ public: } protected: - virtual void onSuccess(LLCore::HttpResponse * response, LLSD &content) = 0; + virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content) = 0; virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) = 0; private: @@ -65,7 +65,7 @@ public: LLHttpSDGenericHandler(const LLURI &uri, const std::string &action); protected: - virtual void onSuccess(LLCore::HttpResponse * response, LLSD &content); + virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content); virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status); private: diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 81387fb927..667d530e39 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2559,7 +2559,7 @@ public: { } protected: - virtual void onSuccess(LLCore::HttpResponse * response, LLSD &content); + virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content); virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status); private: @@ -2572,7 +2572,7 @@ private: }; //------------------------------------------------------------------------- -void LLMaturityHttpHandler::onSuccess(LLCore::HttpResponse * response, LLSD &content) +void LLMaturityHttpHandler::onSuccess(LLCore::HttpResponse * response, const LLSD &content) { U8 actualMaturity = parseMaturityFromServerResponse(content); @@ -2774,7 +2774,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) LL_INFOS() << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity) << "' via capability to: " << url << LL_ENDL; - LLCore::HttpHandle handle = requestPostCapibility("UpdateAgentInformation", url, postData, handler); + LLCore::HttpHandle handle = requestPostCapability("UpdateAgentInformation", url, postData, handler); if (handle == LLCORE_HTTP_HANDLE_INVALID) { @@ -2784,7 +2784,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) } } -LLCore::HttpHandle LLAgent::requestPostCapibility(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr) +LLCore::HttpHandle LLAgent::requestPostCapability(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr) { LLHttpSDHandler * handler = (usrhndlr) ? usrhndlr : new LLHttpSDGenericHandler(url, cap); LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, @@ -2793,6 +2793,9 @@ LLCore::HttpHandle LLAgent::requestPostCapibility(const std::string &cap, const if (handle == LLCORE_HTTP_HANDLE_INVALID) { + // If no handler was passed in we delete the handler default handler allocated + // at the start of this function. + // *TODO: Change this metaphore to use boost::shared_ptr<> for handlers. Requires change in LLCore::HTTP if (!usrhndlr) delete handler; LLCore::HttpStatus status = mHttpRequest->getStatus(); diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 6b636a2dc0..26120b52f6 100755 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -925,8 +925,8 @@ public: public: /// Utilities for allowing the the agent sub managers to post and get via /// HTTP using the agent's policy settings and headers. - LLCore::HttpHandle requestPostCapibility(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr = NULL); - //LLCore::HttpHandle httpGetCapibility(const std::string &cap, const LLURI &uri, LLHttpSDHandler *usrhndlr = NULL); + LLCore::HttpHandle requestPostCapability(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr = NULL); + //LLCore::HttpHandle httpGetCapability(const std::string &cap, const LLURI &uri, LLHttpSDHandler *usrhndlr = NULL); /** Utility ** ** diff --git a/indra/newview/llagentlanguage.cpp b/indra/newview/llagentlanguage.cpp index 81fce9b257..f2ac323578 100755 --- a/indra/newview/llagentlanguage.cpp +++ b/indra/newview/llagentlanguage.cpp @@ -71,7 +71,7 @@ bool LLAgentLanguage::update() body["language_is_public"] = gSavedSettings.getBOOL("LanguageIsPublic"); //LLHTTPClient::post(url, body, new LLHTTPClient::Responder); - LLCore::HttpHandle handle = gAgent.requestPostCapibility("UpdateAgentLanguage", url, body); + LLCore::HttpHandle handle = gAgent.requestPostCapability("UpdateAgentLanguage", url, body); if (handle == LLCORE_HTTP_HANDLE_INVALID) { LL_WARNS() << "Unable to change language." << LL_ENDL; diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index cd9166f7b7..51cca273d8 100755 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -494,7 +494,7 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url, validation_params[CERT_HOSTNAME] = uri.hostName(); - // *TODO*: In the case of an exception while validating the cert, we need a way + // *TODO: In the case of an exception while validating the cert, we need a way // to pass the offending(?) cert back out. *Rider* try diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index be71c430f4..709d9881e1 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1260,7 +1260,7 @@ public: virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); protected: - virtual void onSuccess(LLCore::HttpResponse * response, LLSD &content); + virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content); virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status); private: @@ -1278,7 +1278,7 @@ void LLAppearanceMgrHttpHandler::onCompleted(LLCore::HttpHandle handle, LLCore:: LLHttpSDHandler::onCompleted(handle, response); } -void LLAppearanceMgrHttpHandler::onSuccess(LLCore::HttpResponse * response, LLSD &content) +void LLAppearanceMgrHttpHandler::onSuccess(LLCore::HttpResponse * response, const LLSD &content) { if (!content.isMap()) { @@ -3443,7 +3443,7 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version; - LLCore::HttpHandle handle = gAgent.requestPostCapibility("UpdateAvatarAppearance", url, postData, handler); + LLCore::HttpHandle handle = gAgent.requestPostCapability("UpdateAvatarAppearance", url, postData, handler); if (handle == LLCORE_HTTP_HANDLE_INVALID) { diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp index 38e153137c..aeaa832bc7 100644 --- a/indra/newview/llavatarrenderinfoaccountant.cpp +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -43,7 +43,9 @@ #include "llviewerregion.h" #include "llvoavatar.h" #include "llworld.h" - +#include "llhttpsdhandler.h" +#include "httpheaders.h" +#include "httpoptions.h" static const std::string KEY_AGENTS = "agents"; // map static const std::string KEY_WEIGHT = "weight"; // integer @@ -55,8 +57,113 @@ static const std::string KEY_ERROR = "error"; // Send data updates about once per minute, only need per-frame resolution LLFrameTimer LLAvatarRenderInfoAccountant::sRenderInfoReportTimer; +//LLCore::HttpRequest::ptr_t LLAvatarRenderInfoAccountant::sHttpRequest; + +#if 0 +//========================================================================= +class LLAvatarRenderInfoHandler : public LLHttpSDHandler +{ +public: + LLAvatarRenderInfoHandler(const LLURI &uri, U64 regionHandle); + +protected: + virtual void onSuccess(LLCore::HttpResponse * response, LLSD &content); + virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status); + +private: + U64 mRegionHandle; +}; + +LLAvatarRenderInfoHandler::LLAvatarRenderInfoHandler(const LLURI &uri, U64 regionHandle) : + LLHttpSDHandler(uri), + mRegionHandle(regionHandle) +{ +} + +void LLAvatarRenderInfoHandler::onSuccess(LLCore::HttpResponse * response, LLSD &content) +{ + LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if (regionp) + { + if (LLAvatarRenderInfoAccountant::logRenderInfo()) + { + LL_INFOS() << "LRI: Result for avatar weights request for region " << regionp->getName() << ":" << LL_ENDL; + } + + if (content.isMap()) + { + if (content.has(KEY_AGENTS)) + { + const LLSD & agents = content[KEY_AGENTS]; + if (agents.isMap()) + { + LLSD::map_const_iterator report_iter = agents.beginMap(); + while (report_iter != agents.endMap()) + { + LLUUID target_agent_id = LLUUID(report_iter->first); + const LLSD & agent_info_map = report_iter->second; + LLViewerObject* avatarp = gObjectList.findObject(target_agent_id); + if (avatarp && + avatarp->isAvatar() && + agent_info_map.isMap()) + { // Extract the data for this avatar + + if (LLAvatarRenderInfoAccountant::logRenderInfo()) + { + LL_INFOS() << "LRI: Agent " << target_agent_id + << ": " << agent_info_map << LL_ENDL; + } + + if (agent_info_map.has(KEY_WEIGHT)) + { + ((LLVOAvatar *)avatarp)->setReportedVisualComplexity(agent_info_map[KEY_WEIGHT].asInteger()); + } + } + report_iter++; + } + } + } // has "agents" + else if (content.has(KEY_ERROR)) + { + const LLSD & error = content[KEY_ERROR]; + LL_WARNS() << "Avatar render info GET error: " + << error[KEY_IDENTIFIER] + << ": " << error[KEY_MESSAGE] + << " from region " << regionp->getName() + << LL_ENDL; + } + } + } + else + { + LL_INFOS() << "Avatar render weight info received but region not found for " + << mRegionHandle << LL_ENDL; + } +} +void LLAvatarRenderInfoHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) +{ + LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if (regionp) + { + LL_WARNS() << "HTTP error result for avatar weight GET: " << status.toULong() + << ", " << status.toString() + << " returned by region " << regionp->getName() + << LL_ENDL; + } + else + { + LL_WARNS() << "Avatar render weight GET error received but region not found for " + << mRegionHandle + << ", error " << status.toULong() + << ", " << status.toString() + << LL_ENDL; + } +} + +//------------------------------------------------------------------------- +#else // HTTP responder class for GET request for avatar render weight information class LLAvatarRenderInfoGetResponder : public LLHTTPClient::Responder { @@ -142,7 +249,7 @@ public: } else { - LL_INFOS() << "Avatar render weight info recieved but region not found for " + LL_INFOS() << "Avatar render weight info received but region not found for " << mRegionHandle << LL_ENDL; } } @@ -150,7 +257,7 @@ public: private: U64 mRegionHandle; }; - +#endif // HTTP responder class for POST request for avatar render weight information class LLAvatarRenderInfoPostResponder : public LLHTTPClient::Responder @@ -172,7 +279,7 @@ public: } else { - LL_WARNS() << "Avatar render weight POST error recieved but region not found for " + LL_WARNS() << "Avatar render weight POST error received but region not found for " << mRegionHandle << ", error " << statusNum << ", " << reason @@ -215,7 +322,6 @@ private: U64 mRegionHandle; }; - // static // Send request for one region, no timer checks void LLAvatarRenderInfoAccountant::sendRenderInfoToRegion(LLViewerRegion * regionp) @@ -292,7 +398,19 @@ void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regi } // First send a request to get the latest data +#if 0 + if (!LLAvatarRenderInfoAccountant::sHttpRequest) + sHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest()); + LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp()); + + LLCore::HttpHeaders::ptr_t httpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false); + LLCore::HttpOptions::ptr_t httpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false); + LLCore::HttpRequest::policy_t httpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_AGENT); + + LLCore::HttpHandle handle = sHttpRequest-> +#else LLHTTPClient::get(url, new LLAvatarRenderInfoGetResponder(regionp->getHandle())); +#endif } } @@ -301,6 +419,9 @@ void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regi // Called every frame - send render weight requests to every region void LLAvatarRenderInfoAccountant::idle() { +// if (!LLAvatarRenderInfoAccountant::sHttpRequest) +// sHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest()); + if (sRenderInfoReportTimer.hasExpired()) { const F32 SECS_BETWEEN_REGION_SCANS = 5.f; // Scan the region list every 5 seconds diff --git a/indra/newview/llavatarrenderinfoaccountant.h b/indra/newview/llavatarrenderinfoaccountant.h index d68f2dccfb..13054f5e2f 100644 --- a/indra/newview/llavatarrenderinfoaccountant.h +++ b/indra/newview/llavatarrenderinfoaccountant.h @@ -29,6 +29,8 @@ #if ! defined(LL_llavatarrenderinfoaccountant_H) #define LL_llavatarrenderinfoaccountant_H +#include "httpcommon.h" + class LLViewerRegion; // Class to gather avatar rendering information @@ -36,8 +38,6 @@ class LLViewerRegion; class LLAvatarRenderInfoAccountant { public: - LLAvatarRenderInfoAccountant() {}; - ~LLAvatarRenderInfoAccountant() {}; static void sendRenderInfoToRegion(LLViewerRegion * regionp); static void getRenderInfoFromRegion(LLViewerRegion * regionp); @@ -49,8 +49,14 @@ public: static bool logRenderInfo(); private: + LLAvatarRenderInfoAccountant() {}; + ~LLAvatarRenderInfoAccountant() {}; + // Send data updates about once per minute, only need per-frame resolution static LLFrameTimer sRenderInfoReportTimer; + +// static LLCore::HttpRequest::ptr_t sHttpRequest; + }; #endif /* ! defined(LL_llavatarrenderinfoaccountant_H) */ diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp index 065d763596..78fbe9af0a 100755 --- a/indra/newview/llmaterialmgr.cpp +++ b/indra/newview/llmaterialmgr.cpp @@ -75,7 +75,7 @@ public: virtual ~LLMaterialHttpHandler(); protected: - virtual void onSuccess(LLCore::HttpResponse * response, LLSD &content); + virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content); virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status); private: @@ -95,7 +95,7 @@ LLMaterialHttpHandler::~LLMaterialHttpHandler() { } -void LLMaterialHttpHandler::onSuccess(LLCore::HttpResponse * response, LLSD &content) +void LLMaterialHttpHandler::onSuccess(LLCore::HttpResponse * response, const LLSD &content) { LL_DEBUGS("Materials") << LL_ENDL; mCallback(true, content); -- cgit v1.3 From edc1439bd633bdac183fbecc131edd55074b5442 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Wed, 1 Apr 2015 16:37:00 -0700 Subject: Added AvatarNameCache as coroutine, with LLCore::HttpHandler to respond correctly to Event Pumps. Added get/setRequestURL() to LLCore::HttpResponse Removed URI from the HttpSDHandler. --- indra/llcorehttp/_httpoprequest.cpp | 4 +- indra/llcorehttp/httpresponse.cpp | 3 +- indra/llcorehttp/httpresponse.h | 11 ++ indra/llmessage/llavatarnamecache.cpp | 286 +++++++++++++++++++++++----------- indra/llmessage/llavatarnamecache.h | 7 +- indra/llmessage/llcorehttputil.cpp | 96 +++++++++++- indra/llmessage/llcorehttputil.h | 30 ++++ indra/llmessage/llhttpsdhandler.cpp | 12 +- indra/llmessage/llhttpsdhandler.h | 11 +- indra/newview/llagent.cpp | 55 ++++--- indra/newview/llagent.h | 10 +- indra/newview/llappearancemgr.cpp | 8 +- indra/newview/llmaterialmgr.cpp | 14 +- 13 files changed, 405 insertions(+), 142 deletions(-) (limited to 'indra/newview/llagent.cpp') diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 5768fe5a90..7c2309b31d 100755 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -260,7 +260,9 @@ void HttpOpRequest::visitNotifier(HttpRequest * request) response->setStatus(mStatus); response->setBody(mReplyBody); response->setHeaders(mReplyHeaders); - if (mReplyOffset || mReplyLength) + response->setRequestURL(mReqURL); + + if (mReplyOffset || mReplyLength) { // Got an explicit offset/length in response response->setRange(mReplyOffset, mReplyLength, mReplyFullLength); diff --git a/indra/llcorehttp/httpresponse.cpp b/indra/llcorehttp/httpresponse.cpp index 87e3426415..7d88f02527 100755 --- a/indra/llcorehttp/httpresponse.cpp +++ b/indra/llcorehttp/httpresponse.cpp @@ -41,7 +41,8 @@ HttpResponse::HttpResponse() mBufferArray(NULL), mHeaders(NULL), mRetries(0U), - m503Retries(0U) + m503Retries(0U), + mRequestUrl() {} diff --git a/indra/llcorehttp/httpresponse.h b/indra/llcorehttp/httpresponse.h index 39b582ff85..6c3b4da5e6 100755 --- a/indra/llcorehttp/httpresponse.h +++ b/indra/llcorehttp/httpresponse.h @@ -194,6 +194,16 @@ public: return mStats; } + void setRequestURL(const std::string &url) + { + mRequestUrl = url; + } + + const std::string &getRequestURL() const + { + return mRequestUrl; + } + protected: // Response data here @@ -206,6 +216,7 @@ protected: std::string mContentType; unsigned int mRetries; unsigned int m503Retries; + std::string mRequestUrl; TransferStats::ptr_t mStats; }; diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index d02a60b7b2..88859819e0 100755 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -33,9 +33,18 @@ #include "llhttpclient.h" #include "llsd.h" #include "llsdserialize.h" - +#include "httpresponse.h" +#include "llhttpsdhandler.h" #include +#include "httpcommon.h" +#include "httprequest.h" +#include "httpheaders.h" +#include "httpoptions.h" +#include "llcoros.h" +#include "lleventcoro.h" +#include "llcorehttputil.h" + #include #include @@ -90,6 +99,12 @@ namespace LLAvatarNameCache // Time-to-live for a temp cache entry. const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0; + LLCore::HttpRequest::ptr_t sHttpRequest; + LLCore::HttpHeaders::ptr_t sHttpHeaders; + LLCore::HttpOptions::ptr_t sHttpOptions; + LLCore::HttpRequest::policy_t sHttpPolicy; + LLCore::HttpRequest::priority_t sHttpPriority; + //----------------------------------------------------------------------- // Internal methods //----------------------------------------------------------------------- @@ -121,7 +136,13 @@ namespace LLAvatarNameCache // Erase expired names from cache void eraseUnrefreshed(); - bool expirationFromCacheControl(const LLSD& headers, F64 *expires); + //bool expirationFromCacheControl(LLCore::HttpHeaders *headers, F64 *expires); + bool expirationFromCacheControl(const LLSD& headers, F64 *expires); + + // This is a coroutine. The only parameter that can be specified as a reference is the self + void requestAvatarNameCache_(LLCoros::self& self, std::string url, std::vector agentIds); + + void handleAvNameCacheSuccess(const LLSD &data, const LLSD &httpResult); } /* Sample response: @@ -163,94 +184,125 @@ namespace LLAvatarNameCache */ -class LLAvatarNameResponder : public LLHTTPClient::Responder +// Coroutine for sending and processing avatar name cache requests. +// Do not call directly. See documentation in lleventcoro.h and llcoro.h for +// further explanation. +void LLAvatarNameCache::requestAvatarNameCache_(LLCoros::self& self, std::string url, std::vector agentIds) { - LOG_CLASS(LLAvatarNameResponder); -private: - // need to store agent ids that are part of this request in case of - // an error, so we can flag them as unavailable - std::vector mAgentIDs; - -public: - LLAvatarNameResponder(const std::vector& agent_ids) - : mAgentIDs(agent_ids) - { } - -protected: - /*virtual*/ void httpSuccess() - { - const LLSD& content = getContent(); - if (!content.isMap()) - { - failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); - return; - } - // Pull expiration out of headers if available - F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(getResponseHeaders()); - F64 now = LLFrameTimer::getTotalSeconds(); + LLEventStream replyPump("NameCacheReply", true); + LLCoreHttpUtil::HttpCoroHandler::ptr_t httpHandler = + LLCoreHttpUtil::HttpCoroHandler::ptr_t(new LLCoreHttpUtil::HttpCoroHandler(replyPump)); - const LLSD& agents = content["agents"]; - LLSD::array_const_iterator it = agents.beginArray(); - for ( ; it != agents.endArray(); ++it) - { - const LLSD& row = *it; - LLUUID agent_id = row["id"].asUUID(); + LL_DEBUGS("AvNameCache") << "Entering coroutine " << LLCoros::instance().getName(self) + << " with url '" << url << "', requesting " << agentIds.size() << " Agent Ids" << LL_ENDL; - LLAvatarName av_name; - av_name.fromLLSD(row); + try + { + bool success = true; - // Use expiration time from header - av_name.mExpires = expires; + LLAvatarNameCache::sHttpRequest->requestGet( + LLAvatarNameCache::sHttpPolicy, LLAvatarNameCache::sHttpPriority, + url, LLAvatarNameCache::sHttpOptions.get(), + LLAvatarNameCache::sHttpHeaders.get(), httpHandler.get()); - LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << LL_ENDL; - av_name.dump(); - - // cache it and fire signals - LLAvatarNameCache::processName(agent_id, av_name); - } + LLSD results = waitForEventOn(self, replyPump); + LLSD httpResults; - // Same logic as error response case - const LLSD& unresolved_agents = content["bad_ids"]; - S32 num_unresolved = unresolved_agents.size(); - if (num_unresolved > 0) - { - LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result " << num_unresolved << " unresolved ids; " - << "expires in " << expires - now << " seconds" - << LL_ENDL; - it = unresolved_agents.beginArray(); - for ( ; it != unresolved_agents.endArray(); ++it) - { - const LLUUID& agent_id = *it; + LL_DEBUGS() << results << LL_ENDL; - LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result " - << "failed id " << agent_id - << LL_ENDL; + if (!results.isMap()) + { + LL_WARNS("AvNameCache") << " Invalid result returned from LLCoreHttpUtil::HttpCoroHandler." << LL_ENDL; + success = false; + } + else + { + httpResults = results["http_result"]; + success = httpResults["success"].asBoolean(); + if (!success) + { + LL_WARNS("AvNameCache") << "Error result from LLCoreHttpUtil::HttpCoroHandler. Code " + << httpResults["status"] << ": '" << httpResults["message"] << "'" << LL_ENDL; + } + } + if (!success) + { // on any sort of failure add dummy records for any agent IDs + // in this request that we do not have cached already + std::vector::const_iterator it = agentIds.begin(); + for ( ; it != agentIds.end(); ++it) + { + const LLUUID& agent_id = *it; LLAvatarNameCache::handleAgentError(agent_id); - } - } - LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result " - << LLAvatarNameCache::sCache.size() << " cached names" - << LL_ENDL; + } + return; + } + + LLAvatarNameCache::handleAvNameCacheSuccess(results, httpResults); + } + catch (std::exception e) + { + LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL; + } + catch (...) + { + LL_WARNS() << "Caught unknown exception." << LL_ENDL; + } +} - /*virtual*/ void httpFailure() - { - // If there's an error, it might be caused by PeopleApi, - // or when loading textures on startup and using a very slow - // network, this query may time out. - // What we should do depends on whether or not we have a cached name - LL_WARNS("AvNameCache") << dumpResponse() << LL_ENDL; - - // Add dummy records for any agent IDs in this request that we do not have cached already - std::vector::const_iterator it = mAgentIDs.begin(); - for ( ; it != mAgentIDs.end(); ++it) - { - const LLUUID& agent_id = *it; - LLAvatarNameCache::handleAgentError(agent_id); - } - } -}; +void LLAvatarNameCache::handleAvNameCacheSuccess(const LLSD &data, const LLSD &httpResult) +{ + + LLSD headers = httpResult["headers"]; + // Pull expiration out of headers if available + F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(headers); + F64 now = LLFrameTimer::getTotalSeconds(); + + const LLSD& agents = data["agents"]; + LLSD::array_const_iterator it = agents.beginArray(); + for (; it != agents.endArray(); ++it) + { + const LLSD& row = *it; + LLUUID agent_id = row["id"].asUUID(); + + LLAvatarName av_name; + av_name.fromLLSD(row); + + // Use expiration time from header + av_name.mExpires = expires; + + LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << LL_ENDL; + av_name.dump(); + + // cache it and fire signals + LLAvatarNameCache::processName(agent_id, av_name); + } + + // Same logic as error response case + const LLSD& unresolved_agents = data["bad_ids"]; + S32 num_unresolved = unresolved_agents.size(); + if (num_unresolved > 0) + { + LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result " << num_unresolved << " unresolved ids; " + << "expires in " << expires - now << " seconds" + << LL_ENDL; + it = unresolved_agents.beginArray(); + for (; it != unresolved_agents.endArray(); ++it) + { + const LLUUID& agent_id = *it; + + LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result " + << "failed id " << agent_id + << LL_ENDL; + + LLAvatarNameCache::handleAgentError(agent_id); + } + } + LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result " + << LLAvatarNameCache::sCache.size() << " cached names" + << LL_ENDL; +} // Provide some fallback for agents that return errors void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id) @@ -353,12 +405,17 @@ void LLAvatarNameCache::requestNamesViaCapability() } } - if (!url.empty()) - { - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability requested " - << ids << " ids" - << LL_ENDL; - LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids)); + if (!url.empty()) + { + LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability requested " + << ids << " ids" + << LL_ENDL; + + std::string coroname = + LLCoros::instance().launch("LLAvatarNameCache::requestAvatarNameCache_", + boost::bind(&LLAvatarNameCache::requestAvatarNameCache_, _1, url, agent_ids)); + LL_DEBUGS("AvNameCache") << coroname << " with url '" << url << "', agent_ids.size()=" << agent_ids.size() << LL_ENDL; + } } @@ -422,11 +479,20 @@ void LLAvatarNameCache::initClass(bool running, bool usePeopleAPI) { sRunning = running; sUsePeopleAPI = usePeopleAPI; + + sHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest()); + sHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false); + sHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false); + sHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID; + sHttpPriority = 0; } void LLAvatarNameCache::cleanupClass() { - sCache.clear(); + sHttpRequest.reset(); + sHttpHeaders.reset(); + sHttpOptions.reset(); + sCache.clear(); } void LLAvatarNameCache::importFile(std::istream& istr) @@ -498,6 +564,8 @@ void LLAvatarNameCache::idle() // By convention, start running at first idle() call sRunning = true; + sHttpRequest->update(0L); + // *TODO: Possibly re-enabled this based on People API load measurements // 100 ms is the threshold for "user speed" operations, so we can // stall for about that long to batch up requests. @@ -697,6 +765,50 @@ void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_na sCache[agent_id] = av_name; } +#if 0 +F64 LLAvatarNameCache::nameExpirationFromHeaders(LLCore::HttpHeaders *headers) +{ + F64 expires = 0.0; + if (expirationFromCacheControl(headers, &expires)) + { + return expires; + } + else + { + // With no expiration info, default to an hour + const F64 DEFAULT_EXPIRES = 60.0 * 60.0; + F64 now = LLFrameTimer::getTotalSeconds(); + return now + DEFAULT_EXPIRES; + } +} + +bool LLAvatarNameCache::expirationFromCacheControl(LLCore::HttpHeaders *headers, F64 *expires) +{ + bool fromCacheControl = false; + F64 now = LLFrameTimer::getTotalSeconds(); + + // Allow the header to override the default + const std::string *cache_control; + + cache_control = headers->find(HTTP_IN_HEADER_CACHE_CONTROL); + + if (cache_control && !cache_control->empty()) + { + S32 max_age = 0; + if (max_age_from_cache_control(*cache_control, &max_age)) + { + *expires = now + (F64)max_age; + fromCacheControl = true; + } + } + LL_DEBUGS("AvNameCache") + << ( fromCacheControl ? "expires based on cache control " : "default expiration " ) + << "in " << *expires - now << " seconds" + << LL_ENDL; + + return fromCacheControl; +} +#else F64 LLAvatarNameCache::nameExpirationFromHeaders(const LLSD& headers) { F64 expires = 0.0; @@ -741,7 +853,7 @@ bool LLAvatarNameCache::expirationFromCacheControl(const LLSD& headers, F64 *exp return fromCacheControl; } - +#endif void LLAvatarNameCache::addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb) { diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index ea016b3125..fdfd4e972d 100755 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -29,7 +29,8 @@ #define LLAVATARNAMECACHE_H #include "llavatarname.h" // for convenience - +//#include "httpcommon.h" +//#include "httpheaders.h" #include class LLSD; @@ -49,7 +50,7 @@ namespace LLAvatarNameCache void importFile(std::istream& istr); void exportFile(std::ostream& ostr); - // On the viewer, usually a simulator capabilitity. + // On the viewer, usually a simulator capabilities. // If empty, name cache will fall back to using legacy name lookup system. void setNameLookupURL(const std::string& name_lookup_url); @@ -90,7 +91,7 @@ namespace LLAvatarNameCache // Compute name expiration time from HTTP Cache-Control header, // or return default value, in seconds from epoch. - F64 nameExpirationFromHeaders(const LLSD& headers); + F64 nameExpirationFromHeaders(const LLSD& headers); void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb); } diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index 366a0b9460..991985b1cf 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -30,15 +30,17 @@ #include #include "llcorehttputil.h" +#include "llhttpconstants.h" #include "llsdserialize.h" - using namespace LLCore; namespace LLCoreHttpUtil { + + // *TODO: Currently converts only from XML content. A mode // to convert using fromBinary() might be useful as well. Mesh // headers could use it. @@ -186,5 +188,97 @@ std::string responseToString(LLCore::HttpResponse * response) } +HttpCoroHandler::HttpCoroHandler(LLEventStream &reply) : + mReplyPump(reply) +{ +} + +void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response) +{ + LLSD result; + + LLCore::HttpStatus status = response->getStatus(); + + if (!status) + { + result = LLSD::emptyMap(); + LL_WARNS() + << "\n--------------------------------------------------------------------------\n" + << " Error[" << status.toULong() << "] cannot access url '" << response->getRequestURL() + << "' because " << status.toString() + << "\n--------------------------------------------------------------------------" + << LL_ENDL; + + } + else + { + const bool emit_parse_errors = false; + + bool parsed = !((response->getBodySize() == 0) || + !LLCoreHttpUtil::responseToLLSD(response, emit_parse_errors, result)); + + if (!parsed) + { + // Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml' + LLCore::HttpHeaders::ptr_t headers(response->getHeaders()); + const std::string *contentType = (headers) ? headers->find(HTTP_IN_HEADER_CONTENT_TYPE) : NULL; + + if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType)) + { + std::string thebody = LLCoreHttpUtil::responseToString(response); + LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] " + << " body: " << thebody << LL_ENDL; + + // Replace the status with a new one indicating the failure. + status = LLCore::HttpStatus(499, "Failed to deserialize LLSD."); + } + } + + if (result.isUndefined()) + { + // If we've gotten to this point and the result LLSD is still undefined + // either there was an issue deserializing the body or the response was + // blank. Create an empty map to hold the result either way. + result = LLSD::emptyMap(); + } + } + + buildStatusEntry(response, status, result); + mReplyPump.post(result); +} + +void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result) +{ + LLSD httpresults = LLSD::emptyMap(); + + httpresults["success"] = static_cast(status); + httpresults["type"] = static_cast(status.getType()); + httpresults["status"] = static_cast(status.getStatus()); + httpresults["message"] = static_cast(status.getMessage()); + httpresults["url"] = static_cast(response->getRequestURL()); + + LLSD httpHeaders = LLSD::emptyMap(); + LLCore::HttpHeaders * hdrs = response->getHeaders(); + + if (hdrs) + { + for (LLCore::HttpHeaders::iterator it = hdrs->begin(); it != hdrs->end(); ++it) + { + if (!(*it).second.empty()) + { + httpHeaders[(*it).first] = (*it).second; + } + else + { + httpHeaders[(*it).first] = static_cast(true); + } + } + } + + httpresults["headers"] = httpHeaders; + result["http_result"] = httpresults; +} + + } // end namespace LLCoreHttpUtil diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h index 8e26f413fe..0bc102a0a3 100644 --- a/indra/llmessage/llcorehttputil.h +++ b/indra/llmessage/llcorehttputil.h @@ -39,6 +39,7 @@ #include "bufferarray.h" #include "bufferstream.h" #include "llsd.h" +#include "llevents.h" /// /// The base llcorehttp library implements many HTTP idioms @@ -152,6 +153,35 @@ LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request, LLCore::HttpHeaders::ptr_t & headers, LLCore::HttpHandler * handler); +/// The HttpCoroHandler is a specialization of the LLCore::HttpHandler for +/// interacting with coroutines. When the request is completed the response +/// will be posted onto the supplied Event Pump. +/// +/// The LLSD posted back to the coroutine will have the following additions: +/// llsd["http_result"] -+- ["message"] - An error message returned from the HTTP status +/// +- ["status"] - The status code associated with the HTTP call +/// +- ["success"] - Success of failure of the HTTP call and LLSD parsing. +/// +- ["type"] - The LLCore::HttpStatus type associted with the HTTP call +/// +- ["url"] - The URL used to make the call. +/// +- ["headers"] - A map of name name value pairs with the HTTP headers. +/// + +/// +class HttpCoroHandler : public LLCore::HttpHandler +{ +public: + HttpCoroHandler(LLEventStream &reply); + + virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); + + typedef boost::shared_ptr ptr_t; + +private: + void buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result); + + LLEventStream &mReplyPump; +}; + } // end namespace LLCoreHttpUtil diff --git a/indra/llmessage/llhttpsdhandler.cpp b/indra/llmessage/llhttpsdhandler.cpp index 72ecfe77e2..159d03b176 100644 --- a/indra/llmessage/llhttpsdhandler.cpp +++ b/indra/llmessage/llhttpsdhandler.cpp @@ -36,10 +36,8 @@ #include "llcorehttputil.h" //======================================================================== -LLHttpSDHandler::LLHttpSDHandler(const LLURI &uri): - mUri(uri) +LLHttpSDHandler::LLHttpSDHandler() { - } void LLHttpSDHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response) @@ -68,7 +66,7 @@ void LLHttpSDHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons { std::string thebody = LLCoreHttpUtil::responseToString(response); - LL_WARNS() << "Failed to deserialize . " << getUri() << " [status:" << response->getStatus().toString() << "] " + LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] " << " body: " << thebody << LL_ENDL; } } @@ -83,8 +81,8 @@ void LLHttpSDHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons } //======================================================================== -LLHttpSDGenericHandler::LLHttpSDGenericHandler(const LLURI &uri, const std::string &caps) : - LLHttpSDHandler(uri), +LLHttpSDGenericHandler::LLHttpSDGenericHandler(const std::string &caps) : + LLHttpSDHandler(), mCaps(caps) { } @@ -99,7 +97,7 @@ void LLHttpSDGenericHandler::onFailure(LLCore::HttpResponse * response, LLCore:: LL_WARNS() << "\n--------------------------------------------------------------------------\n" << mCaps << " Error[" << status.toULong() << "] cannot access cap with url '" - << getUri() << "' because " << status.toString() + << response->getRequestURL() << "' because " << status.toString() << "\n--------------------------------------------------------------------------" << LL_ENDL; } diff --git a/indra/llmessage/llhttpsdhandler.h b/indra/llmessage/llhttpsdhandler.h index a2598c9709..7c28dbcab6 100644 --- a/indra/llmessage/llhttpsdhandler.h +++ b/indra/llmessage/llhttpsdhandler.h @@ -39,21 +39,14 @@ class LLHttpSDHandler : public LLCore::HttpHandler { public: - LLHttpSDHandler(const LLURI &uri); + LLHttpSDHandler(); virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); - inline const LLURI &getUri() const - { - return mUri; - } - protected: virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content) = 0; virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) = 0; -private: - LLURI mUri; }; /// A trivial implementation of LLHttpSDHandler. This success and failure @@ -62,7 +55,7 @@ private: class LLHttpSDGenericHandler : public LLHttpSDHandler { public: - LLHttpSDGenericHandler(const LLURI &uri, const std::string &action); + LLHttpSDGenericHandler(const std::string &action); protected: virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content); diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 667d530e39..eeedda5c6d 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -325,7 +325,6 @@ bool LLAgent::isMicrophoneOn(const LLSD& sdname) // For a toggled version, see viewer.h for the // TOGGLE_HACKED_GODLIKE_VIEWER define, instead. // ************************************************************ -bool LLAgent::mActive = true; // Constructors and Destructors @@ -474,7 +473,9 @@ void LLAgent::init() mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false); mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_AGENT); - doOnIdleRepeating(boost::bind(&LLAgent::onIdle, this)); + // Now ensure that we get regular callbacks to poll for completion. + mBoundListener = LLEventPumps::instance().obtain("mainloop"). + listen(LLEventPump::inventName(), boost::bind(&LLAgent::pollHttp, this, _1)); mInitialized = TRUE; } @@ -484,7 +485,6 @@ void LLAgent::init() //----------------------------------------------------------------------------- void LLAgent::cleanup() { - mActive = false; mRegionp = NULL; if (mTeleportFinishedSlot.connected()) { @@ -494,6 +494,10 @@ void LLAgent::cleanup() { mTeleportFailedSlot.disconnect(); } + if (mBoundListener.connected()) + { + mBoundListener.disconnect(); + } } //----------------------------------------------------------------------------- @@ -517,16 +521,16 @@ LLAgent::~LLAgent() } //----------------------------------------------------------------------------- -// Idle processing +// pollHttp +// Polling done once per frame on the "mainloop" to support HTTP processing. //----------------------------------------------------------------------------- -bool LLAgent::onIdle() +bool LLAgent::pollHttp(const LLSD&) { - if (!LLAgent::mActive) - return true; - mHttpRequest->update(0L); - return false; + mHttpRequest->update(0L); + return false; } + // Handle any actions that need to be performed when the main app gains focus // (such as through alt-tab). //----------------------------------------------------------------------------- @@ -2548,8 +2552,8 @@ int LLAgent::convertTextToMaturity(char text) class LLMaturityHttpHandler : public LLHttpSDHandler { public: - LLMaturityHttpHandler(const std::string& capabilityURL, LLAgent *agent, U8 preferred, U8 previous): - LLHttpSDHandler(capabilityURL), + LLMaturityHttpHandler(LLAgent *agent, U8 preferred, U8 previous): + LLHttpSDHandler(), mAgent(agent), mPreferredMaturity(preferred), mPreviousMaturity(previous) @@ -2764,7 +2768,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) return; } - LLMaturityHttpHandler * handler = new LLMaturityHttpHandler(url, this, pPreferredMaturity, mLastKnownResponseMaturity); + LLMaturityHttpHandler * handler = new LLMaturityHttpHandler(this, pPreferredMaturity, mLastKnownResponseMaturity); LLSD access_prefs = LLSD::emptyMap(); access_prefs["max"] = LLViewerRegion::accessToShortString(pPreferredMaturity); @@ -2779,14 +2783,14 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) if (handle == LLCORE_HTTP_HANDLE_INVALID) { delete handler; - LL_WARNS("Avatar") << "Maturity request post failed." << LL_ENDL; + LL_WARNS("Agent") << "Maturity request post failed." << LL_ENDL; } } } LLCore::HttpHandle LLAgent::requestPostCapability(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr) { - LLHttpSDHandler * handler = (usrhndlr) ? usrhndlr : new LLHttpSDGenericHandler(url, cap); + LLHttpSDHandler * handler = (usrhndlr) ? usrhndlr : new LLHttpSDGenericHandler(cap); LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, mHttpPolicy, mHttpPriority, url, postData, mHttpOptions, mHttpHeaders, handler); @@ -2799,16 +2803,31 @@ LLCore::HttpHandle LLAgent::requestPostCapability(const std::string &cap, const if (!usrhndlr) delete handler; LLCore::HttpStatus status = mHttpRequest->getStatus(); - LL_WARNS("Avatar") << "'" << cap << "' request POST failed. Reason " + LL_WARNS("Agent") << "'" << cap << "' request POST failed. Reason " << status.toTerseString() << " \"" << status.toString() << "\"" << LL_ENDL; } return handle; } -//LLCore::HttpHandle LLAgent::httpGetCapibility(const std::string &cap, const LLURI &uri, LLHttpSDHandler *usrhndlr) -//{ -//} +LLCore::HttpHandle LLAgent::requestGetCapability(const std::string &cap, const std::string &url, LLHttpSDHandler *usrhndlr) +{ + LLHttpSDHandler * handler = (usrhndlr) ? usrhndlr : new LLHttpSDGenericHandler(cap); + LLCore::HttpHandle handle = mHttpRequest->requestGet(mHttpPolicy, mHttpPriority, + url, mHttpOptions.get(), mHttpHeaders.get(), handler); + if (handle == LLCORE_HTTP_HANDLE_INVALID) + { + // If no handler was passed in we delete the handler default handler allocated + // at the start of this function. + // *TODO: Change this metaphore to use boost::shared_ptr<> for handlers. Requires change in LLCore::HTTP + if (!usrhndlr) + delete handler; + LLCore::HttpStatus status = mHttpRequest->getStatus(); + LL_WARNS("Agent") << "'" << cap << "' request GET failed. Reason " + << status.toTerseString() << " \"" << status.toString() << "\"" << LL_ENDL; + } + return handle; +} BOOL LLAgent::getAdminOverride() const { diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 26120b52f6..9ffc9b9a7a 100755 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -34,6 +34,7 @@ #include "llcoordframe.h" // for mFrameAgent #include "llavatarappearancedefines.h" #include "llpermissionsflags.h" +#include "llevents.h" #include "v3dmath.h" #include "httprequest.h" #include "httpheaders.h" @@ -117,9 +118,7 @@ public: void cleanup(); private: - bool onIdle(); - static bool mActive; //-------------------------------------------------------------------- // Login //-------------------------------------------------------------------- @@ -767,6 +766,7 @@ private: LLCore::HttpOptions::ptr_t mHttpOptions; LLCore::HttpRequest::policy_t mHttpPolicy; LLCore::HttpRequest::priority_t mHttpPriority; + LLTempBoundListener mBoundListener; bool isMaturityPreferenceSyncedWithServer() const; void sendMaturityPreferenceToServer(U8 pPreferredMaturity); @@ -781,6 +781,8 @@ private: void handleMaturity(const LLSD &pNewValue); bool validateMaturity(const LLSD& newvalue); + bool pollHttp(const LLSD &); + /** Access ** ** @@ -924,9 +926,9 @@ public: **/ public: /// Utilities for allowing the the agent sub managers to post and get via - /// HTTP using the agent's policy settings and headers. + /// HTTP using the agent's policy settings and headers. LLCore::HttpHandle requestPostCapability(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr = NULL); - //LLCore::HttpHandle httpGetCapability(const std::string &cap, const LLURI &uri, LLHttpSDHandler *usrhndlr = NULL); + LLCore::HttpHandle requestGetCapability(const std::string &cap, const std::string &url, LLHttpSDHandler *usrhndlr = NULL); /** Utility ** ** diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 709d9881e1..4fbcd90baa 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1249,8 +1249,8 @@ static void removeDuplicateItems(LLInventoryModel::item_array_t& items) class LLAppearanceMgrHttpHandler : public LLHttpSDHandler { public: - LLAppearanceMgrHttpHandler(const std::string& capabilityURL, LLAppearanceMgr *mgr) : - LLHttpSDHandler(capabilityURL), + LLAppearanceMgrHttpHandler(LLAppearanceMgr *mgr) : + LLHttpSDHandler(), mManager(mgr) { } @@ -1314,7 +1314,7 @@ void LLAppearanceMgrHttpHandler::onSuccess(LLCore::HttpResponse * response, cons void LLAppearanceMgrHttpHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) { - LL_WARNS("Avatar") << "Appearance Mgr request failed to " << getUri() + LL_WARNS("Avatar") << "Appearance Mgr request failed to " << response->getRequestURL() << ". Reason code: (" << status.toTerseString() << ") " << status.toString() << LL_ENDL; } @@ -3434,7 +3434,7 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() } LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << LL_ENDL; - LLAppearanceMgrHttpHandler * handler = new LLAppearanceMgrHttpHandler(url, this); + LLAppearanceMgrHttpHandler * handler = new LLAppearanceMgrHttpHandler(this); mInFlightCounter++; mInFlightTimer.setTimerExpirySec(60.0); diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp index 78fbe9af0a..8a726ec7c9 100755 --- a/indra/newview/llmaterialmgr.cpp +++ b/indra/newview/llmaterialmgr.cpp @@ -70,7 +70,7 @@ public: typedef boost::function CallbackFunction; typedef boost::shared_ptr ptr_t; - LLMaterialHttpHandler(const std::string& method, const std::string& capabilityURL, CallbackFunction cback); + LLMaterialHttpHandler(const std::string& method, CallbackFunction cback); virtual ~LLMaterialHttpHandler(); @@ -83,8 +83,8 @@ private: CallbackFunction mCallback; }; -LLMaterialHttpHandler::LLMaterialHttpHandler(const std::string& method, const std::string& capabilityURL, CallbackFunction cback): - LLHttpSDHandler(capabilityURL), +LLMaterialHttpHandler::LLMaterialHttpHandler(const std::string& method, CallbackFunction cback): + LLHttpSDHandler(), mMethod(method), mCallback(cback) { @@ -106,7 +106,7 @@ void LLMaterialHttpHandler::onFailure(LLCore::HttpResponse * response, LLCore::H LL_WARNS("Materials") << "\n--------------------------------------------------------------------------\n" << mMethod << " Error[" << status.toULong() << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME - << "'\n with url '" << getUri() << "' because " << status.toString() + << "'\n with url '" << response->getRequestURL() << "' because " << status.toString() << "\n--------------------------------------------------------------------------" << LL_ENDL; @@ -653,7 +653,7 @@ void LLMaterialMgr::processGetQueue() postData[MATERIALS_CAP_ZIP_FIELD] = materialBinary; LLMaterialHttpHandler * handler = - new LLMaterialHttpHandler("POST", capURL, + new LLMaterialHttpHandler("POST", boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id) ); @@ -707,7 +707,7 @@ void LLMaterialMgr::processGetAllQueue() LL_DEBUGS("Materials") << "GET all for region " << region_id << "url " << capURL << LL_ENDL; LLMaterialHttpHandler *handler = - new LLMaterialHttpHandler("GET", capURL, + new LLMaterialHttpHandler("GET", boost::bind(&LLMaterialMgr::onGetAllResponse, this, _1, _2, *itRegion) ); @@ -810,7 +810,7 @@ void LLMaterialMgr::processPutQueue() LL_DEBUGS("Materials") << "put for " << itRequest->second.size() << " faces to region " << itRequest->first->getName() << LL_ENDL; LLMaterialHttpHandler * handler = - new LLMaterialHttpHandler("PUT", capURL, + new LLMaterialHttpHandler("PUT", boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2) ); -- cgit v1.3 From 176d8cd268611e28c07a462df3027f4872456e5a Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Wed, 15 Apr 2015 11:51:48 -0700 Subject: Region caps and sim features converted to coroutine. --- indra/newview/llagent.cpp | 2 + indra/newview/llappearancemgr.cpp | 193 +++++++------ indra/newview/llviewerregion.cpp | 569 +++++++++++++++++++------------------- indra/newview/llviewerregion.h | 3 +- 4 files changed, 399 insertions(+), 368 deletions(-) (limited to 'indra/newview/llagent.cpp') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index eeedda5c6d..7f38e4b79f 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2788,6 +2788,8 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) } } +// *TODO:RIDER Convert this system to using the coroutine scheme for HTTP communications +// LLCore::HttpHandle LLAgent::requestPostCapability(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr) { LLHttpSDHandler * handler = (usrhndlr) ? usrhndlr : new LLHttpSDGenericHandler(cap); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 4fbcd90baa..42c8c0fb1c 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1246,6 +1246,38 @@ static void removeDuplicateItems(LLInventoryModel::item_array_t& items) } //========================================================================= +#if 0 +// *TODO: +class LLAppearanceMgrHttpHandler +{ +public: + + static void apperanceMgrRequestCoro(LLCoros::self& self, std::string url); + +private: + LLAppearanceMgrHttpHandler(); + + static void debugCOF(const LLSD& content); + + +}; + +void LLAppearanceMgrHttpHandler::apperanceMgrRequestCoro(LLCoros::self& self, std::string url) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EnvironmentRequest", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + + +} + +#else + +// *TODO: Convert this and llavatar over to using the coroutine scheme rather +// than the responder for communications. (see block above for start...) + class LLAppearanceMgrHttpHandler : public LLHttpSDHandler { public: @@ -1319,89 +1351,90 @@ void LLAppearanceMgrHttpHandler::onFailure(LLCore::HttpResponse * response, LLCo << status.toString() << LL_ENDL; } +#endif + void LLAppearanceMgrHttpHandler::debugCOF(const LLSD& content) { - dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_error", content); - - LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger() - << " ================================= " << LL_ENDL; - std::set ais_items, local_items; - const LLSD& cof_raw = content["cof_raw"]; - for (LLSD::array_const_iterator it = cof_raw.beginArray(); - it != cof_raw.endArray(); ++it) - { - const LLSD& item = *it; - if (item["parent_id"].asUUID() == LLAppearanceMgr::instance().getCOF()) - { - ais_items.insert(item["item_id"].asUUID()); - if (item["type"].asInteger() == 24) // link - { - LL_INFOS("Avatar") << "AIS Link: item_id: " << item["item_id"].asUUID() - << " linked_item_id: " << item["asset_id"].asUUID() - << " name: " << item["name"].asString() - << LL_ENDL; - } - else if (item["type"].asInteger() == 25) // folder link - { - LL_INFOS("Avatar") << "AIS Folder link: item_id: " << item["item_id"].asUUID() - << " linked_item_id: " << item["asset_id"].asUUID() - << " name: " << item["name"].asString() - << LL_ENDL; - } - else - { - LL_INFOS("Avatar") << "AIS Other: item_id: " << item["item_id"].asUUID() - << " linked_item_id: " << item["asset_id"].asUUID() - << " name: " << item["name"].asString() - << " type: " << item["type"].asInteger() - << LL_ENDL; - } - } - } - LL_INFOS("Avatar") << LL_ENDL; - LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() - << " ================================= " << LL_ENDL; - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), - cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH); - for (S32 i = 0; i < item_array.size(); i++) - { - const LLViewerInventoryItem* inv_item = item_array.at(i).get(); - local_items.insert(inv_item->getUUID()); - LL_INFOS("Avatar") << "LOCAL: item_id: " << inv_item->getUUID() - << " linked_item_id: " << inv_item->getLinkedUUID() - << " name: " << inv_item->getName() - << " parent: " << inv_item->getParentUUID() - << LL_ENDL; - } - LL_INFOS("Avatar") << " ================================= " << LL_ENDL; - S32 local_only = 0, ais_only = 0; - for (std::set::iterator it = local_items.begin(); it != local_items.end(); ++it) - { - if (ais_items.find(*it) == ais_items.end()) - { - LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << LL_ENDL; - local_only++; - } - } - for (std::set::iterator it = ais_items.begin(); it != ais_items.end(); ++it) - { - if (local_items.find(*it) == local_items.end()) - { - LL_INFOS("Avatar") << "AIS ONLY: " << *it << LL_ENDL; - ais_only++; - } - } - if (local_only == 0 && ais_only == 0) - { - LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req " - << content["observed"].asInteger() - << " rcv " << content["expected"].asInteger() - << ")" << LL_ENDL; - } + dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_error", content); + + LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger() + << " ================================= " << LL_ENDL; + std::set ais_items, local_items; + const LLSD& cof_raw = content["cof_raw"]; + for (LLSD::array_const_iterator it = cof_raw.beginArray(); + it != cof_raw.endArray(); ++it) + { + const LLSD& item = *it; + if (item["parent_id"].asUUID() == LLAppearanceMgr::instance().getCOF()) + { + ais_items.insert(item["item_id"].asUUID()); + if (item["type"].asInteger() == 24) // link + { + LL_INFOS("Avatar") << "AIS Link: item_id: " << item["item_id"].asUUID() + << " linked_item_id: " << item["asset_id"].asUUID() + << " name: " << item["name"].asString() + << LL_ENDL; + } + else if (item["type"].asInteger() == 25) // folder link + { + LL_INFOS("Avatar") << "AIS Folder link: item_id: " << item["item_id"].asUUID() + << " linked_item_id: " << item["asset_id"].asUUID() + << " name: " << item["name"].asString() + << LL_ENDL; + } + else + { + LL_INFOS("Avatar") << "AIS Other: item_id: " << item["item_id"].asUUID() + << " linked_item_id: " << item["asset_id"].asUUID() + << " name: " << item["name"].asString() + << " type: " << item["type"].asInteger() + << LL_ENDL; + } + } + } + LL_INFOS("Avatar") << LL_ENDL; + LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() + << " ================================= " << LL_ENDL; + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), + cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH); + for (S32 i = 0; i < item_array.size(); i++) + { + const LLViewerInventoryItem* inv_item = item_array.at(i).get(); + local_items.insert(inv_item->getUUID()); + LL_INFOS("Avatar") << "LOCAL: item_id: " << inv_item->getUUID() + << " linked_item_id: " << inv_item->getLinkedUUID() + << " name: " << inv_item->getName() + << " parent: " << inv_item->getParentUUID() + << LL_ENDL; + } + LL_INFOS("Avatar") << " ================================= " << LL_ENDL; + S32 local_only = 0, ais_only = 0; + for (std::set::iterator it = local_items.begin(); it != local_items.end(); ++it) + { + if (ais_items.find(*it) == ais_items.end()) + { + LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << LL_ENDL; + local_only++; + } + } + for (std::set::iterator it = ais_items.begin(); it != ais_items.end(); ++it) + { + if (local_items.find(*it) == local_items.end()) + { + LL_INFOS("Avatar") << "AIS ONLY: " << *it << LL_ENDL; + ais_only++; + } + } + if (local_only == 0 && ais_only == 0) + { + LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req " + << content["observed"].asInteger() + << " rcv " << content["expected"].asInteger() + << ")" << LL_ENDL; + } } - //========================================================================= const LLUUID LLAppearanceMgr::getCOF() const diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 4bfea81182..bebbf4ea56 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -78,6 +78,9 @@ #include "llviewerdisplay.h" #include "llviewerwindow.h" #include "llprogressview.h" +#include "llcoros.h" +#include "lleventcoro.h" +#include "llcorehttputil.h" #ifdef LL_WINDOWS #pragma warning(disable:4355) @@ -105,7 +108,8 @@ typedef std::map CapabilityMap; static void log_capabilities(const CapabilityMap &capmap); -class LLViewerRegionImpl { +class LLViewerRegionImpl +{ public: LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host) : mHost(host), @@ -189,212 +193,281 @@ public: //spatial partitions for objects in this region std::vector mObjectPartition; - LLVector3 mLastCameraOrigin; - U32 mLastCameraUpdate; -}; - -// support for secondlife:///app/region/{REGION} SLapps -// N.B. this is defined to work exactly like the classic secondlife://{REGION} -// However, the later syntax cannot support spaces in the region name because -// spaces (and %20 chars) are illegal in the hostname of an http URL. Some -// browsers let you get away with this, but some do not (such as Qt's Webkit). -// Hence we introduced the newer secondlife:///app/region alternative. -class LLRegionHandler : public LLCommandHandler -{ -public: - // requests will be throttled from a non-trusted browser - LLRegionHandler() : LLCommandHandler("region", UNTRUSTED_THROTTLE) {} - - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) - { - // make sure that we at least have a region name - int num_params = params.size(); - if (num_params < 1) - { - return false; - } + LLVector3 mLastCameraOrigin; + U32 mLastCameraUpdate; - // build a secondlife://{PLACE} SLurl from this SLapp - std::string url = "secondlife://"; - for (int i = 0; i < num_params; i++) - { - if (i > 0) - { - url += "/"; - } - url += params[i].asString(); - } - - // Process the SLapp as if it was a secondlife://{PLACE} SLurl - LLURLDispatcher::dispatch(url, "clicked", web, true); - return true; - } + void requestBaseCapabilitiesCoro(LLCoros::self& self, U64 regionHandle); + void requestBaseCapabilitiesCompleteCoro(LLCoros::self& self, U64 regionHandle); + void requestSimulatorFeatureCoro(LLCoros::self& self, std::string url, U64 regionHandle); }; -LLRegionHandler gRegionHandler; -class BaseCapabilitiesComplete : public LLHTTPClient::Responder +void LLViewerRegionImpl::requestBaseCapabilitiesCoro(LLCoros::self& self, U64 regionHandle) { - LOG_CLASS(BaseCapabilitiesComplete); -public: - BaseCapabilitiesComplete(U64 region_handle, S32 id) - : mRegionHandle(region_handle), mID(id) - { } - virtual ~BaseCapabilitiesComplete() - { } - - static BaseCapabilitiesComplete* build( U64 region_handle, S32 id ) - { - return new BaseCapabilitiesComplete(region_handle, id); - } - -private: - /* virtual */void httpFailure() - { - LL_WARNS("AppInit", "Capabilities") << dumpResponse() << LL_ENDL; - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); - if (regionp) - { - regionp->failedSeedCapability(); - } - } - - /* virtual */ void httpSuccess() - { - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); - if(!regionp) //region was removed - { - LL_WARNS("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL; - return ; - } - if( mID != regionp->getHttpResponderID() ) // region is no longer referring to this responder - { - LL_WARNS("AppInit", "Capabilities") << "Received results for a stale http responder!" << LL_ENDL; - regionp->failedSeedCapability(); - return ; - } - - const LLSD& content = getContent(); - if (!content.isMap()) - { - failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); - return; - } - LLSD::map_const_iterator iter; - for(iter = content.beginMap(); iter != content.endMap(); ++iter) - { - regionp->setCapability(iter->first, iter->second); + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("BaseCapabilitiesRequest", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - LL_DEBUGS("AppInit", "Capabilities") - << "Capability '" << iter->first << "' is '" << iter->second << "'" << LL_ENDL; + LLSD result; + LLViewerRegion *regionp = NULL; - /* HACK we're waiting for the ServerReleaseNotes */ - if (iter->first == "ServerReleaseNotes" && regionp->getReleaseNotesRequested()) - { - regionp->showReleaseNotes(); - } - } - - regionp->setCapabilitiesReceived(true); + // This loop is used for retrying a capabilities request. + do + { + regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); + if (!regionp) //region was removed + { + LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities for region that no longer exists!" << LL_ENDL; + return; // this error condition is not recoverable. + } + + std::string url = regionp->getCapability("Seed"); + if (url.empty()) + { + LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url!" << LL_ENDL; + return; // this error condition is not recoverable. + } + + // After a few attempts, continue login. But keep trying to get the caps: + if (mSeedCapAttempts >= mSeedCapMaxAttemptsBeforeLogin && + STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) + { + LLStartUp::setStartupState(STATE_SEED_CAP_GRANTED); + } + + if (mSeedCapAttempts > mSeedCapMaxAttempts) + { + // *TODO: Give a user pop-up about this error? + LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities from '" << url << "' after " << mSeedCapAttempts << " attempts. Giving up!" << LL_ENDL; + return; // this error condition is not recoverable. + } + + S32 id = ++mHttpResponderID; + ++mSeedCapAttempts; + + LLSD capabilityNames = LLSD::emptyArray(); + buildCapabilityNames(capabilityNames); + + LL_INFOS("AppInit", "Capabilities") << "Requesting seed from " << url + << " (attempt #" << mSeedCapAttempts << ")" << LL_ENDL; + + regionp = NULL; + result = httpAdapter->postAndYield(self, httpRequest, url, capabilityNames); + + regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); + if (!regionp) //region was removed + { + LL_WARNS("AppInit", "Capabilities") << "Received capabilities for region that no longer exists!" << LL_ENDL; + return; // this error condition is not recoverable. + } + + if (id != mHttpResponderID) // region is no longer referring to this request + { + LL_WARNS("AppInit", "Capabilities") << "Received results for a stale capabilities request!" << LL_ENDL; + // setup for retry. + continue; + } + + LLSD httpResults = result["http_result"]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults); + if (!status) + { + LL_WARNS("AppInit", "Capabilities") << "HttpStatus error " << LL_ENDL; + // setup for retry. + continue; + } + + // remove the http_result from the llsd + result.erase("http_result"); + + LLSD::map_const_iterator iter; + for (iter = result.beginMap(); iter != result.endMap(); ++iter) + { + regionp->setCapability(iter->first, iter->second); + + LL_DEBUGS("AppInit", "Capabilities") + << "Capability '" << iter->first << "' is '" << iter->second << "'" << LL_ENDL; + } + + regionp->setCapabilitiesReceived(true); + + if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) + { + LLStartUp::setStartupState(STATE_SEED_CAP_GRANTED); + } + + break; + } + while (true); + + if (regionp && regionp->isCapabilityAvailable("ServerReleaseNotes") && + regionp->getReleaseNotesRequested()) + { // *HACK: we're waiting for the ServerReleaseNotes + regionp->showReleaseNotes(); + } - if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) - { - LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); - } - } +} -private: - U64 mRegionHandle; - S32 mID; -}; -class BaseCapabilitiesCompleteTracker : public LLHTTPClient::Responder +void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(LLCoros::self& self, U64 regionHandle) { - LOG_CLASS(BaseCapabilitiesCompleteTracker); -public: - BaseCapabilitiesCompleteTracker( U64 region_handle) - : mRegionHandle(region_handle) - { } - - virtual ~BaseCapabilitiesCompleteTracker() - { } + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("BaseCapabilitiesRequest", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - static BaseCapabilitiesCompleteTracker* build( U64 region_handle ) - { - return new BaseCapabilitiesCompleteTracker( region_handle ); - } - -private: - /* virtual */ void httpFailure() - { - LL_WARNS() << dumpResponse() << LL_ENDL; - } - - /* virtual */ void httpSuccess() - { - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); - if( !regionp ) - { - LL_WARNS("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL; - return ; - } + LLSD result; + LLViewerRegion *regionp = NULL; - const LLSD& content = getContent(); - if (!content.isMap()) - { - failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); - return; - } - LLSD::map_const_iterator iter; - for(iter = content.beginMap(); iter != content.endMap(); ++iter) - { - regionp->setCapabilityDebug(iter->first, iter->second); - //LL_INFOS()<<"BaseCapabilitiesCompleteTracker New Caps "<first<<" "<< iter->second<getRegionImpl()->mCapabilities.size() != regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() ) - { - LL_WARNS("AppInit", "Capabilities") - << "Sim sent duplicate base caps that differ in size from what we initially received - most likely content. " - << "mCapabilities == " << regionp->getRegionImpl()->mCapabilities.size() - << " mSecondCapabilitiesTracker == " << regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() - << LL_ENDL; + // This loop is used for retrying a capabilities request. + do + { + regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); + if (!regionp) //region was removed + { + LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities for region that no longer exists!" << LL_ENDL; + break; // this error condition is not recoverable. + } + + std::string url = regionp->getCapabilityDebug("Seed"); + if (url.empty()) + { + LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url!" << LL_ENDL; + break; // this error condition is not recoverable. + } + + LLSD capabilityNames = LLSD::emptyArray(); + buildCapabilityNames(capabilityNames); + + LL_INFOS("AppInit", "Capabilities") << "Requesting second Seed from " << url << LL_ENDL; + + regionp = NULL; + result = httpAdapter->postAndYield(self, httpRequest, url, capabilityNames); + + LLSD httpResults = result["http_result"]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults); + if (!status) + { + LL_WARNS("AppInit", "Capabilities") << "HttpStatus error " << LL_ENDL; + break; // no retry + } + + regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); + if (!regionp) //region was removed + { + LL_WARNS("AppInit", "Capabilities") << "Received capabilities for region that no longer exists!" << LL_ENDL; + break; // this error condition is not recoverable. + } + + // remove the http_result from the llsd + result.erase("http_result"); + + LLSD::map_const_iterator iter; + for (iter = result.beginMap(); iter != result.endMap(); ++iter) + { + regionp->setCapabilityDebug(iter->first, iter->second); + //LL_INFOS()<<"BaseCapabilitiesCompleteTracker New Caps "<first<<" "<< iter->second<getRegionImpl()->mCapabilities); + log_capabilities(mCapabilities); - LL_WARNS("AppInit", "Capabilities") - << "Latest base capabilities: " << LL_ENDL; + LL_WARNS("AppInit", "Capabilities") + << "Latest base capabilities: " << LL_ENDL; - log_capabilities(regionp->getRegionImpl()->mSecondCapabilitiesTracker); + log_capabilities(mSecondCapabilitiesTracker); #endif - if (regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() > regionp->getRegionImpl()->mCapabilities.size() ) - { - // *HACK Since we were granted more base capabilities in this grant request than the initial, replace - // the old with the new. This shouldn't happen i.e. we should always get the same capabilities from a - // sim. The simulator fix from SH-3895 should prevent it from happening, at least in the case of the - // inventory api capability grants. - - // Need to clear a std::map before copying into it because old keys take precedence. - regionp->getRegionImplNC()->mCapabilities.clear(); - regionp->getRegionImplNC()->mCapabilities = regionp->getRegionImpl()->mSecondCapabilitiesTracker; - } - } - else - { - LL_DEBUGS("CrossingCaps") << "Sim sent multiple base cap grants with matching sizes." << LL_ENDL; - } - regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear(); - } + if (mSecondCapabilitiesTracker.size() > mCapabilities.size()) + { + // *HACK Since we were granted more base capabilities in this grant request than the initial, replace + // the old with the new. This shouldn't happen i.e. we should always get the same capabilities from a + // sim. The simulator fix from SH-3895 should prevent it from happening, at least in the case of the + // inventory api capability grants. + // Need to clear a std::map before copying into it because old keys take precedence. + mCapabilities.clear(); + mCapabilities = mSecondCapabilitiesTracker; + } + } + else + { + LL_DEBUGS("CrossingCaps") << "Sim sent multiple base cap grants with matching sizes." << LL_ENDL; + } + mSecondCapabilitiesTracker.clear(); + } + while (false); -private: - U64 mRegionHandle; -}; +} + +void LLViewerRegionImpl::requestSimulatorFeatureCoro(LLCoros::self& self, std::string url, U64 regionHandle) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("BaseCapabilitiesRequest", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLViewerRegion *regionp = NULL; + S32 attemptNumber = 0; + // This loop is used for retrying a capabilities request. + do + { + ++attemptNumber; + + if (attemptNumber > MAX_CAP_REQUEST_ATTEMPTS) + { + LL_WARNS("AppInit", "SimulatorFeatures") << "Retries count exceeded attempting to get Simulator feature from " + << url << LL_ENDL; + break; + } + + regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); + if (!regionp) //region was removed + { + LL_WARNS("AppInit", "SimulatorFeatures") << "Attempting to request Sim Feature for region that no longer exists!" << LL_ENDL; + break; // this error condition is not recoverable. + } + + regionp = NULL; + LLSD result = httpAdapter->getAndYield(self, httpRequest, url); + + LLSD httpResults = result["http_result"]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults); + if (!status) + { + LL_WARNS("AppInit", "SimulatorFeatures") << "HttpStatus error retrying" << LL_ENDL; + continue; + } + + // remove the http_result from the llsd + result.erase("http_result"); + + regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); + if (!regionp) //region was removed + { + LL_WARNS("AppInit", "SimulatorFeatures") << "Attempting to set Sim Feature for region that no longer exists!" << LL_ENDL; + break; // this error condition is not recoverable. + } + + regionp->setSimulatorFeatures(result); + + break; + } + while (true); + +} LLViewerRegion::LLViewerRegion(const U64 &handle, const LLHost &host, @@ -2800,15 +2873,14 @@ void LLViewerRegion::setSeedCapability(const std::string& url) if (getCapability("Seed") == url) { setCapabilityDebug("Seed", url); - LL_DEBUGS("CrossingCaps") << "Received duplicate seed capability, posting to seed " << + LL_WARNS("CrossingCaps") << "Received duplicate seed capability, posting to seed " << url << LL_ENDL; //Instead of just returning we build up a second set of seed caps and compare them //to the "original" seed cap received and determine why there is problem! - LLSD capabilityNames = LLSD::emptyArray(); - mImpl->buildCapabilityNames( capabilityNames ); - LLHTTPClient::post( url, capabilityNames, BaseCapabilitiesCompleteTracker::build(getHandle() ), - LLSD(), CAP_REQUEST_TIMEOUT ); + std::string coroname = + LLCoros::instance().launch("LLEnvironmentRequest::requestBaseCapabilitiesCompleteCoro", + boost::bind(&LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro, mImpl, _1, getHandle())); return; } @@ -2818,15 +2890,11 @@ void LLViewerRegion::setSeedCapability(const std::string& url) mImpl->mCapabilities.clear(); setCapability("Seed", url); - LLSD capabilityNames = LLSD::emptyArray(); - mImpl->buildCapabilityNames(capabilityNames); - - LL_INFOS() << "posting to seed " << url << LL_ENDL; + std::string coroname = + LLCoros::instance().launch("LLEnvironmentRequest::environmentRequestCoro", + boost::bind(&LLViewerRegionImpl::requestBaseCapabilitiesCoro, mImpl, _1, getHandle())); - S32 id = ++mImpl->mHttpResponderID; - LLHTTPClient::post(url, capabilityNames, - BaseCapabilitiesComplete::build(getHandle(), id), - LLSD(), CAP_REQUEST_TIMEOUT); + LL_INFOS("AppInit", "Capabilities") << "Launching " << coroname << " requesting seed capabilities from " << url << LL_ENDL; } S32 LLViewerRegion::getNumSeedCapRetries() @@ -2834,94 +2902,6 @@ S32 LLViewerRegion::getNumSeedCapRetries() return mImpl->mSeedCapAttempts; } -void LLViewerRegion::failedSeedCapability() -{ - // Should we retry asking for caps? - mImpl->mSeedCapAttempts++; - std::string url = getCapability("Seed"); - if ( url.empty() ) - { - LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url for retries!" << LL_ENDL; - return; - } - // After a few attempts, continue login. We will keep trying once in-world: - if ( mImpl->mSeedCapAttempts >= mImpl->mSeedCapMaxAttemptsBeforeLogin && - STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState() ) - { - LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); - } - - if ( mImpl->mSeedCapAttempts < mImpl->mSeedCapMaxAttempts) - { - LLSD capabilityNames = LLSD::emptyArray(); - mImpl->buildCapabilityNames(capabilityNames); - - LL_INFOS() << "posting to seed " << url << " (retry " - << mImpl->mSeedCapAttempts << ")" << LL_ENDL; - - S32 id = ++mImpl->mHttpResponderID; - LLHTTPClient::post(url, capabilityNames, - BaseCapabilitiesComplete::build(getHandle(), id), - LLSD(), CAP_REQUEST_TIMEOUT); - } - else - { - // *TODO: Give a user pop-up about this error? - LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities from '" << url << "' after " << mImpl->mSeedCapAttempts << " attempts. Giving up!" << LL_ENDL; - } -} - -class SimulatorFeaturesReceived : public LLHTTPClient::Responder -{ - LOG_CLASS(SimulatorFeaturesReceived); -public: - SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, - S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS) - : mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts) - { } - - /* virtual */ void httpFailure() - { - LL_WARNS("AppInit", "SimulatorFeatures") << dumpResponse() << LL_ENDL; - retry(); - } - - /* virtual */ void httpSuccess() - { - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); - if(!regionp) //region is removed or responder is not created. - { - LL_WARNS("AppInit", "SimulatorFeatures") - << "Received results for region that no longer exists!" << LL_ENDL; - return ; - } - - const LLSD& content = getContent(); - if (!content.isMap()) - { - failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); - return; - } - regionp->setSimulatorFeatures(content); - } - - void retry() - { - if (mAttempt < mMaxAttempts) - { - mAttempt++; - LL_WARNS("AppInit", "SimulatorFeatures") << "Re-trying '" << mRetryURL << "'. Retry #" << mAttempt << LL_ENDL; - LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this), LLSD(), CAP_REQUEST_TIMEOUT); - } - } - - std::string mRetryURL; - U64 mRegionHandle; - S32 mAttempt; - S32 mMaxAttempts; -}; - - void LLViewerRegion::setCapability(const std::string& name, const std::string& url) { if(name == "EventQueueGet") @@ -2937,7 +2917,11 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u else if (name == "SimulatorFeatures") { // kick off a request for simulator features - LLHTTPClient::get(url, new SimulatorFeaturesReceived(url, getHandle()), LLSD(), CAP_REQUEST_TIMEOUT); + std::string coroname = + LLCoros::instance().launch("LLViewerRegionImpl::requestSimulatorFeatureCoro", + boost::bind(&LLViewerRegionImpl::requestSimulatorFeatureCoro, mImpl, _1, url, getHandle())); + + LL_INFOS("AppInit", "SimulatorFeatures") << "Launching " << coroname << " requesting simulator features from " << url << LL_ENDL; } else { @@ -2960,9 +2944,20 @@ void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::stri mHttpUrl = url ; } } +} + +std::string LLViewerRegion::getCapabilityDebug(const std::string& name) const +{ + CapabilityMap::const_iterator iter = mImpl->mSecondCapabilitiesTracker.find(name); + if (iter == mImpl->mSecondCapabilitiesTracker.end()) + { + return ""; + } + return iter->second; } + bool LLViewerRegion::isSpecialCapabilityName(const std::string &name) { return name == "EventQueueGet" || name == "UntrustedSimulatorMessage"; diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index c14fa5aee8..d15f2eab20 100755 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -253,13 +253,14 @@ public: // Get/set named capability URLs for this region. void setSeedCapability(const std::string& url); - void failedSeedCapability(); S32 getNumSeedCapRetries(); void setCapability(const std::string& name, const std::string& url); void setCapabilityDebug(const std::string& name, const std::string& url); bool isCapabilityAvailable(const std::string& name) const; // implements LLCapabilityProvider virtual std::string getCapability(const std::string& name) const; + std::string getCapabilityDebug(const std::string& name) const; + // has region received its final (not seed) capability list? bool capabilitiesReceived() const; -- cgit v1.3 From cf4fec954ca46a139465144ccc3888b8fc7d41da Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Mon, 8 Jun 2015 17:29:01 -0700 Subject: Added a way to pass a policy Id to the coroadapter. Changed language, appearance, and maturity to conform to use the adapter rather than the SDHandler --- indra/llmessage/llcorehttputil.cpp | 22 ++- indra/llmessage/llcorehttputil.h | 18 ++- indra/newview/llagent.cpp | 193 ++++++++-------------- indra/newview/llagent.h | 18 ++- indra/newview/llagentlanguage.cpp | 27 ++-- indra/newview/llappearancemgr.cpp | 316 +++++++++++++------------------------ indra/newview/llappearancemgr.h | 3 + 7 files changed, 222 insertions(+), 375 deletions(-) (limited to 'indra/newview/llagent.cpp') diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index 1fd7e7be2e..9ccebabab4 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -848,10 +848,10 @@ LLCore::HttpStatus HttpCoroutineAdapter::getStatusFromLLSD(const LLSD &httpResul } /*static*/ -void HttpCoroutineAdapter::callbackHttpGet(const std::string &url, completionCallback_t success, completionCallback_t failure) +void HttpCoroutineAdapter::callbackHttpGet(const std::string &url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure) { LLCoros::instance().launch("HttpCoroutineAdapter::genericGetCoro", - boost::bind(&HttpCoroutineAdapter::trivialGetCoro, _1, url, success, failure)); + boost::bind(&HttpCoroutineAdapter::trivialGetCoro, _1, url, policyId, success, failure)); } /*static*/ @@ -865,13 +865,12 @@ void HttpCoroutineAdapter::messageHttpGet(const std::string &url, const std::str } /*static*/ -void HttpCoroutineAdapter::trivialGetCoro(LLCoros::self& self, std::string url, completionCallback_t success, completionCallback_t failure) +void HttpCoroutineAdapter::trivialGetCoro(LLCoros::self& self, std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure) { - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericGetCoro", httpPolicy)); + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericGetCoro", policyId)); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions, false); httpOpts->setWantHeaders(true); @@ -899,10 +898,10 @@ void HttpCoroutineAdapter::trivialGetCoro(LLCoros::self& self, std::string url, } /*static*/ -void HttpCoroutineAdapter::callbackHttpPost(const std::string &url, const LLSD &postData, completionCallback_t success, completionCallback_t failure) +void HttpCoroutineAdapter::callbackHttpPost(const std::string &url, LLCore::HttpRequest::policy_t policyId, const LLSD &postData, completionCallback_t success, completionCallback_t failure) { LLCoros::instance().launch("HttpCoroutineAdapter::genericPostCoro", - boost::bind(&HttpCoroutineAdapter::trivialPostCoro, _1, url, postData, success, failure)); + boost::bind(&HttpCoroutineAdapter::trivialPostCoro, _1, url, policyId, postData, success, failure)); } /*static*/ @@ -917,13 +916,12 @@ void HttpCoroutineAdapter::messageHttpPost(const std::string &url, const LLSD &p } /*static*/ -void HttpCoroutineAdapter::trivialPostCoro(LLCoros::self& self, std::string url, LLSD postData, completionCallback_t success, completionCallback_t failure) +void HttpCoroutineAdapter::trivialPostCoro(LLCoros::self& self, std::string url, LLCore::HttpRequest::policy_t policyId, LLSD postData, completionCallback_t success, completionCallback_t failure) { - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy)); + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", policyId)); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions, false); httpOpts->setWantHeaders(true); diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h index e6c9d2463c..e98399c985 100644 --- a/indra/llmessage/llcorehttputil.h +++ b/indra/llmessage/llcorehttputil.h @@ -427,10 +427,18 @@ public: /// should match this form. /// @sa callbackHttpGet /// @sa callbackHttpPost - typedef boost::function completionCallback_t; + typedef boost::function completionCallback_t; - static void callbackHttpGet(const std::string &url, completionCallback_t success = NULL, completionCallback_t failure = NULL); - static void callbackHttpPost(const std::string &url, const LLSD &postData, completionCallback_t success = NULL, completionCallback_t failure = NULL); + static void callbackHttpGet(const std::string &url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success = NULL, completionCallback_t failure = NULL); + static void callbackHttpGet(const std::string &url, completionCallback_t success = NULL, completionCallback_t failure = NULL) + { + callbackHttpGet(url, LLCore::HttpRequest::DEFAULT_POLICY_ID, success, failure); + } + static void callbackHttpPost(const std::string &url, LLCore::HttpRequest::policy_t policyId, const LLSD &postData, completionCallback_t success = NULL, completionCallback_t failure = NULL); + static void callbackHttpPost(const std::string &url, const LLSD &postData, completionCallback_t success = NULL, completionCallback_t failure = NULL) + { + callbackHttpPost(url, LLCore::HttpRequest::DEFAULT_POLICY_ID, postData, success, failure); + } /// Generic Get and post routines for HTTP via coroutines. /// These static methods do all required setup for the GET or POST operation. @@ -471,8 +479,8 @@ private: const std::string & url, LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers, HttpCoroHandler::ptr_t &handler); - static void trivialGetCoro(LLCoros::self& self, std::string url, completionCallback_t success, completionCallback_t failure); - static void trivialPostCoro(LLCoros::self& self, std::string url, LLSD postData, completionCallback_t success, completionCallback_t failure); + static void trivialGetCoro(LLCoros::self& self, std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure); + static void trivialPostCoro(LLCoros::self& self, std::string url, LLCore::HttpRequest::policy_t policyId, LLSD postData, completionCallback_t success, completionCallback_t failure); void checkDefaultHeaders(LLCore::HttpHeaders::ptr_t &headers); diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index b983a636b6..df304d66c3 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2550,83 +2550,6 @@ int LLAgent::convertTextToMaturity(char text) return LLAgentAccess::convertTextToMaturity(text); } -//========================================================================= -class LLMaturityHttpHandler : public LLHttpSDHandler -{ -public: - LLMaturityHttpHandler(LLAgent *agent, U8 preferred, U8 previous): - LLHttpSDHandler(), - mAgent(agent), - mPreferredMaturity(preferred), - mPreviousMaturity(previous) - { } - - virtual ~LLMaturityHttpHandler() - { } - -protected: - virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content); - virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status); - -private: - U8 parseMaturityFromServerResponse(const LLSD &pContent) const; - - LLAgent * mAgent; - U8 mPreferredMaturity; - U8 mPreviousMaturity; - -}; - -//------------------------------------------------------------------------- -void LLMaturityHttpHandler::onSuccess(LLCore::HttpResponse * response, const LLSD &content) -{ - U8 actualMaturity = parseMaturityFromServerResponse(content); - - if (actualMaturity != mPreferredMaturity) - { - LL_WARNS() << "while attempting to change maturity preference from '" - << LLViewerRegion::accessToString(mPreviousMaturity) - << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) - << "', the server responded with '" - << LLViewerRegion::accessToString(actualMaturity) - << "' [value:" << static_cast(actualMaturity) - << "], " << LL_ENDL; - } - mAgent->handlePreferredMaturityResult(actualMaturity); -} - -void LLMaturityHttpHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) -{ - LL_WARNS() << "while attempting to change maturity preference from '" - << LLViewerRegion::accessToString(mPreviousMaturity) - << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) - << "', " << LL_ENDL; - mAgent->handlePreferredMaturityError(); -} - -U8 LLMaturityHttpHandler::parseMaturityFromServerResponse(const LLSD &pContent) const -{ - U8 maturity = SIM_ACCESS_MIN; - - llassert(pContent.isDefined()); - llassert(pContent.isMap()); - llassert(pContent.has("access_prefs")); - llassert(pContent.get("access_prefs").isMap()); - llassert(pContent.get("access_prefs").has("max")); - llassert(pContent.get("access_prefs").get("max").isString()); - if (pContent.isDefined() && pContent.isMap() && pContent.has("access_prefs") - && pContent.get("access_prefs").isMap() && pContent.get("access_prefs").has("max") - && pContent.get("access_prefs").get("max").isString()) - { - LLSD::String actualPreference = pContent.get("access_prefs").get("max").asString(); - LLStringUtil::trim(actualPreference); - maturity = LLViewerRegion::shortStringToAccess(actualPreference); - } - - return maturity; -} -//========================================================================= - void LLAgent::handlePreferredMaturityResult(U8 pServerMaturity) { // Update the number of responses received @@ -2761,76 +2684,88 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) LL_WARNS("Agent") << "Region is not defined, can not change Maturity setting." << LL_ENDL; return; } - std::string url = getRegion()->getCapability("UpdateAgentInformation"); - - // If the capability is not defined, report it as an error - if (url.empty()) - { - LL_WARNS("Agent") << "'UpdateAgentInformation' is not defined for region" << LL_ENDL; - return; - } - - LLMaturityHttpHandler * handler = new LLMaturityHttpHandler(this, pPreferredMaturity, mLastKnownResponseMaturity); LLSD access_prefs = LLSD::emptyMap(); access_prefs["max"] = LLViewerRegion::accessToShortString(pPreferredMaturity); LLSD postData = LLSD::emptyMap(); postData["access_prefs"] = access_prefs; - LL_INFOS() << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity) - << "' via capability to: " << url << LL_ENDL; - - LLCore::HttpHandle handle = requestPostCapability("UpdateAgentInformation", url, postData, handler); + LL_INFOS() << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity) << LL_ENDL; - if (handle == LLCORE_HTTP_HANDLE_INVALID) - { - delete handler; - LL_WARNS("Agent") << "Maturity request post failed." << LL_ENDL; - } + if (!requestPostCapability("UpdateAgentInformation", postData, + static_cast(boost::bind(&LLAgent::processMaturityPreferenceFromServer, this, _1, pPreferredMaturity)), + static_cast(boost::bind(&LLAgent::handlePreferredMaturityError, this)) + )) + { + LL_WARNS("Agent") << "Maturity request post failed." << LL_ENDL; + } } } -// *TODO:RIDER Convert this system to using the coroutine scheme for HTTP communications -// -LLCore::HttpHandle LLAgent::requestPostCapability(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr) + +void LLAgent::processMaturityPreferenceFromServer(const LLSD &result, U8 perferredMaturity) { - LLHttpSDHandler * handler = (usrhndlr) ? usrhndlr : new LLHttpSDGenericHandler(cap); - LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, - mHttpPolicy, mHttpPriority, url, - postData, mHttpOptions, mHttpHeaders, handler); + U8 maturity = SIM_ACCESS_MIN; - if (handle == LLCORE_HTTP_HANDLE_INVALID) - { - // If no handler was passed in we delete the handler default handler allocated - // at the start of this function. - // *TODO: Change this metaphore to use boost::shared_ptr<> for handlers. Requires change in LLCore::HTTP - if (!usrhndlr) - delete handler; - LLCore::HttpStatus status = mHttpRequest->getStatus(); - LL_WARNS("Agent") << "'" << cap << "' request POST failed. Reason " - << status.toTerseString() << " \"" << status.toString() << "\"" << LL_ENDL; - } - return handle; + llassert(result.isDefined()); + llassert(result.isMap()); + llassert(result.has("access_prefs")); + llassert(result.get("access_prefs").isMap()); + llassert(result.get("access_prefs").has("max")); + llassert(result.get("access_prefs").get("max").isString()); + if (result.isDefined() && result.isMap() && result.has("access_prefs") + && result.get("access_prefs").isMap() && result.get("access_prefs").has("max") + && result.get("access_prefs").get("max").isString()) + { + LLSD::String actualPreference = result.get("access_prefs").get("max").asString(); + LLStringUtil::trim(actualPreference); + maturity = LLViewerRegion::shortStringToAccess(actualPreference); + } + + if (maturity != perferredMaturity) + { + LL_WARNS() << "while attempting to change maturity preference from '" + << LLViewerRegion::accessToString(mLastKnownResponseMaturity) + << "' to '" << LLViewerRegion::accessToString(perferredMaturity) + << "', the server responded with '" + << LLViewerRegion::accessToString(maturity) + << "' [value:" << static_cast(maturity) + << "], " << LL_ENDL; + } + handlePreferredMaturityResult(maturity); } -LLCore::HttpHandle LLAgent::requestGetCapability(const std::string &cap, const std::string &url, LLHttpSDHandler *usrhndlr) + +bool LLAgent::requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess, httpCallback_t cbFailure) { - LLHttpSDHandler * handler = (usrhndlr) ? usrhndlr : new LLHttpSDGenericHandler(cap); - LLCore::HttpHandle handle = mHttpRequest->requestGet(mHttpPolicy, mHttpPriority, - url, mHttpOptions.get(), mHttpHeaders.get(), handler); + std::string url; + + url = getRegion()->getCapability(capName); - if (handle == LLCORE_HTTP_HANDLE_INVALID) + if (url.empty()) { - // If no handler was passed in we delete the handler default handler allocated - // at the start of this function. - // *TODO: Change this metaphore to use boost::shared_ptr<> for handlers. Requires change in LLCore::HTTP - if (!usrhndlr) - delete handler; - LLCore::HttpStatus status = mHttpRequest->getStatus(); - LL_WARNS("Agent") << "'" << cap << "' request GET failed. Reason " - << status.toTerseString() << " \"" << status.toString() << "\"" << LL_ENDL; + LL_WARNS("Agent") << "Could not retrieve region capability \"" << capName << "\"" << LL_ENDL; + return false; } - return handle; + + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, mHttpPolicy, postData, cbSuccess, cbFailure); + return true; +} + +bool LLAgent::requestGetCapability(const std::string &capName, httpCallback_t cbSuccess, httpCallback_t cbFailure) +{ + std::string url; + + url = getRegion()->getCapability(capName); + + if (url.empty()) + { + LL_WARNS("Agent") << "Could not retrieve region capability \"" << capName << "\"" << LL_ENDL; + return false; + } + + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(url, mHttpPolicy, cbSuccess, cbFailure); + return true; } BOOL LLAgent::getAdminOverride() const diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 1bad35751f..745c0b063a 100755 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -36,9 +36,7 @@ #include "llpermissionsflags.h" #include "llevents.h" #include "v3dmath.h" -#include "httprequest.h" -#include "httpheaders.h" -#include "httpoptions.h" +#include "llcorehttputil.h" #include #include @@ -66,6 +64,8 @@ class LLUIColor; class LLTeleportRequest; class LLHttpSDHandler; + + typedef boost::shared_ptr LLTeleportRequestPtr; //-------------------------------------------------------------------- @@ -638,6 +638,8 @@ public: void setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange); private: + + friend class LLTeleportRequest; friend class LLTeleportRequestViaLandmark; friend class LLTeleportRequestViaLure; @@ -774,8 +776,8 @@ private: bool isMaturityPreferenceSyncedWithServer() const; void sendMaturityPreferenceToServer(U8 pPreferredMaturity); + void processMaturityPreferenceFromServer(const LLSD &result, U8 perferredMaturity); - friend class LLMaturityHttpHandler; void handlePreferredMaturityResult(U8 pServerMaturity); void handlePreferredMaturityError(); void reportPreferredMaturitySuccess(); @@ -929,10 +931,14 @@ public: ** UTILITY **/ public: + typedef LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t httpCallback_t; + /// Utilities for allowing the the agent sub managers to post and get via /// HTTP using the agent's policy settings and headers. - LLCore::HttpHandle requestPostCapability(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr = NULL); - LLCore::HttpHandle requestGetCapability(const std::string &cap, const std::string &url, LLHttpSDHandler *usrhndlr = NULL); + bool requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess = NULL, httpCallback_t cbFailure = NULL); + bool requestGetCapability(const std::string &capName, httpCallback_t cbSuccess = NULL, httpCallback_t cbFailure = NULL); +// LLCore::HttpHandle requestPostCapability(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr = NULL); +// LLCore::HttpHandle requestGetCapability(const std::string &cap, const std::string &url, LLHttpSDHandler *usrhndlr = NULL); /** Utility ** ** diff --git a/indra/newview/llagentlanguage.cpp b/indra/newview/llagentlanguage.cpp index 66aec42417..cdb0e3302d 100755 --- a/indra/newview/llagentlanguage.cpp +++ b/indra/newview/llagentlanguage.cpp @@ -55,26 +55,17 @@ void LLAgentLanguage::onChange() // static bool LLAgentLanguage::update() { - LLSD body; - std::string url; + LLSD body; - if (gAgent.getRegion()) - { - url = gAgent.getRegion()->getCapability("UpdateAgentLanguage"); - } - - if (!url.empty()) - { - std::string language = LLUI::getLanguage(); + std::string language = LLUI::getLanguage(); - body["language"] = language; - body["language_is_public"] = gSavedSettings.getBOOL("LanguageIsPublic"); + body["language"] = language; + body["language_is_public"] = gSavedSettings.getBOOL("LanguageIsPublic"); - LLCore::HttpHandle handle = gAgent.requestPostCapability("UpdateAgentLanguage", url, body); - if (handle == LLCORE_HTTP_HANDLE_INVALID) - { - LL_WARNS() << "Unable to change language." << LL_ENDL; - } - } + if (!gAgent.requestPostCapability("UpdateAgentLanguage", body)) + { + LL_WARNS("Language") << "Language capability unavailable." << LL_ENDL; + } + return true; } diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 59d2079b5d..5ad71369c3 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1245,196 +1245,6 @@ static void removeDuplicateItems(LLInventoryModel::item_array_t& items) items = new_items; } -//========================================================================= -#if 0 -// *TODO: -class LLAppearanceMgrHttpHandler -{ -public: - - static void apperanceMgrRequestCoro(LLCoros::self& self, std::string url); - -private: - LLAppearanceMgrHttpHandler(); - - static void debugCOF(const LLSD& content); - - -}; - -void LLAppearanceMgrHttpHandler::apperanceMgrRequestCoro(LLCoros::self& self, std::string url) -{ - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EnvironmentRequest", httpPolicy)); - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - - - -} - -#else - -// *TODO: Convert this and llavatar over to using the coroutine scheme rather -// than the responder for communications. (see block above for start...) - -class LLAppearanceMgrHttpHandler : public LLHttpSDHandler -{ -public: - LLAppearanceMgrHttpHandler(LLAppearanceMgr *mgr) : - LLHttpSDHandler(), - mManager(mgr) - { } - - virtual ~LLAppearanceMgrHttpHandler() - { } - - virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); - -protected: - virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content); - virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status); - -private: - static void debugCOF(const LLSD& content); - - LLAppearanceMgr *mManager; - -}; - -//------------------------------------------------------------------------- -void LLAppearanceMgrHttpHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response) -{ - mManager->decrementInFlightCounter(); - - LLHttpSDHandler::onCompleted(handle, response); -} - -void LLAppearanceMgrHttpHandler::onSuccess(LLCore::HttpResponse * response, const LLSD &content) -{ - if (!content.isMap()) - { - LLCore::HttpStatus status = LLCore::HttpStatus(HTTP_INTERNAL_ERROR, "Malformed response contents"); - response->setStatus(status); - onFailure(response, status); - if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) - { - debugCOF(content); - } - return; - } - if (content["success"].asBoolean()) - { - LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL; - if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) - { - dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", content); - } - } - else - { - LLCore::HttpStatus status = LLCore::HttpStatus(HTTP_INTERNAL_ERROR, "Non-success response"); - response->setStatus(status); - onFailure(response, status); - if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) - { - debugCOF(content); - } - return; - } -} - -void LLAppearanceMgrHttpHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) -{ - LL_WARNS("Avatar") << "Appearance Mgr request failed to " << response->getRequestURL() - << ". Reason code: (" << status.toTerseString() << ") " - << status.toString() << LL_ENDL; -} - -#endif - -void LLAppearanceMgrHttpHandler::debugCOF(const LLSD& content) -{ - dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_error", content); - - LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger() - << " ================================= " << LL_ENDL; - std::set ais_items, local_items; - const LLSD& cof_raw = content["cof_raw"]; - for (LLSD::array_const_iterator it = cof_raw.beginArray(); - it != cof_raw.endArray(); ++it) - { - const LLSD& item = *it; - if (item["parent_id"].asUUID() == LLAppearanceMgr::instance().getCOF()) - { - ais_items.insert(item["item_id"].asUUID()); - if (item["type"].asInteger() == 24) // link - { - LL_INFOS("Avatar") << "AIS Link: item_id: " << item["item_id"].asUUID() - << " linked_item_id: " << item["asset_id"].asUUID() - << " name: " << item["name"].asString() - << LL_ENDL; - } - else if (item["type"].asInteger() == 25) // folder link - { - LL_INFOS("Avatar") << "AIS Folder link: item_id: " << item["item_id"].asUUID() - << " linked_item_id: " << item["asset_id"].asUUID() - << " name: " << item["name"].asString() - << LL_ENDL; - } - else - { - LL_INFOS("Avatar") << "AIS Other: item_id: " << item["item_id"].asUUID() - << " linked_item_id: " << item["asset_id"].asUUID() - << " name: " << item["name"].asString() - << " type: " << item["type"].asInteger() - << LL_ENDL; - } - } - } - LL_INFOS("Avatar") << LL_ENDL; - LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() - << " ================================= " << LL_ENDL; - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), - cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH); - for (S32 i = 0; i < item_array.size(); i++) - { - const LLViewerInventoryItem* inv_item = item_array.at(i).get(); - local_items.insert(inv_item->getUUID()); - LL_INFOS("Avatar") << "LOCAL: item_id: " << inv_item->getUUID() - << " linked_item_id: " << inv_item->getLinkedUUID() - << " name: " << inv_item->getName() - << " parent: " << inv_item->getParentUUID() - << LL_ENDL; - } - LL_INFOS("Avatar") << " ================================= " << LL_ENDL; - S32 local_only = 0, ais_only = 0; - for (std::set::iterator it = local_items.begin(); it != local_items.end(); ++it) - { - if (ais_items.find(*it) == ais_items.end()) - { - LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << LL_ENDL; - local_only++; - } - } - for (std::set::iterator it = ais_items.begin(); it != ais_items.end(); ++it) - { - if (local_items.find(*it) == local_items.end()) - { - LL_INFOS("Avatar") << "AIS ONLY: " << *it << LL_ENDL; - ais_only++; - } - } - if (local_only == 0 && ais_only == 0) - { - LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req " - << content["observed"].asInteger() - << " rcv " << content["expected"].asInteger() - << ")" << LL_ENDL; - } -} //========================================================================= const LLUUID LLAppearanceMgr::getCOF() const @@ -3509,7 +3319,7 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() if (gAgentAvatarp->isEditingAppearance()) { - LL_WARNS("Avatar") << "Avatar editing appeance, not sending request." << LL_ENDL; + LL_WARNS("Avatar") << "Avatar editing appearance, not sending request." << LL_ENDL; // don't send out appearance updates if in appearance editing mode return; } @@ -3523,12 +3333,6 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() { LL_WARNS("Avatar") << "Region does not support baking" << LL_ENDL; } - std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance"); - if (url.empty()) - { - LL_WARNS("Avatar") << "No cap for UpdateAvatarAppearance." << LL_ENDL; - return; - } LLSD postData; S32 cof_version = LLAppearanceMgr::instance().getCOFVersion(); @@ -3544,9 +3348,6 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() postData["cof_version"] = cof_version + 999; } } - LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << LL_ENDL; - - LLAppearanceMgrHttpHandler * handler = new LLAppearanceMgrHttpHandler(this); mInFlightCounter++; mInFlightTimer.setTimerExpirySec(60.0); @@ -3554,15 +3355,120 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() llassert(cof_version >= gAgentAvatarp->mLastUpdateRequestCOFVersion); gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version; + if (!gAgent.requestPostCapability("UpdateAvatarAppearance", postData, + static_cast(boost::bind(&LLAppearanceMgr::serverAppearanceUpdateSuccess, this, _1)), + static_cast(boost::bind(&LLAppearanceMgr::decrementInFlightCounter, this)))) + { + LL_WARNS("Avatar") << "Unable to access UpdateAvatarAppearance in this region." << LL_ENDL; + } +} + +void LLAppearanceMgr::serverAppearanceUpdateSuccess(const LLSD &result) +{ + decrementInFlightCounter(); + if (result["success"].asBoolean()) + { + LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL; + if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + { + dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", result); + } + } + else + { + LL_WARNS("Avatar") << "Non success response for change appearance" << LL_ENDL; + if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + { + debugAppearanceUpdateCOF(result); + } + } +} - LLCore::HttpHandle handle = gAgent.requestPostCapability("UpdateAvatarAppearance", url, postData, handler); +/*static*/ +void LLAppearanceMgr::debugAppearanceUpdateCOF(const LLSD& content) +{ + dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_error", content); - if (handle == LLCORE_HTTP_HANDLE_INVALID) - { - delete handler; - } + LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger() + << " ================================= " << LL_ENDL; + std::set ais_items, local_items; + const LLSD& cof_raw = content["cof_raw"]; + for (LLSD::array_const_iterator it = cof_raw.beginArray(); + it != cof_raw.endArray(); ++it) + { + const LLSD& item = *it; + if (item["parent_id"].asUUID() == LLAppearanceMgr::instance().getCOF()) + { + ais_items.insert(item["item_id"].asUUID()); + if (item["type"].asInteger() == 24) // link + { + LL_INFOS("Avatar") << "AIS Link: item_id: " << item["item_id"].asUUID() + << " linked_item_id: " << item["asset_id"].asUUID() + << " name: " << item["name"].asString() + << LL_ENDL; + } + else if (item["type"].asInteger() == 25) // folder link + { + LL_INFOS("Avatar") << "AIS Folder link: item_id: " << item["item_id"].asUUID() + << " linked_item_id: " << item["asset_id"].asUUID() + << " name: " << item["name"].asString() + << LL_ENDL; + } + else + { + LL_INFOS("Avatar") << "AIS Other: item_id: " << item["item_id"].asUUID() + << " linked_item_id: " << item["asset_id"].asUUID() + << " name: " << item["name"].asString() + << " type: " << item["type"].asInteger() + << LL_ENDL; + } + } + } + LL_INFOS("Avatar") << LL_ENDL; + LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() + << " ================================= " << LL_ENDL; + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), + cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH); + for (S32 i = 0; i < item_array.size(); i++) + { + const LLViewerInventoryItem* inv_item = item_array.at(i).get(); + local_items.insert(inv_item->getUUID()); + LL_INFOS("Avatar") << "LOCAL: item_id: " << inv_item->getUUID() + << " linked_item_id: " << inv_item->getLinkedUUID() + << " name: " << inv_item->getName() + << " parent: " << inv_item->getParentUUID() + << LL_ENDL; + } + LL_INFOS("Avatar") << " ================================= " << LL_ENDL; + S32 local_only = 0, ais_only = 0; + for (std::set::iterator it = local_items.begin(); it != local_items.end(); ++it) + { + if (ais_items.find(*it) == ais_items.end()) + { + LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << LL_ENDL; + local_only++; + } + } + for (std::set::iterator it = ais_items.begin(); it != ais_items.end(); ++it) + { + if (local_items.find(*it) == local_items.end()) + { + LL_INFOS("Avatar") << "AIS ONLY: " << *it << LL_ENDL; + ais_only++; + } + } + if (local_only == 0 && ais_only == 0) + { + LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req " + << content["observed"].asInteger() + << " rcv " << content["expected"].asInteger() + << ")" << LL_ENDL; + } } + bool LLAppearanceMgr::testCOFRequestVersion() const { // If we have already received an update for this or higher cof version, ignore. diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 669d7242aa..3d9a1f1518 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -233,6 +233,9 @@ public: private: + void serverAppearanceUpdateSuccess(const LLSD &result); + static void debugAppearanceUpdateCOF(const LLSD& content); + std::string mAppearanceServiceURL; protected: -- cgit v1.3 From aba8d5e488d771f3d30ee75f0fbca30747adb7d1 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 9 Jun 2015 13:06:09 -0700 Subject: Removed homelocation responder (rolled into llagent) Removed sdhandler from llagent. Removed unused values from llacountingccostmgr Fixed smart pontier creation in llfacebook --- indra/llmessage/llavatarnamecache.cpp | 1 - indra/newview/CMakeLists.txt | 2 - indra/newview/llaccountingcostmanager.cpp | 4 -- indra/newview/llaccountingcostmanager.h | 2 - indra/newview/llagent.cpp | 100 +++++++++++++-------------- indra/newview/llagent.h | 12 +--- indra/newview/llfacebookconnect.cpp | 10 +-- indra/newview/llhomelocationresponder.cpp | 108 ------------------------------ indra/newview/llhomelocationresponder.h | 44 ------------ 9 files changed, 58 insertions(+), 225 deletions(-) delete mode 100755 indra/newview/llhomelocationresponder.cpp delete mode 100755 indra/newview/llhomelocationresponder.h (limited to 'indra/newview/llagent.cpp') diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 5d9daca37a..e4b8642c4d 100755 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -135,7 +135,6 @@ namespace LLAvatarNameCache // Erase expired names from cache void eraseUnrefreshed(); - //bool expirationFromCacheControl(LLCore::HttpHeaders *headers, F64 *expires); bool expirationFromCacheControl(const LLSD& headers, F64 *expires); // This is a coroutine. The only parameter that can be specified as a reference is the self diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3553e3a612..bebc82e847 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -326,7 +326,6 @@ set(viewer_SOURCE_FILES llgroupmgr.cpp llhasheduniqueid.cpp llhints.cpp - llhomelocationresponder.cpp llhttpretrypolicy.cpp llhudeffect.cpp llhudeffectbeam.cpp @@ -931,7 +930,6 @@ set(viewer_HEADER_FILES llhasheduniqueid.h llhints.h llhttpretrypolicy.h - llhomelocationresponder.h llhudeffect.h llhudeffectbeam.h llhudeffectlookat.h diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp index 6337fbe444..f928c84ecb 100755 --- a/indra/newview/llaccountingcostmanager.cpp +++ b/indra/newview/llaccountingcostmanager.cpp @@ -35,13 +35,9 @@ //=============================================================================== LLAccountingCostManager::LLAccountingCostManager(): mHttpRequest(), - mHttpHeaders(), - mHttpOptions(), mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID) { mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest()); - mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false); - mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false); //mHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID; } diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h index f4d45d43cb..34748894e3 100755 --- a/indra/newview/llaccountingcostmanager.h +++ b/indra/newview/llaccountingcostmanager.h @@ -80,8 +80,6 @@ private: void accountingCostCoro(LLCoros::self& self, std::string url, eSelectionType selectionType, const LLHandle observerHandle); LLCore::HttpRequest::ptr_t mHttpRequest; - LLCore::HttpHeaders::ptr_t mHttpHeaders; - LLCore::HttpOptions::ptr_t mHttpOptions; LLCore::HttpRequest::policy_t mHttpPolicy; }; //=============================================================================== diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index df304d66c3..230447b256 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -52,7 +52,6 @@ #include "llfloatertools.h" #include "llgroupactions.h" #include "llgroupmgr.h" -#include "llhomelocationresponder.h" #include "llhudmanager.h" #include "lljoystickbutton.h" #include "llmorphview.h" @@ -95,7 +94,6 @@ #include "lscript_byteformat.h" #include "stringize.h" #include "boost/foreach.hpp" -#include "llhttpsdhandler.h" #include "llcorehttputil.h" using namespace LLAvatarAppearanceDefines; @@ -363,11 +361,7 @@ LLAgent::LLAgent() : mMaturityPreferenceNumRetries(0U), mLastKnownRequestMaturity(SIM_ACCESS_MIN), mLastKnownResponseMaturity(SIM_ACCESS_MIN), - mHttpRequest(), - mHttpHeaders(), - mHttpOptions(), mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID), - mHttpPriority(0), mTeleportState(TELEPORT_NONE), mRegionp(NULL), @@ -470,15 +464,8 @@ void LLAgent::init() LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp()); - mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest()); - mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false); - mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false); mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_AGENT); - // Now ensure that we get regular callbacks to poll for completion. - mBoundListener = LLEventPumps::instance().obtain("mainloop"). - listen(LLEventPump::inventName(), boost::bind(&LLAgent::pollHttp, this, _1)); - mInitialized = TRUE; } @@ -496,10 +483,6 @@ void LLAgent::cleanup() { mTeleportFailedSlot.disconnect(); } - if (mBoundListener.connected()) - { - mBoundListener.disconnect(); - } } //----------------------------------------------------------------------------- @@ -522,17 +505,6 @@ LLAgent::~LLAgent() mTeleportSourceSLURL = NULL; } -//----------------------------------------------------------------------------- -// pollHttp -// Polling done once per frame on the "mainloop" to support HTTP processing. -//----------------------------------------------------------------------------- -bool LLAgent::pollHttp(const LLSD&) -{ - mHttpRequest->update(0L); - return false; -} - - // Handle any actions that need to be performed when the main app gains focus // (such as through alt-tab). //----------------------------------------------------------------------------- @@ -2359,27 +2331,9 @@ void LLAgent::setStartPosition( U32 location_id ) body["HomeLocation"] = homeLocation; - // This awkward idiom warrants explanation. - // For starters, LLSDMessage::ResponderAdapter is ONLY for testing the new - // LLSDMessage functionality with a pre-existing LLHTTPClient::Responder. - // In new code, define your reply/error methods on the same class as the - // sending method, bind them to local LLEventPump objects and pass those - // LLEventPump names in the request LLSD object. - // When testing old code, the new LLHomeLocationResponder object - // is referenced by an LLHTTPClient::ResponderPtr, so when the - // ResponderAdapter is deleted, the LLHomeLocationResponder will be too. - // We must trust that the underlying LLHTTPClient code will eventually - // fire either the reply callback or the error callback; either will cause - // the ResponderAdapter to delete itself. - LLSDMessage::ResponderAdapter* - adapter(new LLSDMessage::ResponderAdapter(new LLHomeLocationResponder())); - - request["message"] = "HomeLocation"; - request["payload"] = body; - request["reply"] = adapter->getReplyName(); - request["error"] = adapter->getErrorName(); - - gAgent.getRegion()->getCapAPI().post(request); + if (!requestPostCapability("HomeLocation", body, + boost::bind(&LLAgent::setStartPositionSuccess, this, _1))) + LL_WARNS() << "Unable to post to HomeLocation capability." << LL_ENDL; const U32 HOME_INDEX = 1; if( HOME_INDEX == location_id ) @@ -2388,6 +2342,53 @@ void LLAgent::setStartPosition( U32 location_id ) } } +void LLAgent::setStartPositionSuccess(const LLSD &result) +{ + LLVector3 agent_pos; + bool error = true; + + do { + // was the call to /agent//home-location successful? + // If not, we keep error set to true + if (!result.has("success")) + break; + + if (0 != strncmp("true", result["success"].asString().c_str(), 4)) + break; + + // did the simulator return a "justified" home location? + // If no, we keep error set to true + if (!result.has("HomeLocation")) + break; + + if ((!result["HomeLocation"].has("LocationPos")) || + (!result["HomeLocation"]["LocationPos"].has("X")) || + (!result["HomeLocation"]["LocationPos"].has("Y")) || + (!result["HomeLocation"]["LocationPos"].has("Z"))) + break; + + agent_pos.mV[VX] = result["HomeLocation"]["LocationPos"]["X"].asInteger(); + agent_pos.mV[VY] = result["HomeLocation"]["LocationPos"]["Y"].asInteger(); + agent_pos.mV[VZ] = result["HomeLocation"]["LocationPos"]["Z"].asInteger(); + + error = false; + + } while (0); + + if (error) + { + LL_WARNS() << "Error in response to home position set." << LL_ENDL; + } + else + { + LL_INFOS() << "setting home position" << LL_ENDL; + + LLViewerRegion *viewer_region = gAgent.getRegion(); + setHomePosRegion(viewer_region->getHandle(), agent_pos); + } +} + +#if 1 struct HomeLocationMapper: public LLCapabilityListener::CapabilityMapper { // No reply message expected @@ -2414,6 +2415,7 @@ struct HomeLocationMapper: public LLCapabilityListener::CapabilityMapper }; // Need an instance of this class so it will self-register static HomeLocationMapper homeLocationMapper; +#endif void LLAgent::requestStopMotion( LLMotion* motion ) { diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 745c0b063a..0ba3dea427 100755 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -62,7 +62,6 @@ class LLSLURL; class LLPauseRequestHandle; class LLUIColor; class LLTeleportRequest; -class LLHttpSDHandler; @@ -234,6 +233,8 @@ public: void setHomePosRegion(const U64& region_handle, const LLVector3& pos_region); BOOL getHomePosGlobal(LLVector3d* pos_global); private: + void setStartPositionSuccess(const LLSD &result); + BOOL mHaveHomePosition; U64 mHomeRegionHandle; LLVector3 mHomePosRegion; @@ -767,12 +768,7 @@ private: unsigned int mMaturityPreferenceNumRetries; U8 mLastKnownRequestMaturity; U8 mLastKnownResponseMaturity; - LLCore::HttpRequest::ptr_t mHttpRequest; - LLCore::HttpHeaders::ptr_t mHttpHeaders; - LLCore::HttpOptions::ptr_t mHttpOptions; LLCore::HttpRequest::policy_t mHttpPolicy; - LLCore::HttpRequest::priority_t mHttpPriority; - LLTempBoundListener mBoundListener; bool isMaturityPreferenceSyncedWithServer() const; void sendMaturityPreferenceToServer(U8 pPreferredMaturity); @@ -787,8 +783,6 @@ private: void handleMaturity(const LLSD &pNewValue); bool validateMaturity(const LLSD& newvalue); - bool pollHttp(const LLSD &); - /** Access ** ** @@ -937,8 +931,6 @@ public: /// HTTP using the agent's policy settings and headers. bool requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess = NULL, httpCallback_t cbFailure = NULL); bool requestGetCapability(const std::string &capName, httpCallback_t cbSuccess = NULL, httpCallback_t cbFailure = NULL); -// LLCore::HttpHandle requestPostCapability(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr = NULL); -// LLCore::HttpHandle requestGetCapability(const std::string &cap, const std::string &url, LLHttpSDHandler *usrhndlr = NULL); /** Utility ** ** diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index d1ed4e8ba4..a295910379 100755 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -131,7 +131,7 @@ void LLFacebookConnect::facebookConnectCoro(LLCoros::self& self, std::string aut LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy)); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions, false); LLSD putData; if (!authCode.empty()) @@ -217,7 +217,7 @@ void LLFacebookConnect::facebookShareCoro(LLCoros::self& self, std::string route LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy)); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions, false); httpOpts->setWantHeaders(true); @@ -239,8 +239,8 @@ void LLFacebookConnect::facebookShareImageCoro(LLCoros::self& self, std::string LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy)); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders); - LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders, false); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions, false); httpOpts->setWantHeaders(true); @@ -386,7 +386,7 @@ void LLFacebookConnect::facebookConnectInfoCoro(LLCoros::self& self) LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy)); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions, false); httpOpts->setWantHeaders(true); diff --git a/indra/newview/llhomelocationresponder.cpp b/indra/newview/llhomelocationresponder.cpp deleted file mode 100755 index d0492bcdb4..0000000000 --- a/indra/newview/llhomelocationresponder.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file llhomelocationresponder.cpp - * @author Meadhbh Hamrick - * @brief Processes responses to the HomeLocation CapReq - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -/* File Inclusions */ -#include "llviewerprecompiledheaders.h" - -#include "llhomelocationresponder.h" -#include "llsdutil.h" -#include "llagent.h" -#include "llviewerregion.h" - -void LLHomeLocationResponder::httpSuccess() -{ - const LLSD& content = getContent(); - LLVector3 agent_pos; - bool error = true; - - do { - - // was the call to /agent//home-location successful? - // If not, we keep error set to true - if( ! content.has("success") ) - { - break; - } - - if( 0 != strncmp("true", content["success"].asString().c_str(), 4 ) ) - { - break; - } - - // did the simulator return a "justified" home location? - // If no, we keep error set to true - if( ! content.has( "HomeLocation" ) ) - { - break; - } - - if( ! content["HomeLocation"].has("LocationPos") ) - { - break; - } - - if( ! content["HomeLocation"]["LocationPos"].has("X") ) - { - break; - } - - agent_pos.mV[VX] = content["HomeLocation"]["LocationPos"]["X"].asInteger(); - - if( ! content["HomeLocation"]["LocationPos"].has("Y") ) - { - break; - } - - agent_pos.mV[VY] = content["HomeLocation"]["LocationPos"]["Y"].asInteger(); - - if( ! content["HomeLocation"]["LocationPos"].has("Z") ) - { - break; - } - - agent_pos.mV[VZ] = content["HomeLocation"]["LocationPos"]["Z"].asInteger(); - - error = false; - } while( 0 ); - - if( error ) - { - failureResult(HTTP_INTERNAL_ERROR, "Invalid server response content", content); - } - else - { - LL_INFOS() << "setting home position" << LL_ENDL; - - LLViewerRegion *viewer_region = gAgent.getRegion(); - gAgent.setHomePosRegion( viewer_region->getHandle(), agent_pos ); - } -} - -void LLHomeLocationResponder::httpFailure() -{ - LL_WARNS() << dumpResponse() << LL_ENDL; -} diff --git a/indra/newview/llhomelocationresponder.h b/indra/newview/llhomelocationresponder.h deleted file mode 100755 index adc6c8cb58..0000000000 --- a/indra/newview/llhomelocationresponder.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @file llhomelocationresponder.h - * @author Meadhbh Hamrick - * @brief Processes responses to the HomeLocation CapReq - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - - /* Macro Definitions */ -#ifndef LL_LLHOMELOCATIONRESPONDER_H -#define LL_LLHOMELOCATIONRESPONDER_H - -/* File Inclusions */ -#include "llhttpclient.h" - -/* Typedef, Enum, Class, Struct, etc. */ -class LLHomeLocationResponder : public LLHTTPClient::Responder -{ - LOG_CLASS(LLHomeLocationResponder); -private: - /* virtual */ void httpSuccess(); - /* virtual */ void httpFailure(); -}; - -#endif -- cgit v1.3 From be1fa962dffd9601d65b480ddd2bb09c70ad5f89 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 9 Jun 2015 15:36:10 -0700 Subject: Removed dead code, llsdmessage, llcapabilitylistener and the associated tests. --- indra/llmessage/CMakeLists.txt | 18 -- indra/llmessage/llsdmessage.cpp | 168 -------------- indra/llmessage/llsdmessage.h | 168 -------------- indra/llmessage/tests/llsdmessage_test.cpp | 130 ----------- indra/newview/CMakeLists.txt | 10 - indra/newview/llagent.cpp | 31 --- indra/newview/llcapabilitylistener.cpp | 202 ---------------- indra/newview/llcapabilitylistener.h | 131 ----------- indra/newview/llviewerinventory.cpp | 23 +- indra/newview/llviewerregion.cpp | 46 +--- indra/newview/llviewerregion.h | 5 - indra/newview/tests/llcapabilitylistener_test.cpp | 271 ---------------------- 12 files changed, 20 insertions(+), 1183 deletions(-) delete mode 100755 indra/llmessage/llsdmessage.cpp delete mode 100755 indra/llmessage/llsdmessage.h delete mode 100755 indra/llmessage/tests/llsdmessage_test.cpp delete mode 100755 indra/newview/llcapabilitylistener.cpp delete mode 100755 indra/newview/llcapabilitylistener.h delete mode 100755 indra/newview/tests/llcapabilitylistener_test.cpp (limited to 'indra/newview/llagent.cpp') diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index abdb418224..57710049a5 100755 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -75,7 +75,6 @@ set(llmessage_SOURCE_FILES llpumpio.cpp llsdappservices.cpp llsdhttpserver.cpp - llsdmessage.cpp llsdmessagebuilder.cpp llsdmessagereader.cpp llsdrpcclient.cpp @@ -176,7 +175,6 @@ set(llmessage_HEADER_FILES llregionhandle.h llsdappservices.h llsdhttpserver.h - llsdmessage.h llsdmessagebuilder.h llsdmessagereader.h llsdrpcclient.h @@ -261,22 +259,6 @@ if (LL_TESTS) ${GOOGLEMOCK_LIBRARIES} ) - LL_ADD_INTEGRATION_TEST( - llsdmessage - "llsdmessage.cpp" - "${test_libs}" - ${PYTHON_EXECUTABLE} - "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py" - ) - - LL_ADD_INTEGRATION_TEST( - llhttpclient - "llhttpclient.cpp" - "${test_libs}" - ${PYTHON_EXECUTABLE} - "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py" - ) - LL_ADD_INTEGRATION_TEST(llavatarnamecache "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}") diff --git a/indra/llmessage/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp deleted file mode 100755 index 61fcc5dd2f..0000000000 --- a/indra/llmessage/llsdmessage.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/** - * @file llsdmessage.cpp - * @author Nat Goodspeed - * @date 2008-10-31 - * @brief Implementation for llsdmessage. - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#if LL_WINDOWS -#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want! -#endif - -// Precompiled header -#include "linden_common.h" -// associated header -#include "llsdmessage.h" -// STL headers -// std headers -// external library headers -// other Linden headers -#include "llevents.h" -#include "llsdserialize.h" -#include "llhttpclient.h" -#include "llmessageconfig.h" -#include "llhost.h" -#include "message.h" -#include "llsdutil.h" - -// Declare a static LLSDMessage instance to ensure that we have a listener as -// soon as someone tries to post on our canonical LLEventPump name. -static LLSDMessage httpListener; - -LLSDMessage::LLSDMessage(): - // Instantiating our own local LLEventPump with a string name the - // constructor is NOT allowed to tweak is a way of ensuring Singleton - // semantics: attempting to instantiate a second LLSDMessage object would - // throw LLEventPump::DupPumpName. - mEventPump("LLHTTPClient") -{ - mEventPump.listen("self", boost::bind(&LLSDMessage::httpListener, this, _1)); -} - -bool LLSDMessage::httpListener(const LLSD& request) -{ - // Extract what we want from the request object. We do it all up front - // partly to document what we expect. - LLSD::String url(request["url"]); - LLSD payload(request["payload"]); - LLSD::String reply(request["reply"]); - LLSD::String error(request["error"]); - LLSD::Real timeout(request["timeout"]); - // If the LLSD doesn't even have a "url" key, we doubt it was intended for - // this listener. - if (url.empty()) - { - std::ostringstream out; - out << "request event without 'url' key to '" << mEventPump.getName() << "'"; - throw ArgError(out.str()); - } - // Establish default timeout. This test relies on LLSD::asReal() returning - // exactly 0.0 for an undef value. - if (! timeout) - { - timeout = HTTP_REQUEST_EXPIRY_SECS; - } - LLHTTPClient::post(url, payload, - new LLSDMessage::EventResponder(LLEventPumps::instance(), - request, - url, "POST", reply, error), - LLSD(), // headers - (F32)timeout); - return false; -} - -void LLSDMessage::EventResponder::httpSuccess() -{ - // If our caller passed an empty replyPump name, they're not - // listening: this is a fire-and-forget message. Don't bother posting - // to the pump whose name is "". - if (! mReplyPump.empty()) - { - LLSD response(getContent()); - mReqID.stamp(response); - mPumps.obtain(mReplyPump).post(response); - } - else // default success handling - { - LL_INFOS("LLSDMessage::EventResponder") - << "'" << mMessage << "' to '" << mTarget << "' succeeded" - << LL_ENDL; - } -} - -void LLSDMessage::EventResponder::httpFailure() -{ - // If our caller passed an empty errorPump name, they're not - // listening: "default error handling is acceptable." Only post to an - // explicit pump name. - if (! mErrorPump.empty()) - { - LLSD info(mReqID.makeResponse()); - info["target"] = mTarget; - info["message"] = mMessage; - info["status"] = getStatus(); - info["reason"] = getReason(); - info["content"] = getContent(); - mPumps.obtain(mErrorPump).post(info); - } - else // default error handling - { - // convention seems to be to use LL_INFOS(), but that seems a bit casual? - LL_WARNS("LLSDMessage::EventResponder") - << "'" << mMessage << "' to '" << mTarget - << "' failed " << dumpResponse() << LL_ENDL; - } -} - -LLSDMessage::ResponderAdapter::ResponderAdapter(LLHTTPClient::ResponderPtr responder, - const std::string& name): - mResponder(responder), - mReplyPump(name + ".reply", true), // tweak name for uniqueness - mErrorPump(name + ".error", true) -{ - mReplyPump.listen("self", boost::bind(&ResponderAdapter::listener, this, _1, true)); - mErrorPump.listen("self", boost::bind(&ResponderAdapter::listener, this, _1, false)); -} - -bool LLSDMessage::ResponderAdapter::listener(const LLSD& payload, bool success) -{ - if (success) - { - mResponder->successResult(payload); - } - else - { - mResponder->failureResult(payload["status"].asInteger(), payload["reason"], payload["content"]); - } - - /*---------------- MUST BE LAST STATEMENT BEFORE RETURN ----------------*/ - delete this; - // Destruction of mResponder will usually implicitly free its referent as well - /*------------------------- NOTHING AFTER THIS -------------------------*/ - return false; -} - -void LLSDMessage::link() -{ -} diff --git a/indra/llmessage/llsdmessage.h b/indra/llmessage/llsdmessage.h deleted file mode 100755 index e5d532d6a4..0000000000 --- a/indra/llmessage/llsdmessage.h +++ /dev/null @@ -1,168 +0,0 @@ -/** - * @file llsdmessage.h - * @author Nat Goodspeed - * @date 2008-10-30 - * @brief API intended to unify sending capability, UDP and TCP messages: - * https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#if ! defined(LL_LLSDMESSAGE_H) -#define LL_LLSDMESSAGE_H - -#include "llerror.h" // LOG_CLASS() -#include "llevents.h" // LLEventPumps -#include "llhttpclient.h" -#include -#include - -class LLSD; - -/** - * Class managing the messaging API described in - * https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes - */ -class LLSDMessage -{ - LOG_CLASS(LLSDMessage); - -public: - LLSDMessage(); - - /// Exception if you specify arguments badly - struct ArgError: public std::runtime_error - { - ArgError(const std::string& what): - std::runtime_error(std::string("ArgError: ") + what) {} - }; - - /** - * The response idiom used by LLSDMessage -- LLEventPump names on which to - * post reply or error -- is designed for the case in which your - * reply/error handlers are methods on the same class as the method - * sending the message. Any state available to the sending method that - * must be visible to the reply/error methods can conveniently be stored - * on that class itself, if it's not already. - * - * The LLHTTPClient::Responder idiom requires a separate instance of a - * separate class so that it can dispatch to the code of interest by - * calling canonical virtual methods. Interesting state must be copied - * into that new object. - * - * With some trepidation, because existing response code is packaged in - * LLHTTPClient::Responder subclasses, we provide this adapter class - * for transitional purposes only. Instantiate a new heap - * ResponderAdapter with your new LLHTTPClient::ResponderPtr. Pass - * ResponderAdapter::getReplyName() and/or getErrorName() in your - * LLSDMessage (or LLViewerRegion::getCapAPI()) request event. The - * ResponderAdapter will call the appropriate Responder method, then - * @c delete itself. - */ - class ResponderAdapter - { - public: - /** - * Bind the new LLHTTPClient::Responder subclass instance. - * - * Passing the constructor a name other than the default is only - * interesting if you suspect some usage will lead to an exception or - * log message. - */ - ResponderAdapter(LLHTTPClient::ResponderPtr responder, - const std::string& name="ResponderAdapter"); - - /// EventPump name on which LLSDMessage should post reply event - std::string getReplyName() const { return mReplyPump.getName(); } - /// EventPump name on which LLSDMessage should post error event - std::string getErrorName() const { return mErrorPump.getName(); } - - private: - // We have two different LLEventStreams, though we route them both to - // the same listener, so that we can bind an extra flag identifying - // which case (reply or error) reached that listener. - bool listener(const LLSD&, bool success); - - LLHTTPClient::ResponderPtr mResponder; - LLEventStream mReplyPump, mErrorPump; - }; - - /** - * Force our implementation file to be linked with caller. The .cpp file - * contains a static instance of this class, which must be linked into the - * executable to support the canonical listener. But since the primary - * interface to that static instance is via a named LLEventPump rather - * than by direct reference, the linker doesn't necessarily perceive the - * necessity to bring in the translation unit. Referencing this dummy - * method forces the issue. - */ - static void link(); - -private: - friend class LLCapabilityListener; - /// Responder used for internal purposes by LLSDMessage and - /// LLCapabilityListener. Others should use higher-level APIs. - class EventResponder: public LLHTTPClient::Responder - { - LOG_CLASS(EventResponder); - public: - /** - * LLHTTPClient::Responder that dispatches via named LLEventPump instances. - * We bind LLEventPumps, even though it's an LLSingleton, for testability. - * We bind the string names of the desired LLEventPump instances rather - * than actually obtain()ing them so we only obtain() the one we're going - * to use. If the caller doesn't bother to listen() on it, the other pump - * may never materialize at all. - * @a target and @a message are only to clarify error processing. - * For a capability message, @a target should be the region description, - * @a message should be the capability name. - * For a service with a visible URL, pass the URL as @a target and the HTTP verb - * (e.g. "POST") as @a message. - */ - EventResponder(LLEventPumps& pumps, - const LLSD& request, - const std::string& target, const std::string& message, - const std::string& replyPump, const std::string& errorPump): - mPumps(pumps), - mReqID(request), - mTarget(target), - mMessage(message), - mReplyPump(replyPump), - mErrorPump(errorPump) - {} - - protected: - virtual void httpSuccess(); - virtual void httpFailure(); - - private: - LLEventPumps& mPumps; - LLReqID mReqID; - const std::string mTarget, mMessage, mReplyPump, mErrorPump; - }; - -private: - bool httpListener(const LLSD&); - LLEventStream mEventPump; -}; - -#endif /* ! defined(LL_LLSDMESSAGE_H) */ diff --git a/indra/llmessage/tests/llsdmessage_test.cpp b/indra/llmessage/tests/llsdmessage_test.cpp deleted file mode 100755 index 44b024a83f..0000000000 --- a/indra/llmessage/tests/llsdmessage_test.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @file llsdmessage_test.cpp - * @author Nat Goodspeed - * @date 2008-12-22 - * @brief Test of llsdmessage.h - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#if LL_WINDOWS -#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want! -#endif - -// Precompiled header -#include "linden_common.h" -// associated header -#include "llsdmessage.h" -// STL headers -#include -// std headers -#include -#include -// external library headers -// other Linden headers -#include "../test/lltut.h" -#include "../test/catch_and_store_what_in.h" -#include "llsdserialize.h" -#include "llevents.h" -#include "stringize.h" -#include "llhost.h" -#include "tests/networkio.h" -#include "tests/commtest.h" - -/***************************************************************************** -* TUT -*****************************************************************************/ -namespace tut -{ - struct llsdmessage_data: public commtest_data - { - LLEventPump& httpPump; - - llsdmessage_data(): - httpPump(pumps.obtain("LLHTTPClient")) - { - LLCurl::initClass(); - LLSDMessage::link(); - } - }; - typedef test_group llsdmessage_group; - typedef llsdmessage_group::object llsdmessage_object; - llsdmessage_group llsdmgr("llsdmessage"); - - template<> template<> - void llsdmessage_object::test<1>() - { - std::string threw; - // This should fail... - try - { - LLSDMessage localListener; - } - CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupPumpName) - ensure("second LLSDMessage should throw", ! threw.empty()); - } - - template<> template<> - void llsdmessage_object::test<2>() - { - LLSD request, body; - body["data"] = "yes"; - request["payload"] = body; - request["reply"] = replyPump.getName(); - request["error"] = errorPump.getName(); - bool threw = false; - try - { - httpPump.post(request); - } - catch (const LLSDMessage::ArgError&) - { - threw = true; - } - ensure("missing URL", threw); - } - - template<> template<> - void llsdmessage_object::test<3>() - { - LLSD request, body; - body["data"] = "yes"; - request["url"] = server + "got-message"; - request["payload"] = body; - request["reply"] = replyPump.getName(); - request["error"] = errorPump.getName(); - httpPump.post(request); - ensure("got response", netio.pump()); - ensure("success response", success); - ensure_equals(result["reply"].asString(), "success"); - - body["status"] = 499; - body["reason"] = "custom error message"; - request["url"] = server + "fail"; - request["payload"] = body; - httpPump.post(request); - ensure("got response", netio.pump()); - ensure("failure response", ! success); - ensure_equals(result["status"].asInteger(), body["status"].asInteger()); - ensure_equals(result["reason"].asString(), body["reason"].asString()); - } -} // namespace tut diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index bebc82e847..9949656fcc 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -142,7 +142,6 @@ set(viewer_SOURCE_FILES llbuycurrencyhtml.cpp llcallbacklist.cpp llcallingcard.cpp - llcapabilitylistener.cpp llcaphttpsender.cpp llchannelmanager.cpp llchatbar.cpp @@ -742,7 +741,6 @@ set(viewer_HEADER_FILES llbuycurrencyhtml.h llcallbacklist.h llcallingcard.h - llcapabilitylistener.h llcapabilityprovider.h llcaphttpsender.h llchannelmanager.h @@ -2298,7 +2296,6 @@ if (LL_TESTS) LL_ADD_PROJECT_UNIT_TESTS(${VIEWER_BINARY_NAME} "${viewer_TEST_SOURCE_FILES}") #set(TEST_DEBUG on) - set(test_sources llcapabilitylistener.cpp) ################################################## # DISABLING PRECOMPILED HEADERS USAGE FOR TESTS ################################################## @@ -2314,13 +2311,6 @@ if (LL_TESTS) ${GOOGLEMOCK_LIBRARIES} ) - LL_ADD_INTEGRATION_TEST(llcapabilitylistener - "${test_sources}" - "${test_libs}" - ${PYTHON_EXECUTABLE} - "${CMAKE_SOURCE_DIR}/llmessage/tests/test_llsdmessage_peer.py" - ) - if (LINUX) # llcommon uses `clock_gettime' which is provided by librt on linux. set(LIBRT_LIBRARY diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 230447b256..2060065c75 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -38,7 +38,6 @@ #include "llappearancemgr.h" #include "llanimationstates.h" #include "llcallingcard.h" -#include "llcapabilitylistener.h" #include "llchannelmanager.h" #include "llchicletbar.h" #include "llconsole.h" @@ -62,7 +61,6 @@ #include "llpaneltopinfobar.h" #include "llparcel.h" #include "llrendersphere.h" -#include "llsdmessage.h" #include "llsdutil.h" #include "llsky.h" #include "llslurl.h" @@ -2388,35 +2386,6 @@ void LLAgent::setStartPositionSuccess(const LLSD &result) } } -#if 1 -struct HomeLocationMapper: public LLCapabilityListener::CapabilityMapper -{ - // No reply message expected - HomeLocationMapper(): LLCapabilityListener::CapabilityMapper("HomeLocation") {} - virtual void buildMessage(LLMessageSystem* msg, - const LLUUID& agentID, - const LLUUID& sessionID, - const std::string& capabilityName, - const LLSD& payload) const - { - msg->newMessageFast(_PREHASH_SetStartLocationRequest); - msg->nextBlockFast( _PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, agentID); - msg->addUUIDFast(_PREHASH_SessionID, sessionID); - msg->nextBlockFast( _PREHASH_StartLocationData); - // corrected by sim - msg->addStringFast(_PREHASH_SimName, ""); - msg->addU32Fast(_PREHASH_LocationID, payload["HomeLocation"]["LocationId"].asInteger()); - msg->addVector3Fast(_PREHASH_LocationPos, - ll_vector3_from_sdmap(payload["HomeLocation"]["LocationPos"])); - msg->addVector3Fast(_PREHASH_LocationLookAt, - ll_vector3_from_sdmap(payload["HomeLocation"]["LocationLookAt"])); - } -}; -// Need an instance of this class so it will self-register -static HomeLocationMapper homeLocationMapper; -#endif - void LLAgent::requestStopMotion( LLMotion* motion ) { // Notify all avatars that a motion has stopped. diff --git a/indra/newview/llcapabilitylistener.cpp b/indra/newview/llcapabilitylistener.cpp deleted file mode 100755 index ef9b910ae5..0000000000 --- a/indra/newview/llcapabilitylistener.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/** - * @file llcapabilitylistener.cpp - * @author Nat Goodspeed - * @date 2009-01-07 - * @brief Implementation for llcapabilitylistener. - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -// Precompiled header -#include "llviewerprecompiledheaders.h" -// associated header -#include "llcapabilitylistener.h" -// STL headers -#include -// std headers -// external library headers -#include -// other Linden headers -#include "stringize.h" -#include "llcapabilityprovider.h" -#include "message.h" - -class LLCapabilityListener::CapabilityMappers: public LLSingleton -{ -public: - void registerMapper(const LLCapabilityListener::CapabilityMapper*); - void unregisterMapper(const LLCapabilityListener::CapabilityMapper*); - const LLCapabilityListener::CapabilityMapper* find(const std::string& cap) const; - - struct DupCapMapper: public std::runtime_error - { - DupCapMapper(const std::string& what): - std::runtime_error(std::string("DupCapMapper: ") + what) - {} - }; - -private: - friend class LLSingleton; - CapabilityMappers(); - - typedef std::map CapabilityMap; - CapabilityMap mMap; -}; - -LLCapabilityListener::LLCapabilityListener(const std::string& name, - LLMessageSystem* messageSystem, - const LLCapabilityProvider& provider, - const LLUUID& agentID, - const LLUUID& sessionID): - mEventPump(name), - mMessageSystem(messageSystem), - mProvider(provider), - mAgentID(agentID), - mSessionID(sessionID) -{ - mEventPump.listen("self", boost::bind(&LLCapabilityListener::capListener, this, _1)); -} - -bool LLCapabilityListener::capListener(const LLSD& request) -{ - // Extract what we want from the request object. We do it all up front - // partly to document what we expect. - LLSD::String cap(request["message"]); - LLSD payload(request["payload"]); - LLSD::String reply(request["reply"]); - LLSD::String error(request["error"]); - LLSD::Real timeout(request["timeout"]); - // If the LLSD doesn't even have a "message" key, we doubt it was intended - // for this listener. - if (cap.empty()) - { - LL_ERRS("capListener") << "capability request event without 'message' key to '" - << getCapAPI().getName() - << "' on region\n" << mProvider.getDescription() - << LL_ENDL; - return false; // in case fatal-error function isn't - } - // Establish default timeout. This test relies on LLSD::asReal() returning - // exactly 0.0 for an undef value. - if (! timeout) - { - timeout = HTTP_REQUEST_EXPIRY_SECS; - } - // Look up the url for the requested capability name. - std::string url = mProvider.getCapability(cap); - if (! url.empty()) - { - // This capability is supported by the region to which we're talking. - LLHTTPClient::post(url, payload, - new LLSDMessage::EventResponder(LLEventPumps::instance(), - request, - mProvider.getDescription(), - cap, reply, error), - LLSD(), // headers - timeout); - } - else - { - // Capability not supported -- do we have a registered mapper? - const CapabilityMapper* mapper = CapabilityMappers::instance().find(cap); - if (! mapper) // capability neither supported nor mapped - { - LL_ERRS("capListener") << "unsupported capability '" << cap << "' request to '" - << getCapAPI().getName() << "' on region\n" - << mProvider.getDescription() - << LL_ENDL; - } - else if (! mapper->getReplyName().empty()) // mapper expects reply support - { - LL_ERRS("capListener") << "Mapper for capability '" << cap - << "' requires unimplemented support for reply message '" - << mapper->getReplyName() - << "' on '" << getCapAPI().getName() << "' on region\n" - << mProvider.getDescription() - << LL_ENDL; - } - else - { - LL_INFOS("capListener") << "fallback invoked for capability '" << cap - << "' request to '" << getCapAPI().getName() - << "' on region\n" << mProvider.getDescription() - << LL_ENDL; - mapper->buildMessage(mMessageSystem, mAgentID, mSessionID, cap, payload); - mMessageSystem->sendReliable(mProvider.getHost()); - } - } - return false; -} - -LLCapabilityListener::CapabilityMapper::CapabilityMapper(const std::string& cap, const std::string& reply): - mCapName(cap), - mReplyName(reply) -{ - LLCapabilityListener::CapabilityMappers::instance().registerMapper(this); -} - -LLCapabilityListener::CapabilityMapper::~CapabilityMapper() -{ - LLCapabilityListener::CapabilityMappers::instance().unregisterMapper(this); -} - -LLSD LLCapabilityListener::CapabilityMapper::readResponse(LLMessageSystem* messageSystem) const -{ - return LLSD(); -} - -LLCapabilityListener::CapabilityMappers::CapabilityMappers() {} - -void LLCapabilityListener::CapabilityMappers::registerMapper(const LLCapabilityListener::CapabilityMapper* mapper) -{ - // Try to insert a new map entry by which we can look up the passed mapper - // instance. - std::pair inserted = - mMap.insert(CapabilityMap::value_type(mapper->getCapName(), mapper)); - // If we already have a mapper for that name, insert() merely located the - // existing iterator and returned false. It is a coding error to try to - // register more than one mapper for the same capability name. - if (! inserted.second) - { - throw DupCapMapper(std::string("Duplicate capability name ") + mapper->getCapName()); - } -} - -void LLCapabilityListener::CapabilityMappers::unregisterMapper(const LLCapabilityListener::CapabilityMapper* mapper) -{ - CapabilityMap::iterator found = mMap.find(mapper->getCapName()); - if (found != mMap.end()) - { - mMap.erase(found); - } -} - -const LLCapabilityListener::CapabilityMapper* -LLCapabilityListener::CapabilityMappers::find(const std::string& cap) const -{ - CapabilityMap::const_iterator found = mMap.find(cap); - if (found != mMap.end()) - { - return found->second; - } - return NULL; -} diff --git a/indra/newview/llcapabilitylistener.h b/indra/newview/llcapabilitylistener.h deleted file mode 100755 index e7535013e7..0000000000 --- a/indra/newview/llcapabilitylistener.h +++ /dev/null @@ -1,131 +0,0 @@ -/** - * @file llcapabilitylistener.h - * @author Nat Goodspeed - * @date 2009-01-07 - * @brief Provide an event-based API for capability requests - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#if ! defined(LL_LLCAPABILITYLISTENER_H) -#define LL_LLCAPABILITYLISTENER_H - -#include "llevents.h" // LLEventPump -#include "llsdmessage.h" // LLSDMessage::ArgError -#include "llerror.h" // LOG_CLASS() - -class LLCapabilityProvider; -class LLMessageSystem; -class LLSD; - -class LLCapabilityListener -{ - LOG_CLASS(LLCapabilityListener); -public: - LLCapabilityListener(const std::string& name, LLMessageSystem* messageSystem, - const LLCapabilityProvider& provider, - const LLUUID& agentID, const LLUUID& sessionID); - - /// Capability-request exception - typedef LLSDMessage::ArgError ArgError; - /// Get LLEventPump on which we listen for capability requests - /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities) - LLEventPump& getCapAPI() { return mEventPump; } - - /** - * Base class for mapping an as-yet-undeployed capability name to a (pair - * of) LLMessageSystem message(s). To map a capability name to such - * messages, derive a subclass of CapabilityMapper and declare a static - * instance in a translation unit known to be loaded. The mapping is not - * region-specific. If an LLViewerRegion's capListener() receives a - * request for a supported capability, it will use the capability's URL. - * If not, it will look for an applicable CapabilityMapper subclass - * instance. - */ - class CapabilityMapper - { - public: - /** - * Base-class constructor. Typically your subclass constructor will - * pass these parameters as literals. - * @param cap the capability name handled by this (subclass) instance - * @param reply the name of the response LLMessageSystem message. Omit - * if the LLMessageSystem message you intend to send doesn't prompt a - * reply message, or if you already handle that message in some other - * way. - */ - CapabilityMapper(const std::string& cap, const std::string& reply = ""); - virtual ~CapabilityMapper(); - /// query the capability name - std::string getCapName() const { return mCapName; } - /// query the reply message name - std::string getReplyName() const { return mReplyName; } - /** - * Override this method to build the LLMessageSystem message we should - * send instead of the requested capability message. DO NOT send that - * message: that will be handled by the caller. - */ - virtual void buildMessage(LLMessageSystem* messageSystem, - const LLUUID& agentID, - const LLUUID& sessionID, - const std::string& capabilityName, - const LLSD& payload) const = 0; - /** - * Override this method if you pass a non-empty @a reply - * LLMessageSystem message name to the constructor: that is, if you - * expect to receive an LLMessageSystem message in response to the - * message you constructed in buildMessage(). If you don't pass a @a - * reply message name, you need not override this method as it won't - * be called. - * - * Using LLMessageSystem message-reading operations, your - * readResponse() override should construct and return an LLSD object - * of the form you expect to receive from the real implementation of - * the capability you intend to invoke, when it finally goes live. - */ - virtual LLSD readResponse(LLMessageSystem* messageSystem) const; - - private: - const std::string mCapName; - const std::string mReplyName; - }; - -private: - /// Bind the LLCapabilityProvider passed to our ctor - const LLCapabilityProvider& mProvider; - - /// Post an event to this LLEventPump to invoke a capability message on - /// the bound LLCapabilityProvider's server - /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities) - LLEventStream mEventPump; - - LLMessageSystem* mMessageSystem; - LLUUID mAgentID, mSessionID; - - /// listener to process capability requests - bool capListener(const LLSD&); - - /// helper class for capListener() - class CapabilityMappers; -}; - -#endif /* ! defined(LL_LLCAPABILITYLISTENER_H) */ diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d112118082..9a20dea2aa 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1750,27 +1750,20 @@ void copy_inventory_from_notecard(const LLUUID& destination_id, return; } - // check capability to prevent a crash while LL_ERRS in LLCapabilityListener::capListener. See EXT-8459. - std::string url = viewer_region->getCapability("CopyInventoryFromNotecard"); - if (url.empty()) - { - LL_WARNS(LOG_NOTECARD) << "There is no 'CopyInventoryFromNotecard' capability" - << " for region: " << viewer_region->getName() - << LL_ENDL; - return; - } - - LLSD request, body; + LLSD body; body["notecard-id"] = notecard_inv_id; body["object-id"] = object_id; body["item-id"] = src->getUUID(); body["folder-id"] = destination_id; body["callback-id"] = (LLSD::Integer)callback_id; - request["message"] = "CopyInventoryFromNotecard"; - request["payload"] = body; - - viewer_region->getCapAPI().post(request); + /// *TODO: RIDER: This posts the request under the agents policy. + /// When I convert the inventory over this call should be moved under that + /// policy as well. + if (!gAgent.requestPostCapability("CopyInventoryFromNotecard", body)) + { + LL_WARNS() << "SIM does not have the capability to copy from notecard." << LL_ENDL; + } } void create_new_item(const std::string& name, diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index ddf64aa08b..5c25e03e09 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -48,7 +48,6 @@ #include "llavatarrenderinfoaccountant.h" #include "llcallingcard.h" #include "llcaphttpsender.h" -#include "llcapabilitylistener.h" #include "llcommandhandler.h" #include "lldir.h" #include "lleventpoll.h" @@ -151,29 +150,18 @@ LLRegionHandler gRegionHandler; class LLViewerRegionImpl { public: - LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host) - : mHost(host), - mCompositionp(NULL), - mEventPoll(NULL), - mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS), - mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN), - mSeedCapAttempts(0), - mHttpResponderID(0), - mLastCameraUpdate(0), - mLastCameraOrigin(), - mVOCachePartition(NULL), - mLandp(NULL), - // I'd prefer to set the LLCapabilityListener name to match the region - // name -- it's disappointing that's not available at construction time. - // We could instead store an LLCapabilityListener*, making - // setRegionNameAndZone() replace the instance. Would that pose - // consistency problems? Can we even request a capability before calling - // setRegionNameAndZone()? - // For testability -- the new Michael Feathers paradigm -- - // LLCapabilityListener binds all the globals it expects to need at - // construction time. - mCapabilityListener(host.getString(), gMessageSystem, *region, - gAgent.getID(), gAgent.getSessionID()) + LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host): + mHost(host), + mCompositionp(NULL), + mEventPoll(NULL), + mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS), + mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN), + mSeedCapAttempts(0), + mHttpResponderID(0), + mLastCameraUpdate(0), + mLastCameraOrigin(), + mVOCachePartition(NULL), + mLandp(NULL) {} void buildCapabilityNames(LLSD& capabilityNames); @@ -225,11 +213,6 @@ public: S32 mHttpResponderID; - /// Post an event to this LLCapabilityListener to invoke a capability message on - /// this LLViewerRegion's server - /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities) - LLCapabilityListener mCapabilityListener; - //spatial partitions for objects in this region std::vector mObjectPartition; @@ -638,11 +621,6 @@ LLViewerRegion::~LLViewerRegion() mImpl = NULL; } -LLEventPump& LLViewerRegion::getCapAPI() const -{ - return mImpl->mCapabilityListener.getCapAPI(); -} - /*virtual*/ const LLHost& LLViewerRegion::getHost() const { diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index c6df155cb5..8c4966369c 100755 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -61,7 +61,6 @@ class LLVOCache; class LLVOCacheEntry; class LLSpatialPartition; class LLEventPump; -class LLCapabilityListener; class LLDataPacker; class LLDataPackerBinaryBuffer; class LLHost; @@ -269,10 +268,6 @@ public: static bool isSpecialCapabilityName(const std::string &name); void logActiveCapabilities() const; - /// Get LLEventPump on which we listen for capability requests - /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities) - LLEventPump& getCapAPI() const; - /// implements LLCapabilityProvider /*virtual*/ const LLHost& getHost() const; const U64 &getHandle() const { return mHandle; } diff --git a/indra/newview/tests/llcapabilitylistener_test.cpp b/indra/newview/tests/llcapabilitylistener_test.cpp deleted file mode 100755 index bde991a01e..0000000000 --- a/indra/newview/tests/llcapabilitylistener_test.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/** - * @file llcapabilitylistener_test.cpp - * @author Nat Goodspeed - * @date 2008-12-31 - * @brief Test for llcapabilitylistener.cpp. - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -// Precompiled header -#include "../llviewerprecompiledheaders.h" -// Own header -#include "../llcapabilitylistener.h" -// STL headers -#include -#include -#include -// std headers -// external library headers -#include "boost/bind.hpp" -// other Linden headers -#include "../test/lltut.h" -#include "../llcapabilityprovider.h" -#include "lluuid.h" -#include "tests/networkio.h" -#include "tests/commtest.h" -#include "tests/wrapllerrs.h" -#include "message.h" -#include "stringize.h" - -#if defined(LL_WINDOWS) -#pragma warning(disable: 4355) // using 'this' in base-class ctor initializer expr -#endif - -/***************************************************************************** -* TestCapabilityProvider -*****************************************************************************/ -struct TestCapabilityProvider: public LLCapabilityProvider -{ - TestCapabilityProvider(const LLHost& host): - mHost(host) - {} - - std::string getCapability(const std::string& cap) const - { - CapMap::const_iterator found = mCaps.find(cap); - if (found != mCaps.end()) - return found->second; - // normal LLViewerRegion lookup failure mode - return ""; - } - void setCapability(const std::string& cap, const std::string& url) - { - mCaps[cap] = url; - } - const LLHost& getHost() const { return mHost; } - std::string getDescription() const { return "TestCapabilityProvider"; } - - LLHost mHost; - typedef std::map CapMap; - CapMap mCaps; -}; - -/***************************************************************************** -* Dummy LLMessageSystem methods -*****************************************************************************/ -/*==========================================================================*| -// This doesn't work because we're already linking in llmessage.a, and we get -// duplicate-symbol errors from the linker. Perhaps if I wanted to go through -// the exercise of providing dummy versions of every single symbol defined in -// message.o -- maybe some day. -typedef std::vector< std::pair > StringPairVector; -StringPairVector call_history; - -S32 LLMessageSystem::sendReliable(const LLHost& host) -{ - call_history.push_back(StringPairVector::value_type("sendReliable", stringize(host))); - return 0; -} -|*==========================================================================*/ - -/***************************************************************************** -* TUT -*****************************************************************************/ -namespace tut -{ - struct llcapears_data: public commtest_data - { - TestCapabilityProvider provider; - LLCapabilityListener regionListener; - LLEventPump& regionPump; - - llcapears_data(): - provider(host), - regionListener("testCapabilityListener", NULL, provider, LLUUID(), LLUUID()), - regionPump(regionListener.getCapAPI()) - { - LLCurl::initClass(); - provider.setCapability("good", server + "capability-test"); - provider.setCapability("fail", server + "fail"); - } - }; - typedef test_group llcapears_group; - typedef llcapears_group::object llcapears_object; - llcapears_group llsdmgr("llcapabilitylistener"); - - template<> template<> - void llcapears_object::test<1>() - { - LLSD request, body; - body["data"] = "yes"; - request["payload"] = body; - request["reply"] = replyPump.getName(); - request["error"] = errorPump.getName(); - std::string threw; - try - { - WrapLLErrs capture; - regionPump.post(request); - } - catch (const WrapLLErrs::FatalException& e) - { - threw = e.what(); - } - ensure_contains("missing capability name", threw, "without 'message' key"); - } - - template<> template<> - void llcapears_object::test<2>() - { - LLSD request, body; - body["data"] = "yes"; - request["message"] = "good"; - request["payload"] = body; - request["reply"] = replyPump.getName(); - request["error"] = errorPump.getName(); - regionPump.post(request); - ensure("got response", netio.pump()); - ensure("success response", success); - ensure_equals(result["reply"].asString(), "success"); - - body["status"] = 499; - body["reason"] = "custom error message"; - request["message"] = "fail"; - request["payload"] = body; - regionPump.post(request); - ensure("got response", netio.pump()); - ensure("failure response", ! success); - ensure_equals(result["status"].asInteger(), body["status"].asInteger()); - ensure_equals(result["reason"].asString(), body["reason"].asString()); - } - - template<> template<> - void llcapears_object::test<3>() - { - LLSD request, body; - body["data"] = "yes"; - request["message"] = "unknown"; - request["payload"] = body; - request["reply"] = replyPump.getName(); - request["error"] = errorPump.getName(); - std::string threw; - try - { - WrapLLErrs capture; - regionPump.post(request); - } - catch (const WrapLLErrs::FatalException& e) - { - threw = e.what(); - } - ensure_contains("bad capability name", threw, "unsupported capability"); - } - - struct TestMapper: public LLCapabilityListener::CapabilityMapper - { - // Instantiator gets to specify whether mapper expects a reply. - // I'd really like to be able to test CapabilityMapper::buildMessage() - // functionality, too, but -- even though LLCapabilityListener accepts - // the LLMessageSystem* that it passes to CapabilityMapper -- - // LLMessageSystem::sendReliable(const LLHost&) isn't virtual, so it's - // not helpful to pass a subclass instance. I suspect that making any - // LLMessageSystem methods virtual would provoke howls of outrage, - // given how heavily it's used. Nor can I just provide a local - // definition of LLMessageSystem::sendReliable(const LLHost&) because - // we're already linking in the rest of message.o via llmessage.a, and - // that produces duplicate-symbol link errors. - TestMapper(const std::string& replyMessage = std::string()): - LLCapabilityListener::CapabilityMapper("test", replyMessage) - {} - virtual void buildMessage(LLMessageSystem* msg, - const LLUUID& agentID, - const LLUUID& sessionID, - const std::string& capabilityName, - const LLSD& payload) const - { - msg->newMessageFast(_PREHASH_SetStartLocationRequest); - msg->nextBlockFast( _PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, agentID); - msg->addUUIDFast(_PREHASH_SessionID, sessionID); - msg->nextBlockFast( _PREHASH_StartLocationData); - // corrected by sim - msg->addStringFast(_PREHASH_SimName, ""); - msg->addU32Fast(_PREHASH_LocationID, payload["HomeLocation"]["LocationId"].asInteger()); -/*==========================================================================*| - msg->addVector3Fast(_PREHASH_LocationPos, - ll_vector3_from_sdmap(payload["HomeLocation"]["LocationPos"])); - msg->addVector3Fast(_PREHASH_LocationLookAt, - ll_vector3_from_sdmap(payload["HomeLocation"]["LocationLookAt"])); -|*==========================================================================*/ - } - }; - - template<> template<> - void llcapears_object::test<4>() - { - TestMapper testMapper("WantReply"); - LLSD request, body; - body["data"] = "yes"; - request["message"] = "test"; - request["payload"] = body; - request["reply"] = replyPump.getName(); - request["error"] = errorPump.getName(); - std::string threw; - try - { - WrapLLErrs capture; - regionPump.post(request); - } - catch (const WrapLLErrs::FatalException& e) - { - threw = e.what(); - } - ensure_contains("capability mapper wants reply", threw, "unimplemented support for reply message"); - } - - template<> template<> - void llcapears_object::test<5>() - { - TestMapper testMapper; - std::string threw; - try - { - TestMapper testMapper2; - } - catch (const std::runtime_error& e) - { - threw = e.what(); - } - ensure_contains("no dup cap mapper", threw, "DupCapMapper"); - } -} -- cgit v1.3 From 62527e6f18f0a035a234cf584e31f7eea93fd4a7 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 18 Aug 2015 17:05:29 -0400 Subject: MAINT-5506: Fix ugly timing bug in llurlentry static initialization. The problem was that class-static LLUrlEntryParcel::sRegionHost was being initialized by copying class-static LLHost::invalid. Naturally, these two statics are initialized in different source files. Since C++ makes no promises about the relative order in which objects in different object files are initialized, it seems we hit a case in which we were trying to initialize sRegionHost by copying a completely uninitialized LLHost::invalid. In general we might attempt to address such cross-translation-unit issues by introducing an LLSingleton. But in this particular case, the punch line is that LLHost::invalid is explicitly constructed identically to a default-constructed LLHost! In other words, LLHost::invalid provides nothing we couldn't get from LLHost(). All it gives us is an opportunity for glitches such as the above. Remove LLHost::invalid and all references, replacing with LLHost(). --- indra/llmessage/llassetstorage.cpp | 2 +- indra/llmessage/llcachename.cpp | 2 +- indra/llmessage/llhost.cpp | 2 -- indra/llmessage/llhost.h | 2 -- indra/llmessage/message.cpp | 2 +- indra/llui/llurlentry.cpp | 4 ++-- indra/llui/tests/llurlentry_stub.cpp | 2 -- indra/newview/llagent.cpp | 2 +- indra/newview/llfloatergodtools.cpp | 6 +++--- indra/newview/llpreviewnotecard.cpp | 2 +- indra/newview/llpreviewscript.cpp | 2 +- indra/newview/lltexturefetch.cpp | 8 ++++---- indra/newview/llviewerobject.cpp | 6 +++--- indra/newview/llviewertexture.h | 6 +++--- indra/newview/llviewertexturelist.cpp | 2 +- indra/newview/llvoavatar.cpp | 2 +- 16 files changed, 23 insertions(+), 29 deletions(-) (limited to 'indra/newview/llagent.cpp') diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 8ba2535531..a6edafecf8 100755 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -290,7 +290,7 @@ LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS *vfs, LLVFS *static_vfs) { - _init(msg, xfer, vfs, static_vfs, LLHost::invalid); + _init(msg, xfer, vfs, static_vfs, LLHost()); } diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index daf3e0b4de..66bd85f4e6 100755 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -259,7 +259,7 @@ LLCacheName::~LLCacheName() } LLCacheName::Impl::Impl(LLMessageSystem* msg) - : mMsg(msg), mUpstreamHost(LLHost::invalid) + : mMsg(msg), mUpstreamHost(LLHost()) { mMsg->setHandlerFuncFast( _PREHASH_UUIDNameRequest, handleUUIDNameRequest, (void**)this); diff --git a/indra/llmessage/llhost.cpp b/indra/llmessage/llhost.cpp index 63c15f0d5e..ae5c2ecf69 100755 --- a/indra/llmessage/llhost.cpp +++ b/indra/llmessage/llhost.cpp @@ -41,8 +41,6 @@ #include #endif -LLHost LLHost::invalid(INVALID_PORT,INVALID_HOST_IP_ADDRESS); - LLHost::LLHost(const std::string& ip_and_port) { std::string::size_type colon_index = ip_and_port.find(":"); diff --git a/indra/llmessage/llhost.h b/indra/llmessage/llhost.h index 9a221e2a6e..376371cffd 100755 --- a/indra/llmessage/llhost.h +++ b/indra/llmessage/llhost.h @@ -42,8 +42,6 @@ protected: U32 mIP; std::string mUntrustedSimCap; public: - - static LLHost invalid; // CREATORS LLHost() diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index feb756a0c7..6712171418 100755 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -1675,7 +1675,7 @@ LLHost LLMessageSystem::findHost(const U32 circuit_code) } else { - return LLHost::invalid; + return LLHost(); } } diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 6db0d88998..adefae6e2d 100755 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -957,7 +957,7 @@ std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const // LLUrlEntryParcel statics. LLUUID LLUrlEntryParcel::sAgentID(LLUUID::null); LLUUID LLUrlEntryParcel::sSessionID(LLUUID::null); -LLHost LLUrlEntryParcel::sRegionHost(LLHost::invalid); +LLHost LLUrlEntryParcel::sRegionHost; bool LLUrlEntryParcel::sDisconnected(false); std::set LLUrlEntryParcel::sParcelInfoObservers; @@ -1006,7 +1006,7 @@ std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelC void LLUrlEntryParcel::sendParcelInfoRequest(const LLUUID& parcel_id) { - if (sRegionHost == LLHost::invalid || sDisconnected) return; + if (sRegionHost == LLHost() || sDisconnected) return; LLMessageSystem *msg = gMessageSystem; msg->newMessage("ParcelInfoRequest"); diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index 5d3f9ac327..f01178c374 100755 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -165,8 +165,6 @@ LLFontGL* LLFontGL::getFontDefault() char const* const _PREHASH_AgentData = (char *)"AgentData"; char const* const _PREHASH_AgentID = (char *)"AgentID"; -LLHost LLHost::invalid(INVALID_PORT,INVALID_HOST_IP_ADDRESS); - LLMessageSystem* gMessageSystem = NULL; // diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 7147769c43..e7dd378edd 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -930,7 +930,7 @@ LLHost LLAgent::getRegionHost() const } else { - return LLHost::invalid; + return LLHost(); } } diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index 37774fbc5c..adc7f71586 100755 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -115,7 +115,7 @@ void LLFloaterGodTools::refreshAll() LLFloaterGodTools::LLFloaterGodTools(const LLSD& key) : LLFloater(key), - mCurrentHost(LLHost::invalid), + mCurrentHost(LLHost()), mUpdateTimer() { mFactoryMap["grid"] = LLCallbackMap(createPanelGrid, this); @@ -180,7 +180,7 @@ void LLFloaterGodTools::updatePopup(LLCoordGL center, MASK mask) // virtual void LLFloaterGodTools::draw() { - if (mCurrentHost == LLHost::invalid) + if (mCurrentHost == LLHost()) { if (mUpdateTimer.getElapsedTimeF32() > SECONDS_BETWEEN_UPDATE_REQUESTS) { @@ -325,7 +325,7 @@ void LLFloaterGodTools::sendRegionInfoRequest() { if (mPanelRegionTools) mPanelRegionTools->clearAllWidgets(); if (mPanelObjectTools) mPanelObjectTools->clearAllWidgets(); - mCurrentHost = LLHost::invalid; + mCurrentHost = LLHost(); mUpdateTimer.reset(); LLMessageSystem* msg = gMessageSystem; diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 2c609d902c..308b6ee922 100755 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -232,7 +232,7 @@ void LLPreviewNotecard::loadAsset() } else { - LLHost source_sim = LLHost::invalid; + LLHost source_sim = LLHost(); if (mObjectUUID.notNull()) { LLViewerObject *objectp = gObjectList.findObject(mObjectUUID); diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 11a503e71f..b6210bdc6b 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1571,7 +1571,7 @@ void LLPreviewLSL::loadAsset() if (gAgent.isGodlike() || (is_copyable && (is_modifiable || is_library))) { LLUUID* new_uuid = new LLUUID(mItemUUID); - gAssetStorage->getInvItemAsset(LLHost::invalid, + gAssetStorage->getInvItemAsset(LLHost(), gAgent.getID(), gAgent.getSessionID(), item->getPermissions().getOwner(), diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index e61eeb2f4e..6674532efa 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1328,11 +1328,11 @@ bool LLTextureFetchWorker::doWork(S32 param) static LLCachedControl use_http(gSavedSettings, "ImagePipelineUseHTTP", true); -// if (mHost != LLHost::invalid) get_url = false; +// if (mHost != LLHost()) get_url = false; if ( use_http && mCanUseHTTP && mUrl.empty())//get http url. { LLViewerRegion* region = NULL; - if (mHost == LLHost::invalid) + if (mHost == LLHost()) region = gAgent.getRegion(); else region = LLWorld::getInstance()->getRegion(mHost); @@ -3224,7 +3224,7 @@ void LLTextureFetch::sendRequestListToSimulators() { LLHost host = iter1->first; // invalid host = use agent host - if (host == LLHost::invalid) + if (host == LLHost()) { host = gAgent.getRegionHost(); } @@ -3304,7 +3304,7 @@ void LLTextureFetch::sendRequestListToSimulators() iter1 != mCancelQueue.end(); ++iter1) { LLHost host = iter1->first; - if (host == LLHost::invalid) + if (host == LLHost()) { host = gAgent.getRegionHost(); } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index ac3f07fcd8..190102ff0f 100755 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4437,21 +4437,21 @@ S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid) { // Invalid host == get from the agent's sim LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture( - uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost()); return setTETextureCore(te,image); } S32 LLViewerObject::setTENormalMap(const U8 te, const LLUUID& uuid) { LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( - uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost()); return setTENormalMapCore(te, image); } S32 LLViewerObject::setTESpecularMap(const U8 te, const LLUUID& uuid) { LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( - uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost()); return setTESpecularMapCore(te, image); } diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index aed7e94945..e496cb9f78 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -266,7 +266,7 @@ class LLViewerFetchedTexture : public LLViewerTexture protected: /*virtual*/ ~LLViewerFetchedTexture(); public: - LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); + LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), BOOL usemipmaps = TRUE); LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, BOOL usemipmaps); LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); @@ -498,7 +498,7 @@ protected: S32 mCachedRawDiscardLevel; BOOL mCachedRawImageReady; //the rez of the mCachedRawImage reaches the upper limit. - LLHost mTargetHost; // if LLHost::invalid, just request from agent's simulator + LLHost mTargetHost; // if invalid, just request from agent's simulator // Timers LLFrameTimer mLastPacketTimer; // Time since last packet. @@ -528,7 +528,7 @@ protected: /*virtual*/ ~LLViewerLODTexture(){} public: - LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); + LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), BOOL usemipmaps = TRUE); LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); /*virtual*/ S8 getType() const; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 926c40307b..0232dcfa15 100755 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -236,7 +236,7 @@ void LLViewerTextureList::shutdown() if (!image->hasGLTexture() || !image->getUseDiscard() || image->needsAux() || - image->getTargetHost() != LLHost::invalid || + image->getTargetHost() != LLHost() || !image->getUrl().empty() ) { diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index f753448770..db949437a7 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -8095,7 +8095,7 @@ LLHost LLVOAvatar::getObjectHost() const } else { - return LLHost::invalid; + return LLHost(); } } -- cgit v1.3 From 96e343b49b0b5a0951ffab0beb2e1d09c37bbdc5 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 1 Sep 2015 16:13:52 -0700 Subject: MAINT-5575: Convert the Experience cache into a coro based singleton. --HG-- branch : MAINT-5575 --- indra/llmessage/CMakeLists.txt | 2 + indra/llmessage/llcoproceduremanager.cpp | 414 +++++++++++++++ indra/llmessage/llcoproceduremanager.h | 98 ++++ indra/llmessage/llexperiencecache.cpp | 569 ++++++++++----------- indra/llmessage/llexperiencecache.h | 99 ++-- indra/llui/CMakeLists.txt | 2 + indra/llui/llurlentry.cpp | 4 +- indra/newview/CMakeLists.txt | 2 - indra/newview/llagent.cpp | 9 + indra/newview/llagent.h | 3 + indra/newview/llappviewer.cpp | 57 +-- indra/newview/llappviewer.h | 4 - indra/newview/llcoproceduremanager.cpp | 406 --------------- indra/newview/llcoproceduremanager.h | 87 ---- indra/newview/llexperienceassociationresponder.cpp | 2 +- indra/newview/llfloaterexperienceprofile.cpp | 10 +- indra/newview/llfloaterreporter.cpp | 2 +- indra/newview/llpanelexperiencelisteditor.cpp | 2 +- indra/newview/llpanelexperiencelog.cpp | 4 +- indra/newview/llpanelexperiencepicker.cpp | 2 +- indra/newview/llpreviewscript.cpp | 6 +- indra/newview/llstartup.cpp | 7 +- indra/newview/llviewermessage.cpp | 2 +- 23 files changed, 897 insertions(+), 896 deletions(-) create mode 100644 indra/llmessage/llcoproceduremanager.cpp create mode 100644 indra/llmessage/llcoproceduremanager.h delete mode 100644 indra/newview/llcoproceduremanager.cpp delete mode 100644 indra/newview/llcoproceduremanager.h (limited to 'indra/newview/llagent.cpp') diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 9739f7c607..12fc1bbcfc 100755 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -40,6 +40,7 @@ set(llmessage_SOURCE_FILES llchainio.cpp llcircuit.cpp llclassifiedflags.cpp + llcoproceduremanager.cpp llcorehttputil.cpp llcurl.cpp lldatapacker.cpp @@ -128,6 +129,7 @@ set(llmessage_HEADER_FILES llcipher.h llcircuit.h llclassifiedflags.h + llcoproceduremanager.h llcorehttputil.h llcurl.h lldatapacker.h diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp new file mode 100644 index 0000000000..062f2e6e42 --- /dev/null +++ b/indra/llmessage/llcoproceduremanager.cpp @@ -0,0 +1,414 @@ +/** +* @file LLCoprocedurePool.cpp +* @author Rider Linden +* @brief Singleton class for managing asset uploads to the sim. +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "linden_common.h" +#include "llcoproceduremanager.h" + +//========================================================================= +// Map of pool sizes for known pools +static std::map DefaultPoolSizes; + +// *TODO$: When C++11 this can be initialized here as follows: +// = {{"AIS", 25}, {"Upload", 1}} + +#define DEFAULT_POOL_SIZE 5 + +//========================================================================= +class LLCoprocedurePool: private boost::noncopyable +{ +public: + typedef LLCoprocedureManager::CoProcedure_t CoProcedure_t; + + LLCoprocedurePool(const std::string &name, size_t size); + virtual ~LLCoprocedurePool(); + + /// Places the coprocedure on the queue for processing. + /// + /// @param name Is used for debugging and should identify this coroutine. + /// @param proc Is a bound function to be executed + /// + /// @return This method returns a UUID that can be used later to cancel execution. + LLUUID enqueueCoprocedure(const std::string &name, CoProcedure_t proc); + + /// Cancel a coprocedure. If the coprocedure is already being actively executed + /// this method calls cancelYieldingOperation() on the associated HttpAdapter + /// If it has not yet been dequeued it is simply removed from the queue. + bool cancelCoprocedure(const LLUUID &id); + + /// Requests a shutdown of the upload manager. Passing 'true' will perform + /// an immediate kill on the upload coroutine. + void shutdown(bool hardShutdown = false); + + /// Returns the number of coprocedures in the queue awaiting processing. + /// + inline size_t countPending() const + { + return mPendingCoprocs.size(); + } + + /// Returns the number of coprocedures actively being processed. + /// + inline size_t countActive() const + { + return mActiveCoprocs.size(); + } + + /// Returns the total number of coprocedures either queued or in active processing. + /// + inline size_t count() const + { + return countPending() + countActive(); + } + +private: + struct QueuedCoproc + { + typedef boost::shared_ptr ptr_t; + + QueuedCoproc(const std::string &name, const LLUUID &id, CoProcedure_t proc) : + mName(name), + mId(id), + mProc(proc) + {} + + std::string mName; + LLUUID mId; + CoProcedure_t mProc; + }; + + // we use a deque here rather than std::queue since we want to be able to + // iterate through the queue and potentially erase an entry from the middle. + typedef std::deque CoprocQueue_t; + typedef std::map ActiveCoproc_t; + + std::string mPoolName; + size_t mPoolSize; + CoprocQueue_t mPendingCoprocs; + ActiveCoproc_t mActiveCoprocs; + bool mShutdown; + LLEventStream mWakeupTrigger; + + typedef std::map CoroAdapterMap_t; + LLCore::HttpRequest::policy_t mHTTPPolicy; + + CoroAdapterMap_t mCoroMapping; + + void coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter); + +}; + +//========================================================================= +LLCoprocedureManager::LLCoprocedureManager() +{ + DefaultPoolSizes.insert(std::map::value_type("Upload", 1)); + DefaultPoolSizes.insert(std::map::value_type("AIS", 25)); +} + +LLCoprocedureManager::~LLCoprocedureManager() +{ + +} + +LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std::string &poolName) +{ + // Attempt to look up a pool size in the configuration. If found use that + std::string keyName = "PoolSize" + poolName; + int size = 0; + + if (mPropertyQueryFn && !mPropertyQueryFn.empty()) + { + size = mPropertyQueryFn(keyName); + } + + if (size == 0) + { // if not found grab the know default... if there is no known + // default use a reasonable number like 5. + std::map::iterator it = DefaultPoolSizes.find(poolName); + if (it == DefaultPoolSizes.end()) + size = DEFAULT_POOL_SIZE; + else + size = (*it).second; + + if (mPropertyDefineFn && !mPropertyDefineFn.empty()) + mPropertyDefineFn(keyName, size, "Coroutine Pool size for " + poolName); + LL_WARNS() << "LLCoprocedureManager: No setting for \"" << keyName << "\" setting pool size to default of " << size << LL_ENDL; + } + + poolPtr_t pool = poolPtr_t(new LLCoprocedurePool(poolName, size)); + mPoolMap.insert(poolMap_t::value_type(poolName, pool)); + + return pool; +} + +//------------------------------------------------------------------------- +LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc) +{ + // Attempt to find the pool and enqueue the procedure. If the pool does + // not exist, create it. + poolPtr_t targetPool; + poolMap_t::iterator it = mPoolMap.find(pool); + + if (it == mPoolMap.end()) + { + targetPool = initializePool(pool); + } + else + { + targetPool = (*it).second; + } + + if (!targetPool) + { + LL_WARNS() << "LLCoprocedureManager unable to create coprocedure pool named \"" << pool << "\"" << LL_ENDL; + return LLUUID::null; + } + + return targetPool->enqueueCoprocedure(name, proc); +} + +void LLCoprocedureManager::cancelCoprocedure(const LLUUID &id) +{ + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + if ((*it).second->cancelCoprocedure(id)) + return; + } + LL_INFOS() << "Coprocedure not found." << LL_ENDL; +} + +void LLCoprocedureManager::shutdown(bool hardShutdown) +{ + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + (*it).second->shutdown(hardShutdown); + } + mPoolMap.clear(); +} + +void LLCoprocedureManager::setPropertyMethods(SettingQuery_t queryfn, SettingUpdate_t updatefn) +{ + mPropertyQueryFn = queryfn; + mPropertyDefineFn = updatefn; +} + +//------------------------------------------------------------------------- +size_t LLCoprocedureManager::countPending() const +{ + size_t count = 0; + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + count += (*it).second->countPending(); + } + return count; +} + +size_t LLCoprocedureManager::countPending(const std::string &pool) const +{ + poolMap_t::const_iterator it = mPoolMap.find(pool); + + if (it == mPoolMap.end()) + return 0; + return (*it).second->countPending(); +} + +size_t LLCoprocedureManager::countActive() const +{ + size_t count = 0; + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + count += (*it).second->countActive(); + } + return count; +} + +size_t LLCoprocedureManager::countActive(const std::string &pool) const +{ + poolMap_t::const_iterator it = mPoolMap.find(pool); + + if (it == mPoolMap.end()) + return 0; + return (*it).second->countActive(); +} + +size_t LLCoprocedureManager::count() const +{ + size_t count = 0; + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + count += (*it).second->count(); + } + return count; +} + +size_t LLCoprocedureManager::count(const std::string &pool) const +{ + poolMap_t::const_iterator it = mPoolMap.find(pool); + + if (it == mPoolMap.end()) + return 0; + return (*it).second->count(); +} + +//========================================================================= +LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size): + mPoolName(poolName), + mPoolSize(size), + mPendingCoprocs(), + mShutdown(false), + mWakeupTrigger("CoprocedurePool" + poolName, true), + mCoroMapping(), + mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID) +{ + for (size_t count = 0; count < mPoolSize; ++count) + { + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter = + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t( + new LLCoreHttpUtil::HttpCoroutineAdapter( mPoolName + "Adapter", mHTTPPolicy)); + + std::string uploadCoro = LLCoros::instance().launch("LLCoprocedurePool("+mPoolName+")::coprocedureInvokerCoro", + boost::bind(&LLCoprocedurePool::coprocedureInvokerCoro, this, httpAdapter)); + + mCoroMapping.insert(CoroAdapterMap_t::value_type(uploadCoro, httpAdapter)); + } + + LL_INFOS() << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items." << LL_ENDL; + + mWakeupTrigger.post(LLSD()); +} + +LLCoprocedurePool::~LLCoprocedurePool() +{ + shutdown(); +} + +//------------------------------------------------------------------------- +void LLCoprocedurePool::shutdown(bool hardShutdown) +{ + CoroAdapterMap_t::iterator it; + + for (it = mCoroMapping.begin(); it != mCoroMapping.end(); ++it) + { + if (!(*it).first.empty()) + { + if (hardShutdown) + { + LLCoros::instance().kill((*it).first); + } + } + if ((*it).second) + { + (*it).second->cancelYieldingOperation(); + } + } + + mShutdown = true; + mCoroMapping.clear(); + mPendingCoprocs.clear(); +} + +//------------------------------------------------------------------------- +LLUUID LLCoprocedurePool::enqueueCoprocedure(const std::string &name, LLCoprocedurePool::CoProcedure_t proc) +{ + LLUUID id(LLUUID::generateNewID()); + + mPendingCoprocs.push_back(QueuedCoproc::ptr_t(new QueuedCoproc(name, id, proc))); + LL_INFOS() << "Coprocedure(" << name << ") enqueued with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; + + mWakeupTrigger.post(LLSD()); + + return id; +} + +bool LLCoprocedurePool::cancelCoprocedure(const LLUUID &id) +{ + // first check the active coroutines. If there, remove it and return. + ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(id); + if (itActive != mActiveCoprocs.end()) + { + LL_INFOS() << "Found and canceling active coprocedure with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; + (*itActive).second->cancelYieldingOperation(); + mActiveCoprocs.erase(itActive); + return true; + } + + for (CoprocQueue_t::iterator it = mPendingCoprocs.begin(); it != mPendingCoprocs.end(); ++it) + { + if ((*it)->mId == id) + { + LL_INFOS() << "Found and removing queued coroutine(" << (*it)->mName << ") with Id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; + mPendingCoprocs.erase(it); + return true; + } + } + + LL_INFOS() << "Coprocedure with Id=" << id.asString() << " was not found." << " in pool \"" << mPoolName << "\"" << LL_ENDL; + return false; +} + +//------------------------------------------------------------------------- +void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter) +{ + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + while (!mShutdown) + { + llcoro::waitForEventOn(mWakeupTrigger); + if (mShutdown) + break; + + while (!mPendingCoprocs.empty()) + { + QueuedCoproc::ptr_t coproc = mPendingCoprocs.front(); + mPendingCoprocs.pop_front(); + mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)); + + LL_INFOS() << "Dequeued and invoking coprocedure(" << coproc->mName << ") with id=" << coproc->mId.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; + + try + { + coproc->mProc(httpAdapter, coproc->mId); + } + catch (std::exception &e) + { + LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() << + " threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL; + } + catch (...) + { + LL_WARNS() << "A non std::exception was thrown from " << coproc->mName << " with id=" << coproc->mId << "." << " in pool \"" << mPoolName << "\"" << LL_ENDL; + } + + LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL; + + ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(coproc->mId); + if (itActive != mActiveCoprocs.end()) + { + mActiveCoprocs.erase(itActive); + } + } + } +} diff --git a/indra/llmessage/llcoproceduremanager.h b/indra/llmessage/llcoproceduremanager.h new file mode 100644 index 0000000000..497367b80c --- /dev/null +++ b/indra/llmessage/llcoproceduremanager.h @@ -0,0 +1,98 @@ +/** +* @file llcoproceduremanager.h +* @author Rider Linden +* @brief Singleton class for managing asset uploads to the sim. +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#ifndef LL_COPROCEDURE_MANAGER_H +#define LL_COPROCEDURE_MANAGER_H + +#include "lleventcoro.h" +#include "llcoros.h" +#include "llcorehttputil.h" +#include "lluuid.h" + +class LLCoprocedurePool; + +class LLCoprocedureManager : public LLSingleton < LLCoprocedureManager > +{ + friend class LLSingleton < LLCoprocedureManager > ; + +public: + typedef boost::function SettingQuery_t; + typedef boost::function SettingUpdate_t; + + typedef boost::function CoProcedure_t; + + LLCoprocedureManager(); + virtual ~LLCoprocedureManager(); + + /// Places the coprocedure on the queue for processing. + /// + /// @param name Is used for debugging and should identify this coroutine. + /// @param proc Is a bound function to be executed + /// + /// @return This method returns a UUID that can be used later to cancel execution. + LLUUID enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc); + + /// Cancel a coprocedure. If the coprocedure is already being actively executed + /// this method calls cancelYieldingOperation() on the associated HttpAdapter + /// If it has not yet been dequeued it is simply removed from the queue. + void cancelCoprocedure(const LLUUID &id); + + /// Requests a shutdown of the upload manager. Passing 'true' will perform + /// an immediate kill on the upload coroutine. + void shutdown(bool hardShutdown = false); + + void setPropertyMethods(SettingQuery_t queryfn, SettingUpdate_t updatefn); + + /// Returns the number of coprocedures in the queue awaiting processing. + /// + size_t countPending() const; + size_t countPending(const std::string &pool) const; + + /// Returns the number of coprocedures actively being processed. + /// + size_t countActive() const; + size_t countActive(const std::string &pool) const; + + /// Returns the total number of coprocedures either queued or in active processing. + /// + size_t count() const; + size_t count(const std::string &pool) const; + +private: + + typedef boost::shared_ptr poolPtr_t; + typedef std::map poolMap_t; + + poolMap_t mPoolMap; + + poolPtr_t initializePool(const std::string &poolName); + + SettingQuery_t mPropertyQueryFn; + SettingUpdate_t mPropertyDefineFn; +}; + +#endif diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp index 34c4210359..36a4fc8823 100644 --- a/indra/llmessage/llexperiencecache.cpp +++ b/indra/llmessage/llexperiencecache.cpp @@ -26,53 +26,51 @@ #include "llexperiencecache.h" #include "llavatarname.h" -#include "llframetimer.h" #include "llhttpclient.h" #include "llsdserialize.h" +#include "llcoros.h" +#include "lleventcoro.h" +#include "lleventfilter.h" +#include "llcoproceduremanager.h" +#include "lldir.h" #include #include -#include "boost/tokenizer.hpp" +#include #include - -typedef std::map KeyMap; -KeyMap privateToPublicKeyMap; - - -std::string sLookupURL; - -typedef std::map pending_queue_t; -pending_queue_t sPendingQueue; - -int sMaximumLookups = 10; - -LLFrameTimer sRequestTimer; - -// Periodically clean out expired entries from the cache -LLFrameTimer sEraseExpiredTimer; - - //========================================================================= namespace LLExperienceCacheImpl { - bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age); void mapKeys(const LLSD& legacyKeys); + F64 getErrorRetryDeltaTime(S32 status, LLSD headers); + bool maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age); + + static const std::string PRIVATE_KEY = "private_id"; + static const std::string EXPERIENCE_ID = "public_id"; + + static const std::string MAX_AGE("max-age"); + static const boost::char_separator EQUALS_SEPARATOR("="); + static const boost::char_separator COMMA_SEPARATOR(","); + + // *TODO$: this seems to be tied to mapKeys which is used by bootstrap.... but I don't think that bootstrap is used. + typedef std::map KeyMap; + KeyMap privateToPublicKeyMap; } //========================================================================= const std::string LLExperienceCache::PRIVATE_KEY = "private_id"; const std::string LLExperienceCache::MISSING = "DoesNotExist"; -const std::string LLExperienceCache::AGENT_ID = "agent_id"; -const std::string LLExperienceCache::GROUP_ID = "group_id"; +const std::string LLExperienceCache::AGENT_ID = "agent_id"; +const std::string LLExperienceCache::GROUP_ID = "group_id"; const std::string LLExperienceCache::EXPERIENCE_ID = "public_id"; const std::string LLExperienceCache::NAME = "name"; const std::string LLExperienceCache::PROPERTIES = "properties"; const std::string LLExperienceCache::EXPIRES = "expiration"; const std::string LLExperienceCache::DESCRIPTION = "description"; const std::string LLExperienceCache::QUOTA = "quota"; -const std::string LLExperienceCache::MATURITY = "maturity"; -const std::string LLExperienceCache::METADATA = "extended_metadata"; +const std::string LLExperienceCache::MATURITY = "maturity"; +const std::string LLExperienceCache::METADATA = "extended_metadata"; const std::string LLExperienceCache::SLURL = "slurl"; // should be in sync with experience-api/experiences/models.py @@ -80,20 +78,51 @@ const int LLExperienceCache::PROPERTY_INVALID = 1 << 0; const int LLExperienceCache::PROPERTY_PRIVILEGED = 1 << 3; const int LLExperienceCache::PROPERTY_GRID = 1 << 4; const int LLExperienceCache::PROPERTY_PRIVATE = 1 << 5; -const int LLExperienceCache::PROPERTY_DISABLED = 1 << 6; -const int LLExperienceCache::PROPERTY_SUSPENDED = 1 << 7; +const int LLExperienceCache::PROPERTY_DISABLED = 1 << 6; +const int LLExperienceCache::PROPERTY_SUSPENDED = 1 << 7; // default values -const F64 LLExperienceCache::DEFAULT_EXPIRATION = 600.0; +const F64 LLExperienceCache::DEFAULT_EXPIRATION = 600.0; const S32 LLExperienceCache::DEFAULT_QUOTA = 128; // this is megabytes //========================================================================= -LLExperienceCache::LLExperienceCache() +LLExperienceCache::LLExperienceCache(): + mShutdown(false) { } LLExperienceCache::~LLExperienceCache() { + +} + +void LLExperienceCache::initSingleton() +{ + mCacheFileName = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); + + LL_INFOS("ExperienceCache") << "Loading " << mCacheFileName << LL_ENDL; + llifstream cache_stream(mCacheFileName.c_str()); + + if (cache_stream.is_open()) + { + cache_stream >> (*this); + } + + LLCoros::instance().launch("LLExperienceCache::idleCoro", + boost::bind(&LLExperienceCache::idleCoro, this)); + +} + +void LLExperienceCache::cleanup() +{ + LL_INFOS("ExperienceCache") << "Saving " << mCacheFileName << LL_ENDL; + + llofstream cache_stream(mCacheFileName.c_str()); + if (cache_stream.is_open()) + { + cache_stream << (*this); + } + mShutdown = true; } //------------------------------------------------------------------------- @@ -110,18 +139,18 @@ void LLExperienceCache::importFile(std::istream& istr) for (; it != experiences.endMap(); ++it) { public_key.set(it->first); - sCache[public_key] = it->second; + mCache[public_key] = it->second; } - LL_DEBUGS("ExperienceCache") << "importFile() loaded " << sCache.size() << LL_ENDL; + LL_DEBUGS("ExperienceCache") << "importFile() loaded " << mCache.size() << LL_ENDL; } void LLExperienceCache::exportFile(std::ostream& ostr) const { LLSD experiences; - cache_t::const_iterator it = sCache.begin(); - for (; it != sCache.end(); ++it) + cache_t::const_iterator it = mCache.begin(); + for (; it != mCache.end(); ++it) { if (!it->second.has(EXPERIENCE_ID) || it->second[EXPERIENCE_ID].asUUID().isNull() || it->second.has("DoesNotExist") || (it->second.has(PROPERTIES) && it->second[PROPERTIES].asInteger() & PROPERTY_INVALID)) @@ -136,7 +165,7 @@ void LLExperienceCache::exportFile(std::ostream& ostr) const LLSDSerialize::toPrettyXML(data, ostr); } -// *TODO$: Rider: These three functions not seem to be used... it may be useful in testing. +// *TODO$: Rider: This method does not seem to be used... it may be useful in testing. void LLExperienceCache::bootstrap(const LLSD& legacyKeys, int initialExpiration) { LLExperienceCacheImpl::mapKeys(legacyKeys); @@ -166,8 +195,8 @@ LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_i if (private_key.isNull()) return LLUUID::null; - KeyMap::const_iterator it = privateToPublicKeyMap.find(private_key); - if (it == privateToPublicKeyMap.end()) + LLExperienceCacheImpl::KeyMap::const_iterator it = LLExperienceCacheImpl::privateToPublicKeyMap.find(private_key); + if (it == LLExperienceCacheImpl::privateToPublicKeyMap.end()) { if (null_if_not_found) { @@ -182,8 +211,10 @@ LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_i //========================================================================= void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD& experience) { - sCache[public_key]=experience; - LLSD & row = sCache[public_key]; + LL_INFOS("ExperienceCache") << "Processing experience \"" << experience[NAME] << "\" with key " << public_key.asString() << LL_ENDL; + + mCache[public_key]=experience; + LLSD & row = mCache[public_key]; if(row.has(EXPIRES)) { @@ -192,233 +223,148 @@ void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD& if(row.has(EXPERIENCE_ID)) { - sPendingQueue.erase(row[EXPERIENCE_ID].asUUID()); + mPendingQueue.erase(row[EXPERIENCE_ID].asUUID()); } //signal - signal_map_t::iterator sig_it = sSignalMap.find(public_key); - if (sig_it != sSignalMap.end()) + signal_map_t::iterator sig_it = mSignalMap.find(public_key); + if (sig_it != mSignalMap.end()) { signal_ptr signal = sig_it->second; (*signal)(experience); - sSignalMap.erase(public_key); + mSignalMap.erase(public_key); } } const LLExperienceCache::cache_t& LLExperienceCache::getCached() { - return sCache; -} - -void LLExperienceCache::setMaximumLookups(int maximumLookups) -{ - sMaximumLookups = maximumLookups; + return mCache; } - -bool LLExperienceCache::expirationFromCacheControl(LLSD headers, F64 *expires) +void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, std::string url, RequestQueue_t requests) { - // Allow the header to override the default - LLSD cache_control_header = headers["cache-control"]; - if (cache_control_header.isDefined()) - { - S32 max_age = 0; - std::string cache_control = cache_control_header.asString(); - if (max_age_from_cache_control(cache_control, &max_age)) - { - LL_WARNS("ExperienceCache") - << "got EXPIRES from headers, max_age " << max_age - << LL_ENDL; - F64 now = LLFrameTimer::getTotalSeconds(); - *expires = now + (F64)max_age; - return true; - } - } - return false; -} + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest()); + //LL_INFOS("requestExperiencesCoro") << "url: " << url << LL_ENDL; -static const std::string MAX_AGE("max-age"); -static const boost::char_separator EQUALS_SEPARATOR("="); -static const boost::char_separator COMMA_SEPARATOR(","); + LLSD result = httpAdapter->getAndYield(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + if (!status) + { + F64 now = LLFrameTimer::getTotalSeconds(); -class LLExperienceResponder : public LLHTTPClient::Responder -{ -public: - LLExperienceResponder(const ask_queue_t& keys) - :mKeys(keys) - { - - } - - /*virtual*/ void httpCompleted() - { - LLSD experiences = getContent()["experience_keys"]; - LLSD::array_const_iterator it = experiences.beginArray(); - for( /**/ ; it != experiences.endArray(); ++it) - { - const LLSD& row = *it; - LLUUID public_key = row[EXPERIENCE_ID].asUUID(); - - - LL_DEBUGS("ExperienceCache") << "Received result for " << public_key - << " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL ; - - processExperience(public_key, row); - } - - LLSD error_ids = getContent()["error_ids"]; - LLSD::array_const_iterator errIt = error_ids.beginArray(); - for( /**/ ; errIt != error_ids.endArray() ; ++errIt ) - { - LLUUID id = errIt->asUUID(); - LLSD exp; - exp[EXPIRES]=DEFAULT_EXPIRATION; - exp[EXPERIENCE_ID] = id; - exp[PROPERTIES]=PROPERTY_INVALID; - exp[MISSING]=true; - exp[QUOTA] = DEFAULT_QUOTA; - - processExperience(id, exp); - LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL ; - } - - LL_DEBUGS("ExperienceCache") << sCache.size() << " cached experiences" << LL_ENDL; - } - - /*virtual*/ void httpFailure() - { - LL_WARNS("ExperienceCache") << "Request failed "<first); + LLSD headers = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; + // build dummy entries for the failed requests + for (RequestQueue_t::const_iterator it = requests.begin(); it != requests.end(); ++it) + { + LLSD exp = get(*it); //leave the properties alone if we already have a cache entry for this xp - if(exp.isUndefined()) + if (exp.isUndefined()) { - exp[PROPERTIES]=PROPERTY_INVALID; + exp[PROPERTIES] = PROPERTY_INVALID; } - exp[EXPIRES]=retry_timestamp; - exp[EXPERIENCE_ID] = it->first; - exp["key_type"] = it->second; - exp["uuid"] = it->first; - exp["error"] = (LLSD::Integer)getStatus(); + exp[EXPIRES] = now + LLExperienceCacheImpl::getErrorRetryDeltaTime(status, headers); + exp[EXPERIENCE_ID] = *it; + exp["key_type"] = EXPERIENCE_ID; + exp["uuid"] = *it; + exp["error"] = (LLSD::Integer)status.getType(); exp[QUOTA] = DEFAULT_QUOTA; - LLExperienceCache::processExperience(it->first, exp); - } - - } - - // Return time to retry a request that generated an error, based on - // error type and headers. Return value is seconds-since-epoch. - F64 errorRetryTimestamp(S32 status) - { + processExperience(*it, exp); + } + return; + } - // Retry-After takes priority - LLSD retry_after = getResponseHeaders()["retry-after"]; - if (retry_after.isDefined()) - { - // We only support the delta-seconds type - S32 delta_seconds = retry_after.asInteger(); - if (delta_seconds > 0) - { - // ...valid delta-seconds - return F64(delta_seconds); - } - } + LLSD experiences = result["experience_keys"]; + + for (LLSD::array_const_iterator it = experiences.beginArray(); + it != experiences.endArray(); ++it) + { + const LLSD& row = *it; + LLUUID public_key = row[EXPERIENCE_ID].asUUID(); - // If no Retry-After, look for Cache-Control max-age - F64 expires = 0.0; - if (LLExperienceCache::expirationFromCacheControl(getResponseHeaders(), &expires)) - { - return expires; - } + LL_DEBUGS("ExperienceCache") << "Received result for " << public_key + << " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL; - // No information in header, make a guess - if (status == 503) - { - // ...service unavailable, retry soon - const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min - return SERVICE_UNAVAILABLE_DELAY; - } - else if (status == 499) - { - // ...we were probably too busy, retry quickly - const F64 BUSY_DELAY = 10.0; // 10 seconds - return BUSY_DELAY; + processExperience(public_key, row); + } - } - else - { - // ...other unexpected error - const F64 DEFAULT_DELAY = 3600.0; // 1 hour - return DEFAULT_DELAY; - } - } + LLSD error_ids = result["error_ids"]; + + for (LLSD::array_const_iterator errIt = error_ids.beginArray(); + errIt != error_ids.endArray(); ++errIt) + { + LLUUID id = errIt->asUUID(); + LLSD exp; + exp[EXPIRES] = DEFAULT_EXPIRATION; + exp[EXPERIENCE_ID] = id; + exp[PROPERTIES] = PROPERTY_INVALID; + exp[MISSING] = true; + exp[QUOTA] = DEFAULT_QUOTA; + + processExperience(id, exp); + LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL; + } -private: - ask_queue_t mKeys; -}; +} void LLExperienceCache::requestExperiences() { - if(sAskQueue.empty() || sLookupURL.empty()) - return; - - F64 now = LLFrameTimer::getTotalSeconds(); + if (mCapability.empty()) + { + LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL; + return; + } - const U32 EXP_URL_SEND_THRESHOLD = 3000; - const U32 PAGE_SIZE = EXP_URL_SEND_THRESHOLD/UUID_STR_LENGTH; + std::string urlBase = mCapability("GetExperienceInfo"); + if (urlBase.empty()) + { + LL_WARNS("ExperienceCache") << "No Experience capability." << LL_ENDL; + return; + } - std::ostringstream ostr; + if (*urlBase.rbegin() != '/') + { + urlBase += "/"; + } + urlBase += "id/"; - ask_queue_t keys; - ostr << sLookupURL << "?page_size=" << PAGE_SIZE; + F64 now = LLFrameTimer::getTotalSeconds(); - int request_count = 0; - while(!sAskQueue.empty() && request_count < sMaximumLookups) - { - ask_queue_t::iterator it = sAskQueue.begin(); - const LLUUID& key = it->first; - const std::string& key_type = it->second; + const U32 EXP_URL_SEND_THRESHOLD = 3000; + const U32 PAGE_SIZE = EXP_URL_SEND_THRESHOLD / UUID_STR_LENGTH; - ostr << '&' << key_type << '=' << key.asString() ; - - keys[key]=key_type; - request_count++; + std::ostringstream ostr; + ostr << urlBase << "?page_size=" << PAGE_SIZE; + RequestQueue_t requests; - sPendingQueue[key] = now; - - if(ostr.tellp() > EXP_URL_SEND_THRESHOLD) - { - LL_DEBUGS("ExperienceCache") << "requestExperiences() query: " << ostr.str() << LL_ENDL; - LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys)); - ostr.clear(); - ostr.str(sLookupURL); - ostr << "?page_size=" << PAGE_SIZE; - keys.clear(); - } - sAskQueue.erase(it); - } + while (!mRequestQueue.empty()) + { + RequestQueue_t::iterator it = mRequestQueue.begin(); + LLUUID key = (*it); + mRequestQueue.erase(it); + requests.insert(key); + + ostr << "&" << EXPERIENCE_ID << "=" << key.asString(); + mPendingQueue[key] = now; + + if (mRequestQueue.empty() || (ostr.tellp() > EXP_URL_SEND_THRESHOLD)) + { // request is placed in the coprocedure pool for the ExpCache cache. Throttling is done by the pool itself. + LLCoprocedureManager::getInstance()->enqueueCoprocedure("ExpCache", "Request", + boost::bind(&LLExperienceCache::requestExperiencesCoro, this, _1, ostr.str(), requests) ); + + ostr.str(std::string()); + ostr << urlBase << "?page_size=" << PAGE_SIZE; + requests.clear(); + } + } - if(ostr.tellp() > sLookupURL.size()) - { - LL_DEBUGS("ExperienceCache") << "requestExperiences() query 2: " << ostr.str() << LL_ENDL; - LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys)); - } } @@ -427,9 +373,9 @@ bool LLExperienceCache::isRequestPending(const LLUUID& public_key) bool isPending = false; const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0; - pending_queue_t::const_iterator it = sPendingQueue.find(public_key); + PendingQueue_t::const_iterator it = mPendingQueue.find(public_key); - if(it != sPendingQueue.end()) + if(it != mPendingQueue.end()) { F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS; isPending = (it->second > expire_time); @@ -438,69 +384,70 @@ bool LLExperienceCache::isRequestPending(const LLUUID& public_key) return isPending; } - -void LLExperienceCache::setLookupURL(const std::string& lookup_url) +void LLExperienceCache::setCapabilityQuery(LLExperienceCache::CapabilityQuery_t queryfn) { - sLookupURL = lookup_url; - if(!sLookupURL.empty()) - { - sLookupURL += "id/"; - } + mCapability = queryfn; } -bool LLExperienceCache::hasLookupURL() -{ - return !sLookupURL.empty(); -} -void LLExperienceCache::idle() +void LLExperienceCache::idleCoro() { - const F32 SECS_BETWEEN_REQUESTS = 0.1f; - if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS)) - { - return; - } + const F32 SECS_BETWEEN_REQUESTS = 0.5f; + const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds - // Must be large relative to above - const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds - if (sEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) - { - eraseExpired(); - } + LL_INFOS("ExperienceCache") << "Launching Experience cache idle coro." << LL_ENDL; + LLEventTimeout timeout; - if(!sAskQueue.empty()) - { - requestExperiences(); - } + do + { + timeout.eventAfter(SECS_BETWEEN_REQUESTS, LLSD()); + llcoro::waitForEventOn(timeout); + + if (mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) + { + eraseExpired(); + } + + if (!mRequestQueue.empty()) + { + requestExperiences(); + } + + } while (!mShutdown); + + // The coroutine system will likely be shut down by the time we get to this point + // (or at least no further cycling will occur on it since the user has decided to quit.) } void LLExperienceCache::erase(const LLUUID& key) { - cache_t::iterator it = sCache.find(key); + cache_t::iterator it = mCache.find(key); - if(it != sCache.end()) + if(it != mCache.end()) { - sCache.erase(it); + mCache.erase(it); } } void LLExperienceCache::eraseExpired() { F64 now = LLFrameTimer::getTotalSeconds(); - cache_t::iterator it = sCache.begin(); - while (it != sCache.end()) + cache_t::iterator it = mCache.begin(); + while (it != mCache.end()) { cache_t::iterator cur = it; LLSD& exp = cur->second; ++it; + //LL_INFOS("ExperienceCache") << "Testing experience \"" << exp[NAME] << "\" with exp time " << exp[EXPIRES].asReal() << "(now = " << now << ")" << LL_ENDL; + if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now) { if(!exp.has(EXPERIENCE_ID)) { LL_WARNS("ExperienceCache") << "Removing experience with no id " << LL_ENDL ; - sCache.erase(cur); - } + mCache.erase(cur); + } else { LLUUID id = exp[EXPERIENCE_ID].asUUID(); @@ -512,7 +459,7 @@ void LLExperienceCache::eraseExpired() else { LL_WARNS("ExperienceCache") << "Removing invalid experience " << id << LL_ENDL ; - sCache.erase(cur); + mCache.erase(cur); } } } @@ -521,11 +468,11 @@ void LLExperienceCache::eraseExpired() bool LLExperienceCache::fetch(const LLUUID& key, bool refresh/* = true*/) { - if(!key.isNull() && !isRequestPending(key) && (refresh || sCache.find(key)==sCache.end())) + if(!key.isNull() && !isRequestPending(key) && (refresh || mCache.find(key)==mCache.end())) { - LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL ; - sAskQueue[key]=EXPERIENCE_ID; + LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL; + mRequestQueue.insert(key); return true; } return false; @@ -549,13 +496,12 @@ const LLSD& LLExperienceCache::get(const LLUUID& key) if(key.isNull()) return empty; - cache_t::const_iterator it = sCache.find(key); + cache_t::const_iterator it = mCache.find(key); - if (it != sCache.end()) + if (it != mCache.end()) { return it->second; } - fetch(key); return empty; @@ -565,8 +511,8 @@ void LLExperienceCache::get(const LLUUID& key, LLExperienceCache::Callback_t slo if(key.isNull()) return; - cache_t::const_iterator it = sCache.find(key); - if (it != sCache.end()) + cache_t::const_iterator it = mCache.find(key); + if (it != mCache.end()) { // ...name already exists in cache, fire callback now callback_signal_t signal; @@ -580,28 +526,10 @@ void LLExperienceCache::get(const LLUUID& key, LLExperienceCache::Callback_t slo signal_ptr signal = signal_ptr(new callback_signal_t()); - std::pair result = sSignalMap.insert(signal_map_t::value_type(key, signal)); + std::pair result = mSignalMap.insert(signal_map_t::value_type(key, signal)); if (!result.second) - signal = result.first.second; + signal = (*result.first).second; signal->connect(slot); - -#if 0 - // always store additional callback, even if request is pending - signal_map_t::iterator sig_it = sSignalMap.find(key); - if (sig_it == sSignalMap.end()) - { - // ...new callback for this id - signal_ptr signal = signal_ptr(new callback_signal_t()); - signal->connect(slot); - sSignalMap[key] = signal; - } - else - { - // ...existing callback, bind additional slot - callback_signal_t* signal = sig_it->second; - signal->connect(slot); - } -#endif } //========================================================================= @@ -610,14 +538,71 @@ void LLExperienceCacheImpl::mapKeys(const LLSD& legacyKeys) LLSD::array_const_iterator exp = legacyKeys.beginArray(); for (/**/; exp != legacyKeys.endArray(); ++exp) { - if (exp->has(LLExperienceCache::EXPERIENCE_ID) && exp->has(LLExperienceCache::PRIVATE_KEY)) + if (exp->has(LLExperienceCacheImpl::EXPERIENCE_ID) && exp->has(LLExperienceCacheImpl::PRIVATE_KEY)) { - privateToPublicKeyMap[(*exp)[LLExperienceCache::PRIVATE_KEY].asUUID()] = (*exp)[LLExperienceCache::EXPERIENCE_ID].asUUID(); + LLExperienceCacheImpl::privateToPublicKeyMap[(*exp)[LLExperienceCacheImpl::PRIVATE_KEY].asUUID()] = + (*exp)[LLExperienceCacheImpl::EXPERIENCE_ID].asUUID(); } } } -bool LLExperienceCacheImpl::max_age_from_cache_control(const std::string& cache_control, S32 *max_age) +// Return time to retry a request that generated an error, based on +// error type and headers. Return value is seconds-since-epoch. +F64 LLExperienceCacheImpl::getErrorRetryDeltaTime(S32 status, LLSD headers) +{ + + // Retry-After takes priority + LLSD retry_after = headers["retry-after"]; + if (retry_after.isDefined()) + { + // We only support the delta-seconds type + S32 delta_seconds = retry_after.asInteger(); + if (delta_seconds > 0) + { + // ...valid delta-seconds + return F64(delta_seconds); + } + } + + // If no Retry-After, look for Cache-Control max-age + // Allow the header to override the default + LLSD cache_control_header = headers["cache-control"]; + if (cache_control_header.isDefined()) + { + S32 max_age = 0; + std::string cache_control = cache_control_header.asString(); + if (LLExperienceCacheImpl::maxAgeFromCacheControl(cache_control, &max_age)) + { + LL_WARNS("ExperienceCache") + << "got EXPIRES from headers, max_age " << max_age + << LL_ENDL; + return (F64)max_age; + } + } + + // No information in header, make a guess + if (status == 503) + { + // ...service unavailable, retry soon + const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min + return SERVICE_UNAVAILABLE_DELAY; + } + else if (status == 499) + { + // ...we were probably too busy, retry quickly + const F64 BUSY_DELAY = 10.0; // 10 seconds + return BUSY_DELAY; + + } + else + { + // ...other unexpected error + const F64 DEFAULT_DELAY = 3600.0; // 1 hour + return DEFAULT_DELAY; + } +} + +bool LLExperienceCacheImpl::maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age) { // Split the string on "," to get a list of directives typedef boost::tokenizer > tokenizer; diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h index 8da038a8c3..937225a80a 100644 --- a/indra/llmessage/llexperiencecache.h +++ b/indra/llmessage/llexperiencecache.h @@ -31,7 +31,9 @@ #include "linden_common.h" #include "llsingleton.h" +#include "llframetimer.h" #include "llsd.h" +#include "llcorehttputil.h" #include #include @@ -44,8 +46,11 @@ class LLExperienceCache: public LLSingleton < LLExperienceCache > friend class LLSingleton < LLExperienceCache > ; public: + typedef boost::function CapabilityQuery_t; typedef boost::function Callback_t; + void cleanup(); + void erase(const LLUUID& key); bool fetch(const LLUUID& key, bool refresh = false); void insert(const LLSD& experience_data); @@ -54,7 +59,39 @@ public: // If name information is in cache, callback will be called immediately. void get(const LLUUID& key, Callback_t slot); + bool isRequestPending(const LLUUID& public_key); + + void setCapabilityQuery(CapabilityQuery_t queryfn); + + static const std::string NAME; // "name" + static const std::string EXPERIENCE_ID; // "public_id" + static const std::string AGENT_ID; // "agent_id" + static const std::string GROUP_ID; // "group_id" + static const std::string PROPERTIES; // "properties" + static const std::string EXPIRES; // "expiration" + static const std::string DESCRIPTION; // "description" + static const std::string QUOTA; // "quota" + static const std::string MATURITY; // "maturity" + static const std::string METADATA; // "extended_metadata" + static const std::string SLURL; // "slurl" + + static const std::string MISSING; // "DoesNotExist" + + // should be in sync with experience-api/experiences/models.py + static const int PROPERTY_INVALID; // 1 << 0 + static const int PROPERTY_PRIVILEGED; // 1 << 3 + static const int PROPERTY_GRID; // 1 << 4 + static const int PROPERTY_PRIVATE; // 1 << 5 + static const int PROPERTY_DISABLED; // 1 << 6 + static const int PROPERTY_SUSPENDED; // 1 << 7 + private: + LLExperienceCache(); + virtual ~LLExperienceCache(); + + virtual void initSingleton(); + + // Callback types for get() typedef boost::signals2::signal < void(const LLSD &) > callback_signal_t; typedef boost::shared_ptr signal_ptr; @@ -64,63 +101,43 @@ private: typedef std::map signal_map_t; typedef std::map cache_t; - typedef std::set ask_queue_t; - - + typedef std::set RequestQueue_t; + typedef std::map PendingQueue_t; + //-------------------------------------------- static const std::string PRIVATE_KEY; // "private_id" - static const std::string MISSING; // "DoesNotExist" - - static const std::string AGENT_ID; // "agent_id" - static const std::string GROUP_ID; // "group_id" - static const std::string EXPERIENCE_ID; // "public_id" - static const std::string NAME; // "name" - static const std::string PROPERTIES; // "properties" - static const std::string EXPIRES; // "expiration" - static const std::string DESCRIPTION; // "description" - static const std::string QUOTA; // "quota" - static const std::string MATURITY; // "maturity" - static const std::string METADATA; // "extended_metadata" - static const std::string SLURL; // "slurl" - - // should be in sync with experience-api/experiences/models.py - static const int PROPERTY_INVALID; // 1 << 0 - static const int PROPERTY_PRIVILEGED; // 1 << 3 - static const int PROPERTY_GRID; // 1 << 4 - static const int PROPERTY_PRIVATE; // 1 << 5 - static const int PROPERTY_DISABLED; // 1 << 6 - static const int PROPERTY_SUSPENDED; // 1 << 7 // default values static const F64 DEFAULT_EXPIRATION; // 600.0 static const S32 DEFAULT_QUOTA; // 128 this is megabytes -//-------------------------------------------- - LLExperienceCache(); - virtual ~LLExperienceCache(); - - void exportFile(std::ostream& ostr) const; - void importFile(std::istream& istr); - //-------------------------------------------- void processExperience(const LLUUID& public_key, const LLSD& experience); //-------------------------------------------- - cache_t sCache; - signal_map_t sSignalMap; - ask_queue_t sAskQueue; - + cache_t mCache; + signal_map_t mSignalMap; + RequestQueue_t mRequestQueue; + PendingQueue_t mPendingQueue; + + LLFrameTimer mRequestTimer; + LLFrameTimer mEraseExpiredTimer; // Periodically clean out expired entries from the cache + CapabilityQuery_t mCapability; + std::string mCacheFileName; + bool mShutdown; + + void idleCoro(); void eraseExpired(); - - void setLookupURL(const std::string& lookup_url); - bool hasLookupURL(); + void requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, std::string, RequestQueue_t); + void requestExperiences(); void setMaximumLookups(int maximumLookups); - void idle(); - void bootstrap(const LLSD& legacyKeys, int initialExpiration); - + void bootstrap(const LLSD& legacyKeys, int initialExpiration); + void exportFile(std::ostream& ostr) const; + void importFile(std::istream& istr); + // const cache_t& getCached(); // maps an experience private key to the experience id diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 259fbde806..d192aac448 100755 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -11,11 +11,13 @@ include(LLMessage) include(LLCoreHttp) include(LLRender) include(LLWindow) +include(LLCoreHttp) include(LLVFS) include(LLXML) include_directories( ${LLCOMMON_INCLUDE_DIRS} + ${LLCOREHTTP_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS} ${LLINVENTORY_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index eb7f98e618..e76f2a1550 100755 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -1430,7 +1430,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const return LLTrans::getString("ExperienceNameNull"); } - const LLSD& experience_details = LLExperienceCache::get(experience_id); + const LLSD& experience_details = LLExperienceCache::getInstance()->get(experience_id); if(!experience_details.isUndefined()) { std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString(); @@ -1438,7 +1438,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const } addObserver(experience_id_string, url, cb); - LLExperienceCache::get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1)); + LLExperienceCache::getInstance()->get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1)); return LLTrans::getString("LoadingData"); } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index fe9c7c0fc0..090879e372 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -161,7 +161,6 @@ set(viewer_SOURCE_FILES llconversationloglistitem.cpp llconversationmodel.cpp llconversationview.cpp - llcoproceduremanager.cpp llcurrencyuimanager.cpp llcylinder.cpp lldateutil.cpp @@ -771,7 +770,6 @@ set(viewer_HEADER_FILES llconversationloglistitem.h llconversationmodel.h llconversationview.h - llcoproceduremanager.h llcurrencyuimanager.h llcylinder.h lldateutil.h diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index e7dd378edd..3316f1e654 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -953,6 +953,15 @@ BOOL LLAgent::inPrelude() } +std::string LLAgent::getRegionCapability(const std::string &name) +{ + if (!mRegionp) + return std::string(); + + return mRegionp->getCapability(name); +} + + //----------------------------------------------------------------------------- // canManageEstate() //----------------------------------------------------------------------------- diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 0ba3dea427..5731f4db89 100755 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -262,6 +262,9 @@ public: LLHost getRegionHost() const; BOOL inPrelude(); + // Capability + std::string getRegionCapability(const std::string &name); // short hand for if (getRegion()) { getRegion()->getCapability(name) } + /** * Register a boost callback to be called when the agent changes regions * Note that if you need to access a capability for the region, you may need to wait diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9b9b591cd1..e13a9d96c7 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -228,7 +228,7 @@ #include "llmachineid.h" #include "llmainlooprepeater.h" - +#include "llcoproceduremanager.h" #include "llviewereventrecorder.h" @@ -755,8 +755,11 @@ void fast_exit(int rc) { _exit(rc); } + + } + bool LLAppViewer::init() { setupErrorHandling(mSecondInstance); @@ -1216,6 +1219,12 @@ bool LLAppViewer::init() LLAgentLanguage::init(); + /// Tell the Coprocedure manager how to discover and store the pool sizes + // what I wanted + LLCoprocedureManager::getInstance()->setPropertyMethods( + boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1), + boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS)); + return true; } @@ -4700,31 +4709,6 @@ void LLAppViewer::saveNameCache() } -void LLAppViewer::saveExperienceCache() -{ - std::string filename = - gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); - LL_INFOS("ExperienceCache") << "Saving " << filename << LL_ENDL; - llofstream cache_stream(filename.c_str()); - if(cache_stream.is_open()) - { - LLExperienceCache::exportFile(cache_stream); - } -} - -void LLAppViewer::loadExperienceCache() -{ - std::string filename = - gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); - LL_INFOS("ExperienceCache") << "Loading " << filename << LL_ENDL; - llifstream cache_stream(filename.c_str()); - if(cache_stream.is_open()) - { - LLExperienceCache::importFile(cache_stream); - } -} - - /*! @brief This class is an LLFrameTimer that can be created with an elapsed time that starts counting up from the given value rather than 0.0. @@ -4920,7 +4904,6 @@ void LLAppViewer::idle() // floating throughout the various object lists. // idleNameCache(); - idleExperienceCache(); idleNetwork(); @@ -5350,22 +5333,6 @@ void LLAppViewer::idleNameCache() LLAvatarNameCache::idle(); } -void LLAppViewer::idleExperienceCache() -{ - LLViewerRegion* region = gAgent.getRegion(); - if (!region) return; - - std::string lookup_url=region->getCapability("GetExperienceInfo"); - if(!lookup_url.empty() && *lookup_url.rbegin() != '/') - { - lookup_url += '/'; - } - - LLExperienceCache::setLookupURL(lookup_url); - - LLExperienceCache::idle(); -} - // // Handle messages, and all message related stuff // @@ -5528,7 +5495,9 @@ void LLAppViewer::disconnectViewer() } saveNameCache(); - saveExperienceCache(); + LLExperienceCache *expCache = LLExperienceCache::getIfExists(); + if (expCache) + expCache->cleanup(); // close inventory interface, close all windows LLFloaterInventory::cleanup(); diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 718871138e..e8a1ca036b 100755 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -122,9 +122,6 @@ public: void loadNameCache(); void saveNameCache(); - void loadExperienceCache(); - void saveExperienceCache(); - void removeMarkerFiles(); void removeDumpDir(); @@ -233,7 +230,6 @@ private: void idle(); void idleShutdown(); // update avatar SLID and display name caches - void idleExperienceCache(); void idleNameCache(); void idleNetwork(); diff --git a/indra/newview/llcoproceduremanager.cpp b/indra/newview/llcoproceduremanager.cpp deleted file mode 100644 index db01c13079..0000000000 --- a/indra/newview/llcoproceduremanager.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/** -* @file LLCoprocedurePool.cpp -* @author Rider Linden -* @brief Singleton class for managing asset uploads to the sim. -* -* $LicenseInfo:firstyear=2015&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2015, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#include "llviewerprecompiledheaders.h" -#include "linden_common.h" - -#include "llviewercontrol.h" - -#include "llcoproceduremanager.h" - -//========================================================================= -// Map of pool sizes for known pools -static std::map DefaultPoolSizes; - -// *TODO$: When C++11 this can be initialized here as follows: -// = {{"AIS", 25}, {"Upload", 1}} - -#define DEFAULT_POOL_SIZE 5 - -//========================================================================= -class LLCoprocedurePool: private boost::noncopyable -{ -public: - typedef LLCoprocedureManager::CoProcedure_t CoProcedure_t; - - LLCoprocedurePool(const std::string &name, size_t size); - virtual ~LLCoprocedurePool(); - - /// Places the coprocedure on the queue for processing. - /// - /// @param name Is used for debugging and should identify this coroutine. - /// @param proc Is a bound function to be executed - /// - /// @return This method returns a UUID that can be used later to cancel execution. - LLUUID enqueueCoprocedure(const std::string &name, CoProcedure_t proc); - - /// Cancel a coprocedure. If the coprocedure is already being actively executed - /// this method calls cancelYieldingOperation() on the associated HttpAdapter - /// If it has not yet been dequeued it is simply removed from the queue. - bool cancelCoprocedure(const LLUUID &id); - - /// Requests a shutdown of the upload manager. Passing 'true' will perform - /// an immediate kill on the upload coroutine. - void shutdown(bool hardShutdown = false); - - /// Returns the number of coprocedures in the queue awaiting processing. - /// - inline size_t countPending() const - { - return mPendingCoprocs.size(); - } - - /// Returns the number of coprocedures actively being processed. - /// - inline size_t countActive() const - { - return mActiveCoprocs.size(); - } - - /// Returns the total number of coprocedures either queued or in active processing. - /// - inline size_t count() const - { - return countPending() + countActive(); - } - -private: - struct QueuedCoproc - { - typedef boost::shared_ptr ptr_t; - - QueuedCoproc(const std::string &name, const LLUUID &id, CoProcedure_t proc) : - mName(name), - mId(id), - mProc(proc) - {} - - std::string mName; - LLUUID mId; - CoProcedure_t mProc; - }; - - // we use a deque here rather than std::queue since we want to be able to - // iterate through the queue and potentially erase an entry from the middle. - typedef std::deque CoprocQueue_t; - typedef std::map ActiveCoproc_t; - - std::string mPoolName; - size_t mPoolSize; - CoprocQueue_t mPendingCoprocs; - ActiveCoproc_t mActiveCoprocs; - bool mShutdown; - LLEventStream mWakeupTrigger; - - typedef std::map CoroAdapterMap_t; - LLCore::HttpRequest::policy_t mHTTPPolicy; - - CoroAdapterMap_t mCoroMapping; - - void coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter); - -}; - -//========================================================================= -LLCoprocedureManager::LLCoprocedureManager() -{ - DefaultPoolSizes.insert(std::map::value_type("Upload", 1)); - DefaultPoolSizes.insert(std::map::value_type("AIS", 25)); -} - -LLCoprocedureManager::~LLCoprocedureManager() -{ - -} - -LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std::string &poolName) -{ - // Attempt to look up a pool size in the configuration. If found use that - std::string keyName = "PoolSize" + poolName; - int size = 5; - - size = gSavedSettings.getU32(keyName); - if (size == 0) - { // if not found grab the know default... if there is no known - // default use a reasonable number like 5. - std::map::iterator it = DefaultPoolSizes.find(poolName); - if (it == DefaultPoolSizes.end()) - size = DEFAULT_POOL_SIZE; - else - size = (*it).second; - gSavedSettings.declareU32(keyName, size, "Coroutine Pool size for " + poolName, LLControlVariable::PERSIST_ALWAYS); - LL_WARNS() << "LLCoprocedureManager: No setting for \"" << keyName << "\" setting pool size to default of " << size << LL_ENDL; - } - - poolPtr_t pool = poolPtr_t(new LLCoprocedurePool(poolName, size)); - mPoolMap.insert(poolMap_t::value_type(poolName, pool)); - - return pool; -} - -//------------------------------------------------------------------------- -LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc) -{ - // Attempt to find the pool and enqueue the procedure. If the pool does - // not exist, create it. - poolPtr_t targetPool; - poolMap_t::iterator it = mPoolMap.find(pool); - - if (it == mPoolMap.end()) - { - targetPool = initializePool(pool); - } - else - { - targetPool = (*it).second; - } - - if (!targetPool) - { - LL_WARNS() << "LLCoprocedureManager unable to create coprocedure pool named \"" << pool << "\"" << LL_ENDL; - return LLUUID::null; - } - - return targetPool->enqueueCoprocedure(name, proc); -} - -void LLCoprocedureManager::cancelCoprocedure(const LLUUID &id) -{ - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - if ((*it).second->cancelCoprocedure(id)) - return; - } - LL_INFOS() << "Coprocedure not found." << LL_ENDL; -} - -void LLCoprocedureManager::shutdown(bool hardShutdown) -{ - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - (*it).second->shutdown(hardShutdown); - } - mPoolMap.clear(); -} - -//------------------------------------------------------------------------- -size_t LLCoprocedureManager::countPending() const -{ - size_t count = 0; - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - count += (*it).second->countPending(); - } - return count; -} - -size_t LLCoprocedureManager::countPending(const std::string &pool) const -{ - poolMap_t::const_iterator it = mPoolMap.find(pool); - - if (it == mPoolMap.end()) - return 0; - return (*it).second->countPending(); -} - -size_t LLCoprocedureManager::countActive() const -{ - size_t count = 0; - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - count += (*it).second->countActive(); - } - return count; -} - -size_t LLCoprocedureManager::countActive(const std::string &pool) const -{ - poolMap_t::const_iterator it = mPoolMap.find(pool); - - if (it == mPoolMap.end()) - return 0; - return (*it).second->countActive(); -} - -size_t LLCoprocedureManager::count() const -{ - size_t count = 0; - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - count += (*it).second->count(); - } - return count; -} - -size_t LLCoprocedureManager::count(const std::string &pool) const -{ - poolMap_t::const_iterator it = mPoolMap.find(pool); - - if (it == mPoolMap.end()) - return 0; - return (*it).second->count(); -} - -//========================================================================= -LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size): - mPoolName(poolName), - mPoolSize(size), - mPendingCoprocs(), - mShutdown(false), - mWakeupTrigger("CoprocedurePool" + poolName, true), - mCoroMapping(), - mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID) -{ - for (size_t count = 0; count < mPoolSize; ++count) - { - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter = - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t( - new LLCoreHttpUtil::HttpCoroutineAdapter( mPoolName + "Adapter", mHTTPPolicy)); - - std::string uploadCoro = LLCoros::instance().launch("LLCoprocedurePool("+mPoolName+")::coprocedureInvokerCoro", - boost::bind(&LLCoprocedurePool::coprocedureInvokerCoro, this, httpAdapter)); - - mCoroMapping.insert(CoroAdapterMap_t::value_type(uploadCoro, httpAdapter)); - } - - LL_INFOS() << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items." << LL_ENDL; - - mWakeupTrigger.post(LLSD()); -} - -LLCoprocedurePool::~LLCoprocedurePool() -{ - shutdown(); -} - -//------------------------------------------------------------------------- -void LLCoprocedurePool::shutdown(bool hardShutdown) -{ - CoroAdapterMap_t::iterator it; - - for (it = mCoroMapping.begin(); it != mCoroMapping.end(); ++it) - { - if (!(*it).first.empty()) - { - if (hardShutdown) - { - LLCoros::instance().kill((*it).first); - } - } - if ((*it).second) - { - (*it).second->cancelYieldingOperation(); - } - } - - mShutdown = true; - mCoroMapping.clear(); - mPendingCoprocs.clear(); -} - -//------------------------------------------------------------------------- -LLUUID LLCoprocedurePool::enqueueCoprocedure(const std::string &name, LLCoprocedurePool::CoProcedure_t proc) -{ - LLUUID id(LLUUID::generateNewID()); - - mPendingCoprocs.push_back(QueuedCoproc::ptr_t(new QueuedCoproc(name, id, proc))); - LL_INFOS() << "Coprocedure(" << name << ") enqueued with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; - - mWakeupTrigger.post(LLSD()); - - return id; -} - -bool LLCoprocedurePool::cancelCoprocedure(const LLUUID &id) -{ - // first check the active coroutines. If there, remove it and return. - ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(id); - if (itActive != mActiveCoprocs.end()) - { - LL_INFOS() << "Found and canceling active coprocedure with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; - (*itActive).second->cancelYieldingOperation(); - mActiveCoprocs.erase(itActive); - return true; - } - - for (CoprocQueue_t::iterator it = mPendingCoprocs.begin(); it != mPendingCoprocs.end(); ++it) - { - if ((*it)->mId == id) - { - LL_INFOS() << "Found and removing queued coroutine(" << (*it)->mName << ") with Id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; - mPendingCoprocs.erase(it); - return true; - } - } - - LL_INFOS() << "Coprocedure with Id=" << id.asString() << " was not found." << " in pool \"" << mPoolName << "\"" << LL_ENDL; - return false; -} - -//------------------------------------------------------------------------- -void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter) -{ - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - - while (!mShutdown) - { - llcoro::waitForEventOn(mWakeupTrigger); - if (mShutdown) - break; - - while (!mPendingCoprocs.empty()) - { - QueuedCoproc::ptr_t coproc = mPendingCoprocs.front(); - mPendingCoprocs.pop_front(); - mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)); - - LL_INFOS() << "Dequeued and invoking coprocedure(" << coproc->mName << ") with id=" << coproc->mId.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; - - try - { - coproc->mProc(httpAdapter, coproc->mId); - } - catch (std::exception &e) - { - LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() << - " threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL; - } - catch (...) - { - LL_WARNS() << "A non std::exception was thrown from " << coproc->mName << " with id=" << coproc->mId << "." << " in pool \"" << mPoolName << "\"" << LL_ENDL; - } - - LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL; - - ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(coproc->mId); - if (itActive != mActiveCoprocs.end()) - { - mActiveCoprocs.erase(itActive); - } - } - } -} diff --git a/indra/newview/llcoproceduremanager.h b/indra/newview/llcoproceduremanager.h deleted file mode 100644 index d7f74af76b..0000000000 --- a/indra/newview/llcoproceduremanager.h +++ /dev/null @@ -1,87 +0,0 @@ -/** -* @file llcoproceduremanager.h -* @author Rider Linden -* @brief Singleton class for managing asset uploads to the sim. -* -* $LicenseInfo:firstyear=2015&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2015, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#ifndef LL_COPROCEDURE_MANAGER_H -#define LL_COPROCEDURE_MANAGER_H - -#include "lleventcoro.h" -#include "llcoros.h" -#include "llcorehttputil.h" -#include "lluuid.h" - -class LLCoprocedurePool; - -class LLCoprocedureManager : public LLSingleton < LLCoprocedureManager > -{ -public: - typedef boost::function CoProcedure_t; - - LLCoprocedureManager(); - virtual ~LLCoprocedureManager(); - - /// Places the coprocedure on the queue for processing. - /// - /// @param name Is used for debugging and should identify this coroutine. - /// @param proc Is a bound function to be executed - /// - /// @return This method returns a UUID that can be used later to cancel execution. - LLUUID enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc); - - /// Cancel a coprocedure. If the coprocedure is already being actively executed - /// this method calls cancelYieldingOperation() on the associated HttpAdapter - /// If it has not yet been dequeued it is simply removed from the queue. - void cancelCoprocedure(const LLUUID &id); - - /// Requests a shutdown of the upload manager. Passing 'true' will perform - /// an immediate kill on the upload coroutine. - void shutdown(bool hardShutdown = false); - - /// Returns the number of coprocedures in the queue awaiting processing. - /// - size_t countPending() const; - size_t countPending(const std::string &pool) const; - - /// Returns the number of coprocedures actively being processed. - /// - size_t countActive() const; - size_t countActive(const std::string &pool) const; - - /// Returns the total number of coprocedures either queued or in active processing. - /// - size_t count() const; - size_t count(const std::string &pool) const; - -private: - typedef boost::shared_ptr poolPtr_t; - typedef std::map poolMap_t; - - poolMap_t mPoolMap; - - poolPtr_t initializePool(const std::string &poolName); -}; - -#endif diff --git a/indra/newview/llexperienceassociationresponder.cpp b/indra/newview/llexperienceassociationresponder.cpp index b50c81eedc..cd4a7516b1 100644 --- a/indra/newview/llexperienceassociationresponder.cpp +++ b/indra/newview/llexperienceassociationresponder.cpp @@ -83,7 +83,7 @@ void ExperienceAssociationResponder::httpSuccess() return; } - LLExperienceCache::get(getContent()["experience"].asUUID(), boost::bind(&ExperienceAssociationResponder::sendResult, this, _1)); + LLExperienceCache::getInstance()->get(getContent()["experience"].asUUID(), boost::bind(&ExperienceAssociationResponder::sendResult, this, _1)); } diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp index 197162487d..8a04f9e4cc 100644 --- a/indra/newview/llfloaterexperienceprofile.cpp +++ b/indra/newview/llfloaterexperienceprofile.cpp @@ -99,7 +99,7 @@ public: if(params.size() != 2 || params[1].asString() != "profile") return false; - LLExperienceCache::get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1)); + LLExperienceCache::getInstance()->get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1)); return true; } @@ -288,8 +288,8 @@ BOOL LLFloaterExperienceProfile::postBuild() if (mExperienceId.notNull()) { - LLExperienceCache::fetch(mExperienceId, true); - LLExperienceCache::get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback, + LLExperienceCache::getInstance()->fetch(mExperienceId, true); + LLExperienceCache::getInstance()->get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback, getDerivedHandle(), _1)); LLViewerRegion* region = gAgent.getRegion(); @@ -799,8 +799,8 @@ void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content ) } refreshExperience(*it); - LLExperienceCache::insert(*it); - LLExperienceCache::fetch(id, true); + LLExperienceCache::getInstance()->insert(*it); + LLExperienceCache::getInstance()->fetch(id, true); if(mSaveCompleteAction==VIEW) { diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 370d0f4f1b..714d8d0e8f 100755 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -268,7 +268,7 @@ void LLFloaterReporter::getExperienceInfo(const LLUUID& experience_id) if (LLUUID::null != mExperienceID) { - const LLSD& experience = LLExperienceCache::get(mExperienceID); + const LLSD& experience = LLExperienceCache::getInstance()->get(mExperienceID); std::stringstream desc; if(experience.isDefined()) diff --git a/indra/newview/llpanelexperiencelisteditor.cpp b/indra/newview/llpanelexperiencelisteditor.cpp index fc4ee9862e..20fe0c52fa 100644 --- a/indra/newview/llpanelexperiencelisteditor.cpp +++ b/indra/newview/llpanelexperiencelisteditor.cpp @@ -183,7 +183,7 @@ void LLPanelExperienceListEditor::onItems() columns[0]["value"] = getString("loading"); mItems->addElement(item); - LLExperienceCache::get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, + LLExperienceCache::getInstance()->get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, getDerivedHandle(), _1)); } diff --git a/indra/newview/llpanelexperiencelog.cpp b/indra/newview/llpanelexperiencelog.cpp index df03ef7526..9329d900b1 100644 --- a/indra/newview/llpanelexperiencelog.cpp +++ b/indra/newview/llpanelexperiencelog.cpp @@ -140,7 +140,7 @@ void LLPanelExperienceLog::refresh() } const LLSD event = dayArray[i]; LLUUID id = event[LLExperienceCache::EXPERIENCE_ID].asUUID(); - const LLSD& experience = LLExperienceCache::get(id); + const LLSD& experience = LLExperienceCache::getInstance()->get(id); if(experience.isUndefined()){ waiting = true; waiting_id = id; @@ -168,7 +168,7 @@ void LLPanelExperienceLog::refresh() { mEventList->deleteAllItems(); mEventList->setCommentText(getString("loading")); - LLExperienceCache::get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this)); + LLExperienceCache::getInstance()->get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this)); } else { diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp index c7a353a6af..7c19e32e7e 100644 --- a/indra/newview/llpanelexperiencepicker.cpp +++ b/indra/newview/llpanelexperiencepicker.cpp @@ -238,7 +238,7 @@ void LLPanelExperiencePicker::processResponse( const LLUUID& query_id, const LLS LLSD::array_const_iterator it = experiences.beginArray(); for ( ; it != experiences.endArray(); ++it) { - LLExperienceCache::insert(*it); + LLExperienceCache::getInstance()->insert(*it); } getChildView(BTN_RIGHT)->setEnabled(content.has("next_page_url")); diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index a548d7b705..4f5d21b6be 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1326,7 +1326,7 @@ void LLLiveLSLEditor::buildExperienceList() position = ADD_TOP; } - const LLSD& experience = LLExperienceCache::get(id); + const LLSD& experience = LLExperienceCache::getInstance()->get(id); if(experience.isUndefined()) { mExperiences->add(getString("loading"), id, position); @@ -1345,7 +1345,7 @@ void LLLiveLSLEditor::buildExperienceList() if(!foundAssociated ) { - const LLSD& experience = LLExperienceCache::get(associated); + const LLSD& experience = LLExperienceCache::getInstance()->get(associated); if(experience.isDefined()) { std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); @@ -1366,7 +1366,7 @@ void LLLiveLSLEditor::buildExperienceList() if(last.notNull()) { mExperiences->setEnabled(FALSE); - LLExperienceCache::get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); + LLExperienceCache::getInstance()->get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); } else { diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 46f75c4f57..361cc6c48b 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2821,9 +2821,10 @@ void LLStartUp::initNameCache() void LLStartUp::initExperiences() { - // just a get instance here. Should trigger loading the cache. - LLExperienceCache::getInstance(); - LLAppViewer::instance()->loadExperienceCache(); + // Should trigger loading the cache. + LLExperienceCache::getInstance()->setCapabilityQuery( + boost::bind(&LLAgent::getRegionCapability, &gAgent, _1)); + LLExperienceLog::instance().initialize(); } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 886725be79..4e1a86bb71 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6653,7 +6653,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data) else if(experienceid.notNull()) { payload["experience"]=experienceid; - LLExperienceCache::get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); + LLExperienceCache::getInstance()->get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); return; } -- cgit v1.3 From 4676db63b2c38bec92fc5078b08a7c4b3d381fce Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 17 Nov 2015 15:35:49 -0800 Subject: MAINT-5804: Additional logging in attempt to trap teleport disconnect. MAINT-5831: Discard late teleport initiation for teleport sequence that has already failed. --- indra/newview/llagent.cpp | 48 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) (limited to 'indra/newview/llagent.cpp') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index e33d34ebc7..7f238a9a3b 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -3690,6 +3690,7 @@ void LLAgent::clearVisualParams(void *data) // protected bool LLAgent::teleportCore(bool is_local) { + LL_INFOS("Teleport") << "In teleport core!" << LL_ENDL; if ((TELEPORT_NONE != mTeleportState) && (mTeleportState != TELEPORT_PENDING)) { LL_WARNS() << "Attempt to teleport when already teleporting." << LL_ENDL; @@ -3783,6 +3784,7 @@ bool LLAgent::hasRestartableFailedTeleportRequest() void LLAgent::restartFailedTeleportRequest() { + LL_INFOS("Teleport") << "Agent wishes to restart failed teleport." << LL_ENDL; if (hasRestartableFailedTeleportRequest()) { mTeleportRequest->setStatus(LLTeleportRequest::kRestartPending); @@ -3814,6 +3816,7 @@ bool LLAgent::hasPendingTeleportRequest() void LLAgent::startTeleportRequest() { + LL_INFOS("Telport") << "Agent handling start teleport request." << LL_ENDL; if(LLVoiceClient::instanceExists()) { LLVoiceClient::getInstance()->setHidden(TRUE); @@ -3848,6 +3851,7 @@ void LLAgent::startTeleportRequest() void LLAgent::handleTeleportFinished() { + LL_INFOS("Teleport") << "Agent handling teleport finished." << LL_ENDL; clearTeleportRequest(); if (mIsMaturityRatingChangingDuringTeleport) { @@ -3869,12 +3873,18 @@ void LLAgent::handleTeleportFinished() void LLAgent::handleTeleportFailed() { + LL_WARNS("Teleport") << "Agent handling teleport failure!" << LL_ENDL; if(LLVoiceClient::instanceExists()) { LLVoiceClient::getInstance()->setHidden(FALSE); } - if (mTeleportRequest != NULL) + setTeleportState(LLAgent::TELEPORT_NONE); + // Unlock the UI if the progress bar has been shown. +// gViewerWindow->setShowProgress(FALSE); +// gTeleportDisplay = FALSE; + + if (mTeleportRequest) { mTeleportRequest->setStatus(LLTeleportRequest::kFailed); } @@ -4076,6 +4086,13 @@ void LLAgent::doTeleportViaLocationLookAt(const LLVector3d& pos_global) void LLAgent::setTeleportState(ETeleportState state) { + if (mTeleportRequest && (state != TELEPORT_NONE) && (mTeleportRequest->getStatus() == LLTeleportRequest::kFailed)) + { // A late message has come in regarding a failed teleport. + // We have already decided that it failed so should not reinitiate the teleport sequence in the viewer. + LL_WARNS("Teleport") << "Attempt to set teleport state to " << state << + " for previously failed teleport. Ignore!" << LL_ENDL; + return; + } mTeleportState = state; if (mTeleportState > TELEPORT_NONE && gSavedSettings.getBOOL("FreezeTime")) { @@ -4422,24 +4439,29 @@ LLTeleportRequestViaLandmark::LLTeleportRequestViaLandmark(const LLUUID &pLandma : LLTeleportRequest(), mLandmarkId(pLandmarkId) { + LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark created." << LL_ENDL; } LLTeleportRequestViaLandmark::~LLTeleportRequestViaLandmark() { + LL_INFOS("Teleport") << "~LLTeleportRequestViaLandmark" << LL_ENDL; } bool LLTeleportRequestViaLandmark::canRestartTeleport() { + LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark::canRestartTeleport? -> true" << LL_ENDL; return true; } void LLTeleportRequestViaLandmark::startTeleport() { + LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark::startTeleport" << LL_ENDL; gAgent.doTeleportViaLandmark(getLandmarkId()); } void LLTeleportRequestViaLandmark::restartTeleport() { + LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark::restartTeleport" << LL_ENDL; gAgent.doTeleportViaLandmark(getLandmarkId()); } @@ -4451,10 +4473,12 @@ LLTeleportRequestViaLure::LLTeleportRequestViaLure(const LLUUID &pLureId, BOOL p : LLTeleportRequestViaLandmark(pLureId), mIsLureGodLike(pIsLureGodLike) { + LL_INFOS("Teleport") << "LLTeleportRequestViaLure created" << LL_ENDL; } LLTeleportRequestViaLure::~LLTeleportRequestViaLure() { + LL_INFOS("Teleport") << "~LLTeleportRequestViaLure" << LL_ENDL; } bool LLTeleportRequestViaLure::canRestartTeleport() @@ -4471,11 +4495,13 @@ bool LLTeleportRequestViaLure::canRestartTeleport() // 8. User B's viewer then attempts to teleport via lure again // 9. This request will time-out on the viewer-side because User A's initial request has been removed from the "queue" in step 4 - return false; + LL_INFOS("Teleport") << "LLTeleportRequestViaLure::canRestartTeleport? -> false" << LL_ENDL; + return false; } void LLTeleportRequestViaLure::startTeleport() { + LL_INFOS("Teleport") << "LLTeleportRequestViaLure::startTeleport" << LL_ENDL; gAgent.doTeleportViaLure(getLandmarkId(), isLureGodLike()); } @@ -4487,25 +4513,30 @@ LLTeleportRequestViaLocation::LLTeleportRequestViaLocation(const LLVector3d &pPo : LLTeleportRequest(), mPosGlobal(pPosGlobal) { + LL_INFOS("Teleport") << "LLTeleportRequestViaLocation created" << LL_ENDL; } LLTeleportRequestViaLocation::~LLTeleportRequestViaLocation() { + LL_INFOS("Teleport") << "~LLTeleportRequestViaLocation" << LL_ENDL; } bool LLTeleportRequestViaLocation::canRestartTeleport() { + LL_INFOS("Teleport") << "LLTeleportRequestViaLocation::canRestartTeleport -> true" << LL_ENDL; return true; } void LLTeleportRequestViaLocation::startTeleport() { + LL_INFOS("Teleport") << "LLTeleportRequestViaLocation::startTeleport" << LL_ENDL; gAgent.doTeleportViaLocation(getPosGlobal()); } void LLTeleportRequestViaLocation::restartTeleport() { - gAgent.doTeleportViaLocation(getPosGlobal()); + LL_INFOS("Teleport") << "LLTeleportRequestViaLocation::restartTeleport" << LL_ENDL; + gAgent.doTeleportViaLocation(getPosGlobal()); } //----------------------------------------------------------------------------- @@ -4515,25 +4546,30 @@ void LLTeleportRequestViaLocation::restartTeleport() LLTeleportRequestViaLocationLookAt::LLTeleportRequestViaLocationLookAt(const LLVector3d &pPosGlobal) : LLTeleportRequestViaLocation(pPosGlobal) { + LL_INFOS("Teleport") << "LLTeleportRequestViaLocationLookAt created" << LL_ENDL; } LLTeleportRequestViaLocationLookAt::~LLTeleportRequestViaLocationLookAt() { + LL_INFOS("Teleport") << "~LLTeleportRequestViaLocationLookAt" << LL_ENDL; } bool LLTeleportRequestViaLocationLookAt::canRestartTeleport() { - return true; + LL_INFOS("Teleport") << "LLTeleportRequestViaLocationLookAt::canRestartTeleport -> true" << LL_ENDL; + return true; } void LLTeleportRequestViaLocationLookAt::startTeleport() { - gAgent.doTeleportViaLocationLookAt(getPosGlobal()); + LL_INFOS("Teleport") << "LLTeleportRequestViaLocationLookAt::startTeleport" << LL_ENDL; + gAgent.doTeleportViaLocationLookAt(getPosGlobal()); } void LLTeleportRequestViaLocationLookAt::restartTeleport() { - gAgent.doTeleportViaLocationLookAt(getPosGlobal()); + LL_INFOS("Teleport") << "LLTeleportRequestViaLocationLookAt::restartTeleport" << LL_ENDL; + gAgent.doTeleportViaLocationLookAt(getPosGlobal()); } // EOF -- cgit v1.3 From 40b085dfece81e155f336f39cb1d5bd7e3154991 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Fri, 20 Nov 2015 10:24:16 -0800 Subject: MAINT-5831: If there is a teleport request active and it has failed, teleport state will always return "None". --- indra/newview/llagent.cpp | 7 +++++++ indra/newview/llagent.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'indra/newview/llagent.cpp') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 7f238a9a3b..157eb7d662 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -4084,6 +4084,13 @@ void LLAgent::doTeleportViaLocationLookAt(const LLVector3d& pos_global) teleportRequest(region_handle, pos_local, getTeleportKeepsLookAt()); } +LLAgent::ETeleportState LLAgent::getTeleportState() const +{ + return (mTeleportRequest && (mTeleportRequest->getStatus() == LLTeleportRequest::kFailed)) ? + TELEPORT_NONE : mTeleportState; +} + + void LLAgent::setTeleportState(ETeleportState state) { if (mTeleportRequest && (state != TELEPORT_NONE) && (mTeleportRequest->getStatus() == LLTeleportRequest::kFailed)) diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index d46973ddee..af8bd50c5d 100755 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -676,7 +676,7 @@ private: // Teleport State //-------------------------------------------------------------------- public: - ETeleportState getTeleportState() const { return mTeleportState; } + ETeleportState getTeleportState() const; void setTeleportState(ETeleportState state); private: ETeleportState mTeleportState; -- cgit v1.3