Implement all aisv3 HTTP requests. Added PATCH and COPY methods.

This commit is contained in:
Shyotl
2015-07-23 01:02:02 -05:00
parent 2b9245ba2e
commit dedd75dc4f
16 changed files with 1456 additions and 80 deletions

View File

@@ -36,6 +36,7 @@
// linden libraries
#include "indra_constants.h"
#include "llaisapi.h"
#include "llavatarnamecache.h" // name lookup cap url
//#include "llfloaterreg.h"
#include "llmath.h"
@@ -89,8 +90,8 @@
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy baseCapabilitiesComplete_timeout;
extern AIHTTPTimeoutPolicy gamingDataReceived_timeout;
extern AIHTTPTimeoutPolicy simulatorFeaturesReceived_timeout;
extern AIHTTPTimeoutPolicy baseCapabilitiesCompleteTracker_timeout;
extern AIHTTPTimeoutPolicy baseFeaturesReceived_timeout;
const F32 WATER_TEXTURE_SCALE = 8.f; // Number of times to repeat the water texture across a region
const S16 MAX_MAP_DIST = 10;
@@ -103,6 +104,8 @@ const S32 MAX_CAP_REQUEST_ATTEMPTS = 30;
typedef std::map<std::string, std::string> CapabilityMap;
static void log_capabilities(const CapabilityMap &capmap);
class LLViewerRegionImpl {
public:
LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host)
@@ -158,6 +161,7 @@ public:
LLUUID mCacheID;
CapabilityMap mCapabilities;
CapabilityMap mSecondCapabilitiesTracker;
LLEventPoll* mEventPoll;
@@ -219,15 +223,25 @@ class BaseCapabilitiesComplete : public LLHTTPClient::ResponderWithResult
{
LOG_CLASS(BaseCapabilitiesComplete);
public:
BaseCapabilitiesComplete(U64 region_handle, S32 id)
BaseCapabilitiesComplete(U64 region_handle, S32 id)
: mRegionHandle(region_handle), mID(id)
{ }
{ }
virtual ~BaseCapabilitiesComplete()
{ }
static boost::intrusive_ptr<BaseCapabilitiesComplete> build( U64 region_handle, S32 id )
{
return boost::intrusive_ptr<BaseCapabilitiesComplete>(
new BaseCapabilitiesComplete(region_handle, id) );
}
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return baseCapabilitiesComplete_timeout; }
/*virtual*/ char const* getName(void) const { return "BaseCapabilitiesComplete"; }
private:
void httpFailure(void)
{
LL_WARNS("AppInit", "Capabilities") << mStatus << ": " << mReason << LL_ENDL;
LL_WARNS("AppInit", "Capabilities") << dumpResponse() << LL_ENDL;
LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
if (regionp)
{
@@ -246,15 +260,23 @@ public:
if( mID != regionp->getHttpResponderID() ) // region is no longer referring to this responder
{
LL_WARNS("AppInit", "Capabilities") << "Received results for a stale http responder!" << LL_ENDL;
regionp->failedSeedCapability();
return ;
}
const LLSD& content = getContent();
if (!content.isMap())
{
failureResult(400, "Malformed response contents", content);
return;
}
LLSD::map_const_iterator iter;
for(iter = mContent.beginMap(); iter != mContent.endMap(); ++iter)
for(iter = content.beginMap(); iter != content.endMap(); ++iter)
{
regionp->setCapability(iter->first, iter->second);
LL_DEBUGS("AppInit", "Capabilities") << "got capability for "
<< iter->first << LL_ENDL;
LL_DEBUGS("AppInit", "Capabilities")
<< "Capability '" << iter->first << "' is '" << iter->second << "'" << LL_ENDL;
/* HACK we're waiting for the ServerReleaseNotes */
if (iter->first == "ServerReleaseNotes" && regionp->getReleaseNotesRequested())
@@ -271,20 +293,103 @@ public:
}
}
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return baseCapabilitiesComplete_timeout; }
/*virtual*/ char const* getName(void) const { return "BaseCapabilitiesComplete"; }
static boost::intrusive_ptr<BaseCapabilitiesComplete> build( U64 region_handle, S32 id )
{
return boost::intrusive_ptr<BaseCapabilitiesComplete>(
new BaseCapabilitiesComplete(region_handle, id) );
}
private:
U64 mRegionHandle;
S32 mID;
};
class BaseCapabilitiesCompleteTracker : public LLHTTPClient::ResponderWithResult
{
LOG_CLASS(BaseCapabilitiesCompleteTracker);
public:
BaseCapabilitiesCompleteTracker( U64 region_handle)
: mRegionHandle(region_handle)
{ }
virtual ~BaseCapabilitiesCompleteTracker()
{ }
static boost::intrusive_ptr<BaseCapabilitiesCompleteTracker> build( U64 region_handle )
{
return boost::intrusive_ptr<BaseCapabilitiesCompleteTracker>(
new BaseCapabilitiesCompleteTracker(region_handle));
}
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return baseCapabilitiesCompleteTracker_timeout; }
/*virtual*/ char const* getName(void) const { return "BaseCapabilitiesCompleteTracker"; }
private:
/* virtual */ void httpFailure()
{
LL_WARNS() << dumpResponse() << LL_ENDL;
}
/* virtual */ void httpSuccess()
{
LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
if( !regionp )
{
LL_WARNS("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL;
return ;
}
const LLSD& content = getContent();
if (!content.isMap())
{
failureResult(400, "Malformed response contents", content);
return;
}
LLSD::map_const_iterator iter;
for(iter = content.beginMap(); iter != content.endMap(); ++iter)
{
regionp->setCapabilityDebug(iter->first, iter->second);
//LL_INFOS()<<"BaseCapabilitiesCompleteTracker New Caps "<<iter->first<<" "<< iter->second<<LL_ENDL;
}
if ( regionp->getRegionImpl()->mCapabilities.size() != regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() )
{
LL_WARNS("AppInit", "Capabilities")
<< "Sim sent duplicate base caps that differ in size from what we initially received - most likely content. "
<< "mCapabilities == " << regionp->getRegionImpl()->mCapabilities.size()
<< " mSecondCapabilitiesTracker == " << regionp->getRegionImpl()->mSecondCapabilitiesTracker.size()
<< LL_ENDL;
//#ifdef DEBUG_CAPS_GRANTS
LL_WARNS("AppInit", "Capabilities")
<< "Initial Base capabilities: " << LL_ENDL;
log_capabilities(regionp->getRegionImpl()->mCapabilities);
LL_WARNS("AppInit", "Capabilities")
<< "Latest base capabilities: " << LL_ENDL;
log_capabilities(regionp->getRegionImpl()->mSecondCapabilitiesTracker);
//#endif
if (regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() > regionp->getRegionImpl()->mCapabilities.size() )
{
// *HACK Since we were granted more base capabilities in this grant request than the initial, replace
// the old with the new. This shouldn't happen i.e. we should always get the same capabilities from a
// sim. The simulator fix from SH-3895 should prevent it from happening, at least in the case of the
// inventory api capability grants.
// Need to clear a std::map before copying into it because old keys take precedence.
regionp->getRegionImplNC()->mCapabilities.clear();
regionp->getRegionImplNC()->mCapabilities = regionp->getRegionImpl()->mSecondCapabilitiesTracker;
}
}
else
{
LL_DEBUGS("CrossingCaps") << "Sim sent multiple base cap grants with matching sizes." << LL_ENDL;
}
regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear();
}
private:
U64 mRegionHandle;
};
LLViewerRegion::LLViewerRegion(const U64 &handle,
const LLHost &host,
@@ -1786,6 +1891,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("FetchInventoryDescendents2");
capabilityNames.append("IncrementCOFVersion");
capabilityNames.append("GamingData"); //Used by certain grids.
AISCommand::getCapabilityNames(capabilityNames);
capabilityNames.append("GetDisplayNames");
capabilityNames.append("GetMesh");
capabilityNames.append("GetMesh2"); // Used on SecondLife(tm) sim versions 280647 and higher (13.09.17).
@@ -1851,8 +1957,16 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
void LLViewerRegion::setSeedCapability(const std::string& url)
{
if (getCapability("Seed") == url)
{
// LL_WARNS() << "Ignoring duplicate seed capability" << LL_ENDL;
{
setCapabilityDebug("Seed", url);
LL_DEBUGS("CrossingCaps") << "Received duplicate seed capability, posting to seed " <<
url << LL_ENDL;
//Instead of just returning we build up a second set of seed caps and compare them
//to the "original" seed cap received and determine why there is problem!
LLSD capabilityNames = LLSD::emptyArray();
mImpl->buildCapabilityNames( capabilityNames );
LLHTTPClient::post( url, capabilityNames, BaseCapabilitiesCompleteTracker::build(getHandle() ));
return;
}
@@ -1913,19 +2027,19 @@ void LLViewerRegion::failedSeedCapability()
}
}
class SimulatorFeaturesReceived : public LLHTTPClient::ResponderWithResult
class BaseFeaturesReceived : public LLHTTPClient::ResponderWithResult
{
LOG_CLASS(SimulatorFeaturesReceived);
LOG_CLASS(BaseFeaturesReceived);
public:
SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle,
BaseFeaturesReceived(const std::string& retry_url, U64 region_handle, const char* classname, boost::function<void(LLViewerRegion*, const LLSD&)> fn,
S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS)
: mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts)
: mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts), mClassName(classname), mFunction(fn)
{ }
void httpFailure(void)
{
LL_WARNS("AppInit", "SimulatorFeatures") << mStatus << ": " << mReason << LL_ENDL;
LL_WARNS("AppInit", mClassName) << dumpResponse() << LL_ENDL;
retry();
}
@@ -1934,24 +2048,32 @@ public:
LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
if(!regionp) //region is removed or responder is not created.
{
LL_WARNS("AppInit", "SimulatorFeatures") << "Received results for region that no longer exists!" << LL_ENDL;
LL_WARNS("AppInit", mClassName)
<< "Received results for region that no longer exists!" << LL_ENDL;
return ;
}
regionp->setSimulatorFeatures(mContent);
const LLSD& content = getContent();
if (!content.isMap())
{
failureResult(400, "Malformed response contents", content);
return;
}
mFunction(regionp, content);
}
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return simulatorFeaturesReceived_timeout; }
/*virtual*/ char const* getName(void) const { return "SimulatorFeaturesReceived"; }
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return baseFeaturesReceived_timeout; }
/*virtual*/ char const* getName(void) const { return mClassName; }
private:
void retry()
{
if (mAttempt < mMaxAttempts)
{
mAttempt++;
LL_WARNS("AppInit", "SimulatorFeatures") << "Re-trying '" << mRetryURL << "'. Retry #" << mAttempt << LL_ENDL;
LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this));
LL_WARNS("AppInit", mClassName) << "Re-trying '" << mRetryURL << "'. Retry #" << mAttempt << LL_ENDL;
LLHTTPClient::get(mRetryURL, new BaseFeaturesReceived(*this));
}
}
@@ -1959,49 +2081,10 @@ private:
U64 mRegionHandle;
S32 mAttempt;
S32 mMaxAttempts;
const char* mClassName;
boost::function<void(LLViewerRegion*, const LLSD&)> mFunction;
};
class GamingDataReceived : public LLHTTPClient::ResponderWithResult
{
LOG_CLASS(GamingDataReceived);
public:
GamingDataReceived(const std::string& retry_url, U64 region_handle, S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS)
: mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts)
{}
/*virtual*/ void httpFailure(void)
{
LL_WARNS("AppInit", "GamingData") << mStatus << ": " << mReason << LL_ENDL;
retry();
}
/*virtual*/ void httpSuccess(void)
{
LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
if(regionp) regionp->setGamingData(mContent);
}
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return gamingDataReceived_timeout; }
/*virtual*/ char const* getName(void) const { return "GamingDataReceived"; }
private:
void retry()
{
if (mAttempt < mMaxAttempts)
{
mAttempt++;
LL_WARNS("AppInit", "GamingData") << "Retrying '" << mRetryURL << "'. Retry #" << mAttempt << LL_ENDL;
LLHTTPClient::get(mRetryURL, new GamingDataReceived(*this));
}
}
std::string mRetryURL;
U64 mRegionHandle;
S32 mAttempt;
S32 mMaxAttempts;
};
void LLViewerRegion::setCapability(const std::string& name, const std::string& url)
{
if(name == "EventQueueGet")
@@ -2020,13 +2103,13 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
mImpl->mCapabilities[name] = url;
// kick off a request for simulator features
LLHTTPClient::get(url, new SimulatorFeaturesReceived(url, getHandle()));
LLHTTPClient::get(url, new BaseFeaturesReceived(url, getHandle(), "SimulatorFeaturesReceived", &LLViewerRegion::setSimulatorFeatures));
}
else if (name == "GamingData")
{
LLSD gamingRequest = LLSD::emptyMap();
// request settings from simulator
LLHTTPClient::post(url, gamingRequest, new GamingDataReceived(url, getHandle()));
LLHTTPClient::post(url, gamingRequest, new BaseFeaturesReceived(url, getHandle(), "GamingDataReceived", &LLViewerRegion::setGamingData));
}
else
{
@@ -2038,6 +2121,20 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
}
}
void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::string& url)
{
// Continue to not add certain caps, as we do in setCapability. This is so they match up when we check them later.
if ( ! ( name == "EventQueueGet" || name == "UntrustedSimulatorMessage" || name == "SimulatorFeatures" ) )
{
mImpl->mSecondCapabilitiesTracker[name] = url;
if(name == "GetTexture")
{
mHttpUrl = url ;
}
}
}
bool LLViewerRegion::isSpecialCapabilityName(const std::string &name)
{
return name == "EventQueueGet" || name == "UntrustedSimulatorMessage";
@@ -2047,7 +2144,7 @@ std::string LLViewerRegion::getCapability(const std::string& name) const
{
if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia")))
{
LL_WARNS() << "getCapability("<<name<<") called before caps received" << LL_ENDL;
LL_WARNS() << "getCapability called before caps received for " << name << LL_ENDL;
}
CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name);
@@ -2059,6 +2156,22 @@ std::string LLViewerRegion::getCapability(const std::string& name) const
return iter->second;
}
bool LLViewerRegion::isCapabilityAvailable(const std::string& name) const
{
if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia")))
{
LL_WARNS() << "isCapabilityAvailable called before caps received for " << name << LL_ENDL;
}
CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name);
if(iter == mImpl->mCapabilities.end())
{
return false;
}
return true;
}
bool LLViewerRegion::capabilitiesReceived() const
{
return mCapabilitiesReceived;
@@ -2210,7 +2323,21 @@ bool LLViewerRegion::avatarHoverHeightEnabled() const
return ( mSimulatorFeatures.has("AvatarHoverHeightEnabled") &&
mSimulatorFeatures["AvatarHoverHeightEnabled"].asBoolean());
}
/* Static Functions */
void log_capabilities(const CapabilityMap &capmap)
{
S32 count = 0;
CapabilityMap::const_iterator iter;
for (iter = capmap.begin(); iter != capmap.end(); ++iter, ++count)
{
if (!iter->second.empty())
{
LL_INFOS() << "log_capabilities: " << iter->first << " URL is " << iter->second << LL_ENDL;
}
}
LL_INFOS() << "log_capabilities: Dumped " << count << " entries." << LL_ENDL;
}
void LLViewerRegion::resetMaterialsCapThrottle()
{
F32 requests_per_sec = 1.0f; // original default;