diff --git a/Cargo.lock b/Cargo.lock index f190c81..1dccf59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -444,7 +444,7 @@ dependencies = [ [[package]] name = "netkraken" -version = "0.1.6" +version = "0.1.7" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index af8c494..4cbea87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "netkraken" -version = "0.1.6" +version = "0.1.7" edition = "2021" [[bin]] diff --git a/src/core/common.rs b/src/core/common.rs index ed88cad..84c8e49 100644 --- a/src/core/common.rs +++ b/src/core/common.rs @@ -173,10 +173,10 @@ impl Tabled for ClientResult { std::borrow::Cow::Borrowed("Sent"), std::borrow::Cow::Borrowed("Received"), std::borrow::Cow::Borrowed("Lost"), - std::borrow::Cow::Borrowed("Loss %"), - std::borrow::Cow::Borrowed("Min"), - std::borrow::Cow::Borrowed("Max"), - std::borrow::Cow::Borrowed("Avg"), + std::borrow::Cow::Borrowed("Loss (%)"), + std::borrow::Cow::Borrowed("Min (ms)"), + std::borrow::Cow::Borrowed("Max (ms)"), + std::borrow::Cow::Borrowed("Avg (ms)"), ] } } diff --git a/src/tcp/client.rs b/src/tcp/client.rs index ac93c79..8526e8d 100644 --- a/src/tcp/client.rs +++ b/src/tcp/client.rs @@ -16,11 +16,10 @@ use crate::core::konst::{BIND_ADDR, BIND_PORT, BUFFER_SIZE}; use crate::util::dns::resolve_host; use crate::util::handler::{io_error_switch_handler, loop_handler, output_handler2}; use crate::util::message::{ - client_result_msg, client_summary_msg, client_summary_table_msg, ping_header_msg, - resolved_ips_msg, + client_result_msg, client_summary_table_msg, ping_header_msg, resolved_ips_msg, }; use crate::util::parser::parse_ipaddr; -use crate::util::result::get_results_map; +use crate::util::result::{client_summary_result, get_results_map}; use crate::util::time::{calc_connect_ms, time_now_us}; #[derive(Debug)] @@ -143,7 +142,7 @@ impl TcpClient { send_count, latencies, }; - let summary_msg = client_summary_msg(&addr, ConnectMethod::TCP, client_summary); + let summary_msg = client_summary_result(&addr, ConnectMethod::TCP, client_summary); // println!("{}", summary_msg); client_results.push(summary_msg) } diff --git a/src/udp/client.rs b/src/udp/client.rs index caac0dd..3050bbf 100644 --- a/src/udp/client.rs +++ b/src/udp/client.rs @@ -16,11 +16,10 @@ use crate::core::konst::{BIND_ADDR, BIND_PORT, BUFFER_SIZE, MAX_PACKET_SIZE, PIN use crate::util::dns::resolve_host; use crate::util::handler::{io_error_switch_handler, loop_handler, output_handler2}; use crate::util::message::{ - client_result_msg, client_summary_msg, client_summary_table_msg, ping_header_msg, - resolved_ips_msg, + client_result_msg, client_summary_table_msg, ping_header_msg, resolved_ips_msg, }; use crate::util::parser::parse_ipaddr; -use crate::util::result::get_results_map; +use crate::util::result::{client_summary_result, get_results_map}; use crate::util::time::{calc_connect_ms, time_now_us}; pub struct UdpClient { @@ -134,8 +133,9 @@ impl UdpClient { send_count, latencies, }; - let summary_msg = client_summary_msg(&addr, ConnectMethod::UDP, client_summary); - client_results.push(summary_msg) + let client_summary = + client_summary_result(&addr, ConnectMethod::UDP, client_summary); + client_results.push(client_summary) } } diff --git a/src/util/message.rs b/src/util/message.rs index eedd37a..5e6f5dd 100644 --- a/src/util/message.rs +++ b/src/util/message.rs @@ -1,11 +1,10 @@ use std::net::SocketAddr; use tabled::settings::Panel; +use tabled::settings::{object::Rows, Alignment, Margin, Modify, Span, Style}; use tabled::Table; -use crate::core::common::{ - ClientResult, ClientSummary, ConnectMethod, ConnectRecord, ConnectResult, HostRecord, -}; +use crate::core::common::{ClientResult, ConnectMethod, ConnectRecord, ConnectResult, HostRecord}; /// Return the CLI header message pub fn cli_header_msg() -> String { @@ -85,47 +84,6 @@ pub fn client_result_msg(record: &ConnectRecord) -> String { } } -/// Returns a client connection summary message -pub fn client_summary_msg( - destination: &String, - protocol: ConnectMethod, - client_summary: ClientSummary, -) -> ClientResult { - let mut min: f64 = 0.0; - let mut max: f64 = 0.0; - let mut avg: f64 = 0.0; - let mut latencies = client_summary.latencies; - - // Filetr our any f64::NAN - latencies.retain(|f| !f.is_nan()); - latencies.retain(|f| f > &0.0); - - // Sort lowest to highest - // TODO: Fix this unwrap - latencies.sort_by(|a, b| a.partial_cmp(b).unwrap()); - - if !latencies.is_empty() { - min = *latencies.first().unwrap_or(&0.0); - max = *latencies.last().unwrap_or(&0.0); - let sum: f64 = latencies.iter().sum(); - avg = sum / latencies.len() as f64; - } - - let received_count = latencies.len() as u16; - - ClientResult { - destination: destination.to_owned(), - protocol, - sent: client_summary.send_count, - received: received_count, - lost: client_summary.send_count - received_count, - loss_percent: calc_loss_percent(client_summary.send_count, received_count), - min, - max, - avg, - } -} - pub fn client_summary_table_msg( dst_host: &String, dst_port: u16, @@ -133,14 +91,22 @@ pub fn client_summary_table_msg( client_results: &Vec, ) -> String { let header = format!( - "Statistics for {} connection to {}:{}", + "--- Statistics for {} connection to {}:{} ---", connect_method.to_string().to_uppercase(), dst_host, dst_port, ); - let mut table = Table::new(client_results); - table.with(Panel::header(header)); - table.to_string() + Table::new(client_results) + // table + .with(Style::ascii()) + .with(Margin::new(0, 0, 1, 1)) + .with(Panel::header(header)) + .with( + Modify::new(Rows::first()) + .with(Span::column(9)) + .with(Alignment::center()), + ) + .to_string() } /// Returns a server connection summary message @@ -174,13 +140,6 @@ pub fn server_conn_success_msg( } } -/// Calculate the percentage of loss between the -/// amount of pings sent and the amount received -pub fn calc_loss_percent(sent: u16, received: u16) -> f64 { - let percent = (sent as f64 - received as f64) / sent as f64; - percent * 100.0 -} - #[cfg(test)] mod tests { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; @@ -259,13 +218,6 @@ mod tests { assert_eq!(msg, "Connecting to 198.51.100.1:443 via TCP"); } - #[test] - fn calc_loss_percent_is_expected() { - let loss = calc_loss_percent(100, 99); - - assert_eq!(loss, 1.0); - } - #[test] fn cli_header_msg_is_expected() { let msg = cli_header_msg(); @@ -307,13 +259,14 @@ mod tests { &vec![client_results], ); - let expected = "+--------------+----------+------+----------+------+--------+---------+---------+---------+\n\ - | Statistics for TCP connection to stuff.things:443 |\n\ - +--------------+----------+------+----------+------+--------+---------+---------+---------+\n\ - | Destination | Protocol | Sent | Received | Lost | Loss % | Min | Max | Avg |\n\ - +--------------+----------+------+----------+------+--------+---------+---------+---------+\n\ - | 198.51.100.1 | TCP | 4 | 4 | 0 | 0.00 | 234.000 | 254.000 | 243.000 |\n\ - +--------------+----------+------+----------+------+--------+---------+---------+---------+"; + let expected = " \n\ + +--------------+----------+------+----------+------+----------+----------+----------+----------+\n\ + | --- Statistics for TCP connection to stuff.things:443 --- |\n\ + +--------------+----------+------+----------+------+----------+----------+----------+----------+\n\ + | Destination | Protocol | Sent | Received | Lost | Loss (%) | Min (ms) | Max (ms) | Avg (ms) |\n\ + +--------------+----------+------+----------+------+----------+----------+----------+----------+\n\ + | 198.51.100.1 | TCP | 4 | 4 | 0 | 0.00 | 234.000 | 254.000 | 243.000 |\n\ + +--------------+----------+------+----------+------+----------+----------+----------+----------+\n "; assert_eq!(summary_table, expected); } diff --git a/src/util/result.rs b/src/util/result.rs index 6032d40..0b8c1ef 100644 --- a/src/util/result.rs +++ b/src/util/result.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use crate::core::common::HostRecord; +use crate::core::common::{ClientResult, ClientSummary, ConnectMethod, HostRecord}; /// Return a results_map hash from a Vec of HostRecords pub fn get_results_map(host_records: &[HostRecord]) -> HashMap>> { @@ -28,6 +28,54 @@ pub fn get_results_map(host_records: &[HostRecord]) -> HashMap ClientResult { + let mut min: f64 = 0.0; + let mut max: f64 = 0.0; + let mut avg: f64 = 0.0; + let mut latencies = client_summary.latencies; + + // Filetr our any f64::NAN + latencies.retain(|f| !f.is_nan()); + latencies.retain(|f| f > &0.0); + + // Sort lowest to highest + // TODO: Fix this unwrap + latencies.sort_by(|a, b| a.partial_cmp(b).unwrap()); + + if !latencies.is_empty() { + min = *latencies.first().unwrap_or(&0.0); + max = *latencies.last().unwrap_or(&0.0); + let sum: f64 = latencies.iter().sum(); + avg = sum / latencies.len() as f64; + } + + let received_count = latencies.len() as u16; + + ClientResult { + destination: destination.to_owned(), + protocol, + sent: client_summary.send_count, + received: received_count, + lost: client_summary.send_count - received_count, + loss_percent: calc_loss_percent(client_summary.send_count, received_count), + min, + max, + avg, + } +} + +/// Calculate the percentage of loss between the +/// amount of pings sent and the amount received +pub fn calc_loss_percent(sent: u16, received: u16) -> f64 { + let percent = (sent as f64 - received as f64) / sent as f64; + percent * 100.0 +} + #[cfg(test)] mod tests { use std::collections::HashMap; @@ -85,4 +133,11 @@ mod tests { assert_eq!(results_map, expected); } + + #[test] + fn calc_loss_percent_is_expected() { + let loss = calc_loss_percent(100, 99); + + assert_eq!(loss, 1.0); + } }