Backed out 5 changesets (bug 1675016) for causing xpcshell failures in test_http3_fatal_stream_error. CLOSED TREE

Backed out changeset aae840485291 (bug 1675016)
Backed out changeset c5f004fdef59 (bug 1675016)
Backed out changeset 56b8282707e0 (bug 1675016)
Backed out changeset ac23fff376cf (bug 1675016)
Backed out changeset 63109e213984 (bug 1675016)
This commit is contained in:
smolnar 2020-11-10 14:19:44 +02:00
parent 06adde3adb
commit 03e890da15
17 changed files with 169 additions and 479 deletions

View File

@ -160,9 +160,7 @@ void AltSvcMapping::ProcessHeader(
SpdyInformation* spdyInfo = gHttpHandler->SpdyInfo();
if (!(NS_SUCCEEDED(spdyInfo->GetNPNIndex(npnToken, &spdyIndex)) &&
spdyInfo->ProtocolEnabled(spdyIndex)) &&
!(isHttp3 && gHttpHandler->IsHttp3Enabled() &&
!gHttpHandler->IsHttp3Excluded(hostname.IsEmpty() ? originHost
: hostname))) {
!(isHttp3 && gHttpHandler->IsHttp3Enabled())) {
LOG(("Alt Svc unknown protocol %s, ignoring", npnToken.get()));
continue;
}
@ -944,8 +942,7 @@ already_AddRefed<AltSvcMapping> AltSvcCache::LookupMapping(
if (rv->IsHttp3() &&
(!gHttpHandler->IsHttp3Enabled() ||
!gHttpHandler->IsHttp3VersionSupported(rv->NPNToken()) ||
gHttpHandler->IsHttp3Excluded(rv->AlternateHost()))) {
!gHttpHandler->IsHttp3VersionSupported(rv->NPNToken()))) {
// If Http3 is disabled or the version not supported anymore, remove the
// mapping.
mStorage->Remove(

View File

@ -73,7 +73,8 @@ Http3Session::Http3Session()
gHttpHandler->ConnMgr()->CurrentTopLevelOuterContentWindowId();
}
nsresult Http3Session::Init(const nsHttpConnectionInfo* aConnInfo,
nsresult Http3Session::Init(const nsACString& aOrigin,
const nsACString& aAlpnToken,
nsISocketTransport* aSocketTransport,
HttpConnectionUDP* readerWriter) {
LOG3(("Http3Session::Init %p", this));
@ -82,7 +83,7 @@ nsresult Http3Session::Init(const nsHttpConnectionInfo* aConnInfo,
MOZ_ASSERT(aSocketTransport);
MOZ_ASSERT(readerWriter);
mConnInfo = aConnInfo->Clone();
mAlpnToken = aAlpnToken;
mSocketTransport = aSocketTransport;
nsCOMPtr<nsISupports> info;
@ -136,14 +137,14 @@ nsresult Http3Session::Init(const nsHttpConnectionInfo* aConnInfo,
LOG3(
("Http3Session::Init origin=%s, alpn=%s, selfAddr=%s, peerAddr=%s,"
" qpack table size=%u, max blocked streams=%u [this=%p]",
PromiseFlatCString(mConnInfo->GetOrigin()).get(),
PromiseFlatCString(mConnInfo->GetNPNToken()).get(), selfAddrStr.get(),
peerAddrStr.get(), gHttpHandler->DefaultQpackTableSize(),
PromiseFlatCString(aOrigin).get(), PromiseFlatCString(aAlpnToken).get(),
selfAddrStr.get(), peerAddrStr.get(),
gHttpHandler->DefaultQpackTableSize(),
gHttpHandler->DefaultHttp3MaxBlockedStreams(), this));
nsresult rv = NeqoHttp3Conn::Init(
mConnInfo->GetOrigin(), mConnInfo->GetNPNToken(), selfAddrStr,
peerAddrStr, gHttpHandler->DefaultQpackTableSize(),
aOrigin, aAlpnToken, selfAddrStr, peerAddrStr,
gHttpHandler->DefaultQpackTableSize(),
gHttpHandler->DefaultHttp3MaxBlockedStreams(),
gHttpHandler->Http3QlogDir(), getter_AddRefs(mHttp3Connection));
if (NS_FAILED(rv)) {
@ -186,11 +187,6 @@ nsresult Http3Session::Init(const nsHttpConnectionInfo* aConnInfo,
void Http3Session::Shutdown() {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
if ((mBeforeConnectedError || (mError == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR)) &&
(mError != mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN))) {
gHttpHandler->ExcludeHttp3(mConnInfo);
}
for (auto iter = mStreamTransactionHash.Iter(); !iter.Done(); iter.Next()) {
RefPtr<Http3Stream> stream = iter.Data();
@ -199,12 +195,10 @@ void Http3Session::Shutdown() {
// The transaction restart code path will remove AltSvc mapping and the
// direct path will be used.
MOZ_ASSERT(NS_FAILED(mError));
stream->Close(NS_ERROR_NET_RESET);
stream->Close(mError);
} else if (!stream->HasStreamId()) {
if (NS_SUCCEEDED(mError)) {
// Connection has not been started yet. We can restart it.
stream->Transaction()->DoNotRemoveAltSvc();
}
// Connection has not been started yet. We can restart it.
stream->Transaction()->DoNotRemoveAltSvc();
stream->Close(NS_ERROR_NET_RESET);
} else if (stream->RecvdData()) {
stream->Close(NS_ERROR_NET_PARTIAL_TRANSFER);
@ -842,8 +836,7 @@ void Http3Session::ResetRecvd(uint64_t aStreamId, uint64_t aError) {
if (aError == HTTP3_APP_ERROR_VERSION_FALLBACK) {
// We will restart the request and the alt-svc will be removed
// automatically.
// Also disable http3 we want http1.1.
stream->Transaction()->DisableHttp3();
// Also disable spdy we want http/1.1.
stream->Transaction()->DisableSpdy();
CloseStream(stream, NS_ERROR_NET_RESET);
} else if (aError == HTTP3_APP_ERROR_REQUEST_REJECTED) {
@ -1481,11 +1474,11 @@ bool Http3Session::RealJoinConnection(const nsACString& hostname, int32_t port,
bool joinedReturn = false;
if (justKidding) {
rv = sslSocketControl->TestJoinConnection(mConnInfo->GetNPNToken(),
hostname, port, &isJoined);
rv = sslSocketControl->TestJoinConnection(mAlpnToken, hostname, port,
&isJoined);
} else {
rv = sslSocketControl->JoinConnection(mConnInfo->GetNPNToken(), hostname,
port, &isJoined);
rv =
sslSocketControl->JoinConnection(mAlpnToken, hostname, port, &isJoined);
}
if (NS_SUCCEEDED(rv) && isJoined) {
joinedReturn = true;

View File

@ -46,7 +46,7 @@ class Http3Session final : public nsAHttpTransaction,
NS_DECL_NSAHTTPSEGMENTWRITER
Http3Session();
nsresult Init(const nsHttpConnectionInfo* aConnInfo,
nsresult Init(const nsACString& aOrigin, const nsACString& aAlpnToken,
nsISocketTransport* aSocketTransport,
HttpConnectionUDP* readerWriter);
@ -206,8 +206,6 @@ class Http3Session final : public nsAHttpTransaction,
// NS_NET_STATUS_CONNECTED_TO event will be created by the Http3Session.
// We want to propagate it to the first transaction.
RefPtr<nsHttpTransaction> mFirstHttpTransaction;
RefPtr<nsHttpConnectionInfo> mConnInfo;
};
NS_DEFINE_STATIC_IID_ACCESSOR(Http3Session, NS_HTTP3SESSION_IID);

View File

@ -115,7 +115,8 @@ nsresult HttpConnectionUDP::Init(
MOZ_ASSERT(mConnInfo->IsHttp3());
mHttp3Session = new Http3Session();
nsresult rv = mHttp3Session->Init(mConnInfo, mSocketTransport, this);
nsresult rv = mHttp3Session->Init(
mConnInfo->GetOrigin(), mConnInfo->GetNPNToken(), mSocketTransport, this);
if (NS_FAILED(rv)) {
LOG(
("HttpConnectionUDP::Init mHttp3Session->Init failed "

View File

@ -396,7 +396,8 @@ nsresult TRRServiceChannel::BeginConnect() {
mAllowAltSvc = XRE_IsParentProcess() && mAllowAltSvc;
bool http2Allowed = !gHttpHandler->IsHttp2Excluded(connInfo);
bool http3Allowed = !mUpgradeProtocolCallback && !mProxyInfo &&
!(mCaps & NS_HTTP_BE_CONSERVATIVE) && !mBeConservative;
!(mCaps & NS_HTTP_BE_CONSERVATIVE) && !mBeConservative &&
!gHttpHandler->IsHttp3Excluded(connInfo);
RefPtr<AltSvcMapping> mapping;
if (!mConnectionInfo && mAllowAltSvc && // per channel

View File

@ -178,7 +178,6 @@ class nsAHttpTransaction : public nsSupportsWeakReference {
}
virtual void DisableSpdy() {}
virtual void DisableHttp3() {}
virtual void MakeNonSticky() {}
virtual void ReuseConnectionOnRestartOK(bool) {}

View File

@ -6672,7 +6672,7 @@ nsresult nsHttpChannel::BeginConnect() {
}
bool http3Allowed = !mUpgradeProtocolCallback && !mProxyInfo &&
!(mCaps & NS_HTTP_BE_CONSERVATIVE) && !mBeConservative &&
mAllowHttp3;
!gHttpHandler->IsHttp3Excluded(connInfo) && mAllowHttp3;
// No need to lookup HTTPSSVC record if we already have one.
mUseHTTPSSVC =

View File

@ -2851,15 +2851,15 @@ void nsHttpHandler::ExcludeHttp3(const nsHttpConnectionInfo* ci) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
mConnMgr->ExcludeHttp3(ci);
if (!mExcludedHttp3Origins.Contains(ci->GetRoutedHost())) {
if (!mExcludedHttp3Origins.Contains(ci->GetOrigin())) {
MutexAutoLock lock(mHttpExclusionLock);
mExcludedHttp3Origins.PutEntry(ci->GetRoutedHost());
mExcludedHttp3Origins.PutEntry(ci->GetOrigin());
}
}
bool nsHttpHandler::IsHttp3Excluded(const nsACString& aRoutedHost) {
bool nsHttpHandler::IsHttp3Excluded(const nsHttpConnectionInfo* ci) {
MutexAutoLock lock(mHttpExclusionLock);
return mExcludedHttp3Origins.Contains(aRoutedHost);
return mExcludedHttp3Origins.Contains(ci->GetOrigin());
}
HttpTrafficAnalyzer* nsHttpHandler::GetHttpTrafficAnalyzer() {

View File

@ -855,7 +855,7 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
void ExcludeHttp2(const nsHttpConnectionInfo* ci);
[[nodiscard]] bool IsHttp2Excluded(const nsHttpConnectionInfo* ci);
void ExcludeHttp3(const nsHttpConnectionInfo* ci);
[[nodiscard]] bool IsHttp3Excluded(const nsACString& aRoutedHost);
[[nodiscard]] bool IsHttp3Excluded(const nsHttpConnectionInfo* ci);
private:
nsTHashtable<nsCStringHashKey> mExcludedHttp2Origins;

View File

@ -2413,11 +2413,6 @@ void nsHttpTransaction::DisableHttp3() {
// After CloneAsDirectRoute(), http3 will be disabled.
RefPtr<nsHttpConnectionInfo> connInfo;
mConnInfo->CloneAsDirectRoute(getter_AddRefs(connInfo));
if (mRequestHead) {
DebugOnly<nsresult> rv =
mRequestHead->SetHeader(nsHttp::Alternate_Service_Used, "0"_ns);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
MOZ_ASSERT(!connInfo->IsHttp3());
mConnInfo.swap(connInfo);
}
@ -2808,11 +2803,6 @@ nsresult nsHttpTransaction::RestartOnFastOpenError() {
RefPtr<nsHttpConnectionInfo> ci;
mConnInfo->CloneAsDirectRoute(getter_AddRefs(ci));
mConnInfo = ci;
if (mRequestHead) {
DebugOnly<nsresult> rv =
mRequestHead->SetHeader(nsHttp::Alternate_Service_Used, "0"_ns);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
}
mEarlyDataDisposition = EARLY_NONE;
m0RTTInProgress = false;

View File

@ -103,7 +103,7 @@ class nsHttpTransaction final : public nsAHttpTransaction,
void RemoveDispatchedAsBlocking();
void DisableSpdy() override;
void DisableHttp3() override;
void DisableHttp3();
nsHttpTransaction* QueryHttpTransaction() override { return this; }

View File

@ -304,24 +304,6 @@ impl HttpServer for Server {
}
}
#[derive(Default)]
struct NonRespondingServer {
}
impl ::std::fmt::Display for NonRespondingServer {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "NonRespondingServer")
}
}
impl HttpServer for NonRespondingServer {
fn process(&mut self, _dgram: Option<Datagram>) -> Output {
Output::None
}
fn process_events(&mut self) {}
}
fn emit_packet(socket: &UdpSocket, out_dgram: Datagram) {
let sent = socket
.send_to(&out_dgram, &out_dgram.destination())
@ -386,12 +368,6 @@ fn read_dgram(
}
}
enum ServerType {
Http3,
Http3Fail,
Http3NoResponse,
}
struct ServersRunner {
hosts: Vec<SocketAddr>,
poll: Poll,
@ -416,21 +392,19 @@ impl ServersRunner {
}
pub fn init(&mut self) {
self.add_new_socket(0, ServerType::Http3);
self.add_new_socket(1, ServerType::Http3Fail);
self.add_new_socket(3, ServerType::Http3NoResponse);
self.add_new_socket(0, true);
self.add_new_socket(1, false);
println!(
"HTTP3 server listening on ports {}, {} and {}",
"HTTP3 server listening on ports {} and {}",
self.hosts[0].port(),
self.hosts[1].port(),
self.hosts[2].port()
self.hosts[1].port()
);
self.poll
.register(&self.timer, TIMER_TOKEN, Ready::readable(), PollOpt::edge())
.unwrap();
}
fn add_new_socket(&mut self, count: usize, server_type: ServerType) -> u16 {
fn add_new_socket(&mut self, count: usize, http3: bool) -> u16 {
let addr = "127.0.0.1:0".parse().unwrap();
let socket = match UdpSocket::bind(&addr) {
@ -462,49 +436,44 @@ impl ServersRunner {
self.sockets.push(socket);
self.servers
.insert(local_addr, (self.create_server(server_type), None));
.insert(local_addr, (self.create_server(http3), None));
local_addr.port()
}
fn create_server(&self, server_type: ServerType) -> Box<dyn HttpServer> {
fn create_server(&self, http3: bool) -> Box<dyn HttpServer> {
let anti_replay = AntiReplay::new(Instant::now(), Duration::from_secs(10), 7, 14)
.expect("unable to setup anti-replay");
let cid_mgr = Rc::new(RefCell::new(FixedConnectionIdManager::new(10)));
match server_type {
ServerType::Http3 =>
Box::new(
Http3TestServer::new(
Http3Server::new(
Instant::now(),
&[" HTTP2 Test Cert"],
PROTOCOLS,
anti_replay,
cid_mgr,
QpackSettings {
max_table_size_encoder: MAX_TABLE_SIZE,
max_table_size_decoder: MAX_TABLE_SIZE,
max_blocked_streams: MAX_BLOCKED_STREAMS,
},
).expect("We cannot make a server!")
)
),
ServerType::Http3Fail =>
Box::new(
Server::new(
if http3 {
Box::new(
Http3TestServer::new(
Http3Server::new(
Instant::now(),
&[" HTTP2 Test Cert"],
PROTOCOLS,
anti_replay,
Box::new(AllowZeroRtt {}),
cid_mgr,
)
.expect("We cannot make a server!"),
),
ServerType::Http3NoResponse =>
Box::new(
NonRespondingServer::default()
),
QpackSettings {
max_table_size_encoder: MAX_TABLE_SIZE,
max_table_size_decoder: MAX_TABLE_SIZE,
max_blocked_streams: MAX_BLOCKED_STREAMS,
},
).expect("We cannot make a server!")
)
)
} else {
Box::new(
Server::new(
Instant::now(),
&[" HTTP2 Test Cert"],
PROTOCOLS,
anti_replay,
Box::new(AllowZeroRtt {}),
cid_mgr,
)
.expect("We cannot make a server!"),
)
}
}

View File

@ -1,124 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let httpsUri;
registerCleanupFunction(async () => {
Services.prefs.clearUserPref("network.http.http3.enabled");
Services.prefs.clearUserPref("network.dns.localDomains");
Services.prefs.clearUserPref("network.dns.disableIPv6");
Services.prefs.clearUserPref(
"network.http.http3.alt-svc-mapping-for-testing"
);
dump("cleanup done\n");
});
function chanPromise(chan, listener) {
return new Promise(resolve => {
function finish() {
resolve();
}
listener.finish = finish;
chan.asyncOpen(listener);
});
}
function makeChan() {
let chan = NetUtil.newChannel({
uri: httpsUri,
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIHttpChannel);
chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
return chan;
}
function altsvcSetupPromise(chan, listener) {
return new Promise(resolve => {
function finish(result) {
resolve(result);
}
listener.finish = finish;
chan.asyncOpen(listener);
});
}
add_task(async function test_fatal_error() {
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
let h2Port = env.get("MOZHTTP2_PORT");
Assert.notEqual(h2Port, null);
let h3Port = env.get("MOZHTTP3_PORT_NO_RESPONSE");
Assert.notEqual(h3Port, null);
Assert.notEqual(h3Port, "");
Services.prefs.setBoolPref("network.http.http3.enabled", true);
Services.prefs.setCharPref("network.dns.localDomains", "foo.example.com");
Services.prefs.setBoolPref("network.dns.disableIPv6", true);
// Set AltSvc to point to not existing HTTP3 server on port 443
Services.prefs.setCharPref(
"network.http.http3.alt-svc-mapping-for-testing",
"foo.example.com;h3-27=:" + h3Port
);
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
httpsUri = "https://foo.example.com:" + h2Port + "/";
});
add_task(async function test_fatal_stream_error() {
let result = 1;
// We need to loop here because we need to wait for AltSvc storage to
// to be started.
// We also do not have a way to verify that HTTP3 has been tried, because
// the fallback is automatic, so try a couple of times.
do {
// We need to close HTTP2 connections, otherwise our connection pooling
// will dispatch the request over already existing HTTP2 connection.
Services.obs.notifyObservers(null, "net:prune-all-connections");
let chan = makeChan();
let listener = new CheckOnlyHttp2Listener();
await altsvcSetupPromise(chan, listener);
result++;
} while (result < 5);
});
let CheckOnlyHttp2Listener = function() {};
CheckOnlyHttp2Listener.prototype = {
onStartRequest: function testOnStartRequest(request) {},
onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) {
read_stream(stream, cnt);
},
onStopRequest: function testOnStopRequest(request, status) {
Assert.equal(status, Cr.NS_OK);
let httpVersion = "";
try {
httpVersion = request.protocolVersion;
} catch (e) {}
Assert.equal(httpVersion, "h2");
this.finish();
},
};
add_task(async function test_no_http3_after_error() {
let chan = makeChan();
let listener = new CheckOnlyHttp2Listener();
await altsvcSetupPromise(chan, listener);
});
// also after all connections are closed.
add_task(async function test_no_http3_after_error2() {
Services.obs.notifyObservers(null, "net:prune-all-connections");
let chan = makeChan();
let listener = new CheckOnlyHttp2Listener();
await altsvcSetupPromise(chan, listener);
});

View File

@ -1,147 +1,141 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let httpsUri;
let h3Port;
let h3Route;
let h3AltSvc;
let prefs;
let httpsOrigin;
registerCleanupFunction(async () => {
Services.prefs.clearUserPref("network.http.http3.enabled");
Services.prefs.clearUserPref("network.dns.localDomains");
Services.prefs.clearUserPref("network.dns.disableIPv6");
Services.prefs.clearUserPref(
"network.http.http3.alt-svc-mapping-for-testing"
let tests = [
// The altSvc storage may not be up imediately, therefore run test_no_altsvc_pref
// for a couple times to wait for the storage.
test_no_altsvc_pref,
test_no_altsvc_pref,
test_no_altsvc_pref,
test_protocol_error,
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
);
dump("cleanup done\n");
});
h3Port = env.get("MOZHTTP3_PORT_FAILED");
Assert.notEqual(h3Port, null);
Assert.notEqual(h3Port, "");
h3AltSvc = ":" + h3Port;
let Http3FailedListener = function() {};
h3Route = "foo.example.com:" + h3Port;
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
Http3FailedListener.prototype = {
onStartRequest: function testOnStartRequest(request) {},
prefs.setBoolPref("network.http.http3.enabled", true);
prefs.setCharPref("network.dns.localDomains", "foo.example.com");
prefs.setBoolPref("network.dns.disableIPv6", true);
// 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/";
run_next_test();
}
let Http3CheckListener = function() {};
Http3CheckListener.prototype = {
expectedRoute: "",
expectedStatus: Cr.NS_OK,
onStartRequest: function testOnStartRequest(request) {
Assert.ok(request instanceof Ci.nsIHttpChannel);
Assert.equal(request.status, this.expectedStatus);
if (Components.isSuccessCode(this.expectedStatus)) {
Assert.equal(request.responseStatus, 200);
}
},
onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) {
this.amount += cnt;
read_stream(stream, cnt);
},
onStopRequest: function testOnStopRequest(request, status) {
if (Components.isSuccessCode(status)) {
// This is still HTTP2 connection
Assert.equal(status, this.expectedStatus);
if (Components.isSuccessCode(this.expectedStatus)) {
Assert.equal(request.responseStatus, 200);
let routed = "NA";
try {
routed = request.getRequestHeader("Alt-Used");
} catch (e) {}
dump("routed is " + routed + "\n");
Assert.equal(routed, this.expectedRoute);
let httpVersion = "";
try {
httpVersion = request.protocolVersion;
} catch (e) {}
Assert.equal(httpVersion, "h2");
this.finish(false);
} else {
Assert.equal(status, Cr.NS_ERROR_NET_PARTIAL_TRANSFER);
this.finish(true);
Assert.equal(httpVersion, "h3");
}
run_next_test();
do_test_finished();
},
};
function chanPromise(chan, listener) {
return new Promise(resolve => {
function finish(result) {
resolve(result);
}
listener.finish = finish;
chan.asyncOpen(listener);
});
}
function makeChan() {
function makeChan(uri) {
let chan = NetUtil.newChannel({
uri: httpsUri,
uri,
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIHttpChannel);
chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
return chan;
}
function altsvcSetupPromise(chan, listener) {
return new Promise(resolve => {
function finish(result) {
resolve(result);
}
listener.finish = finish;
chan.asyncOpen(listener);
});
function test_no_altsvc_pref() {
dump("test_no_altsvc_pref");
do_test_pending();
let chan = makeChan(httpsOrigin + "http3-test");
let listener = new Http3CheckListener();
listener.expectedStatus = Cr.NS_ERROR_CONNECTION_REFUSED;
chan.asyncOpen(listener);
}
add_task(async function test_fatal_error() {
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
function test_protocol_error() {
dump("test_protocol_error");
do_test_pending();
let h2Port = env.get("MOZHTTP2_PORT");
Assert.notEqual(h2Port, null);
let h3Port = env.get("MOZHTTP3_PORT_FAILED");
Assert.notEqual(h3Port, null);
Assert.notEqual(h3Port, "");
Services.prefs.setBoolPref("network.http.http3.enabled", true);
Services.prefs.setCharPref("network.dns.localDomains", "foo.example.com");
Services.prefs.setBoolPref("network.dns.disableIPv6", true);
Services.prefs.setCharPref(
prefs.setCharPref(
"network.http.http3.alt-svc-mapping-for-testing",
"foo.example.com;h3-27=:" + h3Port
"foo.example.com;h3-27=" + h3AltSvc
);
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
let chan = makeChan(httpsOrigin + "wrong_frame_after_data_frame");
let listener = new Http3CheckListener();
listener.expectedRoute = h3Route;
listener.expectedStatus = Cr.NS_ERROR_NET_PARTIAL_TRANSFER;
chan.asyncOpen(listener);
}
httpsUri = "https://foo.example.com:" + h2Port + "/";
});
add_task(async function test_fatal_stream_error() {
let result = false;
// We need to loop here because we need to wait for AltSvc storage to
// to be started.
do {
// We need to close HTTP2 connections, otherwise our connection pooling
// will dispatch the request over already existing HTTP2 connection.
Services.obs.notifyObservers(null, "net:prune-all-connections");
let chan = makeChan();
let listener = new Http3FailedListener();
result = await altsvcSetupPromise(chan, listener);
} while (result === false);
});
let CheckOnlyHttp2Listener = function() {};
CheckOnlyHttp2Listener.prototype = {
onStartRequest: function testOnStartRequest(request) {},
onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) {
read_stream(stream, cnt);
},
onStopRequest: function testOnStopRequest(request, status) {
Assert.equal(status, Cr.NS_OK);
let httpVersion = "";
try {
httpVersion = request.protocolVersion;
} catch (e) {}
Assert.equal(httpVersion, "h2");
this.finish(false);
},
};
add_task(async function test_no_http3_after_error() {
let chan = makeChan();
let listener = new CheckOnlyHttp2Listener();
await altsvcSetupPromise(chan, listener);
});
// also after all connections are closed.
add_task(async function test_no_http3_after_error2() {
Services.obs.notifyObservers(null, "net:prune-all-connections");
let chan = makeChan();
let listener = new CheckOnlyHttp2Listener();
await altsvcSetupPromise(chan, listener);
});
function testsDone() {
prefs.clearUserPref("network.http.http3.enabled");
prefs.clearUserPref("network.dns.localDomains");
prefs.clearUserPref("network.dns.disableIPv6");
prefs.clearUserPref("network.http.http3.alt-svc-mapping-for-testing");
dump("testDone\n");
}

View File

@ -1,121 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let httpsUri;
registerCleanupFunction(async () => {
Services.prefs.clearUserPref("network.http.http3.enabled");
Services.prefs.clearUserPref("network.dns.localDomains");
Services.prefs.clearUserPref("network.dns.disableIPv6");
Services.prefs.clearUserPref(
"network.http.http3.alt-svc-mapping-for-testing"
);
dump("cleanup done\n");
});
function chanPromise(chan, listener) {
return new Promise(resolve => {
function finish() {
resolve();
}
listener.finish = finish;
chan.asyncOpen(listener);
});
}
function makeChan() {
let chan = NetUtil.newChannel({
uri: httpsUri,
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIHttpChannel);
chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
return chan;
}
function altsvcSetupPromise(chan, listener) {
return new Promise(resolve => {
function finish(result) {
resolve(result);
}
listener.finish = finish;
chan.asyncOpen(listener);
});
}
add_task(async function test_fatal_error() {
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
let h2Port = env.get("MOZHTTP2_PORT");
Assert.notEqual(h2Port, null);
Services.prefs.setBoolPref("network.http.http3.enabled", true);
Services.prefs.setCharPref("network.dns.localDomains", "foo.example.com");
Services.prefs.setBoolPref("network.dns.disableIPv6", true);
// Set AltSvc to point to not existing HTTP3 server on port 443
Services.prefs.setCharPref(
"network.http.http3.alt-svc-mapping-for-testing",
"foo.example.com;h3-27=:443"
);
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
httpsUri = "https://foo.example.com:" + h2Port + "/";
});
add_task(async function test_fatal_stream_error() {
let result = 1;
// We need to loop here because we need to wait for AltSvc storage to
// to be started.
// We also do not have a way to verify that HTTP3 has been tried, because
// the fallback is automatic, so try a couple of times.
do {
// We need to close HTTP2 connections, otherwise our connection pooling
// will dispatch the request over already existing HTTP2 connection.
Services.obs.notifyObservers(null, "net:prune-all-connections");
let chan = makeChan();
let listener = new CheckOnlyHttp2Listener();
await altsvcSetupPromise(chan, listener);
result++;
} while (result < 5);
});
let CheckOnlyHttp2Listener = function() {};
CheckOnlyHttp2Listener.prototype = {
onStartRequest: function testOnStartRequest(request) {},
onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) {
read_stream(stream, cnt);
},
onStopRequest: function testOnStopRequest(request, status) {
Assert.equal(status, Cr.NS_OK);
let httpVersion = "";
try {
httpVersion = request.protocolVersion;
} catch (e) {}
Assert.equal(httpVersion, "h2");
this.finish();
},
};
add_task(async function test_no_http3_after_error() {
let chan = makeChan();
let listener = new CheckOnlyHttp2Listener();
await altsvcSetupPromise(chan, listener);
});
// also after all connections are closed.
add_task(async function test_no_http3_after_error2() {
Services.obs.notifyObservers(null, "net:prune-all-connections");
let chan = makeChan();
let listener = new CheckOnlyHttp2Listener();
await altsvcSetupPromise(chan, listener);
});

View File

@ -479,9 +479,5 @@ skip-if = asan || tsan || os == 'win' || os =='android'
skip-if = asan || tsan || os == 'win' || os =='android'
[test_http3_large_post.js]
skip-if = asan || tsan || os == 'win' || os =='android'
[test_http3_error_before_connect.js]
skip-if = asan || tsan || os == 'win' || os =='android'
[test_http3_server_not_existing.js]
skip-if = asan || tsan || os == 'win' || os =='android'
[test_cookie_ipv6.js]

View File

@ -1412,14 +1412,11 @@ class XPCShellTests(object):
msg = process.stdout.readline()
if "server listening" in msg:
searchObj = re.search(
r"HTTP3 server listening on ports ([0-9]+), ([0-9]+) and ([0-9]+)",
msg,
0,
r"HTTP3 server listening on ports ([0-9]+) and ([0-9]+)", msg, 0
)
if searchObj:
self.env["MOZHTTP3_PORT"] = searchObj.group(1)
self.env["MOZHTTP3_PORT_FAILED"] = searchObj.group(2)
self.env["MOZHTTP3_PORT_NO_RESPONSE"] = searchObj.group(3)
except OSError as e:
# This occurs if the subprocess couldn't be started
self.log.error("Could not run the http3 server: %s" % (str(e)))