summaryrefslogtreecommitdiff
path: root/indra/newview/llappearancemgr.cpp
diff options
context:
space:
mode:
authorDon Kjer <don@lindenlab.com>2013-03-13 06:26:25 +0000
committerDon Kjer <don@lindenlab.com>2013-03-13 06:26:25 +0000
commitf945415210f0e18c2c6d941fda6b7d45cb0f06f1 (patch)
treecf93ca0d9596a82a8fc7a4d1b1f0ee263ea5549e /indra/newview/llappearancemgr.cpp
parent54cdc322b8f2bd35b289cacf3493622e7cc51194 (diff)
Large changes to the LLCurl::Responder API, as well as pulling in some changes to common libraries from the server codebase:
* Additional error checking in http handlers. * Uniform log spam for http errors. * Switch to using constants for http heads and status codes. * Fixed bugs in incorrectly checking if parsing LLSD xml resulted in an error. * Reduced spam regarding LLSD parsing errors in the default completedRaw http handler. It should not longer be necessary to short-circuit completedRaw to avoid spam. * Ported over a few bug fixes from the server code. * Switch mode http status codes to use S32 instead of U32. * Ported LLSD::asStringRef from server code; avoids copying strings all over the place. * Ported server change to LLSD::asBinary; this always returns a reference now instead of copying the entire binary blob. * Ported server pretty notation format (and pretty binary format) to llsd serialization. * The new LLCurl::Responder API no longer has two error handlers to choose from. Overriding the following methods have been deprecated: ** error - use httpFailure ** errorWithContent - use httpFailure ** result - use httpSuccess ** completed - use httpCompleted ** completedHeader - no longer necessary; call getResponseHeaders() from a completion method to obtain these headers. * In order to 'catch' a completed http request, override one of these methods: ** httpSuccess - Called for any 2xx status code. ** httpFailure - Called for any non-2xx status code. ** httpComplete - Called for all status codes. Default implementation is to call either httpSuccess or httpFailure. * It is recommended to keep these methods protected/private in order to avoid triggering of these methods without using a 'push' method (see below). * Uniform error handling should followed whenever possible by calling a variant of this during httpFailure: ** llwarns << dumpResponse() << llendl; * Be sure to include LOG_CLASS(your_class_name) in your class in order for the log entry to give more context. * In order to 'push' a result into the responder, you should no longer call error, errorWithContent, result, or completed. * Nor should you directly call httpSuccess/Failure/Completed (unless passing a message up to a parent class). * Instead, you can set the internal content of a responder and trigger a corresponding method using the following methods: ** successResult - Sets results and calls httpSuccess ** failureResult - Sets results and calls httpFailure ** completedResult - Sets results and calls httpCompleted * To obtain information about a the response from a reponder method, use the following getters: ** getStatus - HTTP status code ** getReason - Reason string ** getContent - Content (Parsed body LLSD) ** getResponseHeaders - Response Headers (LLSD map) ** getHTTPMethod - HTTP method of the request ** getURL - URL of the request * It is still possible to override completeRaw if you want to manipulate data directly out of LLPumpIO. * See indra/llmessage/llcurl.h for more information.
Diffstat (limited to 'indra/newview/llappearancemgr.cpp')
-rwxr-xr-xindra/newview/llappearancemgr.cpp83
1 files changed, 60 insertions, 23 deletions
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 2c76efc7fb..92a896a3c2 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2984,20 +2984,23 @@ class LLHTTPRetryPolicy: public LLThreadSafeRefCount
public:
LLHTTPRetryPolicy() {}
virtual ~LLHTTPRetryPolicy() {}
- virtual bool shouldRetry(U32 status, F32& seconds_to_wait) = 0;
+ virtual bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) = 0;
};
// Example of simplest possible policy, not necessarily recommended.
+// This would be a potentially dangerous policy to enable. Removing for now:
+#if 0
class LLAlwaysRetryImmediatelyPolicy: public LLHTTPRetryPolicy
{
public:
LLAlwaysRetryImmediatelyPolicy() {}
- bool shouldRetry(U32 status, F32& seconds_to_wait)
+ bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait)
{
seconds_to_wait = 0.0;
return true;
}
};
+#endif
// Very general policy with geometric back-off after failures,
// up to a maximum delay, and maximum number of retries.
@@ -3014,10 +3017,25 @@ public:
{
}
- bool shouldRetry(U32 status, F32& seconds_to_wait)
+ bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait)
{
- seconds_to_wait = mDelay;
- mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay);
+#if 0
+ // *TODO: Test using status codes to only retry server errors.
+ // Only server errors would potentially return a different result on retry.
+ if (!isHttpServerErrorStatus(status)) return false;
+#endif
+
+#if 0
+ // *TODO: Honor server Retry-After header.
+ // Status 503 may ask us to wait for a certain amount of time before retrying.
+ if (!headers.has(HTTP_HEADER_RETRY_AFTER)
+ || !getSecondsUntilRetryAfter(headers[HTTP_HEADER_RETRY_AFTER].asStringRef(), seconds_to_wait))
+#endif
+ {
+ seconds_to_wait = mDelay;
+ mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay);
+ }
+
mRetryCount++;
return (mRetryCount<=mMaxRetries);
}
@@ -3033,6 +3051,7 @@ private:
class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder
{
+ LOG_CLASS(RequestAgentUpdateAppearanceResponder);
public:
RequestAgentUpdateAppearanceResponder()
{
@@ -3043,13 +3062,19 @@ public:
{
}
+protected:
// Successful completion.
- /* virtual */ void result(const LLSD& content)
+ /* virtual */ void httpSuccess()
{
- LL_DEBUGS("Avatar") << "content: " << ll_pretty_print_sd(content) << LL_ENDL;
+ const LLSD& content = getContent();
+ if (!content.isMap())
+ {
+ failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+ return;
+ }
if (content["success"].asBoolean())
{
- LL_DEBUGS("Avatar") << "OK" << LL_ENDL;
+ LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL;
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
{
dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
@@ -3057,33 +3082,35 @@ public:
}
else
{
- onFailure(200);
+ failureResult(HTTP_INTERNAL_ERROR, "Non-success response", content);
}
}
// Error
- /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+ /*virtual*/ void httpFailure()
{
- llwarns << "appearance update request failed, status: " << status << " reason: " << reason << " code: " << content["code"].asInteger() << " error: \"" << content["error"].asString() << "\"" << llendl;
+ const LLSD& content = getContent();
+ LL_WARNS("Avatar") << "appearance update request failed "
+ << dumpResponse() << LL_ENDL;
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
{
dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
debugCOF(content);
}
- onFailure(status);
- }
+ onFailure();
+ }
- void onFailure(U32 status)
+ void onFailure()
{
F32 seconds_to_wait;
- if (mRetryPolicy->shouldRetry(status,seconds_to_wait))
+ if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait))
{
llinfos << "retrying" << llendl;
doAfterInterval(boost::bind(&LLAppearanceMgr::requestServerAppearanceUpdate,
LLAppearanceMgr::getInstance(),
- LLCurl::ResponderPtr(this)),
- seconds_to_wait);
+ LLHTTPClient::ResponderPtr(this)),
+ seconds_to_wait);
}
else
{
@@ -3286,6 +3313,7 @@ void LLAppearanceMgr::requestServerAppearanceUpdate(LLCurl::ResponderPtr respond
class LLIncrementCofVersionResponder : public LLHTTPClient::Responder
{
+ LOG_CLASS(LLIncrementCofVersionResponder);
public:
LLIncrementCofVersionResponder() : LLHTTPClient::Responder()
{
@@ -3296,10 +3324,17 @@ public:
{
}
- virtual void result(const LLSD &pContent)
+protected:
+ virtual void httpSuccess()
{
llinfos << "Successfully incremented agent's COF." << llendl;
- S32 new_version = pContent["category"]["version"].asInteger();
+ const LLSD& content = getContent();
+ if (!content.isMap())
+ {
+ failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+ return;
+ }
+ S32 new_version = content["category"]["version"].asInteger();
LLAppearanceMgr* app_mgr = LLAppearanceMgr::getInstance();
@@ -3308,12 +3343,13 @@ public:
app_mgr->mLastUpdateRequestCOFVersion = new_version;
}
- virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& content)
+
+ virtual void httpFailure()
{
- llwarns << "While attempting to increment the agent's cof we got an error with [status:"
- << pStatus << "]: " << content << llendl;
+ LL_WARNS("Avatar") << "While attempting to increment the agent's cof we got an error "
+ << dumpResponse() << LL_ENDL;
F32 seconds_to_wait;
- if (mRetryPolicy->shouldRetry(pStatus,seconds_to_wait))
+ if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait))
{
llinfos << "retrying" << llendl;
doAfterInterval(boost::bind(&LLAppearanceMgr::incrementCofVersion,
@@ -3327,6 +3363,7 @@ public:
}
}
+private:
LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
};