summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rwxr-xr-xindra/newview/CMakeLists.txt14
-rwxr-xr-xindra/newview/llaccountingcostmanager.cpp284
-rwxr-xr-xindra/newview/llaccountingcostmanager.h15
-rwxr-xr-xindra/newview/llagent.cpp197
-rwxr-xr-xindra/newview/llagent.h31
-rwxr-xr-xindra/newview/llagentlanguage.cpp8
-rwxr-xr-xindra/newview/llappcorehttp.cpp81
-rwxr-xr-xindra/newview/llappcorehttp.h28
-rwxr-xr-xindra/newview/llappearancemgr.cpp586
-rwxr-xr-xindra/newview/llappearancemgr.h22
-rw-r--r--indra/newview/llavatarrenderinfoaccountant.cpp131
-rw-r--r--indra/newview/llavatarrenderinfoaccountant.h10
-rwxr-xr-xindra/newview/llhttpretrypolicy.cpp2
-rwxr-xr-xindra/newview/llmaterialmgr.cpp141
-rw-r--r--indra/newview/llmaterialmgr.h49
-rwxr-xr-xindra/newview/llvoavatarself.cpp1
-rwxr-xr-xindra/newview/llxmlrpctransaction.cpp500
-rwxr-xr-xindra/newview/llxmlrpctransaction.h4
18 files changed, 1215 insertions, 889 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 13040ea423..3858383e39 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -2330,16 +2330,26 @@ if (LL_TESTS)
"${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
+ rt
+ )
+ endif (LINUX)
+
set(test_libs
- ${LLMESSAGE_LIBRARIES}
- ${LLCOREHTTP_LIBRARIES}
${WINDOWS_LIBRARIES}
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES}
+ ${LLMESSAGE_LIBRARIES}
+ ${LLCOREHTTP_LIBRARIES}
${GOOGLEMOCK_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
+ ${LIBRT_LIBRARY}
+ ${BOOST_CONTEXT_LIBRARY}
+ ${BOOST_COROUTINE_LIBRARY}
)
LL_ADD_INTEGRATION_TEST(llsechandler_basic
diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp
index a42286a9e4..c52e6e1172 100755
--- a/indra/newview/llaccountingcostmanager.cpp
+++ b/indra/newview/llaccountingcostmanager.cpp
@@ -27,90 +27,171 @@
#include "llviewerprecompiledheaders.h"
#include "llaccountingcostmanager.h"
#include "llagent.h"
-#include "llcurl.h"
-#include "llhttpclient.h"
+#include "httpcommon.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "llcorehttputil.h"
+
//===============================================================================
-LLAccountingCostManager::LLAccountingCostManager()
+LLAccountingCostManager::LLAccountingCostManager():
+ mHttpRequest(),
+ mHttpHeaders(),
+ mHttpOptions(),
+ mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
+ mHttpPriority(0)
{
+ 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;
+
}
-//===============================================================================
-class LLAccountingCostResponder : public LLCurl::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 LLAccountingCostManager::accountingCostCoro(LLCoros::self& self, std::string url,
+ eSelectionType selectionType, const LLHandle<LLAccountingCostObserver> observerHandle)
{
- LOG_CLASS(LLAccountingCostResponder);
-public:
- LLAccountingCostResponder( const LLSD& objectIDs, const LLHandle<LLAccountingCostObserver>& observer_handle )
- : mObjectIDs( objectIDs ),
- mObserverHandle( observer_handle )
- {
- LLAccountingCostObserver* observer = mObserverHandle.get();
- if (observer)
- {
- mTransactionID = observer->getTransactionID();
- }
- }
+ LLEventStream replyPump("AccountingCostReply", true);
+ LLCoreHttpUtil::HttpCoroHandler::ptr_t httpHandler =
+ LLCoreHttpUtil::HttpCoroHandler::ptr_t(new LLCoreHttpUtil::HttpCoroHandler(replyPump));
- void clearPendingRequests ( void )
- {
- for ( LLSD::array_iterator iter = mObjectIDs.beginArray(); iter != mObjectIDs.endArray(); ++iter )
- {
- LLAccountingCostManager::getInstance()->removePendingObject( iter->asUUID() );
- }
- }
-
-protected:
- void httpFailure()
- {
- LL_WARNS() << dumpResponse() << LL_ENDL;
- clearPendingRequests();
-
- LLAccountingCostObserver* observer = mObserverHandle.get();
- if (observer && observer->getTransactionID() == mTransactionID)
- {
- observer->setErrorStatus(getStatus(), getReason());
- }
- }
-
- void httpSuccess()
- {
- const LLSD& content = getContent();
- //Check for error
- if ( !content.isMap() || content.has("error") )
- {
- failureResult(HTTP_INTERNAL_ERROR, "Error on fetched data", content);
- return;
- }
- else if (content.has("selected"))
- {
- F32 physicsCost = 0.0f;
- F32 networkCost = 0.0f;
- F32 simulationCost = 0.0f;
-
- physicsCost = content["selected"]["physics"].asReal();
- networkCost = content["selected"]["streaming"].asReal();
- simulationCost = content["selected"]["simulation"].asReal();
-
- SelectionCost selectionCost( /*transactionID,*/ physicsCost, networkCost, simulationCost );
-
- LLAccountingCostObserver* observer = mObserverHandle.get();
- if (observer && observer->getTransactionID() == mTransactionID)
- {
- observer->onWeightsUpdate(selectionCost);
- }
- }
-
- clearPendingRequests();
- }
-
-private:
- //List of posted objects
- LLSD mObjectIDs;
+ LL_DEBUGS("LLAccountingCostManager") << "Entering coroutine " << LLCoros::instance().getName(self)
+ << " with url '" << url << LL_ENDL;
+
+ try
+ {
+ LLSD objectList;
+ U32 objectIndex = 0;
+
+ IDIt IDIter = mObjectList.begin();
+ IDIt IDIterEnd = mObjectList.end();
+
+ for (; IDIter != IDIterEnd; ++IDIter)
+ {
+ // Check to see if a request for this object has already been made.
+ if (mPendingObjectQuota.find(*IDIter) == mPendingObjectQuota.end())
+ {
+ mPendingObjectQuota.insert(*IDIter);
+ objectList[objectIndex++] = *IDIter;
+ }
+ }
+
+ mObjectList.clear();
+
+ //Post results
+ if (objectList.size() == 0)
+ return;
+
+ std::string keystr;
+ if (selectionType == Roots)
+ {
+ keystr = "selected_roots";
+ }
+ else if (selectionType == Prims)
+ {
+ keystr = "selected_prims";
+ }
+ else
+ {
+ LL_INFOS() << "Invalid selection type " << LL_ENDL;
+ mObjectList.clear();
+ mPendingObjectQuota.clear();
+ return;
+ }
- // Current request ID
- LLUUID mTransactionID;
+ LLSD dataToPost = LLSD::emptyMap();
+ dataToPost[keystr.c_str()] = objectList;
+
+ LLAccountingCostObserver* observer = observerHandle.get();
+ LLUUID transactionId = observer->getTransactionID();
+ observer = NULL;
+
+ LLSD results;
+ { // Scoping block for pumper object
+ LL_INFOS() << "Requesting transaction " << transactionId << LL_ENDL;
+ LLCoreHttpUtil::HttpRequestPumper pumper(mHttpRequest);
+ LLCore::HttpHandle hhandle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,
+ mHttpPolicy, mHttpPriority, url, dataToPost, mHttpOptions, mHttpHeaders,
+ httpHandler.get());
+
+ if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ LLCore::HttpStatus status = mHttpRequest->getStatus();
+ LL_WARNS() << "Error posting to " << url << " Status=" << status.getStatus() <<
+ " message = " << status.getMessage() << LL_ENDL;
+ mPendingObjectQuota.clear();
+ return;
+ }
+
+ results = waitForEventOn(self, replyPump);
+ LL_INFOS() << "Results for transaction " << transactionId << LL_ENDL;
+ }
+ LLSD httpResults;
+ httpResults = results["http_result"];
+
+ do
+ {
+ observer = observerHandle.get();
+ if ((!observer) || (observer->getTransactionID() != transactionId))
+ {
+ if (!observer)
+ break;
+ LL_WARNS() << "Request transaction Id(" << transactionId
+ << ") does not match observer's transaction Id("
+ << observer->getTransactionID() << ")." << LL_ENDL;
+ break;
+ }
+
+ if (!httpResults["success"].asBoolean())
+ {
+ LL_WARNS() << "Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
+ << httpResults["status"] << ": '" << httpResults["message"] << "'" << LL_ENDL;
+ if (observer)
+ {
+ observer->setErrorStatus(httpResults["status"].asInteger(), httpResults["message"].asStringRef());
+ }
+ break;
+ }
+
+ if (!results.isMap() || results.has("error"))
+ {
+ LL_WARNS() << "Error on fetched data" << LL_ENDL;
+ observer->setErrorStatus(499, "Error on fetched data");
+ break;
+ }
+
+ if (results.has("selected"))
+ {
+ F32 physicsCost = 0.0f;
+ F32 networkCost = 0.0f;
+ F32 simulationCost = 0.0f;
+
+ physicsCost = results["selected"]["physics"].asReal();
+ networkCost = results["selected"]["streaming"].asReal();
+ simulationCost = results["selected"]["simulation"].asReal();
+
+ SelectionCost selectionCost( physicsCost, networkCost, simulationCost);
+
+ observer->onWeightsUpdate(selectionCost);
+ }
+
+ } while (false);
+
+ }
+ catch (std::exception e)
+ {
+ LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL;
+ }
+ catch (...)
+ {
+ LL_WARNS() << "Caught unknown exception." << LL_ENDL;
+ }
+
+ mPendingObjectQuota.clear();
+}
- // Cost update observer handle
- LLHandle<LLAccountingCostObserver> mObserverHandle;
-};
//===============================================================================
void LLAccountingCostManager::fetchCosts( eSelectionType selectionType,
const std::string& url,
@@ -119,50 +200,11 @@ void LLAccountingCostManager::fetchCosts( eSelectionType selectionType,
// Invoking system must have already determined capability availability
if ( !url.empty() )
{
- LLSD objectList;
- U32 objectIndex = 0;
-
- IDIt IDIter = mObjectList.begin();
- IDIt IDIterEnd = mObjectList.end();
-
- for ( ; IDIter != IDIterEnd; ++IDIter )
- {
- // Check to see if a request for this object has already been made.
- if ( mPendingObjectQuota.find( *IDIter ) == mPendingObjectQuota.end() )
- {
- mPendingObjectQuota.insert( *IDIter );
- objectList[objectIndex++] = *IDIter;
- }
- }
-
- mObjectList.clear();
-
- //Post results
- if ( objectList.size() > 0 )
- {
- std::string keystr;
- if ( selectionType == Roots )
- {
- keystr="selected_roots";
- }
- else
- if ( selectionType == Prims )
- {
- keystr="selected_prims";
- }
- else
- {
- LL_INFOS()<<"Invalid selection type "<<LL_ENDL;
- mObjectList.clear();
- mPendingObjectQuota.clear();
- return;
- }
-
- LLSD dataToPost = LLSD::emptyMap();
- dataToPost[keystr.c_str()] = objectList;
-
- LLHTTPClient::post( url, dataToPost, new LLAccountingCostResponder( objectList, observer_handle ));
- }
+ std::string coroname =
+ LLCoros::instance().launch("LLAccountingCostManager::accountingCostCoro",
+ boost::bind(&LLAccountingCostManager::accountingCostCoro, this, _1, url, selectionType, observer_handle));
+ LL_DEBUGS() << coroname << " with url '" << url << LL_ENDL;
+
}
else
{
diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h
index 3ade34c81d..7d544b15e8 100755
--- a/indra/newview/llaccountingcostmanager.h
+++ b/indra/newview/llaccountingcostmanager.h
@@ -30,6 +30,13 @@
#include "llhandle.h"
#include "llaccountingcost.h"
+#include "httpcommon.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "httprequest.h"
+#include "httpheaders.h"
+#include "httpoptions.h"
+
//===============================================================================
// An interface class for panels which display the parcel accounting information.
class LLAccountingCostObserver
@@ -69,6 +76,14 @@ private:
//a fetch has been instigated.
std::set<LLUUID> mPendingObjectQuota;
typedef std::set<LLUUID>::iterator IDIt;
+
+ void accountingCostCoro(LLCoros::self& self, std::string url, eSelectionType selectionType, const LLHandle<LLAccountingCostObserver> observerHandle);
+
+ 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;
};
//===============================================================================
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index f151b15e29..eeedda5c6d 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;
@@ -361,7 +363,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 +466,17 @@ 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_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;
}
@@ -476,6 +494,10 @@ void LLAgent::cleanup()
{
mTeleportFailedSlot.disconnect();
}
+ if (mBoundListener.connected())
+ {
+ mBoundListener.disconnect();
+ }
}
//-----------------------------------------------------------------------------
@@ -498,6 +520,17 @@ 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).
//-----------------------------------------------------------------------------
@@ -2515,66 +2548,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(LLAgent *agent, U8 preferred, U8 previous):
+ LLHttpSDHandler(),
+ mAgent(agent),
+ mPreferredMaturity(preferred),
+ mPreviousMaturity(previous)
+ { }
-protected:
- virtual void httpSuccess();
- virtual void httpFailure();
+ 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;
+ U8 parseMaturityFromServerResponse(const LLSD &pContent) const;
- LLAgent *mAgent;
- U8 mPreferredMaturity;
- U8 mPreviousMaturity;
-};
-
-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, const 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<U32>(actualMaturity)
- << "], " << dumpResponse() << LL_ENDL;
+ << LLViewerRegion::accessToString(mPreviousMaturity)
+ << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity)
+ << "', the server responded with '"
+ << LLViewerRegion::accessToString(actualMaturity)
+ << "' [value:" << static_cast<U32>(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 +2623,7 @@ U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &p
return maturity;
}
+//=========================================================================
void LLAgent::handlePreferredMaturityResult(U8 pServerMaturity)
{
@@ -2724,42 +2753,82 @@ 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(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);
+
+ if (handle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ delete handler;
+ 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(cap);
+ LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,
+ mHttpPolicy, mHttpPriority, url,
+ postData, mHttpOptions, mHttpHeaders, 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 POST failed. Reason "
+ << status.toTerseString() << " \"" << status.toString() << "\"" << LL_ENDL;
+ }
+ return handle;
+}
+
+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
{
return mAgentAccess->getAdminOverride();
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 56bd1428ce..9ffc9b9a7a 100755
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -34,7 +34,11 @@
#include "llcoordframe.h" // for mFrameAgent
#include "llavatarappearancedefines.h"
#include "llpermissionsflags.h"
+#include "llevents.h"
#include "v3dmath.h"
+#include "httprequest.h"
+#include "httpheaders.h"
+#include "httpoptions.h"
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
@@ -60,6 +64,7 @@ class LLSLURL;
class LLPauseRequestHandle;
class LLUIColor;
class LLTeleportRequest;
+class LLHttpSDHandler;
typedef boost::shared_ptr<LLTeleportRequest> LLTeleportRequestPtr;
@@ -112,6 +117,8 @@ public:
void init();
void cleanup();
+private:
+
//--------------------------------------------------------------------
// Login
//--------------------------------------------------------------------
@@ -754,11 +761,17 @@ 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);
- friend class LLMaturityPreferencesResponder;
+ friend class LLMaturityHttpHandler;
void handlePreferredMaturityResult(U8 pServerMaturity);
void handlePreferredMaturityError();
void reportPreferredMaturitySuccess();
@@ -768,6 +781,8 @@ private:
void handleMaturity(const LLSD &pNewValue);
bool validateMaturity(const LLSD& newvalue);
+ bool pollHttp(const LLSD &);
+
/** Access
** **
@@ -907,6 +922,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 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
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
** DEBUGGING
**/
diff --git a/indra/newview/llagentlanguage.cpp b/indra/newview/llagentlanguage.cpp
index fe6236a32a..f2ac323578 100755
--- a/indra/newview/llagentlanguage.cpp
+++ b/indra/newview/llagentlanguage.cpp
@@ -32,6 +32,7 @@
#include "llviewerregion.h"
// library includes
#include "llui.h" // getLanguage()
+#include "httpcommon.h"
// static
void LLAgentLanguage::init()
@@ -69,7 +70,12 @@ bool LLAgentLanguage::update()
body["language"] = language;
body["language_is_public"] = gSavedSettings.getBOOL("LanguageIsPublic");
- LLHTTPClient::post(url, body, new LLHTTPClient::Responder);
+ //LLHTTPClient::post(url, body, new LLHTTPClient::Responder);
+ LLCore::HttpHandle handle = gAgent.requestPostCapability("UpdateAgentLanguage", url, body);
+ if (handle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ LL_WARNS() << "Unable to change language." << LL_ENDL;
+ }
}
return true;
}
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index f5f224b83e..51cca273d8 100755
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -31,6 +31,10 @@
#include "llappviewer.h"
#include "llviewercontrol.h"
+#include <openssl/x509_vfy.h>
+#include <openssl/ssl.h>
+#include "llsecapi.h"
+#include <curl/curl.h>
// Here is where we begin to get our connection usage under control.
// This establishes llcorehttp policy classes that, among other
@@ -93,6 +97,16 @@ static const struct
4, 1, 4, 0, false,
"",
"inventory"
+ },
+ { // AP_MATERIALS
+ 2, 1, 8, 0, false,
+ "RenderMaterials",
+ "material manager requests"
+ },
+ { // AP_AGENT
+ 2, 1, 32, 0, true,
+ "Agent",
+ "Agent requests"
}
};
@@ -151,6 +165,15 @@ void LLAppCoreHttp::init()
<< LL_ENDL;
}
+ // Set up SSL Verification call back.
+ status = LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_SSL_VERIFY_CALLBACK,
+ LLCore::HttpRequest::GLOBAL_POLICY_ID,
+ sslVerify, NULL);
+ if (!status)
+ {
+ LL_WARNS("Init") << "Failed to set SSL Verification. Reason: " << status.toString() << LL_ENDL;
+ }
+
// Tracing levels for library & libcurl (note that 2 & 3 are beyond spammy):
// 0 - None
// 1 - Basic start, stop simple transitions
@@ -182,6 +205,8 @@ void LLAppCoreHttp::init()
}
mHttpClasses[app_policy].mPolicy = LLCore::HttpRequest::createPolicyClass();
+ // We have run out of available HTTP policies. Adjust HTTP_POLICY_CLASS_LIMIT in _httpinternal.h
+ llassert(mHttpClasses[app_policy].mPolicy != LLCore::HttpRequest::INVALID_POLICY_ID);
if (! mHttpClasses[app_policy].mPolicy)
{
// Use default policy (but don't accidentally modify default)
@@ -457,6 +482,62 @@ void LLAppCoreHttp::refreshSettings(bool initial)
}
}
+LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
+ LLCore::HttpHandler const * const handler, void *appdata)
+{
+ X509_STORE_CTX *ctx = static_cast<X509_STORE_CTX *>(appdata);
+ LLCore::HttpStatus result;
+ LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore("");
+ LLPointer<LLCertificateChain> chain = gSecAPIHandler->getCertificateChain(ctx);
+ LLSD validation_params = LLSD::emptyMap();
+ LLURI uri(url);
+
+ validation_params[CERT_HOSTNAME] = uri.hostName();
+
+ // *TODO: In the case of an exception while validating the cert, we need a way
+ // to pass the offending(?) cert back out. *Rider*
+
+ try
+ {
+ // don't validate hostname. Let libcurl do it instead. That way, it'll handle redirects
+ store->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), chain, validation_params);
+ }
+ catch (LLCertValidationTrustException &cert_exception)
+ {
+ // this exception is is handled differently than the general cert
+ // exceptions, as we allow the user to actually add the certificate
+ // for trust.
+ // therefore we pass back a different error code
+ // NOTE: We're currently 'wired' to pass around CURL error codes. This is
+ // somewhat clumsy, as we may run into errors that do not map directly to curl
+ // error codes. Should be refactored with login refactoring, perhaps.
+ result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CACERT);
+ result.setMessage(cert_exception.getMessage());
+ LLPointer<LLCertificate> cert = cert_exception.getCert();
+ cert->ref(); // adding an extra ref here
+ result.setErrorData(cert.get());
+ // We should probably have a more generic way of passing information
+ // back to the error handlers.
+ }
+ catch (LLCertException &cert_exception)
+ {
+ result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_PEER_CERTIFICATE);
+ result.setMessage(cert_exception.getMessage());
+ LLPointer<LLCertificate> cert = cert_exception.getCert();
+ cert->ref(); // adding an extra ref here
+ result.setErrorData(cert.get());
+ }
+ catch (...)
+ {
+ // any other odd error, we just handle as a connect error.
+ result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CONNECT_ERROR);
+ }
+
+ return result;
+}
+
+
+
void LLAppCoreHttp::onCompleted(LLCore::HttpHandle, LLCore::HttpResponse *)
{
diff --git a/indra/newview/llappcorehttp.h b/indra/newview/llappcorehttp.h
index 37d7a737e7..410d7c6b07 100755
--- a/indra/newview/llappcorehttp.h
+++ b/indra/newview/llappcorehttp.h
@@ -164,7 +164,29 @@ public:
/// Pipelined: no
AP_INVENTORY,
AP_REPORTING = AP_INVENTORY, // Piggy-back on inventory
-
+
+ /// Material resource requests and puts.
+ ///
+ /// Destination: simhost:12043
+ /// Protocol: https:
+ /// Transfer size: KB
+ /// Long poll: no
+ /// Concurrency: low
+ /// Request rate: low
+ /// Pipelined: no
+ AP_MATERIALS,
+
+ /// Appearance resource requests and puts.
+ ///
+ /// Destination: simhost:12043
+ /// Protocol: https:
+ /// Transfer size: KB
+ /// Long poll: no
+ /// Concurrency: mid
+ /// Request rate: low
+ /// Pipelined: yes
+ AP_AGENT,
+
AP_COUNT // Must be last
};
@@ -233,7 +255,9 @@ private:
bool mStopped;
HttpClass mHttpClasses[AP_COUNT];
bool mPipelined; // Global setting
- boost::signals2::connection mPipelinedSignal; // Signal for 'HttpPipelining' setting
+ boost::signals2::connection mPipelinedSignal; // Signal for 'HttpPipelining' setting
+
+ static LLCore::HttpStatus sslVerify(const std::string &uri, LLCore::HttpHandler const * const handler, void *appdata);
};
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index a64d5b50b3..4fbcd90baa 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -23,7 +23,7 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
+
#include "llviewerprecompiledheaders.h"
#include <boost/lexical_cast.hpp>
@@ -54,6 +54,9 @@
#include "llsdserialize.h"
#include "llhttpretrypolicy.h"
#include "llaisapi.h"
+#include "llhttpsdhandler.h"
+#include "llcorehttputil.h"
+#include "llappviewer.h"
#if LL_MSVC
// disable boost::lexical_cast warning
@@ -1242,6 +1245,165 @@ static void removeDuplicateItems(LLInventoryModel::item_array_t& items)
items = new_items;
}
+//=========================================================================
+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;
+}
+
+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<LLUUID> 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<LLUUID>::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<LLUUID>::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
{
return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
@@ -3154,276 +3316,6 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id,
}
-class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder
-{
- LOG_CLASS(RequestAgentUpdateAppearanceResponder);
-
- friend class LLAppearanceMgr;
-
-public:
- RequestAgentUpdateAppearanceResponder();
-
- virtual ~RequestAgentUpdateAppearanceResponder();
-
-private:
- // Called when sendServerAppearanceUpdate called. May or may not
- // trigger a request depending on various bits of state.
- void onRequestRequested();
-
- // Post the actual appearance request to cap.
- void sendRequest();
-
- void debugCOF(const LLSD& content);
-
-protected:
- // Successful completion.
- /* virtual */ void httpSuccess();
-
- // Error
- /*virtual*/ void httpFailure();
-
- void onFailure();
- void onSuccess();
-
- S32 mInFlightCounter;
- LLTimer mInFlightTimer;
- LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
-};
-
-RequestAgentUpdateAppearanceResponder::RequestAgentUpdateAppearanceResponder()
-{
- bool retry_on_4xx = true;
- mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10, retry_on_4xx);
- mInFlightCounter = 0;
-}
-
-RequestAgentUpdateAppearanceResponder::~RequestAgentUpdateAppearanceResponder()
-{
-}
-
-void RequestAgentUpdateAppearanceResponder::onRequestRequested()
-{
- // If we have already received an update for this or higher cof version, ignore.
- S32 cof_version = LLAppearanceMgr::instance().getCOFVersion();
- S32 last_rcv = gAgentAvatarp->mLastUpdateReceivedCOFVersion;
- S32 last_req = gAgentAvatarp->mLastUpdateRequestCOFVersion;
- LL_DEBUGS("Avatar") << "cof_version " << cof_version
- << " last_rcv " << last_rcv
- << " last_req " << last_req
- << " in flight " << mInFlightCounter << LL_ENDL;
- if ((mInFlightCounter>0) && (mInFlightTimer.hasExpired()))
- {
- LL_WARNS("Avatar") << "in flight timer expired, resetting " << LL_ENDL;
- mInFlightCounter = 0;
- }
- if (cof_version < last_rcv)
- {
- LL_DEBUGS("Avatar") << "Have already received update for cof version " << last_rcv
- << " will not request for " << cof_version << LL_ENDL;
- return;
- }
- if (mInFlightCounter>0 && last_req >= cof_version)
- {
- LL_DEBUGS("Avatar") << "Request already in flight for cof version " << last_req
- << " will not request for " << cof_version << LL_ENDL;
- return;
- }
-
- // Actually send the request.
- LL_DEBUGS("Avatar") << "Will send request for cof_version " << cof_version << LL_ENDL;
- mRetryPolicy->reset();
- sendRequest();
-}
-
-void RequestAgentUpdateAppearanceResponder::sendRequest()
-{
- if (gAgentAvatarp->isEditingAppearance())
- {
- // don't send out appearance updates if in appearance editing mode
- return;
- }
-
- if (!gAgent.getRegion())
- {
- LL_WARNS() << "Region not set, cannot request server appearance update" << LL_ENDL;
- return;
- }
- if (gAgent.getRegion()->getCentralBakeVersion()==0)
- {
- LL_WARNS() << "Region does not support baking" << LL_ENDL;
- }
- std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance");
- if (url.empty())
- {
- LL_WARNS() << "No cap for UpdateAvatarAppearance." << LL_ENDL;
- return;
- }
-
- LLSD body;
- S32 cof_version = LLAppearanceMgr::instance().getCOFVersion();
- if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate"))
- {
- body = LLAppearanceMgr::instance().dumpCOF();
- }
- else
- {
- body["cof_version"] = cof_version;
- if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
- {
- body["cof_version"] = cof_version+999;
- }
- }
- LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << LL_ENDL;
-
- mInFlightCounter++;
- mInFlightTimer.setTimerExpirySec(60.0);
- LLHTTPClient::post(url, body, this);
- llassert(cof_version >= gAgentAvatarp->mLastUpdateRequestCOFVersion);
- gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version;
-}
-
-void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content)
-{
- LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger()
- << " ================================= " << LL_ENDL;
- std::set<LLUUID> 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<LLUUID>::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<LLUUID>::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;
- }
-}
-
-/* virtual */ void RequestAgentUpdateAppearanceResponder::httpSuccess()
-{
- const LLSD& content = getContent();
- if (!content.isMap())
- {
- failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", 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);
- }
-
- onSuccess();
- }
- else
- {
- failureResult(HTTP_INTERNAL_ERROR, "Non-success response", content);
- }
-}
-
-void RequestAgentUpdateAppearanceResponder::onSuccess()
-{
- mInFlightCounter = llmax(mInFlightCounter-1,0);
-}
-
-/*virtual*/ void RequestAgentUpdateAppearanceResponder::httpFailure()
-{
- LL_WARNS("Avatar") << "appearance update request failed, status "
- << getStatus() << " reason " << getReason() << LL_ENDL;
-
- if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
- {
- const LLSD& content = getContent();
- dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
- debugCOF(content);
- }
- onFailure();
-}
-
-void RequestAgentUpdateAppearanceResponder::onFailure()
-{
- mInFlightCounter = llmax(mInFlightCounter-1,0);
-
- F32 seconds_to_wait;
- mRetryPolicy->onFailure(getStatus(), getResponseHeaders());
- if (mRetryPolicy->shouldRetry(seconds_to_wait))
- {
- LL_INFOS() << "retrying" << LL_ENDL;
- doAfterInterval(boost::bind(&RequestAgentUpdateAppearanceResponder::sendRequest,this),
- seconds_to_wait);
- }
- else
- {
- LL_WARNS() << "giving up after too many retries" << LL_ENDL;
- }
-}
-
LLSD LLAppearanceMgr::dumpCOF() const
{
@@ -3490,101 +3382,104 @@ LLSD LLAppearanceMgr::dumpCOF() const
void LLAppearanceMgr::requestServerAppearanceUpdate()
{
- mAppearanceResponder->onRequestRequested();
-}
-class LLIncrementCofVersionResponder : public LLHTTPClient::Responder
-{
- LOG_CLASS(LLIncrementCofVersionResponder);
-public:
- LLIncrementCofVersionResponder() : LLHTTPClient::Responder()
+ if (!testCOFRequestVersion())
{
- mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 16.0, 2.0, 5);
+ // *TODO: LL_LOG message here
+ return;
}
- virtual ~LLIncrementCofVersionResponder()
+ if ((mInFlightCounter > 0) && (mInFlightTimer.hasExpired()))
{
+ LL_WARNS("Avatar") << "in flight timer expired, resetting " << LL_ENDL;
+ mInFlightCounter = 0;
}
-protected:
- virtual void httpSuccess()
+ if (gAgentAvatarp->isEditingAppearance())
{
- LL_INFOS() << "Successfully incremented agent's COF." << LL_ENDL;
- const LLSD& content = getContent();
- if (!content.isMap())
- {
- failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
- return;
- }
- S32 new_version = content["category"]["version"].asInteger();
-
- // cof_version should have increased
- llassert(new_version > gAgentAvatarp->mLastUpdateRequestCOFVersion);
-
- gAgentAvatarp->mLastUpdateRequestCOFVersion = new_version;
+ LL_WARNS("Avatar") << "Avatar editing appeance, not sending request." << LL_ENDL;
+ // don't send out appearance updates if in appearance editing mode
+ return;
}
- virtual void httpFailure()
+ if (!gAgent.getRegion())
{
- LL_WARNS("Avatar") << "While attempting to increment the agent's cof we got an error "
- << dumpResponse() << LL_ENDL;
- F32 seconds_to_wait;
- mRetryPolicy->onFailure(getStatus(), getResponseHeaders());
- if (mRetryPolicy->shouldRetry(seconds_to_wait))
- {
- LL_INFOS() << "retrying" << LL_ENDL;
- doAfterInterval(boost::bind(&LLAppearanceMgr::incrementCofVersion,
- LLAppearanceMgr::getInstance(),
- LLHTTPClient::ResponderPtr(this)),
- seconds_to_wait);
- }
- else
- {
- LL_WARNS() << "giving up after too many retries" << LL_ENDL;
- }
+ LL_WARNS("Avatar") << "Region not set, cannot request server appearance update" << LL_ENDL;
+ return;
}
-
-private:
- LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
-};
-
-void LLAppearanceMgr::incrementCofVersion(LLHTTPClient::ResponderPtr responder_ptr)
-{
- // If we don't have a region, report it as an error
- if (gAgent.getRegion() == NULL)
+ if (gAgent.getRegion()->getCentralBakeVersion() == 0)
{
- LL_WARNS() << "Region not set, cannot request cof_version increment" << LL_ENDL;
- return;
+ LL_WARNS("Avatar") << "Region does not support baking" << LL_ENDL;
}
-
- std::string url = gAgent.getRegion()->getCapability("IncrementCofVersion");
+ std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance");
if (url.empty())
{
- LL_WARNS() << "No cap for IncrementCofVersion." << LL_ENDL;
+ LL_WARNS("Avatar") << "No cap for UpdateAvatarAppearance." << LL_ENDL;
return;
}
- LL_INFOS() << "Requesting cof_version be incremented via capability to: "
- << url << LL_ENDL;
- LLSD headers;
- LLSD body = LLSD::emptyMap();
-
- if (!responder_ptr.get())
+ LLSD postData;
+ S32 cof_version = LLAppearanceMgr::instance().getCOFVersion();
+ if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate"))
{
- responder_ptr = LLHTTPClient::ResponderPtr(new LLIncrementCofVersionResponder());
+ postData = LLAppearanceMgr::instance().dumpCOF();
}
+ else
+ {
+ postData["cof_version"] = cof_version;
+ if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
+ {
+ postData["cof_version"] = cof_version + 999;
+ }
+ }
+ LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << LL_ENDL;
+
+ LLAppearanceMgrHttpHandler * handler = new LLAppearanceMgrHttpHandler(this);
- LLHTTPClient::get(url, body, responder_ptr, headers, 30.0f);
+ mInFlightCounter++;
+ mInFlightTimer.setTimerExpirySec(60.0);
+
+ llassert(cof_version >= gAgentAvatarp->mLastUpdateRequestCOFVersion);
+ gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version;
+
+
+ LLCore::HttpHandle handle = gAgent.requestPostCapability("UpdateAvatarAppearance", url, postData, handler);
+
+ if (handle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ delete handler;
+ }
}
-U32 LLAppearanceMgr::getNumAttachmentsInCOF()
+bool LLAppearanceMgr::testCOFRequestVersion() const
{
- const LLUUID cof = getCOF();
- LLInventoryModel::item_array_t obj_items;
- getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT);
- return obj_items.size();
-}
+ // If we have already received an update for this or higher cof version, ignore.
+ S32 cof_version = getCOFVersion();
+ S32 last_rcv = gAgentAvatarp->mLastUpdateReceivedCOFVersion;
+ S32 last_req = gAgentAvatarp->mLastUpdateRequestCOFVersion;
+ LL_DEBUGS("Avatar") << "cof_version " << cof_version
+ << " last_rcv " << last_rcv
+ << " last_req " << last_req
+ << " in flight " << mInFlightCounter
+ << LL_ENDL;
+ if (cof_version < last_rcv)
+ {
+ LL_DEBUGS("Avatar") << "Have already received update for cof version " << last_rcv
+ << " will not request for " << cof_version << LL_ENDL;
+ return false;
+ }
+ if (/*mInFlightCounter > 0 &&*/ last_req >= cof_version)
+ {
+ LL_DEBUGS("Avatar") << "Request already in flight for cof version " << last_req
+ << " will not request for " << cof_version << LL_ENDL;
+ return false;
+ }
+
+ // Actually send the request.
+ LL_DEBUGS("Avatar") << "Will send request for cof_version " << cof_version << LL_ENDL;
+ return true;
+}
std::string LLAppearanceMgr::getAppearanceServiceURL() const
{
@@ -3850,15 +3745,17 @@ void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items,
}
}
+bool LLAppearanceMgr::mActive = true;
+
LLAppearanceMgr::LLAppearanceMgr():
mAttachmentInvLinkEnabled(false),
mOutfitIsDirty(false),
mOutfitLocked(false),
- mIsInUpdateAppearanceFromCOF(false),
- mAppearanceResponder(new RequestAgentUpdateAppearanceResponder)
+ mInFlightCounter(0),
+ mInFlightTimer(),
+ mIsInUpdateAppearanceFromCOF(false)
{
LLOutfitObserver& outfit_observer = LLOutfitObserver::instance();
-
// unlock outfit on save operation completed
outfit_observer.addCOFSavedCallback(boost::bind(
&LLAppearanceMgr::setOutfitLocked, this, false));
@@ -3866,11 +3763,12 @@ LLAppearanceMgr::LLAppearanceMgr():
mUnlockOutfitTimer.reset(new LLOutfitUnLockTimer(gSavedSettings.getS32(
"OutfitOperationsTimeout")));
- gIdleCallbacks.addFunction(&LLAttachmentsMgr::onIdle,NULL);
+ gIdleCallbacks.addFunction(&LLAttachmentsMgr::onIdle, NULL);
}
LLAppearanceMgr::~LLAppearanceMgr()
{
+ mActive = false;
}
void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val)
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 7742a19c07..760a0bc6ef 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -34,12 +34,10 @@
#include "llinventorymodel.h"
#include "llinventoryobserver.h"
#include "llviewerinventory.h"
-#include "llhttpclient.h"
class LLWearableHoldingPattern;
class LLInventoryCallback;
class LLOutfitUnLockTimer;
-class RequestAgentUpdateAppearanceResponder;
class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
{
@@ -54,7 +52,6 @@ public:
void updateAppearanceFromCOF(bool enforce_item_restrictions = true,
bool enforce_ordering = true,
nullary_func_t post_update_func = no_op);
- bool needToSaveCOF();
void updateCOF(const LLUUID& category, bool append = false);
void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append);
@@ -215,20 +212,20 @@ public:
void requestServerAppearanceUpdate();
- void incrementCofVersion(LLHTTPClient::ResponderPtr responder_ptr = NULL);
+ void setAppearanceServiceURL(const std::string& url) { mAppearanceServiceURL = url; }
+ std::string getAppearanceServiceURL() const;
- U32 getNumAttachmentsInCOF();
- // *HACK Remove this after server side texture baking is deployed on all sims.
- void incrementCofVersionLegacy();
+ bool testCOFRequestVersion() const;
+ void decrementInFlightCounter()
+ {
+ mInFlightCounter = llmax(mInFlightCounter - 1, 0);
+ }
- void setAppearanceServiceURL(const std::string& url) { mAppearanceServiceURL = url; }
- std::string getAppearanceServiceURL() const;
private:
std::string mAppearanceServiceURL;
-
protected:
LLAppearanceMgr();
~LLAppearanceMgr();
@@ -252,13 +249,14 @@ private:
bool mOutfitIsDirty;
bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls.
- LLPointer<RequestAgentUpdateAppearanceResponder> mAppearanceResponder;
-
/**
* Lock for blocking operations on outfit until server reply or timeout exceed
* to avoid unsynchronized outfit state or performing duplicate operations.
*/
bool mOutfitLocked;
+ S32 mInFlightCounter;
+ LLTimer mInFlightTimer;
+ static bool mActive;
std::auto_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer;
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/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
index 2d4ce6c883..530eb685fa 100755
--- a/indra/newview/llhttpretrypolicy.cpp
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -87,7 +87,7 @@ void LLAdaptiveRetryPolicy::onFailure(const LLCore::HttpResponse *response)
F32 retry_header_time;
const LLCore::HttpHeaders *headers = response->getHeaders();
bool has_retry_header_time = getRetryAfter(headers,retry_header_time);
- onFailureCommon(response->getStatus().mType, has_retry_header_time, retry_header_time);
+ onFailureCommon(response->getStatus().getType(), has_retry_header_time, retry_header_time);
}
void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time)
diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp
index a1f6a01aa0..8a726ec7c9 100755
--- a/indra/newview/llmaterialmgr.cpp
+++ b/indra/newview/llmaterialmgr.cpp
@@ -36,6 +36,9 @@
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llworld.h"
+#include "llhttpsdhandler.h"
+#include "httpcommon.h"
+#include "llcorehttputil.h"
/**
* Materials cap parameters
@@ -59,56 +62,51 @@
#define MATERIALS_PUT_THROTTLE_SECS 1.f
#define MATERIALS_PUT_MAX_ENTRIES 50
-/**
- * LLMaterialsResponder helper class
- */
-class LLMaterialsResponder : public LLHTTPClient::Responder
+
+class LLMaterialHttpHandler : public LLHttpSDHandler
{
-public:
- typedef boost::function<void (bool, const LLSD&)> CallbackFunction;
+public:
+ typedef boost::function<void(bool, const LLSD&)> CallbackFunction;
+ typedef boost::shared_ptr<LLMaterialHttpHandler> ptr_t;
+
+ LLMaterialHttpHandler(const std::string& method, CallbackFunction cback);
- LLMaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback);
- virtual ~LLMaterialsResponder();
+ virtual ~LLMaterialHttpHandler();
- virtual void httpSuccess();
- virtual void httpFailure();
+protected:
+ virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content);
+ virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status);
private:
std::string mMethod;
- std::string mCapabilityURL;
CallbackFunction mCallback;
};
-LLMaterialsResponder::LLMaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback)
- : LLHTTPClient::Responder()
- , mMethod(pMethod)
- , mCapabilityURL(pCapabilityURL)
- , mCallback(pCallback)
+LLMaterialHttpHandler::LLMaterialHttpHandler(const std::string& method, CallbackFunction cback):
+ LLHttpSDHandler(),
+ mMethod(method),
+ mCallback(cback)
{
+
}
-LLMaterialsResponder::~LLMaterialsResponder()
+LLMaterialHttpHandler::~LLMaterialHttpHandler()
{
}
-void LLMaterialsResponder::httpSuccess()
+void LLMaterialHttpHandler::onSuccess(LLCore::HttpResponse * response, const LLSD &content)
{
- const LLSD& pContent = getContent();
-
LL_DEBUGS("Materials") << LL_ENDL;
- mCallback(true, pContent);
+ mCallback(true, content);
}
-void LLMaterialsResponder::httpFailure()
+void LLMaterialHttpHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status)
{
- U32 pStatus = (U32) getStatus();
- const std::string& pReason = getReason();
-
LL_WARNS("Materials")
<< "\n--------------------------------------------------------------------------\n"
- << mMethod << " Error[" << pStatus << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME
- << "'\n with url '" << mCapabilityURL << "' because " << pReason
+ << mMethod << " Error[" << status.toULong() << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME
+ << "'\n with url '" << response->getRequestURL() << "' because " << status.toString()
<< "\n--------------------------------------------------------------------------"
<< LL_ENDL;
@@ -116,12 +114,35 @@ void LLMaterialsResponder::httpFailure()
mCallback(false, emptyResult);
}
+
+
/**
* LLMaterialMgr class
*/
-
-LLMaterialMgr::LLMaterialMgr()
+LLMaterialMgr::LLMaterialMgr():
+ mGetQueue(),
+ mGetPending(),
+ mGetCallbacks(),
+ mGetTECallbacks(),
+ mGetAllQueue(),
+ mGetAllRequested(),
+ mGetAllPending(),
+ mGetAllCallbacks(),
+ mPutQueue(),
+ mMaterials(),
+ mHttpRequest(),
+ mHttpHeaders(),
+ mHttpOptions(),
+ mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
+ mHttpPriority(0)
{
+ 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_MATERIALS);
+
mMaterials.insert(std::pair<LLMaterialID, LLMaterialPtr>(LLMaterialID::null, LLMaterialPtr(NULL)));
gIdleCallbacks.addFunction(&LLMaterialMgr::onIdle, NULL);
LLWorld::instance().setRegionRemovedCallback(boost::bind(&LLMaterialMgr::onRegionRemoved, this, _1));
@@ -554,6 +575,8 @@ void LLMaterialMgr::onIdle(void*)
{
instancep->processPutQueue();
}
+
+ instancep->mHttpRequest->update(0L);
}
void LLMaterialMgr::processGetQueue()
@@ -629,10 +652,26 @@ void LLMaterialMgr::processGetQueue()
LLSD postData = LLSD::emptyMap();
postData[MATERIALS_CAP_ZIP_FIELD] = materialBinary;
- LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("POST", capURL, boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id));
- LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '"<< capURL << " for " << materialsData.size() << " materials."
+ LLMaterialHttpHandler * handler =
+ new LLMaterialHttpHandler("POST",
+ boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id)
+ );
+
+ LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '" << capURL << " for " << materialsData.size() << " materials."
<< "\ndata: " << ll_pretty_print_sd(materialsData) << LL_ENDL;
- LLHTTPClient::post(capURL, postData, materialsResponder);
+
+ LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,
+ mHttpPolicy, mHttpPriority, capURL,
+ postData, mHttpOptions, mHttpHeaders, handler);
+
+ if (handle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ delete handler;
+ LLCore::HttpStatus status = mHttpRequest->getStatus();
+ LL_ERRS("Meterials") << "Failed to execute material POST. Status = " <<
+ status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL;
+ }
+
regionp->resetMaterialsCapThrottle();
}
}
@@ -667,8 +706,22 @@ void LLMaterialMgr::processGetAllQueue()
}
LL_DEBUGS("Materials") << "GET all for region " << region_id << "url " << capURL << LL_ENDL;
- LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("GET", capURL, boost::bind(&LLMaterialMgr::onGetAllResponse, this, _1, _2, *itRegion));
- LLHTTPClient::get(capURL, materialsResponder);
+ LLMaterialHttpHandler *handler =
+ new LLMaterialHttpHandler("GET",
+ boost::bind(&LLMaterialMgr::onGetAllResponse, this, _1, _2, *itRegion)
+ );
+
+ LLCore::HttpHandle handle = mHttpRequest->requestGet(mHttpPolicy, mHttpPriority, capURL,
+ mHttpOptions.get(), mHttpHeaders.get(), handler);
+
+ if (handle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ delete handler;
+ LLCore::HttpStatus status = mHttpRequest->getStatus();
+ LL_ERRS("Meterials") << "Failed to execute material GET. Status = " <<
+ status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL;
+ }
+
regionp->resetMaterialsCapThrottle();
mGetAllPending.insert(std::pair<LLUUID, F64>(region_id, LLFrameTimer::getTotalSeconds()));
mGetAllQueue.erase(itRegion); // Invalidates region_id
@@ -755,8 +808,24 @@ void LLMaterialMgr::processPutQueue()
putData[MATERIALS_CAP_ZIP_FIELD] = materialBinary;
LL_DEBUGS("Materials") << "put for " << itRequest->second.size() << " faces to region " << itRequest->first->getName() << LL_ENDL;
- LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("PUT", capURL, boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2));
- LLHTTPClient::put(capURL, putData, materialsResponder);
+
+ LLMaterialHttpHandler * handler =
+ new LLMaterialHttpHandler("PUT",
+ boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2)
+ );
+
+ LLCore::HttpHandle handle = LLCoreHttpUtil::requestPutWithLLSD(
+ mHttpRequest, mHttpPolicy, mHttpPriority, capURL,
+ putData, mHttpOptions, mHttpHeaders, handler);
+
+ if (handle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ delete handler;
+ LLCore::HttpStatus status = mHttpRequest->getStatus();
+ LL_ERRS("Meterials") << "Failed to execute material PUT. Status = " <<
+ status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL;
+ }
+
regionp->resetMaterialsCapThrottle();
}
else
diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h
index e83f1f4e01..ef202d24ba 100644
--- a/indra/newview/llmaterialmgr.h
+++ b/indra/newview/llmaterialmgr.h
@@ -30,6 +30,9 @@
#include "llmaterial.h"
#include "llmaterialid.h"
#include "llsingleton.h"
+#include "httprequest.h"
+#include "httpheaders.h"
+#include "httpoptions.h"
class LLViewerRegion;
@@ -56,7 +59,7 @@ public:
void put(const LLUUID& object_id, const U8 te, const LLMaterial& material);
void remove(const LLUUID& object_id, const U8 te);
-protected:
+private:
void clearGetQueues(const LLUUID& region_id);
bool isGetPending(const LLUUID& region_id, const LLMaterialID& material_id) const;
bool isGetAllPending(const LLUUID& region_id) const;
@@ -72,16 +75,7 @@ protected:
void onPutResponse(bool success, const LLSD& content);
void onRegionRemoved(LLViewerRegion* regionp);
-protected:
- typedef std::set<LLMaterialID> material_queue_t;
- typedef std::map<LLUUID, material_queue_t> get_queue_t;
- get_queue_t mGetQueue;
- typedef std::pair<const LLUUID, LLMaterialID> pending_material_t;
- typedef std::map<const pending_material_t, F64> get_pending_map_t;
- get_pending_map_t mGetPending;
- typedef std::map<LLMaterialID, get_callback_t*> get_callback_map_t;
- get_callback_map_t mGetCallbacks;
-
+private:
// struct for TE-specific material ID query
class TEMaterialPair
{
@@ -108,22 +102,37 @@ protected:
bool operator()(const TEMaterialPair& left, const TEMaterialPair& right) const { return left < right; }
};
- typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*, TEMaterialPairHasher> get_callback_te_map_t;
- get_callback_te_map_t mGetTECallbacks;
+ typedef std::set<LLMaterialID> material_queue_t;
+ typedef std::map<LLUUID, material_queue_t> get_queue_t;
+ typedef std::pair<const LLUUID, LLMaterialID> pending_material_t;
+ typedef std::map<const pending_material_t, F64> get_pending_map_t;
+ typedef std::map<LLMaterialID, get_callback_t*> get_callback_map_t;
+
+ typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*, TEMaterialPairHasher> get_callback_te_map_t;
typedef std::set<LLUUID> getall_queue_t;
- getall_queue_t mGetAllQueue;
- getall_queue_t mGetAllRequested;
typedef std::map<LLUUID, F64> getall_pending_map_t;
- getall_pending_map_t mGetAllPending;
typedef std::map<LLUUID, getall_callback_t*> getall_callback_map_t;
- getall_callback_map_t mGetAllCallbacks;
-
typedef std::map<U8, LLMaterial> facematerial_map_t;
typedef std::map<LLUUID, facematerial_map_t> put_queue_t;
- put_queue_t mPutQueue;
- material_map_t mMaterials;
+ get_queue_t mGetQueue;
+ get_pending_map_t mGetPending;
+ get_callback_map_t mGetCallbacks;
+
+ get_callback_te_map_t mGetTECallbacks;
+ getall_queue_t mGetAllQueue;
+ getall_queue_t mGetAllRequested;
+ getall_pending_map_t mGetAllPending;
+ getall_callback_map_t mGetAllCallbacks;
+ put_queue_t mPutQueue;
+ material_map_t mMaterials;
+
+ 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;
U32 getMaxEntries(const LLViewerRegion* regionp);
};
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 1e9945b514..f9160b6d60 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2362,7 +2362,6 @@ void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
if (!caps_url.empty())
{
gPendingMetricsUploads++;
- LLCurlRequest::headers_t headers;
LLHTTPClient::post(caps_url,
msg,
new ViewerAppearanceChangeMetricsResponder(report_sequence,
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index c12c2cc24c..702d0c3a29 100755
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -35,6 +35,11 @@
#include "llxmlrpclistener.h"
#include "llcurl.h"
+#include "httpcommon.h"
+#include "httprequest.h"
+#include "httpoptions.h"
+#include "httpheaders.h"
+#include "bufferarray.h"
#include "llviewercontrol.h"
// Have to include these last to avoid queue redefinition!
@@ -43,6 +48,13 @@
#include "llappviewer.h"
#include "lltrans.h"
+#include "boost/move/unique_ptr.hpp"
+
+namespace boost
+{
+ using ::boost::movelib::unique_ptr; // move unique_ptr into the boost namespace.
+}
+
// Static instance of LLXMLRPCListener declared here so that every time we
// bring in this code, we instantiate a listener. If we put the static
// instance of LLXMLRPCListener into llxmlrpclistener.cpp, the linker would
@@ -155,55 +167,158 @@ XMLRPC_VALUE LLXMLRPCValue::getValue() const
}
+class LLXMLRPCTransaction::Handler : public LLCore::HttpHandler
+{
+public:
+ Handler(LLCore::HttpRequest::ptr_t &request, LLXMLRPCTransaction::Impl *impl);
+ virtual ~Handler();
+
+ virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
+
+ typedef boost::unique_ptr<LLXMLRPCTransaction::Handler> ptr_t;
+
+private:
+
+ LLXMLRPCTransaction::Impl *mImpl;
+ LLCore::HttpRequest::ptr_t mRequest;
+};
+
class LLXMLRPCTransaction::Impl
{
public:
typedef LLXMLRPCTransaction::EStatus EStatus;
- LLCurlEasyRequest* mCurlRequest;
+ LLCore::HttpRequest::ptr_t mHttpRequest;
+
+
+ EStatus mStatus;
+ CURLcode mCurlCode;
+ std::string mStatusMessage;
+ std::string mStatusURI;
+ LLCore::HttpResponse::TransferStats::ptr_t mTransferStats;
+ Handler::ptr_t mHandler;
+ LLCore::HttpHandle mPostH;
- EStatus mStatus;
- CURLcode mCurlCode;
- std::string mStatusMessage;
- std::string mStatusURI;
- LLCurl::TransferInfo mTransferInfo;
-
std::string mURI;
- char* mRequestText;
- int mRequestTextSize;
-
+
std::string mProxyAddress;
std::string mResponseText;
XMLRPC_REQUEST mResponse;
std::string mCertStore;
LLPointer<LLCertificate> mErrorCert;
-
+
Impl(const std::string& uri, XMLRPC_REQUEST request, bool useGzip);
Impl(const std::string& uri,
- const std::string& method, LLXMLRPCValue params, bool useGzip);
+ const std::string& method, LLXMLRPCValue params, bool useGzip);
~Impl();
-
+
bool process();
-
- void setStatus(EStatus code,
- const std::string& message = "", const std::string& uri = "");
- void setCurlStatus(CURLcode);
+
+ void setStatus(EStatus code, const std::string& message = "", const std::string& uri = "");
+ void setHttpStatus(const LLCore::HttpStatus &status);
private:
void init(XMLRPC_REQUEST request, bool useGzip);
- static int _sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param);
- static CURLcode _sslCtxFunction(CURL * curl, void *sslctx, void *param);
- static size_t curlDownloadCallback(
- char* data, size_t size, size_t nmemb, void* user_data);
};
+LLXMLRPCTransaction::Handler::Handler(LLCore::HttpRequest::ptr_t &request,
+ LLXMLRPCTransaction::Impl *impl) :
+ mImpl(impl),
+ mRequest(request)
+{
+}
+
+LLXMLRPCTransaction::Handler::~Handler()
+{
+}
+
+void LLXMLRPCTransaction::Handler::onCompleted(LLCore::HttpHandle handle,
+ LLCore::HttpResponse * response)
+{
+ LLCore::HttpStatus status = response->getStatus();
+
+ if (!status)
+ {
+ if ((status.toULong() != CURLE_SSL_PEER_CERTIFICATE) &&
+ (status.toULong() != CURLE_SSL_CACERT))
+ {
+ // if we have a curl error that's not already been handled
+ // (a non cert error), then generate the error message as
+ // appropriate
+ mImpl->setHttpStatus(status);
+ LLCertificate *errordata = static_cast<LLCertificate *>(status.getErrorData());
+
+ if (errordata)
+ {
+ mImpl->mErrorCert = LLPointer<LLCertificate>(errordata);
+ status.setErrorData(NULL);
+ errordata->unref();
+ }
+
+ LL_WARNS() << "LLXMLRPCTransaction error "
+ << status.toHex() << ": " << status.toString() << LL_ENDL;
+ LL_WARNS() << "LLXMLRPCTransaction request URI: "
+ << mImpl->mURI << LL_ENDL;
+ }
+
+ return;
+ }
+
+ mImpl->setStatus(LLXMLRPCTransaction::StatusComplete);
+ mImpl->mTransferStats = response->getTransferStats();
+
+ // the contents of a buffer array are potentially noncontiguous, so we
+ // will need to copy them into an contiguous block of memory for XMLRPC.
+ LLCore::BufferArray *body = response->getBody();
+ char * bodydata = new char[body->size()];
+
+ body->read(0, bodydata, body->size());
+
+ mImpl->mResponse = XMLRPC_REQUEST_FromXML(bodydata, body->size(), 0);
+
+ delete[] bodydata;
+
+ bool hasError = false;
+ bool hasFault = false;
+ int faultCode = 0;
+ std::string faultString;
+
+ LLXMLRPCValue error(XMLRPC_RequestGetError(mImpl->mResponse));
+ if (error.isValid())
+ {
+ hasError = true;
+ faultCode = error["faultCode"].asInt();
+ faultString = error["faultString"].asString();
+ }
+ else if (XMLRPC_ResponseIsFault(mImpl->mResponse))
+ {
+ hasFault = true;
+ faultCode = XMLRPC_GetResponseFaultCode(mImpl->mResponse);
+ faultString = XMLRPC_GetResponseFaultString(mImpl->mResponse);
+ }
+
+ if (hasError || hasFault)
+ {
+ mImpl->setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
+
+ LL_WARNS() << "LLXMLRPCTransaction XMLRPC "
+ << (hasError ? "error " : "fault ")
+ << faultCode << ": "
+ << faultString << LL_ENDL;
+ LL_WARNS() << "LLXMLRPCTransaction request URI: "
+ << mImpl->mURI << LL_ENDL;
+ }
+
+}
+
+//=========================================================================
+
LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
XMLRPC_REQUEST request, bool useGzip)
- : mCurlRequest(0),
+ : mHttpRequest(),
mStatus(LLXMLRPCTransaction::StatusNotStarted),
mURI(uri),
- mRequestText(0),
mResponse(0)
{
init(request, useGzip);
@@ -212,10 +327,9 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
const std::string& method, LLXMLRPCValue params, bool useGzip)
- : mCurlRequest(0),
+ : mHttpRequest(),
mStatus(LLXMLRPCTransaction::StatusNotStarted),
mURI(uri),
- mRequestText(0),
mResponse(0)
{
XMLRPC_REQUEST request = XMLRPC_RequestNew();
@@ -231,127 +345,53 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
XMLRPC_RequestFree(request, 1);
}
-// _sslCertVerifyCallback
-// callback called when a cert verification is requested.
-// calls SECAPI to validate the context
-int LLXMLRPCTransaction::Impl::_sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param)
+void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
{
- LLXMLRPCTransaction::Impl *transaction = (LLXMLRPCTransaction::Impl *)param;
- LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore(transaction->mCertStore);
- LLPointer<LLCertificateChain> chain = gSecAPIHandler->getCertificateChain(ctx);
- LLSD validation_params = LLSD::emptyMap();
- LLURI uri(transaction->mURI);
- validation_params[CERT_HOSTNAME] = uri.hostName();
- try
- {
- // don't validate hostname. Let libcurl do it instead. That way, it'll handle redirects
- store->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), chain, validation_params);
- }
- catch (LLCertValidationTrustException& cert_exception)
- {
- // this exception is is handled differently than the general cert
- // exceptions, as we allow the user to actually add the certificate
- // for trust.
- // therefore we pass back a different error code
- // NOTE: We're currently 'wired' to pass around CURL error codes. This is
- // somewhat clumsy, as we may run into errors that do not map directly to curl
- // error codes. Should be refactored with login refactoring, perhaps.
- transaction->mCurlCode = CURLE_SSL_CACERT;
- // set the status directly. set curl status generates error messages and we want
- // to use the fixed ones from the exceptions
- transaction->setStatus(StatusCURLError, cert_exception.getMessage(), std::string());
- // We should probably have a more generic way of passing information
- // back to the error handlers.
- transaction->mErrorCert = cert_exception.getCert();
- return 0;
- }
- catch (LLCertException& cert_exception)
- {
- transaction->mCurlCode = CURLE_SSL_PEER_CERTIFICATE;
- // set the status directly. set curl status generates error messages and we want
- // to use the fixed ones from the exceptions
- transaction->setStatus(StatusCURLError, cert_exception.getMessage(), std::string());
- transaction->mErrorCert = cert_exception.getCert();
- return 0;
- }
- catch (...)
- {
- // any other odd error, we just handle as a connect error.
- transaction->mCurlCode = CURLE_SSL_CONNECT_ERROR;
- transaction->setCurlStatus(CURLE_SSL_CONNECT_ERROR);
- return 0;
- }
- return 1;
-}
+ LLCore::HttpOptions::ptr_t httpOpts;
+ LLCore::HttpHeaders::ptr_t httpHeaders;
-// _sslCtxFunction
-// Callback function called when an SSL Context is created via CURL
-// used to configure the context for custom cert validate(<, <#const & xs#>, <#T * #>, <#long #>)tion
-// based on SECAPI
-
-CURLcode LLXMLRPCTransaction::Impl::_sslCtxFunction(CURL * curl, void *sslctx, void *param)
-{
- SSL_CTX * ctx = (SSL_CTX *) sslctx;
- // disable any default verification for server certs
- SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
- // set the verification callback.
- SSL_CTX_set_cert_verify_callback(ctx, _sslCertVerifyCallback, param);
- // the calls are void
- return CURLE_OK;
-
-}
-void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
-{
- if (!mCurlRequest)
+ if (!mHttpRequest)
{
- mCurlRequest = new LLCurlEasyRequest();
+ mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest);
}
- if(!mCurlRequest->isValid())
- {
- LL_WARNS() << "mCurlRequest is invalid." << LL_ENDL ;
- delete mCurlRequest ;
- mCurlRequest = NULL ;
- return ;
- }
+ // LLRefCounted starts with a 1 ref, so don't add a ref in the smart pointer
+ httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false);
- mErrorCert = NULL;
+ httpOpts->setTimeout(40L);
-// mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // useful for debugging
- mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
- mCurlRequest->setWriteCallback(&curlDownloadCallback, (void*)this);
- BOOL vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert");
+ bool vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert");
mCertStore = gSavedSettings.getString("CertStore");
- mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, vefifySSLCert);
- mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, vefifySSLCert ? 2 : 0);
- // Be a little impatient about establishing connections.
- mCurlRequest->setopt(CURLOPT_CONNECTTIMEOUT, 40L);
- mCurlRequest->setSSLCtxCallback(_sslCtxFunction, (void *)this);
- /* Setting the DNS cache timeout to -1 disables it completely.
- This might help with bug #503 */
- mCurlRequest->setopt(CURLOPT_DNS_CACHE_TIMEOUT, -1);
+ httpOpts->setSSLVerifyPeer( vefifySSLCert );
+ httpOpts->setSSLVerifyHost( vefifySSLCert ? 2 : 0);
- mCurlRequest->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
+ // LLRefCounted starts with a 1 ref, so don't add a ref in the smart pointer
+ httpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false);
- if (useGzip)
- {
- mCurlRequest->setoptString(CURLOPT_ENCODING, "");
- }
+ httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
+
+ ///* Setting the DNS cache timeout to -1 disables it completely.
+ //This might help with bug #503 */
+ //httpOpts->setDNSCacheTimeout(-1);
+
+ LLCore::BufferArray::ptr_t body = LLCore::BufferArray::ptr_t(new LLCore::BufferArray(), false);
+
+ // TODO: See if there is a way to serialize to a preallocated buffer I'm
+ // not fond of the copy here.
+ int requestSize(0);
+ char * requestText = XMLRPC_REQUEST_ToXML(request, &requestSize);
+
+ body->append(requestText, requestSize);
- mRequestText = XMLRPC_REQUEST_ToXML(request, &mRequestTextSize);
- if (mRequestText)
- {
- mCurlRequest->setoptString(CURLOPT_POSTFIELDS, mRequestText);
- mCurlRequest->setopt(CURLOPT_POSTFIELDSIZE, mRequestTextSize);
- }
- else
- {
- setStatus(StatusOtherError);
- }
+ XMLRPC_Free(requestText);
+
+ mHandler = LLXMLRPCTransaction::Handler::ptr_t(new Handler( mHttpRequest, this ));
+
+ mPostH = mHttpRequest->requestPost(LLCore::HttpRequest::DEFAULT_POLICY_ID, 0,
+ mURI, body.get(), httpOpts.get(), httpHeaders.get(), mHandler.get());
- mCurlRequest->sendRequest(mURI);
}
@@ -361,28 +401,17 @@ LLXMLRPCTransaction::Impl::~Impl()
{
XMLRPC_RequestFree(mResponse, 1);
}
-
- if (mRequestText)
- {
- XMLRPC_Free(mRequestText);
- }
-
- delete mCurlRequest;
- mCurlRequest = NULL ;
}
bool LLXMLRPCTransaction::Impl::process()
{
- if(!mCurlRequest || !mCurlRequest->isValid())
+ if (!mPostH || !mHttpRequest)
{
- LL_WARNS() << "transaction failed." << LL_ENDL ;
-
- delete mCurlRequest ;
- mCurlRequest = NULL ;
- return true ; //failed, quit.
+ LL_WARNS() << "transaction failed." << LL_ENDL;
+ return true; //failed, quit.
}
- switch(mStatus)
+ switch (mStatus)
{
case LLXMLRPCTransaction::StatusComplete:
case LLXMLRPCTransaction::StatusCURLError:
@@ -391,93 +420,25 @@ bool LLXMLRPCTransaction::Impl::process()
{
return true;
}
-
+
case LLXMLRPCTransaction::StatusNotStarted:
{
setStatus(LLXMLRPCTransaction::StatusStarted);
break;
}
-
+
default:
- {
- // continue onward
- }
- }
-
- if(!mCurlRequest->wait())
- {
- return false ;
+ break;
}
- while(1)
- {
- CURLcode result;
- bool newmsg = mCurlRequest->getResult(&result, &mTransferInfo);
- if (newmsg)
- {
- if (result != CURLE_OK)
- {
- if ((result != CURLE_SSL_PEER_CERTIFICATE) &&
- (result != CURLE_SSL_CACERT))
- {
- // if we have a curl error that's not already been handled
- // (a non cert error), then generate the error message as
- // appropriate
- setCurlStatus(result);
-
- LL_WARNS() << "LLXMLRPCTransaction CURL error "
- << mCurlCode << ": " << mCurlRequest->getErrorString() << LL_ENDL;
- LL_WARNS() << "LLXMLRPCTransaction request URI: "
- << mURI << LL_ENDL;
- }
-
- return true;
- }
-
- setStatus(LLXMLRPCTransaction::StatusComplete);
+ LLCore::HttpStatus status = mHttpRequest->update(0);
- mResponse = XMLRPC_REQUEST_FromXML(
- mResponseText.data(), mResponseText.size(), NULL);
-
- bool hasError = false;
- bool hasFault = false;
- int faultCode = 0;
- std::string faultString;
-
- LLXMLRPCValue error(XMLRPC_RequestGetError(mResponse));
- if (error.isValid())
- {
- hasError = true;
- faultCode = error["faultCode"].asInt();
- faultString = error["faultString"].asString();
- }
- else if (XMLRPC_ResponseIsFault(mResponse))
- {
- hasFault = true;
- faultCode = XMLRPC_GetResponseFaultCode(mResponse);
- faultString = XMLRPC_GetResponseFaultString(mResponse);
- }
-
- if (hasError || hasFault)
- {
- setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
-
- LL_WARNS() << "LLXMLRPCTransaction XMLRPC "
- << (hasError ? "error " : "fault ")
- << faultCode << ": "
- << faultString << LL_ENDL;
- LL_WARNS() << "LLXMLRPCTransaction request URI: "
- << mURI << LL_ENDL;
- }
-
- return true;
- }
- else
- {
- break; // done
- }
+ status = mHttpRequest->getStatus();
+ if (!status)
+ {
+ return false;
}
-
+
return false;
}
@@ -516,64 +477,51 @@ void LLXMLRPCTransaction::Impl::setStatus(EStatus status,
}
}
-void LLXMLRPCTransaction::Impl::setCurlStatus(CURLcode code)
+void LLXMLRPCTransaction::Impl::setHttpStatus(const LLCore::HttpStatus &status)
{
+ CURLcode code = static_cast<CURLcode>(status.toULong());
std::string message;
std::string uri = "http://secondlife.com/community/support.php";
-
+ LLURI failuri(mURI);
+
+
switch (code)
{
- case CURLE_COULDNT_RESOLVE_HOST:
- message =
- "DNS could not resolve the host name.\n"
- "Please verify that you can connect to the www.secondlife.com\n"
- "web site. If you can, but continue to receive this error,\n"
- "please go to the support section and report this problem.";
- break;
-
- case CURLE_SSL_PEER_CERTIFICATE:
- message =
- "The login server couldn't verify itself via SSL.\n"
- "If you continue to receive this error, please go\n"
- "to the Support section of the SecondLife.com web site\n"
- "and report the problem.";
- break;
-
- case CURLE_SSL_CACERT:
- case CURLE_SSL_CONNECT_ERROR:
- message =
- "Often this means that your computer\'s clock is set incorrectly.\n"
- "Please go to Control Panels and make sure the time and date\n"
- "are set correctly.\n"
- "Also check that your network and firewall are set up correctly.\n"
- "If you continue to receive this error, please go\n"
- "to the Support section of the SecondLife.com web site\n"
- "and report the problem.";
- break;
-
- default:
- break;
+ case CURLE_COULDNT_RESOLVE_HOST:
+ message =
+ std::string("DNS could not resolve the host name(") + failuri.hostName() + ").\n"
+ "Please verify that you can connect to the www.secondlife.com\n"
+ "web site. If you can, but continue to receive this error,\n"
+ "please go to the support section and report this problem.";
+ break;
+
+ case CURLE_SSL_PEER_CERTIFICATE:
+ message =
+ "The login server couldn't verify itself via SSL.\n"
+ "If you continue to receive this error, please go\n"
+ "to the Support section of the SecondLife.com web site\n"
+ "and report the problem.";
+ break;
+
+ case CURLE_SSL_CACERT:
+ case CURLE_SSL_CONNECT_ERROR:
+ message =
+ "Often this means that your computer\'s clock is set incorrectly.\n"
+ "Please go to Control Panels and make sure the time and date\n"
+ "are set correctly.\n"
+ "Also check that your network and firewall are set up correctly.\n"
+ "If you continue to receive this error, please go\n"
+ "to the Support section of the SecondLife.com web site\n"
+ "and report the problem.";
+ break;
+
+ default:
+ break;
}
-
+
mCurlCode = code;
setStatus(StatusCURLError, message, uri);
-}
-
-size_t LLXMLRPCTransaction::Impl::curlDownloadCallback(
- char* data, size_t size, size_t nmemb, void* user_data)
-{
- Impl& impl(*(Impl*)user_data);
-
- size_t n = size * nmemb;
- impl.mResponseText.append(data, n);
-
- if (impl.mStatus == LLXMLRPCTransaction::StatusStarted)
- {
- impl.setStatus(LLXMLRPCTransaction::StatusDownloading);
- }
-
- return n;
}
@@ -645,11 +593,11 @@ F64 LLXMLRPCTransaction::transferRate()
return 0.0L;
}
- double rate_bits_per_sec = impl.mTransferInfo.mSpeedDownload * 8.0;
+ double rate_bits_per_sec = impl.mTransferStats->mSpeedDownload * 8.0;
LL_INFOS("AppInit") << "Buffer size: " << impl.mResponseText.size() << " B" << LL_ENDL;
- LL_DEBUGS("AppInit") << "Transfer size: " << impl.mTransferInfo.mSizeDownload << " B" << LL_ENDL;
- LL_DEBUGS("AppInit") << "Transfer time: " << impl.mTransferInfo.mTotalTime << " s" << LL_ENDL;
+ LL_DEBUGS("AppInit") << "Transfer size: " << impl.mTransferStats->mSizeDownload << " B" << LL_ENDL;
+ LL_DEBUGS("AppInit") << "Transfer time: " << impl.mTransferStats->mTotalTime << " s" << LL_ENDL;
LL_INFOS("AppInit") << "Transfer rate: " << rate_bits_per_sec / 1000.0 << " Kb/s" << LL_ENDL;
return rate_bits_per_sec;
diff --git a/indra/newview/llxmlrpctransaction.h b/indra/newview/llxmlrpctransaction.h
index f2589c7f41..3a1c9c82b7 100755
--- a/indra/newview/llxmlrpctransaction.h
+++ b/indra/newview/llxmlrpctransaction.h
@@ -81,7 +81,7 @@ private:
class LLXMLRPCTransaction
- // an asynchronous request and respones via XML-RPC
+ // an asynchronous request and responses via XML-RPC
{
public:
LLXMLRPCTransaction(const std::string& uri,
@@ -127,7 +127,9 @@ public:
// only valid if StsatusComplete, otherwise 0.0
private:
+ class Handler;
class Impl;
+
Impl& impl;
};