summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/AlternateServices.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/protocol/http/AlternateServices.cpp')
-rw-r--r--netwerk/protocol/http/AlternateServices.cpp71
1 files changed, 44 insertions, 27 deletions
diff --git a/netwerk/protocol/http/AlternateServices.cpp b/netwerk/protocol/http/AlternateServices.cpp
index a386206b6d..e0571f02ce 100644
--- a/netwerk/protocol/http/AlternateServices.cpp
+++ b/netwerk/protocol/http/AlternateServices.cpp
@@ -7,6 +7,7 @@
#include "HttpLog.h"
#include "AlternateServices.h"
+#include <algorithm>
#include "LoadInfo.h"
#include "mozilla/Atomics.h"
#include "mozilla/StaticPrefs_network.h"
@@ -87,16 +88,15 @@ void AltSvcMapping::ProcessHeader(
ParsedHeaderValueListList parsedAltSvc(buf);
int32_t numEntriesInHeader = parsedAltSvc.mValues.Length();
- // Only use one http3 version.
- bool http3Found = false;
-
+ nsTArray<RefPtr<AltSvcMapping>> h3Mappings;
+ nsTArray<RefPtr<AltSvcMapping>> otherMappings;
for (uint32_t index = 0; index < parsedAltSvc.mValues.Length(); ++index) {
uint32_t maxage = 86400; // default
nsAutoCString hostname;
nsAutoCString npnToken;
int32_t portno = originPort;
bool clearEntry = false;
- bool isHttp3 = false;
+ SupportedAlpnRank alpnRank = SupportedAlpnRank::NOT_SUPPORTED;
for (uint32_t pairIndex = 0;
pairIndex < parsedAltSvc.mValues[index].mValues.Length();
@@ -116,7 +116,7 @@ void AltSvcMapping::ProcessHeader(
// h2=[hostname]:443 or h3-xx=[hostname]:port
// XX is current version we support and it is define in nsHttp.h.
- isHttp3 = gHttpHandler->IsHttp3VersionSupported(currentName);
+ alpnRank = IsAlpnSupported(currentName);
npnToken = currentName;
int32_t colonIndex = currentValue.FindChar(':');
@@ -153,12 +153,7 @@ void AltSvcMapping::ProcessHeader(
// update nsCString length
nsUnescape(npnToken.BeginWriting());
npnToken.SetLength(strlen(npnToken.BeginReading()));
-
- if (http3Found && isHttp3) {
- LOG(("Alt Svc ignore multiple Http3 options (%s)", npnToken.get()));
- continue;
- }
-
+ bool isHttp3 = net::IsHttp3(alpnRank);
SpdyInformation* spdyInfo = gHttpHandler->SpdyInfo();
if (!(npnToken.Equals(spdyInfo->VersionString) &&
StaticPrefs::network_http_http2_enabled()) &&
@@ -169,16 +164,13 @@ void AltSvcMapping::ProcessHeader(
continue;
}
- if (isHttp3) {
- http3Found = true;
- }
-
- RefPtr<AltSvcMapping> mapping =
- new AltSvcMapping(gHttpHandler->AltServiceCache()->GetStoragePtr(),
- gHttpHandler->AltServiceCache()->StorageEpoch(),
- originScheme, originHost, originPort, username,
- privateBrowsing, NowInSeconds() + maxage, hostname,
- portno, npnToken, originAttributes, isHttp3);
+ LOG(("AltSvcMapping created npnToken=%s", npnToken.get()));
+ RefPtr<AltSvcMapping> mapping = new AltSvcMapping(
+ gHttpHandler->AltServiceCache()->GetStoragePtr(),
+ gHttpHandler->AltServiceCache()->StorageEpoch(), originScheme,
+ originHost, originPort, username, privateBrowsing,
+ NowInSeconds() + maxage, hostname, portno, npnToken, originAttributes,
+ isHttp3, alpnRank);
if (mapping->TTL() <= 0) {
LOG(("Alt Svc invalid map"));
mapping = nullptr;
@@ -186,15 +178,39 @@ void AltSvcMapping::ProcessHeader(
// as that would have happened if we had accepted the parameters.
gHttpHandler->AltServiceCache()->ClearHostMapping(originHost, originPort,
originAttributes);
- } else if (!aDontValidate) {
- gHttpHandler->UpdateAltServiceMapping(mapping, proxyInfo, callbacks, caps,
- originAttributes);
+ } else {
+ if (isHttp3) {
+ h3Mappings.AppendElement(std::move(mapping));
+ } else {
+ otherMappings.AppendElement(std::move(mapping));
+ }
+ }
+ }
+
+ auto doUpdateAltSvcMapping = [&](AltSvcMapping* aMapping) {
+ if (!aDontValidate) {
+ gHttpHandler->UpdateAltServiceMapping(aMapping, proxyInfo, callbacks,
+ caps, originAttributes);
} else {
gHttpHandler->UpdateAltServiceMappingWithoutValidation(
- mapping, proxyInfo, callbacks, caps, originAttributes);
+ aMapping, proxyInfo, callbacks, caps, originAttributes);
}
+ };
+
+ if (!h3Mappings.IsEmpty()) {
+ // Select the HTTP/3 (h3) AltSvcMapping with the highest ALPN rank from
+ // h3Mappings.
+ RefPtr<AltSvcMapping> latestH3Mapping = *std::max_element(
+ h3Mappings.begin(), h3Mappings.end(),
+ [](const RefPtr<AltSvcMapping>& a, const RefPtr<AltSvcMapping>& b) {
+ return a->AlpnRank() < b->AlpnRank();
+ });
+ doUpdateAltSvcMapping(latestH3Mapping);
}
+ std::for_each(otherMappings.begin(), otherMappings.end(),
+ doUpdateAltSvcMapping);
+
if (numEntriesInHeader) { // Ignore headers that were just "alt-svc: clear"
Telemetry::Accumulate(Telemetry::HTTP_ALTSVC_ENTRIES_PER_HEADER,
numEntriesInHeader);
@@ -209,7 +225,7 @@ AltSvcMapping::AltSvcMapping(nsIDataStorage* storage, int32_t epoch,
const nsACString& alternateHost,
int32_t alternatePort, const nsACString& npnToken,
const OriginAttributes& originAttributes,
- bool aIsHttp3)
+ bool aIsHttp3, SupportedAlpnRank aRank)
: mStorage(storage),
mStorageEpoch(epoch),
mAlternateHost(alternateHost),
@@ -221,7 +237,8 @@ AltSvcMapping::AltSvcMapping(nsIDataStorage* storage, int32_t epoch,
mExpiresAt(expiresAt),
mNPNToken(npnToken),
mOriginAttributes(originAttributes),
- mIsHttp3(aIsHttp3) {
+ mIsHttp3(aIsHttp3),
+ mAlpnRank(aRank) {
MOZ_ASSERT(NS_IsMainThread());
if (NS_FAILED(SchemeIsHTTPS(originScheme, mHttps))) {