diff --git a/src/main.rs b/src/main.rs index 7bc89f1..e8b6693 100644 --- a/src/main.rs +++ b/src/main.rs @@ -118,7 +118,11 @@ struct SpeedArgs { #[arg(long, default_value_t = 10_000_000)] bytes: u64, - /// Keep only the best N nodes. 0 means keep all. + /// Reject IPs slower than this (Mbps). 0 = keep all. + #[arg(long = "min", default_value_t = 0.0)] + min_speed: f64, + + /// Keep only the best N results. 0 means keep all. #[arg(short = 'p', long, default_value_t = 0)] top: usize, @@ -394,6 +398,7 @@ async fn run_speed(args: SpeedArgs) -> Result<()> { args.concurrency.max(1), Duration::from_secs_f64(args.timeout), args.bytes, + args.min_speed, |p| { bar.set_position(p.done as u64); match p.speed_mbps { diff --git a/src/speed.rs b/src/speed.rs index 199388a..fe9b81f 100644 --- a/src/speed.rs +++ b/src/speed.rs @@ -37,14 +37,16 @@ pub fn bucket(speed_mbps: f64) -> i64 { speed_mbps.floor() as i64 } -/// Speed-test every input IP, carrying its latency through, and return -/// successes ranked best-first (speed bucket desc, then latency asc). +/// Speed-test every input IP, carrying its latency through. Keeps results at +/// or above `min_speed` Mbps (zero = disabled), ranked best-first (speed +/// bucket desc, then latency asc). pub async fn run( node: &VlessNode, inputs: &[(IpAddr, Duration)], concurrency: usize, timeout: Duration, limit_bytes: u64, + min_speed: f64, mut on_progress: impl FnMut(Probed), ) -> Vec { let total = inputs.len(); @@ -58,11 +60,15 @@ pub async fn run( while let Some((ip, latency, outcome)) = stream.next().await { done += 1; - let speed = outcome.ok(); - if let Some(mbps) = speed { - results.push(SpeedResult { ip, latency, speed_mbps: mbps }); - } - on_progress(Probed { ip, speed_mbps: speed, done, total }); + // Kept only if it succeeded and meets the optional min-speed floor. + let kept = match outcome { + Ok(mbps) if min_speed <= 0.0 || mbps >= min_speed => { + results.push(SpeedResult { ip, latency, speed_mbps: mbps }); + Some(mbps) + } + _ => None, + }; + on_progress(Probed { ip, speed_mbps: kept, done, total }); } results.sort_by(|a, b| {