From aa3042ea331479128a65d890d44314cc7c630e2c Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Fri, 14 Aug 2015 16:45:26 -0700 Subject: MAINT-5506: Converted llmessage untrusted sim message responder to coroutine. Removed HTTPSender, HTTPNullSender, HTTPCapSender. Moved UntrustedMessageCap storage into LLHost Added boost libraries to PROJECT_x_TEST linkage. --- indra/newview/llstartup.cpp | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 6622fa7d9c..8f856b1300 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -56,7 +56,6 @@ #include "llerrorcontrol.h" #include "llfloaterreg.h" #include "llfocusmgr.h" -#include "llhttpsender.h" #include "llfloaterimsession.h" #include "lllocationhistory.h" #include "llimageworker.h" @@ -291,20 +290,6 @@ void callback_cache_name(const LLUUID& id, const std::string& full_name, bool is // local classes // -namespace -{ - class LLNullHTTPSender : public LLHTTPSender - { - virtual void send(const LLHost& host, - const std::string& message, const LLSD& body, - LLHTTPClient::ResponderPtr response) const - { - LL_WARNS("AppInit") << " attemped to send " << message << " to " << host - << " with null sender" << LL_ENDL; - } - }; -} - void update_texture_fetch() { LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread @@ -510,8 +495,6 @@ bool idle_startup() port = gSavedSettings.getU32("ConnectionPort"); } - LLHTTPSender::setDefaultSender(new LLNullHTTPSender()); - // TODO parameterize const F32 circuit_heartbeat_interval = 5; const F32 circuit_timeout = 100; -- cgit v1.3 From 99e56eedabfe34dbfbfd8105759403173de72d44 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Fri, 28 Aug 2015 16:55:33 -0700 Subject: MAINT-5575: Begin conversion to Singleton<> for Experience Cache. Commited on branch so that I don't trigger a build of it until I'm ready. --HG-- branch : MAINT-5575 --- indra/llmessage/llexperiencecache.cpp | 925 +++++++++++++++++----------------- indra/llmessage/llexperiencecache.h | 67 ++- indra/newview/llstartup.cpp | 5 +- 3 files changed, 515 insertions(+), 482 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp index 52b60a176e..d196d7da93 100644 --- a/indra/llmessage/llexperiencecache.cpp +++ b/indra/llmessage/llexperiencecache.cpp @@ -34,608 +34,613 @@ #include "boost/tokenizer.hpp" -namespace LLExperienceCache -{ +typedef std::map KeyMap; +KeyMap privateToPublicKeyMap; - typedef std::map KeyMap; - KeyMap privateToPublicKeyMap; +void mapKeys(const LLSD& legacyKeys); - void mapKeys(const LLSD& legacyKeys); +std::string sLookupURL; - std::string sLookupURL; +typedef std::map ask_queue_t; +ask_queue_t sAskQueue; - typedef std::map ask_queue_t; - ask_queue_t sAskQueue; +typedef std::map pending_queue_t; +pending_queue_t sPendingQueue; - typedef std::map pending_queue_t; - pending_queue_t sPendingQueue; +LLExperienceCache::cache_t sCache; +int sMaximumLookups = 10; - cache_t sCache; - int sMaximumLookups = 10; +LLFrameTimer sRequestTimer; - LLFrameTimer sRequestTimer; +// Periodically clean out expired entries from the cache +LLFrameTimer sEraseExpiredTimer; - // Periodically clean out expired entries from the cache - LLFrameTimer sEraseExpiredTimer; +// May have multiple callbacks for a single ID, which are +// represented as multiple slots bound to the signal. +// Avoid copying signals via pointers. +typedef std::map signal_map_t; +signal_map_t sSignalMap; - // May have multiple callbacks for a single ID, which are - // represented as multiple slots bound to the signal. - // Avoid copying signals via pointers. - typedef std::map signal_map_t; - signal_map_t sSignalMap; +bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age); +void eraseExpired(); - bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age); - void eraseExpired(); +//========================================================================= +LLExperienceCache::LLExperienceCache() +{ +} - void processExperience( const LLUUID& public_key, const LLSD& experience ) - { - sCache[public_key]=experience; - LLSD & row = sCache[public_key]; +LLExperienceCache::~LLExperienceCache() +{ +} - if(row.has(EXPIRES)) - { - row[EXPIRES] = row[EXPIRES].asReal() + LLFrameTimer::getTotalSeconds(); - } +//------------------------------------------------------------------------- +void LLExperienceCache::importFile(std::istream& istr) +{ + LLSD data; + S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr); + if (parse_count < 1) return; - if(row.has(EXPERIENCE_ID)) - { - sPendingQueue.erase(row[EXPERIENCE_ID].asUUID()); - } + LLSD experiences = data["experiences"]; - //signal - signal_map_t::iterator sig_it = sSignalMap.find(public_key); - if (sig_it != sSignalMap.end()) - { - callback_signal_t* signal = sig_it->second; - (*signal)(experience); + LLUUID public_key; + LLSD::map_const_iterator it = experiences.beginMap(); + for (; it != experiences.endMap(); ++it) + { + public_key.set(it->first); + sCache[public_key] = it->second; + } - sSignalMap.erase(public_key); + LL_DEBUGS("ExperienceCache") << "importFile() loaded " << sCache.size() << LL_ENDL; +} - delete signal; - } - } +void LLExperienceCache::exportFile(std::ostream& ostr) const +{ + LLSD experiences; - void initClass( ) - { - } + cache_t::const_iterator it = sCache.begin(); + for (; it != sCache.end(); ++it) + { + if (!it->second.has(EXPERIENCE_ID) || it->second[EXPERIENCE_ID].asUUID().isNull() || + it->second.has("DoesNotExist") || (it->second.has(PROPERTIES) && it->second[PROPERTIES].asInteger() & PROPERTY_INVALID)) + continue; - const cache_t& getCached() + experiences[it->first.asString()] = it->second; + } + + LLSD data; + data["experiences"] = experiences; + + LLSDSerialize::toPrettyXML(data, ostr); +} + +// *TODO$: Rider: These three functions not seem to be used... it may be useful in testing. +void LLExperienceCache::bootstrap(const LLSD& legacyKeys, int initialExpiration) +{ + mapKeys(legacyKeys); + LLSD::array_const_iterator it = legacyKeys.beginArray(); + for (/**/; it != legacyKeys.endArray(); ++it) + { + LLSD experience = *it; + if (experience.has(EXPERIENCE_ID)) + { + if (!experience.has(EXPIRES)) + { + experience[EXPIRES] = initialExpiration; + } + processExperience(experience[EXPERIENCE_ID].asUUID(), experience); + } + else + { + LL_WARNS("ExperienceCache") + << "Skipping bootstrap entry which is missing " << EXPERIENCE_ID + << LL_ENDL; + } + } +} + +void LLExperienceCache::mapKeys(const LLSD& legacyKeys) +{ + LLSD::array_const_iterator exp = legacyKeys.beginArray(); + for (/**/; exp != legacyKeys.endArray(); ++exp) + { + if (exp->has(LLExperienceCache::EXPERIENCE_ID) && exp->has(LLExperienceCache::PRIVATE_KEY)) + { + privateToPublicKeyMap[(*exp)[LLExperienceCache::PRIVATE_KEY].asUUID()] = (*exp)[LLExperienceCache::EXPERIENCE_ID].asUUID(); + } + } +} + +LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_if_not_found) +{ + if (private_key.isNull()) + return LLUUID::null; + + KeyMap::const_iterator it = privateToPublicKeyMap.find(private_key); + if (it == privateToPublicKeyMap.end()) + { + if (null_if_not_found) + { + return LLUUID::null; + } + return private_key; + } + LL_WARNS("LLExperience") << "converted private key " << private_key << " to experience_id " << it->second << LL_ENDL; + return it->second; +} + +//========================================================================= +void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD& experience) +{ + sCache[public_key]=experience; + LLSD & row = sCache[public_key]; + + if(row.has(EXPIRES)) { - return sCache; + row[EXPIRES] = row[EXPIRES].asReal() + LLFrameTimer::getTotalSeconds(); } - void setMaximumLookups( int maximumLookups) + if(row.has(EXPERIENCE_ID)) { - sMaximumLookups = maximumLookups; + sPendingQueue.erase(row[EXPERIENCE_ID].asUUID()); } - void bootstrap(const LLSD& legacyKeys, int initialExpiration) + //signal + signal_map_t::iterator sig_it = sSignalMap.find(public_key); + if (sig_it != sSignalMap.end()) { - mapKeys(legacyKeys); - LLSD::array_const_iterator it = legacyKeys.beginArray(); - for(/**/; it != legacyKeys.endArray(); ++it) - { - LLSD experience = *it; - if(experience.has(EXPERIENCE_ID)) - { - if(!experience.has(EXPIRES)) - { - experience[EXPIRES] = initialExpiration; - } - processExperience(experience[EXPERIENCE_ID].asUUID(), experience); - } - else - { - LL_WARNS("ExperienceCache") - << "Skipping bootstrap entry which is missing " << EXPERIENCE_ID - << LL_ENDL; - } - } + callback_signal_t* signal = sig_it->second; + (*signal)(experience); + + sSignalMap.erase(public_key); + + delete signal; } +} +const LLExperienceCache::cache_t& LLExperienceCache::getCached() +{ + return sCache; +} + +void LLExperienceCache::setMaximumLookups(int maximumLookups) +{ + sMaximumLookups = maximumLookups; +} - bool expirationFromCacheControl(LLSD headers, F64 *expires) +bool LLExperienceCache::expirationFromCacheControl(LLSD headers, F64 *expires) +{ + // Allow the header to override the default + LLSD cache_control_header = headers["cache-control"]; + if (cache_control_header.isDefined()) { - // Allow the header to override the default - LLSD cache_control_header = headers["cache-control"]; - if (cache_control_header.isDefined()) + S32 max_age = 0; + std::string cache_control = cache_control_header.asString(); + if (max_age_from_cache_control(cache_control, &max_age)) { - S32 max_age = 0; - std::string cache_control = cache_control_header.asString(); - if (max_age_from_cache_control(cache_control, &max_age)) - { - LL_WARNS("ExperienceCache") - << "got EXPIRES from headers, max_age " << max_age - << LL_ENDL; - F64 now = LLFrameTimer::getTotalSeconds(); - *expires = now + (F64)max_age; - return true; - } + LL_WARNS("ExperienceCache") + << "got EXPIRES from headers, max_age " << max_age + << LL_ENDL; + F64 now = LLFrameTimer::getTotalSeconds(); + *expires = now + (F64)max_age; + return true; } - return false; } + return false; +} - static const std::string MAX_AGE("max-age"); - static const boost::char_separator EQUALS_SEPARATOR("="); - static const boost::char_separator COMMA_SEPARATOR(","); +static const std::string MAX_AGE("max-age"); +static const boost::char_separator EQUALS_SEPARATOR("="); +static const boost::char_separator COMMA_SEPARATOR(","); + +bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age) +{ + // Split the string on "," to get a list of directives + typedef boost::tokenizer > tokenizer; + tokenizer directives(cache_control, COMMA_SEPARATOR); - bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age) + tokenizer::iterator token_it = directives.begin(); + for ( ; token_it != directives.end(); ++token_it) { - // Split the string on "," to get a list of directives - typedef boost::tokenizer > tokenizer; - tokenizer directives(cache_control, COMMA_SEPARATOR); + // Tokens may have leading or trailing whitespace + std::string token = *token_it; + LLStringUtil::trim(token); - tokenizer::iterator token_it = directives.begin(); - for ( ; token_it != directives.end(); ++token_it) + if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0) { - // Tokens may have leading or trailing whitespace - std::string token = *token_it; - LLStringUtil::trim(token); - - if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0) + // ...this token starts with max-age, so let's chop it up by "=" + tokenizer subtokens(token, EQUALS_SEPARATOR); + tokenizer::iterator subtoken_it = subtokens.begin(); + + // Must have a token + if (subtoken_it == subtokens.end()) return false; + std::string subtoken = *subtoken_it; + + // Must exactly equal "max-age" + LLStringUtil::trim(subtoken); + if (subtoken != MAX_AGE) return false; + + // Must have another token + ++subtoken_it; + if (subtoken_it == subtokens.end()) return false; + subtoken = *subtoken_it; + + // Must be a valid integer + // *NOTE: atoi() returns 0 for invalid values, so we have to + // check the string first. + // *TODO: Do servers ever send "0000" for zero? We don't handle it + LLStringUtil::trim(subtoken); + if (subtoken == "0") { - // ...this token starts with max-age, so let's chop it up by "=" - tokenizer subtokens(token, EQUALS_SEPARATOR); - tokenizer::iterator subtoken_it = subtokens.begin(); - - // Must have a token - if (subtoken_it == subtokens.end()) return false; - std::string subtoken = *subtoken_it; - - // Must exactly equal "max-age" - LLStringUtil::trim(subtoken); - if (subtoken != MAX_AGE) return false; - - // Must have another token - ++subtoken_it; - if (subtoken_it == subtokens.end()) return false; - subtoken = *subtoken_it; - - // Must be a valid integer - // *NOTE: atoi() returns 0 for invalid values, so we have to - // check the string first. - // *TODO: Do servers ever send "0000" for zero? We don't handle it - LLStringUtil::trim(subtoken); - if (subtoken == "0") - { - *max_age = 0; - return true; - } - S32 val = atoi( subtoken.c_str() ); - if (val > 0 && val < S32_MAX) - { - *max_age = val; - return true; - } - return false; + *max_age = 0; + return true; } + S32 val = atoi( subtoken.c_str() ); + if (val > 0 && val < S32_MAX) + { + *max_age = val; + return true; + } + return false; } - return false; } + return false; +} - void importFile(std::istream& istr) +class LLExperienceResponder : public LLHTTPClient::Responder +{ +public: + LLExperienceResponder(const ask_queue_t& keys) + :mKeys(keys) { - LLSD data; - S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr); - if(parse_count < 1) return; - - LLSD experiences = data["experiences"]; - LLUUID public_key; - LLSD::map_const_iterator it = experiences.beginMap(); - for(; it != experiences.endMap() ; ++it) - { - public_key.set(it->first); - sCache[public_key]=it->second; - } - - LL_DEBUGS("ExperienceCache") << "importFile() loaded " << sCache.size() << LL_ENDL; } - void exportFile(std::ostream& ostr) + /*virtual*/ void httpCompleted() { - LLSD experiences; - - cache_t::const_iterator it =sCache.begin(); - for( ; it != sCache.end() ; ++it) + LLSD experiences = getContent()["experience_keys"]; + LLSD::array_const_iterator it = experiences.beginArray(); + for( /**/ ; it != experiences.endArray(); ++it) { - if(!it->second.has(EXPERIENCE_ID) || it->second[EXPERIENCE_ID].asUUID().isNull() || - it->second.has("DoesNotExist") || (it->second.has(PROPERTIES) && it->second[PROPERTIES].asInteger() & PROPERTY_INVALID)) - continue; + const LLSD& row = *it; + LLUUID public_key = row[EXPERIENCE_ID].asUUID(); - experiences[it->first.asString()] = it->second; - } - LLSD data; - data["experiences"] = experiences; + LL_DEBUGS("ExperienceCache") << "Received result for " << public_key + << " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL ; - LLSDSerialize::toPrettyXML(data, ostr); - } + processExperience(public_key, row); + } - class LLExperienceResponder : public LLHTTPClient::Responder - { - public: - LLExperienceResponder(const ask_queue_t& keys) - :mKeys(keys) + LLSD error_ids = getContent()["error_ids"]; + LLSD::array_const_iterator errIt = error_ids.beginArray(); + for( /**/ ; errIt != error_ids.endArray() ; ++errIt ) { - + LLUUID id = errIt->asUUID(); + LLSD exp; + exp[EXPIRES]=DEFAULT_EXPIRATION; + exp[EXPERIENCE_ID] = id; + exp[PROPERTIES]=PROPERTY_INVALID; + exp[MISSING]=true; + exp[QUOTA] = DEFAULT_QUOTA; + + processExperience(id, exp); + LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL ; } - /*virtual*/ void httpCompleted() + LL_DEBUGS("ExperienceCache") << sCache.size() << " cached experiences" << LL_ENDL; + } + + /*virtual*/ void httpFailure() + { + LL_WARNS("ExperienceCache") << "Request failed "<first); + //leave the properties alone if we already have a cache entry for this xp + if(exp.isUndefined()) + { + exp[PROPERTIES]=PROPERTY_INVALID; + } + exp[EXPIRES]=retry_timestamp; + exp[EXPERIENCE_ID] = it->first; + exp["key_type"] = it->second; + exp["uuid"] = it->first; + exp["error"] = (LLSD::Integer)getStatus(); + exp[QUOTA] = DEFAULT_QUOTA; + + LLExperienceCache::processExperience(it->first, exp); + } - LL_DEBUGS("ExperienceCache") << "Received result for " << public_key - << " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL ; + } - processExperience(public_key, row); - } + // Return time to retry a request that generated an error, based on + // error type and headers. Return value is seconds-since-epoch. + F64 errorRetryTimestamp(S32 status) + { - LLSD error_ids = getContent()["error_ids"]; - LLSD::array_const_iterator errIt = error_ids.beginArray(); - for( /**/ ; errIt != error_ids.endArray() ; ++errIt ) + // Retry-After takes priority + LLSD retry_after = getResponseHeaders()["retry-after"]; + if (retry_after.isDefined()) + { + // We only support the delta-seconds type + S32 delta_seconds = retry_after.asInteger(); + if (delta_seconds > 0) { - LLUUID id = errIt->asUUID(); - LLSD exp; - exp[EXPIRES]=DEFAULT_EXPIRATION; - exp[EXPERIENCE_ID] = id; - exp[PROPERTIES]=PROPERTY_INVALID; - exp[MISSING]=true; - exp[QUOTA] = DEFAULT_QUOTA; - - processExperience(id, exp); - LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL ; + // ...valid delta-seconds + return F64(delta_seconds); } - - LL_DEBUGS("ExperienceCache") << sCache.size() << " cached experiences" << LL_ENDL; } - /*virtual*/ void httpFailure() + // If no Retry-After, look for Cache-Control max-age + F64 expires = 0.0; + if (LLExperienceCache::expirationFromCacheControl(getResponseHeaders(), &expires)) { - LL_WARNS("ExperienceCache") << "Request failed "<first); - //leave the properties alone if we already have a cache entry for this xp - if(exp.isUndefined()) - { - exp[PROPERTIES]=PROPERTY_INVALID; - } - exp[EXPIRES]=retry_timestamp; - exp[EXPERIENCE_ID] = it->first; - exp["key_type"] = it->second; - exp["uuid"] = it->first; - exp["error"] = (LLSD::Integer)getStatus(); - exp[QUOTA] = DEFAULT_QUOTA; - - LLExperienceCache::processExperience(it->first, exp); - } - + return expires; } - // Return time to retry a request that generated an error, based on - // error type and headers. Return value is seconds-since-epoch. - F64 errorRetryTimestamp(S32 status) + // No information in header, make a guess + if (status == 503) { + // ...service unavailable, retry soon + const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min + return SERVICE_UNAVAILABLE_DELAY; + } + else if (status == 499) + { + // ...we were probably too busy, retry quickly + const F64 BUSY_DELAY = 10.0; // 10 seconds + return BUSY_DELAY; - // Retry-After takes priority - LLSD retry_after = getResponseHeaders()["retry-after"]; - if (retry_after.isDefined()) - { - // We only support the delta-seconds type - S32 delta_seconds = retry_after.asInteger(); - if (delta_seconds > 0) - { - // ...valid delta-seconds - return F64(delta_seconds); - } - } - - // If no Retry-After, look for Cache-Control max-age - F64 expires = 0.0; - if (LLExperienceCache::expirationFromCacheControl(getResponseHeaders(), &expires)) - { - return expires; - } - - // No information in header, make a guess - if (status == 503) - { - // ...service unavailable, retry soon - const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min - return SERVICE_UNAVAILABLE_DELAY; - } - else if (status == 499) - { - // ...we were probably too busy, retry quickly - const F64 BUSY_DELAY = 10.0; // 10 seconds - return BUSY_DELAY; - - } - else - { - // ...other unexpected error - const F64 DEFAULT_DELAY = 3600.0; // 1 hour - return DEFAULT_DELAY; - } } + else + { + // ...other unexpected error + const F64 DEFAULT_DELAY = 3600.0; // 1 hour + return DEFAULT_DELAY; + } + } - private: - ask_queue_t mKeys; - }; +private: + ask_queue_t mKeys; +}; - void requestExperiences() - { - if(sAskQueue.empty() || sLookupURL.empty()) - return; - F64 now = LLFrameTimer::getTotalSeconds(); +void LLExperienceCache::requestExperiences() +{ + if(sAskQueue.empty() || sLookupURL.empty()) + return; - const U32 EXP_URL_SEND_THRESHOLD = 3000; - const U32 PAGE_SIZE = EXP_URL_SEND_THRESHOLD/UUID_STR_LENGTH; + F64 now = LLFrameTimer::getTotalSeconds(); - std::ostringstream ostr; + const U32 EXP_URL_SEND_THRESHOLD = 3000; + const U32 PAGE_SIZE = EXP_URL_SEND_THRESHOLD/UUID_STR_LENGTH; - ask_queue_t keys; + std::ostringstream ostr; - ostr << sLookupURL << "?page_size=" << PAGE_SIZE; + ask_queue_t keys; + ostr << sLookupURL << "?page_size=" << PAGE_SIZE; - int request_count = 0; - while(!sAskQueue.empty() && request_count < sMaximumLookups) - { - ask_queue_t::iterator it = sAskQueue.begin(); - const LLUUID& key = it->first; - const std::string& key_type = it->second; - ostr << '&' << key_type << '=' << key.asString() ; + int request_count = 0; + while(!sAskQueue.empty() && request_count < sMaximumLookups) + { + ask_queue_t::iterator it = sAskQueue.begin(); + const LLUUID& key = it->first; + const std::string& key_type = it->second; + + ostr << '&' << key_type << '=' << key.asString() ; - keys[key]=key_type; - request_count++; + keys[key]=key_type; + request_count++; - sPendingQueue[key] = now; + sPendingQueue[key] = now; - if(ostr.tellp() > EXP_URL_SEND_THRESHOLD) - { - LL_DEBUGS("ExperienceCache") << "requestExperiences() query: " << ostr.str() << LL_ENDL; - LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys)); - ostr.clear(); - ostr.str(sLookupURL); - ostr << "?page_size=" << PAGE_SIZE; - keys.clear(); - } - sAskQueue.erase(it); - } - - if(ostr.tellp() > sLookupURL.size()) + if(ostr.tellp() > EXP_URL_SEND_THRESHOLD) { - LL_DEBUGS("ExperienceCache") << "requestExperiences() query 2: " << ostr.str() << LL_ENDL; + LL_DEBUGS("ExperienceCache") << "requestExperiences() query: " << ostr.str() << LL_ENDL; LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys)); + ostr.clear(); + ostr.str(sLookupURL); + ostr << "?page_size=" << PAGE_SIZE; + keys.clear(); } + sAskQueue.erase(it); } - bool isRequestPending(const LLUUID& public_key) + if(ostr.tellp() > sLookupURL.size()) { - bool isPending = false; - const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0; + LL_DEBUGS("ExperienceCache") << "requestExperiences() query 2: " << ostr.str() << LL_ENDL; + LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys)); + } +} - pending_queue_t::const_iterator it = sPendingQueue.find(public_key); - if(it != sPendingQueue.end()) - { - F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS; - isPending = (it->second > expire_time); - } +bool LLExperienceCache::isRequestPending(const LLUUID& public_key) +{ + bool isPending = false; + const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0; + + pending_queue_t::const_iterator it = sPendingQueue.find(public_key); - return isPending; + if(it != sPendingQueue.end()) + { + F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS; + isPending = (it->second > expire_time); } + return isPending; +} + - void setLookupURL( const std::string& lookup_url ) +void LLExperienceCache::setLookupURL(const std::string& lookup_url) +{ + sLookupURL = lookup_url; + if(!sLookupURL.empty()) { - sLookupURL = lookup_url; - if(!sLookupURL.empty()) - { - sLookupURL += "id/"; - } + sLookupURL += "id/"; } +} + +bool LLExperienceCache::hasLookupURL() +{ + return !sLookupURL.empty(); +} - bool hasLookupURL() +void LLExperienceCache::idle() +{ + + const F32 SECS_BETWEEN_REQUESTS = 0.1f; + if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS)) { - return !sLookupURL.empty(); + return; } - void idle() + // Must be large relative to above + const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds + if (sEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) { - - const F32 SECS_BETWEEN_REQUESTS = 0.1f; - if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS)) - { - return; - } - - // Must be large relative to above - const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds - if (sEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) - { - eraseExpired(); - } + eraseExpired(); + } - if(!sAskQueue.empty()) - { - requestExperiences(); - } + if(!sAskQueue.empty()) + { + requestExperiences(); } +} - void erase( const LLUUID& key ) - { - cache_t::iterator it = sCache.find(key); +void LLExperienceCache::erase(const LLUUID& key) +{ + cache_t::iterator it = sCache.find(key); - if(it != sCache.end()) - { - sCache.erase(it); - } + if(it != sCache.end()) + { + sCache.erase(it); } +} - void eraseExpired() +void LLExperienceCache::eraseExpired() +{ + F64 now = LLFrameTimer::getTotalSeconds(); + cache_t::iterator it = sCache.begin(); + while (it != sCache.end()) { - F64 now = LLFrameTimer::getTotalSeconds(); - cache_t::iterator it = sCache.begin(); - while (it != sCache.end()) - { - cache_t::iterator cur = it; - LLSD& exp = cur->second; - ++it; + cache_t::iterator cur = it; + LLSD& exp = cur->second; + ++it; - if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now) + if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now) + { + if(!exp.has(EXPERIENCE_ID)) { - if(!exp.has(EXPERIENCE_ID)) + LL_WARNS("ExperienceCache") << "Removing experience with no id " << LL_ENDL ; + sCache.erase(cur); + } + else + { + LLUUID id = exp[EXPERIENCE_ID].asUUID(); + LLUUID private_key = exp.has(LLExperienceCache::PRIVATE_KEY) ? exp[LLExperienceCache::PRIVATE_KEY].asUUID():LLUUID::null; + if(private_key.notNull() || !exp.has("DoesNotExist")) { - LL_WARNS("ExperienceCache") << "Removing experience with no id " << LL_ENDL ; - sCache.erase(cur); - } - else - { - LLUUID id = exp[EXPERIENCE_ID].asUUID(); - LLUUID private_key = exp.has(LLExperienceCache::PRIVATE_KEY) ? exp[LLExperienceCache::PRIVATE_KEY].asUUID():LLUUID::null; - if(private_key.notNull() || !exp.has("DoesNotExist")) - { - fetch(id, true); - } - else - { - LL_WARNS("ExperienceCache") << "Removing invalid experience " << id << LL_ENDL ; - sCache.erase(cur); - } + fetch(id, true); + } + else + { + LL_WARNS("ExperienceCache") << "Removing invalid experience " << id << LL_ENDL ; + sCache.erase(cur); } } } } +} - bool fetch( const LLUUID& key, bool refresh/* = true*/ ) +bool LLExperienceCache::fetch(const LLUUID& key, bool refresh/* = true*/) +{ + if(!key.isNull() && !isRequestPending(key) && (refresh || sCache.find(key)==sCache.end())) { - if(!key.isNull() && !isRequestPending(key) && (refresh || sCache.find(key)==sCache.end())) - { - LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL ; - sAskQueue[key]=EXPERIENCE_ID; + LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL ; + sAskQueue[key]=EXPERIENCE_ID; - return true; - } - return false; + return true; } + return false; +} - void insert(const LLSD& experience_data ) +void LLExperienceCache::insert(const LLSD& experience_data) +{ + if(experience_data.has(EXPERIENCE_ID)) { - if(experience_data.has(EXPERIENCE_ID)) - { - processExperience(experience_data[EXPERIENCE_ID].asUUID(), experience_data); - } - else - { - LL_WARNS("ExperienceCache") << ": Ignoring cache insert of experience which is missing " << EXPERIENCE_ID << LL_ENDL; - } + processExperience(experience_data[EXPERIENCE_ID].asUUID(), experience_data); } - static LLSD empty; - const LLSD& get(const LLUUID& key) + else { - if(key.isNull()) return empty; - cache_t::const_iterator it = sCache.find(key); - - if (it != sCache.end()) - { - return it->second; - } - - fetch(key); - - return empty; + LL_WARNS("ExperienceCache") << ": Ignoring cache insert of experience which is missing " << EXPERIENCE_ID << LL_ENDL; } - void get( const LLUUID& key, callback_slot_t slot ) - { - if(key.isNull()) return; - - cache_t::const_iterator it = sCache.find(key); - if (it != sCache.end()) - { - // ...name already exists in cache, fire callback now - callback_signal_t signal; - signal.connect(slot); - - signal(it->second); - return; - } +} - fetch(key); +static LLSD empty; +const LLSD& LLExperienceCache::get(const LLUUID& key) +{ + if(key.isNull()) return empty; + cache_t::const_iterator it = sCache.find(key); - // always store additional callback, even if request is pending - signal_map_t::iterator sig_it = sSignalMap.find(key); - if (sig_it == sSignalMap.end()) - { - // ...new callback for this id - callback_signal_t* signal = new callback_signal_t(); - signal->connect(slot); - sSignalMap[key] = signal; - } - else - { - // ...existing callback, bind additional slot - callback_signal_t* signal = sig_it->second; - signal->connect(slot); - } + if (it != sCache.end()) + { + return it->second; } -} - + fetch(key); -void LLExperienceCache::mapKeys( const LLSD& legacyKeys ) + return empty; +} +void LLExperienceCache::get(const LLUUID& key, callback_slot_t slot) { - LLSD::array_const_iterator exp = legacyKeys.beginArray(); - for(/**/ ; exp != legacyKeys.endArray() ; ++exp) + if(key.isNull()) return; + + cache_t::const_iterator it = sCache.find(key); + if (it != sCache.end()) { - if(exp->has(LLExperienceCache::EXPERIENCE_ID) && exp->has(LLExperienceCache::PRIVATE_KEY)) - { - privateToPublicKeyMap[(*exp)[LLExperienceCache::PRIVATE_KEY].asUUID()]=(*exp)[LLExperienceCache::EXPERIENCE_ID].asUUID(); - } + // ...name already exists in cache, fire callback now + callback_signal_t signal; + signal.connect(slot); + + signal(it->second); + return; } -} + fetch(key); -LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_if_not_found) -{ - if (private_key.isNull()) - return LLUUID::null; - - KeyMap::const_iterator it=privateToPublicKeyMap.find(private_key); - if(it == privateToPublicKeyMap.end()) + // always store additional callback, even if request is pending + signal_map_t::iterator sig_it = sSignalMap.find(key); + if (sig_it == sSignalMap.end()) { - if(null_if_not_found) - { - return LLUUID::null; - } - return private_key; + // ...new callback for this id + callback_signal_t* signal = new callback_signal_t(); + signal->connect(slot); + sSignalMap[key] = signal; + } + else + { + // ...existing callback, bind additional slot + callback_signal_t* signal = sig_it->second; + signal->connect(slot); } - LL_WARNS("LLExperience") << "converted private key " << private_key << " to experience_id " << it->second << LL_ENDL; - return it->second; } + + diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h index e669ee888e..8a55719443 100644 --- a/indra/llmessage/llexperiencecache.h +++ b/indra/llmessage/llexperiencecache.h @@ -30,15 +30,47 @@ #define LL_LLEXPERIENCECACHE_H #include "linden_common.h" +#include "llsingleton.h" +#include "llsd.h" #include +#include class LLSD; class LLUUID; - -namespace LLExperienceCache +class LLExperienceCache: public LLSingleton < LLExperienceCache > { + friend class LLSingleton < LLExperienceCache > ; + +public: + typedef boost::function Callback_t; + + void erase(const LLUUID& key); + bool fetch(const LLUUID& key, bool refresh = false); + void insert(const LLSD& experience_data); + const LLSD& get(const LLUUID& key); + + // If name information is in cache, callback will be called immediately. + void get(const LLUUID& key, Callback_t slot); + +private: + // Callback types for get() +// typedef boost::signals2::signal < void(const LLSD &) > callback_signal_t; + typedef boost::signals2::signal < Callback_t > callback_signal_t; + typedef std::map cache_t; + +//-------------------------------------------- + LLExperienceCache(); + virtual ~LLExperienceCache(); + + void exportFile(std::ostream& ostr) const; + void importFile(std::istream& istr); + +//-------------------------------------------- + void processExperience(const LLUUID& public_key, const LLSD& experience); + + const std::string PRIVATE_KEY = "private_id"; const std::string MISSING = "DoesNotExist"; @@ -61,19 +93,12 @@ namespace LLExperienceCache const int PROPERTY_GRID = 1 << 4; const int PROPERTY_PRIVATE = 1 << 5; const int PROPERTY_DISABLED = 1 << 6; - const int PROPERTY_SUSPENDED = 1 << 7; - + const int PROPERTY_SUSPENDED = 1 << 7; // default values const static F64 DEFAULT_EXPIRATION = 600.0; const static S32 DEFAULT_QUOTA = 128; // this is megabytes - // Callback types for get() below - typedef boost::signals2::signal - callback_signal_t; - typedef callback_signal_t::slot_type callback_slot_t; - typedef std::map cache_t; - void setLookupURL(const std::string& lookup_url); bool hasLookupURL(); @@ -81,24 +106,26 @@ namespace LLExperienceCache void setMaximumLookups(int maximumLookups); void idle(); - void exportFile(std::ostream& ostr); - void importFile(std::istream& istr); - void initClass(); void bootstrap(const LLSD& legacyKeys, int initialExpiration); - void erase(const LLUUID& key); - bool fetch(const LLUUID& key, bool refresh=false); - void insert(const LLSD& experience_data); - const LLSD& get(const LLUUID& key); - - // If name information is in cache, callback will be called immediately. - void get(const LLUUID& key, callback_slot_t slot); const cache_t& getCached(); // maps an experience private key to the experience id LLUUID getExperienceId(const LLUUID& private_key, bool null_if_not_found=false); + //===================================================================== + inline friend std::ostream &operator << (std::ostream &os, const LLExperienceCache &cache) + { + cache.exportFile(os); + return os; + } + + inline friend std::istream &operator >> (std::istream &is, LLExperienceCache &cache) + { + cache.importFile(is); + return is; + } }; #endif // LL_LLEXPERIENCECACHE_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index c74890a4e9..46f75c4f57 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2820,9 +2820,10 @@ void LLStartUp::initNameCache() void LLStartUp::initExperiences() -{ +{ + // just a get instance here. Should trigger loading the cache. + LLExperienceCache::getInstance(); LLAppViewer::instance()->loadExperienceCache(); - LLExperienceCache::initClass(); LLExperienceLog::instance().initialize(); } -- cgit v1.3 From 96e343b49b0b5a0951ffab0beb2e1d09c37bbdc5 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 1 Sep 2015 16:13:52 -0700 Subject: MAINT-5575: Convert the Experience cache into a coro based singleton. --HG-- branch : MAINT-5575 --- indra/llmessage/CMakeLists.txt | 2 + indra/llmessage/llcoproceduremanager.cpp | 414 +++++++++++++++ indra/llmessage/llcoproceduremanager.h | 98 ++++ indra/llmessage/llexperiencecache.cpp | 569 ++++++++++----------- indra/llmessage/llexperiencecache.h | 99 ++-- indra/llui/CMakeLists.txt | 2 + indra/llui/llurlentry.cpp | 4 +- indra/newview/CMakeLists.txt | 2 - indra/newview/llagent.cpp | 9 + indra/newview/llagent.h | 3 + indra/newview/llappviewer.cpp | 57 +-- indra/newview/llappviewer.h | 4 - indra/newview/llcoproceduremanager.cpp | 406 --------------- indra/newview/llcoproceduremanager.h | 87 ---- indra/newview/llexperienceassociationresponder.cpp | 2 +- indra/newview/llfloaterexperienceprofile.cpp | 10 +- indra/newview/llfloaterreporter.cpp | 2 +- indra/newview/llpanelexperiencelisteditor.cpp | 2 +- indra/newview/llpanelexperiencelog.cpp | 4 +- indra/newview/llpanelexperiencepicker.cpp | 2 +- indra/newview/llpreviewscript.cpp | 6 +- indra/newview/llstartup.cpp | 7 +- indra/newview/llviewermessage.cpp | 2 +- 23 files changed, 897 insertions(+), 896 deletions(-) create mode 100644 indra/llmessage/llcoproceduremanager.cpp create mode 100644 indra/llmessage/llcoproceduremanager.h delete mode 100644 indra/newview/llcoproceduremanager.cpp delete mode 100644 indra/newview/llcoproceduremanager.h (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 9739f7c607..12fc1bbcfc 100755 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -40,6 +40,7 @@ set(llmessage_SOURCE_FILES llchainio.cpp llcircuit.cpp llclassifiedflags.cpp + llcoproceduremanager.cpp llcorehttputil.cpp llcurl.cpp lldatapacker.cpp @@ -128,6 +129,7 @@ set(llmessage_HEADER_FILES llcipher.h llcircuit.h llclassifiedflags.h + llcoproceduremanager.h llcorehttputil.h llcurl.h lldatapacker.h diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp new file mode 100644 index 0000000000..062f2e6e42 --- /dev/null +++ b/indra/llmessage/llcoproceduremanager.cpp @@ -0,0 +1,414 @@ +/** +* @file LLCoprocedurePool.cpp +* @author Rider Linden +* @brief Singleton class for managing asset uploads to the sim. +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "linden_common.h" +#include "llcoproceduremanager.h" + +//========================================================================= +// Map of pool sizes for known pools +static std::map DefaultPoolSizes; + +// *TODO$: When C++11 this can be initialized here as follows: +// = {{"AIS", 25}, {"Upload", 1}} + +#define DEFAULT_POOL_SIZE 5 + +//========================================================================= +class LLCoprocedurePool: private boost::noncopyable +{ +public: + typedef LLCoprocedureManager::CoProcedure_t CoProcedure_t; + + LLCoprocedurePool(const std::string &name, size_t size); + virtual ~LLCoprocedurePool(); + + /// Places the coprocedure on the queue for processing. + /// + /// @param name Is used for debugging and should identify this coroutine. + /// @param proc Is a bound function to be executed + /// + /// @return This method returns a UUID that can be used later to cancel execution. + LLUUID enqueueCoprocedure(const std::string &name, CoProcedure_t proc); + + /// Cancel a coprocedure. If the coprocedure is already being actively executed + /// this method calls cancelYieldingOperation() on the associated HttpAdapter + /// If it has not yet been dequeued it is simply removed from the queue. + bool cancelCoprocedure(const LLUUID &id); + + /// Requests a shutdown of the upload manager. Passing 'true' will perform + /// an immediate kill on the upload coroutine. + void shutdown(bool hardShutdown = false); + + /// Returns the number of coprocedures in the queue awaiting processing. + /// + inline size_t countPending() const + { + return mPendingCoprocs.size(); + } + + /// Returns the number of coprocedures actively being processed. + /// + inline size_t countActive() const + { + return mActiveCoprocs.size(); + } + + /// Returns the total number of coprocedures either queued or in active processing. + /// + inline size_t count() const + { + return countPending() + countActive(); + } + +private: + struct QueuedCoproc + { + typedef boost::shared_ptr ptr_t; + + QueuedCoproc(const std::string &name, const LLUUID &id, CoProcedure_t proc) : + mName(name), + mId(id), + mProc(proc) + {} + + std::string mName; + LLUUID mId; + CoProcedure_t mProc; + }; + + // we use a deque here rather than std::queue since we want to be able to + // iterate through the queue and potentially erase an entry from the middle. + typedef std::deque CoprocQueue_t; + typedef std::map ActiveCoproc_t; + + std::string mPoolName; + size_t mPoolSize; + CoprocQueue_t mPendingCoprocs; + ActiveCoproc_t mActiveCoprocs; + bool mShutdown; + LLEventStream mWakeupTrigger; + + typedef std::map CoroAdapterMap_t; + LLCore::HttpRequest::policy_t mHTTPPolicy; + + CoroAdapterMap_t mCoroMapping; + + void coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter); + +}; + +//========================================================================= +LLCoprocedureManager::LLCoprocedureManager() +{ + DefaultPoolSizes.insert(std::map::value_type("Upload", 1)); + DefaultPoolSizes.insert(std::map::value_type("AIS", 25)); +} + +LLCoprocedureManager::~LLCoprocedureManager() +{ + +} + +LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std::string &poolName) +{ + // Attempt to look up a pool size in the configuration. If found use that + std::string keyName = "PoolSize" + poolName; + int size = 0; + + if (mPropertyQueryFn && !mPropertyQueryFn.empty()) + { + size = mPropertyQueryFn(keyName); + } + + if (size == 0) + { // if not found grab the know default... if there is no known + // default use a reasonable number like 5. + std::map::iterator it = DefaultPoolSizes.find(poolName); + if (it == DefaultPoolSizes.end()) + size = DEFAULT_POOL_SIZE; + else + size = (*it).second; + + if (mPropertyDefineFn && !mPropertyDefineFn.empty()) + mPropertyDefineFn(keyName, size, "Coroutine Pool size for " + poolName); + LL_WARNS() << "LLCoprocedureManager: No setting for \"" << keyName << "\" setting pool size to default of " << size << LL_ENDL; + } + + poolPtr_t pool = poolPtr_t(new LLCoprocedurePool(poolName, size)); + mPoolMap.insert(poolMap_t::value_type(poolName, pool)); + + return pool; +} + +//------------------------------------------------------------------------- +LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc) +{ + // Attempt to find the pool and enqueue the procedure. If the pool does + // not exist, create it. + poolPtr_t targetPool; + poolMap_t::iterator it = mPoolMap.find(pool); + + if (it == mPoolMap.end()) + { + targetPool = initializePool(pool); + } + else + { + targetPool = (*it).second; + } + + if (!targetPool) + { + LL_WARNS() << "LLCoprocedureManager unable to create coprocedure pool named \"" << pool << "\"" << LL_ENDL; + return LLUUID::null; + } + + return targetPool->enqueueCoprocedure(name, proc); +} + +void LLCoprocedureManager::cancelCoprocedure(const LLUUID &id) +{ + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + if ((*it).second->cancelCoprocedure(id)) + return; + } + LL_INFOS() << "Coprocedure not found." << LL_ENDL; +} + +void LLCoprocedureManager::shutdown(bool hardShutdown) +{ + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + (*it).second->shutdown(hardShutdown); + } + mPoolMap.clear(); +} + +void LLCoprocedureManager::setPropertyMethods(SettingQuery_t queryfn, SettingUpdate_t updatefn) +{ + mPropertyQueryFn = queryfn; + mPropertyDefineFn = updatefn; +} + +//------------------------------------------------------------------------- +size_t LLCoprocedureManager::countPending() const +{ + size_t count = 0; + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + count += (*it).second->countPending(); + } + return count; +} + +size_t LLCoprocedureManager::countPending(const std::string &pool) const +{ + poolMap_t::const_iterator it = mPoolMap.find(pool); + + if (it == mPoolMap.end()) + return 0; + return (*it).second->countPending(); +} + +size_t LLCoprocedureManager::countActive() const +{ + size_t count = 0; + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + count += (*it).second->countActive(); + } + return count; +} + +size_t LLCoprocedureManager::countActive(const std::string &pool) const +{ + poolMap_t::const_iterator it = mPoolMap.find(pool); + + if (it == mPoolMap.end()) + return 0; + return (*it).second->countActive(); +} + +size_t LLCoprocedureManager::count() const +{ + size_t count = 0; + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + count += (*it).second->count(); + } + return count; +} + +size_t LLCoprocedureManager::count(const std::string &pool) const +{ + poolMap_t::const_iterator it = mPoolMap.find(pool); + + if (it == mPoolMap.end()) + return 0; + return (*it).second->count(); +} + +//========================================================================= +LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size): + mPoolName(poolName), + mPoolSize(size), + mPendingCoprocs(), + mShutdown(false), + mWakeupTrigger("CoprocedurePool" + poolName, true), + mCoroMapping(), + mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID) +{ + for (size_t count = 0; count < mPoolSize; ++count) + { + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter = + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t( + new LLCoreHttpUtil::HttpCoroutineAdapter( mPoolName + "Adapter", mHTTPPolicy)); + + std::string uploadCoro = LLCoros::instance().launch("LLCoprocedurePool("+mPoolName+")::coprocedureInvokerCoro", + boost::bind(&LLCoprocedurePool::coprocedureInvokerCoro, this, httpAdapter)); + + mCoroMapping.insert(CoroAdapterMap_t::value_type(uploadCoro, httpAdapter)); + } + + LL_INFOS() << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items." << LL_ENDL; + + mWakeupTrigger.post(LLSD()); +} + +LLCoprocedurePool::~LLCoprocedurePool() +{ + shutdown(); +} + +//------------------------------------------------------------------------- +void LLCoprocedurePool::shutdown(bool hardShutdown) +{ + CoroAdapterMap_t::iterator it; + + for (it = mCoroMapping.begin(); it != mCoroMapping.end(); ++it) + { + if (!(*it).first.empty()) + { + if (hardShutdown) + { + LLCoros::instance().kill((*it).first); + } + } + if ((*it).second) + { + (*it).second->cancelYieldingOperation(); + } + } + + mShutdown = true; + mCoroMapping.clear(); + mPendingCoprocs.clear(); +} + +//------------------------------------------------------------------------- +LLUUID LLCoprocedurePool::enqueueCoprocedure(const std::string &name, LLCoprocedurePool::CoProcedure_t proc) +{ + LLUUID id(LLUUID::generateNewID()); + + mPendingCoprocs.push_back(QueuedCoproc::ptr_t(new QueuedCoproc(name, id, proc))); + LL_INFOS() << "Coprocedure(" << name << ") enqueued with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; + + mWakeupTrigger.post(LLSD()); + + return id; +} + +bool LLCoprocedurePool::cancelCoprocedure(const LLUUID &id) +{ + // first check the active coroutines. If there, remove it and return. + ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(id); + if (itActive != mActiveCoprocs.end()) + { + LL_INFOS() << "Found and canceling active coprocedure with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; + (*itActive).second->cancelYieldingOperation(); + mActiveCoprocs.erase(itActive); + return true; + } + + for (CoprocQueue_t::iterator it = mPendingCoprocs.begin(); it != mPendingCoprocs.end(); ++it) + { + if ((*it)->mId == id) + { + LL_INFOS() << "Found and removing queued coroutine(" << (*it)->mName << ") with Id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; + mPendingCoprocs.erase(it); + return true; + } + } + + LL_INFOS() << "Coprocedure with Id=" << id.asString() << " was not found." << " in pool \"" << mPoolName << "\"" << LL_ENDL; + return false; +} + +//------------------------------------------------------------------------- +void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter) +{ + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + while (!mShutdown) + { + llcoro::waitForEventOn(mWakeupTrigger); + if (mShutdown) + break; + + while (!mPendingCoprocs.empty()) + { + QueuedCoproc::ptr_t coproc = mPendingCoprocs.front(); + mPendingCoprocs.pop_front(); + mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)); + + LL_INFOS() << "Dequeued and invoking coprocedure(" << coproc->mName << ") with id=" << coproc->mId.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; + + try + { + coproc->mProc(httpAdapter, coproc->mId); + } + catch (std::exception &e) + { + LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() << + " threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL; + } + catch (...) + { + LL_WARNS() << "A non std::exception was thrown from " << coproc->mName << " with id=" << coproc->mId << "." << " in pool \"" << mPoolName << "\"" << LL_ENDL; + } + + LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL; + + ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(coproc->mId); + if (itActive != mActiveCoprocs.end()) + { + mActiveCoprocs.erase(itActive); + } + } + } +} diff --git a/indra/llmessage/llcoproceduremanager.h b/indra/llmessage/llcoproceduremanager.h new file mode 100644 index 0000000000..497367b80c --- /dev/null +++ b/indra/llmessage/llcoproceduremanager.h @@ -0,0 +1,98 @@ +/** +* @file llcoproceduremanager.h +* @author Rider Linden +* @brief Singleton class for managing asset uploads to the sim. +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#ifndef LL_COPROCEDURE_MANAGER_H +#define LL_COPROCEDURE_MANAGER_H + +#include "lleventcoro.h" +#include "llcoros.h" +#include "llcorehttputil.h" +#include "lluuid.h" + +class LLCoprocedurePool; + +class LLCoprocedureManager : public LLSingleton < LLCoprocedureManager > +{ + friend class LLSingleton < LLCoprocedureManager > ; + +public: + typedef boost::function SettingQuery_t; + typedef boost::function SettingUpdate_t; + + typedef boost::function CoProcedure_t; + + LLCoprocedureManager(); + virtual ~LLCoprocedureManager(); + + /// Places the coprocedure on the queue for processing. + /// + /// @param name Is used for debugging and should identify this coroutine. + /// @param proc Is a bound function to be executed + /// + /// @return This method returns a UUID that can be used later to cancel execution. + LLUUID enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc); + + /// Cancel a coprocedure. If the coprocedure is already being actively executed + /// this method calls cancelYieldingOperation() on the associated HttpAdapter + /// If it has not yet been dequeued it is simply removed from the queue. + void cancelCoprocedure(const LLUUID &id); + + /// Requests a shutdown of the upload manager. Passing 'true' will perform + /// an immediate kill on the upload coroutine. + void shutdown(bool hardShutdown = false); + + void setPropertyMethods(SettingQuery_t queryfn, SettingUpdate_t updatefn); + + /// Returns the number of coprocedures in the queue awaiting processing. + /// + size_t countPending() const; + size_t countPending(const std::string &pool) const; + + /// Returns the number of coprocedures actively being processed. + /// + size_t countActive() const; + size_t countActive(const std::string &pool) const; + + /// Returns the total number of coprocedures either queued or in active processing. + /// + size_t count() const; + size_t count(const std::string &pool) const; + +private: + + typedef boost::shared_ptr poolPtr_t; + typedef std::map poolMap_t; + + poolMap_t mPoolMap; + + poolPtr_t initializePool(const std::string &poolName); + + SettingQuery_t mPropertyQueryFn; + SettingUpdate_t mPropertyDefineFn; +}; + +#endif diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp index 34c4210359..36a4fc8823 100644 --- a/indra/llmessage/llexperiencecache.cpp +++ b/indra/llmessage/llexperiencecache.cpp @@ -26,53 +26,51 @@ #include "llexperiencecache.h" #include "llavatarname.h" -#include "llframetimer.h" #include "llhttpclient.h" #include "llsdserialize.h" +#include "llcoros.h" +#include "lleventcoro.h" +#include "lleventfilter.h" +#include "llcoproceduremanager.h" +#include "lldir.h" #include #include -#include "boost/tokenizer.hpp" +#include #include - -typedef std::map KeyMap; -KeyMap privateToPublicKeyMap; - - -std::string sLookupURL; - -typedef std::map pending_queue_t; -pending_queue_t sPendingQueue; - -int sMaximumLookups = 10; - -LLFrameTimer sRequestTimer; - -// Periodically clean out expired entries from the cache -LLFrameTimer sEraseExpiredTimer; - - //========================================================================= namespace LLExperienceCacheImpl { - bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age); void mapKeys(const LLSD& legacyKeys); + F64 getErrorRetryDeltaTime(S32 status, LLSD headers); + bool maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age); + + static const std::string PRIVATE_KEY = "private_id"; + static const std::string EXPERIENCE_ID = "public_id"; + + static const std::string MAX_AGE("max-age"); + static const boost::char_separator EQUALS_SEPARATOR("="); + static const boost::char_separator COMMA_SEPARATOR(","); + + // *TODO$: this seems to be tied to mapKeys which is used by bootstrap.... but I don't think that bootstrap is used. + typedef std::map KeyMap; + KeyMap privateToPublicKeyMap; } //========================================================================= const std::string LLExperienceCache::PRIVATE_KEY = "private_id"; const std::string LLExperienceCache::MISSING = "DoesNotExist"; -const std::string LLExperienceCache::AGENT_ID = "agent_id"; -const std::string LLExperienceCache::GROUP_ID = "group_id"; +const std::string LLExperienceCache::AGENT_ID = "agent_id"; +const std::string LLExperienceCache::GROUP_ID = "group_id"; const std::string LLExperienceCache::EXPERIENCE_ID = "public_id"; const std::string LLExperienceCache::NAME = "name"; const std::string LLExperienceCache::PROPERTIES = "properties"; const std::string LLExperienceCache::EXPIRES = "expiration"; const std::string LLExperienceCache::DESCRIPTION = "description"; const std::string LLExperienceCache::QUOTA = "quota"; -const std::string LLExperienceCache::MATURITY = "maturity"; -const std::string LLExperienceCache::METADATA = "extended_metadata"; +const std::string LLExperienceCache::MATURITY = "maturity"; +const std::string LLExperienceCache::METADATA = "extended_metadata"; const std::string LLExperienceCache::SLURL = "slurl"; // should be in sync with experience-api/experiences/models.py @@ -80,20 +78,51 @@ const int LLExperienceCache::PROPERTY_INVALID = 1 << 0; const int LLExperienceCache::PROPERTY_PRIVILEGED = 1 << 3; const int LLExperienceCache::PROPERTY_GRID = 1 << 4; const int LLExperienceCache::PROPERTY_PRIVATE = 1 << 5; -const int LLExperienceCache::PROPERTY_DISABLED = 1 << 6; -const int LLExperienceCache::PROPERTY_SUSPENDED = 1 << 7; +const int LLExperienceCache::PROPERTY_DISABLED = 1 << 6; +const int LLExperienceCache::PROPERTY_SUSPENDED = 1 << 7; // default values -const F64 LLExperienceCache::DEFAULT_EXPIRATION = 600.0; +const F64 LLExperienceCache::DEFAULT_EXPIRATION = 600.0; const S32 LLExperienceCache::DEFAULT_QUOTA = 128; // this is megabytes //========================================================================= -LLExperienceCache::LLExperienceCache() +LLExperienceCache::LLExperienceCache(): + mShutdown(false) { } LLExperienceCache::~LLExperienceCache() { + +} + +void LLExperienceCache::initSingleton() +{ + mCacheFileName = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); + + LL_INFOS("ExperienceCache") << "Loading " << mCacheFileName << LL_ENDL; + llifstream cache_stream(mCacheFileName.c_str()); + + if (cache_stream.is_open()) + { + cache_stream >> (*this); + } + + LLCoros::instance().launch("LLExperienceCache::idleCoro", + boost::bind(&LLExperienceCache::idleCoro, this)); + +} + +void LLExperienceCache::cleanup() +{ + LL_INFOS("ExperienceCache") << "Saving " << mCacheFileName << LL_ENDL; + + llofstream cache_stream(mCacheFileName.c_str()); + if (cache_stream.is_open()) + { + cache_stream << (*this); + } + mShutdown = true; } //------------------------------------------------------------------------- @@ -110,18 +139,18 @@ void LLExperienceCache::importFile(std::istream& istr) for (; it != experiences.endMap(); ++it) { public_key.set(it->first); - sCache[public_key] = it->second; + mCache[public_key] = it->second; } - LL_DEBUGS("ExperienceCache") << "importFile() loaded " << sCache.size() << LL_ENDL; + LL_DEBUGS("ExperienceCache") << "importFile() loaded " << mCache.size() << LL_ENDL; } void LLExperienceCache::exportFile(std::ostream& ostr) const { LLSD experiences; - cache_t::const_iterator it = sCache.begin(); - for (; it != sCache.end(); ++it) + cache_t::const_iterator it = mCache.begin(); + for (; it != mCache.end(); ++it) { if (!it->second.has(EXPERIENCE_ID) || it->second[EXPERIENCE_ID].asUUID().isNull() || it->second.has("DoesNotExist") || (it->second.has(PROPERTIES) && it->second[PROPERTIES].asInteger() & PROPERTY_INVALID)) @@ -136,7 +165,7 @@ void LLExperienceCache::exportFile(std::ostream& ostr) const LLSDSerialize::toPrettyXML(data, ostr); } -// *TODO$: Rider: These three functions not seem to be used... it may be useful in testing. +// *TODO$: Rider: This method does not seem to be used... it may be useful in testing. void LLExperienceCache::bootstrap(const LLSD& legacyKeys, int initialExpiration) { LLExperienceCacheImpl::mapKeys(legacyKeys); @@ -166,8 +195,8 @@ LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_i if (private_key.isNull()) return LLUUID::null; - KeyMap::const_iterator it = privateToPublicKeyMap.find(private_key); - if (it == privateToPublicKeyMap.end()) + LLExperienceCacheImpl::KeyMap::const_iterator it = LLExperienceCacheImpl::privateToPublicKeyMap.find(private_key); + if (it == LLExperienceCacheImpl::privateToPublicKeyMap.end()) { if (null_if_not_found) { @@ -182,8 +211,10 @@ LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_i //========================================================================= void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD& experience) { - sCache[public_key]=experience; - LLSD & row = sCache[public_key]; + LL_INFOS("ExperienceCache") << "Processing experience \"" << experience[NAME] << "\" with key " << public_key.asString() << LL_ENDL; + + mCache[public_key]=experience; + LLSD & row = mCache[public_key]; if(row.has(EXPIRES)) { @@ -192,233 +223,148 @@ void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD& if(row.has(EXPERIENCE_ID)) { - sPendingQueue.erase(row[EXPERIENCE_ID].asUUID()); + mPendingQueue.erase(row[EXPERIENCE_ID].asUUID()); } //signal - signal_map_t::iterator sig_it = sSignalMap.find(public_key); - if (sig_it != sSignalMap.end()) + signal_map_t::iterator sig_it = mSignalMap.find(public_key); + if (sig_it != mSignalMap.end()) { signal_ptr signal = sig_it->second; (*signal)(experience); - sSignalMap.erase(public_key); + mSignalMap.erase(public_key); } } const LLExperienceCache::cache_t& LLExperienceCache::getCached() { - return sCache; -} - -void LLExperienceCache::setMaximumLookups(int maximumLookups) -{ - sMaximumLookups = maximumLookups; + return mCache; } - -bool LLExperienceCache::expirationFromCacheControl(LLSD headers, F64 *expires) +void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, std::string url, RequestQueue_t requests) { - // Allow the header to override the default - LLSD cache_control_header = headers["cache-control"]; - if (cache_control_header.isDefined()) - { - S32 max_age = 0; - std::string cache_control = cache_control_header.asString(); - if (max_age_from_cache_control(cache_control, &max_age)) - { - LL_WARNS("ExperienceCache") - << "got EXPIRES from headers, max_age " << max_age - << LL_ENDL; - F64 now = LLFrameTimer::getTotalSeconds(); - *expires = now + (F64)max_age; - return true; - } - } - return false; -} + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest()); + //LL_INFOS("requestExperiencesCoro") << "url: " << url << LL_ENDL; -static const std::string MAX_AGE("max-age"); -static const boost::char_separator EQUALS_SEPARATOR("="); -static const boost::char_separator COMMA_SEPARATOR(","); + LLSD result = httpAdapter->getAndYield(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + if (!status) + { + F64 now = LLFrameTimer::getTotalSeconds(); -class LLExperienceResponder : public LLHTTPClient::Responder -{ -public: - LLExperienceResponder(const ask_queue_t& keys) - :mKeys(keys) - { - - } - - /*virtual*/ void httpCompleted() - { - LLSD experiences = getContent()["experience_keys"]; - LLSD::array_const_iterator it = experiences.beginArray(); - for( /**/ ; it != experiences.endArray(); ++it) - { - const LLSD& row = *it; - LLUUID public_key = row[EXPERIENCE_ID].asUUID(); - - - LL_DEBUGS("ExperienceCache") << "Received result for " << public_key - << " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL ; - - processExperience(public_key, row); - } - - LLSD error_ids = getContent()["error_ids"]; - LLSD::array_const_iterator errIt = error_ids.beginArray(); - for( /**/ ; errIt != error_ids.endArray() ; ++errIt ) - { - LLUUID id = errIt->asUUID(); - LLSD exp; - exp[EXPIRES]=DEFAULT_EXPIRATION; - exp[EXPERIENCE_ID] = id; - exp[PROPERTIES]=PROPERTY_INVALID; - exp[MISSING]=true; - exp[QUOTA] = DEFAULT_QUOTA; - - processExperience(id, exp); - LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL ; - } - - LL_DEBUGS("ExperienceCache") << sCache.size() << " cached experiences" << LL_ENDL; - } - - /*virtual*/ void httpFailure() - { - LL_WARNS("ExperienceCache") << "Request failed "<first); + LLSD headers = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; + // build dummy entries for the failed requests + for (RequestQueue_t::const_iterator it = requests.begin(); it != requests.end(); ++it) + { + LLSD exp = get(*it); //leave the properties alone if we already have a cache entry for this xp - if(exp.isUndefined()) + if (exp.isUndefined()) { - exp[PROPERTIES]=PROPERTY_INVALID; + exp[PROPERTIES] = PROPERTY_INVALID; } - exp[EXPIRES]=retry_timestamp; - exp[EXPERIENCE_ID] = it->first; - exp["key_type"] = it->second; - exp["uuid"] = it->first; - exp["error"] = (LLSD::Integer)getStatus(); + exp[EXPIRES] = now + LLExperienceCacheImpl::getErrorRetryDeltaTime(status, headers); + exp[EXPERIENCE_ID] = *it; + exp["key_type"] = EXPERIENCE_ID; + exp["uuid"] = *it; + exp["error"] = (LLSD::Integer)status.getType(); exp[QUOTA] = DEFAULT_QUOTA; - LLExperienceCache::processExperience(it->first, exp); - } - - } - - // Return time to retry a request that generated an error, based on - // error type and headers. Return value is seconds-since-epoch. - F64 errorRetryTimestamp(S32 status) - { + processExperience(*it, exp); + } + return; + } - // Retry-After takes priority - LLSD retry_after = getResponseHeaders()["retry-after"]; - if (retry_after.isDefined()) - { - // We only support the delta-seconds type - S32 delta_seconds = retry_after.asInteger(); - if (delta_seconds > 0) - { - // ...valid delta-seconds - return F64(delta_seconds); - } - } + LLSD experiences = result["experience_keys"]; + + for (LLSD::array_const_iterator it = experiences.beginArray(); + it != experiences.endArray(); ++it) + { + const LLSD& row = *it; + LLUUID public_key = row[EXPERIENCE_ID].asUUID(); - // If no Retry-After, look for Cache-Control max-age - F64 expires = 0.0; - if (LLExperienceCache::expirationFromCacheControl(getResponseHeaders(), &expires)) - { - return expires; - } + LL_DEBUGS("ExperienceCache") << "Received result for " << public_key + << " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL; - // No information in header, make a guess - if (status == 503) - { - // ...service unavailable, retry soon - const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min - return SERVICE_UNAVAILABLE_DELAY; - } - else if (status == 499) - { - // ...we were probably too busy, retry quickly - const F64 BUSY_DELAY = 10.0; // 10 seconds - return BUSY_DELAY; + processExperience(public_key, row); + } - } - else - { - // ...other unexpected error - const F64 DEFAULT_DELAY = 3600.0; // 1 hour - return DEFAULT_DELAY; - } - } + LLSD error_ids = result["error_ids"]; + + for (LLSD::array_const_iterator errIt = error_ids.beginArray(); + errIt != error_ids.endArray(); ++errIt) + { + LLUUID id = errIt->asUUID(); + LLSD exp; + exp[EXPIRES] = DEFAULT_EXPIRATION; + exp[EXPERIENCE_ID] = id; + exp[PROPERTIES] = PROPERTY_INVALID; + exp[MISSING] = true; + exp[QUOTA] = DEFAULT_QUOTA; + + processExperience(id, exp); + LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL; + } -private: - ask_queue_t mKeys; -}; +} void LLExperienceCache::requestExperiences() { - if(sAskQueue.empty() || sLookupURL.empty()) - return; - - F64 now = LLFrameTimer::getTotalSeconds(); + if (mCapability.empty()) + { + LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL; + return; + } - const U32 EXP_URL_SEND_THRESHOLD = 3000; - const U32 PAGE_SIZE = EXP_URL_SEND_THRESHOLD/UUID_STR_LENGTH; + std::string urlBase = mCapability("GetExperienceInfo"); + if (urlBase.empty()) + { + LL_WARNS("ExperienceCache") << "No Experience capability." << LL_ENDL; + return; + } - std::ostringstream ostr; + if (*urlBase.rbegin() != '/') + { + urlBase += "/"; + } + urlBase += "id/"; - ask_queue_t keys; - ostr << sLookupURL << "?page_size=" << PAGE_SIZE; + F64 now = LLFrameTimer::getTotalSeconds(); - int request_count = 0; - while(!sAskQueue.empty() && request_count < sMaximumLookups) - { - ask_queue_t::iterator it = sAskQueue.begin(); - const LLUUID& key = it->first; - const std::string& key_type = it->second; + const U32 EXP_URL_SEND_THRESHOLD = 3000; + const U32 PAGE_SIZE = EXP_URL_SEND_THRESHOLD / UUID_STR_LENGTH; - ostr << '&' << key_type << '=' << key.asString() ; - - keys[key]=key_type; - request_count++; + std::ostringstream ostr; + ostr << urlBase << "?page_size=" << PAGE_SIZE; + RequestQueue_t requests; - sPendingQueue[key] = now; - - if(ostr.tellp() > EXP_URL_SEND_THRESHOLD) - { - LL_DEBUGS("ExperienceCache") << "requestExperiences() query: " << ostr.str() << LL_ENDL; - LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys)); - ostr.clear(); - ostr.str(sLookupURL); - ostr << "?page_size=" << PAGE_SIZE; - keys.clear(); - } - sAskQueue.erase(it); - } + while (!mRequestQueue.empty()) + { + RequestQueue_t::iterator it = mRequestQueue.begin(); + LLUUID key = (*it); + mRequestQueue.erase(it); + requests.insert(key); + + ostr << "&" << EXPERIENCE_ID << "=" << key.asString(); + mPendingQueue[key] = now; + + if (mRequestQueue.empty() || (ostr.tellp() > EXP_URL_SEND_THRESHOLD)) + { // request is placed in the coprocedure pool for the ExpCache cache. Throttling is done by the pool itself. + LLCoprocedureManager::getInstance()->enqueueCoprocedure("ExpCache", "Request", + boost::bind(&LLExperienceCache::requestExperiencesCoro, this, _1, ostr.str(), requests) ); + + ostr.str(std::string()); + ostr << urlBase << "?page_size=" << PAGE_SIZE; + requests.clear(); + } + } - if(ostr.tellp() > sLookupURL.size()) - { - LL_DEBUGS("ExperienceCache") << "requestExperiences() query 2: " << ostr.str() << LL_ENDL; - LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys)); - } } @@ -427,9 +373,9 @@ bool LLExperienceCache::isRequestPending(const LLUUID& public_key) bool isPending = false; const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0; - pending_queue_t::const_iterator it = sPendingQueue.find(public_key); + PendingQueue_t::const_iterator it = mPendingQueue.find(public_key); - if(it != sPendingQueue.end()) + if(it != mPendingQueue.end()) { F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS; isPending = (it->second > expire_time); @@ -438,69 +384,70 @@ bool LLExperienceCache::isRequestPending(const LLUUID& public_key) return isPending; } - -void LLExperienceCache::setLookupURL(const std::string& lookup_url) +void LLExperienceCache::setCapabilityQuery(LLExperienceCache::CapabilityQuery_t queryfn) { - sLookupURL = lookup_url; - if(!sLookupURL.empty()) - { - sLookupURL += "id/"; - } + mCapability = queryfn; } -bool LLExperienceCache::hasLookupURL() -{ - return !sLookupURL.empty(); -} -void LLExperienceCache::idle() +void LLExperienceCache::idleCoro() { - const F32 SECS_BETWEEN_REQUESTS = 0.1f; - if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS)) - { - return; - } + const F32 SECS_BETWEEN_REQUESTS = 0.5f; + const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds - // Must be large relative to above - const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds - if (sEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) - { - eraseExpired(); - } + LL_INFOS("ExperienceCache") << "Launching Experience cache idle coro." << LL_ENDL; + LLEventTimeout timeout; - if(!sAskQueue.empty()) - { - requestExperiences(); - } + do + { + timeout.eventAfter(SECS_BETWEEN_REQUESTS, LLSD()); + llcoro::waitForEventOn(timeout); + + if (mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) + { + eraseExpired(); + } + + if (!mRequestQueue.empty()) + { + requestExperiences(); + } + + } while (!mShutdown); + + // The coroutine system will likely be shut down by the time we get to this point + // (or at least no further cycling will occur on it since the user has decided to quit.) } void LLExperienceCache::erase(const LLUUID& key) { - cache_t::iterator it = sCache.find(key); + cache_t::iterator it = mCache.find(key); - if(it != sCache.end()) + if(it != mCache.end()) { - sCache.erase(it); + mCache.erase(it); } } void LLExperienceCache::eraseExpired() { F64 now = LLFrameTimer::getTotalSeconds(); - cache_t::iterator it = sCache.begin(); - while (it != sCache.end()) + cache_t::iterator it = mCache.begin(); + while (it != mCache.end()) { cache_t::iterator cur = it; LLSD& exp = cur->second; ++it; + //LL_INFOS("ExperienceCache") << "Testing experience \"" << exp[NAME] << "\" with exp time " << exp[EXPIRES].asReal() << "(now = " << now << ")" << LL_ENDL; + if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now) { if(!exp.has(EXPERIENCE_ID)) { LL_WARNS("ExperienceCache") << "Removing experience with no id " << LL_ENDL ; - sCache.erase(cur); - } + mCache.erase(cur); + } else { LLUUID id = exp[EXPERIENCE_ID].asUUID(); @@ -512,7 +459,7 @@ void LLExperienceCache::eraseExpired() else { LL_WARNS("ExperienceCache") << "Removing invalid experience " << id << LL_ENDL ; - sCache.erase(cur); + mCache.erase(cur); } } } @@ -521,11 +468,11 @@ void LLExperienceCache::eraseExpired() bool LLExperienceCache::fetch(const LLUUID& key, bool refresh/* = true*/) { - if(!key.isNull() && !isRequestPending(key) && (refresh || sCache.find(key)==sCache.end())) + if(!key.isNull() && !isRequestPending(key) && (refresh || mCache.find(key)==mCache.end())) { - LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL ; - sAskQueue[key]=EXPERIENCE_ID; + LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL; + mRequestQueue.insert(key); return true; } return false; @@ -549,13 +496,12 @@ const LLSD& LLExperienceCache::get(const LLUUID& key) if(key.isNull()) return empty; - cache_t::const_iterator it = sCache.find(key); + cache_t::const_iterator it = mCache.find(key); - if (it != sCache.end()) + if (it != mCache.end()) { return it->second; } - fetch(key); return empty; @@ -565,8 +511,8 @@ void LLExperienceCache::get(const LLUUID& key, LLExperienceCache::Callback_t slo if(key.isNull()) return; - cache_t::const_iterator it = sCache.find(key); - if (it != sCache.end()) + cache_t::const_iterator it = mCache.find(key); + if (it != mCache.end()) { // ...name already exists in cache, fire callback now callback_signal_t signal; @@ -580,28 +526,10 @@ void LLExperienceCache::get(const LLUUID& key, LLExperienceCache::Callback_t slo signal_ptr signal = signal_ptr(new callback_signal_t()); - std::pair result = sSignalMap.insert(signal_map_t::value_type(key, signal)); + std::pair result = mSignalMap.insert(signal_map_t::value_type(key, signal)); if (!result.second) - signal = result.first.second; + signal = (*result.first).second; signal->connect(slot); - -#if 0 - // always store additional callback, even if request is pending - signal_map_t::iterator sig_it = sSignalMap.find(key); - if (sig_it == sSignalMap.end()) - { - // ...new callback for this id - signal_ptr signal = signal_ptr(new callback_signal_t()); - signal->connect(slot); - sSignalMap[key] = signal; - } - else - { - // ...existing callback, bind additional slot - callback_signal_t* signal = sig_it->second; - signal->connect(slot); - } -#endif } //========================================================================= @@ -610,14 +538,71 @@ void LLExperienceCacheImpl::mapKeys(const LLSD& legacyKeys) LLSD::array_const_iterator exp = legacyKeys.beginArray(); for (/**/; exp != legacyKeys.endArray(); ++exp) { - if (exp->has(LLExperienceCache::EXPERIENCE_ID) && exp->has(LLExperienceCache::PRIVATE_KEY)) + if (exp->has(LLExperienceCacheImpl::EXPERIENCE_ID) && exp->has(LLExperienceCacheImpl::PRIVATE_KEY)) { - privateToPublicKeyMap[(*exp)[LLExperienceCache::PRIVATE_KEY].asUUID()] = (*exp)[LLExperienceCache::EXPERIENCE_ID].asUUID(); + LLExperienceCacheImpl::privateToPublicKeyMap[(*exp)[LLExperienceCacheImpl::PRIVATE_KEY].asUUID()] = + (*exp)[LLExperienceCacheImpl::EXPERIENCE_ID].asUUID(); } } } -bool LLExperienceCacheImpl::max_age_from_cache_control(const std::string& cache_control, S32 *max_age) +// Return time to retry a request that generated an error, based on +// error type and headers. Return value is seconds-since-epoch. +F64 LLExperienceCacheImpl::getErrorRetryDeltaTime(S32 status, LLSD headers) +{ + + // Retry-After takes priority + LLSD retry_after = headers["retry-after"]; + if (retry_after.isDefined()) + { + // We only support the delta-seconds type + S32 delta_seconds = retry_after.asInteger(); + if (delta_seconds > 0) + { + // ...valid delta-seconds + return F64(delta_seconds); + } + } + + // If no Retry-After, look for Cache-Control max-age + // Allow the header to override the default + LLSD cache_control_header = headers["cache-control"]; + if (cache_control_header.isDefined()) + { + S32 max_age = 0; + std::string cache_control = cache_control_header.asString(); + if (LLExperienceCacheImpl::maxAgeFromCacheControl(cache_control, &max_age)) + { + LL_WARNS("ExperienceCache") + << "got EXPIRES from headers, max_age " << max_age + << LL_ENDL; + return (F64)max_age; + } + } + + // No information in header, make a guess + if (status == 503) + { + // ...service unavailable, retry soon + const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min + return SERVICE_UNAVAILABLE_DELAY; + } + else if (status == 499) + { + // ...we were probably too busy, retry quickly + const F64 BUSY_DELAY = 10.0; // 10 seconds + return BUSY_DELAY; + + } + else + { + // ...other unexpected error + const F64 DEFAULT_DELAY = 3600.0; // 1 hour + return DEFAULT_DELAY; + } +} + +bool LLExperienceCacheImpl::maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age) { // Split the string on "," to get a list of directives typedef boost::tokenizer > tokenizer; diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h index 8da038a8c3..937225a80a 100644 --- a/indra/llmessage/llexperiencecache.h +++ b/indra/llmessage/llexperiencecache.h @@ -31,7 +31,9 @@ #include "linden_common.h" #include "llsingleton.h" +#include "llframetimer.h" #include "llsd.h" +#include "llcorehttputil.h" #include #include @@ -44,8 +46,11 @@ class LLExperienceCache: public LLSingleton < LLExperienceCache > friend class LLSingleton < LLExperienceCache > ; public: + typedef boost::function CapabilityQuery_t; typedef boost::function Callback_t; + void cleanup(); + void erase(const LLUUID& key); bool fetch(const LLUUID& key, bool refresh = false); void insert(const LLSD& experience_data); @@ -54,7 +59,39 @@ public: // If name information is in cache, callback will be called immediately. void get(const LLUUID& key, Callback_t slot); + bool isRequestPending(const LLUUID& public_key); + + void setCapabilityQuery(CapabilityQuery_t queryfn); + + static const std::string NAME; // "name" + static const std::string EXPERIENCE_ID; // "public_id" + static const std::string AGENT_ID; // "agent_id" + static const std::string GROUP_ID; // "group_id" + static const std::string PROPERTIES; // "properties" + static const std::string EXPIRES; // "expiration" + static const std::string DESCRIPTION; // "description" + static const std::string QUOTA; // "quota" + static const std::string MATURITY; // "maturity" + static const std::string METADATA; // "extended_metadata" + static const std::string SLURL; // "slurl" + + static const std::string MISSING; // "DoesNotExist" + + // should be in sync with experience-api/experiences/models.py + static const int PROPERTY_INVALID; // 1 << 0 + static const int PROPERTY_PRIVILEGED; // 1 << 3 + static const int PROPERTY_GRID; // 1 << 4 + static const int PROPERTY_PRIVATE; // 1 << 5 + static const int PROPERTY_DISABLED; // 1 << 6 + static const int PROPERTY_SUSPENDED; // 1 << 7 + private: + LLExperienceCache(); + virtual ~LLExperienceCache(); + + virtual void initSingleton(); + + // Callback types for get() typedef boost::signals2::signal < void(const LLSD &) > callback_signal_t; typedef boost::shared_ptr signal_ptr; @@ -64,63 +101,43 @@ private: typedef std::map signal_map_t; typedef std::map cache_t; - typedef std::set ask_queue_t; - - + typedef std::set RequestQueue_t; + typedef std::map PendingQueue_t; + //-------------------------------------------- static const std::string PRIVATE_KEY; // "private_id" - static const std::string MISSING; // "DoesNotExist" - - static const std::string AGENT_ID; // "agent_id" - static const std::string GROUP_ID; // "group_id" - static const std::string EXPERIENCE_ID; // "public_id" - static const std::string NAME; // "name" - static const std::string PROPERTIES; // "properties" - static const std::string EXPIRES; // "expiration" - static const std::string DESCRIPTION; // "description" - static const std::string QUOTA; // "quota" - static const std::string MATURITY; // "maturity" - static const std::string METADATA; // "extended_metadata" - static const std::string SLURL; // "slurl" - - // should be in sync with experience-api/experiences/models.py - static const int PROPERTY_INVALID; // 1 << 0 - static const int PROPERTY_PRIVILEGED; // 1 << 3 - static const int PROPERTY_GRID; // 1 << 4 - static const int PROPERTY_PRIVATE; // 1 << 5 - static const int PROPERTY_DISABLED; // 1 << 6 - static const int PROPERTY_SUSPENDED; // 1 << 7 // default values static const F64 DEFAULT_EXPIRATION; // 600.0 static const S32 DEFAULT_QUOTA; // 128 this is megabytes -//-------------------------------------------- - LLExperienceCache(); - virtual ~LLExperienceCache(); - - void exportFile(std::ostream& ostr) const; - void importFile(std::istream& istr); - //-------------------------------------------- void processExperience(const LLUUID& public_key, const LLSD& experience); //-------------------------------------------- - cache_t sCache; - signal_map_t sSignalMap; - ask_queue_t sAskQueue; - + cache_t mCache; + signal_map_t mSignalMap; + RequestQueue_t mRequestQueue; + PendingQueue_t mPendingQueue; + + LLFrameTimer mRequestTimer; + LLFrameTimer mEraseExpiredTimer; // Periodically clean out expired entries from the cache + CapabilityQuery_t mCapability; + std::string mCacheFileName; + bool mShutdown; + + void idleCoro(); void eraseExpired(); - - void setLookupURL(const std::string& lookup_url); - bool hasLookupURL(); + void requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, std::string, RequestQueue_t); + void requestExperiences(); void setMaximumLookups(int maximumLookups); - void idle(); - void bootstrap(const LLSD& legacyKeys, int initialExpiration); - + void bootstrap(const LLSD& legacyKeys, int initialExpiration); + void exportFile(std::ostream& ostr) const; + void importFile(std::istream& istr); + // const cache_t& getCached(); // maps an experience private key to the experience id diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 259fbde806..d192aac448 100755 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -11,11 +11,13 @@ include(LLMessage) include(LLCoreHttp) include(LLRender) include(LLWindow) +include(LLCoreHttp) include(LLVFS) include(LLXML) include_directories( ${LLCOMMON_INCLUDE_DIRS} + ${LLCOREHTTP_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS} ${LLINVENTORY_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index eb7f98e618..e76f2a1550 100755 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -1430,7 +1430,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const return LLTrans::getString("ExperienceNameNull"); } - const LLSD& experience_details = LLExperienceCache::get(experience_id); + const LLSD& experience_details = LLExperienceCache::getInstance()->get(experience_id); if(!experience_details.isUndefined()) { std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString(); @@ -1438,7 +1438,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const } addObserver(experience_id_string, url, cb); - LLExperienceCache::get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1)); + LLExperienceCache::getInstance()->get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1)); return LLTrans::getString("LoadingData"); } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index fe9c7c0fc0..090879e372 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -161,7 +161,6 @@ set(viewer_SOURCE_FILES llconversationloglistitem.cpp llconversationmodel.cpp llconversationview.cpp - llcoproceduremanager.cpp llcurrencyuimanager.cpp llcylinder.cpp lldateutil.cpp @@ -771,7 +770,6 @@ set(viewer_HEADER_FILES llconversationloglistitem.h llconversationmodel.h llconversationview.h - llcoproceduremanager.h llcurrencyuimanager.h llcylinder.h lldateutil.h diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index e7dd378edd..3316f1e654 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -953,6 +953,15 @@ BOOL LLAgent::inPrelude() } +std::string LLAgent::getRegionCapability(const std::string &name) +{ + if (!mRegionp) + return std::string(); + + return mRegionp->getCapability(name); +} + + //----------------------------------------------------------------------------- // canManageEstate() //----------------------------------------------------------------------------- diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 0ba3dea427..5731f4db89 100755 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -262,6 +262,9 @@ public: LLHost getRegionHost() const; BOOL inPrelude(); + // Capability + std::string getRegionCapability(const std::string &name); // short hand for if (getRegion()) { getRegion()->getCapability(name) } + /** * Register a boost callback to be called when the agent changes regions * Note that if you need to access a capability for the region, you may need to wait diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9b9b591cd1..e13a9d96c7 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -228,7 +228,7 @@ #include "llmachineid.h" #include "llmainlooprepeater.h" - +#include "llcoproceduremanager.h" #include "llviewereventrecorder.h" @@ -755,8 +755,11 @@ void fast_exit(int rc) { _exit(rc); } + + } + bool LLAppViewer::init() { setupErrorHandling(mSecondInstance); @@ -1216,6 +1219,12 @@ bool LLAppViewer::init() LLAgentLanguage::init(); + /// Tell the Coprocedure manager how to discover and store the pool sizes + // what I wanted + LLCoprocedureManager::getInstance()->setPropertyMethods( + boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1), + boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS)); + return true; } @@ -4700,31 +4709,6 @@ void LLAppViewer::saveNameCache() } -void LLAppViewer::saveExperienceCache() -{ - std::string filename = - gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); - LL_INFOS("ExperienceCache") << "Saving " << filename << LL_ENDL; - llofstream cache_stream(filename.c_str()); - if(cache_stream.is_open()) - { - LLExperienceCache::exportFile(cache_stream); - } -} - -void LLAppViewer::loadExperienceCache() -{ - std::string filename = - gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); - LL_INFOS("ExperienceCache") << "Loading " << filename << LL_ENDL; - llifstream cache_stream(filename.c_str()); - if(cache_stream.is_open()) - { - LLExperienceCache::importFile(cache_stream); - } -} - - /*! @brief This class is an LLFrameTimer that can be created with an elapsed time that starts counting up from the given value rather than 0.0. @@ -4920,7 +4904,6 @@ void LLAppViewer::idle() // floating throughout the various object lists. // idleNameCache(); - idleExperienceCache(); idleNetwork(); @@ -5350,22 +5333,6 @@ void LLAppViewer::idleNameCache() LLAvatarNameCache::idle(); } -void LLAppViewer::idleExperienceCache() -{ - LLViewerRegion* region = gAgent.getRegion(); - if (!region) return; - - std::string lookup_url=region->getCapability("GetExperienceInfo"); - if(!lookup_url.empty() && *lookup_url.rbegin() != '/') - { - lookup_url += '/'; - } - - LLExperienceCache::setLookupURL(lookup_url); - - LLExperienceCache::idle(); -} - // // Handle messages, and all message related stuff // @@ -5528,7 +5495,9 @@ void LLAppViewer::disconnectViewer() } saveNameCache(); - saveExperienceCache(); + LLExperienceCache *expCache = LLExperienceCache::getIfExists(); + if (expCache) + expCache->cleanup(); // close inventory interface, close all windows LLFloaterInventory::cleanup(); diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 718871138e..e8a1ca036b 100755 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -122,9 +122,6 @@ public: void loadNameCache(); void saveNameCache(); - void loadExperienceCache(); - void saveExperienceCache(); - void removeMarkerFiles(); void removeDumpDir(); @@ -233,7 +230,6 @@ private: void idle(); void idleShutdown(); // update avatar SLID and display name caches - void idleExperienceCache(); void idleNameCache(); void idleNetwork(); diff --git a/indra/newview/llcoproceduremanager.cpp b/indra/newview/llcoproceduremanager.cpp deleted file mode 100644 index db01c13079..0000000000 --- a/indra/newview/llcoproceduremanager.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/** -* @file LLCoprocedurePool.cpp -* @author Rider Linden -* @brief Singleton class for managing asset uploads to the sim. -* -* $LicenseInfo:firstyear=2015&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2015, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#include "llviewerprecompiledheaders.h" -#include "linden_common.h" - -#include "llviewercontrol.h" - -#include "llcoproceduremanager.h" - -//========================================================================= -// Map of pool sizes for known pools -static std::map DefaultPoolSizes; - -// *TODO$: When C++11 this can be initialized here as follows: -// = {{"AIS", 25}, {"Upload", 1}} - -#define DEFAULT_POOL_SIZE 5 - -//========================================================================= -class LLCoprocedurePool: private boost::noncopyable -{ -public: - typedef LLCoprocedureManager::CoProcedure_t CoProcedure_t; - - LLCoprocedurePool(const std::string &name, size_t size); - virtual ~LLCoprocedurePool(); - - /// Places the coprocedure on the queue for processing. - /// - /// @param name Is used for debugging and should identify this coroutine. - /// @param proc Is a bound function to be executed - /// - /// @return This method returns a UUID that can be used later to cancel execution. - LLUUID enqueueCoprocedure(const std::string &name, CoProcedure_t proc); - - /// Cancel a coprocedure. If the coprocedure is already being actively executed - /// this method calls cancelYieldingOperation() on the associated HttpAdapter - /// If it has not yet been dequeued it is simply removed from the queue. - bool cancelCoprocedure(const LLUUID &id); - - /// Requests a shutdown of the upload manager. Passing 'true' will perform - /// an immediate kill on the upload coroutine. - void shutdown(bool hardShutdown = false); - - /// Returns the number of coprocedures in the queue awaiting processing. - /// - inline size_t countPending() const - { - return mPendingCoprocs.size(); - } - - /// Returns the number of coprocedures actively being processed. - /// - inline size_t countActive() const - { - return mActiveCoprocs.size(); - } - - /// Returns the total number of coprocedures either queued or in active processing. - /// - inline size_t count() const - { - return countPending() + countActive(); - } - -private: - struct QueuedCoproc - { - typedef boost::shared_ptr ptr_t; - - QueuedCoproc(const std::string &name, const LLUUID &id, CoProcedure_t proc) : - mName(name), - mId(id), - mProc(proc) - {} - - std::string mName; - LLUUID mId; - CoProcedure_t mProc; - }; - - // we use a deque here rather than std::queue since we want to be able to - // iterate through the queue and potentially erase an entry from the middle. - typedef std::deque CoprocQueue_t; - typedef std::map ActiveCoproc_t; - - std::string mPoolName; - size_t mPoolSize; - CoprocQueue_t mPendingCoprocs; - ActiveCoproc_t mActiveCoprocs; - bool mShutdown; - LLEventStream mWakeupTrigger; - - typedef std::map CoroAdapterMap_t; - LLCore::HttpRequest::policy_t mHTTPPolicy; - - CoroAdapterMap_t mCoroMapping; - - void coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter); - -}; - -//========================================================================= -LLCoprocedureManager::LLCoprocedureManager() -{ - DefaultPoolSizes.insert(std::map::value_type("Upload", 1)); - DefaultPoolSizes.insert(std::map::value_type("AIS", 25)); -} - -LLCoprocedureManager::~LLCoprocedureManager() -{ - -} - -LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std::string &poolName) -{ - // Attempt to look up a pool size in the configuration. If found use that - std::string keyName = "PoolSize" + poolName; - int size = 5; - - size = gSavedSettings.getU32(keyName); - if (size == 0) - { // if not found grab the know default... if there is no known - // default use a reasonable number like 5. - std::map::iterator it = DefaultPoolSizes.find(poolName); - if (it == DefaultPoolSizes.end()) - size = DEFAULT_POOL_SIZE; - else - size = (*it).second; - gSavedSettings.declareU32(keyName, size, "Coroutine Pool size for " + poolName, LLControlVariable::PERSIST_ALWAYS); - LL_WARNS() << "LLCoprocedureManager: No setting for \"" << keyName << "\" setting pool size to default of " << size << LL_ENDL; - } - - poolPtr_t pool = poolPtr_t(new LLCoprocedurePool(poolName, size)); - mPoolMap.insert(poolMap_t::value_type(poolName, pool)); - - return pool; -} - -//------------------------------------------------------------------------- -LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc) -{ - // Attempt to find the pool and enqueue the procedure. If the pool does - // not exist, create it. - poolPtr_t targetPool; - poolMap_t::iterator it = mPoolMap.find(pool); - - if (it == mPoolMap.end()) - { - targetPool = initializePool(pool); - } - else - { - targetPool = (*it).second; - } - - if (!targetPool) - { - LL_WARNS() << "LLCoprocedureManager unable to create coprocedure pool named \"" << pool << "\"" << LL_ENDL; - return LLUUID::null; - } - - return targetPool->enqueueCoprocedure(name, proc); -} - -void LLCoprocedureManager::cancelCoprocedure(const LLUUID &id) -{ - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - if ((*it).second->cancelCoprocedure(id)) - return; - } - LL_INFOS() << "Coprocedure not found." << LL_ENDL; -} - -void LLCoprocedureManager::shutdown(bool hardShutdown) -{ - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - (*it).second->shutdown(hardShutdown); - } - mPoolMap.clear(); -} - -//------------------------------------------------------------------------- -size_t LLCoprocedureManager::countPending() const -{ - size_t count = 0; - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - count += (*it).second->countPending(); - } - return count; -} - -size_t LLCoprocedureManager::countPending(const std::string &pool) const -{ - poolMap_t::const_iterator it = mPoolMap.find(pool); - - if (it == mPoolMap.end()) - return 0; - return (*it).second->countPending(); -} - -size_t LLCoprocedureManager::countActive() const -{ - size_t count = 0; - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - count += (*it).second->countActive(); - } - return count; -} - -size_t LLCoprocedureManager::countActive(const std::string &pool) const -{ - poolMap_t::const_iterator it = mPoolMap.find(pool); - - if (it == mPoolMap.end()) - return 0; - return (*it).second->countActive(); -} - -size_t LLCoprocedureManager::count() const -{ - size_t count = 0; - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - count += (*it).second->count(); - } - return count; -} - -size_t LLCoprocedureManager::count(const std::string &pool) const -{ - poolMap_t::const_iterator it = mPoolMap.find(pool); - - if (it == mPoolMap.end()) - return 0; - return (*it).second->count(); -} - -//========================================================================= -LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size): - mPoolName(poolName), - mPoolSize(size), - mPendingCoprocs(), - mShutdown(false), - mWakeupTrigger("CoprocedurePool" + poolName, true), - mCoroMapping(), - mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID) -{ - for (size_t count = 0; count < mPoolSize; ++count) - { - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter = - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t( - new LLCoreHttpUtil::HttpCoroutineAdapter( mPoolName + "Adapter", mHTTPPolicy)); - - std::string uploadCoro = LLCoros::instance().launch("LLCoprocedurePool("+mPoolName+")::coprocedureInvokerCoro", - boost::bind(&LLCoprocedurePool::coprocedureInvokerCoro, this, httpAdapter)); - - mCoroMapping.insert(CoroAdapterMap_t::value_type(uploadCoro, httpAdapter)); - } - - LL_INFOS() << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items." << LL_ENDL; - - mWakeupTrigger.post(LLSD()); -} - -LLCoprocedurePool::~LLCoprocedurePool() -{ - shutdown(); -} - -//------------------------------------------------------------------------- -void LLCoprocedurePool::shutdown(bool hardShutdown) -{ - CoroAdapterMap_t::iterator it; - - for (it = mCoroMapping.begin(); it != mCoroMapping.end(); ++it) - { - if (!(*it).first.empty()) - { - if (hardShutdown) - { - LLCoros::instance().kill((*it).first); - } - } - if ((*it).second) - { - (*it).second->cancelYieldingOperation(); - } - } - - mShutdown = true; - mCoroMapping.clear(); - mPendingCoprocs.clear(); -} - -//------------------------------------------------------------------------- -LLUUID LLCoprocedurePool::enqueueCoprocedure(const std::string &name, LLCoprocedurePool::CoProcedure_t proc) -{ - LLUUID id(LLUUID::generateNewID()); - - mPendingCoprocs.push_back(QueuedCoproc::ptr_t(new QueuedCoproc(name, id, proc))); - LL_INFOS() << "Coprocedure(" << name << ") enqueued with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; - - mWakeupTrigger.post(LLSD()); - - return id; -} - -bool LLCoprocedurePool::cancelCoprocedure(const LLUUID &id) -{ - // first check the active coroutines. If there, remove it and return. - ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(id); - if (itActive != mActiveCoprocs.end()) - { - LL_INFOS() << "Found and canceling active coprocedure with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; - (*itActive).second->cancelYieldingOperation(); - mActiveCoprocs.erase(itActive); - return true; - } - - for (CoprocQueue_t::iterator it = mPendingCoprocs.begin(); it != mPendingCoprocs.end(); ++it) - { - if ((*it)->mId == id) - { - LL_INFOS() << "Found and removing queued coroutine(" << (*it)->mName << ") with Id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; - mPendingCoprocs.erase(it); - return true; - } - } - - LL_INFOS() << "Coprocedure with Id=" << id.asString() << " was not found." << " in pool \"" << mPoolName << "\"" << LL_ENDL; - return false; -} - -//------------------------------------------------------------------------- -void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter) -{ - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - - while (!mShutdown) - { - llcoro::waitForEventOn(mWakeupTrigger); - if (mShutdown) - break; - - while (!mPendingCoprocs.empty()) - { - QueuedCoproc::ptr_t coproc = mPendingCoprocs.front(); - mPendingCoprocs.pop_front(); - mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)); - - LL_INFOS() << "Dequeued and invoking coprocedure(" << coproc->mName << ") with id=" << coproc->mId.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; - - try - { - coproc->mProc(httpAdapter, coproc->mId); - } - catch (std::exception &e) - { - LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() << - " threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL; - } - catch (...) - { - LL_WARNS() << "A non std::exception was thrown from " << coproc->mName << " with id=" << coproc->mId << "." << " in pool \"" << mPoolName << "\"" << LL_ENDL; - } - - LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL; - - ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(coproc->mId); - if (itActive != mActiveCoprocs.end()) - { - mActiveCoprocs.erase(itActive); - } - } - } -} diff --git a/indra/newview/llcoproceduremanager.h b/indra/newview/llcoproceduremanager.h deleted file mode 100644 index d7f74af76b..0000000000 --- a/indra/newview/llcoproceduremanager.h +++ /dev/null @@ -1,87 +0,0 @@ -/** -* @file llcoproceduremanager.h -* @author Rider Linden -* @brief Singleton class for managing asset uploads to the sim. -* -* $LicenseInfo:firstyear=2015&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2015, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#ifndef LL_COPROCEDURE_MANAGER_H -#define LL_COPROCEDURE_MANAGER_H - -#include "lleventcoro.h" -#include "llcoros.h" -#include "llcorehttputil.h" -#include "lluuid.h" - -class LLCoprocedurePool; - -class LLCoprocedureManager : public LLSingleton < LLCoprocedureManager > -{ -public: - typedef boost::function CoProcedure_t; - - LLCoprocedureManager(); - virtual ~LLCoprocedureManager(); - - /// Places the coprocedure on the queue for processing. - /// - /// @param name Is used for debugging and should identify this coroutine. - /// @param proc Is a bound function to be executed - /// - /// @return This method returns a UUID that can be used later to cancel execution. - LLUUID enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc); - - /// Cancel a coprocedure. If the coprocedure is already being actively executed - /// this method calls cancelYieldingOperation() on the associated HttpAdapter - /// If it has not yet been dequeued it is simply removed from the queue. - void cancelCoprocedure(const LLUUID &id); - - /// Requests a shutdown of the upload manager. Passing 'true' will perform - /// an immediate kill on the upload coroutine. - void shutdown(bool hardShutdown = false); - - /// Returns the number of coprocedures in the queue awaiting processing. - /// - size_t countPending() const; - size_t countPending(const std::string &pool) const; - - /// Returns the number of coprocedures actively being processed. - /// - size_t countActive() const; - size_t countActive(const std::string &pool) const; - - /// Returns the total number of coprocedures either queued or in active processing. - /// - size_t count() const; - size_t count(const std::string &pool) const; - -private: - typedef boost::shared_ptr poolPtr_t; - typedef std::map poolMap_t; - - poolMap_t mPoolMap; - - poolPtr_t initializePool(const std::string &poolName); -}; - -#endif diff --git a/indra/newview/llexperienceassociationresponder.cpp b/indra/newview/llexperienceassociationresponder.cpp index b50c81eedc..cd4a7516b1 100644 --- a/indra/newview/llexperienceassociationresponder.cpp +++ b/indra/newview/llexperienceassociationresponder.cpp @@ -83,7 +83,7 @@ void ExperienceAssociationResponder::httpSuccess() return; } - LLExperienceCache::get(getContent()["experience"].asUUID(), boost::bind(&ExperienceAssociationResponder::sendResult, this, _1)); + LLExperienceCache::getInstance()->get(getContent()["experience"].asUUID(), boost::bind(&ExperienceAssociationResponder::sendResult, this, _1)); } diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp index 197162487d..8a04f9e4cc 100644 --- a/indra/newview/llfloaterexperienceprofile.cpp +++ b/indra/newview/llfloaterexperienceprofile.cpp @@ -99,7 +99,7 @@ public: if(params.size() != 2 || params[1].asString() != "profile") return false; - LLExperienceCache::get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1)); + LLExperienceCache::getInstance()->get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1)); return true; } @@ -288,8 +288,8 @@ BOOL LLFloaterExperienceProfile::postBuild() if (mExperienceId.notNull()) { - LLExperienceCache::fetch(mExperienceId, true); - LLExperienceCache::get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback, + LLExperienceCache::getInstance()->fetch(mExperienceId, true); + LLExperienceCache::getInstance()->get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback, getDerivedHandle(), _1)); LLViewerRegion* region = gAgent.getRegion(); @@ -799,8 +799,8 @@ void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content ) } refreshExperience(*it); - LLExperienceCache::insert(*it); - LLExperienceCache::fetch(id, true); + LLExperienceCache::getInstance()->insert(*it); + LLExperienceCache::getInstance()->fetch(id, true); if(mSaveCompleteAction==VIEW) { diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 370d0f4f1b..714d8d0e8f 100755 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -268,7 +268,7 @@ void LLFloaterReporter::getExperienceInfo(const LLUUID& experience_id) if (LLUUID::null != mExperienceID) { - const LLSD& experience = LLExperienceCache::get(mExperienceID); + const LLSD& experience = LLExperienceCache::getInstance()->get(mExperienceID); std::stringstream desc; if(experience.isDefined()) diff --git a/indra/newview/llpanelexperiencelisteditor.cpp b/indra/newview/llpanelexperiencelisteditor.cpp index fc4ee9862e..20fe0c52fa 100644 --- a/indra/newview/llpanelexperiencelisteditor.cpp +++ b/indra/newview/llpanelexperiencelisteditor.cpp @@ -183,7 +183,7 @@ void LLPanelExperienceListEditor::onItems() columns[0]["value"] = getString("loading"); mItems->addElement(item); - LLExperienceCache::get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, + LLExperienceCache::getInstance()->get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, getDerivedHandle(), _1)); } diff --git a/indra/newview/llpanelexperiencelog.cpp b/indra/newview/llpanelexperiencelog.cpp index df03ef7526..9329d900b1 100644 --- a/indra/newview/llpanelexperiencelog.cpp +++ b/indra/newview/llpanelexperiencelog.cpp @@ -140,7 +140,7 @@ void LLPanelExperienceLog::refresh() } const LLSD event = dayArray[i]; LLUUID id = event[LLExperienceCache::EXPERIENCE_ID].asUUID(); - const LLSD& experience = LLExperienceCache::get(id); + const LLSD& experience = LLExperienceCache::getInstance()->get(id); if(experience.isUndefined()){ waiting = true; waiting_id = id; @@ -168,7 +168,7 @@ void LLPanelExperienceLog::refresh() { mEventList->deleteAllItems(); mEventList->setCommentText(getString("loading")); - LLExperienceCache::get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this)); + LLExperienceCache::getInstance()->get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this)); } else { diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp index c7a353a6af..7c19e32e7e 100644 --- a/indra/newview/llpanelexperiencepicker.cpp +++ b/indra/newview/llpanelexperiencepicker.cpp @@ -238,7 +238,7 @@ void LLPanelExperiencePicker::processResponse( const LLUUID& query_id, const LLS LLSD::array_const_iterator it = experiences.beginArray(); for ( ; it != experiences.endArray(); ++it) { - LLExperienceCache::insert(*it); + LLExperienceCache::getInstance()->insert(*it); } getChildView(BTN_RIGHT)->setEnabled(content.has("next_page_url")); diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index a548d7b705..4f5d21b6be 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1326,7 +1326,7 @@ void LLLiveLSLEditor::buildExperienceList() position = ADD_TOP; } - const LLSD& experience = LLExperienceCache::get(id); + const LLSD& experience = LLExperienceCache::getInstance()->get(id); if(experience.isUndefined()) { mExperiences->add(getString("loading"), id, position); @@ -1345,7 +1345,7 @@ void LLLiveLSLEditor::buildExperienceList() if(!foundAssociated ) { - const LLSD& experience = LLExperienceCache::get(associated); + const LLSD& experience = LLExperienceCache::getInstance()->get(associated); if(experience.isDefined()) { std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); @@ -1366,7 +1366,7 @@ void LLLiveLSLEditor::buildExperienceList() if(last.notNull()) { mExperiences->setEnabled(FALSE); - LLExperienceCache::get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); + LLExperienceCache::getInstance()->get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); } else { diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 46f75c4f57..361cc6c48b 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2821,9 +2821,10 @@ void LLStartUp::initNameCache() void LLStartUp::initExperiences() { - // just a get instance here. Should trigger loading the cache. - LLExperienceCache::getInstance(); - LLAppViewer::instance()->loadExperienceCache(); + // Should trigger loading the cache. + LLExperienceCache::getInstance()->setCapabilityQuery( + boost::bind(&LLAgent::getRegionCapability, &gAgent, _1)); + LLExperienceLog::instance().initialize(); } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 886725be79..4e1a86bb71 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6653,7 +6653,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data) else if(experienceid.notNull()) { payload["experience"]=experienceid; - LLExperienceCache::get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); + LLExperienceCache::getInstance()->get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); return; } -- cgit v1.3 From 8913ed6692fddc5d72ee01ecb92a21093c5d22ad Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Thu, 3 Sep 2015 16:59:00 -0700 Subject: Changes from code review with Nat --- indra/llmessage/llcoproceduremanager.cpp | 36 +++++++++------------------ indra/llui/llurlentry.cpp | 4 +-- indra/newview/llcompilequeue.cpp | 2 +- indra/newview/llfloaterexperienceprofile.cpp | 10 ++++---- indra/newview/llfloaterregioninfo.cpp | 4 +-- indra/newview/llfloaterreporter.cpp | 2 +- indra/newview/llpanelexperiencelisteditor.cpp | 2 +- indra/newview/llpanelexperiencelog.cpp | 4 +-- indra/newview/llpanelexperiencepicker.cpp | 2 +- indra/newview/llpanelgroupexperiences.cpp | 2 +- indra/newview/llpreviewscript.cpp | 8 +++--- indra/newview/llsidepaneliteminfo.cpp | 2 +- indra/newview/llstartup.cpp | 2 +- indra/newview/llviewermessage.cpp | 2 +- 14 files changed, 35 insertions(+), 47 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp index c9dfcae293..68da248ee4 100644 --- a/indra/llmessage/llcoproceduremanager.cpp +++ b/indra/llmessage/llcoproceduremanager.cpp @@ -140,6 +140,8 @@ LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std:: std::string keyName = "PoolSize" + poolName; int size = 0; + LL_ERRS_IF(poolName.empty(), "CoprocedureManager") << "Poolname must not be empty" << LL_ENDL; + if (mPropertyQueryFn && !mPropertyQueryFn.empty()) { size = mPropertyQueryFn(keyName); @@ -159,9 +161,10 @@ LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std:: LL_WARNS() << "LLCoprocedureManager: No setting for \"" << keyName << "\" setting pool size to default of " << size << LL_ENDL; } - poolPtr_t pool = poolPtr_t(new LLCoprocedurePool(poolName, size)); + poolPtr_t pool(new LLCoprocedurePool(poolName, size)); mPoolMap.insert(poolMap_t::value_type(poolName, pool)); + LL_ERRS_IF(!pool, "CoprocedureManager") << "Unable to create pool named \"" << poolName << "\" FATAL!" << LL_ENDL; return pool; } @@ -182,12 +185,6 @@ LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const s targetPool = (*it).second; } - if (!targetPool) - { - LL_WARNS() << "LLCoprocedureManager unable to create coprocedure pool named \"" << pool << "\"" << LL_ENDL; - return LLUUID::null; - } - return targetPool->enqueueCoprocedure(name, proc); } @@ -286,14 +283,12 @@ LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size): { for (size_t count = 0; count < mPoolSize; ++count) { - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter = - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t( - new LLCoreHttpUtil::HttpCoroutineAdapter( mPoolName + "Adapter", mHTTPPolicy)); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter( mPoolName + "Adapter", mHTTPPolicy)); - std::string uploadCoro = LLCoros::instance().launch("LLCoprocedurePool("+mPoolName+")::coprocedureInvokerCoro", + std::string pooledCoro = LLCoros::instance().launch("LLCoprocedurePool("+mPoolName+")::coprocedureInvokerCoro", boost::bind(&LLCoprocedurePool::coprocedureInvokerCoro, this, httpAdapter)); - mCoroMapping.insert(CoroAdapterMap_t::value_type(uploadCoro, httpAdapter)); + mCoroMapping.insert(CoroAdapterMap_t::value_type(pooledCoro, httpAdapter)); } LL_INFOS() << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items." << LL_ENDL; @@ -313,12 +308,9 @@ void LLCoprocedurePool::shutdown(bool hardShutdown) for (it = mCoroMapping.begin(); it != mCoroMapping.end(); ++it) { - if (!(*it).first.empty()) + if (hardShutdown) { - if (hardShutdown) - { - LLCoros::instance().kill((*it).first); - } + LLCoros::instance().kill((*it).first); } if ((*it).second) { @@ -366,7 +358,7 @@ bool LLCoprocedurePool::cancelCoprocedure(const LLUUID &id) } } - LL_INFOS() << "Coprocedure with Id=" << id.asString() << " was not found." << " in pool \"" << mPoolName << "\"" << LL_ENDL; + LL_INFOS() << "Coprocedure with Id=" << id.asString() << " was not found in pool \"" << mPoolName << "\"" << LL_ENDL; return false; } @@ -385,7 +377,7 @@ void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdap { QueuedCoproc::ptr_t coproc = mPendingCoprocs.front(); mPendingCoprocs.pop_front(); - mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)); + ActiveCoproc_t::iterator itActive = mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)).first; LL_INFOS() << "Dequeued and invoking coprocedure(" << coproc->mName << ") with id=" << coproc->mId.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; @@ -405,11 +397,7 @@ void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdap LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL; - ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(coproc->mId); - if (itActive != mActiveCoprocs.end()) - { - mActiveCoprocs.erase(itActive); - } + mActiveCoprocs.erase(itActive); } } } diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index e76f2a1550..72ff89f33c 100755 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -1430,7 +1430,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const return LLTrans::getString("ExperienceNameNull"); } - const LLSD& experience_details = LLExperienceCache::getInstance()->get(experience_id); + const LLSD& experience_details = LLExperienceCache::instance().get(experience_id); if(!experience_details.isUndefined()) { std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString(); @@ -1438,7 +1438,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const } addObserver(experience_id_string, url, cb); - LLExperienceCache::getInstance()->get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1)); + LLExperienceCache::instance().get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1)); return LLTrans::getString("LoadingData"); } diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index b52ccffed9..219bcf0eb0 100755 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -357,7 +357,7 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object, LLScriptQueueData* datap = new LLScriptQueueData(getKey().asUUID(), viewer_object->getID(), itemp); - LLExperienceCache::getInstance()->fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(), + LLExperienceCache::instance().fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(), boost::bind(&LLFloaterCompileQueue::requestAsset, datap, _1)); } } diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp index 8a04f9e4cc..e850be99ab 100644 --- a/indra/newview/llfloaterexperienceprofile.cpp +++ b/indra/newview/llfloaterexperienceprofile.cpp @@ -99,7 +99,7 @@ public: if(params.size() != 2 || params[1].asString() != "profile") return false; - LLExperienceCache::getInstance()->get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1)); + LLExperienceCache::instance().get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1)); return true; } @@ -288,8 +288,8 @@ BOOL LLFloaterExperienceProfile::postBuild() if (mExperienceId.notNull()) { - LLExperienceCache::getInstance()->fetch(mExperienceId, true); - LLExperienceCache::getInstance()->get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback, + LLExperienceCache::instance().fetch(mExperienceId, true); + LLExperienceCache::instance().get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback, getDerivedHandle(), _1)); LLViewerRegion* region = gAgent.getRegion(); @@ -799,8 +799,8 @@ void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content ) } refreshExperience(*it); - LLExperienceCache::getInstance()->insert(*it); - LLExperienceCache::getInstance()->fetch(id, true); + LLExperienceCache::instance().insert(*it); + LLExperienceCache::instance().fetch(id, true); if(mSaveCompleteAction==VIEW) { diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index a166dda8ee..94f3a45d88 100755 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -3699,7 +3699,7 @@ bool LLPanelRegionExperiences::refreshFromRegion(LLViewerRegion* region) mTrusted->loading(); mTrusted->setReadonly(!allow_modify); - LLExperienceCache::getInstance()->getRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1), + LLExperienceCache::instance().getRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1), boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle(), _1)); return LLPanelRegionInfo::refreshFromRegion(region); @@ -3727,7 +3727,7 @@ BOOL LLPanelRegionExperiences::sendUpdate() content["blocked"]=addIds(mBlocked); content["trusted"]=addIds(mTrusted); - LLExperienceCache::getInstance()->setRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1), + LLExperienceCache::instance().setRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1), content, boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle(), _1)); return TRUE; diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 714d8d0e8f..1c2340b0ef 100755 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -268,7 +268,7 @@ void LLFloaterReporter::getExperienceInfo(const LLUUID& experience_id) if (LLUUID::null != mExperienceID) { - const LLSD& experience = LLExperienceCache::getInstance()->get(mExperienceID); + const LLSD& experience = LLExperienceCache::instance().get(mExperienceID); std::stringstream desc; if(experience.isDefined()) diff --git a/indra/newview/llpanelexperiencelisteditor.cpp b/indra/newview/llpanelexperiencelisteditor.cpp index 20fe0c52fa..9d52a1906b 100644 --- a/indra/newview/llpanelexperiencelisteditor.cpp +++ b/indra/newview/llpanelexperiencelisteditor.cpp @@ -183,7 +183,7 @@ void LLPanelExperienceListEditor::onItems() columns[0]["value"] = getString("loading"); mItems->addElement(item); - LLExperienceCache::getInstance()->get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, + LLExperienceCache::instance().get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, getDerivedHandle(), _1)); } diff --git a/indra/newview/llpanelexperiencelog.cpp b/indra/newview/llpanelexperiencelog.cpp index 9329d900b1..d5979b6e96 100644 --- a/indra/newview/llpanelexperiencelog.cpp +++ b/indra/newview/llpanelexperiencelog.cpp @@ -140,7 +140,7 @@ void LLPanelExperienceLog::refresh() } const LLSD event = dayArray[i]; LLUUID id = event[LLExperienceCache::EXPERIENCE_ID].asUUID(); - const LLSD& experience = LLExperienceCache::getInstance()->get(id); + const LLSD& experience = LLExperienceCache::instance().get(id); if(experience.isUndefined()){ waiting = true; waiting_id = id; @@ -168,7 +168,7 @@ void LLPanelExperienceLog::refresh() { mEventList->deleteAllItems(); mEventList->setCommentText(getString("loading")); - LLExperienceCache::getInstance()->get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this)); + LLExperienceCache::instance().get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this)); } else { diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp index db846ffad9..d71ced443b 100644 --- a/indra/newview/llpanelexperiencepicker.cpp +++ b/indra/newview/llpanelexperiencepicker.cpp @@ -130,7 +130,7 @@ void LLPanelExperiencePicker::find() std::string text = getChild(TEXT_EDIT)->getValue().asString(); mQueryID.generate(); - LLExperienceCache::getInstance()->findExperienceByName(text, mCurrentPage, + LLExperienceCache::instance().findExperienceByName(text, mCurrentPage, boost::bind(&LLPanelExperiencePicker::findResults, getDerivedHandle(), mQueryID, _1)); getChild(LIST_RESULTS)->deleteAllItems(); diff --git a/indra/newview/llpanelgroupexperiences.cpp b/indra/newview/llpanelgroupexperiences.cpp index 067f9eb426..9b4c67a120 100644 --- a/indra/newview/llpanelgroupexperiences.cpp +++ b/indra/newview/llpanelgroupexperiences.cpp @@ -73,7 +73,7 @@ void LLPanelGroupExperiences::activate() return; } - LLExperienceCache::getInstance()->getGroupExperiences(getGroupID(), + LLExperienceCache::instance().getGroupExperiences(getGroupID(), boost::bind(&LLPanelGroupExperiences::groupExperiencesResults, getDerivedHandle(), _1)); } diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 8a493b7084..5f029ca6a2 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1325,7 +1325,7 @@ void LLLiveLSLEditor::buildExperienceList() position = ADD_TOP; } - const LLSD& experience = LLExperienceCache::getInstance()->get(id); + const LLSD& experience = LLExperienceCache::instance().get(id); if(experience.isUndefined()) { mExperiences->add(getString("loading"), id, position); @@ -1344,7 +1344,7 @@ void LLLiveLSLEditor::buildExperienceList() if(!foundAssociated ) { - const LLSD& experience = LLExperienceCache::getInstance()->get(associated); + const LLSD& experience = LLExperienceCache::instance().get(associated); if(experience.isDefined()) { std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); @@ -1365,7 +1365,7 @@ void LLLiveLSLEditor::buildExperienceList() if(last.notNull()) { mExperiences->setEnabled(FALSE); - LLExperienceCache::getInstance()->get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); + LLExperienceCache::instance().get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); } else { @@ -2038,7 +2038,7 @@ void LLLiveLSLEditor::loadAsset() if(item) { - LLExperienceCache::getInstance()->fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), + LLExperienceCache::instance().fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), boost::bind(&LLLiveLSLEditor::setAssociatedExperience, getDerivedHandle(), _1)); bool isGodlike = gAgent.isGodlike(); diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp index ca17fe77b1..12cbff888d 100755 --- a/indra/newview/llsidepaneliteminfo.cpp +++ b/indra/newview/llsidepaneliteminfo.cpp @@ -328,7 +328,7 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item) tb->setText(getString("loading_experience")); tb->setVisible(TRUE); - LLExperienceCache::getInstance()->fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), + LLExperienceCache::instance().fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), boost::bind(&LLSidepanelItemInfo::setAssociatedExperience, getDerivedHandle(), _1)); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 361cc6c48b..4246f72202 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2822,7 +2822,7 @@ void LLStartUp::initNameCache() void LLStartUp::initExperiences() { // Should trigger loading the cache. - LLExperienceCache::getInstance()->setCapabilityQuery( + LLExperienceCache::instance().setCapabilityQuery( boost::bind(&LLAgent::getRegionCapability, &gAgent, _1)); LLExperienceLog::instance().initialize(); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 4e1a86bb71..ea8fc07e8a 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6653,7 +6653,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data) else if(experienceid.notNull()) { payload["experience"]=experienceid; - LLExperienceCache::getInstance()->get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); + LLExperienceCache::instance().get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); return; } -- cgit v1.3 From 97236a42ca08979897d5c7b0826312345754cd67 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Mon, 14 Sep 2015 11:15:23 -0700 Subject: MAINT-5507: Remove HTTPClient and related cruft. --- indra/llmessage/CMakeLists.txt | 3 - indra/llmessage/llcorehttputil.cpp | 4 + indra/llmessage/llcorehttputil.h | 1 + indra/llmessage/llexperiencecache.cpp | 1 - indra/llmessage/llhttpclient.cpp | 677 --------------------------- indra/llmessage/llhttpclient.h | 201 -------- indra/llmessage/llhttpclientinterface.h | 45 -- indra/llmessage/message.cpp | 1 - indra/newview/CMakeLists.txt | 7 - indra/newview/llaisapi.cpp | 2 +- indra/newview/llaisapi.h | 1 - indra/newview/llappviewer.cpp | 3 - indra/newview/lleventpoll.h | 1 - indra/newview/llfloaterexperienceprofile.cpp | 1 - indra/newview/llfloaterexperiences.cpp | 1 - indra/newview/llgroupmgr.cpp | 1 - indra/newview/llmarketplacefunctions.cpp | 1 - indra/newview/llmeshrepository.h | 1 + indra/newview/llpanelexperiencepicker.cpp | 1 - indra/newview/llpanelgroupexperiences.cpp | 1 - indra/newview/llsecapi.cpp | 41 -- indra/newview/llsecapi.h | 3 - indra/newview/llsidepanelinventory.cpp | 1 - indra/newview/llstartup.cpp | 1 - indra/newview/lltranslate.cpp | 22 - indra/newview/lltranslate.h | 2 - indra/newview/lluploadfloaterobservers.h | 1 - indra/newview/llviewermenufile.cpp | 1 - indra/newview/llviewerregion.cpp | 1 - indra/newview/tests/lltranslate_test.cpp | 340 -------------- 30 files changed, 7 insertions(+), 1360 deletions(-) delete mode 100755 indra/llmessage/llhttpclient.cpp delete mode 100755 indra/llmessage/llhttpclient.h delete mode 100755 indra/llmessage/llhttpclientinterface.h delete mode 100755 indra/newview/tests/lltranslate_test.cpp (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 41b618f8c3..aa00faf3f7 100755 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -48,7 +48,6 @@ set(llmessage_SOURCE_FILES llexperiencecache.cpp llfiltersd2xmlrpc.cpp llhost.cpp - llhttpclient.cpp llhttpconstants.cpp llhttpnode.cpp llhttpsdhandler.cpp @@ -140,8 +139,6 @@ set(llmessage_HEADER_FILES llfiltersd2xmlrpc.h llfollowcamparams.h llhost.h - llhttpclient.h - llhttpclientinterface.h llhttpconstants.h llhttpnode.h llhttpnodeadapter.h diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index 4c2e2c5ee7..106df15bf1 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -46,6 +46,10 @@ using namespace LLCore; namespace LLCoreHttpUtil { + +const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f; + + void logMessageSuccess(std::string logAuth, std::string url, std::string message) { LL_INFOS() << logAuth << " Success '" << message << "' for " << url << LL_ENDL; diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h index 6599a4f01a..94800b1a5b 100644 --- a/indra/llmessage/llcorehttputil.h +++ b/indra/llmessage/llcorehttputil.h @@ -57,6 +57,7 @@ /// namespace LLCoreHttpUtil { + extern const F32 HTTP_REQUEST_EXPIRY_SECS; /// Attempt to convert a response object's contents to LLSD. /// It is expected that the response body will be of non-zero diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp index 0fd6836948..ff5f7e793d 100644 --- a/indra/llmessage/llexperiencecache.cpp +++ b/indra/llmessage/llexperiencecache.cpp @@ -26,7 +26,6 @@ #include "llexperiencecache.h" #include "llavatarname.h" -#include "llhttpclient.h" #include "llsdserialize.h" #include "llcoros.h" #include "lleventcoro.h" diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp deleted file mode 100755 index b149d24c4b..0000000000 --- a/indra/llmessage/llhttpclient.cpp +++ /dev/null @@ -1,677 +0,0 @@ -/** - * @file llhttpclient.cpp - * @brief Implementation of classes for making HTTP requests. - * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include -#include "llhttpclient.h" - -#include "llassetstorage.h" -#include "lliopipe.h" -#include "llurlrequest.h" -#include "llbufferstream.h" -#include "llsdserialize.h" -#include "llvfile.h" -#include "llvfs.h" -#include "lluri.h" - -#include "message.h" -#include "httpcommon.h" -#include "httprequest.h" -#include "httpoptions.h" - -#include - - -const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f; -LLURLRequest::SSLCertVerifyCallback LLHTTPClient::mCertVerifyCallback = NULL; - -//////////////////////////////////////////////////////////////////////////// - -// Responder class moved to LLCurl - -namespace -{ - class LLHTTPClientURLAdaptor : public LLURLRequestComplete - { - public: - LLHTTPClientURLAdaptor(LLCurl::ResponderPtr responder) - : LLURLRequestComplete(), mResponder(responder), mStatus(HTTP_INTERNAL_ERROR), - mReason("LLURLRequest complete w/no status") - { - } - - ~LLHTTPClientURLAdaptor() - { - } - - virtual void httpStatus(S32 status, const std::string& reason) - { - LLURLRequestComplete::httpStatus(status,reason); - - mStatus = status; - mReason = reason; - } - - virtual void complete(const LLChannelDescriptors& channels, - const buffer_ptr_t& buffer) - { - // *TODO: Re-interpret mRequestStatus codes? - // Would like to detect curl errors, such as - // connection errors, write erros, etc. - if (mResponder.get()) - { - mResponder->setResult(mStatus, mReason); - mResponder->completedRaw(channels, buffer); - } - } - virtual void header(const std::string& header, const std::string& value) - { - if (mResponder.get()) - { - mResponder->setResponseHeader(header, value); - } - } - - private: - LLCurl::ResponderPtr mResponder; - S32 mStatus; - std::string mReason; - }; - - class Injector : public LLIOPipe - { - public: - virtual const std::string& contentType() = 0; - }; - - class LLSDInjector : public Injector - { - public: - LLSDInjector(const LLSD& sd) : mSD(sd) {} - virtual ~LLSDInjector() {} - - const std::string& contentType() { return HTTP_CONTENT_LLSD_XML; } - - virtual EStatus process_impl(const LLChannelDescriptors& channels, - buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) - { - LLBufferStream ostream(channels, buffer.get()); - LLSDSerialize::toXML(mSD, ostream); - eos = true; - return STATUS_DONE; - } - - const LLSD mSD; - }; - - class RawInjector : public Injector - { - public: - RawInjector(const U8* data, S32 size) : mData(data), mSize(size) {} - virtual ~RawInjector() {delete [] mData;} - - const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; } - - virtual EStatus process_impl(const LLChannelDescriptors& channels, - buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) - { - LLBufferStream ostream(channels, buffer.get()); - ostream.write((const char *)mData, mSize); // hopefully chars are always U8s - eos = true; - return STATUS_DONE; - } - - const U8* mData; - S32 mSize; - }; - - class FileInjector : public Injector - { - public: - FileInjector(const std::string& filename) : mFilename(filename) {} - virtual ~FileInjector() {} - - const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; } - - virtual EStatus process_impl(const LLChannelDescriptors& channels, - buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) - { - LLBufferStream ostream(channels, buffer.get()); - - llifstream fstream(mFilename.c_str(), std::iostream::binary | std::iostream::out); - if(fstream.is_open()) - { - fstream.seekg(0, std::ios::end); - U32 fileSize = (U32)fstream.tellg(); - fstream.seekg(0, std::ios::beg); - std::vector fileBuffer(fileSize); - fstream.read(&fileBuffer[0], fileSize); - ostream.write(&fileBuffer[0], fileSize); - fstream.close(); - eos = true; - return STATUS_DONE; - } - - return STATUS_ERROR; - } - - const std::string mFilename; - }; - - class VFileInjector : public Injector - { - public: - VFileInjector(const LLUUID& uuid, LLAssetType::EType asset_type) : mUUID(uuid), mAssetType(asset_type) {} - virtual ~VFileInjector() {} - - const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; } - - virtual EStatus process_impl(const LLChannelDescriptors& channels, - buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) - { - LLBufferStream ostream(channels, buffer.get()); - - LLVFile vfile(gVFS, mUUID, mAssetType, LLVFile::READ); - S32 fileSize = vfile.getSize(); - U8* fileBuffer; - fileBuffer = new U8 [fileSize]; - vfile.read(fileBuffer, fileSize); - ostream.write((char*)fileBuffer, fileSize); - delete [] fileBuffer; - eos = true; - return STATUS_DONE; - } - - const LLUUID mUUID; - LLAssetType::EType mAssetType; - }; - - - LLPumpIO* theClientPump = NULL; -} - -void LLHTTPClient::setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback callback) -{ - LLHTTPClient::mCertVerifyCallback = callback; -} - -static void request( - const std::string& url, - EHTTPMethod method, - Injector* body_injector, - LLCurl::ResponderPtr responder, - const F32 timeout = HTTP_REQUEST_EXPIRY_SECS, - const LLSD& headers = LLSD(), - bool follow_redirects = true - ) -{ - if (!LLHTTPClient::hasPump()) - { - if (responder) - { - responder->completeResult(HTTP_INTERNAL_ERROR, "No pump"); - } - delete body_injector; - return; - } - LLPumpIO::chain_t chain; - - LLURLRequest* req = new LLURLRequest(method, url, follow_redirects); - if(!req->isValid())//failed - { - if (responder) - { - responder->completeResult(HTTP_INTERNAL_CURL_ERROR, "Internal Error - curl failure"); - } - delete req; - delete body_injector; - return; - } - - req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req); - - LL_DEBUGS("LLHTTPClient") << httpMethodAsVerb(method) << " " << url << " " << headers << LL_ENDL; - - // Insert custom headers if the caller sent any - if (headers.isMap()) - { - if (headers.has(HTTP_OUT_HEADER_COOKIE)) - { - req->allowCookies(); - } - - LLSD::map_const_iterator iter = headers.beginMap(); - LLSD::map_const_iterator end = headers.endMap(); - - for (; iter != end; ++iter) - { - //if the header is "Pragma" with no value - //the caller intends to force libcurl to drop - //the Pragma header it so gratuitously inserts - //Before inserting the header, force libcurl - //to not use the proxy (read: llurlrequest.cpp) - if ((iter->first == HTTP_OUT_HEADER_PRAGMA) && (iter->second.asString().empty())) - { - req->useProxy(false); - } - LL_DEBUGS("LLHTTPClient") << "header = " << iter->first - << ": " << iter->second.asString() << LL_ENDL; - req->addHeader(iter->first, iter->second.asString()); - } - } - - // Check to see if we have already set Accept or not. If no one - // set it, set it to application/llsd+xml since that's what we - // almost always want. - if( method != HTTP_PUT && method != HTTP_POST ) - { - if(!headers.has(HTTP_OUT_HEADER_ACCEPT)) - { - req->addHeader(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML); - } - } - - if (responder) - { - responder->setURL(url); - responder->setHTTPMethod(method); - } - - req->setCallback(new LLHTTPClientURLAdaptor(responder)); - - if (method == HTTP_POST && gMessageSystem) - { - req->addHeader("X-SecondLife-UDP-Listen-Port", llformat("%d", - gMessageSystem->mPort)); - } - - if (method == HTTP_PUT || method == HTTP_POST || method == HTTP_PATCH) - { - if(!headers.has(HTTP_OUT_HEADER_CONTENT_TYPE)) - { - // If the Content-Type header was passed in, it has - // already been added as a header through req->addHeader - // in the loop above. We defer to the caller's wisdom, but - // if they did not specify a Content-Type, then ask the - // injector. - req->addHeader(HTTP_OUT_HEADER_CONTENT_TYPE, body_injector->contentType()); - } - chain.push_back(LLIOPipe::ptr_t(body_injector)); - } - - chain.push_back(LLIOPipe::ptr_t(req)); - - theClientPump->addChain(chain, timeout); -} - - -void LLHTTPClient::getByteRange( - const std::string& url, - S32 offset, - S32 bytes, - ResponderPtr responder, - const LLSD& hdrs, - const F32 timeout, - bool follow_redirects /* = true */) -{ - LLSD headers = hdrs; - if(offset > 0 || bytes > 0) - { - std::string range = llformat("bytes=%d-%d", offset, offset+bytes-1); - headers[HTTP_OUT_HEADER_RANGE] = range; - } - request(url,HTTP_GET, NULL, responder, timeout, headers, follow_redirects); -} - -void LLHTTPClient::head( - const std::string& url, - ResponderPtr responder, - const LLSD& headers, - const F32 timeout, - bool follow_redirects /* = true */) -{ - request(url, HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects); -} - -void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout, - bool follow_redirects /* = true */) -{ - request(url, HTTP_GET, NULL, responder, timeout, headers, follow_redirects); -} -void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const LLSD& headers, - const F32 timeout, bool follow_redirects /* = true */) -{ - request(url, HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects); -} -void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const F32 timeout, - bool follow_redirects /* = true */) -{ - getHeaderOnly(url, responder, LLSD(), timeout, follow_redirects); -} - -void LLHTTPClient::get(const std::string& url, const LLSD& query, ResponderPtr responder, const LLSD& headers, - const F32 timeout, bool follow_redirects /* = true */) -{ - LLURI uri; - - uri = LLURI::buildHTTP(url, LLSD::emptyArray(), query); - get(uri.asString(), responder, headers, timeout, follow_redirects); -} - -// A simple class for managing data returned from a curl http request. -class LLHTTPBuffer -{ -public: - LLHTTPBuffer() { } - - static size_t curl_write( void *ptr, size_t size, size_t nmemb, void *user_data) - { - LLHTTPBuffer* self = (LLHTTPBuffer*)user_data; - - size_t bytes = (size * nmemb); - self->mBuffer.append((char*)ptr,bytes); - return nmemb; - } - - LLSD asLLSD() - { - LLSD content; - - if (mBuffer.empty()) return content; - - std::istringstream istr(mBuffer); - LLSDSerialize::fromXML(content, istr); - return content; - } - - const std::string& asString() - { - return mBuffer; - } - -private: - std::string mBuffer; -}; - -// These calls are blocking! This is usually bad, unless you're a dataserver. Then it's awesome. - -/** - @brief does a blocking request on the url, returning the data or bad status. - - @param url URI to verb on. - @param method the verb to hit the URI with. - @param body the body of the call (if needed - for instance not used for GET and DELETE, but is for POST and PUT) - @param headers HTTP headers to use for the request. - @param timeout Curl timeout to use. Defaults to 5. Rationale: - Without this timeout, blockingGet() calls have been observed to take - up to 90 seconds to complete. Users of blockingGet() already must - check the HTTP return code for validity, so this will not introduce - new errors. A 5 second timeout will succeed > 95% of the time (and - probably > 99% of the time) based on my statistics. JC - - @returns an LLSD map: {status: integer, body: map} - */ -static LLSD blocking_request( - const std::string& url, - EHTTPMethod method, - const LLSD& body, - const LLSD& headers = LLSD(), - const F32 timeout = 5 -) -{ - LL_DEBUGS() << "blockingRequest of " << url << LL_ENDL; - char curl_error_buffer[CURL_ERROR_SIZE] = "\0"; - CURL* curlp = LLCurl::newEasyHandle(); - llassert_always(curlp != NULL) ; - - LLHTTPBuffer http_buffer; - std::string body_str; - - // other request method checks root cert first, we skip? - - // Apply configured proxy settings - LLProxy::getInstance()->applyProxySettings(curlp); - - // * Set curl handle options - curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1); // don't use SIGALRM for timeouts - curl_easy_setopt(curlp, CURLOPT_TIMEOUT, timeout); // seconds, see warning at top of function. - curl_easy_setopt(curlp, CURLOPT_WRITEFUNCTION, LLHTTPBuffer::curl_write); - curl_easy_setopt(curlp, CURLOPT_WRITEDATA, &http_buffer); - curl_easy_setopt(curlp, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer); - - // * Setup headers (don't forget to free them after the call!) - curl_slist* headers_list = NULL; - if (headers.isMap()) - { - LLSD::map_const_iterator iter = headers.beginMap(); - LLSD::map_const_iterator end = headers.endMap(); - for (; iter != end; ++iter) - { - std::ostringstream header; - header << iter->first << ": " << iter->second.asString() ; - LL_DEBUGS() << "header = " << header.str() << LL_ENDL; - headers_list = curl_slist_append(headers_list, header.str().c_str()); - } - } - - // * Setup specific method / "verb" for the URI (currently only GET and POST supported + poppy) - if (method == HTTP_GET) - { - curl_easy_setopt(curlp, CURLOPT_HTTPGET, 1); - } - else if (method == HTTP_POST) - { - curl_easy_setopt(curlp, CURLOPT_POST, 1); - //serialize to ostr then copy to str - need to because ostr ptr is unstable :( - std::ostringstream ostr; - LLSDSerialize::toXML(body, ostr); - body_str = ostr.str(); - curl_easy_setopt(curlp, CURLOPT_POSTFIELDS, body_str.c_str()); - //copied from PHP libs, correct? - headers_list = curl_slist_append(headers_list, - llformat("%s: %s", HTTP_OUT_HEADER_CONTENT_TYPE.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str()); - - // copied from llurlrequest.cpp - // it appears that apache2.2.3 or django in etch is busted. If - // we do not clear the expect header, we get a 500. May be - // limited to django/mod_wsgi. - headers_list = curl_slist_append(headers_list, llformat("%s:", HTTP_OUT_HEADER_EXPECT.c_str()).c_str()); - } - - // * Do the action using curl, handle results - LL_DEBUGS() << "HTTP body: " << body_str << LL_ENDL; - headers_list = curl_slist_append(headers_list, - llformat("%s: %s", HTTP_OUT_HEADER_ACCEPT.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str()); - CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, headers_list); - if ( curl_result != CURLE_OK ) - { - LL_INFOS() << "Curl is hosed - can't add headers" << LL_ENDL; - } - - LLSD response = LLSD::emptyMap(); - S32 curl_success = curl_easy_perform(curlp); - S32 http_status = HTTP_INTERNAL_ERROR; - curl_easy_getinfo(curlp, CURLINFO_RESPONSE_CODE, &http_status); - response["status"] = http_status; - // if we get a non-404 and it's not a 200 OR maybe it is but you have error bits, - if ( http_status != HTTP_NOT_FOUND && (http_status != HTTP_OK || curl_success != 0) ) - { - // We expect 404s, don't spam for them. - LL_WARNS() << "CURL REQ URL: " << url << LL_ENDL; - LL_WARNS() << "CURL REQ METHOD TYPE: " << method << LL_ENDL; - LL_WARNS() << "CURL REQ HEADERS: " << headers.asString() << LL_ENDL; - LL_WARNS() << "CURL REQ BODY: " << body_str << LL_ENDL; - LL_WARNS() << "CURL HTTP_STATUS: " << http_status << LL_ENDL; - LL_WARNS() << "CURL ERROR: " << curl_error_buffer << LL_ENDL; - LL_WARNS() << "CURL ERROR BODY: " << http_buffer.asString() << LL_ENDL; - response["body"] = http_buffer.asString(); - } - else - { - response["body"] = http_buffer.asLLSD(); - LL_DEBUGS() << "CURL response: " << http_buffer.asString() << LL_ENDL; - } - - if(headers_list) - { // free the header list - curl_slist_free_all(headers_list); - } - - // * Cleanup - LLCurl::deleteEasyHandle(curlp); - return response; -} - -LLSD LLHTTPClient::blockingGet(const std::string& url) -{ - return blocking_request(url, HTTP_GET, LLSD()); -} - -LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body) -{ - return blocking_request(url, HTTP_POST, body); -} - -void LLHTTPClient::put( - const std::string& url, - const LLSD& body, - ResponderPtr responder, - const LLSD& headers, - const F32 timeout) -{ - request(url, HTTP_PUT, new LLSDInjector(body), responder, timeout, headers); -} - -void LLHTTPClient::patch( - const std::string& url, - const LLSD& body, - ResponderPtr responder, - const LLSD& headers, - const F32 timeout) -{ - request(url, HTTP_PATCH, new LLSDInjector(body), responder, timeout, headers); -} - -void LLHTTPClient::putRaw( - const std::string& url, - const U8* data, - S32 size, - ResponderPtr responder, - const LLSD& headers, - const F32 timeout) -{ - request(url, HTTP_PUT, new RawInjector(data, size), responder, timeout, headers); -} - -void LLHTTPClient::post( - const std::string& url, - const LLSD& body, - ResponderPtr responder, - const LLSD& headers, - const F32 timeout) -{ - request(url, HTTP_POST, new LLSDInjector(body), responder, timeout, headers); -} - -void LLHTTPClient::postRaw( - const std::string& url, - const U8* data, - S32 size, - ResponderPtr responder, - const LLSD& headers, - const F32 timeout) -{ - request(url, HTTP_POST, new RawInjector(data, size), responder, timeout, headers); -} - -void LLHTTPClient::postFile( - const std::string& url, - const std::string& filename, - ResponderPtr responder, - const LLSD& headers, - const F32 timeout) -{ - request(url, HTTP_POST, new FileInjector(filename), responder, timeout, headers); -} - -void LLHTTPClient::postFile( - const std::string& url, - const LLUUID& uuid, - LLAssetType::EType asset_type, - ResponderPtr responder, - const LLSD& headers, - const F32 timeout) -{ - request(url, HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout, headers); -} - -// static -void LLHTTPClient::del( - const std::string& url, - ResponderPtr responder, - const LLSD& headers, - const F32 timeout) -{ - request(url, HTTP_DELETE, NULL, responder, timeout, headers); -} - -// static -void LLHTTPClient::move( - const std::string& url, - const std::string& destination, - ResponderPtr responder, - const LLSD& hdrs, - const F32 timeout) -{ - LLSD headers = hdrs; - headers[HTTP_OUT_HEADER_DESTINATION] = destination; - request(url, HTTP_MOVE, NULL, responder, timeout, headers); -} - -// static -void LLHTTPClient::copy( - const std::string& url, - const std::string& destination, - ResponderPtr responder, - const LLSD& hdrs, - const F32 timeout) -{ - LLSD headers = hdrs; - headers[HTTP_OUT_HEADER_DESTINATION] = destination; - request(url, HTTP_COPY, NULL, responder, timeout, headers); -} - - -void LLHTTPClient::setPump(LLPumpIO& pump) -{ - theClientPump = &pump; -} - -bool LLHTTPClient::hasPump() -{ - return theClientPump != NULL; -} diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h deleted file mode 100755 index fd48b4a743..0000000000 --- a/indra/llmessage/llhttpclient.h +++ /dev/null @@ -1,201 +0,0 @@ -/** - * @file llhttpclient.h - * @brief Declaration of classes for making HTTP client requests. - * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLHTTPCLIENT_H -#define LL_LLHTTPCLIENT_H - -/** - * These classes represent the HTTP client framework. - */ - -#include - -#include -#include -#include "llurlrequest.h" -#include "llassettype.h" -#include "llcurl.h" -#include "lliopipe.h" - -extern const F32 HTTP_REQUEST_EXPIRY_SECS; - -class LLUUID; -class LLPumpIO; -class LLSD; - - -class LLHTTPClient -{ -public: - // class Responder moved to LLCurl - - // For convenience - typedef LLCurl::Responder Responder; - typedef LLCurl::ResponderPtr ResponderPtr; - - - /** @name non-blocking API */ - //@{ - static void head( - const std::string& url, - ResponderPtr, - const LLSD& headers = LLSD(), - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, - bool follow_redirects = true); - static void getByteRange(const std::string& url, S32 offset, S32 bytes, ResponderPtr, - const LLSD& headers=LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, - bool follow_redirects = true); - static void get(const std::string& url, ResponderPtr, const LLSD& headers = LLSD(), - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, bool follow_redirects = true); - static void get(const std::string& url, const LLSD& query, ResponderPtr, const LLSD& headers = LLSD(), - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, bool follow_redirects = true); - - static void put( - const std::string& url, - const LLSD& body, - ResponderPtr, - const LLSD& headers = LLSD(), - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); - static void putRaw( - const std::string& url, - const U8* data, - S32 size, - ResponderPtr responder, - const LLSD& headers = LLSD(), - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); - - - static void patch( - const std::string& url, - const LLSD& body, - ResponderPtr, - const LLSD& headers = LLSD(), - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); - - static void getHeaderOnly(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, - bool follow_redirects = true); - static void getHeaderOnly(const std::string& url, ResponderPtr, const LLSD& headers, - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, bool follow_redirects = true); - - static void post( - const std::string& url, - const LLSD& body, - ResponderPtr, - const LLSD& headers = LLSD(), - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); - /** Takes ownership of data and deletes it when sent */ - static void postRaw( - const std::string& url, - const U8* data, - S32 size, - ResponderPtr responder, - const LLSD& headers = LLSD(), - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); - static void postFile( - const std::string& url, - const std::string& filename, - ResponderPtr, - const LLSD& headers = LLSD(), - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); - static void postFile( - const std::string& url, - const LLUUID& uuid, - LLAssetType::EType asset_type, - ResponderPtr responder, - const LLSD& headers = LLSD(), - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); - - static void del( - const std::string& url, - ResponderPtr responder, - const LLSD& headers = LLSD(), - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); - ///< sends a DELETE method, but we can't call it delete in c++ - - /** - * @brief Send a MOVE webdav method - * - * @param url The complete serialized (and escaped) url to get. - * @param destination The complete serialized destination url. - * @param responder The responder that will handle the result. - * @param headers A map of key:value headers to pass to the request - * @param timeout The number of seconds to give the server to respond. - */ - static void move( - const std::string& url, - const std::string& destination, - ResponderPtr responder, - const LLSD& headers = LLSD(), - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); - - /** - * @brief Send a COPY webdav method - * - * @param url The complete serialized (and escaped) url to get. - * @param destination The complete serialized destination url. - * @param responder The responder that will handle the result. - * @param headers A map of key:value headers to pass to the request - * @param timeout The number of seconds to give the server to respond. - */ - static void copy( - const std::string& url, - const std::string& destination, - ResponderPtr responder, - const LLSD& headers = LLSD(), - const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); - - //@} - - /** - * @brief Blocking HTTP get that returns an LLSD map of status and body. - * - * @param url the complete serialized (and escaped) url to get - * @return An LLSD of { 'status':status, 'body':payload } - */ - static LLSD blockingGet(const std::string& url); - - /** - * @brief Blocking HTTP POST that returns an LLSD map of status and body. - * - * @param url the complete serialized (and escaped) url to get - * @param body the LLSD post body - * @return An LLSD of { 'status':status (an int), 'body':payload (an LLSD) } - */ - static LLSD blockingPost(const std::string& url, const LLSD& body); - - - static void setPump(LLPumpIO& pump); - ///< must be called before any of the above calls are made - static bool hasPump(); - - static void setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback callback); - static LLURLRequest::SSLCertVerifyCallback getCertVerifyCallback() { return mCertVerifyCallback; } - -protected: - static LLURLRequest::SSLCertVerifyCallback mCertVerifyCallback; -}; - -#endif // LL_LLHTTPCLIENT_H diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h deleted file mode 100755 index 9c1c8e7c11..0000000000 --- a/indra/llmessage/llhttpclientinterface.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @file llhttpclientinterface.h - * @brief - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLHTTPCLIENTINTERFACE_H -#define LL_LLHTTPCLIENTINTERFACE_H - -#include "linden_common.h" -#include "llcurl.h" - -#include - -// class LLHTTPClientInterface -// { -// public: -// virtual ~LLHTTPClientInterface() {} -// virtual void get(const std::string& url, LLCurl::ResponderPtr responder) = 0; -// virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) = 0; -// virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder) = 0; -// }; - -#endif // LL_LLHTTPCLIENTINTERFACE_H - diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 10dbbef046..4f9aa5d2de 100755 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -50,7 +50,6 @@ #include "lldir.h" #include "llerror.h" #include "llfasttimer.h" -#include "llhttpclient.h" #include "llhttpnodeadapter.h" #include "llmd5.h" #include "llmessagebuilder.h" diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7eb4174b7f..af51c6dc36 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2224,7 +2224,6 @@ if (LL_TESTS) # llmediadataclient.cpp lllogininstance.cpp # llremoteparcelrequest.cpp -# lltranslate.cpp llviewerhelputil.cpp llversioninfo.cpp llworldmap.cpp @@ -2245,12 +2244,6 @@ if (LL_TESTS) ${CURL_LIBRARIES} ) -# set_source_files_properties( -# lltranslate.cpp -# PROPERTIES -# LL_TEST_ADDITIONAL_LIBRARIES "${test_libs}" -# ) - set_source_files_properties( llmediadataclient.cpp PROPERTIES diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index da2f69126a..2d877f6a47 100755 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -380,7 +380,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest()); LLCore::HttpHeaders::ptr_t httpHeaders; - httpOptions->setTimeout(HTTP_REQUEST_EXPIRY_SECS); + httpOptions->setTimeout(LLCoreHttpUtil::HTTP_REQUEST_EXPIRY_SECS); LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 2de8003c2f..48c081991a 100755 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -32,7 +32,6 @@ #include #include #include "llcurl.h" -#include "llhttpclient.h" #include "llhttpretrypolicy.h" #include "llviewerinventory.h" #include "llcorehttputil.h" diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index e13a9d96c7..16dac4a9e5 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1160,8 +1160,6 @@ bool LLAppViewer::init() { LLNotificationsUtil::add("CorruptedProtectedDataStore"); } - LLHTTPClient::setCertVerifyCallback(secapiSSLCertVerifyCallback); - gGLActive = FALSE; @@ -1315,7 +1313,6 @@ bool LLAppViewer::mainLoop() // Create IO Pump to use for HTTP Requests. gServicePump = new LLPumpIO(gAPRPoolp); - LLHTTPClient::setPump(*gServicePump); LLCurl::setCAFile(gDirUtilp->getCAFile()); // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. diff --git a/indra/newview/lleventpoll.h b/indra/newview/lleventpoll.h index e32b4ed322..e2afd9226b 100755 --- a/indra/newview/lleventpoll.h +++ b/indra/newview/lleventpoll.h @@ -27,7 +27,6 @@ #ifndef LL_LLEVENTPOLL_H #define LL_LLEVENTPOLL_H -#include "llhttpclient.h" #include "boost/move/unique_ptr.hpp" namespace boost diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp index dd1c6dce0a..d44eb4310d 100644 --- a/indra/newview/llfloaterexperienceprofile.cpp +++ b/indra/newview/llfloaterexperienceprofile.cpp @@ -36,7 +36,6 @@ #include "llexpandabletextbox.h" #include "llexperiencecache.h" #include "llfloaterreg.h" -#include "llhttpclient.h" #include "lllayoutstack.h" #include "lllineeditor.h" #include "llnotificationsutil.h" diff --git a/indra/newview/llfloaterexperiences.cpp b/indra/newview/llfloaterexperiences.cpp index 14fbdb3a8f..bdab9ed868 100644 --- a/indra/newview/llfloaterexperiences.cpp +++ b/indra/newview/llfloaterexperiences.cpp @@ -32,7 +32,6 @@ #include "llevents.h" #include "llexperiencecache.h" #include "llfloaterregioninfo.h" -#include "llhttpclient.h" #include "llnotificationsutil.h" #include "llpanelexperiencelog.h" #include "llpanelexperiencepicker.h" diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index eda9e51d23..b218f4f756 100755 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -41,7 +41,6 @@ #include "llui.h" #include "message.h" #include "roles_constants.h" -#include "llhttpclient.h" #include "lltransactiontypes.h" #include "llstatusbar.h" #include "lleconomy.h" diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index cff8446545..b0cd1dd23e 100755 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -30,7 +30,6 @@ #include "llagent.h" #include "llbufferstream.h" -#include "llhttpclient.h" #include "llinventoryfunctions.h" #include "llinventoryobserver.h" #include "llnotificationsutil.h" diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 55157cc040..ed20641312 100755 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -38,6 +38,7 @@ #include "httpoptions.h" #include "httpheaders.h" #include "httphandler.h" +#include "llthread.h" #define LLCONVEXDECOMPINTER_STATIC 1 diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp index d71ced443b..dcc5f4f234 100644 --- a/indra/newview/llpanelexperiencepicker.cpp +++ b/indra/newview/llpanelexperiencepicker.cpp @@ -42,7 +42,6 @@ #include "llviewercontrol.h" #include "llfloater.h" #include "lltrans.h" -#include "llhttpclient.h" // *TODO: Rider, remove when converting #define BTN_FIND "find" #define BTN_OK "ok_btn" diff --git a/indra/newview/llpanelgroupexperiences.cpp b/indra/newview/llpanelgroupexperiences.cpp index 9b4c67a120..a88a55ab22 100644 --- a/indra/newview/llpanelgroupexperiences.cpp +++ b/indra/newview/llpanelgroupexperiences.cpp @@ -31,7 +31,6 @@ #include "lluictrlfactory.h" #include "roles_constants.h" -#include "llhttpclient.h" #include "llagent.h" #include "llviewerregion.h" #include "llflatlistview.h" diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index 43bb7b1596..4f9f83b6f2 100755 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -32,7 +32,6 @@ #include #include #include -#include "llhttpclient.h" @@ -99,46 +98,6 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred) return s << (std::string)cred; } - -// secapiSSLCertVerifyCallback -// basic callback called when a cert verification is requested. -// calls SECAPI to validate the context -// not initialized in the above initialization function, due to unit tests -// see llappviewer - -int secapiSSLCertVerifyCallback(X509_STORE_CTX *ctx, void *param) -{ - LLURLRequest *req = (LLURLRequest *)param; - LLPointer store = gSecAPIHandler->getCertificateStore(""); - LLPointer chain = gSecAPIHandler->getCertificateChain(ctx); - LLSD validation_params = LLSD::emptyMap(); - LLURI uri(req->getURL()); - validation_params[CERT_HOSTNAME] = uri.hostName(); - try - { - // we rely on libcurl to validate the hostname, as libcurl does more extensive validation - // leaving our hostname validation call mechanism for future additions with respect to - // OS native (Mac keyring, windows CAPI) validation. - store->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), chain, validation_params); - } - catch (LLCertValidationTrustException& cert_exception) - { - LL_WARNS("AppInit") << "Cert not trusted: " << cert_exception.getMessage() << LL_ENDL; - return 0; - } - catch (LLCertException& cert_exception) - { - LL_WARNS("AppInit") << "cert error " << cert_exception.getMessage() << LL_ENDL; - return 0; - } - catch (...) - { - LL_WARNS("AppInit") << "cert error " << LL_ENDL; - return 0; - } - return 1; -} - LLSD LLCredential::getLoginParams() { LLSD result = LLSD::emptyMap(); diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index c01d318f56..6fe3ee31cf 100755 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -489,7 +489,4 @@ void registerSecHandler(const std::string& handler_type, extern LLPointer gSecAPIHandler; -int secapiSSLCertVerifyCallback(X509_STORE_CTX *ctx, void *param); - - #endif // LL_SECAPI_H diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 0e23e2ad10..67ac875428 100755 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -37,7 +37,6 @@ #include "llfloatersidepanelcontainer.h" #include "llfoldertype.h" #include "llfolderview.h" -#include "llhttpclient.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 4246f72202..047e23cefc 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -112,7 +112,6 @@ #include "llgroupmgr.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" -#include "llhttpclient.h" #include "llimagebmp.h" #include "llinventorybridge.h" #include "llinventorymodel.h" diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index 1ca2011a70..5390573f7b 100755 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -574,25 +574,3 @@ LLTranslationAPIHandler& LLTranslate::getHandler(EService service) return bing; } - -// static -void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder) -{ - static const float REQUEST_TIMEOUT = 5; - static LLSD sHeader; - - if (!sHeader.size()) - { - std::string user_agent = llformat("%s %d.%d.%d (%d)", - LLVersionInfo::getChannel().c_str(), - LLVersionInfo::getMajor(), - LLVersionInfo::getMinor(), - LLVersionInfo::getPatch(), - LLVersionInfo::getBuild()); - - sHeader.insert(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN); - sHeader.insert(HTTP_OUT_HEADER_USER_AGENT, user_agent); - } - - LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT); -} diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index 49a0105dbb..bf431cdfbb 100755 --- a/indra/newview/lltranslate.h +++ b/indra/newview/lltranslate.h @@ -27,7 +27,6 @@ #ifndef LL_LLTRANSLATE_H #define LL_LLTRANSLATE_H -#include "llhttpclient.h" #include "llbufferstream.h" #include @@ -95,7 +94,6 @@ public : private: static LLTranslationAPIHandler& getPreferredHandler(); static LLTranslationAPIHandler& getHandler(EService service); - static void sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder); }; #endif diff --git a/indra/newview/lluploadfloaterobservers.h b/indra/newview/lluploadfloaterobservers.h index 02baf8f1c0..15c3dad38e 100755 --- a/indra/newview/lluploadfloaterobservers.h +++ b/indra/newview/lluploadfloaterobservers.h @@ -28,7 +28,6 @@ #define LL_LLUPLOADFLOATEROBSERVERS_H #include "llfloater.h" -#include "llhttpclient.h" #include "llhandle.h" class LLUploadPermissionsObserver diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 782a27a846..4f24dfafac 100755 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -66,7 +66,6 @@ // linden libraries #include "lleconomy.h" -#include "llhttpclient.h" #include "llnotificationsutil.h" #include "llsdserialize.h" #include "llsdutil.h" diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 57548b6e8f..4ed90d26b7 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -34,7 +34,6 @@ #include "llavatarnamecache.h" // name lookup cap url #include "llfloaterreg.h" #include "llmath.h" -#include "llhttpclient.h" #include "llregionflags.h" #include "llregionhandle.h" #include "llsurface.h" diff --git a/indra/newview/tests/lltranslate_test.cpp b/indra/newview/tests/lltranslate_test.cpp deleted file mode 100755 index 5e73dbb981..0000000000 --- a/indra/newview/tests/lltranslate_test.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/** - * @file lltranslate_test.cpp - * - * $LicenseInfo:firstyear=2011&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2011, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "../test/lltut.h" -#include "../lltranslate.h" -#include "../llversioninfo.h" -#include "../llviewercontrol.h" - -#include "llbufferstream.h" -#include "lltrans.h" -#include "llui.h" - -#include "../../llmessage/llhttpconstants.cpp" - -static const std::string GOOGLE_VALID_RESPONSE1 = -"{\ - \"data\": {\ - \"translations\": [\ - {\ - \"translatedText\": \"привет\",\ - \"detectedSourceLanguage\": \"es\"\ - }\ - ]\ - }\ -}"; - -static const std::string GOOGLE_VALID_RESPONSE2 = -"{\ - \"data\": {\ - \"translations\": [\ - {\ - \"translatedText\": \"привет\"\ - }\ - ]\ - }\ -}\ -"; - -static const std::string GOOGLE_VALID_RESPONSE3 = -"{\ - \"error\": {\ - \"errors\": [\ - {\ - \"domain\": \"global\",\ - \"reason\": \"invalid\",\ - \"message\": \"Invalid Value\"\ - }\ - ],\ - \"code\": 400,\ - \"message\": \"Invalid Value\"\ - }\ -}"; - -static const std::string BING_VALID_RESPONSE1 = -"Привет"; - -static const std::string BING_VALID_RESPONSE2 = -"

