mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 07:45:30 +00:00
Bug 1618849 - Add separate AltSvc for http2 and http3 and prefer http3 if allowed. r=necko-reviewers,valentin
Differential Revision: https://phabricator.services.mozilla.com/D86934
This commit is contained in:
parent
735a53ee64
commit
7433c1b34d
@ -165,7 +165,9 @@ void AltSvcMapping::ProcessHeader(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
http3Found = true;
|
if (isHttp3) {
|
||||||
|
http3Found = true;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<AltSvcMapping> mapping = new AltSvcMapping(
|
RefPtr<AltSvcMapping> mapping = new AltSvcMapping(
|
||||||
gHttpHandler->AltServiceCache()->GetStoragePtr(),
|
gHttpHandler->AltServiceCache()->GetStoragePtr(),
|
||||||
@ -255,7 +257,7 @@ AltSvcMapping::AltSvcMapping(
|
|||||||
|
|
||||||
if (mExpiresAt) {
|
if (mExpiresAt) {
|
||||||
MakeHashKey(mHashKey, originScheme, mOriginHost, mOriginPort, mPrivate,
|
MakeHashKey(mHashKey, originScheme, mOriginHost, mOriginPort, mPrivate,
|
||||||
mIsolated, mTopWindowOrigin, mOriginAttributes);
|
mIsolated, mTopWindowOrigin, mOriginAttributes, mIsHttp3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +267,8 @@ void AltSvcMapping::MakeHashKey(nsCString& outKey,
|
|||||||
int32_t originPort, bool privateBrowsing,
|
int32_t originPort, bool privateBrowsing,
|
||||||
bool isolated,
|
bool isolated,
|
||||||
const nsACString& topWindowOrigin,
|
const nsACString& topWindowOrigin,
|
||||||
const OriginAttributes& originAttributes) {
|
const OriginAttributes& originAttributes,
|
||||||
|
bool aHttp3) {
|
||||||
outKey.Truncate();
|
outKey.Truncate();
|
||||||
|
|
||||||
if (originPort == -1) {
|
if (originPort == -1) {
|
||||||
@ -284,15 +287,16 @@ void AltSvcMapping::MakeHashKey(nsCString& outKey,
|
|||||||
nsAutoCString suffix;
|
nsAutoCString suffix;
|
||||||
originAttributes.CreateSuffix(suffix);
|
originAttributes.CreateSuffix(suffix);
|
||||||
outKey.Append(suffix);
|
outKey.Append(suffix);
|
||||||
|
outKey.Append(':');
|
||||||
|
|
||||||
if (isolated) {
|
if (isolated) {
|
||||||
outKey.Append(':');
|
|
||||||
outKey.Append('I');
|
outKey.Append('I');
|
||||||
outKey.Append(':');
|
outKey.Append(':');
|
||||||
outKey.Append(topWindowOrigin);
|
outKey.Append(topWindowOrigin);
|
||||||
outKey.Append(
|
outKey.Append(
|
||||||
'|'); // Be careful, the top window origin may contain colons!
|
'|'); // Be careful, the top window origin may contain colons!
|
||||||
}
|
}
|
||||||
|
outKey.Append(aHttp3 ? '3' : '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t AltSvcMapping::TTL() { return mExpiresAt - NowInSeconds(); }
|
int32_t AltSvcMapping::TTL() { return mExpiresAt - NowInSeconds(); }
|
||||||
@ -479,7 +483,7 @@ AltSvcMapping::AltSvcMapping(DataStorage* storage, int32_t epoch,
|
|||||||
|
|
||||||
MakeHashKey(mHashKey, mHttps ? "https"_ns : "http"_ns, mOriginHost,
|
MakeHashKey(mHashKey, mHttps ? "https"_ns : "http"_ns, mOriginHost,
|
||||||
mOriginPort, mPrivate, mIsolated, mTopWindowOrigin,
|
mOriginPort, mPrivate, mIsolated, mTopWindowOrigin,
|
||||||
mOriginAttributes);
|
mOriginAttributes, mIsHttp3);
|
||||||
} while (false);
|
} while (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1132,7 +1136,8 @@ void AltSvcCache::UpdateAltServiceMapping(
|
|||||||
already_AddRefed<AltSvcMapping> AltSvcCache::GetAltServiceMapping(
|
already_AddRefed<AltSvcMapping> AltSvcCache::GetAltServiceMapping(
|
||||||
const nsACString& scheme, const nsACString& host, int32_t port,
|
const nsACString& scheme, const nsACString& host, int32_t port,
|
||||||
bool privateBrowsing, bool isolated, const nsACString& topWindowOrigin,
|
bool privateBrowsing, bool isolated, const nsACString& topWindowOrigin,
|
||||||
const OriginAttributes& originAttributes, bool aHttp3Allowed) {
|
const OriginAttributes& originAttributes, bool aHttp2Allowed,
|
||||||
|
bool aHttp3Allowed) {
|
||||||
EnsureStorageInited();
|
EnsureStorageInited();
|
||||||
|
|
||||||
bool isHTTPS;
|
bool isHTTPS;
|
||||||
@ -1146,24 +1151,39 @@ already_AddRefed<AltSvcMapping> AltSvcCache::GetAltServiceMapping(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoCString key;
|
// First look for HTTP3
|
||||||
AltSvcMapping::MakeHashKey(key, scheme, host, port, privateBrowsing, isolated,
|
if (aHttp3Allowed) {
|
||||||
topWindowOrigin, originAttributes);
|
nsAutoCString key;
|
||||||
RefPtr<AltSvcMapping> existing = LookupMapping(key, privateBrowsing);
|
AltSvcMapping::MakeHashKey(key, scheme, host, port, privateBrowsing, isolated,
|
||||||
LOG(
|
topWindowOrigin, originAttributes, true);
|
||||||
("AltSvcCache::GetAltServiceMapping %p key=%s "
|
RefPtr<AltSvcMapping> existing = LookupMapping(key, privateBrowsing);
|
||||||
"existing=%p validated=%d ttl=%d",
|
LOG(
|
||||||
this, key.get(), existing.get(), existing ? existing->Validated() : 0,
|
("AltSvcCache::GetAltServiceMapping %p key=%s "
|
||||||
existing ? existing->TTL() : 0));
|
"existing=%p validated=%d ttl=%d",
|
||||||
if (existing && !existing->Validated()) {
|
this, key.get(), existing.get(), existing ? existing->Validated() : 0,
|
||||||
existing = nullptr;
|
existing ? existing->TTL() : 0));
|
||||||
|
if (existing && existing->Validated()) {
|
||||||
|
return existing.forget();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existing && existing->IsHttp3() && !aHttp3Allowed) {
|
// Now look for HTTP2.
|
||||||
existing = nullptr;
|
if (aHttp2Allowed) {
|
||||||
|
nsAutoCString key;
|
||||||
|
AltSvcMapping::MakeHashKey(key, scheme, host, port, privateBrowsing, isolated,
|
||||||
|
topWindowOrigin, originAttributes, false);
|
||||||
|
RefPtr<AltSvcMapping> existing = LookupMapping(key, privateBrowsing);
|
||||||
|
LOG(
|
||||||
|
("AltSvcCache::GetAltServiceMapping %p key=%s "
|
||||||
|
"existing=%p validated=%d ttl=%d",
|
||||||
|
this, key.get(), existing.get(), existing ? existing->Validated() : 0,
|
||||||
|
existing ? existing->TTL() : 0));
|
||||||
|
if (existing && existing->Validated()) {
|
||||||
|
return existing.forget();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return existing.forget();
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProxyClearHostMapping : public Runnable {
|
class ProxyClearHostMapping : public Runnable {
|
||||||
@ -1213,11 +1233,18 @@ void AltSvcCache::ClearHostMapping(const nsACString& host, int32_t port,
|
|||||||
for (int isolate = 0; isolate < 2; ++isolate) {
|
for (int isolate = 0; isolate < 2; ++isolate) {
|
||||||
AltSvcMapping::MakeHashKey(key, scheme, host, port, bool(pb),
|
AltSvcMapping::MakeHashKey(key, scheme, host, port, bool(pb),
|
||||||
bool(isolate), topWindowOrigin,
|
bool(isolate), topWindowOrigin,
|
||||||
originAttributes);
|
originAttributes, false);
|
||||||
RefPtr<AltSvcMapping> existing = LookupMapping(key, bool(pb));
|
RefPtr<AltSvcMapping> existing = LookupMapping(key, bool(pb));
|
||||||
if (existing) {
|
if (existing) {
|
||||||
existing->SetExpired();
|
existing->SetExpired();
|
||||||
}
|
}
|
||||||
|
AltSvcMapping::MakeHashKey(key, scheme, host, port, bool(pb),
|
||||||
|
bool(isolate), topWindowOrigin,
|
||||||
|
originAttributes, true);
|
||||||
|
existing = LookupMapping(key, bool(pb));
|
||||||
|
if (existing) {
|
||||||
|
existing->SetExpired();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ class AltSvcMapping {
|
|||||||
const nsACString& originHost, int32_t originPort,
|
const nsACString& originHost, int32_t originPort,
|
||||||
bool privateBrowsing, bool isolated,
|
bool privateBrowsing, bool isolated,
|
||||||
const nsACString& topWindowOrigin,
|
const nsACString& topWindowOrigin,
|
||||||
const OriginAttributes& originAttributes);
|
const OriginAttributes& originAttributes, bool aIsHttp3);
|
||||||
|
|
||||||
bool IsHttp3() { return mIsHttp3; }
|
bool IsHttp3() { return mIsHttp3; }
|
||||||
const nsCString& NPNToken() const { return mNPNToken; }
|
const nsCString& NPNToken() const { return mNPNToken; }
|
||||||
@ -198,7 +198,8 @@ class AltSvcCache {
|
|||||||
already_AddRefed<AltSvcMapping> GetAltServiceMapping(
|
already_AddRefed<AltSvcMapping> GetAltServiceMapping(
|
||||||
const nsACString& scheme, const nsACString& host, int32_t port, bool pb,
|
const nsACString& scheme, const nsACString& host, int32_t port, bool pb,
|
||||||
bool isolated, const nsACString& topWindowOrigin,
|
bool isolated, const nsACString& topWindowOrigin,
|
||||||
const OriginAttributes& originAttributes, bool aHttp3Allowed);
|
const OriginAttributes& originAttributes, bool aHttp2Allowed,
|
||||||
|
bool aHttp3Allowed);
|
||||||
void ClearAltServiceMappings();
|
void ClearAltServiceMappings();
|
||||||
void ClearHostMapping(const nsACString& host, int32_t port,
|
void ClearHostMapping(const nsACString& host, int32_t port,
|
||||||
const OriginAttributes& originAttributes,
|
const OriginAttributes& originAttributes,
|
||||||
|
@ -3118,7 +3118,7 @@ nsresult Http2Session::WriteSegmentsAgain(nsAHttpSegmentWriter* writer,
|
|||||||
// Don't allow any more h2 connections to this host
|
// Don't allow any more h2 connections to this host
|
||||||
RefPtr<nsHttpConnectionInfo> ci = ConnectionInfo();
|
RefPtr<nsHttpConnectionInfo> ci = ConnectionInfo();
|
||||||
if (ci) {
|
if (ci) {
|
||||||
gHttpHandler->BlacklistSpdy(ci);
|
gHttpHandler->ExcludeHttp2(ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go through and re-start all of our transactions with h2 disabled.
|
// Go through and re-start all of our transactions with h2 disabled.
|
||||||
|
@ -241,8 +241,12 @@ nsresult HttpConnectionMgrParent::VerifyTraffic() {
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnectionMgrParent::BlacklistSpdy(const nsHttpConnectionInfo* ci) {
|
void HttpConnectionMgrParent::ExcludeHttp2(const nsHttpConnectionInfo* ci) {
|
||||||
MOZ_ASSERT_UNREACHABLE("BlacklistSpdy should not be called");
|
MOZ_ASSERT_UNREACHABLE("ExcludeHttp2 should not be called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpConnectionMgrParent::ExcludeHttp3(const nsHttpConnectionInfo* ci) {
|
||||||
|
MOZ_ASSERT_UNREACHABLE("ExcludeHttp3 should not be called");
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult HttpConnectionMgrParent::ClearConnectionHistory() {
|
nsresult HttpConnectionMgrParent::ClearConnectionHistory() {
|
||||||
|
@ -153,7 +153,8 @@ class HttpConnectionMgrShell : public nsISupports {
|
|||||||
// that connection.
|
// that connection.
|
||||||
[[nodiscard]] virtual nsresult VerifyTraffic() = 0;
|
[[nodiscard]] virtual nsresult VerifyTraffic() = 0;
|
||||||
|
|
||||||
virtual void BlacklistSpdy(const nsHttpConnectionInfo* ci) = 0;
|
virtual void ExcludeHttp2(const nsHttpConnectionInfo* ci) = 0;
|
||||||
|
virtual void ExcludeHttp3(const nsHttpConnectionInfo* ci) = 0;
|
||||||
|
|
||||||
// clears the connection history mCT
|
// clears the connection history mCT
|
||||||
[[nodiscard]] virtual nsresult ClearConnectionHistory() = 0;
|
[[nodiscard]] virtual nsresult ClearConnectionHistory() = 0;
|
||||||
@ -216,7 +217,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(HttpConnectionMgrShell,
|
|||||||
nsHttpConnectionInfo*, nsIInterfaceRequestor*, uint32_t caps = 0, \
|
nsHttpConnectionInfo*, nsIInterfaceRequestor*, uint32_t caps = 0, \
|
||||||
NullHttpTransaction* = nullptr) override; \
|
NullHttpTransaction* = nullptr) override; \
|
||||||
virtual nsresult VerifyTraffic() override; \
|
virtual nsresult VerifyTraffic() override; \
|
||||||
virtual void BlacklistSpdy(const nsHttpConnectionInfo* ci) override; \
|
virtual void ExcludeHttp2(const nsHttpConnectionInfo* ci) override; \
|
||||||
|
virtual void ExcludeHttp3(const nsHttpConnectionInfo* ci) override; \
|
||||||
virtual nsresult ClearConnectionHistory() override; \
|
virtual nsresult ClearConnectionHistory() override; \
|
||||||
virtual nsresult CompleteUpgrade(HttpTransactionShell* aTrans, \
|
virtual nsresult CompleteUpgrade(HttpTransactionShell* aTrans, \
|
||||||
nsIHttpUpgradeListener* aUpgradeListener) \
|
nsIHttpUpgradeListener* aUpgradeListener) \
|
||||||
|
@ -392,17 +392,21 @@ nsresult TRRServiceChannel::BeginConnect() {
|
|||||||
host, port, EmptyCString(), mUsername, GetTopWindowOrigin(), proxyInfo,
|
host, port, EmptyCString(), mUsername, GetTopWindowOrigin(), proxyInfo,
|
||||||
OriginAttributes(), isHttps);
|
OriginAttributes(), isHttps);
|
||||||
// TODO: Bug 1622778 for using AltService in socket process.
|
// TODO: Bug 1622778 for using AltService in socket process.
|
||||||
mAllowAltSvc = XRE_IsParentProcess() &&
|
mAllowAltSvc = XRE_IsParentProcess() && mAllowAltSvc;
|
||||||
(mAllowAltSvc && !gHttpHandler->IsSpdyBlacklisted(connInfo));
|
bool http2Allowed = !gHttpHandler->IsHttp2Excluded(connInfo);
|
||||||
|
bool http3Allowed = !mUpgradeProtocolCallback && !mProxyInfo &&
|
||||||
|
!(mCaps & NS_HTTP_BE_CONSERVATIVE) && !mBeConservative &&
|
||||||
|
!gHttpHandler->IsHttp3Excluded(connInfo);
|
||||||
|
|
||||||
RefPtr<AltSvcMapping> mapping;
|
RefPtr<AltSvcMapping> mapping;
|
||||||
if (!mConnectionInfo && mAllowAltSvc && // per channel
|
if (!mConnectionInfo && mAllowAltSvc && // per channel
|
||||||
|
(http2Allowed || http3Allowed) &&
|
||||||
!(mLoadFlags & LOAD_FRESH_CONNECTION) &&
|
!(mLoadFlags & LOAD_FRESH_CONNECTION) &&
|
||||||
AltSvcMapping::AcceptableProxy(proxyInfo) &&
|
AltSvcMapping::AcceptableProxy(proxyInfo) &&
|
||||||
(scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) &&
|
(scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) &&
|
||||||
(mapping = gHttpHandler->GetAltServiceMapping(
|
(mapping = gHttpHandler->GetAltServiceMapping(
|
||||||
scheme, host, port, mPrivateBrowsing, IsIsolated(),
|
scheme, host, port, mPrivateBrowsing, IsIsolated(),
|
||||||
GetTopWindowOrigin(), OriginAttributes(), false))) {
|
GetTopWindowOrigin(), OriginAttributes(), http2Allowed, http3Allowed))) {
|
||||||
LOG(("TRRServiceChannel %p Alt Service Mapping Found %s://%s:%d [%s]\n",
|
LOG(("TRRServiceChannel %p Alt Service Mapping Found %s://%s:%d [%s]\n",
|
||||||
this, scheme.get(), mapping->AlternateHost().get(),
|
this, scheme.get(), mapping->AlternateHost().get(),
|
||||||
mapping->AlternatePort(), mapping->HashKey().get()));
|
mapping->AlternatePort(), mapping->HashKey().get()));
|
||||||
@ -438,7 +442,7 @@ nsresult TRRServiceChannel::BeginConnect() {
|
|||||||
|
|
||||||
// Need to re-ask the handler, since mConnectionInfo may not be the connInfo
|
// Need to re-ask the handler, since mConnectionInfo may not be the connInfo
|
||||||
// we used earlier
|
// we used earlier
|
||||||
if (gHttpHandler->IsSpdyBlacklisted(mConnectionInfo)) {
|
if (gHttpHandler->IsHttp2Excluded(mConnectionInfo)) {
|
||||||
mAllowSpdy = 0;
|
mAllowSpdy = 0;
|
||||||
mCaps |= NS_HTTP_DISALLOW_SPDY;
|
mCaps |= NS_HTTP_DISALLOW_SPDY;
|
||||||
mConnectionInfo->SetNoSpdy(true);
|
mConnectionInfo->SetNoSpdy(true);
|
||||||
|
@ -6895,9 +6895,10 @@ nsresult nsHttpChannel::BeginConnect() {
|
|||||||
RefPtr<nsHttpConnectionInfo> connInfo = new nsHttpConnectionInfo(
|
RefPtr<nsHttpConnectionInfo> connInfo = new nsHttpConnectionInfo(
|
||||||
host, port, EmptyCString(), mUsername, GetTopWindowOrigin(), proxyInfo,
|
host, port, EmptyCString(), mUsername, GetTopWindowOrigin(), proxyInfo,
|
||||||
originAttributes, isHttps);
|
originAttributes, isHttps);
|
||||||
mAllowAltSvc = (mAllowAltSvc && !gHttpHandler->IsSpdyBlacklisted(connInfo));
|
bool http2Allowed = !gHttpHandler->IsHttp2Excluded(connInfo);
|
||||||
bool http3Allowed = !mUpgradeProtocolCallback && !mProxyInfo &&
|
bool http3Allowed = !mUpgradeProtocolCallback && !mProxyInfo &&
|
||||||
!(mCaps & NS_HTTP_BE_CONSERVATIVE) && !mBeConservative;
|
!(mCaps & NS_HTTP_BE_CONSERVATIVE) && !mBeConservative &&
|
||||||
|
!gHttpHandler->IsHttp3Excluded(connInfo);
|
||||||
|
|
||||||
// No need to lookup HTTPSSVC record if we already have one.
|
// No need to lookup HTTPSSVC record if we already have one.
|
||||||
mUseHTTPSSVC =
|
mUseHTTPSSVC =
|
||||||
@ -6905,12 +6906,13 @@ nsresult nsHttpChannel::BeginConnect() {
|
|||||||
|
|
||||||
RefPtr<AltSvcMapping> mapping;
|
RefPtr<AltSvcMapping> mapping;
|
||||||
if (!mConnectionInfo && mAllowAltSvc && // per channel
|
if (!mConnectionInfo && mAllowAltSvc && // per channel
|
||||||
|
(http2Allowed || http3Allowed) &&
|
||||||
!(mLoadFlags & LOAD_FRESH_CONNECTION) &&
|
!(mLoadFlags & LOAD_FRESH_CONNECTION) &&
|
||||||
AltSvcMapping::AcceptableProxy(proxyInfo) &&
|
AltSvcMapping::AcceptableProxy(proxyInfo) &&
|
||||||
(scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) &&
|
(scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) &&
|
||||||
(mapping = gHttpHandler->GetAltServiceMapping(
|
(mapping = gHttpHandler->GetAltServiceMapping(
|
||||||
scheme, host, port, mPrivateBrowsing, IsIsolated(),
|
scheme, host, port, mPrivateBrowsing, IsIsolated(),
|
||||||
GetTopWindowOrigin(), originAttributes, http3Allowed))) {
|
GetTopWindowOrigin(), originAttributes, http2Allowed, http3Allowed))) {
|
||||||
LOG(("nsHttpChannel %p Alt Service Mapping Found %s://%s:%d [%s]\n", this,
|
LOG(("nsHttpChannel %p Alt Service Mapping Found %s://%s:%d [%s]\n", this,
|
||||||
scheme.get(), mapping->AlternateHost().get(), mapping->AlternatePort(),
|
scheme.get(), mapping->AlternateHost().get(), mapping->AlternatePort(),
|
||||||
mapping->HashKey().get()));
|
mapping->HashKey().get()));
|
||||||
@ -6966,7 +6968,7 @@ nsresult nsHttpChannel::BeginConnect() {
|
|||||||
|
|
||||||
// Need to re-ask the handler, since mConnectionInfo may not be the connInfo
|
// Need to re-ask the handler, since mConnectionInfo may not be the connInfo
|
||||||
// we used earlier
|
// we used earlier
|
||||||
if (gHttpHandler->IsSpdyBlacklisted(mConnectionInfo)) {
|
if (gHttpHandler->IsHttp2Excluded(mConnectionInfo)) {
|
||||||
mAllowSpdy = 0;
|
mAllowSpdy = 0;
|
||||||
mCaps |= NS_HTTP_DISALLOW_SPDY;
|
mCaps |= NS_HTTP_DISALLOW_SPDY;
|
||||||
mConnectionInfo->SetNoSpdy(true);
|
mConnectionInfo->SetNoSpdy(true);
|
||||||
|
@ -2060,7 +2060,7 @@ nsresult nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction* trans) {
|
|||||||
trans->SetConnection(nullptr);
|
trans->SetConnection(nullptr);
|
||||||
rv = DispatchTransaction(ent, trans, conn);
|
rv = DispatchTransaction(ent, trans, conn);
|
||||||
} else {
|
} else {
|
||||||
if (!ent->AllowSpdy()) {
|
if (!ent->AllowHttp2()) {
|
||||||
trans->DisableSpdy();
|
trans->DisableSpdy();
|
||||||
}
|
}
|
||||||
pendingTransInfo = new PendingTransactionInfo(trans);
|
pendingTransInfo = new PendingTransactionInfo(trans);
|
||||||
@ -5263,7 +5263,7 @@ nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus(nsITransport* trans,
|
|||||||
|
|
||||||
if (status == NS_NET_STATUS_CONNECTING_TO && gHttpHandler->IsSpdyEnabled() &&
|
if (status == NS_NET_STATUS_CONNECTING_TO && gHttpHandler->IsSpdyEnabled() &&
|
||||||
gHttpHandler->CoalesceSpdy() && mEnt && mEnt->mConnInfo &&
|
gHttpHandler->CoalesceSpdy() && mEnt && mEnt->mConnInfo &&
|
||||||
mEnt->mConnInfo->EndToEndSSL() && mEnt->AllowSpdy() &&
|
mEnt->mConnInfo->EndToEndSSL() && mEnt->AllowHttp2() &&
|
||||||
!mEnt->mConnInfo->UsingProxy() && mEnt->mCoalescingKeys.IsEmpty()) {
|
!mEnt->mConnInfo->UsingProxy() && mEnt->mCoalescingKeys.IsEmpty()) {
|
||||||
nsCOMPtr<nsIDNSAddrRecord> dnsRecord(do_GetInterface(mSocketTransport));
|
nsCOMPtr<nsIDNSAddrRecord> dnsRecord(do_GetInterface(mSocketTransport));
|
||||||
nsTArray<NetAddr> addressSet;
|
nsTArray<NetAddr> addressSet;
|
||||||
@ -5544,19 +5544,31 @@ void nsHttpConnectionMgr::nsConnectionEntry::RemoveHalfOpen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsHttpConnectionMgr::BlacklistSpdy(const nsHttpConnectionInfo* ci) {
|
void nsHttpConnectionMgr::ExcludeHttp2(const nsHttpConnectionInfo* ci) {
|
||||||
LOG(("nsHttpConnectionMgr::BlacklistSpdy blacklisting ci %s",
|
LOG(("nsHttpConnectionMgr::ExcludeHttp2 excluding ci %s",
|
||||||
ci->HashKey().BeginReading()));
|
ci->HashKey().BeginReading()));
|
||||||
nsConnectionEntry* ent = mCT.GetWeak(ci->HashKey());
|
nsConnectionEntry* ent = mCT.GetWeak(ci->HashKey());
|
||||||
if (!ent) {
|
if (!ent) {
|
||||||
LOG(("nsHttpConnectionMgr::BlacklistSpdy no entry found?!"));
|
LOG(("nsHttpConnectionMgr::ExcludeHttp2 no entry found?!"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ent->DisallowSpdy();
|
ent->DisallowHttp2();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsHttpConnectionMgr::nsConnectionEntry::DisallowSpdy() {
|
void nsHttpConnectionMgr::ExcludeHttp3(const nsHttpConnectionInfo* ci) {
|
||||||
|
LOG(("nsHttpConnectionMgr::ExcludeHttp3 exclude ci %s",
|
||||||
|
ci->HashKey().BeginReading()));
|
||||||
|
nsConnectionEntry* ent = mCT.GetWeak(ci->HashKey());
|
||||||
|
if (!ent) {
|
||||||
|
LOG(("nsHttpConnectionMgr::ExcludeHttp3 no entry found?!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ent->DontReuseHttp3Conn();
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsHttpConnectionMgr::nsConnectionEntry::DisallowHttp2() {
|
||||||
mCanUseSpdy = false;
|
mCanUseSpdy = false;
|
||||||
|
|
||||||
// If we have any spdy connections, we want to go ahead and close them when
|
// If we have any spdy connections, we want to go ahead and close them when
|
||||||
@ -5576,6 +5588,19 @@ void nsHttpConnectionMgr::nsConnectionEntry::DisallowSpdy() {
|
|||||||
mCoalescingKeys.Clear();
|
mCoalescingKeys.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nsHttpConnectionMgr::nsConnectionEntry::DontReuseHttp3Conn() {
|
||||||
|
MOZ_ASSERT(mConnInfo->IsHttp3());
|
||||||
|
|
||||||
|
// If we have any spdy connections, we want to go ahead and close them when
|
||||||
|
// they're done so we can free up some connections.
|
||||||
|
for (uint32_t i = 0; i < mActiveConns.Length(); ++i) {
|
||||||
|
mActiveConns[i]->DontReuse();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't coalesce if we're not using http3
|
||||||
|
mCoalescingKeys.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
void nsHttpConnectionMgr::nsConnectionEntry::RecordIPFamilyPreference(
|
void nsHttpConnectionMgr::nsConnectionEntry::RecordIPFamilyPreference(
|
||||||
uint16_t family) {
|
uint16_t family) {
|
||||||
LOG(("nsConnectionEntry::RecordIPFamilyPreference %p, af=%u", this, family));
|
LOG(("nsConnectionEntry::RecordIPFamilyPreference %p, af=%u", this, family));
|
||||||
|
@ -235,8 +235,9 @@ class nsHttpConnectionMgr final : public HttpConnectionMgrShell,
|
|||||||
|
|
||||||
bool mDoNotDestroy : 1;
|
bool mDoNotDestroy : 1;
|
||||||
|
|
||||||
bool AllowSpdy() const { return mCanUseSpdy; }
|
bool AllowHttp2() const { return mCanUseSpdy; }
|
||||||
void DisallowSpdy();
|
void DisallowHttp2();
|
||||||
|
void DontReuseHttp3Conn();
|
||||||
|
|
||||||
// Set the IP family preference flags according the connected family
|
// Set the IP family preference flags according the connected family
|
||||||
void RecordIPFamilyPreference(uint16_t family);
|
void RecordIPFamilyPreference(uint16_t family);
|
||||||
|
@ -316,7 +316,7 @@ nsHttpHandler::nsHttpHandler()
|
|||||||
mNextChannelId(1),
|
mNextChannelId(1),
|
||||||
mLastActiveTabLoadOptimizationLock(
|
mLastActiveTabLoadOptimizationLock(
|
||||||
"nsHttpConnectionMgr::LastActiveTabLoadOptimization"),
|
"nsHttpConnectionMgr::LastActiveTabLoadOptimization"),
|
||||||
mSpdyBlacklistLock("nsHttpHandler::SpdyBlacklist"),
|
mHttpExclusionLock("nsHttpHandler::HttpExclusion"),
|
||||||
mThroughCaptivePortal(false) {
|
mThroughCaptivePortal(false) {
|
||||||
LOG(("Creating nsHttpHandler [this=%p].\n", this));
|
LOG(("Creating nsHttpHandler [this=%p].\n", this));
|
||||||
|
|
||||||
@ -2796,19 +2796,34 @@ bool nsHttpHandler::IsBeforeLastActiveTabLoadOptimization(
|
|||||||
when <= mLastActiveTabLoadOptimizationHit;
|
when <= mLastActiveTabLoadOptimizationHit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsHttpHandler::BlacklistSpdy(const nsHttpConnectionInfo* ci) {
|
void nsHttpHandler::ExcludeHttp2(const nsHttpConnectionInfo* ci) {
|
||||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||||
|
|
||||||
mConnMgr->BlacklistSpdy(ci);
|
mConnMgr->ExcludeHttp2(ci);
|
||||||
if (!mBlacklistedSpdyOrigins.Contains(ci->GetOrigin())) {
|
if (!mExcludedHttp2Origins.Contains(ci->GetOrigin())) {
|
||||||
MutexAutoLock lock(mSpdyBlacklistLock);
|
MutexAutoLock lock(mHttpExclusionLock);
|
||||||
mBlacklistedSpdyOrigins.PutEntry(ci->GetOrigin());
|
mExcludedHttp2Origins.PutEntry(ci->GetOrigin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsHttpHandler::IsSpdyBlacklisted(const nsHttpConnectionInfo* ci) {
|
bool nsHttpHandler::IsHttp2Excluded(const nsHttpConnectionInfo* ci) {
|
||||||
MutexAutoLock lock(mSpdyBlacklistLock);
|
MutexAutoLock lock(mHttpExclusionLock);
|
||||||
return mBlacklistedSpdyOrigins.Contains(ci->GetOrigin());
|
return mExcludedHttp2Origins.Contains(ci->GetOrigin());
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsHttpHandler::ExcludeHttp3(const nsHttpConnectionInfo* ci) {
|
||||||
|
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||||
|
|
||||||
|
mConnMgr->ExcludeHttp3(ci);
|
||||||
|
if (!mExcludedHttp3Origins.Contains(ci->GetOrigin())) {
|
||||||
|
MutexAutoLock lock(mHttpExclusionLock);
|
||||||
|
mExcludedHttp3Origins.PutEntry(ci->GetOrigin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nsHttpHandler::IsHttp3Excluded(const nsHttpConnectionInfo* ci) {
|
||||||
|
MutexAutoLock lock(mHttpExclusionLock);
|
||||||
|
return mExcludedHttp3Origins.Contains(ci->GetOrigin());
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpTrafficAnalyzer* nsHttpHandler::GetHttpTrafficAnalyzer() {
|
HttpTrafficAnalyzer* nsHttpHandler::GetHttpTrafficAnalyzer() {
|
||||||
|
@ -359,10 +359,11 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
|
|||||||
already_AddRefed<AltSvcMapping> GetAltServiceMapping(
|
already_AddRefed<AltSvcMapping> GetAltServiceMapping(
|
||||||
const nsACString& scheme, const nsACString& host, int32_t port, bool pb,
|
const nsACString& scheme, const nsACString& host, int32_t port, bool pb,
|
||||||
bool isolated, const nsACString& topWindowOrigin,
|
bool isolated, const nsACString& topWindowOrigin,
|
||||||
const OriginAttributes& originAttributes, bool aHttp3Allowed) {
|
const OriginAttributes& originAttributes, bool aHttp2Allowed,
|
||||||
|
bool aHttp3Allowed) {
|
||||||
return mAltSvcCache->GetAltServiceMapping(scheme, host, port, pb, isolated,
|
return mAltSvcCache->GetAltServiceMapping(scheme, host, port, pb, isolated,
|
||||||
topWindowOrigin, originAttributes,
|
topWindowOrigin, originAttributes,
|
||||||
aHttp3Allowed);
|
aHttp2Allowed, aHttp3Allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -833,7 +834,7 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
|
|||||||
Mutex mLastActiveTabLoadOptimizationLock;
|
Mutex mLastActiveTabLoadOptimizationLock;
|
||||||
TimeStamp mLastActiveTabLoadOptimizationHit;
|
TimeStamp mLastActiveTabLoadOptimizationHit;
|
||||||
|
|
||||||
Mutex mSpdyBlacklistLock;
|
Mutex mHttpExclusionLock;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] nsresult NewChannelId(uint64_t& channelId);
|
[[nodiscard]] nsresult NewChannelId(uint64_t& channelId);
|
||||||
@ -841,11 +842,14 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
|
|||||||
void RemoveHttpChannel(uint64_t aId);
|
void RemoveHttpChannel(uint64_t aId);
|
||||||
nsWeakPtr GetWeakHttpChannel(uint64_t aId);
|
nsWeakPtr GetWeakHttpChannel(uint64_t aId);
|
||||||
|
|
||||||
void BlacklistSpdy(const nsHttpConnectionInfo* ci);
|
void ExcludeHttp2(const nsHttpConnectionInfo* ci);
|
||||||
[[nodiscard]] bool IsSpdyBlacklisted(const nsHttpConnectionInfo* ci);
|
[[nodiscard]] bool IsHttp2Excluded(const nsHttpConnectionInfo* ci);
|
||||||
|
void ExcludeHttp3(const nsHttpConnectionInfo* ci);
|
||||||
|
[[nodiscard]] bool IsHttp3Excluded(const nsHttpConnectionInfo* ci);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsTHashtable<nsCStringHashKey> mBlacklistedSpdyOrigins;
|
nsTHashtable<nsCStringHashKey> mExcludedHttp2Origins;
|
||||||
|
nsTHashtable<nsCStringHashKey> mExcludedHttp3Origins;
|
||||||
|
|
||||||
bool mThroughCaptivePortal;
|
bool mThroughCaptivePortal;
|
||||||
|
|
||||||
|
125
netwerk/test/unit/test_http3_alt_svc.js
Normal file
125
netwerk/test/unit/test_http3_alt_svc.js
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
let httpsOrigin;
|
||||||
|
let h3AltSvc;
|
||||||
|
let h3Port;
|
||||||
|
let h3Route;
|
||||||
|
let prefs;
|
||||||
|
|
||||||
|
let tests = [test_https_alt_svc, testsDone];
|
||||||
|
|
||||||
|
let current_test = 0;
|
||||||
|
|
||||||
|
function run_next_test() {
|
||||||
|
if (current_test < tests.length) {
|
||||||
|
dump("starting test number " + current_test + "\n");
|
||||||
|
tests[current_test]();
|
||||||
|
current_test++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
let env = Cc["@mozilla.org/process/environment;1"].getService(
|
||||||
|
Ci.nsIEnvironment
|
||||||
|
);
|
||||||
|
let h2Port = env.get("MOZHTTP2_PORT");
|
||||||
|
Assert.notEqual(h2Port, null);
|
||||||
|
Assert.notEqual(h2Port, "");
|
||||||
|
let h3Port = env.get("MOZHTTP3_PORT");
|
||||||
|
Assert.notEqual(h3Port, null);
|
||||||
|
Assert.notEqual(h3Port, "");
|
||||||
|
h3AltSvc = ":" + h3Port;
|
||||||
|
|
||||||
|
h3Route = "foo.example.com:" + h3Port;
|
||||||
|
do_get_profile();
|
||||||
|
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||||
|
|
||||||
|
prefs.setBoolPref("network.http.http3.enabled", true);
|
||||||
|
prefs.setCharPref("network.dns.localDomains", "foo.example.com");
|
||||||
|
|
||||||
|
// The certificate for the http3server server is for foo.example.com and
|
||||||
|
// is signed by http2-ca.pem so add that cert to the trust list as a
|
||||||
|
// signing cert.
|
||||||
|
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
|
||||||
|
Ci.nsIX509CertDB
|
||||||
|
);
|
||||||
|
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
|
||||||
|
httpsOrigin = "https://foo.example.com:" + h2Port + "/";
|
||||||
|
|
||||||
|
run_next_test();
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeChan(uri) {
|
||||||
|
let chan = NetUtil.newChannel({
|
||||||
|
uri,
|
||||||
|
loadUsingSystemPrincipal: true,
|
||||||
|
}).QueryInterface(Ci.nsIHttpChannel);
|
||||||
|
chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
|
||||||
|
return chan;
|
||||||
|
}
|
||||||
|
|
||||||
|
let WaitForHttp3Listener = function() {};
|
||||||
|
|
||||||
|
WaitForHttp3Listener.prototype = {
|
||||||
|
onDataAvailableFired: false,
|
||||||
|
expectedRoute: "",
|
||||||
|
|
||||||
|
onStartRequest: function testOnStartRequest(request) {
|
||||||
|
Assert.ok(request instanceof Ci.nsIHttpChannel);
|
||||||
|
Assert.equal(request.responseStatus, 200);
|
||||||
|
},
|
||||||
|
|
||||||
|
onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) {
|
||||||
|
this.onDataAvailableFired = true;
|
||||||
|
read_stream(stream, cnt);
|
||||||
|
},
|
||||||
|
|
||||||
|
onStopRequest: function testOnStopRequest(request, status) {
|
||||||
|
let routed = "NA";
|
||||||
|
try {
|
||||||
|
routed = request.getRequestHeader("Alt-Used");
|
||||||
|
} catch (e) {}
|
||||||
|
dump("routed is " + routed + "\n");
|
||||||
|
|
||||||
|
if (routed == this.expectedRoute) {
|
||||||
|
let httpVersion = "";
|
||||||
|
try {
|
||||||
|
httpVersion = request.protocolVersion;
|
||||||
|
} catch (e) {}
|
||||||
|
Assert.equal(httpVersion, "h3");
|
||||||
|
run_next_test();
|
||||||
|
} else {
|
||||||
|
dump("poll later for alt svc mapping\n");
|
||||||
|
do_test_pending();
|
||||||
|
do_timeout(500, () => {
|
||||||
|
doTest(this.uri, this.expectedRoute, this.h3AltSvc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
do_test_finished();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function doTest(uri, expectedRoute, altSvc) {
|
||||||
|
let chan = makeChan(uri);
|
||||||
|
let listener = new WaitForHttp3Listener();
|
||||||
|
listener.uri = uri;
|
||||||
|
listener.expectedRoute = expectedRoute;
|
||||||
|
listener.h3AltSvc = altSvc;
|
||||||
|
chan.setRequestHeader("x-altsvc", altSvc, false);
|
||||||
|
chan.asyncOpen(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Alt-Svc for http3.
|
||||||
|
// H2 server returns alt-svc=h2=foo2.example.com:8000,h3-27=:h3port,h3-29=foo2.example.com:8443
|
||||||
|
function test_https_alt_svc() {
|
||||||
|
dump("test_https_alt_svc()\n");
|
||||||
|
do_test_pending();
|
||||||
|
doTest(httpsOrigin + "http3-test2", h3Route, h3AltSvc);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testsDone() {
|
||||||
|
prefs.clearUserPref("network.http.http3.enabled");
|
||||||
|
prefs.clearUserPref("network.dns.localDomains");
|
||||||
|
dump("testDone\n");
|
||||||
|
}
|
@ -447,5 +447,7 @@ skip-if = os == "android"
|
|||||||
[test_blob_channelname.js]
|
[test_blob_channelname.js]
|
||||||
[test_altsvc_pref.js]
|
[test_altsvc_pref.js]
|
||||||
skip-if = asan || tsan || os == 'win' || os =='android'
|
skip-if = asan || tsan || os == 'win' || os =='android'
|
||||||
|
[test_http3_alt_svc.js]
|
||||||
|
skip-if = asan || tsan || os == 'win' || os =='android'
|
||||||
[test_use_httpssvc.js]
|
[test_use_httpssvc.js]
|
||||||
skip-if = os == "android"
|
skip-if = os == "android"
|
||||||
|
@ -553,6 +553,16 @@ function handleRequest(req, res) {
|
|||||||
res.setHeader("Cache-Control", "no-cache");
|
res.setHeader("Cache-Control", "no-cache");
|
||||||
res.setHeader("Alt-Svc", "h3-27=" + req.headers["x-altsvc"]);
|
res.setHeader("Alt-Svc", "h3-27=" + req.headers["x-altsvc"]);
|
||||||
}
|
}
|
||||||
|
// for use with test_http3.js
|
||||||
|
else if (u.pathname === "/http3-test2") {
|
||||||
|
res.setHeader("Cache-Control", "no-cache");
|
||||||
|
res.setHeader(
|
||||||
|
"Alt-Svc",
|
||||||
|
"h2=foo2.example.com:8000,h3-27=" +
|
||||||
|
req.headers["x-altsvc"] +
|
||||||
|
",h3-29=foo2.example.com:8443"
|
||||||
|
);
|
||||||
|
}
|
||||||
// for use with test_trr.js
|
// for use with test_trr.js
|
||||||
else if (u.pathname === "/dns-cname") {
|
else if (u.pathname === "/dns-cname") {
|
||||||
// asking for cname.example.com
|
// asking for cname.example.com
|
||||||
|
@ -4,7 +4,7 @@ function altSvcCacheKeyIsolated(parsed) {
|
|||||||
|
|
||||||
function altSvcPartitionKey(key) {
|
function altSvcPartitionKey(key) {
|
||||||
let parts = key.split(":");
|
let parts = key.split(":");
|
||||||
return parts[parts.length - 1];
|
return parts[parts.length - 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
const gHttpHandler = Cc["@mozilla.org/network/protocol;1?name=http"].getService(
|
const gHttpHandler = Cc["@mozilla.org/network/protocol;1?name=http"].getService(
|
||||||
@ -91,7 +91,7 @@ add_task(async function() {
|
|||||||
await p;
|
await p;
|
||||||
});
|
});
|
||||||
|
|
||||||
checkAltSvcCache([partitionKey2, partitionKey1]);
|
checkAltSvcCache([partitionKey1, partitionKey2]);
|
||||||
|
|
||||||
info("Removing the tabs");
|
info("Removing the tabs");
|
||||||
BrowserTestUtils.removeTab(tab);
|
BrowserTestUtils.removeTab(tab);
|
||||||
|
Loading…
Reference in New Issue
Block a user