summaryrefslogtreecommitdiff
path: root/indra/llmessage
diff options
context:
space:
mode:
authorChristian Goetze <cg@lindenlab.com>2009-07-01 00:22:05 +0000
committerChristian Goetze <cg@lindenlab.com>2009-07-01 00:22:05 +0000
commite588d1f28419745ee1e1ee98dc1852e0364a4088 (patch)
tree8a3546576e0d5a8f0cf32cca68d0913f1061d523 /indra/llmessage
parent5f4c09fa1f4b09126e1a16e78044c64e97828530 (diff)
svn merge -r125825:125901 svn+ssh://svn.lindenlab.com/svn/user/cg/qar-1654
QAR-1654 merge completed.
Diffstat (limited to 'indra/llmessage')
-rw-r--r--indra/llmessage/CMakeLists.txt2
-rw-r--r--indra/llmessage/llcachename.cpp226
-rw-r--r--indra/llmessage/llcachename.h6
-rw-r--r--indra/llmessage/llhttpclientadapter.cpp2
-rw-r--r--indra/llmessage/llhttpclientadapter.h2
-rw-r--r--indra/llmessage/llhttpclientinterface.h2
-rw-r--r--indra/llmessage/llmessagesenderinterface.h2
-rw-r--r--indra/llmessage/llregionpresenceverifier.cpp86
-rw-r--r--indra/llmessage/llregionpresenceverifier.h39
-rw-r--r--indra/llmessage/llstoredmessage.cpp2
-rw-r--r--indra/llmessage/llstoredmessage.h2
-rw-r--r--indra/llmessage/llthrottle.cpp25
-rw-r--r--indra/llmessage/llthrottle.h2
-rw-r--r--indra/llmessage/llurlrequest.cpp54
-rw-r--r--indra/llmessage/llurlrequest.h8
-rw-r--r--indra/llmessage/tests/llregionpresenceverifier_test.cpp111
16 files changed, 433 insertions, 138 deletions
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 88f83ba78e..81e518cf6e 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -221,6 +221,7 @@ IF (NOT LINUX AND VIEWER)
# llhttpclientadapter.cpp
lltrustedmessageservice.cpp
lltemplatemessagedispatcher.cpp
+ llregionpresenceverifier.cpp
)
LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
@@ -228,3 +229,4 @@ IF (NOT LINUX AND VIEWER)
# Don't make llmessage depend on llsdmessage_test because ADD_COMM_BUILD_TEST depends on llmessage!
# ADD_COMM_BUILD_TEST(llsdmessage "" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py")
ENDIF (NOT LINUX AND VIEWER)
+
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 799bc83e20..82186fc503 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -76,11 +76,13 @@ public:
LLCacheNameEntry();
public:
- bool mIsGroup;
- U32 mCreateTime; // unix time_t
- std::string mFirstName;
- std::string mLastName;
- std::string mGroupName;
+ bool isUnknown() { return (mFirstName.empty()
+ || mFirstName == std::string("(???)")); };
+
+ bool mIsGroup; // true if this is a group ID/name
+ U32 mCreateTime; // unix time_t
+ std::string mFirstName; // Doubles as the group name
+ std::string mLastName; // Will be "" for groups
};
LLCacheNameEntry::LLCacheNameEntry()
@@ -162,7 +164,7 @@ void ReplySender::send(const LLUUID& id,
mMsg->addUUIDFast(_PREHASH_ID, id);
if(mCurrIsGroup)
{
- mMsg->addStringFast(_PREHASH_GroupName, entry.mGroupName);
+ mMsg->addStringFast(_PREHASH_GroupName, entry.mFirstName);
}
else
{
@@ -222,6 +224,7 @@ public:
void processPendingReplies();
void sendRequest(const char* msg_name, const AskQueue& queue);
bool isRequestPending(const LLUUID& id);
+ void makeNameRequestForID(const LLUUID& id, bool isGroup, LLHost & fromHost);
// Message system callbacks.
void processUUIDRequest(LLMessageSystem* msg, bool isGroup);
@@ -389,6 +392,7 @@ void LLCacheName::importFile(LLFILE* fp)
entry->mCreateTime = create_time;
entry->mFirstName = firstname;
entry->mLastName = lastname;
+ //llinfos << "Adding entry from file for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl;
impl.mCache[id] = entry;
count++;
@@ -425,6 +429,7 @@ bool LLCacheName::importFile(std::istream& istr)
entry->mCreateTime = ctime;
entry->mFirstName = agent[FIRST].asString();
entry->mLastName = agent[LAST].asString();
+ //llinfos << "Adding name entry from XML file for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl;
impl.mCache[id] = entry;
++count;
@@ -445,7 +450,9 @@ bool LLCacheName::importFile(std::istream& istr)
LLCacheNameEntry* entry = new LLCacheNameEntry();
entry->mIsGroup = true;
entry->mCreateTime = ctime;
- entry->mGroupName = group[NAME].asString();
+ entry->mFirstName = group[NAME].asString();
+ entry->mLastName = "";
+ //llinfos << "Adding group entry from XML file for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl;
impl.mCache[id] = entry;
++count;
}
@@ -463,32 +470,32 @@ void LLCacheName::exportFile(std::ostream& ostr)
// Only write entries for which we have valid data.
LLCacheNameEntry* entry = iter->second;
if(!entry
- || (std::string::npos != entry->mFirstName.find('?'))
- || (std::string::npos != entry->mGroupName.find('?')))
- {
+ || entry->isUnknown())
+ { // No entry, or user or group name is unknown
continue;
}
// store it
LLUUID id = iter->first;
std::string id_str = id.asString();
- if(!entry->mFirstName.empty() && !entry->mLastName.empty())
- {
+ if(entry->mIsGroup)
+ { // Save group name and ID
+ data[GROUPS][id_str][NAME] = entry->mFirstName;
+ data[GROUPS][id_str][CTIME] = (S32)entry->mCreateTime;
+ }
+ else if(!entry->mLastName.empty())
+ { // Save user names and ID
data[AGENTS][id_str][FIRST] = entry->mFirstName;
data[AGENTS][id_str][LAST] = entry->mLastName;
data[AGENTS][id_str][CTIME] = (S32)entry->mCreateTime;
}
- else if(entry->mIsGroup && !entry->mGroupName.empty())
- {
- data[GROUPS][id_str][NAME] = entry->mGroupName;
- data[GROUPS][id_str][CTIME] = (S32)entry->mCreateTime;
- }
}
LLSDSerialize::toPrettyXML(data, ostr);
}
+// DO NOT CALL THIS FOR GROUP NAMES
BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& last)
{
if(id.isNull())
@@ -511,11 +518,11 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
last.clear();
if (!impl.isRequestPending(id))
{
+ //llinfos << "**** adding name req for " << id << llendl;
impl.mAskNameQueue.insert(id);
}
- return FALSE;
}
-
+ return FALSE;
}
BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
@@ -535,7 +542,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
}
LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache,id);
- if (entry && entry->mGroupName.empty())
+ if (entry && entry->mFirstName.empty())
{
// COUNTER-HACK to combat James' HACK in exportFile()...
// this group name was loaded from a name cache that did not
@@ -546,7 +553,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
if (entry)
{
- group = entry->mGroupName;
+ group = entry->mFirstName;
return TRUE;
}
else
@@ -562,7 +569,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
// TODO: Make the cache name callback take a SINGLE std::string,
// not a separate first and last name.
-void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data)
+void LLCacheName::getNameFromUUID(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data)
{
if(id.isNull())
{
@@ -573,15 +580,8 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb
LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id );
if (entry)
{
- // id found in map therefore we can call the callback immediately.
- if (entry->mIsGroup)
- {
- callback(id, entry->mGroupName, "", entry->mIsGroup, user_data);
- }
- else
- {
- callback(id, entry->mFirstName, entry->mLastName, entry->mIsGroup, user_data);
- }
+ // id found in map therefore we can call the callback immediately. mLastName will be empty for groups
+ callback(id, entry->mFirstName, entry->mLastName, entry->mIsGroup, user_data);
}
else
{
@@ -590,13 +590,17 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb
{
if (is_group)
{
+ //llinfos << "Group queued for " << id << llendl;
impl.mAskGroupQueue.insert(id);
}
else
{
+ //llinfos << "Name queued for " << id << llendl;
impl.mAskNameQueue.insert(id);
}
}
+
+ // There may be multiple replies for the same ID request
impl.mReplyQueue.push_back(PendingReply(id, callback, user_data));
}
}
@@ -661,7 +665,7 @@ void LLCacheName::dump()
{
llinfos
<< iter->first << " = (group) "
- << entry->mGroupName
+ << entry->mFirstName
<< " @ " << entry->mCreateTime
<< llendl;
}
@@ -715,17 +719,7 @@ void LLCacheName::Impl::processPendingReplies()
if (it->mCallback)
{
- if (!entry->mIsGroup)
- {
- (it->mCallback)(it->mID,
- entry->mFirstName, entry->mLastName,
- FALSE, it->mData);
- }
- else {
- (it->mCallback)(it->mID,
- entry->mGroupName, "",
- TRUE, it->mData);
- }
+ (it->mCallback)(it->mID, entry->mFirstName, entry->mLastName, entry->mIsGroup, it->mData);
}
}
@@ -768,10 +762,12 @@ void LLCacheName::Impl::sendRequest(
if(start_new_message)
{
start_new_message = false;
+ //llinfos << "newMessageFast : " << msg_name << llendl;
mMsg->newMessageFast(msg_name);
}
mMsg->nextBlockFast(_PREHASH_UUIDNameBlock);
mMsg->addUUIDFast(_PREHASH_ID, (*it));
+ //llinfos << " asking for ID: " << (*it) << llendl;
if(mMsg->isSendFullFast(_PREHASH_UUIDNameBlock))
{
@@ -837,38 +833,102 @@ void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup)
{
if (isGroup != entry->mIsGroup)
{
- llwarns << "LLCacheName - Asked for "
- << (isGroup ? "group" : "user") << " name, "
- << "but found "
- << (entry->mIsGroup ? "group" : "user")
- << ": " << id << llendl;
+ if (entry->isUnknown())
+ {
+ Cache::iterator doomediter = mCache.find(id);
+ if (doomediter != mCache.end())
+ { // Kill existing unknown entry
+ llwarns << "LLCacheName - Asked for "
+ << (isGroup ? "group" : "user") << " name, "
+ << "but found unknown "
+ << (entry->mIsGroup ? "group" : "user")
+ << " entry for: " << id
+ << ", deleting bad entry"
+ << llendl;
+
+ delete entry;
+ entry = NULL;
+ mCache.erase(doomediter);
+
+ // Request it with (hopefully) the correct type
+ makeNameRequestForID(id,isGroup,fromHost);
+ }
+ }
+ else if (isGroup)
+ {
+ llwarns << "LLCacheName - Asked for group name, but found user: "
+ << id
+ << " named "
+ << entry->mFirstName << " " << entry->mLastName
+ << llendl;
+ }
+ else
+ {
+ llwarns << "LLCacheName - Asked for user name, but found group: "
+ << id
+ << " named "
+ << entry->mFirstName
+ << llendl;
+ }
}
else
{
// ...it's in the cache, so send it as the reply
sender.send(id, *entry, fromHost);
- }
- }
- else
- {
- if (!isRequestPending(id))
- {
+
+ /*
if (isGroup)
{
- mAskGroupQueue.insert(id);
+ llinfos << "Group ID " << id
+ << " name " << entry->mFirstName
+ << " was already in cache" << llendl;
}
else
{
- mAskNameQueue.insert(id);
+ llinfos << "Agent ID " << id
+ << " name " << entry->mFirstName << " " << entry->mLastName
+ << " was already in cache" << llendl;
}
+ */
}
-
- mReplyQueue.push_back(PendingReply(id, fromHost));
+ }
+ else
+ { /*
+ if (isGroup)
+ {
+ llinfos << "Group ID " << id << " is not in cache" << llendl;
+ }
+ else
+ {
+ llinfos << "Agent ID " << id << " is not in cache" << llendl;
+ }
+ */
+ makeNameRequestForID(id,isGroup,fromHost);
}
}
}
+void LLCacheName::Impl::makeNameRequestForID(const LLUUID& id, bool isGroup, LLHost & fromHost)
+{
+ if (!isRequestPending(id))
+ {
+ if (isGroup)
+ {
+ //llinfos << "Adding group request for " << id << llendl;
+ mAskGroupQueue.insert(id);
+ }
+ else
+ {
+ //llinfos << "Adding name request for " << id << llendl;
+ mAskNameQueue.insert(id);
+ }
+ }
+
+ // There may be multiple replys for the same ID request
+ mReplyQueue.push_back(PendingReply(id, fromHost));
+}
+
void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
{
@@ -878,35 +938,53 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
LLUUID id;
msg->getUUIDFast(_PREHASH_UUIDNameBlock, _PREHASH_ID, id, i);
LLCacheNameEntry* entry = get_ptr_in_map(mCache, id);
+ bool add_new_entry_to_cache = false;
if (!entry)
{
entry = new LLCacheNameEntry;
- mCache[id] = entry;
+ add_new_entry_to_cache = true;
}
+ // Remove ID from pending queue
mPendingQueue.erase(id);
- entry->mIsGroup = isGroup;
- entry->mCreateTime = (U32)time(NULL);
- if (!isGroup)
- {
- msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_FirstName, entry->mFirstName, i);
- msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_LastName, entry->mLastName, i);
+ std::string first_name;
+ std::string last_name;
+ if (isGroup)
+ { // Group
+ msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_GroupName, first_name, i);
+ LLStringFn::replace_ascii_controlchars(first_name, LL_UNKNOWN_CHAR);
}
else
- { // is group
- msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_GroupName, entry->mGroupName, i);
- LLStringFn::replace_ascii_controlchars(entry->mGroupName, LL_UNKNOWN_CHAR);
+ { // User
+ msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_FirstName, first_name, i);
+ msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_LastName, last_name, i);
}
-
- if (!isGroup)
- {
- notifyObservers(id, entry->mFirstName, entry->mLastName, FALSE);
+
+ if (!add_new_entry_to_cache &&
+ (entry->mFirstName != first_name ||
+ entry->mLastName != last_name ||
+ entry->mIsGroup != isGroup))
+ { // Hmmm, we already had an different entry for this ID. Let's see what happened...
+ llwarns << "Replacing existing entry in name cache for id " << id
+ << " first name was " << entry->mFirstName << ", now " << first_name
+ << " last name was " << entry->mLastName << ", now " << last_name
+ << " group flag was " << (S32) entry->mIsGroup << ", now " << (S32) isGroup
+ << llendl;
}
- else
+
+ entry->mFirstName = first_name;
+ entry->mLastName = last_name;
+ entry->mIsGroup = isGroup;
+ entry->mCreateTime = (U32)time(NULL);
+
+ if (add_new_entry_to_cache)
{
- notifyObservers(id, entry->mGroupName, "", TRUE);
+ //llinfos << "Adding entry for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl;
+ mCache[id] = entry;
}
+
+ notifyObservers(id, entry->mFirstName, entry->mLastName, isGroup);
}
}
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index 2757b86a7c..bfa116ad4a 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -89,12 +89,8 @@ public:
// If the data is currently available, may call the callback immediatly
// otherwise, will request the data, and will call the callback when
// available. There is no garuntee the callback will ever be called.
- void get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data = NULL);
+ void getNameFromUUID(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data = NULL);
- // LEGACY
- void getName(const LLUUID& id, LLCacheNameCallback callback, void* user_data = NULL)
- { get(id, FALSE, callback, user_data); }
-
// This method needs to be called from time to time to send out
// requests.
void processPending();
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index bbb56960df..5236a52164 100644
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llhttpclientadapter.cpp
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
index d5f3aeaf2c..c489dca32d 100644
--- a/indra/llmessage/llhttpclientadapter.h
+++ b/indra/llmessage/llhttpclientadapter.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llhttpclientadepter.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h
index 1f13d46447..61826cc4b4 100644
--- a/indra/llmessage/llhttpclientinterface.h
+++ b/indra/llmessage/llhttpclientinterface.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llhttpclientinterface.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llmessagesenderinterface.h b/indra/llmessage/llmessagesenderinterface.h
index 4082666339..d98d891563 100644
--- a/indra/llmessage/llmessagesenderinterface.h
+++ b/indra/llmessage/llmessagesenderinterface.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llmessagesenderinterface.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp
index 552cf4cbdb..08c12f90da 100644
--- a/indra/llmessage/llregionpresenceverifier.cpp
+++ b/indra/llmessage/llregionpresenceverifier.cpp
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llregionpresenceverifier.cpp
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -25,11 +25,40 @@
#include "net.h"
#include "message.h"
+namespace boost
+{
+ void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p)
+ {
+ ++p->mReferenceCount;
+ }
+
+ void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p)
+ {
+ if(p && 0 == --p->mReferenceCount)
+ {
+ delete p;
+ }
+ }
+};
-LLRegionPresenceVerifier::RegionResponder::RegionResponder(ResponsePtr data) : mSharedData(data)
+LLRegionPresenceVerifier::Response::~Response()
{
}
+LLRegionPresenceVerifier::RegionResponder::RegionResponder(const std::string&
+ uri,
+ ResponsePtr data,
+ S32 retry_count) :
+ mUri(uri),
+ mSharedData(data),
+ mRetryCount(retry_count)
+{
+}
+
+//virtual
+LLRegionPresenceVerifier::RegionResponder::~RegionResponder()
+{
+}
void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
{
@@ -42,26 +71,32 @@ void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
std::stringstream uri;
uri << "http://" << destination.getString() << "/state/basic/";
- mSharedData->getHttpClient().get(uri.str(), new VerifiedDestinationResponder(mSharedData, content));
+ mSharedData->getHttpClient().get(
+ uri.str(),
+ new VerifiedDestinationResponder(mUri, mSharedData, content, mRetryCount));
}
-void LLRegionPresenceVerifier::RegionResponder::completed(
- U32 status,
- const std::string& reason,
- const LLSD& content)
+void LLRegionPresenceVerifier::RegionResponder::error(U32 status,
+ const std::string& reason)
{
- LLHTTPClient::Responder::completed(status, reason, content);
-
- mSharedData->onCompletedRegionRequest();
+ // TODO: babbage: distinguish between region presence service and
+ // region verification errors?
+ mSharedData->onRegionVerificationFailed();
}
-
-LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(ResponsePtr data, const LLSD& content) : mSharedData(data), mContent(content)
+LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, const LLSD& content,
+ S32 retry_count):
+ mUri(uri),
+ mSharedData(data),
+ mContent(content),
+ mRetryCount(retry_count)
{
}
-
-
+//virtual
+LLRegionPresenceVerifier::VerifiedDestinationResponder::~VerifiedDestinationResponder()
+{
+}
void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& content)
{
@@ -76,13 +111,14 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD&
{
mSharedData->onRegionVerified(mContent);
}
- else if (mSharedData->shouldRetry())
+ else if (mRetryCount > 0)
{
retry();
}
else
{
- llwarns << "Could not correctly look up region from region presence service. Region: " << mSharedData->getRegionUri() << llendl;
+ llwarns << "Simulator verification failed. Region: " << mUri << llendl;
+ mSharedData->onRegionVerificationFailed();
}
}
@@ -90,13 +126,21 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::retry()
{
LLSD headers;
headers["Cache-Control"] = "no-cache, max-age=0";
- llinfos << "Requesting region information, get uncached for region " << mSharedData->getRegionUri() << llendl;
- mSharedData->decrementRetries();
- mSharedData->getHttpClient().get(mSharedData->getRegionUri(), new RegionResponder(mSharedData), headers);
+ llinfos << "Requesting region information, get uncached for region "
+ << mUri << llendl;
+ --mRetryCount;
+ mSharedData->getHttpClient().get(mUri, new RegionResponder(mUri, mSharedData, mRetryCount), headers);
}
void LLRegionPresenceVerifier::VerifiedDestinationResponder::error(U32 status, const std::string& reason)
{
- retry();
+ if(mRetryCount > 0)
+ {
+ retry();
+ }
+ else
+ {
+ llwarns << "Failed to contact simulator for verification. Region: " << mUri << llendl;
+ mSharedData->onRegionVerificationFailed();
+ }
}
-
diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h
index d1de608ec6..f11eeef50c 100644
--- a/indra/llmessage/llregionpresenceverifier.h
+++ b/indra/llmessage/llregionpresenceverifier.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llregionpresenceverifier.cpp
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -26,7 +26,7 @@
#include "llhttpclient.h"
#include <string>
#include "llsd.h"
-#include <boost/shared_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
class LLHTTPClientInterface;
@@ -36,48 +36,57 @@ public:
class Response
{
public:
- virtual ~Response() {}
+ virtual ~Response() = 0;
virtual bool checkValidity(const LLSD& content) const = 0;
virtual void onRegionVerified(const LLSD& region_details) = 0;
-
- virtual void decrementRetries() = 0;
+ virtual void onRegionVerificationFailed() = 0;
virtual LLHTTPClientInterface& getHttpClient() = 0;
- virtual std::string getRegionUri() const = 0;
- virtual bool shouldRetry() const = 0;
- virtual void onCompletedRegionRequest() {}
+ public: /* but not really -- don't touch this */
+ U32 mReferenceCount;
};
- typedef boost::shared_ptr<Response> ResponsePtr;
+ typedef boost::intrusive_ptr<Response> ResponsePtr;
class RegionResponder : public LLHTTPClient::Responder
{
public:
- RegionResponder(ResponsePtr data);
+ RegionResponder(const std::string& uri, ResponsePtr data,
+ S32 retry_count);
+ virtual ~RegionResponder();
virtual void result(const LLSD& content);
- virtual void completed(
- U32 status,
- const std::string& reason,
- const LLSD& content);
+ virtual void error(U32 status, const std::string& reason);
private:
ResponsePtr mSharedData;
+ std::string mUri;
+ S32 mRetryCount;
};
class VerifiedDestinationResponder : public LLHTTPClient::Responder
{
public:
- VerifiedDestinationResponder(ResponsePtr data, const LLSD& content);
+ VerifiedDestinationResponder(const std::string& uri, ResponsePtr data,
+ const LLSD& content, S32 retry_count);
+ virtual ~VerifiedDestinationResponder();
virtual void result(const LLSD& content);
virtual void error(U32 status, const std::string& reason);
+
private:
void retry();
ResponsePtr mSharedData;
LLSD mContent;
+ std::string mUri;
+ S32 mRetryCount;
};
};
+namespace boost
+{
+ void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p);
+ void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p);
+};
#endif //LL_LLREGIONPRESENCEVERIFIER_H
diff --git a/indra/llmessage/llstoredmessage.cpp b/indra/llmessage/llstoredmessage.cpp
index 615eff405d..da6d1c84a8 100644
--- a/indra/llmessage/llstoredmessage.cpp
+++ b/indra/llmessage/llstoredmessage.cpp
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llstoredmessage.cpp
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h
index e817f19bd2..6a27698b03 100644
--- a/indra/llmessage/llstoredmessage.h
+++ b/indra/llmessage/llstoredmessage.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llstoredmessage.h
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llthrottle.cpp b/indra/llmessage/llthrottle.cpp
index 70279a3c62..0872efba50 100644
--- a/indra/llmessage/llthrottle.cpp
+++ b/indra/llmessage/llthrottle.cpp
@@ -265,6 +265,31 @@ BOOL LLThrottleGroup::setNominalBPS(F32* throttle_vec)
return changed;
}
+// Return bits available in the channel
+S32 LLThrottleGroup::getAvailable(S32 throttle_cat)
+{
+ S32 retval = 0;
+
+ F32 category_bps = mCurrentBPS[throttle_cat];
+ F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
+
+ // use a temporary bits_available
+ // since we don't want to change mBitsAvailable every time
+ F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]);
+ F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time);
+
+ if (bits_available >= lookahead_bits)
+ {
+ retval = (S32) gThrottleMaximumBPS[throttle_cat];
+ }
+ else
+ {
+ retval = (S32) bits_available;
+ }
+
+ return retval;
+}
+
BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)
{
diff --git a/indra/llmessage/llthrottle.h b/indra/llmessage/llthrottle.h
index 7d1679beb2..47a7c653b2 100644
--- a/indra/llmessage/llthrottle.h
+++ b/indra/llmessage/llthrottle.h
@@ -84,6 +84,8 @@ public:
BOOL dynamicAdjust(); // Shift bandwidth from idle channels to busy channels, TRUE if adjustment occurred
BOOL setNominalBPS(F32* throttle_vec); // TRUE if any value was different, resets adjustment system if was different
+ S32 getAvailable(S32 throttle_cat); // Return bits available in the channel
+
void packThrottle(LLDataPacker &dp) const;
void unpackThrottle(LLDataPacker &dp);
public:
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 3ab8057abb..81b7761ed5 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -51,6 +51,7 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499;
* String constants
*/
const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
+const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
@@ -247,7 +248,29 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
PUMP_DEBUG;
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
//llinfos << "LLURLRequest::process_impl()" << llendl;
- if(!buffer) return STATUS_ERROR;
+ if (!buffer) return STATUS_ERROR;
+
+ // we're still waiting or prcessing, check how many
+ // bytes we have accumulated.
+ const S32 MIN_ACCUMULATION = 100000;
+ if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
+ {
+ // This is a pretty sloppy calculation, but this
+ // tries to make the gross assumption that if data
+ // is coming in at 56kb/s, then this transfer will
+ // probably succeed. So, if we're accumlated
+ // 100,000 bytes (MIN_ACCUMULATION) then let's
+ // give this client another 2s to complete.
+ const F32 TIMEOUT_ADJUSTMENT = 2.0f;
+ mDetail->mByteAccumulator = 0;
+ pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
+ lldebugs << "LLURLRequest adjustTimeoutSeconds for request: " << mDetail->mURL << llendl;
+ if (mState == STATE_INITIALIZED)
+ {
+ llinfos << "LLURLRequest adjustTimeoutSeconds called during upload" << llendl;
+ }
+ }
+
switch(mState)
{
case STATE_INITIALIZED:
@@ -286,27 +309,14 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
bool newmsg = mDetail->mCurlRequest->getResult(&result);
if(!newmsg)
{
- // we're still waiting or prcessing, check how many
- // bytes we have accumulated.
- const S32 MIN_ACCUMULATION = 100000;
- if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
- {
- // This is a pretty sloppy calculation, but this
- // tries to make the gross assumption that if data
- // is coming in at 56kb/s, then this transfer will
- // probably succeed. So, if we're accumlated
- // 100,000 bytes (MIN_ACCUMULATION) then let's
- // give this client another 2s to complete.
- const F32 TIMEOUT_ADJUSTMENT = 2.0f;
- mDetail->mByteAccumulator = 0;
- pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
- }
-
// keep processing
break;
}
mState = STATE_HAVE_RESPONSE;
+ context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+ context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+ lldebugs << this << "Setting context to " << context << llendl;
switch(result)
{
case CURLE_OK:
@@ -353,10 +363,16 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
// we already stuffed everything into channel in in the curl
// callback, so we are done.
eos = true;
+ context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+ context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+ lldebugs << this << "Setting context to " << context << llendl;
return STATUS_DONE;
default:
PUMP_DEBUG;
+ context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+ context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+ lldebugs << this << "Setting context to " << context << llendl;
return STATUS_ERROR;
}
}
@@ -369,6 +385,8 @@ void LLURLRequest::initialize()
mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);
mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this);
+ mRequestTransferedBytes = 0;
+ mResponseTransferedBytes = 0;
}
bool LLURLRequest::configure()
@@ -471,6 +489,7 @@ size_t LLURLRequest::downCallback(
req->mDetail->mChannels.out(),
(U8*)data,
bytes);
+ req->mResponseTransferedBytes += bytes;
req->mDetail->mByteAccumulator += bytes;
return bytes;
}
@@ -494,6 +513,7 @@ size_t LLURLRequest::upCallback(
req->mDetail->mLastRead,
(U8*)data,
bytes);
+ req->mRequestTransferedBytes += bytes;
return bytes;
}
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
index 86ef71f085..cb3c466440 100644
--- a/indra/llmessage/llurlrequest.h
+++ b/indra/llmessage/llurlrequest.h
@@ -45,6 +45,12 @@
#include "llchainio.h"
#include "llerror.h"
+
+extern const std::string CONTEXT_REQUEST;
+extern const std::string CONTEXT_DEST_URI_SD_LABEL;
+extern const std::string CONTEXT_RESPONSE;
+extern const std::string CONTEXT_TRANSFERED_BYTES;
+
class LLURLRequestDetail;
class LLURLRequestComplete;
@@ -208,6 +214,8 @@ protected:
ERequestAction mAction;
LLURLRequestDetail* mDetail;
LLIOPipe::ptr_t mCompletionCallback;
+ S32 mRequestTransferedBytes;
+ S32 mResponseTransferedBytes;
private:
/**
diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
new file mode 100644
index 0000000000..b7602ef15c
--- /dev/null
+++ b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
@@ -0,0 +1,111 @@
+/**
+ * @file
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2001-2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "../test/lltut.h"
+#include "llregionpresenceverifier.h"
+#include "llcurl_stub.cpp"
+#include "llhost.cpp"
+#include "net.cpp"
+#include "lltesthttpclientadapter.cpp"
+
+class LLTestResponse : public LLRegionPresenceVerifier::Response
+{
+public:
+
+ virtual bool checkValidity(const LLSD& content) const
+ {
+ return true;
+ }
+
+ virtual void onRegionVerified(const LLSD& region_details)
+ {
+ }
+
+ virtual void onRegionVerificationFailed()
+ {
+ }
+
+ virtual LLHTTPClientInterface& getHttpClient()
+ {
+ return mHttpInterface;
+ }
+
+ LLTestHTTPClientAdapter mHttpInterface;
+};
+
+namespace tut
+{
+ struct LLRegionPresenceVerifierData
+ {
+ LLRegionPresenceVerifierData() :
+ mResponse(new LLTestResponse()),
+ mResponder("", LLRegionPresenceVerifier::ResponsePtr(mResponse),
+ LLSD(), 3)
+ {
+ }
+
+ LLTestResponse* mResponse;
+ LLRegionPresenceVerifier::VerifiedDestinationResponder mResponder;
+ };
+
+ typedef test_group<LLRegionPresenceVerifierData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory tf("LLRegionPresenceVerifier test");
+}
+
+namespace tut
+{
+ // Test that VerifiedDestinationResponder does retry
+ // on error when shouldRetry returns true.
+ template<> template<>
+ void object::test<1>()
+ {
+ mResponder.error(500, "Internal server error");
+ ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 1);
+ }
+
+ // Test that VerifiedDestinationResponder only retries
+ // on error until shouldRetry returns false.
+ template<> template<>
+ void object::test<2>()
+ {
+ mResponder.error(500, "Internal server error");
+ mResponder.error(500, "Internal server error");
+ mResponder.error(500, "Internal server error");
+ mResponder.error(500, "Internal server error");
+ ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 3);
+ }
+}
+