Argument Exception

Method: Translate()

Parameter:

\ -

Message: 'from' must be a valid language

\ -

message id=3743.V2_Rest.Translate.58E8454F

"; - -static const std::string BING_VALID_RESPONSE3 = -"

Argument Exception

Method: Translate()

\ -

Parameter: appId

Message: Invalid appId \nParameter name: appId

\ -

message id=3737.V2_Rest.Translate.56016759

"; - -namespace tut -{ - class translate_test - { - protected: - void test_translation( - LLTranslationAPIHandler& handler, - int status, const std::string& resp, - const std::string& exp_trans, const std::string& exp_lang, const std::string& exp_err) - { - std::string translation, detected_lang, err_msg; - bool rc = handler.parseResponse(status, resp, translation, detected_lang, err_msg); - ensure_equals("rc", rc, (status == 200)); - ensure_equals("err_msg", err_msg, exp_err); - ensure_equals("translation", translation, exp_trans); - ensure_equals("detected_lang", detected_lang, exp_lang); - } - - LLGoogleTranslationHandler mGoogle; - LLBingTranslationHandler mBing; - }; - - typedef test_group translate_test_group_t; - typedef translate_test_group_t::object translate_test_object_t; - tut::translate_test_group_t tut_translate("LLTranslate"); - - template<> template<> - void translate_test_object_t::test<1>() - { - test_translation(mGoogle, 200, GOOGLE_VALID_RESPONSE1, "привет", "es", ""); - } - - template<> template<> - void translate_test_object_t::test<2>() - { - test_translation(mGoogle, 200, GOOGLE_VALID_RESPONSE2, "привет", "", ""); - } - - template<> template<> - void translate_test_object_t::test<3>() - { - test_translation(mGoogle, 400, GOOGLE_VALID_RESPONSE3, "", "", "Invalid Value"); - } - - template<> template<> - void translate_test_object_t::test<4>() - { - test_translation(mGoogle, 400, - "", - "", "", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n"); - } - - template<> template<> - void translate_test_object_t::test<5>() - { - test_translation(mGoogle, 400, - "[]", - "", "", ""); - } - - template<> template<> - void translate_test_object_t::test<6>() - { - test_translation(mGoogle, 400, - "{\"oops\": \"invalid\"}", - "", "", ""); - } - - template<> template<> - void translate_test_object_t::test<7>() - { - test_translation(mGoogle, 400, - "{\"data\": {}}", - "", "", ""); - } - - template<> template<> - void translate_test_object_t::test<8>() - { - test_translation(mGoogle, 400, - "{\"data\": { \"translations\": [ {} ] }}", - "", "", ""); - } - - template<> template<> - void translate_test_object_t::test<9>() - { - test_translation(mGoogle, 400, - "{\"data\": { \"translations\": [ { \"translatedTextZZZ\": \"привет\", \"detectedSourceLanguageZZZ\": \"es\" } ] }}", - "", "", ""); - } - - template<> template<> - void translate_test_object_t::test<10>() - { - test_translation(mBing, 200, BING_VALID_RESPONSE1, "Привет", "", ""); - } - - template<> template<> - void translate_test_object_t::test<11>() - { - test_translation(mBing, 400, BING_VALID_RESPONSE2, "", "", "'from' must be a valid language"); - } - - template<> template<> - void translate_test_object_t::test<12>() - { - test_translation(mBing, 400, BING_VALID_RESPONSE3, "", "", "Invalid appId\nParameter name: appId"); - } - - template<> template<> - void translate_test_object_t::test<13>() - { - test_translation(mBing, 200, - "Привет
", - "Привет", "", ""); - } - - template<> template<> - void translate_test_object_t::test<14>() - { - test_translation(mBing, 200, - "Привет", - "Привет", "", ""); - } - - template<> template<> - void translate_test_object_t::test<15>() - { - test_translation(mBing, 200, - "Привет", - "Привет", "", ""); - } - - template<> template<> - void translate_test_object_t::test<16>() - { - test_translation(mBing, 400, - "Message: some error

", - "", "", "some error"); - } - - template<> template<> - void translate_test_object_t::test<17>() - { - test_translation(mBing, 400, - "Message: some error", - "", "", "some error"); - } - - template<> template<> - void translate_test_object_t::test<18>() - { - test_translation(mBing, 400, - "some error

", - "", "", "some error"); - } - - template<> template<> - void translate_test_object_t::test<19>() - { - test_translation(mBing, 400, - "some error", - "", "", "some error"); - } - - template<> template<> - void translate_test_object_t::test<20>() - { - std::string url; - mBing.getTranslateURL(url, "en", "es", "hi"); - ensure_equals("bing URL", url, - "http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=dummy&text=hi&to=es&from=en"); - } - - template<> template<> - void translate_test_object_t::test<21>() - { - std::string url; - mBing.getTranslateURL(url, "", "es", "hi"); - ensure_equals("bing URL", url, - "http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=dummy&text=hi&to=es"); - } - - template<> template<> - void translate_test_object_t::test<22>() - { - std::string url; - mGoogle.getTranslateURL(url, "en", "es", "hi"); - ensure_equals("google URL", url, - "https://www.googleapis.com/language/translate/v2?key=dummy&q=hi&target=es&source=en"); - } - - template<> template<> - void translate_test_object_t::test<23>() - { - std::string url; - mGoogle.getTranslateURL(url, "", "es", "hi"); - ensure_equals("google URL", url, - "https://www.googleapis.com/language/translate/v2?key=dummy&q=hi&target=es"); - } -} - -//== Misc stubs =============================================================== -LLControlGroup gSavedSettings("test"); - -std::string LLUI::getLanguage() { return "en"; } -std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) { return "dummy"; } - -LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker(name) {} -std::string LLControlGroup::getString(const std::string& name) { return "dummy"; } -LLControlGroup::~LLControlGroup() {} - -LLCurl::Responder::Responder() {} -void LLCurl::Responder::httpFailure() { } -void LLCurl::Responder::httpSuccess() { } -void LLCurl::Responder::httpCompleted() { } -void LLCurl::Responder::completedRaw(LLChannelDescriptors const &,boost::shared_ptr const &) { } -LLCurl::Responder::~Responder() {} - -void LLHTTPClient::get(const std::string&, const LLSD&, ResponderPtr, const LLSD&, const F32, bool) {} -void LLHTTPClient::get(const std::string&, LLPointer, const LLSD&, const F32, bool) {} - -LLBufferStream::LLBufferStream(const LLChannelDescriptors& channels, LLBufferArray* buffer) -: std::iostream(&mStreamBuf), mStreamBuf(channels, buffer) {} -LLBufferStream::~LLBufferStream() {} - -LLBufferStreamBuf::LLBufferStreamBuf(const LLChannelDescriptors&, LLBufferArray*) {} -#if( LL_WINDOWS || __GNUC__ > 2) -LLBufferStreamBuf::pos_type LLBufferStreamBuf::seekoff( - off_type off, - std::ios::seekdir way, - std::ios::openmode which) -#else -streampos LLBufferStreamBuf::seekoff( - streamoff off, - std::ios::seekdir way, - std::ios::openmode which) -#endif -{ return 0; } -int LLBufferStreamBuf::sync() {return 0;} -int LLBufferStreamBuf::underflow() {return 0;} -int LLBufferStreamBuf::overflow(int) {return 0;} -LLBufferStreamBuf::~LLBufferStreamBuf() {} - -S32 LLVersionInfo::getBuild() { return 0; } -const std::string& LLVersionInfo::getChannel() {static std::string dummy; return dummy;} -S32 LLVersionInfo::getMajor() { return 0; } -S32 LLVersionInfo::getMinor() { return 0; } -S32 LLVersionInfo::getPatch() { return 0; } -- cgit v1.3 From 1eed334e7ff1ce261f740f5da7207a65c3f4ef57 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Mon, 21 Sep 2015 10:59:58 -0700 Subject: MAINT-5629: Remove llares and llareslistener. Login now does not attempt to do a lookup on the server names and rewrite the URL. MAINT-5614: Bad password status correctly detected. --- indra/llmessage/CMakeLists.txt | 4 - indra/llmessage/llares.cpp | 839 --------------------- indra/llmessage/llares.h | 583 -------------- indra/llmessage/llareslistener.cpp | 104 --- indra/llmessage/llareslistener.h | 53 -- indra/newview/llappviewer.cpp | 25 - indra/newview/llstartup.cpp | 8 - indra/viewer_components/login/lllogin.cpp | 221 +++--- .../viewer_components/login/tests/lllogin_test.cpp | 191 +---- 9 files changed, 94 insertions(+), 1934 deletions(-) delete mode 100755 indra/llmessage/llares.cpp delete mode 100755 indra/llmessage/llares.h delete mode 100755 indra/llmessage/llareslistener.cpp delete mode 100755 indra/llmessage/llareslistener.h (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 3bcee13d28..5877c4a8e4 100755 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -28,8 +28,6 @@ include_directories( ) set(llmessage_SOURCE_FILES - llares.cpp - llareslistener.cpp llassetstorage.cpp llavatarname.cpp llavatarnamecache.cpp @@ -109,8 +107,6 @@ set(llmessage_SOURCE_FILES set(llmessage_HEADER_FILES CMakeLists.txt - llares.h - llareslistener.h llassetstorage.h llavatarname.h llavatarnamecache.h diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp deleted file mode 100755 index 9f90ae1544..0000000000 --- a/indra/llmessage/llares.cpp +++ /dev/null @@ -1,839 +0,0 @@ -/** - * @file llares.cpp - * @author Bryan O'Sullivan - * @date 2007-08-15 - * @brief Wrapper for asynchronous DNS lookups. - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llares.h" - -#include -#include - -#include "apr_portable.h" -#include "apr_network_io.h" -#include "apr_poll.h" - -#include "llapr.h" -#include "llareslistener.h" - -#if defined(LL_WINDOWS) -#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally -# define ns_c_in 1 -# define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */ -# define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */ -# define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ -#else -# include -#endif - -LLAres::HostResponder::~HostResponder() -{ -} - -void LLAres::HostResponder::hostResult(const hostent *ent) -{ - LL_INFOS() << "LLAres::HostResponder::hostResult not implemented" << LL_ENDL; -} - -void LLAres::HostResponder::hostError(int code) -{ - LL_INFOS() << "LLAres::HostResponder::hostError " << code << ": " - << LLAres::strerror(code) << LL_ENDL; -} - -LLAres::NameInfoResponder::~NameInfoResponder() -{ -} - -void LLAres::NameInfoResponder::nameInfoResult(const char *node, - const char *service) -{ - LL_INFOS() << "LLAres::NameInfoResponder::nameInfoResult not implemented" - << LL_ENDL; -} - -void LLAres::NameInfoResponder::nameInfoError(int code) -{ - LL_INFOS() << "LLAres::NameInfoResponder::nameInfoError " << code << ": " - << LLAres::strerror(code) << LL_ENDL; -} - -LLAres::QueryResponder::~QueryResponder() -{ -} - -void LLAres::QueryResponder::queryResult(const char *buf, size_t len) -{ - LL_INFOS() << "LLAres::QueryResponder::queryResult not implemented" - << LL_ENDL; -} - -void LLAres::QueryResponder::queryError(int code) -{ - LL_INFOS() << "LLAres::QueryResponder::queryError " << code << ": " - << LLAres::strerror(code) << LL_ENDL; -} - -LLAres::LLAres() : - chan_(NULL), - mInitSuccess(false) -{ - if (ares_library_init( ARES_LIB_INIT_ALL ) != ARES_SUCCESS || - ares_init(&chan_) != ARES_SUCCESS) - { - LL_WARNS() << "Could not succesfully initialize ares!" << LL_ENDL; - return; - } - - mListener = boost::shared_ptr< LLAresListener >(new LLAresListener(this)); - - mInitSuccess = true; -} - -LLAres::~LLAres() -{ - ares_destroy(chan_); - ares_library_cleanup(); -} - -void LLAres::cancel() -{ - ares_cancel(chan_); -} - -static void host_callback_1_5(void *arg, int status, int timeouts, - struct hostent *ent) -{ - LLPointer *resp = - (LLPointer *) arg; - - if (status == ARES_SUCCESS) - { - (*resp)->hostResult(ent); - } else { - (*resp)->hostError(status); - } - - delete resp; -} - -#if ARES_VERSION_MAJOR == 1 && ARES_VERSION_MINOR == 4 -static void host_callback(void *arg, int status, struct hostent *ent) -{ - host_callback_1_5(arg, status, 0, ent); -} -#else -# define host_callback host_callback_1_5 -#endif - -void LLAres::getHostByName(const char *name, HostResponder *resp, - int family) -{ - ares_gethostbyname(chan_, name, family, host_callback, - new LLPointer(resp)); -} - -void LLAres::getSrvRecords(const std::string &name, SrvResponder *resp) -{ - search(name, RES_SRV, resp); -} - -void LLAres::rewriteURI(const std::string &uri, UriRewriteResponder *resp) -{ - if (resp && uri.size()) - { - LLURI* pURI = new LLURI(uri); - - resp->mUri = *pURI; - - delete pURI; - - if (!resp->mUri.scheme().size() || !resp->mUri.hostName().size()) - { - return; - } - - //LL_INFOS() << "LLAres::rewriteURI (" << uri << ") search: '" << "_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName() << "'" << LL_ENDL; - - search("_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName(), RES_SRV, resp); - - - } -} - -LLQueryResponder::LLQueryResponder() - : LLAres::QueryResponder(), - mResult(ARES_ENODATA), - mType(RES_INVALID) -{ -} - -int LLQueryResponder::parseRR(const char *buf, size_t len, const char *&pos, - LLPointer &r) -{ - std::string rrname; - size_t enclen; - int ret; - - // RR name. - - ret = LLAres::expandName(pos, buf, len, rrname, enclen); - if (ret != ARES_SUCCESS) - { - return ret; - } - - pos += enclen; - - if (pos + NS_RRFIXEDSZ > buf + len) - { - return ARES_EBADRESP; - } - - int rrtype = DNS_RR_TYPE(pos); - int rrclass = DNS_RR_CLASS(pos); - int rrttl = DNS_RR_TTL(pos); - int rrlen = DNS_RR_LEN(pos); - - if (rrclass != ns_c_in) - { - return ARES_EBADRESP; - } - - pos += NS_RRFIXEDSZ; - - if (pos + rrlen > buf + len) - { - return ARES_EBADRESP; - } - - switch (rrtype) - { - case RES_A: - r = new LLARecord(rrname, rrttl); - break; - case RES_NS: - r = new LLNsRecord(rrname, rrttl); - break; - case RES_CNAME: - r = new LLCnameRecord(rrname, rrttl); - break; - case RES_PTR: - r = new LLPtrRecord(rrname, rrttl); - break; - case RES_AAAA: - r = new LLAaaaRecord(rrname, rrttl); - break; - case RES_SRV: - r = new LLSrvRecord(rrname, rrttl); - break; - default: - LL_INFOS() << "LLQueryResponder::parseRR got unknown RR type " << rrtype - << LL_ENDL; - return ARES_EBADRESP; - } - - ret = r->parse(buf, len, pos, rrlen); - - if (ret == ARES_SUCCESS) - { - pos += rrlen; - } else { - r = NULL; - } - - return ret; -} - -int LLQueryResponder::parseSection(const char *buf, size_t len, - size_t count, const char *&pos, - dns_rrs_t &rrs) -{ - int ret = ARES_SUCCESS; - - for (size_t i = 0; i < count; i++) - { - LLPointer r; - ret = parseRR(buf, len, pos, r); - if (ret != ARES_SUCCESS) - { - break; - } - rrs.push_back(r); - } - - return ret; -} - -void LLQueryResponder::queryResult(const char *buf, size_t len) -{ - const char *pos = buf; - int qdcount = DNS_HEADER_QDCOUNT(pos); - int ancount = DNS_HEADER_ANCOUNT(pos); - int nscount = DNS_HEADER_NSCOUNT(pos); - int arcount = DNS_HEADER_ARCOUNT(pos); - int ret; - - if (qdcount == 0 || ancount + nscount + arcount == 0) - { - ret = ARES_ENODATA; - goto bail; - } - - pos += NS_HFIXEDSZ; - - for (int i = 0; i < qdcount; i++) - { - std::string ignore; - size_t enclen; - - ret = LLAres::expandName(pos, buf, len, i == 0 ? mQuery : ignore, - enclen); - if (ret != ARES_SUCCESS) - { - goto bail; - } - - pos += enclen; - - if (i == 0) - { - int t = DNS_QUESTION_TYPE(pos); - switch (t) - { - case RES_A: - case RES_NS: - case RES_CNAME: - case RES_PTR: - case RES_AAAA: - case RES_SRV: - mType = (LLResType) t; - break; - default: - LL_INFOS() << "Cannot grok query type " << t << LL_ENDL; - ret = ARES_EBADQUERY; - goto bail; - } - } - - pos += NS_QFIXEDSZ; - if (pos > buf + len) - { - ret = ARES_EBADRESP; - goto bail; - } - } - - ret = parseSection(buf, len, ancount, pos, mAnswers); - if (ret != ARES_SUCCESS) - { - goto bail; - } - - ret = parseSection(buf, len, nscount, pos, mAuthorities); - if (ret != ARES_SUCCESS) - { - goto bail; - } - - ret = parseSection(buf, len, arcount, pos, mAdditional); - -bail: - mResult = ret; - if (mResult == ARES_SUCCESS) - { - querySuccess(); - } else { - queryError(mResult); - } -} - -void LLQueryResponder::querySuccess() -{ - LL_INFOS() << "LLQueryResponder::queryResult not implemented" << LL_ENDL; -} - -void LLAres::SrvResponder::querySuccess() -{ - if (mType == RES_SRV) - { - srvResult(mAnswers); - } else { - srvError(ARES_EBADRESP); - } -} - -void LLAres::SrvResponder::queryError(int code) -{ - srvError(code); -} - -void LLAres::SrvResponder::srvResult(const dns_rrs_t &ents) -{ - LL_INFOS() << "LLAres::SrvResponder::srvResult not implemented" << LL_ENDL; - - for (size_t i = 0; i < ents.size(); i++) - { - const LLSrvRecord *s = (const LLSrvRecord *) ents[i].get(); - - LL_INFOS() << "[" << i << "] " << s->host() << ":" << s->port() - << " priority " << s->priority() - << " weight " << s->weight() - << LL_ENDL; - } -} - -void LLAres::SrvResponder::srvError(int code) -{ - LL_INFOS() << "LLAres::SrvResponder::srvError " << code << ": " - << LLAres::strerror(code) << LL_ENDL; -} - -static void nameinfo_callback_1_5(void *arg, int status, int timeouts, - char *node, char *service) -{ - LLPointer *resp = - (LLPointer *) arg; - - if (status == ARES_SUCCESS) - { - (*resp)->nameInfoResult(node, service); - } else { - (*resp)->nameInfoError(status); - } - - delete resp; -} - -#if ARES_VERSION_MAJOR == 1 && ARES_VERSION_MINOR == 4 -static void nameinfo_callback(void *arg, int status, char *node, char *service) -{ - nameinfo_callback_1_5(arg, status, 0, node, service); -} -#else -# define nameinfo_callback nameinfo_callback_1_5 -#endif - -void LLAres::getNameInfo(const struct sockaddr &sa, socklen_t salen, int flags, - NameInfoResponder *resp) -{ - ares_getnameinfo(chan_, &sa, salen, flags, nameinfo_callback, - new LLPointer(resp)); -} - -static void search_callback_1_5(void *arg, int status, int timeouts, - unsigned char *abuf, int alen) -{ - LLPointer *resp = - (LLPointer *) arg; - - if (status == ARES_SUCCESS) - { - (*resp)->queryResult((const char *) abuf, alen); - } else { - (*resp)->queryError(status); - } - - delete resp; -} - -#if ARES_VERSION_MAJOR == 1 && ARES_VERSION_MINOR == 4 -static void search_callback(void *arg, int status, unsigned char *abuf, - int alen) -{ - search_callback_1_5(arg, status, 0, abuf, alen); -} -#else -# define search_callback search_callback_1_5 -#endif - -void LLAres::search(const std::string &query, LLResType type, - QueryResponder *resp) -{ - ares_search(chan_, query.c_str(), ns_c_in, type, search_callback, - new LLPointer(resp)); -} - -bool LLAres::process(U64 timeout) -{ - if (!gAPRPoolp) - { - ll_init_apr(); - } - - ares_socket_t socks[ARES_GETSOCK_MAXNUM]; - apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM]; - apr_int32_t nsds = 0; - int nactive = 0; - int bitmask; - - bitmask = ares_getsock(chan_, socks, ARES_GETSOCK_MAXNUM); - - if (bitmask == 0) - { - return nsds > 0; - } - - apr_status_t status; - LLAPRPool pool; - status = pool.getStatus() ; - ll_apr_assert_status(status); - - for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++) - { - if (ARES_GETSOCK_READABLE(bitmask, i)) - { - aprFds[nactive].reqevents = APR_POLLIN | APR_POLLERR; - } - else if (ARES_GETSOCK_WRITABLE(bitmask, i)) - { - aprFds[nactive].reqevents = APR_POLLOUT | APR_POLLERR; - } else { - continue; - } - - apr_socket_t *aprSock = NULL; - - status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool.getAPRPool()); - if (status != APR_SUCCESS) - { - ll_apr_warn_status(status); - return nsds > 0; - } - - aprFds[nactive].desc.s = aprSock; - aprFds[nactive].desc_type = APR_POLL_SOCKET; - aprFds[nactive].p = pool.getAPRPool(); - aprFds[nactive].rtnevents = 0; - aprFds[nactive].client_data = &socks[i]; - - nactive++; - } - - if (nactive > 0) - { - status = apr_poll(aprFds, nactive, &nsds, timeout); - - if (status != APR_SUCCESS && status != APR_TIMEUP) - { - ll_apr_warn_status(status); - } - - for (int i = 0; i < nactive; i++) - { - int evts = aprFds[i].rtnevents; - int ifd = (evts & (APR_POLLIN | APR_POLLERR)) - ? *((int *) aprFds[i].client_data) : ARES_SOCKET_BAD; - int ofd = (evts & (APR_POLLOUT | APR_POLLERR)) - ? *((int *) aprFds[i].client_data) : ARES_SOCKET_BAD; - - ares_process_fd(chan_, ifd, ofd); - } - } - - return nsds > 0; -} - -bool LLAres::processAll() -{ - bool anyProcessed = false, ret; - - do { - timeval tv; - - ret = ares_timeout(chan_, NULL, &tv) != NULL; - - if (ret) - { - ret = process(tv.tv_sec * 1000000LL + tv.tv_usec); - anyProcessed |= ret; - } - } while (ret); - - return anyProcessed; -} - -int LLAres::expandName(const char *encoded, const char *abuf, size_t alen, - std::string &s, size_t &enclen) -{ - char *t; - int ret; - long e; - - ret = ares_expand_name((const unsigned char *) encoded, - (const unsigned char *) abuf, alen, &t, &e); - if (ret == ARES_SUCCESS) - { - s.assign(t); - enclen = e; - ares_free_string(t); - } - return ret; -} - -const char *LLAres::strerror(int code) -{ - return ares_strerror(code); -} - -LLAres *gAres; - -LLAres *ll_init_ares() -{ - if (gAres == NULL) - { - gAres = new LLAres(); - } - return gAres; -} - -void ll_cleanup_ares() -{ - if (gAres != NULL) - { - delete gAres; - gAres = NULL; - } -} - -LLDnsRecord::LLDnsRecord(LLResType type, const std::string &name, - unsigned ttl) - : LLRefCount(), - mType(type), - mName(name), - mTTL(ttl) -{ -} - -LLHostRecord::LLHostRecord(LLResType type, const std::string &name, - unsigned ttl) - : LLDnsRecord(type, name, ttl) -{ -} - -int LLHostRecord::parse(const char *buf, size_t len, const char *pos, - size_t rrlen) -{ - int ret; - - ret = LLAres::expandName(pos, buf, len, mHost); - if (ret != ARES_SUCCESS) - { - goto bail; - } - - ret = ARES_SUCCESS; - -bail: - return ret; -} - -LLCnameRecord::LLCnameRecord(const std::string &name, unsigned ttl) - : LLHostRecord(RES_CNAME, name, ttl) -{ -} - -LLPtrRecord::LLPtrRecord(const std::string &name, unsigned ttl) - : LLHostRecord(RES_PTR, name, ttl) -{ -} - -LLAddrRecord::LLAddrRecord(LLResType type, const std::string &name, - unsigned ttl) - : LLDnsRecord(type, name, ttl), - - mSize(0) -{ -} - -LLARecord::LLARecord(const std::string &name, unsigned ttl) - : LLAddrRecord(RES_A, name, ttl) -{ -} - -int LLARecord::parse(const char *buf, size_t len, const char *pos, - size_t rrlen) -{ - int ret; - - if (rrlen != sizeof(mSA.sin.sin_addr.s_addr)) - { - ret = ARES_EBADRESP; - goto bail; - } - - memset(&mSA, 0, sizeof(mSA)); - memcpy(&mSA.sin.sin_addr.s_addr, pos, rrlen); - mSA.sin.sin_family = AF_INET6; - mSize = sizeof(mSA.sin); - - ret = ARES_SUCCESS; - -bail: - return ret; -} - -LLAaaaRecord::LLAaaaRecord(const std::string &name, unsigned ttl) - : LLAddrRecord(RES_AAAA, name, ttl) -{ -} - -int LLAaaaRecord::parse(const char *buf, size_t len, const char *pos, - size_t rrlen) -{ - int ret; - - if (rrlen != sizeof(mSA.sin6.sin6_addr)) - { - ret = ARES_EBADRESP; - goto bail; - } - - memset(&mSA, 0, sizeof(mSA)); - memcpy(&mSA.sin6.sin6_addr.s6_addr, pos, rrlen); - mSA.sin6.sin6_family = AF_INET6; - mSize = sizeof(mSA.sin6); - - ret = ARES_SUCCESS; - -bail: - return ret; -} - -LLSrvRecord::LLSrvRecord(const std::string &name, unsigned ttl) - : LLHostRecord(RES_SRV, name, ttl), - - mPriority(0), - mWeight(0), - mPort(0) -{ -} - -int LLSrvRecord::parse(const char *buf, size_t len, const char *pos, - size_t rrlen) -{ - int ret; - - if (rrlen < 6) - { - ret = ARES_EBADRESP; - goto bail; - } - - memcpy(&mPriority, pos, 2); - memcpy(&mWeight, pos + 2, 2); - memcpy(&mPort, pos + 4, 2); - - mPriority = ntohs(mPriority); - mWeight = ntohs(mWeight); - mPort = ntohs(mPort); - - ret = LLHostRecord::parse(buf, len, pos + 6, rrlen - 6); - -bail: - return ret; -} - -LLNsRecord::LLNsRecord(const std::string &name, unsigned ttl) - : LLHostRecord(RES_NS, name, ttl) -{ -} - -void LLAres::UriRewriteResponder::queryError(int code) -{ - std::vector uris; - uris.push_back(mUri.asString()); - rewriteResult(uris); -} - -void LLAres::UriRewriteResponder::querySuccess() -{ - std::vector uris; - - if (mType != RES_SRV) - { - goto bail; - } - - for (size_t i = 0; i < mAnswers.size(); i++) - { - const LLSrvRecord *r = (const LLSrvRecord *) mAnswers[i].get(); - - if (r->type() == RES_SRV) - { - // Check the domain in the response to ensure that it's - // the same as the domain in the request, so that bad guys - // can't forge responses that point to their own login - // servers with their own certificates. - - // Hard-coding the domain to check here is a bit of a - // hack. Hoist it to an outer caller if anyone ever needs - // this functionality on other domains. - - static const std::string domain(".lindenlab.com"); - const std::string &host = r->host(); - - std::string::size_type s = host.find(domain) + domain.length(); - - if (s != host.length() && s != host.length() - 1) - { - continue; - } - - LLURI uri(mUri.scheme(), - mUri.userName(), - mUri.password(), - r->host(), - mUri.defaultPort() ? r->port() : mUri.hostPort(), - mUri.escapedPath(), - mUri.escapedQuery()); - uris.push_back(uri.asString()); - } - } - - if (!uris.empty()) - { - goto done; - } - -bail: - uris.push_back(mUri.asString()); - -done: - rewriteResult(uris); -} - -void LLAres::UriRewriteResponder::rewriteResult( - const std::vector &uris) -{ - LL_INFOS() << "LLAres::UriRewriteResponder::rewriteResult not implemented" - << LL_ENDL; - - for (size_t i = 0; i < uris.size(); i++) - { - LL_INFOS() << "[" << i << "] " << uris[i] << LL_ENDL; - } -} diff --git a/indra/llmessage/llares.h b/indra/llmessage/llares.h deleted file mode 100755 index c727363b60..0000000000 --- a/indra/llmessage/llares.h +++ /dev/null @@ -1,583 +0,0 @@ -/** - * @file llares.h - * @author Bryan O'Sullivan - * @date 2007-08-15 - * @brief Wrapper for asynchronous DNS lookups. - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLARES_H -#define LL_LLARES_H - -#ifdef LL_WINDOWS -// ares.h is broken on windows in that it depends on types defined in ws2tcpip.h -// we need to include them first to work around it, but the headers issue warnings -# pragma warning(push) -# pragma warning(disable:4996) -# include -# include -# pragma warning(pop) -#endif - -#ifdef LL_USESYSTEMLIBS -# include -#else -# include -#endif - -#include "llpointer.h" -#include "llrefcount.h" -#include "lluri.h" - -#include - -class LLQueryResponder; -class LLAresListener; - -/** - * @brief Supported DNS RR types. - */ -enum LLResType -{ - RES_INVALID = 0, /**< Cookie. */ - RES_A = 1, /**< "A" record. IPv4 address. */ - RES_NS = 2, /**< "NS" record. Authoritative server. */ - RES_CNAME = 5, /**< "CNAME" record. Canonical name. */ - RES_PTR = 12, /**< "PTR" record. Domain name pointer. */ - RES_AAAA = 28, /**< "AAAA" record. IPv6 Address. */ - RES_SRV = 33, /**< "SRV" record. Server Selection. */ - RES_MAX = 65536 /**< Sentinel; RR types are 16 bits wide. */ -}; - -/** - * @class LLDnsRecord - * @brief Base class for all DNS RR types. - */ -class LLDnsRecord : public LLRefCount -{ -protected: - friend class LLQueryResponder; - - LLResType mType; - std::string mName; - unsigned mTTL; - - virtual int parse(const char *buf, size_t len, const char *pos, - size_t rrlen) = 0; - - LLDnsRecord(LLResType type, const std::string &name, unsigned ttl); - -public: - /** - * @brief Record name. - */ - const std::string &name() const { return mName; } - - /** - * @brief Time-to-live value, in seconds. - */ - unsigned ttl() const { return mTTL; } - - /** - * @brief RR type. - */ - LLResType type() const { return mType; } -}; - -/** - * @class LLAddrRecord - * @brief Base class for address-related RRs. - */ -class LLAddrRecord : public LLDnsRecord -{ -protected: - friend class LLQueryResponder; - - LLAddrRecord(LLResType type, const std::string &name, unsigned ttl); - - union - { - sockaddr sa; - sockaddr_in sin; - sockaddr_in6 sin6; - } mSA; - - socklen_t mSize; - -public: - /** - * @brief Generic socket address. - */ - const sockaddr &addr() const { return mSA.sa; } - - /** - * @brief Size of the socket structure. - */ - socklen_t size() const { return mSize; } -}; - -/** - * @class LLARecord - * @brief A RR, for IPv4 addresses. - */ -class LLARecord : public LLAddrRecord -{ -protected: - friend class LLQueryResponder; - - LLARecord(const std::string &name, unsigned ttl); - - int parse(const char *buf, size_t len, const char *pos, size_t rrlen); - -public: - /** - * @brief Socket address. - */ - const sockaddr_in &addr_in() const { return mSA.sin; } -}; - -/** - * @class LLAaaaRecord - * @brief AAAA RR, for IPv6 addresses. - */ -class LLAaaaRecord : public LLAddrRecord -{ -protected: - friend class LLQueryResponder; - - LLAaaaRecord(const std::string &name, unsigned ttl); - - int parse(const char *buf, size_t len, const char *pos, size_t rrlen); - -public: - /** - * @brief Socket address. - */ - const sockaddr_in6 &addr_in6() const { return mSA.sin6; } -}; - -/** - * @class LLHostRecord - * @brief Base class for host-related RRs. - */ -class LLHostRecord : public LLDnsRecord -{ -protected: - LLHostRecord(LLResType type, const std::string &name, unsigned ttl); - - int parse(const char *buf, size_t len, const char *pos, size_t rrlen); - - std::string mHost; - -public: - /** - * @brief Host name. - */ - const std::string &host() const { return mHost; } -}; - -/** - * @class LLCnameRecord - * @brief CNAME RR. - */ -class LLCnameRecord : public LLHostRecord -{ -protected: - friend class LLQueryResponder; - - LLCnameRecord(const std::string &name, unsigned ttl); -}; - -/** - * @class LLPtrRecord - * @brief PTR RR. - */ -class LLPtrRecord : public LLHostRecord -{ -protected: - friend class LLQueryResponder; - - LLPtrRecord(const std::string &name, unsigned ttl); -}; - -/** - * @class LLSrvRecord - * @brief SRV RR. - */ -class LLSrvRecord : public LLHostRecord -{ -protected: - U16 mPriority; - U16 mWeight; - U16 mPort; - - int parse(const char *buf, size_t len, const char *pos, size_t rrlen); - -public: - LLSrvRecord(const std::string &name, unsigned ttl); - - /** - * @brief Service priority. - */ - U16 priority() const { return mPriority; } - - /** - * @brief Service weight. - */ - U16 weight() const { return mWeight; } - - /** - * @brief Port number of service. - */ - U16 port() const { return mPort; } - - /** - * @brief Functor for sorting SRV records by priority. - */ - struct ComparePriorityLowest - { - bool operator()(const LLSrvRecord& lhs, const LLSrvRecord& rhs) - { - return lhs.mPriority < rhs.mPriority; - } - }; -}; - -/** - * @class LLNsRecord - * @brief NS RR. - */ -class LLNsRecord : public LLHostRecord -{ -public: - LLNsRecord(const std::string &name, unsigned ttl); -}; - -class LLQueryResponder; - -/** - * @class LLAres - * @brief Asynchronous address resolver. - */ -class LLAres -{ -public: - /** - * @class HostResponder - * @brief Base class for responding to hostname lookups. - * @see LLAres::getHostByName - */ - class HostResponder : public LLRefCount - { - public: - virtual ~HostResponder(); - - virtual void hostResult(const hostent *ent); - virtual void hostError(int code); - }; - - /** - * @class NameInfoResponder - * @brief Base class for responding to address lookups. - * @see LLAres::getNameInfo - */ - class NameInfoResponder : public LLRefCount - { - public: - virtual ~NameInfoResponder(); - - virtual void nameInfoResult(const char *node, const char *service); - virtual void nameInfoError(int code); - }; - - /** - * @class QueryResponder - * @brief Base class for responding to custom searches. - * @see LLAres::search - */ - class QueryResponder : public LLRefCount - { - public: - virtual ~QueryResponder(); - - virtual void queryResult(const char *buf, size_t len); - virtual void queryError(int code); - }; - - class SrvResponder; - class UriRewriteResponder; - - LLAres(); - - ~LLAres(); - - /** - * Cancel all outstanding requests. The error methods of the - * corresponding responders will be called, with ARES_ETIMEOUT. - */ - void cancel(); - - /** - * Look up the address of a host. - * - * @param name name of host to look up - * @param resp responder to call with result - * @param family AF_INET for IPv4 addresses, AF_INET6 for IPv6 - */ - void getHostByName(const std::string &name, HostResponder *resp, - int family = AF_INET) { - getHostByName(name.c_str(), resp, family); - } - - /** - * Look up the address of a host. - * - * @param name name of host to look up - * @param resp responder to call with result - * @param family AF_INET for IPv4 addresses, AF_INET6 for IPv6 - */ - void getHostByName(const char *name, HostResponder *resp, - int family = PF_INET); - - /** - * Look up the name associated with a socket address. - * - * @param sa socket address to look up - * @param salen size of socket address - * @param flags flags to use - * @param resp responder to call with result - */ - void getNameInfo(const struct sockaddr &sa, socklen_t salen, int flags, - NameInfoResponder *resp); - - /** - * Look up SRV (service location) records for a service name. - * - * @param name service name (e.g. "_https._tcp.login.agni.lindenlab.com") - * @param resp responder to call with result - */ - void getSrvRecords(const std::string &name, SrvResponder *resp); - - /** - * Rewrite a URI, using SRV (service location) records for its - * protocol if available. If no SRV records are published, the - * existing URI is handed to the responder. - * - * @param uri URI to rewrite - * @param resp responder to call with result - */ - void rewriteURI(const std::string &uri, - UriRewriteResponder *resp); - - /** - * Start a custom search. - * - * @param query query to make - * @param type type of query to perform - * @param resp responder to call with result - */ - void search(const std::string &query, LLResType type, - QueryResponder *resp); - - /** - * Process any outstanding queries. This method takes an optional - * timeout parameter (specified in microseconds). If provided, it - * will block the calling thread for that length of time to await - * possible responses. A timeout of zero will return immediately - * if there are no responses or timeouts to process. - * - * @param timeoutUsecs number of microseconds to block before timing out - * @return whether any responses were processed - */ - bool process(U64 timeoutUsecs = 0); - - /** - * Process all outstanding queries, blocking the calling thread - * until all have either been responded to or timed out. - * - * @return whether any responses were processed - */ - bool processAll(); - - /** - * Expand a DNS-encoded compressed string into a normal string. - * - * @param encoded the encoded name (null-terminated) - * @param abuf the response buffer in which the string is embedded - * @param alen the length of the response buffer - * @param s the string into which to place the result - * @return ARES_SUCCESS on success, otherwise an error indicator - */ - static int expandName(const char *encoded, const char *abuf, size_t alen, - std::string &s) { - size_t ignore; - return expandName(encoded, abuf, alen, s, ignore); - } - - static int expandName(const char *encoded, const char *abuf, size_t alen, - std::string &s, size_t &enclen); - - /** - * Return a string describing an error code. - */ - static const char *strerror(int code); - - bool isInitialized(void) { return mInitSuccess; } - -protected: - ares_channel chan_; - bool mInitSuccess; - // boost::scoped_ptr would actually fit the requirement better, but it - // can't handle incomplete types as boost::shared_ptr can. - boost::shared_ptr mListener; -}; - -/** - * An ordered collection of DNS resource records. - */ -typedef std::vector > dns_rrs_t; - -/** - * @class LLQueryResponder - * @brief Base class for friendly handling of DNS query responses. - * - * This class parses a DNS response and represents it in a friendly - * manner. - * - * @see LLDnsRecord - * @see LLARecord - * @see LLNsRecord - * @see LLCnameRecord - * @see LLPtrRecord - * @see LLAaaaRecord - * @see LLSrvRecord - */ -class LLQueryResponder : public LLAres::QueryResponder -{ -protected: - int mResult; - std::string mQuery; - LLResType mType; - - dns_rrs_t mAnswers; - dns_rrs_t mAuthorities; - dns_rrs_t mAdditional; - - /** - * Parse a single RR. - */ - int parseRR(const char *buf, size_t len, const char *&pos, - LLPointer &r); - /** - * Parse one section of a response. - */ - int parseSection(const char *buf, size_t len, - size_t count, const char *& pos, dns_rrs_t &rrs); - - void queryResult(const char *buf, size_t len); - virtual void querySuccess(); - -public: - LLQueryResponder(); - - /** - * Indicate whether the response could be parsed successfully. - */ - bool valid() const { return mResult == ARES_SUCCESS; } - - /** - * The more detailed result of parsing the response. - */ - int result() const { return mResult; } - - /** - * Return the query embedded in the response. - */ - const std::string &query() const { return mQuery; } - - /** - * Return the contents of the "answers" section of the response. - */ - const dns_rrs_t &answers() const { return mAnswers; } - - /** - * Return the contents of the "authorities" section of the - * response. - */ - const dns_rrs_t &authorities() const { return mAuthorities; } - - /** - * Return the contents of the "additional records" section of the - * response. - */ - const dns_rrs_t &additional() const { return mAdditional; } -}; - -/** - * @class LLAres::SrvResponder - * @brief Class for handling SRV query responses. - */ -class LLAres::SrvResponder : public LLQueryResponder -{ -public: - friend void LLAres::getSrvRecords(const std::string &name, - SrvResponder *resp); - void querySuccess(); - void queryError(int code); - - virtual void srvResult(const dns_rrs_t &ents); - virtual void srvError(int code); -}; - -/** - * @class LLAres::UriRewriteResponder - * @brief Class for handling URI rewrites based on SRV records. - */ -class LLAres::UriRewriteResponder : public LLQueryResponder -{ -protected: - LLURI mUri; - -public: - friend void LLAres::rewriteURI(const std::string &uri, - UriRewriteResponder *resp); - void querySuccess(); - void queryError(int code); - - virtual void rewriteResult(const std::vector &uris); -}; - -/** - * Singleton responder. - */ -extern LLAres *gAres; - -/** - * Set up the singleton responder. It's safe to call this more than - * once from within a single thread, but this function is not - * thread safe. - */ -extern LLAres *ll_init_ares(); -extern void ll_cleanup_ares(); - -#endif // LL_LLARES_H diff --git a/indra/llmessage/llareslistener.cpp b/indra/llmessage/llareslistener.cpp deleted file mode 100755 index 3d65906b98..0000000000 --- a/indra/llmessage/llareslistener.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @file llareslistener.cpp - * @author Nat Goodspeed - * @date 2009-03-18 - * @brief Implementation for llareslistener. - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -// Precompiled header -#include "linden_common.h" -// associated header -#include "llareslistener.h" -// STL headers -// std headers -// external library headers -// other Linden headers -#include "llares.h" -#include "llerror.h" -#include "llevents.h" -#include "llsdutil.h" - -LLAresListener::LLAresListener(LLAres* llares): - LLEventAPI("LLAres", - "LLAres listener to request DNS operations"), - mAres(llares) -{ - // add() every method we want to be able to invoke via this event API. - // Optional last parameter validates expected LLSD request structure. - add("rewriteURI", - "Given [\"uri\"], return on [\"reply\"] an array of alternative URIs.\n" - "On failure, returns an array containing only the original URI, so\n" - "failure case can be processed like success case.", - &LLAresListener::rewriteURI, - LLSD().with("uri", LLSD()).with("reply", LLSD())); -} - -/// This UriRewriteResponder subclass packages returned URIs as an LLSD -/// array to send back to the requester. -class UriRewriteResponder: public LLAres::UriRewriteResponder -{ -public: - /** - * Specify the request, containing the event pump name on which to send - * the reply. - */ - UriRewriteResponder(const LLSD& request): - mReqID(request), - mPumpName(request["reply"]) - {} - - /// Called by base class with results. This is called in both the - /// success and error cases. On error, the calling logic passes the - /// original URI. - virtual void rewriteResult(const std::vector& uris) - { - LLSD result; - for (std::vector::const_iterator ui(uris.begin()), uend(uris.end()); - ui != uend; ++ui) - { - result.append(*ui); - } - // This call knows enough to avoid trying to insert a map key into an - // LLSD array. It's there so that if, for any reason, we ever decide - // to change the response from array to map, it will Just Start Working. - mReqID.stamp(result); - LLEventPumps::instance().obtain(mPumpName).post(result); - } - -private: - LLReqID mReqID; - const std::string mPumpName; -}; - -void LLAresListener::rewriteURI(const LLSD& data) -{ - if (mAres) - { - mAres->rewriteURI(data["uri"], new UriRewriteResponder(data)); - } - else - { - LL_INFOS() << "LLAresListener::rewriteURI requested without Ares present. Ignoring: " << data << LL_ENDL; - } -} diff --git a/indra/llmessage/llareslistener.h b/indra/llmessage/llareslistener.h deleted file mode 100755 index 780dcdd9c5..0000000000 --- a/indra/llmessage/llareslistener.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file llareslistener.h - * @author Nat Goodspeed - * @date 2009-03-18 - * @brief LLEventPump API for LLAres. This header doesn't actually define the - * API; the API is defined by the pump name on which this class - * listens, and by the expected content of LLSD it receives. - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#if ! defined(LL_LLARESLISTENER_H) -#define LL_LLARESLISTENER_H - -#include "lleventapi.h" - -class LLAres; -class LLSD; - -/// Listen on an LLEventPump with specified name for LLAres request events. -class LLAresListener: public LLEventAPI -{ -public: - /// Bind the LLAres instance to use (e.g. gAres) - LLAresListener(LLAres* llares); - -private: - /// command["op"] == "rewriteURI" - void rewriteURI(const LLSD& data); - - LLAres* mAres; -}; - -#endif /* ! defined(LL_LLARESLISTENER_H) */ diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ba76341b69..5cf9efa04e 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -57,7 +57,6 @@ #include "llfocusmgr.h" #include "llviewerjoystick.h" #include "llallocator.h" -#include "llares.h" #include "llcalc.h" #include "llconversationlog.h" #include "lldxhardware.h" @@ -1283,7 +1282,6 @@ static LLTrace::BlockTimerStatHandle FTM_LFS("LFS Thread"); static LLTrace::BlockTimerStatHandle FTM_PAUSE_THREADS("Pause Threads"); static LLTrace::BlockTimerStatHandle FTM_IDLE("Idle"); static LLTrace::BlockTimerStatHandle FTM_PUMP("Pump"); -static LLTrace::BlockTimerStatHandle FTM_PUMP_ARES("Ares"); static LLTrace::BlockTimerStatHandle FTM_PUMP_SERVICE("Service"); static LLTrace::BlockTimerStatHandle FTM_SERVICE_CALLBACK("Callback"); static LLTrace::BlockTimerStatHandle FTM_AGENT_AUTOPILOT("Autopilot"); @@ -1425,26 +1423,6 @@ bool LLAppViewer::mainLoop() LL_RECORD_BLOCK_TIME(FTM_IDLE); idle(); - if (gAres != NULL && gAres->isInitialized()) - { - pingMainloopTimeout("Main:ServicePump"); - LL_RECORD_BLOCK_TIME(FTM_PUMP); - { - LL_RECORD_BLOCK_TIME(FTM_PUMP_ARES); - gAres->process(); - } - { - LL_RECORD_BLOCK_TIME(FTM_PUMP_SERVICE); - // this pump is necessary to make the login screen show up - gServicePump->pump(); - - { - LL_RECORD_BLOCK_TIME(FTM_SERVICE_CALLBACK); - gServicePump->callback(); - } - } - } - resumeMainloopTimeout(); } @@ -2014,9 +1992,6 @@ bool LLAppViewer::cleanup() // Non-LLCurl libcurl library mAppCoreHttp.cleanup(); - // NOTE The following call is not thread safe. - ll_cleanup_ares(); - LLFilePickerThread::cleanupClass(); //MUST happen AFTER LLCurl::cleanupClass diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 047e23cefc..7616f65a29 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -46,7 +46,6 @@ #include "llaudioengine_openal.h" #endif -#include "llares.h" #include "llavatarnamecache.h" #include "llexperiencecache.h" #include "lllandmark.h" @@ -444,13 +443,6 @@ bool idle_startup() // Load the throttle settings gViewerThrottle.load(); - if (ll_init_ares() == NULL || !gAres->isInitialized()) - { - std::string diagnostic = "Could not start address resolution system"; - LL_WARNS("AppInit") << diagnostic << LL_ENDL; - LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic)); - } - // // Initialize messaging system // diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index ad3d84b8e5..b361bbb276 100755 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -108,7 +108,7 @@ private: // In a coroutine's top-level function args, do NOT NOT NOT accept // references (const or otherwise) to anything! Pass by value only! - void login_(std::string uri, LLSD credentials); + void loginCoro(std::string uri, LLSD credentials); LLEventStream mPump; LLSD mAuthResponse, mValidAuthResponse; @@ -122,11 +122,11 @@ void LLLogin::Impl::connect(const std::string& uri, const LLSD& login_params) // its first wait; at that point, return here. std::string coroname = LLCoros::instance().launch("LLLogin::Impl::login_", - boost::bind(&Impl::login_, this, uri, login_params)); + boost::bind(&Impl::loginCoro, this, uri, login_params)); LL_DEBUGS("LLLogin") << " connected with uri '" << uri << "', login_params " << login_params << LL_ENDL; } -void LLLogin::Impl::login_(std::string uri, LLSD login_params) +void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params) { try { @@ -143,43 +143,6 @@ void LLLogin::Impl::login_(std::string uri, LLSD login_params) LLEventStream replyPump("SRVreply", true); // Should be an array of one or more uri strings. - LLSD rewrittenURIs; - { - LLEventTimeout filter(replyPump); - sendProgressEvent("offline", "srvrequest"); - - // Request SRV record. - LL_DEBUGS("LLLogin") << "Requesting SRV record from " << uri << LL_ENDL; - - // *NOTE:Mani - Completely arbitrary default timeout value for SRV request. - F32 seconds_to_timeout = 5.0f; - if(login_params.has("cfg_srv_timeout")) - { - seconds_to_timeout = login_params["cfg_srv_timeout"].asReal(); - } - - // If the SRV request times out (e.g. EXT-3934), simulate response: an - // array containing our original URI. - LLSD fakeResponse(LLSD::emptyArray()); - fakeResponse.append(uri); - filter.eventAfter(seconds_to_timeout, fakeResponse); - - std::string srv_pump_name = "LLAres"; - if(login_params.has("cfg_srv_pump")) - { - srv_pump_name = login_params["cfg_srv_pump"].asString(); - } - - // Make request - LLSD request; - request["op"] = "rewriteURI"; - request["uri"] = uri; - request["reply"] = replyPump.getName(); - rewrittenURIs = llcoro::postAndSuspend(request, srv_pump_name, filter); - // EXP-772: If rewrittenURIs fail, try original URI as a fallback. - rewrittenURIs.append(uri); - } // we no longer need the filter - LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction")); // EXT-4193: use a DIFFERENT reply pump than for the SRV request. We used // to share them -- but the EXT-3934 fix made it possible for an abandoned @@ -190,107 +153,103 @@ void LLLogin::Impl::login_(std::string uri, LLSD login_params) // Because of possible redirect responses, we may make more than one // attempt per rewrittenURIs entry. LLSD::Integer attempts = 0; - for (LLSD::array_const_iterator urit(rewrittenURIs.beginArray()), - urend(rewrittenURIs.endArray()); - urit != urend; ++urit) + + LLSD request(login_params); + request["reply"] = loginReplyPump.getName(); + request["uri"] = uri; + std::string status; + + // Loop back to here if login attempt redirects to a different + // request["uri"] + for (;;) { - LLSD request(login_params); - request["reply"] = loginReplyPump.getName(); - request["uri"] = *urit; - std::string status; - - // Loop back to here if login attempt redirects to a different - // request["uri"] - for (;;) + ++attempts; + LLSD progress_data; + progress_data["attempt"] = attempts; + progress_data["request"] = request; + if(progress_data["request"].has("params") + && progress_data["request"]["params"].has("passwd")) + { + progress_data["request"]["params"]["passwd"] = "*******"; + } + sendProgressEvent("offline", "authenticating", progress_data); + + // We expect zero or more "Downloading" status events, followed by + // exactly one event with some other status. Use postAndSuspend() the + // first time, because -- at least in unit-test land -- it's + // possible for the reply to arrive before the post() call + // returns. Subsequent responses, of course, must be awaited + // without posting again. + for (mAuthResponse = validateResponse(loginReplyPump.getName(), + llcoro::postAndSuspend(request, xmlrpcPump, loginReplyPump, "reply")); + mAuthResponse["status"].asString() == "Downloading"; + mAuthResponse = validateResponse(loginReplyPump.getName(), + llcoro::suspendUntilEventOn(loginReplyPump))) { - ++attempts; - LLSD progress_data; - progress_data["attempt"] = attempts; - progress_data["request"] = request; - if(progress_data["request"].has("params") - && progress_data["request"]["params"].has("passwd")) - { - progress_data["request"]["params"]["passwd"] = "*******"; - } - sendProgressEvent("offline", "authenticating", progress_data); - - // We expect zero or more "Downloading" status events, followed by - // exactly one event with some other status. Use postAndSuspend() the - // first time, because -- at least in unit-test land -- it's - // possible for the reply to arrive before the post() call - // returns. Subsequent responses, of course, must be awaited - // without posting again. - for (mAuthResponse = validateResponse(loginReplyPump.getName(), - llcoro::postAndSuspend(request, xmlrpcPump, loginReplyPump, "reply")); - mAuthResponse["status"].asString() == "Downloading"; - mAuthResponse = validateResponse(loginReplyPump.getName(), - llcoro::suspendUntilEventOn(loginReplyPump))) - { - // Still Downloading -- send progress update. - sendProgressEvent("offline", "downloading"); - } + // Still Downloading -- send progress update. + sendProgressEvent("offline", "downloading"); + } - LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL; - status = mAuthResponse["status"].asString(); - - // Okay, we've received our final status event for this - // request. Unless we got a redirect response, break the retry - // loop for the current rewrittenURIs entry. - if (!(status == "Complete" && - mAuthResponse["responses"]["login"].asString() == "indeterminate")) - { - break; - } - - sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]); - - // Here the login service at the current URI is redirecting us - // to some other URI ("indeterminate" -- why not "redirect"?). - // The response should contain another uri to try, with its - // own auth method. - request["uri"] = mAuthResponse["responses"]["next_url"].asString(); - request["method"] = mAuthResponse["responses"]["next_method"].asString(); - } // loop back to try the redirected URI - - // Here we're done with redirects for the current rewrittenURIs - // entry. - if (status == "Complete") + LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL; + status = mAuthResponse["status"].asString(); + + // Okay, we've received our final status event for this + // request. Unless we got a redirect response, break the retry + // loop for the current rewrittenURIs entry. + if (!(status == "Complete" && + mAuthResponse["responses"]["login"].asString() == "indeterminate")) { - // StatusComplete does not imply auth success. Check the - // actual outcome of the request. We've already handled the - // "indeterminate" case in the loop above. - if (mAuthResponse["responses"]["login"].asString() == "true") - { - sendProgressEvent("online", "connect", mAuthResponse["responses"]); - } - else - { - sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]); - } - return; // Done! + break; } - /* Sometimes we end with "Started" here. Slightly slow server? - * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below. - */ - if( status == "Started") - { - LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL; - continue; - } + sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]); + + // Here the login service at the current URI is redirecting us + // to some other URI ("indeterminate" -- why not "redirect"?). + // The response should contain another uri to try, with its + // own auth method. + request["uri"] = mAuthResponse["responses"]["next_url"].asString(); + request["method"] = mAuthResponse["responses"]["next_method"].asString(); + } // loop back to try the redirected URI - // If we don't recognize status at all, trouble - if (! (status == "CURLError" - || status == "XMLRPCError" - || status == "OtherError")) + // Here we're done with redirects for the current rewrittenURIs + // entry. + if (status == "Complete") + { + // StatusComplete does not imply auth success. Check the + // actual outcome of the request. We've already handled the + // "indeterminate" case in the loop above. + if (mAuthResponse["responses"]["login"].asString() == "true") { - LL_ERRS("LLLogin") << "Unexpected status from " << xmlrpcPump.getName() << " pump: " - << mAuthResponse << LL_ENDL; - return; + sendProgressEvent("online", "connect", mAuthResponse["responses"]); } + else + { + sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]); + } + return; // Done! + } + +// /* Sometimes we end with "Started" here. Slightly slow server? +// * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below. +// */ +// if( status == "Started") +// { +// LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL; +// continue; +// } + + // If we don't recognize status at all, trouble + if (! (status == "CURLError" + || status == "XMLRPCError" + || status == "OtherError")) + { + LL_ERRS("LLLogin") << "Unexpected status from " << xmlrpcPump.getName() << " pump: " + << mAuthResponse << LL_ENDL; + return; + } - // Here status IS one of the errors tested above. - } // Retry if there are any more rewrittenURIs. + // Here status IS one of the errors tested above. // Here we got through all the rewrittenURIs without succeeding. Tell // caller this didn't work out so well. Of course, the only failure data diff --git a/indra/viewer_components/login/tests/lllogin_test.cpp b/indra/viewer_components/login/tests/lllogin_test.cpp index 58bf371a04..e96c495446 100755 --- a/indra/viewer_components/login/tests/lllogin_test.cpp +++ b/indra/viewer_components/login/tests/lllogin_test.cpp @@ -96,61 +96,6 @@ public: } }; -class LLAresListener: public LLEventTrackable -{ - std::string mName; - LLSD mEvent; - bool mImmediateResponse; - bool mMultipleURIResponse; - Debug mDebug; - -public: - LLAresListener(const std::string& name, - bool i = false, - bool m = false - ) : - mName(name), - mImmediateResponse(i), - mMultipleURIResponse(m), - mDebug(stringize(*this)) - {} - - bool handle_event(const LLSD& event) - { - mDebug(STRINGIZE("LLAresListener called!: " << event)); - mEvent = event; - if(mImmediateResponse) - { - sendReply(); - } - return false; - } - - void sendReply() - { - if(mEvent["op"].asString() == "rewriteURI") - { - LLSD result; - if(mMultipleURIResponse) - { - result.append(LLSD("login.foo.com")); - } - result.append(mEvent["uri"]); - LLEventPumps::instance().obtain(mEvent["reply"]).post(result); - } - } - - LLBoundListener listenTo(LLEventPump& pump) - { - return pump.listen(mName, boost::bind(&LLAresListener::handle_event, this, _1)); - } - - friend std::ostream& operator<<(std::ostream& out, const LLAresListener& listener) - { - return out << "LLAresListener(" << listener.mName << ')'; - } -}; - class LLXMLRPCListener: public LLEventTrackable { std::string mName; @@ -232,16 +177,12 @@ namespace tut void llviewerlogin_object::test<1>() { DEBUG; - // Testing login with immediate responses from Ares and XMLPRC - // The response from both requests will come before the post request exits. + // Testing login with an immediate response from XMLPRC + // The response will come before the post request exits. // This tests an edge case of the login state handling. - LLEventStream llaresPump("LLAres"); // Dummy LLAres pump. LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump bool respond_immediately = true; - // Have 'dummy ares' respond immediately. - LLAresListener dummyLLAres("dummy_llares", respond_immediately); - dummyLLAres.listenTo(llaresPump); // Have dummy XMLRPC respond immediately. LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc", respond_immediately); @@ -264,111 +205,14 @@ namespace tut template<> template<> void llviewerlogin_object::test<2>() - { - DEBUG; - // Tests a successful login in with delayed responses. - // Also includes 'failure' that cause the login module - // to re-attempt connection, once from a basic failure - // and once from the 'indeterminate' response. - - set_test_name("LLLogin multiple srv uris w/ success"); - - // Testing normal login procedure. - LLEventStream llaresPump("LLAres"); // Dummy LLAres pump. - LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump - - bool respond_immediately = false; - bool multiple_addresses = true; - LLAresListener dummyLLAres("dummy_llares", respond_immediately, multiple_addresses); - dummyLLAres.listenTo(llaresPump); - - LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc"); - dummyXMLRPC.listenTo(xmlrpcPump); - - LLLogin login; - - LoginListener listener("test_ear"); - listener.listenTo(login.getEventPump()); - - LLSD credentials; - credentials["first"] = "foo"; - credentials["last"] = "bar"; - credentials["passwd"] = "secret"; - - login.connect("login.bar.com", credentials); - - ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); - - dummyLLAres.sendReply(); - - // Test Authenticating State prior to first response. - ensure_equals("Auth state 1", listener.lastEvent()["change"].asString(), "authenticating"); - ensure_equals("Attempt 1", listener.lastEvent()["data"]["attempt"].asInteger(), 1); - ensure_equals("URI 1", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.foo.com"); - - // First send emulated LLXMLRPCListener failure, - // this should return login to the authenticating step and increase the attempt - // count. - LLSD data; - data["status"] = "OtherError"; - data["errorcode"] = 0; - data["error"] = "dummy response"; - data["transfer_rate"] = 0; - dummyXMLRPC.setResponse(data); - dummyXMLRPC.sendReply(); - - ensure_equals("Fail back to authenticate 1", listener.lastEvent()["change"].asString(), "authenticating"); - ensure_equals("Attempt 2", listener.lastEvent()["data"]["attempt"].asInteger(), 2); - ensure_equals("URI 2", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.bar.com"); - - // Now send the 'indeterminate' response. - data.clear(); - data["status"] = "Complete"; // StatusComplete - data["errorcode"] = 0; - data["error"] = "dummy response"; - data["transfer_rate"] = 0; - data["responses"]["login"] = "indeterminate"; - data["responses"]["next_url"] = "login.indeterminate.com"; - data["responses"]["next_method"] = "test_login_method"; - dummyXMLRPC.setResponse(data); - dummyXMLRPC.sendReply(); - - ensure_equals("Fail back to authenticate 2", listener.lastEvent()["change"].asString(), "authenticating"); - ensure_equals("Attempt 3", listener.lastEvent()["data"]["attempt"].asInteger(), 3); - ensure_equals("URI 3", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.indeterminate.com"); - ensure_equals("Method 3", listener.lastEvent()["data"]["request"]["method"].asString(), "test_login_method"); - - // Finally let the auth succeed. - data.clear(); - data["status"] = "Complete"; // StatusComplete - data["errorcode"] = 0; - data["error"] = "dummy response"; - data["transfer_rate"] = 0; - data["responses"]["login"] = "true"; - dummyXMLRPC.setResponse(data); - dummyXMLRPC.sendReply(); - - ensure_equals("Success state", listener.lastEvent()["state"].asString(), "online"); - - login.disconnect(); - - ensure_equals("Disconnected state", listener.lastEvent()["state"].asString(), "offline"); - } - - template<> template<> - void llviewerlogin_object::test<3>() { DEBUG; // Test completed response, that fails to login. set_test_name("LLLogin valid response, failure (eg. bad credentials)"); // Testing normal login procedure. - LLEventStream llaresPump("LLAres"); // Dummy LLAres pump. LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump - LLAresListener dummyLLAres("dummy_llares"); - dummyLLAres.listenTo(llaresPump); - LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc"); dummyXMLRPC.listenTo(xmlrpcPump); @@ -383,10 +227,6 @@ namespace tut login.connect("login.bar.com", credentials); - ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); - - dummyLLAres.sendReply(); - ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating"); // Send the failed auth request reponse @@ -403,19 +243,15 @@ namespace tut } template<> template<> - void llviewerlogin_object::test<4>() + void llviewerlogin_object::test<3>() { DEBUG; // Test incomplete response, that end the attempt. set_test_name("LLLogin valid response, failure (eg. bad credentials)"); // Testing normal login procedure. - LLEventStream llaresPump("LLAres"); // Dummy LLAres pump. LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump - LLAresListener dummyLLAres("dummy_llares"); - dummyLLAres.listenTo(llaresPump); - LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc"); dummyXMLRPC.listenTo(xmlrpcPump); @@ -430,10 +266,6 @@ namespace tut login.connect("login.bar.com", credentials); - ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); - - dummyLLAres.sendReply(); - ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating"); // Send the failed auth request reponse @@ -449,17 +281,13 @@ namespace tut } template<> template<> - void llviewerlogin_object::test<5>() + void llviewerlogin_object::test<4>() { DEBUG; // Test SRV request timeout. set_test_name("LLLogin SRV timeout testing"); // Testing normal login procedure. - LLEventStream llaresPump("LLAres"); // Dummy LLAres pump. - - LLAresListener dummyLLAres("dummy_llares"); - dummyLLAres.listenTo(llaresPump); LLLogin login; LoginListener listener("test_ear"); @@ -473,26 +301,15 @@ namespace tut login.connect("login.bar.com", credentials); - ensure_equals("SRV State", listener.lastEvent()["change"].asString(), "srvrequest"); - // Get the mainloop eventpump, which needs a pinging in order to drive the // SRV timeout. LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); LLSD frame_event; mainloop.post(frame_event); - // In this state we have NOT sent a reply from LLAresListener -- in - // fact there's no such object. Nonetheless, we expect the timeout to - // have stepped the login module forward to try to authenticate with - // the original URI. ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating"); ensure_equals("Attempt", listener.lastEvent()["data"]["attempt"].asInteger(), 1); ensure_equals("URI", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.bar.com"); - // EXT-4193: if the SRV reply isn't lost but merely late, and if it - // arrives just at the moment we're expecting the XMLRPC reply, the - // original code got confused and crashed. Drive that case here. We - // observe that without the fix, this call DOES repro. - dummyLLAres.sendReply(); } } -- cgit v1.3 From 29596be514d361c71273629677bcb4c7052a6036 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 22 Sep 2015 13:01:30 -0700 Subject: Test disabling a couple of the display_startup() calls as an experiment. --- indra/newview/llstartup.cpp | 4 ++-- indra/viewer_components/login/lllogin.cpp | 25 ++----------------------- 2 files changed, 4 insertions(+), 25 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 7616f65a29..60d67be9ef 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -752,10 +752,10 @@ bool idle_startup() // Make sure the process dialog doesn't hide things display_startup(); gViewerWindow->setShowProgress(FALSE); - display_startup(); +// display_startup(); // Show the login dialog login_show(); - display_startup(); +// display_startup(); // connect dialog is already shown, so fill in the names if (gUserCredential.notNull()) { diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index b361bbb276..53d4acc9e0 100755 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -310,29 +310,8 @@ LLEventPump& LLLogin::getEventPump() // The list associates to event with the original idle_startup() 'STATE'. -// Rewrite URIs - // State_LOGIN_AUTH_INIT -// Given a vector of login uris (usually just one), perform a dns lookup for the -// SRV record from each URI. I think this is used to distribute login requests to -// a single URI to multiple hosts. -// This is currently a synchronous action. (See LLSRV::rewriteURI() implementation) -// On dns lookup error the output uris == the input uris. -// -// Input: A vector of login uris -// Output: A vector of login uris -// -// Code: -// std::vector uris; -// LLViewerLogin::getInstance()->getLoginURIs(uris); -// std::vector::const_iterator iter, end; -// for (iter = uris.begin(), end = uris.end(); iter != end; ++iter) -// { -// std::vector rewritten; -// rewritten = LLSRV::rewriteURI(*iter); -// sAuthUris.insert(sAuthUris.end(), -// rewritten.begin(), rewritten.end()); -// } -// sAuthUriNum = 0; +// Setup login +// State_LOGIN_AUTH_INIT // Authenticate // STATE_LOGIN_AUTHENTICATE -- cgit v1.3 From a01ad64c3e701de0586043aebf3229c5f5a4916a Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 22 Sep 2015 14:47:42 -0700 Subject: replace the display_startup() removal that didn't work. Try backing up a step in the signon processing. --- indra/newview/llstartup.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 60d67be9ef..b0ea00e6e4 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -752,10 +752,10 @@ bool idle_startup() // Make sure the process dialog doesn't hide things display_startup(); gViewerWindow->setShowProgress(FALSE); -// display_startup(); + display_startup(); // Show the login dialog login_show(); -// display_startup(); + display_startup(); // connect dialog is already shown, so fill in the names if (gUserCredential.notNull()) { @@ -2751,8 +2751,6 @@ void reset_login() gAgent.cleanup(); LLWorld::getInstance()->destroyClass(); - LLStartUp::setStartupState( STATE_LOGIN_SHOW ); - if ( gViewerWindow ) { // Hide menus and normal buttons gViewerWindow->setNormalControlsVisible( FALSE ); @@ -2762,6 +2760,7 @@ void reset_login() // Hide any other stuff LLFloaterReg::hideVisibleInstances(); + LLStartUp::setStartupState( STATE_BROWSER_INIT ); } //--------------------------------------------------------------------------- -- cgit v1.3 From 245677e941d47963b67d36deffd03535dfc3df3f Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Thu, 24 Sep 2015 11:19:20 -0700 Subject: MAINT-5614: There are an obscene number of calls to "display_startup()" in the show login state. Try removing some of them. --- indra/newview/llstartup.cpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index b0ea00e6e4..ff8b79bc7c 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -728,12 +728,12 @@ bool idle_startup() if (gLoginMenuBarView == NULL) { LL_DEBUGS("AppInit") << "initializing menu bar" << LL_ENDL; - display_startup(); +// display_startup(); initialize_edit_menu(); initialize_spellcheck_menu(); - display_startup(); +// display_startup(); init_menus(); - display_startup(); +// display_startup(); } if (show_connect_box) @@ -745,23 +745,23 @@ bool idle_startup() if (gUserCredential.isNull()) { LL_DEBUGS("AppInit") << "loading credentials from gLoginHandler" << LL_ENDL; - display_startup(); +// display_startup(); gUserCredential = gLoginHandler.initializeLoginInfo(); - display_startup(); +// display_startup(); } // Make sure the process dialog doesn't hide things - display_startup(); +// display_startup(); gViewerWindow->setShowProgress(FALSE); - display_startup(); +// display_startup(); // Show the login dialog login_show(); - display_startup(); +// display_startup(); // connect dialog is already shown, so fill in the names if (gUserCredential.notNull()) { LLPanelLogin::setFields( gUserCredential, gRememberPassword); } - display_startup(); +// display_startup(); LLPanelLogin::giveFocus(); // MAINT-3231 Show first run dialog only for Desura viewer @@ -787,22 +787,22 @@ bool idle_startup() LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); } - display_startup(); +// display_startup(); gViewerWindow->setNormalControlsVisible( FALSE ); - display_startup(); +// display_startup(); gLoginMenuBarView->setVisible( TRUE ); - display_startup(); +// display_startup(); gLoginMenuBarView->setEnabled( TRUE ); - display_startup(); +// display_startup(); show_debug_menus(); - display_startup(); +// display_startup(); // Hide the splash screen LLSplashScreen::hide(); - display_startup(); +// display_startup(); // Push our window frontmost gViewerWindow->getWindow()->show(); - display_startup(); +// display_startup(); // DEV-16927. The following code removes errant keystrokes that happen while the window is being // first made visible. @@ -810,9 +810,10 @@ bool idle_startup() MSG msg; while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) ) { } - display_startup(); +// display_startup(); #endif - timeout.reset(); + display_startup(); + timeout.reset(); return FALSE; } -- cgit v1.3 From 4334fd27e2215c1bfad3aa7ab7130b8c6b289de5 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 29 Sep 2015 16:05:09 -0700 Subject: Just remove the display_startup() calls. --- indra/newview/llstartup.cpp | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index ff8b79bc7c..2c6b9d14bf 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -728,12 +728,9 @@ bool idle_startup() if (gLoginMenuBarView == NULL) { LL_DEBUGS("AppInit") << "initializing menu bar" << LL_ENDL; -// display_startup(); initialize_edit_menu(); initialize_spellcheck_menu(); -// display_startup(); init_menus(); -// display_startup(); } if (show_connect_box) @@ -745,23 +742,17 @@ bool idle_startup() if (gUserCredential.isNull()) { LL_DEBUGS("AppInit") << "loading credentials from gLoginHandler" << LL_ENDL; -// display_startup(); gUserCredential = gLoginHandler.initializeLoginInfo(); -// display_startup(); } // Make sure the process dialog doesn't hide things -// display_startup(); gViewerWindow->setShowProgress(FALSE); -// display_startup(); // Show the login dialog login_show(); -// display_startup(); // connect dialog is already shown, so fill in the names if (gUserCredential.notNull()) { LLPanelLogin::setFields( gUserCredential, gRememberPassword); } -// display_startup(); LLPanelLogin::giveFocus(); // MAINT-3231 Show first run dialog only for Desura viewer @@ -787,22 +778,15 @@ bool idle_startup() LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); } -// display_startup(); gViewerWindow->setNormalControlsVisible( FALSE ); -// display_startup(); gLoginMenuBarView->setVisible( TRUE ); -// display_startup(); gLoginMenuBarView->setEnabled( TRUE ); -// display_startup(); show_debug_menus(); -// display_startup(); // Hide the splash screen LLSplashScreen::hide(); -// display_startup(); // Push our window frontmost gViewerWindow->getWindow()->show(); -// display_startup(); // DEV-16927. The following code removes errant keystrokes that happen while the window is being // first made visible. @@ -810,7 +794,6 @@ bool idle_startup() MSG msg; while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) ) { } -// display_startup(); #endif display_startup(); timeout.reset(); -- cgit v1.3