mirror of
https://github.com/Runnin4ik/dpi-detector.git
synced 2026-10-20 11:31:59 +00:00
fix: the QUIC column's counter stops at its total
`probe_domain` ticked the QUIC block for every row, while the block's total is only the rows whose endpoint serves HTTP/3 (`quic_unsupported.txt`), so a 35-domain list with 14 dashed hosts printed `QUIC 35/21` — the count of every row against the count of the applicable ones. The dash now moves nothing, which is what its own comment always said. The decision moved into `start_quic`, one place for both outcomes, so the regression is testable without a network: the new test drives the dashed branch with a counting sink and asserts zero ticks. Verified both ways — with the tick restored it fails `left: 1, right: 0`; without it, 289 core tests pass. The live line itself is drawn only when stderr is a terminal, so the counter was checked through the column's own accounting (`0/3 QUIC` for a four-row run with one dashed host) rather than by reading the rendered line.
This commit is contained in:
parent
262628727c
commit
5ee3da2be9
1 changed files with 86 additions and 21 deletions
|
|
@ -681,27 +681,7 @@ async fn probe_domain(
|
|||
// of after them. A host that drops the TCP side spends one timeout per TCP
|
||||
// step in series; the UDP probe spends its own window alongside them, and the
|
||||
// column ticks from inside the task (`Ticks`).
|
||||
let quic = if applicable {
|
||||
Some(tokio::spawn({
|
||||
let domain = domain.clone();
|
||||
let cfg = Arc::clone(cfg);
|
||||
let sem = Arc::clone(sem);
|
||||
let ticks = ticks.clone();
|
||||
async move {
|
||||
let _permit = crate::probe::permit(&sem).await;
|
||||
let check = crate::probe::quic::check_domain_quic(&domain, target, &cfg).await;
|
||||
ticks.fire(&ticks.quic);
|
||||
check
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
// The endpoint serves no HTTP/3, so no Initial goes out and the column
|
||||
// does not count this row: the cell is the dash and the tick is spent
|
||||
// here rather than by a probe that would have nothing to answer.
|
||||
entry.quic = crate::probe::quic::QuicCheck::unsupported();
|
||||
ticks.fire(&ticks.quic);
|
||||
None
|
||||
};
|
||||
let quic = start_quic(&domain, target, applicable, cfg, sem, ticks, &mut entry);
|
||||
entry.t13 = {
|
||||
let _permit = crate::probe::permit(sem).await;
|
||||
check_domain_tls(&domain, target, false, cfg).await
|
||||
|
|
@ -725,6 +705,39 @@ async fn probe_domain(
|
|||
entry
|
||||
}
|
||||
|
||||
/// The row's QUIC step: an Initial beside the row's TCP probes when the column
|
||||
/// counts the row, the dash when the endpoint serves no HTTP/3.
|
||||
///
|
||||
/// The tick belongs to the counted rows alone, which is why the decision lives
|
||||
/// in one place: the column's total is the applicable rows, and a dashed row
|
||||
/// that moved the counter is what made a 35-domain run print `QUIC 35/21`.
|
||||
fn start_quic(
|
||||
domain: &str,
|
||||
target: IpAddr,
|
||||
applicable: bool,
|
||||
cfg: &Arc<AppConfig>,
|
||||
sem: &Arc<Semaphore>,
|
||||
ticks: &Ticks,
|
||||
entry: &mut DomainEntry,
|
||||
) -> Option<tokio::task::JoinHandle<crate::probe::quic::QuicCheck>> {
|
||||
if !applicable {
|
||||
entry.quic = crate::probe::quic::QuicCheck::unsupported();
|
||||
return None;
|
||||
}
|
||||
Some(tokio::spawn({
|
||||
let domain = domain.to_string();
|
||||
let cfg = Arc::clone(cfg);
|
||||
let sem = Arc::clone(sem);
|
||||
let ticks = ticks.clone();
|
||||
async move {
|
||||
let _permit = crate::probe::permit(&sem).await;
|
||||
let check = crate::probe::quic::check_domain_quic(&domain, target, &cfg).await;
|
||||
ticks.fire(&ticks.quic);
|
||||
check
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
/// Silently collects provider stub IPs: queries the configured UDP resolvers (2 s
|
||||
/// timeout each, stopping at the first that answers) and keeps the IPs returned
|
||||
/// for at least `max(dns_stub_threshold, 2)` distinct domains.
|
||||
|
|
@ -962,6 +975,58 @@ mod tests {
|
|||
assert_eq!(fake_ip_type(&"8.8.8.8".parse().unwrap()), FakeIpType::Clean);
|
||||
}
|
||||
|
||||
/// A row the QUIC column dashes is not one of its units: the column's total
|
||||
/// is the rows whose endpoint serves HTTP/3, so a tick fired for a dashed row
|
||||
/// is what made a 35-domain run print `QUIC 35/21`. Regression: the dashed
|
||||
/// branch ticked, and the counter ran past its total by the number of
|
||||
/// `quic_unsupported.txt` rows in the list.
|
||||
#[test]
|
||||
fn the_dashed_row_does_not_move_the_quic_counter() {
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
let ticked = Arc::new(AtomicUsize::new(0));
|
||||
let counter = Arc::clone(&ticked);
|
||||
let phases = PhaseProgress {
|
||||
on_phase: Arc::new(move |phase: crate::PhaseId, _total: usize| {
|
||||
let counter = Arc::clone(&counter);
|
||||
Arc::new(move || {
|
||||
if phase == crate::PhaseId::DomainQuic {
|
||||
counter.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
})
|
||||
}),
|
||||
on_blocks: Arc::new(|_, _| Arc::new(|_| {})),
|
||||
};
|
||||
// The whole run is this one row, and the column counts none of it.
|
||||
let ticks = Ticks::declare(Some(&phases), 1, 0);
|
||||
let mut entry = entry_for(
|
||||
"www.canva.com",
|
||||
Some("203.0.113.7".parse().unwrap()),
|
||||
false,
|
||||
&HashSet::new(),
|
||||
);
|
||||
let cfg = Arc::new(AppConfig::default());
|
||||
let sem = Arc::new(Semaphore::new(1));
|
||||
|
||||
let started = start_quic(
|
||||
"www.canva.com",
|
||||
"203.0.113.7".parse().unwrap(),
|
||||
false,
|
||||
&cfg,
|
||||
&sem,
|
||||
&ticks,
|
||||
&mut entry,
|
||||
);
|
||||
|
||||
assert!(started.is_none(), "a dashed row starts no Initial");
|
||||
assert_eq!(entry.quic.status, DpiStatus::QuicUnsupported);
|
||||
assert_eq!(
|
||||
ticked.load(Ordering::Relaxed),
|
||||
0,
|
||||
"the dash is not a unit of the QUIC column"
|
||||
);
|
||||
}
|
||||
|
||||
/// The dash is decided before any probe goes out: the list holds hosts, a row
|
||||
/// may hold a URL path (`domains.txt` does for `x.com`), and DNS names are
|
||||
/// case-insensitive.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue