Potential fix for SH-1854 and SH-1125 (caps issues)

meow-7.2.2
Don Kjer 2011-07-14 18:43:49 -07:00
parent 4e61870f3a
commit fde88ae24d
5 changed files with 164 additions and 92 deletions

View File

@ -1242,6 +1242,25 @@ bool idle_startup()
//---------------------------------------------------------------------
if(STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
{
LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle);
if (regionp->capabilitiesReceived())
{
LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
}
else
{
U32 num_retries = regionp->getNumSeedCapRetries();
if (num_retries > 0)
{
LLStringUtil::format_map_t args;
args["[NUMBER]"] = llformat("%d", num_retries + 1);
set_startup_status(0.4f, LLTrans::getString("LoginRetrySeedCapGrant", args), gAgent.mMOTD);
}
else
{
set_startup_status(0.4f, LLTrans::getString("LoginRequestSeedCapGrant"), gAgent.mMOTD);
}
}
return FALSE;
}

View File

@ -77,6 +77,13 @@
const F32 WATER_TEXTURE_SCALE = 8.f; // Number of times to repeat the water texture across a region
const S16 MAX_MAP_DIST = 10;
// The server only keeps our pending agent info for 60 seconds.
// We want to allow for seed cap retry, but its not useful after that 60 seconds.
// Give it 3 chances, each at 18 seconds to give ourselves a few seconds to connect anyways if we give up.
const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN = 3;
const F32 CAP_REQUEST_TIMEOUT = 18;
// Even though we gave up on login, keep trying for caps after we are logged in:
const S32 MAX_CAP_REQUEST_ATTEMPTS = 30;
typedef std::map<std::string, std::string> CapabilityMap;
@ -86,6 +93,10 @@ public:
: mHost(host),
mCompositionp(NULL),
mEventPoll(NULL),
mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS),
mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN),
mSeedCapAttempts(0),
mHttpResponderID(0),
// I'd prefer to set the LLCapabilityListener name to match the region
// name -- it's disappointing that's not available at construction time.
// We could instead store an LLCapabilityListener*, making
@ -100,6 +111,8 @@ public:
{
}
void buildCapabilityNames(LLSD& capabilityNames);
// The surfaces and other layers
LLSurface* mLandp;
@ -132,6 +145,12 @@ public:
LLEventPoll* mEventPoll;
S32 mSeedCapMaxAttempts;
S32 mSeedCapMaxAttemptsBeforeLogin;
S32 mSeedCapAttempts;
S32 mHttpResponderID;
/// Post an event to this LLCapabilityListener to invoke a capability message on
/// this LLViewerRegion's server
/// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
@ -139,8 +158,6 @@ public:
//spatial partitions for objects in this region
std::vector<LLSpatialPartition*> mObjectPartition;
LLHTTPClient::ResponderPtr mHttpResponderPtr ;
};
// support for secondlife:///app/region/{REGION} SLapps
@ -186,69 +203,51 @@ class BaseCapabilitiesComplete : public LLHTTPClient::Responder
{
LOG_CLASS(BaseCapabilitiesComplete);
public:
BaseCapabilitiesComplete(LLViewerRegion* region, S32 retry = 0)
: mRegion(region), mRetry(retry)
BaseCapabilitiesComplete(U64 region_handle, S32 id)
: mRegionHandle(region_handle), mID(id)
{ }
virtual ~BaseCapabilitiesComplete()
{
if(mRegion)
{
mRegion->setHttpResponderPtrNULL() ;
}
}
void setRegion(LLViewerRegion* region)
{
mRegion = region ;
}
{ }
void error(U32 statusNum, const std::string& reason)
{
LL_WARNS2("AppInit", "Capabilities") << statusNum << ": " << reason << LL_ENDL;
const S32 MAX_RETRIES = 5;
if (mRetry < MAX_RETRIES)
LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
if (regionp)
{
std::string url = mRegion->getCapability("Seed");
mRetry++;
llinfos << "retry " << mRetry << " posting to seed " << url << llendl;
mRegion->setSeedCapability(url, mRetry);
}
else
{
if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
{
LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
}
regionp->failedSeedCapability();
}
}
void result(const LLSD& content)
{
if(!mRegion || LLHTTPClient::ResponderPtr(this) != mRegion->getHttpResponderPtr()) //region is removed or responder is not created.
LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
if(!regionp) //region was removed
{
LL_WARNS2("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL;
return ;
}
if( mID != regionp->getHttpResponderID() ) // region is no longer referring to this responder
{
LL_WARNS2("AppInit", "Capabilities") << "Received results for a stale http responder!" << LL_ENDL;
return ;
}
LLSD::map_const_iterator iter;
for(iter = content.beginMap(); iter != content.endMap(); ++iter)
{
mRegion->setCapability(iter->first, iter->second);
regionp->setCapability(iter->first, iter->second);
LL_DEBUGS2("AppInit", "Capabilities") << "got capability for "
<< iter->first << LL_ENDL;
/* HACK we're waiting for the ServerReleaseNotes */
if (iter->first == "ServerReleaseNotes" && mRegion->getReleaseNotesRequested())
if (iter->first == "ServerReleaseNotes" && regionp->getReleaseNotesRequested())
{
mRegion->showReleaseNotes();
regionp->showReleaseNotes();
}
}
mRegion->setCapabilitiesReceived(true);
regionp->setCapabilitiesReceived(true);
if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
{
@ -256,16 +255,15 @@ public:
}
}
static boost::intrusive_ptr<BaseCapabilitiesComplete> build(
LLViewerRegion* region, S32 retry)
static boost::intrusive_ptr<BaseCapabilitiesComplete> build( U64 region_handle, S32 id )
{
return boost::intrusive_ptr<BaseCapabilitiesComplete>(
new BaseCapabilitiesComplete(region, retry));
return boost::intrusive_ptr<BaseCapabilitiesComplete>(
new BaseCapabilitiesComplete(region_handle, id) );
}
private:
LLViewerRegion* mRegion;
S32 mRetry;
U64 mRegionHandle;
S32 mID;
};
@ -356,11 +354,6 @@ void LLViewerRegion::initStats()
LLViewerRegion::~LLViewerRegion()
{
if(mImpl->mHttpResponderPtr)
{
(static_cast<BaseCapabilitiesComplete*>(mImpl->mHttpResponderPtr.get()))->setRegion(NULL) ;
}
gVLManager.cleanupData(this);
// Can't do this on destruction, because the neighbor pointers might be invalid.
// This should be reference counted...
@ -907,14 +900,9 @@ U32 LLViewerRegion::getPacketsLost() const
}
}
void LLViewerRegion::setHttpResponderPtrNULL()
S32 LLViewerRegion::getHttpResponderID() const
{
mImpl->mHttpResponderPtr = NULL;
}
const LLHTTPClient::ResponderPtr LLViewerRegion::getHttpResponderPtr() const
{
return mImpl->mHttpResponderPtr;
return mImpl->mHttpResponderID;
}
BOOL LLViewerRegion::pointInRegionGlobal(const LLVector3d &point_global) const
@ -1493,22 +1481,9 @@ void LLViewerRegion::unpackRegionHandshake()
msg->sendReliable(host);
}
void LLViewerRegion::setSeedCapability(const std::string& url, S32 retry)
void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
{
if (retry == 0 && getCapability("Seed") == url)
{
// llwarns << "Ignoring duplicate seed capability" << llendl;
return;
}
delete mImpl->mEventPoll;
mImpl->mEventPoll = NULL;
mImpl->mCapabilities.clear();
setCapability("Seed", url);
LLSD capabilityNames = LLSD::emptyArray();
capabilityNames.append("AccountingParcel");
capabilityNames.append("AccountingSelection");
capabilityNames.append("AttachmentResources");
@ -1582,46 +1557,118 @@ void LLViewerRegion::setSeedCapability(const std::string& url, S32 retry)
// Please add new capabilities alphabetically to reduce
// merge conflicts.
}
void LLViewerRegion::setSeedCapability(const std::string& url)
{
if (getCapability("Seed") == url)
{
// llwarns << "Ignoring duplicate seed capability" << llendl;
return;
}
delete mImpl->mEventPoll;
mImpl->mEventPoll = NULL;
mImpl->mCapabilities.clear();
setCapability("Seed", url);
LLSD capabilityNames = LLSD::emptyArray();
mImpl->buildCapabilityNames(capabilityNames);
llinfos << "posting to seed " << url << llendl;
mImpl->mHttpResponderPtr = BaseCapabilitiesComplete::build(this, retry) ;
LLHTTPClient::post(url, capabilityNames, mImpl->mHttpResponderPtr);
S32 id = ++mImpl->mHttpResponderID;
LLHTTPClient::post(url, capabilityNames,
BaseCapabilitiesComplete::build(getHandle(), id),
LLSD(), CAP_REQUEST_TIMEOUT);
}
S32 LLViewerRegion::getNumSeedCapRetries()
{
return mImpl->mSeedCapAttempts;
}
void LLViewerRegion::failedSeedCapability()
{
// Should we retry asking for caps?
mImpl->mSeedCapAttempts++;
std::string url = getCapability("Seed");
if ( url.empty() )
{
LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url for retries!" << LL_ENDL;
return;
}
// After a few attempts, continue login. We will keep trying once in-world:
if ( mImpl->mSeedCapAttempts >= mImpl->mSeedCapMaxAttemptsBeforeLogin &&
STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState() )
{
LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
}
if ( mImpl->mSeedCapAttempts < mImpl->mSeedCapMaxAttempts)
{
LLSD capabilityNames = LLSD::emptyArray();
mImpl->buildCapabilityNames(capabilityNames);
llinfos << "posting to seed " << url << " (retry "
<< mImpl->mSeedCapAttempts << ")" << llendl;
S32 id = ++mImpl->mHttpResponderID;
LLHTTPClient::post(url, capabilityNames,
BaseCapabilitiesComplete::build(getHandle(), id),
LLSD(), CAP_REQUEST_TIMEOUT);
}
else
{
// *TODO: Give a user pop-up about this error?
LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities from '" << url << "' after " << mImpl->mSeedCapAttempts << " attempts. Giving up!" << LL_ENDL;
}
}
class SimulatorFeaturesReceived : public LLHTTPClient::Responder
{
LOG_CLASS(SimulatorFeaturesReceived);
public:
SimulatorFeaturesReceived(LLViewerRegion* region)
: mRegion(region)
SimulatorFeaturesReceived(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)
{ }
void error(U32 statusNum, const std::string& reason)
{
LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL;
retry();
}
void result(const LLSD& content)
{
if(!mRegion) //region is removed or responder is not created.
LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
if(!regionp) //region is removed or responder is not created.
{
LL_WARNS2("AppInit", "SimulatorFeatures") << "Received results for region that no longer exists!" << LL_ENDL;
return ;
}
mRegion->setSimulatorFeatures(content);
regionp->setSimulatorFeatures(content);
}
private:
void retry()
{
if (mAttempt < mMaxAttempts)
{
mAttempt++;
LL_WARNS2("AppInit", "SimulatorFeatures") << "Re-trying '" << mRetryURL << "'. Retry #" << mAttempt << LL_ENDL;
LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this), LLSD(), CAP_REQUEST_TIMEOUT);
}
}
static boost::intrusive_ptr<SimulatorFeaturesReceived> build(
LLViewerRegion* region)
{
return boost::intrusive_ptr<SimulatorFeaturesReceived>(
new SimulatorFeaturesReceived(region));
}
private:
LLViewerRegion* mRegion;
std::string mRetryURL;
U64 mRegionHandle;
S32 mAttempt;
S32 mMaxAttempts;
};
@ -1640,7 +1687,7 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
else if (name == "SimulatorFeatures")
{
// kick off a request for simulator features
LLHTTPClient::get(url, new SimulatorFeaturesReceived(this));
LLHTTPClient::get(url, new SimulatorFeaturesReceived(url, getHandle()), LLSD(), CAP_REQUEST_TIMEOUT);
}
else
{

View File

@ -226,11 +226,12 @@ public:
U32 getPacketsLost() const;
void setHttpResponderPtrNULL();
const LLHTTPClient::ResponderPtr getHttpResponderPtr() const;
S32 getHttpResponderID() const;
// Get/set named capability URLs for this region.
void setSeedCapability(const std::string& url, S32 retry = 0);
void setSeedCapability(const std::string& url);
void failedSeedCapability();
S32 getNumSeedCapRetries();
void setCapability(const std::string& name, const std::string& url);
// implements LLCapabilityProvider
virtual std::string getCapability(const std::string& name) const;

View File

@ -1133,7 +1133,10 @@ void LLVOAvatar::initClass()
llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl;
}
// parse avatar_lad.xml
llassert(!sAvatarXmlInfo);
if (sAvatarXmlInfo)
{ //this can happen if a login attempt failed
deleteAndClear(sAvatarXmlInfo);
}
sAvatarXmlInfo = new LLVOAvatarXmlInfo;
if (!sAvatarXmlInfo->parseXmlSkeletonNode(root))
{

View File

@ -43,6 +43,8 @@
<string name="LoginInitializingQuicktime">Initializing QuickTime...</string>
<string name="LoginQuicktimeNotFound">QuickTime not found - unable to initialize.</string>
<string name="LoginQuicktimeOK">QuickTime initialized successfully.</string>
<string name="LoginRequestSeedCapGrant">Requesting region capabilities...</string>
<string name="LoginRetrySeedCapGrant">Requesting region capabilities, attempt [NUMBER]...</string>
<string name="LoginWaitingForRegionHandshake">Waiting for region handshake...</string>
<string name="LoginConnectingToRegion">Connecting to region...</string>
<string name="LoginDownloadingClothing">Downloading clothing...</string>