use ftr::{Ftr, ProbeProtocol, SocketMode, TracerouteConfigBuilder, TracerouteError};
#[tokio::main]
async fn main() {
println!("ftr Error Handling Example\n");
let ftr = Ftr::new();
println!("1. Testing permission handling:");
let config = TracerouteConfigBuilder::new()
.target("google.com")
.socket_mode(SocketMode::Raw) .build()
.unwrap();
match ftr.trace_with_config(config).await {
Ok(result) => {
println!(" Traceroute succeeded! Found {} hops", result.hop_count());
}
Err(TracerouteError::InsufficientPermissions {
required,
suggestion,
}) => {
println!(" Permission error detected!");
println!(" - Required: {}", required);
println!(" - Suggestion: {}", suggestion);
println!(" - Action: Could retry with UDP mode or prompt for sudo");
}
Err(e) => {
println!(" Other error: {}", e);
}
}
println!("\n2. Testing unimplemented feature handling:");
let config = TracerouteConfigBuilder::new()
.target("google.com")
.protocol(ProbeProtocol::Tcp)
.build()
.unwrap();
match ftr.trace_with_config(config).await {
Ok(_) => println!(" Unexpected success!"),
Err(TracerouteError::NotImplemented { feature }) => {
println!(" Feature not implemented: {}", feature);
println!(" - Action: Could fall back to ICMP or UDP protocol");
}
Err(e) => println!(" Other error: {}", e),
}
println!("\n3. Testing IPv6 handling:");
match ftr.trace("2001:4860:4860::8888").await {
Ok(_) => println!(" Unexpected success!"),
Err(TracerouteError::Ipv6NotSupported) => {
println!(" IPv6 not supported yet");
println!(" - Action: Could resolve to IPv4 or inform user");
}
Err(e) => println!(" Other error: {}", e),
}
println!("\n4. Testing DNS resolution error handling:");
match ftr.trace("this-definitely-does-not-exist.invalid").await {
Ok(_) => println!(" Unexpected success!"),
Err(TracerouteError::ResolutionError(msg)) => {
println!(" DNS resolution failed: {}", msg);
println!(" - Action: Could suggest checking network or spelling");
}
Err(e) => println!(" Other error: {}", e),
}
println!("\n5. Testing configuration error handling:");
let config_result = TracerouteConfigBuilder::new()
.target("google.com")
.start_ttl(10)
.max_hops(5) .build();
match config_result {
Ok(_) => println!(" Unexpected success!"),
Err(msg) => {
println!(" Configuration error: {}", msg);
println!(" - Action: Show validation rules to user");
}
}
println!("\n6. Demonstrating automatic fallback:");
let target = "google.com";
let modes = vec![
(SocketMode::Raw, "Raw socket (fastest)"),
(SocketMode::Dgram, "ICMP datagram"),
];
let mut success = false;
for (mode, desc) in modes {
println!(" Trying {}...", desc);
let config = TracerouteConfigBuilder::new()
.target(target)
.socket_mode(mode)
.max_hops(10)
.build()
.unwrap();
match ftr.trace_with_config(config).await {
Ok(result) => {
println!(
" ✓ Success with {}! Found {} hops",
desc,
result.hop_count()
);
success = true;
break;
}
Err(TracerouteError::InsufficientPermissions { .. }) => {
println!(" ✗ Insufficient permissions for {}", desc);
}
Err(e) => {
println!(" ✗ Failed with {}: {}", desc, e);
}
}
}
if !success {
println!(" Trying UDP mode (no special permissions)...");
let config = TracerouteConfigBuilder::new()
.target(target)
.protocol(ProbeProtocol::Udp)
.max_hops(10)
.build()
.unwrap();
match ftr.trace_with_config(config).await {
Ok(result) => {
println!(" ✓ Success with UDP! Found {} hops", result.hop_count());
}
Err(e) => {
println!(" ✗ All methods failed. Last error: {}", e);
}
}
}
println!("\nError handling example complete!");
}