summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorRider Linden <none@none>2015-04-01 16:37:00 -0700
committerRider Linden <none@none>2015-04-01 16:37:00 -0700
commitedc1439bd633bdac183fbecc131edd55074b5442 (patch)
tree4655e22fd1777c5d5c44e585e755aad4676deb7b /indra
parent0b02b36b651987d5d24c225fa9472e0d35803559 (diff)
Added AvatarNameCache as coroutine, with LLCore::HttpHandler to respond correctly to Event Pumps.
Added get/setRequestURL() to LLCore::HttpResponse Removed URI from the HttpSDHandler.
Diffstat (limited to 'indra')
-rwxr-xr-xindra/llcorehttp/_httpoprequest.cpp4
-rwxr-xr-xindra/llcorehttp/httpresponse.cpp3
-rwxr-xr-xindra/llcorehttp/httpresponse.h11
-rwxr-xr-xindra/llmessage/llavatarnamecache.cpp286
-rwxr-xr-xindra/llmessage/llavatarnamecache.h7
-rw-r--r--indra/llmessage/llcorehttputil.cpp96
-rw-r--r--indra/llmessage/llcorehttputil.h30
-rw-r--r--indra/llmessage/llhttpsdhandler.cpp12
-rw-r--r--indra/llmessage/llhttpsdhandler.h11
-rwxr-xr-xindra/newview/llagent.cpp55
-rwxr-xr-xindra/newview/llagent.h10
-rwxr-xr-xindra/newview/llappearancemgr.cpp8
-rwxr-xr-xindra/newview/llmaterialmgr.cpp14
13 files changed, 405 insertions, 142 deletions
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index 5768fe5a90..7c2309b31d 100755
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -260,7 +260,9 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
response->setStatus(mStatus);
response->setBody(mReplyBody);
response->setHeaders(mReplyHeaders);
- if (mReplyOffset || mReplyLength)
+ response->setRequestURL(mReqURL);
+
+ if (mReplyOffset || mReplyLength)
{
// Got an explicit offset/length in response
response->setRange(mReplyOffset, mReplyLength, mReplyFullLength);
diff --git a/indra/llcorehttp/httpresponse.cpp b/indra/llcorehttp/httpresponse.cpp
index 87e3426415..7d88f02527 100755
--- a/indra/llcorehttp/httpresponse.cpp
+++ b/indra/llcorehttp/httpresponse.cpp
@@ -41,7 +41,8 @@ HttpResponse::HttpResponse()
mBufferArray(NULL),
mHeaders(NULL),
mRetries(0U),
- m503Retries(0U)
+ m503Retries(0U),
+ mRequestUrl()
{}
diff --git a/indra/llcorehttp/httpresponse.h b/indra/llcorehttp/httpresponse.h
index 39b582ff85..6c3b4da5e6 100755
--- a/indra/llcorehttp/httpresponse.h
+++ b/indra/llcorehttp/httpresponse.h
@@ -194,6 +194,16 @@ public:
return mStats;
}
+ void setRequestURL(const std::string &url)
+ {
+ mRequestUrl = url;
+ }
+
+ const std::string &getRequestURL() const
+ {
+ return mRequestUrl;
+ }
+
protected:
// Response data here
@@ -206,6 +216,7 @@ protected:
std::string mContentType;
unsigned int mRetries;
unsigned int m503Retries;
+ std::string mRequestUrl;
TransferStats::ptr_t mStats;
};
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index d02a60b7b2..88859819e0 100755
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -33,9 +33,18 @@
#include "llhttpclient.h"
#include "llsd.h"
#include "llsdserialize.h"
-
+#include "httpresponse.h"
+#include "llhttpsdhandler.h"
#include <boost/tokenizer.hpp>
+#include "httpcommon.h"
+#include "httprequest.h"
+#include "httpheaders.h"
+#include "httpoptions.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "llcorehttputil.h"
+
#include <map>
#include <set>
@@ -90,6 +99,12 @@ namespace LLAvatarNameCache
// Time-to-live for a temp cache entry.
const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0;
+ LLCore::HttpRequest::ptr_t sHttpRequest;
+ LLCore::HttpHeaders::ptr_t sHttpHeaders;
+ LLCore::HttpOptions::ptr_t sHttpOptions;
+ LLCore::HttpRequest::policy_t sHttpPolicy;
+ LLCore::HttpRequest::priority_t sHttpPriority;
+
//-----------------------------------------------------------------------
// Internal methods
//-----------------------------------------------------------------------
@@ -121,7 +136,13 @@ namespace LLAvatarNameCache
// Erase expired names from cache
void eraseUnrefreshed();
- bool expirationFromCacheControl(const LLSD& headers, F64 *expires);
+ //bool expirationFromCacheControl(LLCore::HttpHeaders *headers, F64 *expires);
+ bool expirationFromCacheControl(const LLSD& headers, F64 *expires);
+
+ // This is a coroutine. The only parameter that can be specified as a reference is the self
+ void requestAvatarNameCache_(LLCoros::self& self, std::string url, std::vector<LLUUID> agentIds);
+
+ void handleAvNameCacheSuccess(const LLSD &data, const LLSD &httpResult);
}
/* Sample response:
@@ -163,94 +184,125 @@ namespace LLAvatarNameCache
</llsd>
*/
-class LLAvatarNameResponder : public LLHTTPClient::Responder
+// Coroutine for sending and processing avatar name cache requests.
+// Do not call directly. See documentation in lleventcoro.h and llcoro.h for
+// further explanation.
+void LLAvatarNameCache::requestAvatarNameCache_(LLCoros::self& self, std::string url, std::vector<LLUUID> agentIds)
{
- LOG_CLASS(LLAvatarNameResponder);
-private:
- // need to store agent ids that are part of this request in case of
- // an error, so we can flag them as unavailable
- std::vector<LLUUID> mAgentIDs;
-
-public:
- LLAvatarNameResponder(const std::vector<LLUUID>& agent_ids)
- : mAgentIDs(agent_ids)
- { }
-
-protected:
- /*virtual*/ void httpSuccess()
- {
- const LLSD& content = getContent();
- if (!content.isMap())
- {
- failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
- return;
- }
- // Pull expiration out of headers if available
- F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(getResponseHeaders());
- F64 now = LLFrameTimer::getTotalSeconds();
+ LLEventStream replyPump("NameCacheReply", true);
+ LLCoreHttpUtil::HttpCoroHandler::ptr_t httpHandler =
+ LLCoreHttpUtil::HttpCoroHandler::ptr_t(new LLCoreHttpUtil::HttpCoroHandler(replyPump));
- const LLSD& agents = content["agents"];
- LLSD::array_const_iterator it = agents.beginArray();
- for ( ; it != agents.endArray(); ++it)
- {
- const LLSD& row = *it;
- LLUUID agent_id = row["id"].asUUID();
+ LL_DEBUGS("AvNameCache") << "Entering coroutine " << LLCoros::instance().getName(self)
+ << " with url '" << url << "', requesting " << agentIds.size() << " Agent Ids" << LL_ENDL;
- LLAvatarName av_name;
- av_name.fromLLSD(row);
+ try
+ {
+ bool success = true;
- // Use expiration time from header
- av_name.mExpires = expires;
+ LLAvatarNameCache::sHttpRequest->requestGet(
+ LLAvatarNameCache::sHttpPolicy, LLAvatarNameCache::sHttpPriority,
+ url, LLAvatarNameCache::sHttpOptions.get(),
+ LLAvatarNameCache::sHttpHeaders.get(), httpHandler.get());
- LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << LL_ENDL;
- av_name.dump();
-
- // cache it and fire signals
- LLAvatarNameCache::processName(agent_id, av_name);
- }
+ LLSD results = waitForEventOn(self, replyPump);
+ LLSD httpResults;
- // Same logic as error response case
- const LLSD& unresolved_agents = content["bad_ids"];
- S32 num_unresolved = unresolved_agents.size();
- if (num_unresolved > 0)
- {
- LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result " << num_unresolved << " unresolved ids; "
- << "expires in " << expires - now << " seconds"
- << LL_ENDL;
- it = unresolved_agents.beginArray();
- for ( ; it != unresolved_agents.endArray(); ++it)
- {
- const LLUUID& agent_id = *it;
+ LL_DEBUGS() << results << LL_ENDL;
- LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result "
- << "failed id " << agent_id
- << LL_ENDL;
+ if (!results.isMap())
+ {
+ LL_WARNS("AvNameCache") << " Invalid result returned from LLCoreHttpUtil::HttpCoroHandler." << LL_ENDL;
+ success = false;
+ }
+ else
+ {
+ httpResults = results["http_result"];
+ success = httpResults["success"].asBoolean();
+ if (!success)
+ {
+ LL_WARNS("AvNameCache") << "Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
+ << httpResults["status"] << ": '" << httpResults["message"] << "'" << LL_ENDL;
+ }
+ }
+ if (!success)
+ { // on any sort of failure add dummy records for any agent IDs
+ // in this request that we do not have cached already
+ std::vector<LLUUID>::const_iterator it = agentIds.begin();
+ for ( ; it != agentIds.end(); ++it)
+ {
+ const LLUUID& agent_id = *it;
LLAvatarNameCache::handleAgentError(agent_id);
- }
- }
- LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result "
- << LLAvatarNameCache::sCache.size() << " cached names"
- << LL_ENDL;
+ }
+ return;
+ }
+
+ LLAvatarNameCache::handleAvNameCacheSuccess(results, httpResults);
+
}
+ catch (std::exception e)
+ {
+ LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL;
+ }
+ catch (...)
+ {
+ LL_WARNS() << "Caught unknown exception." << LL_ENDL;
+ }
+}
- /*virtual*/ void httpFailure()
- {
- // If there's an error, it might be caused by PeopleApi,
- // or when loading textures on startup and using a very slow
- // network, this query may time out.
- // What we should do depends on whether or not we have a cached name
- LL_WARNS("AvNameCache") << dumpResponse() << LL_ENDL;
-
- // Add dummy records for any agent IDs in this request that we do not have cached already
- std::vector<LLUUID>::const_iterator it = mAgentIDs.begin();
- for ( ; it != mAgentIDs.end(); ++it)
- {
- const LLUUID& agent_id = *it;
- LLAvatarNameCache::handleAgentError(agent_id);
- }
- }
-};
+void LLAvatarNameCache::handleAvNameCacheSuccess(const LLSD &data, const LLSD &httpResult)
+{
+
+ LLSD headers = httpResult["headers"];
+ // Pull expiration out of headers if available
+ F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(headers);
+ F64 now = LLFrameTimer::getTotalSeconds();
+
+ const LLSD& agents = data["agents"];
+ LLSD::array_const_iterator it = agents.beginArray();
+ for (; it != agents.endArray(); ++it)
+ {
+ const LLSD& row = *it;
+ LLUUID agent_id = row["id"].asUUID();
+
+ LLAvatarName av_name;
+ av_name.fromLLSD(row);
+
+ // Use expiration time from header
+ av_name.mExpires = expires;
+
+ LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << LL_ENDL;
+ av_name.dump();
+
+ // cache it and fire signals
+ LLAvatarNameCache::processName(agent_id, av_name);
+ }
+
+ // Same logic as error response case
+ const LLSD& unresolved_agents = data["bad_ids"];
+ S32 num_unresolved = unresolved_agents.size();
+ if (num_unresolved > 0)
+ {
+ LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result " << num_unresolved << " unresolved ids; "
+ << "expires in " << expires - now << " seconds"
+ << LL_ENDL;
+ it = unresolved_agents.beginArray();
+ for (; it != unresolved_agents.endArray(); ++it)
+ {
+ const LLUUID& agent_id = *it;
+
+ LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result "
+ << "failed id " << agent_id
+ << LL_ENDL;
+
+ LLAvatarNameCache::handleAgentError(agent_id);
+ }
+ }
+ LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result "
+ << LLAvatarNameCache::sCache.size() << " cached names"
+ << LL_ENDL;
+}
// Provide some fallback for agents that return errors
void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id)
@@ -353,12 +405,17 @@ void LLAvatarNameCache::requestNamesViaCapability()
}
}
- if (!url.empty())
- {
- LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability requested "
- << ids << " ids"
- << LL_ENDL;
- LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));
+ if (!url.empty())
+ {
+ LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability requested "
+ << ids << " ids"
+ << LL_ENDL;
+
+ std::string coroname =
+ LLCoros::instance().launch("LLAvatarNameCache::requestAvatarNameCache_",
+ boost::bind(&LLAvatarNameCache::requestAvatarNameCache_, _1, url, agent_ids));
+ LL_DEBUGS("AvNameCache") << coroname << " with url '" << url << "', agent_ids.size()=" << agent_ids.size() << LL_ENDL;
+
}
}
@@ -422,11 +479,20 @@ void LLAvatarNameCache::initClass(bool running, bool usePeopleAPI)
{
sRunning = running;
sUsePeopleAPI = usePeopleAPI;
+
+ sHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest());
+ sHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false);
+ sHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false);
+ sHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID;
+ sHttpPriority = 0;
}
void LLAvatarNameCache::cleanupClass()
{
- sCache.clear();
+ sHttpRequest.reset();
+ sHttpHeaders.reset();
+ sHttpOptions.reset();
+ sCache.clear();
}
void LLAvatarNameCache::importFile(std::istream& istr)
@@ -498,6 +564,8 @@ void LLAvatarNameCache::idle()
// By convention, start running at first idle() call
sRunning = true;
+ sHttpRequest->update(0L);
+
// *TODO: Possibly re-enabled this based on People API load measurements
// 100 ms is the threshold for "user speed" operations, so we can
// stall for about that long to batch up requests.
@@ -697,6 +765,50 @@ void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_na
sCache[agent_id] = av_name;
}
+#if 0
+F64 LLAvatarNameCache::nameExpirationFromHeaders(LLCore::HttpHeaders *headers)
+{
+ F64 expires = 0.0;
+ if (expirationFromCacheControl(headers, &expires))
+ {
+ return expires;
+ }
+ else
+ {
+ // With no expiration info, default to an hour
+ const F64 DEFAULT_EXPIRES = 60.0 * 60.0;
+ F64 now = LLFrameTimer::getTotalSeconds();
+ return now + DEFAULT_EXPIRES;
+ }
+}
+
+bool LLAvatarNameCache::expirationFromCacheControl(LLCore::HttpHeaders *headers, F64 *expires)
+{
+ bool fromCacheControl = false;
+ F64 now = LLFrameTimer::getTotalSeconds();
+
+ // Allow the header to override the default
+ const std::string *cache_control;
+
+ cache_control = headers->find(HTTP_IN_HEADER_CACHE_CONTROL);
+
+ if (cache_control && !cache_control->empty())
+ {
+ S32 max_age = 0;
+ if (max_age_from_cache_control(*cache_control, &max_age))
+ {
+ *expires = now + (F64)max_age;
+ fromCacheControl = true;
+ }
+ }
+ LL_DEBUGS("AvNameCache")
+ << ( fromCacheControl ? "expires based on cache control " : "default expiration " )
+ << "in " << *expires - now << " seconds"
+ << LL_ENDL;
+
+ return fromCacheControl;
+}
+#else
F64 LLAvatarNameCache::nameExpirationFromHeaders(const LLSD& headers)
{
F64 expires = 0.0;
@@ -741,7 +853,7 @@ bool LLAvatarNameCache::expirationFromCacheControl(const LLSD& headers, F64 *exp
return fromCacheControl;
}
-
+#endif
void LLAvatarNameCache::addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb)
{
diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h
index ea016b3125..fdfd4e972d 100755
--- a/indra/llmessage/llavatarnamecache.h
+++ b/indra/llmessage/llavatarnamecache.h
@@ -29,7 +29,8 @@
#define LLAVATARNAMECACHE_H
#include "llavatarname.h" // for convenience
-
+//#include "httpcommon.h"
+//#include "httpheaders.h"
#include <boost/signals2.hpp>
class LLSD;
@@ -49,7 +50,7 @@ namespace LLAvatarNameCache
void importFile(std::istream& istr);
void exportFile(std::ostream& ostr);
- // On the viewer, usually a simulator capabilitity.
+ // On the viewer, usually a simulator capabilities.
// If empty, name cache will fall back to using legacy name lookup system.
void setNameLookupURL(const std::string& name_lookup_url);
@@ -90,7 +91,7 @@ namespace LLAvatarNameCache
// Compute name expiration time from HTTP Cache-Control header,
// or return default value, in seconds from epoch.
- F64 nameExpirationFromHeaders(const LLSD& headers);
+ F64 nameExpirationFromHeaders(const LLSD& headers);
void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb);
}
diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp
index 366a0b9460..991985b1cf 100644
--- a/indra/llmessage/llcorehttputil.cpp
+++ b/indra/llmessage/llcorehttputil.cpp
@@ -30,15 +30,17 @@
#include <sstream>
#include "llcorehttputil.h"
+#include "llhttpconstants.h"
#include "llsdserialize.h"
-
using namespace LLCore;
namespace LLCoreHttpUtil
{
+
+
// *TODO: Currently converts only from XML content. A mode
// to convert using fromBinary() might be useful as well. Mesh
// headers could use it.
@@ -186,5 +188,97 @@ std::string responseToString(LLCore::HttpResponse * response)
}
+HttpCoroHandler::HttpCoroHandler(LLEventStream &reply) :
+ mReplyPump(reply)
+{
+}
+
+void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
+{
+ LLSD result;
+
+ LLCore::HttpStatus status = response->getStatus();
+
+ if (!status)
+ {
+ result = LLSD::emptyMap();
+ LL_WARNS()
+ << "\n--------------------------------------------------------------------------\n"
+ << " Error[" << status.toULong() << "] cannot access url '" << response->getRequestURL()
+ << "' because " << status.toString()
+ << "\n--------------------------------------------------------------------------"
+ << LL_ENDL;
+
+ }
+ else
+ {
+ const bool emit_parse_errors = false;
+
+ bool parsed = !((response->getBodySize() == 0) ||
+ !LLCoreHttpUtil::responseToLLSD(response, emit_parse_errors, result));
+
+ if (!parsed)
+ {
+ // Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
+ LLCore::HttpHeaders::ptr_t headers(response->getHeaders());
+ const std::string *contentType = (headers) ? headers->find(HTTP_IN_HEADER_CONTENT_TYPE) : NULL;
+
+ if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType))
+ {
+ std::string thebody = LLCoreHttpUtil::responseToString(response);
+ LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] "
+ << " body: " << thebody << LL_ENDL;
+
+ // Replace the status with a new one indicating the failure.
+ status = LLCore::HttpStatus(499, "Failed to deserialize LLSD.");
+ }
+ }
+
+ if (result.isUndefined())
+ {
+ // If we've gotten to this point and the result LLSD is still undefined
+ // either there was an issue deserializing the body or the response was
+ // blank. Create an empty map to hold the result either way.
+ result = LLSD::emptyMap();
+ }
+ }
+
+ buildStatusEntry(response, status, result);
+ mReplyPump.post(result);
+}
+
+void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result)
+{
+ LLSD httpresults = LLSD::emptyMap();
+
+ httpresults["success"] = static_cast<LLSD::Boolean>(status);
+ httpresults["type"] = static_cast<LLSD::Integer>(status.getType());
+ httpresults["status"] = static_cast<LLSD::Integer>(status.getStatus());
+ httpresults["message"] = static_cast<LLSD::String>(status.getMessage());
+ httpresults["url"] = static_cast<LLSD::String>(response->getRequestURL());
+
+ LLSD httpHeaders = LLSD::emptyMap();
+ LLCore::HttpHeaders * hdrs = response->getHeaders();
+
+ if (hdrs)
+ {
+ for (LLCore::HttpHeaders::iterator it = hdrs->begin(); it != hdrs->end(); ++it)
+ {
+ if (!(*it).second.empty())
+ {
+ httpHeaders[(*it).first] = (*it).second;
+ }
+ else
+ {
+ httpHeaders[(*it).first] = static_cast<LLSD::Boolean>(true);
+ }
+ }
+ }
+
+ httpresults["headers"] = httpHeaders;
+ result["http_result"] = httpresults;
+}
+
+
} // end namespace LLCoreHttpUtil
diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h
index 8e26f413fe..0bc102a0a3 100644
--- a/indra/llmessage/llcorehttputil.h
+++ b/indra/llmessage/llcorehttputil.h
@@ -39,6 +39,7 @@
#include "bufferarray.h"
#include "bufferstream.h"
#include "llsd.h"
+#include "llevents.h"
///
/// The base llcorehttp library implements many HTTP idioms
@@ -152,6 +153,35 @@ LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request,
LLCore::HttpHeaders::ptr_t & headers,
LLCore::HttpHandler * handler);
+/// The HttpCoroHandler is a specialization of the LLCore::HttpHandler for
+/// interacting with coroutines. When the request is completed the response
+/// will be posted onto the supplied Event Pump.
+///
+/// The LLSD posted back to the coroutine will have the following additions:
+/// llsd["http_result"] -+- ["message"] - An error message returned from the HTTP status
+/// +- ["status"] - The status code associated with the HTTP call
+/// +- ["success"] - Success of failure of the HTTP call and LLSD parsing.
+/// +- ["type"] - The LLCore::HttpStatus type associted with the HTTP call
+/// +- ["url"] - The URL used to make the call.
+/// +- ["headers"] - A map of name name value pairs with the HTTP headers.
+///
+
+///
+class HttpCoroHandler : public LLCore::HttpHandler
+{
+public:
+ HttpCoroHandler(LLEventStream &reply);
+
+ virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
+
+ typedef boost::shared_ptr<HttpCoroHandler> ptr_t;
+
+private:
+ void buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result);
+
+ LLEventStream &mReplyPump;
+};
+
} // end namespace LLCoreHttpUtil
diff --git a/indra/llmessage/llhttpsdhandler.cpp b/indra/llmessage/llhttpsdhandler.cpp
index 72ecfe77e2..159d03b176 100644
--- a/indra/llmessage/llhttpsdhandler.cpp
+++ b/indra/llmessage/llhttpsdhandler.cpp
@@ -36,10 +36,8 @@
#include "llcorehttputil.h"
//========================================================================
-LLHttpSDHandler::LLHttpSDHandler(const LLURI &uri):
- mUri(uri)
+LLHttpSDHandler::LLHttpSDHandler()
{
-
}
void LLHttpSDHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
@@ -68,7 +66,7 @@ void LLHttpSDHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons
{
std::string thebody = LLCoreHttpUtil::responseToString(response);
- LL_WARNS() << "Failed to deserialize . " << getUri() << " [status:" << response->getStatus().toString() << "] "
+ LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] "
<< " body: " << thebody << LL_ENDL;
}
}
@@ -83,8 +81,8 @@ void LLHttpSDHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons
}
//========================================================================
-LLHttpSDGenericHandler::LLHttpSDGenericHandler(const LLURI &uri, const std::string &caps) :
- LLHttpSDHandler(uri),
+LLHttpSDGenericHandler::LLHttpSDGenericHandler(const std::string &caps) :
+ LLHttpSDHandler(),
mCaps(caps)
{
}
@@ -99,7 +97,7 @@ void LLHttpSDGenericHandler::onFailure(LLCore::HttpResponse * response, LLCore::
LL_WARNS()
<< "\n--------------------------------------------------------------------------\n"
<< mCaps << " Error[" << status.toULong() << "] cannot access cap with url '"
- << getUri() << "' because " << status.toString()
+ << response->getRequestURL() << "' because " << status.toString()
<< "\n--------------------------------------------------------------------------"
<< LL_ENDL;
}
diff --git a/indra/llmessage/llhttpsdhandler.h b/indra/llmessage/llhttpsdhandler.h
index a2598c9709..7c28dbcab6 100644
--- a/indra/llmessage/llhttpsdhandler.h
+++ b/indra/llmessage/llhttpsdhandler.h
@@ -39,21 +39,14 @@
class LLHttpSDHandler : public LLCore::HttpHandler
{
public:
- LLHttpSDHandler(const LLURI &uri);
+ LLHttpSDHandler();
virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
- inline const LLURI &getUri() const
- {
- return mUri;
- }
-
protected:
virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content) = 0;
virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) = 0;
-private:
- LLURI mUri;
};
/// A trivial implementation of LLHttpSDHandler. This success and failure
@@ -62,7 +55,7 @@ private:
class LLHttpSDGenericHandler : public LLHttpSDHandler
{
public:
- LLHttpSDGenericHandler(const LLURI &uri, const std::string &action);
+ LLHttpSDGenericHandler(const std::string &action);
protected:
virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content);
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 667d530e39..eeedda5c6d 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -325,7 +325,6 @@ bool LLAgent::isMicrophoneOn(const LLSD& sdname)
// For a toggled version, see viewer.h for the
// TOGGLE_HACKED_GODLIKE_VIEWER define, instead.
// ************************************************************
-bool LLAgent::mActive = true;
// Constructors and Destructors
@@ -474,7 +473,9 @@ void LLAgent::init()
mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false);
mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_AGENT);
- doOnIdleRepeating(boost::bind(&LLAgent::onIdle, this));
+ // Now ensure that we get regular callbacks to poll for completion.
+ mBoundListener = LLEventPumps::instance().obtain("mainloop").
+ listen(LLEventPump::inventName(), boost::bind(&LLAgent::pollHttp, this, _1));
mInitialized = TRUE;
}
@@ -484,7 +485,6 @@ void LLAgent::init()
//-----------------------------------------------------------------------------
void LLAgent::cleanup()
{
- mActive = false;
mRegionp = NULL;
if (mTeleportFinishedSlot.connected())
{
@@ -494,6 +494,10 @@ void LLAgent::cleanup()
{
mTeleportFailedSlot.disconnect();
}
+ if (mBoundListener.connected())
+ {
+ mBoundListener.disconnect();
+ }
}
//-----------------------------------------------------------------------------
@@ -517,16 +521,16 @@ LLAgent::~LLAgent()
}
//-----------------------------------------------------------------------------
-// Idle processing
+// pollHttp
+// Polling done once per frame on the "mainloop" to support HTTP processing.
//-----------------------------------------------------------------------------
-bool LLAgent::onIdle()
+bool LLAgent::pollHttp(const LLSD&)
{
- if (!LLAgent::mActive)
- return true;
- mHttpRequest->update(0L);
- return false;
+ mHttpRequest->update(0L);
+ return false;
}
+
// Handle any actions that need to be performed when the main app gains focus
// (such as through alt-tab).
//-----------------------------------------------------------------------------
@@ -2548,8 +2552,8 @@ int LLAgent::convertTextToMaturity(char text)
class LLMaturityHttpHandler : public LLHttpSDHandler
{
public:
- LLMaturityHttpHandler(const std::string& capabilityURL, LLAgent *agent, U8 preferred, U8 previous):
- LLHttpSDHandler(capabilityURL),
+ LLMaturityHttpHandler(LLAgent *agent, U8 preferred, U8 previous):
+ LLHttpSDHandler(),
mAgent(agent),
mPreferredMaturity(preferred),
mPreviousMaturity(previous)
@@ -2764,7 +2768,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity)
return;
}
- LLMaturityHttpHandler * handler = new LLMaturityHttpHandler(url, this, pPreferredMaturity, mLastKnownResponseMaturity);
+ LLMaturityHttpHandler * handler = new LLMaturityHttpHandler(this, pPreferredMaturity, mLastKnownResponseMaturity);
LLSD access_prefs = LLSD::emptyMap();
access_prefs["max"] = LLViewerRegion::accessToShortString(pPreferredMaturity);
@@ -2779,14 +2783,14 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity)
if (handle == LLCORE_HTTP_HANDLE_INVALID)
{
delete handler;
- LL_WARNS("Avatar") << "Maturity request post failed." << LL_ENDL;
+ LL_WARNS("Agent") << "Maturity request post failed." << LL_ENDL;
}
}
}
LLCore::HttpHandle LLAgent::requestPostCapability(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr)
{
- LLHttpSDHandler * handler = (usrhndlr) ? usrhndlr : new LLHttpSDGenericHandler(url, cap);
+ LLHttpSDHandler * handler = (usrhndlr) ? usrhndlr : new LLHttpSDGenericHandler(cap);
LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,
mHttpPolicy, mHttpPriority, url,
postData, mHttpOptions, mHttpHeaders, handler);
@@ -2799,16 +2803,31 @@ LLCore::HttpHandle LLAgent::requestPostCapability(const std::string &cap, const
if (!usrhndlr)
delete handler;
LLCore::HttpStatus status = mHttpRequest->getStatus();
- LL_WARNS("Avatar") << "'" << cap << "' request POST failed. Reason "
+ LL_WARNS("Agent") << "'" << cap << "' request POST failed. Reason "
<< status.toTerseString() << " \"" << status.toString() << "\"" << LL_ENDL;
}
return handle;
}
-//LLCore::HttpHandle LLAgent::httpGetCapibility(const std::string &cap, const LLURI &uri, LLHttpSDHandler *usrhndlr)
-//{
-//}
+LLCore::HttpHandle LLAgent::requestGetCapability(const std::string &cap, const std::string &url, LLHttpSDHandler *usrhndlr)
+{
+ LLHttpSDHandler * handler = (usrhndlr) ? usrhndlr : new LLHttpSDGenericHandler(cap);
+ LLCore::HttpHandle handle = mHttpRequest->requestGet(mHttpPolicy, mHttpPriority,
+ url, mHttpOptions.get(), mHttpHeaders.get(), handler);
+ if (handle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ // If no handler was passed in we delete the handler default handler allocated
+ // at the start of this function.
+ // *TODO: Change this metaphore to use boost::shared_ptr<> for handlers. Requires change in LLCore::HTTP
+ if (!usrhndlr)
+ delete handler;
+ LLCore::HttpStatus status = mHttpRequest->getStatus();
+ LL_WARNS("Agent") << "'" << cap << "' request GET failed. Reason "
+ << status.toTerseString() << " \"" << status.toString() << "\"" << LL_ENDL;
+ }
+ return handle;
+}
BOOL LLAgent::getAdminOverride() const
{
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 26120b52f6..9ffc9b9a7a 100755
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -34,6 +34,7 @@
#include "llcoordframe.h" // for mFrameAgent
#include "llavatarappearancedefines.h"
#include "llpermissionsflags.h"
+#include "llevents.h"
#include "v3dmath.h"
#include "httprequest.h"
#include "httpheaders.h"
@@ -117,9 +118,7 @@ public:
void cleanup();
private:
- bool onIdle();
- static bool mActive;
//--------------------------------------------------------------------
// Login
//--------------------------------------------------------------------
@@ -767,6 +766,7 @@ private:
LLCore::HttpOptions::ptr_t mHttpOptions;
LLCore::HttpRequest::policy_t mHttpPolicy;
LLCore::HttpRequest::priority_t mHttpPriority;
+ LLTempBoundListener mBoundListener;
bool isMaturityPreferenceSyncedWithServer() const;
void sendMaturityPreferenceToServer(U8 pPreferredMaturity);
@@ -781,6 +781,8 @@ private:
void handleMaturity(const LLSD &pNewValue);
bool validateMaturity(const LLSD& newvalue);
+ bool pollHttp(const LLSD &);
+
/** Access
** **
@@ -924,9 +926,9 @@ public:
**/
public:
/// Utilities for allowing the the agent sub managers to post and get via
- /// HTTP using the agent's policy settings and headers.
+ /// HTTP using the agent's policy settings and headers.
LLCore::HttpHandle requestPostCapability(const std::string &cap, const std::string &url, LLSD &postData, LLHttpSDHandler *usrhndlr = NULL);
- //LLCore::HttpHandle httpGetCapability(const std::string &cap, const LLURI &uri, LLHttpSDHandler *usrhndlr = NULL);
+ LLCore::HttpHandle requestGetCapability(const std::string &cap, const std::string &url, LLHttpSDHandler *usrhndlr = NULL);
/** Utility
** **
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 709d9881e1..4fbcd90baa 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1249,8 +1249,8 @@ static void removeDuplicateItems(LLInventoryModel::item_array_t& items)
class LLAppearanceMgrHttpHandler : public LLHttpSDHandler
{
public:
- LLAppearanceMgrHttpHandler(const std::string& capabilityURL, LLAppearanceMgr *mgr) :
- LLHttpSDHandler(capabilityURL),
+ LLAppearanceMgrHttpHandler(LLAppearanceMgr *mgr) :
+ LLHttpSDHandler(),
mManager(mgr)
{ }
@@ -1314,7 +1314,7 @@ void LLAppearanceMgrHttpHandler::onSuccess(LLCore::HttpResponse * response, cons
void LLAppearanceMgrHttpHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status)
{
- LL_WARNS("Avatar") << "Appearance Mgr request failed to " << getUri()
+ LL_WARNS("Avatar") << "Appearance Mgr request failed to " << response->getRequestURL()
<< ". Reason code: (" << status.toTerseString() << ") "
<< status.toString() << LL_ENDL;
}
@@ -3434,7 +3434,7 @@ void LLAppearanceMgr::requestServerAppearanceUpdate()
}
LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << LL_ENDL;
- LLAppearanceMgrHttpHandler * handler = new LLAppearanceMgrHttpHandler(url, this);
+ LLAppearanceMgrHttpHandler * handler = new LLAppearanceMgrHttpHandler(this);
mInFlightCounter++;
mInFlightTimer.setTimerExpirySec(60.0);
diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp
index 78fbe9af0a..8a726ec7c9 100755
--- a/indra/newview/llmaterialmgr.cpp
+++ b/indra/newview/llmaterialmgr.cpp
@@ -70,7 +70,7 @@ public:
typedef boost::function<void(bool, const LLSD&)> CallbackFunction;
typedef boost::shared_ptr<LLMaterialHttpHandler> ptr_t;
- LLMaterialHttpHandler(const std::string& method, const std::string& capabilityURL, CallbackFunction cback);
+ LLMaterialHttpHandler(const std::string& method, CallbackFunction cback);
virtual ~LLMaterialHttpHandler();
@@ -83,8 +83,8 @@ private:
CallbackFunction mCallback;
};
-LLMaterialHttpHandler::LLMaterialHttpHandler(const std::string& method, const std::string& capabilityURL, CallbackFunction cback):
- LLHttpSDHandler(capabilityURL),
+LLMaterialHttpHandler::LLMaterialHttpHandler(const std::string& method, CallbackFunction cback):
+ LLHttpSDHandler(),
mMethod(method),
mCallback(cback)
{
@@ -106,7 +106,7 @@ void LLMaterialHttpHandler::onFailure(LLCore::HttpResponse * response, LLCore::H
LL_WARNS("Materials")
<< "\n--------------------------------------------------------------------------\n"
<< mMethod << " Error[" << status.toULong() << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME
- << "'\n with url '" << getUri() << "' because " << status.toString()
+ << "'\n with url '" << response->getRequestURL() << "' because " << status.toString()
<< "\n--------------------------------------------------------------------------"
<< LL_ENDL;
@@ -653,7 +653,7 @@ void LLMaterialMgr::processGetQueue()
postData[MATERIALS_CAP_ZIP_FIELD] = materialBinary;
LLMaterialHttpHandler * handler =
- new LLMaterialHttpHandler("POST", capURL,
+ new LLMaterialHttpHandler("POST",
boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id)
);
@@ -707,7 +707,7 @@ void LLMaterialMgr::processGetAllQueue()
LL_DEBUGS("Materials") << "GET all for region " << region_id << "url " << capURL << LL_ENDL;
LLMaterialHttpHandler *handler =
- new LLMaterialHttpHandler("GET", capURL,
+ new LLMaterialHttpHandler("GET",
boost::bind(&LLMaterialMgr::onGetAllResponse, this, _1, _2, *itRegion)
);
@@ -810,7 +810,7 @@ void LLMaterialMgr::processPutQueue()
LL_DEBUGS("Materials") << "put for " << itRequest->second.size() << " faces to region " << itRequest->first->getName() << LL_ENDL;
LLMaterialHttpHandler * handler =
- new LLMaterialHttpHandler("PUT", capURL,
+ new LLMaterialHttpHandler("PUT",
boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2)
);