Added AvatarNameCache as coroutine, with LLCore::HttpHandler to respond correctly to Event Pumps.
Added get/setRequestURL() to LLCore::HttpResponse Removed URI from the HttpSDHandler.meow-7.2.2
parent
0b02b36b65
commit
edc1439bd6
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ HttpResponse::HttpResponse()
|
|||
mBufferArray(NULL),
|
||||
mHeaders(NULL),
|
||||
mRetries(0U),
|
||||
m503Retries(0U)
|
||||
m503Retries(0U),
|
||||
mRequestUrl()
|
||||
{}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
LLEventStream replyPump("NameCacheReply", true);
|
||||
LLCoreHttpUtil::HttpCoroHandler::ptr_t httpHandler =
|
||||
LLCoreHttpUtil::HttpCoroHandler::ptr_t(new LLCoreHttpUtil::HttpCoroHandler(replyPump));
|
||||
|
||||
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();
|
||||
LL_DEBUGS("AvNameCache") << "Entering coroutine " << LLCoros::instance().getName(self)
|
||||
<< " with url '" << url << "', requesting " << agentIds.size() << " Agent Ids" << LL_ENDL;
|
||||
|
||||
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();
|
||||
try
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
LLAvatarName av_name;
|
||||
av_name.fromLLSD(row);
|
||||
LLAvatarNameCache::sHttpRequest->requestGet(
|
||||
LLAvatarNameCache::sHttpPolicy, LLAvatarNameCache::sHttpPriority,
|
||||
url, LLAvatarNameCache::sHttpOptions.get(),
|
||||
LLAvatarNameCache::sHttpHeaders.get(), httpHandler.get());
|
||||
|
||||
// Use expiration time from header
|
||||
av_name.mExpires = expires;
|
||||
LLSD results = waitForEventOn(self, replyPump);
|
||||
LLSD httpResults;
|
||||
|
||||
LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << LL_ENDL;
|
||||
av_name.dump();
|
||||
|
||||
// cache it and fire signals
|
||||
LLAvatarNameCache::processName(agent_id, av_name);
|
||||
}
|
||||
LL_DEBUGS() << results << LL_ENDL;
|
||||
|
||||
// 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_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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*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;
|
||||
// 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;
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
** **
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue