Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions indra/llcorehttp/_httpinternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ constexpr int HTTP_CONNECTION_LIMIT_MAX = 256;
constexpr long HTTP_PIPELINING_DEFAULT = 0L;
constexpr long HTTP_PIPELINING_MAX = 20L;

// Multiplexing limits
constexpr long HTTP_MULTIPLEXING_DEFAULT = 0L;

// Miscellaneous defaults
constexpr bool HTTP_USE_RETRY_AFTER_DEFAULT = true;
constexpr long HTTP_THROTTLE_RATE_DEFAULT = 0L;
Expand Down
22 changes: 19 additions & 3 deletions indra/llcorehttp/_httplibcurl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,12 +487,27 @@ void HttpLibcurl::policyUpdated(unsigned int policy_class)
policy.stallPolicy(policy_class, false);
mDirtyPolicy[policy_class] = false;

if (options.mPipelining > 1)
if (options.mMultiplexing)
{
// Enable HTTP/2 Multiplexing
LL_INFOS(LOG_CORE) << "HTTP/2 Multiplexing Enable." << LL_ENDL;
check_curl_multi_setopt(multi_handle,
CURLMOPT_PIPELINING,
CURLPIPE_MULTIPLEX);
check_curl_multi_setopt(multi_handle,
CURLMOPT_MAX_HOST_CONNECTIONS,
long(options.mPerHostConnectionLimit));
check_curl_multi_setopt(multi_handle,
CURLMOPT_MAX_TOTAL_CONNECTIONS,
long(options.mConnectionLimit));
}
else if (options.mPipelining > 1)
{
// We'll try to do pipelining on this multihandle
LL_INFOS(LOG_CORE) << "HTTP Pipelining Enable." << LL_ENDL;
check_curl_multi_setopt(multi_handle,
CURLMOPT_PIPELINING,
1L);
CURLPIPE_HTTP1);
check_curl_multi_setopt(multi_handle,
CURLMOPT_MAX_PIPELINE_LENGTH,
long(options.mPipelining));
Expand All @@ -505,9 +520,10 @@ void HttpLibcurl::policyUpdated(unsigned int policy_class)
}
else
{
LL_INFOS(LOG_CORE) << "HTTP Pipelining Disable." << LL_ENDL;
check_curl_multi_setopt(multi_handle,
CURLMOPT_PIPELINING,
0L);
CURLPIPE_NOTHING);
check_curl_multi_setopt(multi_handle,
CURLMOPT_MAX_HOST_CONNECTIONS,
0L);
Expand Down
11 changes: 11 additions & 0 deletions indra/llcorehttp/_httppolicyclass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ HttpPolicyClass::HttpPolicyClass()
: mConnectionLimit(HTTP_CONNECTION_LIMIT_DEFAULT),
mPerHostConnectionLimit(HTTP_CONNECTION_LIMIT_DEFAULT),
mPipelining(HTTP_PIPELINING_DEFAULT),
mMultiplexing(HTTP_MULTIPLEXING_DEFAULT),
mThrottleRate(HTTP_THROTTLE_RATE_DEFAULT)
{}

Expand All @@ -52,6 +53,7 @@ HttpPolicyClass & HttpPolicyClass::operator=(const HttpPolicyClass & other)
mConnectionLimit = other.mConnectionLimit;
mPerHostConnectionLimit = other.mPerHostConnectionLimit;
mPipelining = other.mPipelining;
mMultiplexing = other.mMultiplexing;
mThrottleRate = other.mThrottleRate;
}
return *this;
Expand All @@ -62,6 +64,7 @@ HttpPolicyClass::HttpPolicyClass(const HttpPolicyClass & other)
: mConnectionLimit(other.mConnectionLimit),
mPerHostConnectionLimit(other.mPerHostConnectionLimit),
mPipelining(other.mPipelining),
mMultiplexing(other.mMultiplexing),
mThrottleRate(other.mThrottleRate)
{}

Expand All @@ -82,6 +85,10 @@ HttpStatus HttpPolicyClass::set(HttpRequest::EPolicyOption opt, long value)
mPipelining = llclamp(value, 0L, HTTP_PIPELINING_MAX);
break;

case HttpRequest::PO_MULTIPLEXING_MODE:
mMultiplexing = llclamp(value, 0L, 1L);
break;

case HttpRequest::PO_THROTTLE_RATE:
mThrottleRate = llclamp(value, 0L, 1000000L);
break;
Expand Down Expand Up @@ -110,6 +117,10 @@ HttpStatus HttpPolicyClass::get(HttpRequest::EPolicyOption opt, long * value) co
*value = mPipelining;
break;

case HttpRequest::PO_MULTIPLEXING_MODE:
*value = mMultiplexing;
break;

case HttpRequest::PO_THROTTLE_RATE:
*value = mThrottleRate;
break;
Expand Down
1 change: 1 addition & 0 deletions indra/llcorehttp/_httppolicyclass.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class HttpPolicyClass
long mConnectionLimit;
long mPerHostConnectionLimit;
long mPipelining;
long mMultiplexing;
long mThrottleRate;
}; // end class HttpPolicyClass

Expand Down
4 changes: 4 additions & 0 deletions indra/llcorehttp/httprequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ class HttpRequest
/// Per-class only
PO_PIPELINING_DEPTH,

/// If it is 1, enable HTTP Multiplexing.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More explanation about this API. The 'public' API presented here is not meant to be a facade for libcurl. At the time this was written and also possibly for future purposes, libcurl might be replaced by another library. (For Sansar, we had our own low-level libcurl-like library which could have slotted in.) The 'public' API avoided using libcurl definitions.

Instead, this API is meant to describe how the viewer wants to use HTTP requests and how HTTP traffic should be managed and shaped. The intent is to have this description be as minimal as possible. If a concept isn't used by the viewer, it won't appear here.

Internal APIs, such as _httplibcurl.*, are the translation layer between the public API and whatever is going on below. An adapter layer. There's only one concrete adapter at this point but that is okay.

And so we have the comment above:

When PIPELINING_DEPTH is 2 or more, libcurl performs

That is still correct. The public API describes an abstract usage and a pipelining depth of 2 or more enables pipelining. And so the code above in _httplibcurl is no longer correct.

What should this API be in the http/2 world? Well, we don't know yet. We haven't stood up the infrastructure to support it. But we would probably want to modify llcorehttp differently. PO_PIPELINING_DEPTH might instead be changed to PO_REQUEST_CONCURRENCY covering both the http/1 (pipelining) and http/2 (multiplexing) cases with added explicit enables/disables for pipelining and http/2. However, we may find that we need independent http/2 parameters for the policy classes.

(There's another weak reason to keep existing API definitions as-is: we use a copy of this code in server-side binaries and subtle changes may not be caught. This isn't meant to stop changes and progress in the viewer. But when all other considerations are equal, keeping an API spec has a benefit to us.)

/// Per-class only
PO_MULTIPLEXING_MODE,

/// Controls whether client-side throttling should be
/// performed on this policy class. Positive values
/// enable throttling and specify the request rate
Expand Down
11 changes: 11 additions & 0 deletions indra/newview/app_settings/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3522,6 +3522,17 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>UseHTTP2Multiplexing</key>
<map>
<key>Comment</key>
<string>Enable HTTP/2 Multiplexing</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>HttpRangeRequestsDisable</key>
<map>
<key>Comment</key>
Expand Down
47 changes: 45 additions & 2 deletions indra/newview/llappcorehttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ static void ssl_verification_changed();
LLAppCoreHttp::HttpClass::HttpClass()
: mPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
mConnLimit(0U),
mPipelined(false)
mPipelined(false),
mMultiplexing(false)
{}


Expand All @@ -131,7 +132,8 @@ LLAppCoreHttp::LLAppCoreHttp()
mStopHandle(LLCORE_HTTP_HANDLE_INVALID),
mStopRequested(0.0),
mStopped(false),
mPipelined(true)
mPipelined(true),
mMultiplexing(false)
{}


Expand Down Expand Up @@ -281,6 +283,15 @@ void LLAppCoreHttp::init()
LL_INFOS("Init") << "HTTP Pipelining " << (mPipelined ? "enabled" : "disabled") << "!" << LL_ENDL;
}

// Global multiplexing setting
static const std::string http_multiplexing("UseHTTP2Multiplexing");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I would have merged "HttpPipelining" and "UseHTTP2Multiplexing" into some kind of 'mode switch' since they are sort of exclusive.

if (gSavedSettings.controlExists(http_multiplexing))
{
// Default to true (in ctor) if absent.
mMultiplexing = gSavedSettings.getBOOL(http_multiplexing);
LL_INFOS("Init") << "HTTP Multiplexing " << (mMultiplexing ? "enabled" : "disabled") << "!" << LL_ENDL;
}

// Register signals for settings and state changes
for (int i(0); i < LL_ARRAY_SIZE(init_data); ++i)
{
Expand Down Expand Up @@ -451,6 +462,38 @@ void LLAppCoreHttp::refreshSettings(bool initial)
}
}

// Multiplexing changes
if (initial)
{
const bool to_multiplex(mMultiplexing);
if (to_multiplex != mHttpClasses[app_policy].mMultiplexing)
{
// Pipeline election changing, set dynamic option via request

LLCore::HttpHandle handle;
const long new_mode(to_multiplex ? 1 : 0);

handle = mRequest->setPolicyOption(LLCore::HttpRequest::PO_MULTIPLEXING_MODE,
mHttpClasses[app_policy].mPolicy,
new_mode,
LLCore::HttpHandler::ptr_t());
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
status = mRequest->getStatus();
LL_WARNS("Init") << "Unable to set " << init_data[i].mUsage
<< " pipelining. Reason: " << status.toString()
<< LL_ENDL;
}
else
{
LL_DEBUGS("Init") << "Changed " << init_data[i].mUsage
<< " multiplexing. New mode: " << (new_mode ? "enable" : "disable")
<< LL_ENDL;
mHttpClasses[app_policy].mMultiplexing = to_multiplex;
}
}
}

// Get target connection concurrency value
U32 setting(init_data[i].mDefault);
if (! init_data[i].mKey.empty() && gSavedSettings.controlExists(init_data[i].mKey))
Expand Down
2 changes: 2 additions & 0 deletions indra/newview/llappcorehttp.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ class LLAppCoreHttp : public LLCore::HttpHandler
policy_t mPolicy; // Policy class id for the class
U32 mConnLimit;
bool mPipelined;
bool mMultiplexing;
boost::signals2::connection mSettingsSignal; // Signal to global setting that affect this class (if any)
};

Expand All @@ -255,6 +256,7 @@ class LLAppCoreHttp : public LLCore::HttpHandler
bool mStopped;
HttpClass mHttpClasses[AP_COUNT];
bool mPipelined; // Global setting
bool mMultiplexing; // Global setting
boost::signals2::connection mPipelinedSignal; // Signal for 'HttpPipelining' setting
boost::signals2::connection mSSLNoVerifySignal; // Signal for 'NoVerifySSLCert' setting

Expand Down