diff options
| -rw-r--r-- | indra/newview/llstartup.cpp | 19 | ||||
| -rw-r--r-- | indra/newview/llviewerregion.cpp | 223 | ||||
| -rw-r--r-- | indra/newview/llviewerregion.h | 7 | ||||
| -rw-r--r-- | indra/newview/llvoavatar.cpp | 5 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/strings.xml | 2 | 
5 files changed, 164 insertions, 92 deletions
| diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 4dfcb85295..46ff3d808a 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -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;  	} diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 5b7492b66f..5be2234ec2 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -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) -		{ -			std::string url = mRegion->getCapability("Seed"); - -			mRetry++; - -			llinfos << "retry " << mRetry << " posting to seed " << url << llendl; - -			mRegion->setSeedCapability(url, mRetry); -		} -		else +		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); +		if (regionp)  		{ -			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() -{ -	mImpl->mHttpResponderPtr = NULL; -} - -const LLHTTPClient::ResponderPtr LLViewerRegion::getHttpResponderPtr() const +S32 LLViewerRegion::getHttpResponderID() 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) -{ -	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(); +void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) +{  	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);  	} -	 -    static boost::intrusive_ptr<SimulatorFeaturesReceived> build( -																 LLViewerRegion* region) -    { -		return boost::intrusive_ptr<SimulatorFeaturesReceived>( -															   new SimulatorFeaturesReceived(region)); -    } -	 +  private: -	LLViewerRegion* mRegion; +	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); +		} +	} +	 +	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  	{ diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 0176969cea..b3c19ea58d 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -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; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 5c977492d8..b5be3cd552 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -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))  	{ diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 022c97f341..cb371edacf 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -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> | 
