Bug 1943011 - If 'no-default-alpn' is not found, add 'http/1.1' to the list of records, a=RyanVM

Original Revision: https://phabricator.services.mozilla.com/D235170

Differential Revision: https://phabricator.services.mozilla.com/D235356
This commit is contained in:
Kershaw Chang 2025-01-24 15:42:46 +00:00
parent 4aa75fd5e3
commit b686ede718
4 changed files with 98 additions and 39 deletions

View file

@ -214,13 +214,25 @@ class AlpnComparator {
nsTArray<std::tuple<nsCString, SupportedAlpnRank>> SVCB::GetAllAlpn() const { nsTArray<std::tuple<nsCString, SupportedAlpnRank>> SVCB::GetAllAlpn() const {
nsTArray<std::tuple<nsCString, SupportedAlpnRank>> alpnList; nsTArray<std::tuple<nsCString, SupportedAlpnRank>> alpnList;
bool shouldAddDefaultAlpn = true;
for (const auto& value : mSvcFieldValue) { for (const auto& value : mSvcFieldValue) {
if (value.mValue.is<SvcParamAlpn>()) { if (value.mValue.is<SvcParamAlpn>()) {
for (const auto& alpn : value.mValue.as<SvcParamAlpn>().mValue) { for (const auto& alpn : value.mValue.as<SvcParamAlpn>().mValue) {
alpnList.AppendElement(std::make_tuple(alpn, IsAlpnSupported(alpn))); auto tuple = std::make_tuple(alpn, IsAlpnSupported(alpn));
alpnList.AppendElement(tuple);
if (std::get<1>(tuple) == SupportedAlpnRank::HTTP_1_1) {
shouldAddDefaultAlpn = false;
}
} }
} else if (value.mValue.is<SvcParamKeyNoDefaultAlpn>()) {
// Found "no-default-alpn", so don't bother to add it.
shouldAddDefaultAlpn = false;
} }
} }
if (shouldAddDefaultAlpn) {
alpnList.AppendElement(
std::make_tuple("http/1.1"_ns, SupportedAlpnRank::HTTP_1_1));
}
alpnList.Sort(AlpnComparator()); alpnList.Sort(AlpnComparator());
return alpnList; return alpnList;
} }
@ -330,8 +342,10 @@ static bool CheckAlpnIsUsable(SupportedAlpnRank aAlpnType, bool aNoHttp2,
return true; return true;
} }
static nsTArray<SVCBWrapper> FlattenRecords(const nsTArray<SVCB>& aRecords) { static nsTArray<SVCBWrapper> FlattenRecords(const nsTArray<SVCB>& aRecords,
uint32_t& aH3RecordCount) {
nsTArray<SVCBWrapper> result; nsTArray<SVCBWrapper> result;
aH3RecordCount = 0;
for (const auto& record : aRecords) { for (const auto& record : aRecords) {
nsTArray<std::tuple<nsCString, SupportedAlpnRank>> alpnList = nsTArray<std::tuple<nsCString, SupportedAlpnRank>> alpnList =
record.GetAllAlpn(); record.GetAllAlpn();
@ -341,6 +355,9 @@ static nsTArray<SVCBWrapper> FlattenRecords(const nsTArray<SVCB>& aRecords) {
for (const auto& alpn : alpnList) { for (const auto& alpn : alpnList) {
SVCBWrapper wrapper(record); SVCBWrapper wrapper(record);
wrapper.mAlpn = Some(alpn); wrapper.mAlpn = Some(alpn);
if (IsHttp3(std::get<1>(alpn))) {
aH3RecordCount++;
}
result.AppendElement(wrapper); result.AppendElement(wrapper);
} }
} }
@ -359,8 +376,8 @@ DNSHTTPSSVCRecordBase::GetServiceModeRecordInternal(
aRecordsAllExcluded = false; aRecordsAllExcluded = false;
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID); nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
uint32_t h3ExcludedCount = 0; uint32_t h3ExcludedCount = 0;
uint32_t h3RecordCount = 0;
nsTArray<SVCBWrapper> records = FlattenRecords(aRecords); nsTArray<SVCBWrapper> records = FlattenRecords(aRecords, h3RecordCount);
for (const auto& record : records) { for (const auto& record : records) {
if (record.mRecord.mSvcFieldPriority == 0) { if (record.mRecord.mSvcFieldPriority == 0) {
// In ServiceMode, the SvcPriority should never be 0. // In ServiceMode, the SvcPriority should never be 0.
@ -421,7 +438,7 @@ DNSHTTPSSVCRecordBase::GetServiceModeRecordInternal(
// If all records are in http3 excluded list, try again without checking the // If all records are in http3 excluded list, try again without checking the
// excluded list. This is better than returning nothing. // excluded list. This is better than returning nothing.
if (h3ExcludedCount == records.Length() && aCheckHttp3ExcludedList) { if (h3ExcludedCount == h3RecordCount && aCheckHttp3ExcludedList) {
return GetServiceModeRecordInternal(aNoHttp2, aNoHttp3, aRecords, return GetServiceModeRecordInternal(aNoHttp2, aNoHttp3, aRecords,
aRecordsAllExcluded, false); aRecordsAllExcluded, false);
} }
@ -454,7 +471,8 @@ void DNSHTTPSSVCRecordBase::GetAllRecordsWithEchConfigInternal(
} }
uint32_t h3ExcludedCount = 0; uint32_t h3ExcludedCount = 0;
nsTArray<SVCBWrapper> records = FlattenRecords(aRecords); uint32_t h3RecordCount = 0;
nsTArray<SVCBWrapper> records = FlattenRecords(aRecords, h3RecordCount);
for (const auto& record : records) { for (const auto& record : records) {
if (record.mRecord.mSvcFieldPriority == 0) { if (record.mRecord.mSvcFieldPriority == 0) {
// This should not happen, since GetAllRecordsWithEchConfigInternal() // This should not happen, since GetAllRecordsWithEchConfigInternal()
@ -493,7 +511,7 @@ void DNSHTTPSSVCRecordBase::GetAllRecordsWithEchConfigInternal(
// If all records are in http3 excluded list, try again without checking the // If all records are in http3 excluded list, try again without checking the
// excluded list. This is better than returning nothing. // excluded list. This is better than returning nothing.
if (h3ExcludedCount == records.Length() && aCheckHttp3ExcludedList) { if (h3ExcludedCount == h3RecordCount && aCheckHttp3ExcludedList) {
GetAllRecordsWithEchConfigInternal( GetAllRecordsWithEchConfigInternal(
aNoHttp2, aNoHttp3, aRecords, aAllRecordsHaveEchConfig, aNoHttp2, aNoHttp3, aRecords, aAllRecordsHaveEchConfig,
aAllRecordsInH3ExcludedList, aResult, false); aAllRecordsInH3ExcludedList, aResult, false);

View file

@ -211,6 +211,7 @@ add_task(async function testFastfallback() {
name: "test.fastfallback1.com", name: "test.fastfallback1.com",
values: [ values: [
{ key: "alpn", value: "h3-29" }, { key: "alpn", value: "h3-29" },
{ key: "no-default-alpn" },
{ key: "port", value: h3Port }, { key: "port", value: h3Port },
{ key: "echconfig", value: "456..." }, { key: "echconfig", value: "456..." },
], ],
@ -300,6 +301,7 @@ add_task(async function testFastfallback1() {
name: "test.fastfallback1.org", name: "test.fastfallback1.org",
values: [ values: [
{ key: "alpn", value: "h3-29" }, { key: "alpn", value: "h3-29" },
{ key: "no-default-alpn" },
{ key: "port", value: h3Port }, { key: "port", value: h3Port },
{ key: "echconfig", value: "456..." }, { key: "echconfig", value: "456..." },
], ],

View file

@ -74,7 +74,10 @@ add_task(async function testEchConfigEnabled() {
data: { data: {
priority: 1, priority: 1,
name: "test.bar_1.com", name: "test.bar_1.com",
values: [{ key: "alpn", value: ["h3-29"] }], values: [
{ key: "alpn", value: ["h3-29"] },
{ key: "no-default-alpn" },
],
}, },
}, },
{ {
@ -113,7 +116,11 @@ add_task(async function testEchConfigEnabled() {
expectedName: "test.bar_1.com", expectedName: "test.bar_1.com",
expectedAlpn: "h3-29", expectedAlpn: "h3-29",
}); });
checkResult(inRecord, true, true); checkResult(inRecord, true, true, {
expectedPriority: 2,
expectedName: "test.bar_2.com",
expectedAlpn: "http/1.1",
});
Services.prefs.setBoolPref("network.dns.echconfig.enabled", true); Services.prefs.setBoolPref("network.dns.echconfig.enabled", true);
Services.dns.clearCache(true); Services.dns.clearCache(true);
@ -133,11 +140,15 @@ add_task(async function testEchConfigEnabled() {
expectedAlpn: "h2", expectedAlpn: "h2",
}); });
checkResult(inRecord, true, false, { checkResult(inRecord, true, false, {
expectedPriority: 1, expectedPriority: 2,
expectedName: "test.bar_1.com", expectedName: "test.bar_2.com",
expectedAlpn: "h3-29", expectedAlpn: "http/1.1",
});
checkResult(inRecord, true, true, {
expectedPriority: 2,
expectedName: "test.bar_2.com",
expectedAlpn: "http/1.1",
}); });
checkResult(inRecord, true, true);
await trrServer.stop(); await trrServer.stop();
trrServer = null; trrServer = null;
@ -175,6 +186,7 @@ add_task(async function testTwoRecordsHaveEchConfig() {
name: "test.foo_h3.com", name: "test.foo_h3.com",
values: [ values: [
{ key: "alpn", value: ["h3"] }, { key: "alpn", value: ["h3"] },
{ key: "no-default-alpn" },
{ key: "echconfig", value: "456..." }, { key: "echconfig", value: "456..." },
], ],
}, },
@ -211,11 +223,15 @@ add_task(async function testTwoRecordsHaveEchConfig() {
expectedAlpn: "h2", expectedAlpn: "h2",
}); });
checkResult(inRecord, true, false, { checkResult(inRecord, true, false, {
expectedPriority: 1, expectedPriority: 2,
expectedName: "test.foo_h3.com", expectedName: "test.foo_h2.com",
expectedAlpn: "h3", expectedAlpn: "http/1.1",
});
checkResult(inRecord, true, true, {
expectedPriority: 2,
expectedName: "test.foo_h2.com",
expectedAlpn: "http/1.1",
}); });
checkResult(inRecord, true, true);
Services.prefs.setBoolPref("network.dns.http3_echconfig.enabled", true); Services.prefs.setBoolPref("network.dns.http3_echconfig.enabled", true);
Services.dns.clearCache(true); Services.dns.clearCache(true);
@ -238,7 +254,11 @@ add_task(async function testTwoRecordsHaveEchConfig() {
expectedName: "test.foo_h3.com", expectedName: "test.foo_h3.com",
expectedAlpn: "h3", expectedAlpn: "h3",
}); });
checkResult(inRecord, true, true); checkResult(inRecord, true, true, {
expectedPriority: 2,
expectedName: "test.foo_h2.com",
expectedAlpn: "http/1.1",
});
await trrServer.stop(); await trrServer.stop();
trrServer = null; trrServer = null;
@ -274,6 +294,7 @@ add_task(async function testTwoRecordsHaveEchConfig1() {
name: "test.foo_h3.com", name: "test.foo_h3.com",
values: [ values: [
{ key: "alpn", value: ["h3", "h2"] }, { key: "alpn", value: ["h3", "h2"] },
{ key: "no-default-alpn" },
{ key: "echconfig", value: "456..." }, { key: "echconfig", value: "456..." },
], ],
}, },
@ -380,6 +401,7 @@ add_task(async function testOneRecordsHasEchConfig() {
name: "test.foo_h3.com", name: "test.foo_h3.com",
values: [ values: [
{ key: "alpn", value: ["h3"] }, { key: "alpn", value: ["h3"] },
{ key: "no-default-alpn" },
{ key: "echconfig", value: "456..." }, { key: "echconfig", value: "456..." },
], ],
}, },
@ -417,7 +439,11 @@ add_task(async function testOneRecordsHasEchConfig() {
expectedName: "test.foo_h3.com", expectedName: "test.foo_h3.com",
expectedAlpn: "h3", expectedAlpn: "h3",
}); });
checkResult(inRecord, true, true); checkResult(inRecord, true, true, {
expectedPriority: 2,
expectedName: "test.foo_h2.com",
expectedAlpn: "http/1.1",
});
Services.prefs.setBoolPref("network.dns.http3_echconfig.enabled", true); Services.prefs.setBoolPref("network.dns.http3_echconfig.enabled", true);
Services.dns.clearCache(true); Services.dns.clearCache(true);
@ -440,7 +466,11 @@ add_task(async function testOneRecordsHasEchConfig() {
expectedName: "test.foo_h3.com", expectedName: "test.foo_h3.com",
expectedAlpn: "h3", expectedAlpn: "h3",
}); });
checkResult(inRecord, true, true); checkResult(inRecord, true, true, {
expectedPriority: 2,
expectedName: "test.foo_h2.com",
expectedAlpn: "http/1.1",
});
await trrServer.stop(); await trrServer.stop();
trrServer = null; trrServer = null;
@ -475,6 +505,7 @@ add_task(async function testHttp3AndHttp2Pref() {
name: "test.foo_h3.com", name: "test.foo_h3.com",
values: [ values: [
{ key: "alpn", value: ["h3", "h2"] }, { key: "alpn", value: ["h3", "h2"] },
{ key: "no-default-alpn" },
{ key: "echconfig", value: "456..." }, { key: "echconfig", value: "456..." },
], ],
}, },
@ -510,11 +541,23 @@ add_task(async function testHttp3AndHttp2Pref() {
expectedName: "test.foo_h3.com", expectedName: "test.foo_h3.com",
expectedAlpn: "h2", expectedAlpn: "h2",
}); });
checkResult(inRecord, true, false); checkResult(inRecord, true, false, {
checkResult(inRecord, true, true); expectedPriority: 2,
expectedName: "test.foo_h2.com",
expectedAlpn: "http/1.1",
});
checkResult(inRecord, true, true, {
expectedPriority: 2,
expectedName: "test.foo_h2.com",
expectedAlpn: "http/1.1",
});
Services.prefs.setBoolPref("network.http.http2.enabled", false); Services.prefs.setBoolPref("network.http.http2.enabled", false);
checkResult(inRecord, false, false); checkResult(inRecord, false, false, {
expectedPriority: 2,
expectedName: "test.foo_h2.com",
expectedAlpn: "http/1.1",
});
Services.prefs.setBoolPref("network.http.http3.enable", true); Services.prefs.setBoolPref("network.http.http3.enable", true);
checkResult(inRecord, false, false, { checkResult(inRecord, false, false, {
@ -522,13 +565,21 @@ add_task(async function testHttp3AndHttp2Pref() {
expectedName: "test.foo_h3.com", expectedName: "test.foo_h3.com",
expectedAlpn: "h3", expectedAlpn: "h3",
}); });
checkResult(inRecord, false, true); checkResult(inRecord, false, true, {
expectedPriority: 2,
expectedName: "test.foo_h2.com",
expectedAlpn: "http/1.1",
});
checkResult(inRecord, true, false, { checkResult(inRecord, true, false, {
expectedPriority: 1, expectedPriority: 1,
expectedName: "test.foo_h3.com", expectedName: "test.foo_h3.com",
expectedAlpn: "h3", expectedAlpn: "h3",
}); });
checkResult(inRecord, true, true); checkResult(inRecord, true, true, {
expectedPriority: 2,
expectedName: "test.foo_h2.com",
expectedAlpn: "http/1.1",
});
await trrServer.stop(); await trrServer.stop();
trrServer = null; trrServer = null;

View file

@ -206,20 +206,6 @@ add_task(async function testFallbackToTheOrigin() {
], ],
}, },
}, },
{
name: "test.foo.com",
ttl: 55,
type: "HTTPS",
flush: false,
data: {
priority: 3,
name: "test.foo3.com",
values: [
{ key: "alpn", value: ["h2", "h3-26"] },
{ key: "echconfig", value: "456..." },
],
},
},
{ {
name: "test.foo.com", name: "test.foo.com",
ttl: 55, ttl: 55,
@ -799,6 +785,7 @@ add_task(async function testHttp3ExcludedList() {
name: "www.h3_fail.org", name: "www.h3_fail.org",
values: [ values: [
{ key: "alpn", value: "h3-29" }, { key: "alpn", value: "h3-29" },
{ key: "no-default-alpn" },
{ key: "port", value: h3Port }, { key: "port", value: h3Port },
], ],
}, },
@ -901,6 +888,7 @@ add_task(async function testAllRecordsInHttp3ExcludedList() {
name: "www.h3_fail1.org", name: "www.h3_fail1.org",
values: [ values: [
{ key: "alpn", value: "h3-29" }, { key: "alpn", value: "h3-29" },
{ key: "no-default-alpn" },
{ key: "port", value: h3Port }, { key: "port", value: h3Port },
{ key: "echconfig", value: "456..." }, { key: "echconfig", value: "456..." },
], ],