tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 97c5ed3c963f0b43775a008d9120779b31dda96d
parent 10f519f933411749defbc118956c28dc910addef
Author: Kershaw Chang <kershaw@mozilla.com>
Date:   Sun,  4 Jan 2026 20:16:21 +0000

Bug 2000787 - Using stable connection ID from StreamHandler::conn, r=mxinden,necko-reviewers,valentin

Differential Revision: https://phabricator.services.mozilla.com/D277758

Diffstat:
Mnetwerk/test/http3server/src/main.rs | 68+++++++++++++++++++++++++++++++++++++++++---------------------------
Mnetwerk/test/unit/test_http3_coalescing.js | 8--------
2 files changed, 41 insertions(+), 35 deletions(-)

diff --git a/netwerk/test/http3server/src/main.rs b/netwerk/test/http3server/src/main.rs @@ -7,7 +7,7 @@ use base64::prelude::*; use neqo_bin::server::{HttpServer, Runner}; use neqo_common::Bytes; -use neqo_common::{event::Provider, qdebug, qinfo, qtrace, qerror, Datagram, Header}; +use neqo_common::{event::Provider, qdebug, qerror, qinfo, qtrace, Datagram, Header}; use neqo_crypto::{generate_ech_keys, init_db, AllowZeroRtt, AntiReplay}; use neqo_http3::{ ConnectUdpRequest, ConnectUdpServerEvent, Error, Http3OrWebTransportStream, Http3Parameters, @@ -70,7 +70,6 @@ struct Http3TestServer { posts: HashMap<Http3OrWebTransportStream, usize>, responses: HashMap<Http3OrWebTransportStream, Vec<u8>>, connections_to_close: HashMap<Instant, Vec<ConnectionRef>>, - current_connection_hash: u64, sessions_to_close: HashMap<Instant, Vec<WebTransportRequest>>, sessions_to_create_stream: Vec<(WebTransportRequest, StreamType, Option<Vec<u8>>)>, webtransport_bidi_stream: HashSet<Http3OrWebTransportStream>, @@ -91,7 +90,6 @@ impl Http3TestServer { posts: HashMap::new(), responses: HashMap::new(), connections_to_close: HashMap::new(), - current_connection_hash: 0, sessions_to_close: HashMap::new(), sessions_to_create_stream: Vec::new(), webtransport_bidi_stream: HashSet::new(), @@ -231,6 +229,12 @@ impl HttpServer for Http3TestServer { } => { qtrace!("Headers (request={} fin={}): {:?}", stream, fin, headers); + let connection_hash = { + let mut hasher = DefaultHasher::new(); + stream.conn.hash(&mut hasher); + hasher.finish() + }; + // Some responses do not have content-type. This is on purpose to exercise // UnknownDecoder code. let default_ret = b"Hello World".to_vec(); @@ -238,17 +242,17 @@ impl HttpServer for Http3TestServer { Header::new(":status", "200"), Header::new("cache-control", "no-cache"), Header::new("content-length", default_ret.len().to_string()), - Header::new( - "x-http3-conn-hash", - self.current_connection_hash.to_string(), - ), + Header::new("x-http3-conn-hash", connection_hash.to_string()), ]; let path_hdr = headers.iter().find(|&h| h.name() == ":path"); match path_hdr { Some(ph) if !ph.value().is_empty() => { let path = ph.value(); - qtrace!("Serve request {:?}", ph.value_utf8().unwrap_or("<invalid utf8>")); + qtrace!( + "Serve request {:?}", + ph.value_utf8().unwrap_or("<invalid utf8>") + ); if path == b"/Response421" { let response_body = b"0123456789".to_vec(); stream @@ -373,18 +377,17 @@ impl HttpServer for Http3TestServer { Header::new(":status", "200"), Header::new("cache-control", "no-cache"), Header::new("content-type", "text/plain"), - Header::new("priority-mirror", priority.value_utf8().unwrap()), + Header::new( + "priority-mirror", + priority.value_utf8().unwrap(), + ), Header::new( "content-length", priority.value().len().to_string(), ), ]) .unwrap(); - self.new_response( - stream, - priority.value().to_vec(), - now, - ); + self.new_response(stream, priority.value().to_vec(), now); } else { stream .send_headers(&[ @@ -460,7 +463,9 @@ impl HttpServer for Http3TestServer { self.new_response(stream, vec![b'a'; 100], now); } } else { - match ph.value_utf8().ok().and_then(|s| s.trim_matches(|p| p == '/').parse::<usize>().ok()) { + match ph.value_utf8().ok().and_then(|s| { + s.trim_matches(|p| p == '/').parse::<usize>().ok() + }) { Some(v) => { stream .send_headers(&[ @@ -524,13 +529,7 @@ impl HttpServer for Http3TestServer { Http3ServerEvent::DataWritable { stream } => { self.handle_stream_writable(stream, now) } - Http3ServerEvent::StateChange { conn, state } => { - if matches!(state, neqo_http3::Http3State::Connected) { - let mut h = DefaultHasher::new(); - conn.hash(&mut h); - self.current_connection_hash = h.finish(); - } - } + Http3ServerEvent::StateChange { .. } => {} Http3ServerEvent::PriorityUpdate { .. } => {} Http3ServerEvent::StreamReset { stream, error } => { qtrace!("Http3ServerEvent::StreamReset {:?} {:?}", stream, error); @@ -555,7 +554,10 @@ impl HttpServer for Http3TestServer { match path_hdr { Some(ph) if !ph.value().is_empty() => { let path = ph.value(); - qtrace!("Serve request {:?}", ph.value_utf8().unwrap_or("<invalid utf8>")); + qtrace!( + "Serve request {:?}", + ph.value_utf8().unwrap_or("<invalid utf8>") + ); if path == b"/success" { session.response(&SessionAcceptAction::Accept, now).unwrap(); } else if path == b"/redirect" { @@ -997,7 +999,9 @@ impl HttpServer for Http3ReverseProxyServer { let content_length = headers.iter().find(|&h| h.name() == "content-length"); if let Some(length_str) = content_length { - if let Ok(len) = length_str.value_utf8().unwrap_or("0").parse::<u32>() { + if let Ok(len) = + length_str.value_utf8().unwrap_or("0").parse::<u32>() + { if len > 0 { self.requests.insert(stream, (headers, Vec::new())); } else { @@ -1275,7 +1279,11 @@ impl HttpServer for Http3ConnectProxyServer { reason, headers: _, }) => { - qdebug!("ConnectUdp session closed: {:?} reason: {:?}", session, reason); + qdebug!( + "ConnectUdp session closed: {:?} reason: {:?}", + session, + reason + ); self.udp_sockets.remove(&session.stream_id()); } Http3ServerEvent::StateChange { .. } | Http3ServerEvent::PriorityUpdate { .. } => {} @@ -1407,7 +1415,11 @@ impl HttpServer for Http3ConnectProxyServer { progressed = true; } Poll::Ready(Err(e)) => { - qerror!("Error sending UDP datagram: {} {:?}, closing socket", e, socket.socket); + qerror!( + "Error sending UDP datagram: {} {:?}, closing socket", + e, + socket.socket + ); failed_udp_sockets.push(*stream_id); break; } @@ -1420,7 +1432,9 @@ impl HttpServer for Http3ConnectProxyServer { if let Some(socket) = self.udp_sockets.remove(&stream_id) { qdebug!("Removed failed UDP socket for stream {}", stream_id); // Close the session with an error code - let _ = socket.session.close_session(0x0100, "UDP socket error", Instant::now()); + let _ = socket + .session + .close_session(0x0100, "UDP socket error", Instant::now()); } } diff --git a/netwerk/test/unit/test_http3_coalescing.js b/netwerk/test/unit/test_http3_coalescing.js @@ -68,14 +68,6 @@ function channelOpenPromise(chan, flags) { } async function H3CoalescingTest(host1, host2) { - // Disable PMTUD (Path MTU Discovery) to avoid race condition between DNS - // resolution (to validate whether we can coalesce) and new connection - // attempt. Long term one might not want to start the new connection attempt - // in the first place. - // - // See Bug 1909910 for more details. - Services.prefs.setBoolPref("network.http.http3.pmtud", false); - Services.prefs.setCharPref( "network.http.http3.alt-svc-mapping-for-testing", `${host1};h3=:${h3Port}`