diff options
| -rwxr-xr-x | indra/llcommon/llerror.h | 1 | ||||
| -rw-r--r-- | indra/llmessage/llcorehttputil.cpp | 11 | ||||
| -rwxr-xr-x | indra/newview/lleventpoll.cpp | 47 | ||||
| -rwxr-xr-x | indra/newview/llwlhandlers.cpp | 215 | ||||
| -rwxr-xr-x | indra/newview/llwlhandlers.h | 20 | 
5 files changed, 168 insertions, 126 deletions
| diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 63040e1772..b1b5e9be7d 100755 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -354,6 +354,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;  #define LL_WARNS(...)	lllog(LLError::LEVEL_WARN, false, ##__VA_ARGS__)  #define LL_ERRS(...)	lllog(LLError::LEVEL_ERROR, false, ##__VA_ARGS__)  // alternative to llassert_always that prints explanatory message +#define LL_WARNS_IF(exp, ...)	if (exp) LL_WARNS(##__VA_ARGS__) << "(" #exp ")"  #define LL_ERRS_IF(exp, ...)	if (exp) LL_ERRS(##__VA_ARGS__) << "(" #exp ")"  // Only print the log message once (good for warnings or infos that would otherwise diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index dd9cb2032a..a32c4cad22 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -241,12 +241,19 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons          }          if (result.isUndefined()) -        { -            // If we've gotten to this point and the result LLSD is still undefined  +        {   // If we've gotten to this point and the result LLSD is still undefined               // either there was an issue deserializing the body or the response was              // blank.  Create an empty map to hold the result either way.              result = LLSD::emptyMap();          } +        else if (!result.isMap()) +        {   // The results are not themselves a map.  Move them down so that  +            // this method can return a map to the caller. +            // *TODO: Should it always do this? +            LLSD newResult = LLSD::emptyMap(); +            newResult["content"] = result; +            result = newResult; +        }      }      buildStatusEntry(response, status, result); diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index a35140a6a7..25504e7cbf 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -59,11 +59,11 @@ namespace Details          // We will wait RETRY_SECONDS + (errorCount * RETRY_SECONDS_INC) before retrying after an error.          // This means we attempt to recover relatively quickly but back off giving more time to recover          // until we finally give up after MAX_EVENT_POLL_HTTP_ERRORS attempts. -        static const F32    EVENT_POLL_ERROR_RETRY_SECONDS; -        static const F32    EVENT_POLL_ERROR_RETRY_SECONDS_INC; -        static const S32    MAX_EVENT_POLL_HTTP_ERRORS; +        static const F32                EVENT_POLL_ERROR_RETRY_SECONDS; +        static const F32                EVENT_POLL_ERROR_RETRY_SECONDS_INC; +        static const S32                MAX_EVENT_POLL_HTTP_ERRORS; -        void eventPollCoro(LLCoros::self& self, std::string url); +        void                            eventPollCoro(LLCoros::self& self, std::string url);          void                            handleMessage(const LLSD &content); @@ -138,11 +138,14 @@ namespace Details          LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EventPoller", mHttpPolicy));          LLSD acknowledge;          int errorCount = 0; -        int counter = mCounter; // saved on the stack for debugging. +        int counter = mCounter; // saved on the stack for logging.           LL_INFOS("LLEventPollImpl") << " <" << counter << "> entering coroutine." << LL_ENDL;          mAdapter = httpAdapter; + +        // continually poll for a server update until we've been flagged as  +        // finished           while (!mDone)          {              LLSD request; @@ -158,23 +161,23 @@ namespace Details  //          LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = "  //              << LLSDXMLStreamer(result) << LL_ENDL; -            LLSD httpResults; -            httpResults = result["http_result"]; +            LLSD httpResults = result["http_result"];              LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults);              if (!status)              { -                  if (status == LLCore::HttpStatus(HTTP_BAD_GATEWAY)) -                { -                    // A HTTP_BAD_GATEWAY (502) error is our standard timeout response +                {   // A HTTP_BAD_GATEWAY (502) error is our standard timeout response                      // we get this when there are no events.                      errorCount = 0;                      continue;                  }                  else if ((status == LLCore::HttpStatus(LLCore::HttpStatus::LLCORE, LLCore::HE_OP_CANCELED)) ||                           (status == LLCore::HttpStatus(HTTP_NOT_FOUND))) -                {    +                {   // Event polling for this server has been canceled.  In  +                    // some cases the server gets ahead of the viewer and will  +                    // return a 404 error (Not Found) before the cancel event +                    // comes back in the queue                      LL_WARNS() << "Canceling coroutine" << LL_ENDL;                      break;                  } @@ -182,7 +185,11 @@ namespace Details                      << status.toTerseString() << ": '" << httpResults["message"] << "'" << LL_ENDL;                  if (errorCount < MAX_EVENT_POLL_HTTP_ERRORS) -                { +                {   // An unanticipated error has been received from our poll  +                    // request. Calculate a timeout and wait for it to expire(sleep) +                    // before trying again.  The sleep time is increased by 5 seconds +                    // for each consecutive error. +                    LLEventTimeout timeout;                      ++errorCount;                      F32 waitToRetry = EVENT_POLL_ERROR_RETRY_SECONDS @@ -191,15 +198,12 @@ namespace Details                      LL_WARNS("LLEventPollImpl") << "<" << counter << "> Retrying in " << waitToRetry <<                          " seconds, error count is now " << errorCount << LL_ENDL; -                    { -                        LLEventTimeout timeout; -                        timeout.eventAfter(waitToRetry, LLSD()); -                        waitForEventOn(self, timeout); -                    } +                    timeout.eventAfter(waitToRetry, LLSD()); +                    waitForEventOn(self, timeout); +                                          if (mDone)                          break;                      LL_INFOS("LLEventPollImpl") << "<" << counter << "> About to retry request." << LL_ENDL; -                      continue;                  }                  else @@ -208,7 +212,6 @@ namespace Details                      // IMs, teleports, about land, selecting land, region crossing and more will all fail.                      // They are essentially disconnected from the region even though some things may still work.                      // Since things won't get better until they relog we force a disconnect now. -                      mDone = true;                      // *NOTE:Mani - The following condition check to see if this failing event poll @@ -237,10 +240,7 @@ namespace Details              acknowledge = result["id"];              LLSD events = result["events"]; -            if (acknowledge.isUndefined()) -            { -                LL_WARNS("LLEventPollImpl") << " id undefined" << LL_ENDL; -            } +            LL_WARNS_IF((acknowledge.isUndefined()), "LLEventPollImpl") << " id undefined" << LL_ENDL;              // was LL_INFOS() but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG              LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> " << events.size() << "events (id " << LLSDXMLStreamer(acknowledge) << ")" << LL_ENDL; @@ -256,7 +256,6 @@ namespace Details              }          }          LL_INFOS("LLEventPollImpl") << " <" << counter << "> Leaving coroutine." << LL_ENDL; -      }  } diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp index 3bedfbe502..c05486b173 100755 --- a/indra/newview/llwlhandlers.cpp +++ b/indra/newview/llwlhandlers.cpp @@ -32,6 +32,7 @@  #include "llviewerregion.h"  #include "llenvmanager.h"  #include "llnotificationsutil.h" +#include "llcorehttputil.h"  /****   * LLEnvironmentRequest @@ -81,55 +82,62 @@ bool LLEnvironmentRequest::doRequest()  		return false;  	} -	LL_INFOS("WindlightCaps") << "Requesting region windlight settings via " << url << LL_ENDL; -	LLHTTPClient::get(url, new LLEnvironmentRequestResponder()); -	return true; -} - -/**** - * LLEnvironmentRequestResponder - ****/ -int LLEnvironmentRequestResponder::sCount = 0; // init to 0 +    std::string coroname = +        LLCoros::instance().launch("LLEnvironmentRequest::environmentRequestCoro", +        boost::bind(&LLEnvironmentRequest::environmentRequestCoro, _1, url)); -LLEnvironmentRequestResponder::LLEnvironmentRequestResponder() -{ -	mID = ++sCount; +    LL_INFOS("WindlightCaps") << "Requesting region windlight settings via " << url << LL_ENDL; +    return true;  } -/*virtual*/ void LLEnvironmentRequestResponder::httpSuccess() -{ -	const LLSD& unvalidated_content = getContent(); -	LL_INFOS("WindlightCaps") << "Received region windlight settings" << LL_ENDL; -	if (mID != sCount) -	{ -		LL_INFOS("WindlightCaps") << "Got superseded by another responder; ignoring..." << LL_ENDL; -		return; -	} - -	LLUUID regionId; -	if( gAgent.getRegion() ) -	{ -		regionId = gAgent.getRegion()->getRegionID(); -	} -	 -	if (unvalidated_content[0]["regionID"].asUUID() != regionId ) -	{ -		LL_WARNS("WindlightCaps") << "Not in the region from where this data was received (wanting " -			<< regionId << " but got " << unvalidated_content[0]["regionID"].asUUID() -			<< ") - ignoring..." << LL_ENDL; -		return; -	} +S32 LLEnvironmentRequest::sLastRequest = 0; -	LLEnvManagerNew::getInstance()->onRegionSettingsResponse(unvalidated_content); -} -/*virtual*/ -void LLEnvironmentRequestResponder::httpFailure() +//static  +void LLEnvironmentRequest::environmentRequestCoro(LLCoros::self& self, std::string url)  { -	LL_WARNS("WindlightCaps") << "Got an error, not using region windlight... " -			<< dumpResponse() << LL_ENDL; -	LLEnvManagerNew::getInstance()->onRegionSettingsResponse(LLSD()); +    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); +    S32 requestId = ++LLEnvironmentRequest::sLastRequest; +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t  +            httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EnvironmentRequest", httpPolicy)); +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + +    LLSD result = httpAdapter->getAndYield(self, httpRequest, url); + +    if (requestId != LLEnvironmentRequest::sLastRequest) +    { +        LL_INFOS("WindlightCaps") << "Got superseded by another responder; ignoring..." << LL_ENDL; +        return; +    } + +    LLSD httpResults = result["http_result"]; +    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults); +    if (!status) +    { +        LL_WARNS("WindlightCaps") << "Got an error, not using region windlight... " << LL_ENDL; +        LLEnvManagerNew::getInstance()->onRegionSettingsResponse(LLSD()); +        return; +    } +    result = result["content"]; +    LL_INFOS("WindlightCaps") << "Received region windlight settings" << LL_ENDL; + +    LLUUID regionId; +    if (gAgent.getRegion()) +    { +        regionId = gAgent.getRegion()->getRegionID(); +    } + +    if (result[0]["regionID"].asUUID() != regionId) +    { +        LL_WARNS("WindlightCaps") << "Not in the region from where this data was received (wanting " +            << regionId << " but got " << result[0]["regionID"].asUUID() +            << ") - ignoring..." << LL_ENDL; +        return; +    } + +    LLEnvManagerNew::getInstance()->onRegionSettingsResponse(result);  } +  /****   * LLEnvironmentApply   ****/ @@ -161,53 +169,86 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content)  		return false;  	} -	LL_INFOS("WindlightCaps") << "Sending windlight settings to " << url << LL_ENDL; -	LL_DEBUGS("WindlightCaps") << "content: " << content << LL_ENDL; -	LLHTTPClient::post(url, content, new LLEnvironmentApplyResponder()); +    LL_INFOS("WindlightCaps") << "Sending windlight settings to " << url << LL_ENDL; +    LL_DEBUGS("WindlightCaps") << "content: " << content << LL_ENDL; + +    std::string coroname = +        LLCoros::instance().launch("LLEnvironmentApply::environmentApplyCoro", +        boost::bind(&LLEnvironmentApply::environmentApplyCoro, _1, url, content));  	return true;  } -/**** - * LLEnvironmentApplyResponder - ****/ -/*virtual*/ void LLEnvironmentApplyResponder::httpSuccess() -{ -	const LLSD& content = getContent(); -	if (!content.isMap() || !content.has("regionID")) -	{ -		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); -		return; -	} -	if (content["regionID"].asUUID() != gAgent.getRegion()->getRegionID()) -	{ -		LL_WARNS("WindlightCaps") << "No longer in the region where data was sent (currently " -			<< gAgent.getRegion()->getRegionID() << ", reply is from " << content["regionID"].asUUID() -			<< "); ignoring..." << LL_ENDL; -		return; -	} -	else if (content["success"].asBoolean()) -	{ -		LL_DEBUGS("WindlightCaps") << "Success in applying windlight settings to region " << content["regionID"].asUUID() << LL_ENDL; -		LLEnvManagerNew::instance().onRegionSettingsApplyResponse(true); -	} -	else -	{ -		LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings!  " << dumpResponse() << LL_ENDL; -		LLSD args(LLSD::emptyMap()); -		args["FAIL_REASON"] = content["fail_reason"].asString(); -		LLNotificationsUtil::add("WLRegionApplyFail", args); -		LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false); -	} -} -/*virtual*/ -void LLEnvironmentApplyResponder::httpFailure() +void LLEnvironmentApply::environmentApplyCoro(LLCoros::self& self, std::string url, LLSD content)  { -	LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! " -		<< dumpResponse() << LL_ENDL; - -	LLSD args(LLSD::emptyMap()); -	std::stringstream msg; -	msg << getReason() << " (Code " << getStatus() << ")"; -	args["FAIL_REASON"] = msg.str(); -	LLNotificationsUtil::add("WLRegionApplyFail", args); +    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t +        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EnvironmentApply", httpPolicy)); +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + +    LLSD result = httpAdapter->postAndYield(self, httpRequest, url, content); + +    LLSD notify; // for error reporting.  If there is something to report to user this will be defined. +    /* +     * Expecting reply from sim in form of: +     * { +     *   regionID : uuid, +     *   messageID: uuid, +     *   success : true +     * } +     * or +     * { +     *   regionID : uuid, +     *   success : false, +     *   fail_reason : string +     * } +     */ + +    do // while false.   +    {  // Breaks from loop in the case of an error. + +        LLSD httpResults = result["http_result"]; +        LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults); +        if (!status) +        { +            LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! " << LL_ENDL; + +            std::stringstream msg; +            msg << status.toString() << " (Code " << status.toTerseString() << ")"; +            notify = LLSD::emptyMap(); +            notify["FAIL_REASON"] = msg.str(); +            break; +        } + +        if (!result.has("regionID")) +        { +            notify = LLSD::emptyMap(); +            notify["FAIL_REASON"] = "Missing regionID, malformed response"; +            break; +        }  +        else if (result["regionID"].asUUID() != gAgent.getRegion()->getRegionID()) +        { +            // note that there is no report to the user in this failure case. +            LL_WARNS("WindlightCaps") << "No longer in the region where data was sent (currently " +                << gAgent.getRegion()->getRegionID() << ", reply is from " << result["regionID"].asUUID() +                << "); ignoring..." << LL_ENDL; +            break; +        } +        else if (!result["success"].asBoolean()) +        { +            LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings!  " << LL_ENDL; +            notify = LLSD::emptyMap(); +            notify["FAIL_REASON"] = result["fail_reason"].asString(); +            break; +        } + +        LL_DEBUGS("WindlightCaps") << "Success in applying windlight settings to region " << result["regionID"].asUUID() << LL_ENDL; +        LLEnvManagerNew::instance().onRegionSettingsApplyResponse(true); + +    } while (false); + +    if (!notify.isUndefined()) +    { +        LLNotificationsUtil::add("WLRegionApplyFail", notify); +        LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false); +    }  } diff --git a/indra/newview/llwlhandlers.h b/indra/newview/llwlhandlers.h index 089c799da7..6c093c733d 100755 --- a/indra/newview/llwlhandlers.h +++ b/indra/newview/llwlhandlers.h @@ -29,6 +29,7 @@  #include "llviewerprecompiledheaders.h"  #include "llhttpclient.h" +#include "llcoros.h"  class LLEnvironmentRequest  { @@ -40,21 +41,10 @@ public:  private:  	static void onRegionCapsReceived(const LLUUID& region_id);  	static bool doRequest(); -}; - -class LLEnvironmentRequestResponder: public LLHTTPClient::Responder -{ -	LOG_CLASS(LLEnvironmentRequestResponder); -private: -	/* virtual */ void httpSuccess(); -	/* virtual */ void httpFailure(); -private: -	friend class LLEnvironmentRequest; +    static void environmentRequestCoro(LLCoros::self& self, std::string url); -	LLEnvironmentRequestResponder(); -	static int sCount; -	int mID; +    static S32 sLastRequest;  };  class LLEnvironmentApply @@ -67,8 +57,11 @@ public:  private:  	static clock_t sLastUpdate;  	static clock_t UPDATE_WAIT_SECONDS; + +    static void environmentApplyCoro(LLCoros::self& self, std::string url, LLSD content);  }; +#if 0  class LLEnvironmentApplyResponder: public LLHTTPClient::Responder  {  	LOG_CLASS(LLEnvironmentApplyResponder); @@ -97,5 +90,6 @@ private:  	LLEnvironmentApplyResponder() {}  }; +#endif  #endif // LL_LLWLHANDLERS_H | 
