diff options
Diffstat (limited to 'indra/newview')
| -rwxr-xr-x | indra/newview/CMakeLists.txt | 14 | ||||
| -rwxr-xr-x | indra/newview/llaccountingcostmanager.cpp | 284 | ||||
| -rwxr-xr-x | indra/newview/llaccountingcostmanager.h | 15 | ||||
| -rwxr-xr-x | indra/newview/llagent.cpp | 197 | ||||
| -rwxr-xr-x | indra/newview/llagent.h | 31 | ||||
| -rwxr-xr-x | indra/newview/llagentlanguage.cpp | 8 | ||||
| -rwxr-xr-x | indra/newview/llappcorehttp.cpp | 81 | ||||
| -rwxr-xr-x | indra/newview/llappcorehttp.h | 28 | ||||
| -rwxr-xr-x | indra/newview/llappearancemgr.cpp | 586 | ||||
| -rwxr-xr-x | indra/newview/llappearancemgr.h | 22 | ||||
| -rw-r--r-- | indra/newview/llavatarrenderinfoaccountant.cpp | 131 | ||||
| -rw-r--r-- | indra/newview/llavatarrenderinfoaccountant.h | 10 | ||||
| -rwxr-xr-x | indra/newview/llhttpretrypolicy.cpp | 2 | ||||
| -rwxr-xr-x | indra/newview/llmaterialmgr.cpp | 141 | ||||
| -rw-r--r-- | indra/newview/llmaterialmgr.h | 49 | ||||
| -rwxr-xr-x | indra/newview/llvoavatarself.cpp | 1 | ||||
| -rwxr-xr-x | indra/newview/llxmlrpctransaction.cpp | 500 | ||||
| -rwxr-xr-x | indra/newview/llxmlrpctransaction.h | 4 | 
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;  }; | 
