summaryrefslogtreecommitdiff
path: root/indra/newview/llappcorehttp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llappcorehttp.cpp')
-rwxr-xr-xindra/newview/llappcorehttp.cpp249
1 files changed, 207 insertions, 42 deletions
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index 0d7d41304d..70dcffefb2 100755
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -28,18 +28,81 @@
#include "llappcorehttp.h"
+#include "llappviewer.h"
#include "llviewercontrol.h"
+// Here is where we begin to get our connection usage under control.
+// This establishes llcorehttp policy classes that, among other
+// things, limit the maximum number of connections to outside
+// services. Each of the entries below maps to a policy class and
+// has a limit, sometimes configurable, of how many connections can
+// be open at a time.
+
const F64 LLAppCoreHttp::MAX_THREAD_WAIT_TIME(10.0);
+static const struct
+{
+ LLAppCoreHttp::EAppPolicy mPolicy;
+ U32 mDefault;
+ U32 mMin;
+ U32 mMax;
+ U32 mRate;
+ std::string mKey;
+ const char * mUsage;
+} init_data[] = // Default and dynamic values for classes
+{
+ {
+ LLAppCoreHttp::AP_DEFAULT, 8, 8, 8, 0,
+ "",
+ "other"
+ },
+ {
+ LLAppCoreHttp::AP_TEXTURE, 8, 1, 12, 0,
+ "TextureFetchConcurrency",
+ "texture fetch"
+ },
+ {
+ LLAppCoreHttp::AP_MESH1, 32, 1, 128, 100,
+ "MeshMaxConcurrentRequests",
+ "mesh fetch"
+ },
+ {
+ LLAppCoreHttp::AP_MESH2, 8, 1, 32, 100,
+ "Mesh2MaxConcurrentRequests",
+ "mesh2 fetch"
+ },
+ {
+ LLAppCoreHttp::AP_LARGE_MESH, 2, 1, 8, 0,
+ "",
+ "large mesh fetch"
+ },
+ {
+ LLAppCoreHttp::AP_UPLOADS, 2, 1, 8, 0,
+ "",
+ "asset upload"
+ },
+ {
+ LLAppCoreHttp::AP_LONG_POLL, 32, 32, 32, 0,
+ "",
+ "long poll"
+ }
+};
+
+static void setting_changed();
+
LLAppCoreHttp::LLAppCoreHttp()
: mRequest(NULL),
mStopHandle(LLCORE_HTTP_HANDLE_INVALID),
mStopRequested(0.0),
- mStopped(false),
- mPolicyDefault(-1)
-{}
+ mStopped(false)
+{
+ for (int i(0); i < LL_ARRAY_SIZE(mPolicies); ++i)
+ {
+ mPolicies[i] = LLCore::HttpRequest::DEFAULT_POLICY_ID;
+ mSettings[i] = 0U;
+ }
+}
LLAppCoreHttp::~LLAppCoreHttp()
@@ -54,30 +117,28 @@ void LLAppCoreHttp::init()
LLCore::HttpStatus status = LLCore::HttpRequest::createService();
if (! status)
{
- LL_ERRS("Init") << "Failed to initialize HTTP services. Reason: "
- << status.toString()
+ LL_ERRS("Init") << "Failed to initialize HTTP services. Reason: " << status.toString()
<< LL_ENDL;
}
// Point to our certs or SSH/https: will fail on connect
- status = LLCore::HttpRequest::setPolicyGlobalOption(LLCore::HttpRequest::GP_CA_FILE,
- gDirUtilp->getCAFile());
+ status = LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_CA_FILE,
+ LLCore::HttpRequest::GLOBAL_POLICY_ID,
+ gDirUtilp->getCAFile(), NULL);
if (! status)
{
- LL_ERRS("Init") << "Failed to set CA File for HTTP services. Reason: "
- << status.toString()
+ LL_ERRS("Init") << "Failed to set CA File for HTTP services. Reason: " << status.toString()
<< LL_ENDL;
}
- // Establish HTTP Proxy. "LLProxy" is a special string which directs
- // the code to use LLProxy::applyProxySettings() to establish any
- // HTTP or SOCKS proxy for http operations.
- status = LLCore::HttpRequest::setPolicyGlobalOption(LLCore::HttpRequest::GP_LLPROXY, 1);
+ // Establish HTTP Proxy, if desired.
+ status = LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_LLPROXY,
+ LLCore::HttpRequest::GLOBAL_POLICY_ID,
+ 1, NULL);
if (! status)
{
- LL_ERRS("Init") << "Failed to set HTTP proxy for HTTP services. Reason: "
- << status.toString()
- << LL_ENDL;
+ LL_WARNS("Init") << "Failed to set HTTP proxy for HTTP services. Reason: " << status.toString()
+ << LL_ENDL;
}
// Tracing levels for library & libcurl (note that 2 & 3 are beyond spammy):
@@ -90,47 +151,74 @@ void LLAppCoreHttp::init()
{
long trace_level(0L);
trace_level = long(gSavedSettings.getU32(http_trace));
- status = LLCore::HttpRequest::setPolicyGlobalOption(LLCore::HttpRequest::GP_TRACE, trace_level);
+ status = LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_TRACE,
+ LLCore::HttpRequest::GLOBAL_POLICY_ID,
+ trace_level, NULL);
}
// Setup default policy and constrain if directed to
- mPolicyDefault = LLCore::HttpRequest::DEFAULT_POLICY_ID;
- static const std::string texture_concur("TextureFetchConcurrency");
- if (gSavedSettings.controlExists(texture_concur))
+ mPolicies[AP_DEFAULT] = LLCore::HttpRequest::DEFAULT_POLICY_ID;
+
+ // Setup additional policies based on table and some special rules
+ for (int i(0); i < LL_ARRAY_SIZE(init_data); ++i)
{
- U32 concur(llmin(gSavedSettings.getU32(texture_concur), U32(12)));
+ const EAppPolicy policy(init_data[i].mPolicy);
- if (concur > 0)
+ if (AP_DEFAULT == policy)
{
- LLCore::HttpStatus status;
- status = LLCore::HttpRequest::setPolicyClassOption(mPolicyDefault,
- LLCore::HttpRequest::CP_CONNECTION_LIMIT,
- concur);
- if (! status)
- {
- LL_WARNS("Init") << "Unable to set texture fetch concurrency. Reason: "
- << status.toString()
- << LL_ENDL;
- }
- else
- {
- LL_INFOS("Init") << "Application settings overriding default texture fetch concurrency. New value: "
- << concur
- << LL_ENDL;
- }
+ // Pre-created
+ continue;
+ }
+
+ mPolicies[policy] = LLCore::HttpRequest::createPolicyClass();
+ if (! mPolicies[policy])
+ {
+ // Use default policy (but don't accidentally modify default)
+ LL_WARNS("Init") << "Failed to create HTTP policy class for " << init_data[i].mUsage
+ << ". Using default policy."
+ << LL_ENDL;
+ mPolicies[policy] = mPolicies[AP_DEFAULT];
+ continue;
}
}
+
+ // Need a request object to handle dynamic options before setting them
+ mRequest = new LLCore::HttpRequest;
+
+ // Apply initial settings
+ refreshSettings(true);
// Kick the thread
status = LLCore::HttpRequest::startThread();
if (! status)
{
- LL_ERRS("Init") << "Failed to start HTTP servicing thread. Reason: "
- << status.toString()
+ LL_ERRS("Init") << "Failed to start HTTP servicing thread. Reason: " << status.toString()
<< LL_ENDL;
}
- mRequest = new LLCore::HttpRequest;
+ // Register signals for settings and state changes
+ for (int i(0); i < LL_ARRAY_SIZE(init_data); ++i)
+ {
+ if (! init_data[i].mKey.empty() && gSavedSettings.controlExists(init_data[i].mKey))
+ {
+ LLPointer<LLControlVariable> cntrl_ptr = gSavedSettings.getControl(init_data[i].mKey);
+ if (cntrl_ptr.isNull())
+ {
+ LL_WARNS("Init") << "Unable to set signal on global setting '" << init_data[i].mKey
+ << "'" << LL_ENDL;
+ }
+ else
+ {
+ mSettingsSignal[i] = cntrl_ptr->getCommitSignal()->connect(boost::bind(&setting_changed));
+ }
+ }
+ }
+}
+
+
+void setting_changed()
+{
+ LLAppViewer::instance()->getAppCoreHttp().refreshSettings(false);
}
@@ -173,6 +261,11 @@ void LLAppCoreHttp::cleanup()
}
}
+ for (int i(0); i < LL_ARRAY_SIZE(init_data); ++i)
+ {
+ mSettingsSignal[i].disconnect();
+ }
+
delete mRequest;
mRequest = NULL;
@@ -185,6 +278,78 @@ void LLAppCoreHttp::cleanup()
}
}
+void LLAppCoreHttp::refreshSettings(bool initial)
+{
+ LLCore::HttpStatus status;
+
+ for (int i(0); i < LL_ARRAY_SIZE(init_data); ++i)
+ {
+ const EAppPolicy policy(init_data[i].mPolicy);
+
+ // Set any desired throttle
+ if (initial && init_data[i].mRate)
+ {
+ // Init-time only, can use the static setters here
+ status = LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_THROTTLE_RATE,
+ mPolicies[policy],
+ init_data[i].mRate,
+ NULL);
+ if (! status)
+ {
+ LL_WARNS("Init") << "Unable to set " << init_data[i].mUsage
+ << " throttle rate. Reason: " << status.toString()
+ << LL_ENDL;
+ }
+ }
+
+ // Get target connection concurrency value
+ U32 setting(init_data[i].mDefault);
+ if (! init_data[i].mKey.empty() && gSavedSettings.controlExists(init_data[i].mKey))
+ {
+ U32 new_setting(gSavedSettings.getU32(init_data[i].mKey));
+ if (new_setting)
+ {
+ // Treat zero settings as an ask for default
+ setting = llclamp(new_setting, init_data[i].mMin, init_data[i].mMax);
+ }
+ }
+
+ if (! initial && setting == mSettings[policy])
+ {
+ // Unchanged, try next setting
+ continue;
+ }
+
+ // Set it and report
+ // *TODO: These are intended to be per-host limits when we can
+ // support that in llcorehttp/libcurl.
+ LLCore::HttpHandle handle;
+ handle = mRequest->setPolicyOption(LLCore::HttpRequest::PO_CONNECTION_LIMIT,
+ mPolicies[policy],
+ setting, NULL);
+ if (LLCORE_HTTP_HANDLE_INVALID == handle)
+ {
+ status = mRequest->getStatus();
+ LL_WARNS("Init") << "Unable to set " << init_data[i].mUsage
+ << " concurrency. Reason: " << status.toString()
+ << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("Init") << "Changed " << init_data[i].mUsage
+ << " concurrency. New value: " << setting
+ << LL_ENDL;
+ mSettings[policy] = setting;
+ if (initial && setting != init_data[i].mDefault)
+ {
+ LL_INFOS("Init") << "Application settings overriding default " << init_data[i].mUsage
+ << " concurrency. New value: " << setting
+ << LL_ENDL;
+ }
+ }
+ }
+}
+
void LLAppCoreHttp::onCompleted(LLCore::HttpHandle, LLCore::HttpResponse *)
{