Add: per-hop and rdns for probe trace

This commit is contained in:
DaZuo0122
2026-01-17 12:51:41 +08:00
parent 7e87edb411
commit c538e31174
9 changed files with 809 additions and 73 deletions

View File

@@ -238,6 +238,8 @@ struct ProbeTraceArgs {
target: String,
#[arg(long, default_value_t = 30)]
max_hops: u8,
#[arg(long, default_value_t = 3)]
per_hop: u32,
#[arg(long, default_value_t = 800)]
timeout_ms: u64,
#[arg(long)]
@@ -245,6 +247,8 @@ struct ProbeTraceArgs {
#[arg(long, default_value_t = 33434)]
port: u16,
#[arg(long)]
rdns: bool,
#[arg(long)]
no_geoip: bool,
}
@@ -1076,9 +1080,25 @@ async fn handle_probe_trace(cli: &Cli, args: ProbeTraceArgs) -> i32 {
};
let result = if args.udp {
wtfnet_probe::udp_trace(&host, port, args.max_hops, args.timeout_ms).await
wtfnet_probe::udp_trace(
&host,
port,
args.max_hops,
args.timeout_ms,
args.per_hop,
args.rdns,
)
.await
} else {
wtfnet_probe::tcp_trace(&host, port, args.max_hops, args.timeout_ms).await
wtfnet_probe::tcp_trace(
&host,
port,
args.max_hops,
args.timeout_ms,
args.per_hop,
args.rdns,
)
.await
};
match result {
@@ -1088,7 +1108,30 @@ async fn handle_probe_trace(cli: &Cli, args: ProbeTraceArgs) -> i32 {
}
if cli.json {
let meta = Meta::new("wtfnet", env!("CARGO_PKG_VERSION"), false);
let command = CommandInfo::new("probe trace", vec![args.target]);
let mut command_args = vec![args.target];
if args.udp {
command_args.push("--udp".to_string());
}
if args.rdns {
command_args.push("--rdns".to_string());
}
if args.per_hop != 3 {
command_args.push("--per-hop".to_string());
command_args.push(args.per_hop.to_string());
}
if args.max_hops != 30 {
command_args.push("--max-hops".to_string());
command_args.push(args.max_hops.to_string());
}
if args.timeout_ms != 800 {
command_args.push("--timeout-ms".to_string());
command_args.push(args.timeout_ms.to_string());
}
if args.udp && args.port != 33434 {
command_args.push("--port".to_string());
command_args.push(args.port.to_string());
}
let command = CommandInfo::new("probe trace", command_args);
let envelope = CommandEnvelope::new(meta, command, report);
emit_json(cli, &envelope)
} else {
@@ -1102,17 +1145,30 @@ async fn handle_probe_trace(cli: &Cli, args: ProbeTraceArgs) -> i32 {
}
for hop in report.hops {
let geoip = hop.geoip.as_ref().map(format_geoip);
let addr = hop.addr.unwrap_or_else(|| "*".to_string());
let rtt = if let (Some(min), Some(avg), Some(max)) =
(hop.min_ms, hop.avg_ms, hop.max_ms)
{
format!("{min}/{avg:.1}/{max}ms")
} else {
"-".to_string()
};
let rdns = hop
.rdns
.as_ref()
.map(|value| format!(" rdns={value}"))
.unwrap_or_default();
let note = hop
.note
.as_ref()
.map(|value| format!(" note={value}"))
.unwrap_or_default();
let geoip = geoip
.map(|value| format!(" geoip={value}"))
.unwrap_or_default();
println!(
"ttl={} addr={} rtt={}ms {}{}",
hop.ttl,
hop.addr.unwrap_or_else(|| "*".to_string()),
hop.rtt_ms
.map(|v| v.to_string())
.unwrap_or_else(|| "-".to_string()),
hop.note.unwrap_or_default(),
geoip
.map(|value| format!(" geoip={value}"))
.unwrap_or_default()
"ttl={} addr={} loss={:.1}% rtt(min/avg/max)={}{}{}{}",
hop.ttl, addr, hop.loss_pct, rtt, rdns, note, geoip
);
}
ExitKind::Ok.code()