mirror of
https://github.com/imsnif/bandwhich.git
synced 2026-02-09 01:59:18 +08:00
Merge pull request #435 from imsnif/cleanup
Minor cleanup and optimisations
This commit is contained in:
@@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
|||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
* Add build optimizations for release binary #434 - @pando85
|
* Add build optimizations for release binary #434 - @pando85
|
||||||
|
* Minor cleanup and optimisations #435 - @cyqsimon
|
||||||
|
|
||||||
## [0.23.1] - 2024-10-09
|
## [0.23.1] - 2024-10-09
|
||||||
|
|
||||||
|
|||||||
@@ -99,12 +99,15 @@ impl Layout<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&self, frame: &mut Frame, rect: Rect, ui_offset: usize) {
|
pub fn render(&self, frame: &mut Frame, rect: Rect, table_cycle_offset: usize) {
|
||||||
let (top, app, bottom) = top_app_and_bottom_split(rect);
|
let (top, app, bottom) = top_app_and_bottom_split(rect);
|
||||||
let layout_slots = self.build_layout(app);
|
let layout_slots = self.build_layout(app);
|
||||||
for i in 0..layout_slots.len() {
|
for i in 0..layout_slots.len() {
|
||||||
if let Some(rect) = layout_slots.get(i) {
|
if let Some(rect) = layout_slots.get(i) {
|
||||||
if let Some(child) = self.children.get((i + ui_offset) % self.children.len()) {
|
if let Some(child) = self
|
||||||
|
.children
|
||||||
|
.get((i + table_cycle_offset) % self.children.len())
|
||||||
|
{
|
||||||
child.render(frame, *rect);
|
child.render(frame, *rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ where
|
|||||||
state.interface_name.clone_from(&opts.interface);
|
state.interface_name.clone_from(&opts.interface);
|
||||||
state.unit_family = opts.render_opts.unit_family.into();
|
state.unit_family = opts.render_opts.unit_family.into();
|
||||||
state.cumulative_mode = opts.render_opts.total_utilization;
|
state.cumulative_mode = opts.render_opts.total_utilization;
|
||||||
|
state.show_dns = opts.show_dns;
|
||||||
state
|
state
|
||||||
};
|
};
|
||||||
Ui {
|
Ui {
|
||||||
@@ -45,17 +46,17 @@ where
|
|||||||
opts: opts.render_opts,
|
opts: opts.render_opts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn output_text(&mut self, write_to_stdout: &mut (dyn FnMut(String) + Send)) {
|
pub fn output_text(&mut self, write_to_stdout: &mut (dyn FnMut(&str) + Send)) {
|
||||||
let state = &self.state;
|
let state = &self.state;
|
||||||
let ip_to_host = &self.ip_to_host;
|
let ip_to_host = &self.ip_to_host;
|
||||||
let local_time: DateTime<Local> = Local::now();
|
let local_time: DateTime<Local> = Local::now();
|
||||||
let timestamp = local_time.timestamp();
|
let timestamp = local_time.timestamp();
|
||||||
let mut no_traffic = true;
|
let mut no_traffic = true;
|
||||||
|
|
||||||
let output_process_data = |write_to_stdout: &mut (dyn FnMut(String) + Send),
|
let output_process_data = |write_to_stdout: &mut (dyn FnMut(&str) + Send),
|
||||||
no_traffic: &mut bool| {
|
no_traffic: &mut bool| {
|
||||||
for (proc_info, process_network_data) in &state.processes {
|
for (proc_info, process_network_data) in &state.processes {
|
||||||
write_to_stdout(format!(
|
write_to_stdout(&format!(
|
||||||
"process: <{timestamp}> \"{}\" up/down Bps: {}/{} connections: {}",
|
"process: <{timestamp}> \"{}\" up/down Bps: {}/{} connections: {}",
|
||||||
proc_info.name,
|
proc_info.name,
|
||||||
process_network_data.total_bytes_uploaded,
|
process_network_data.total_bytes_uploaded,
|
||||||
@@ -67,9 +68,9 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
let output_connections_data =
|
let output_connections_data =
|
||||||
|write_to_stdout: &mut (dyn FnMut(String) + Send), no_traffic: &mut bool| {
|
|write_to_stdout: &mut (dyn FnMut(&str) + Send), no_traffic: &mut bool| {
|
||||||
for (connection, connection_network_data) in &state.connections {
|
for (connection, connection_network_data) in &state.connections {
|
||||||
write_to_stdout(format!(
|
write_to_stdout(&format!(
|
||||||
"connection: <{timestamp}> {} up/down Bps: {}/{} process: \"{}\"",
|
"connection: <{timestamp}> {} up/down Bps: {}/{} process: \"{}\"",
|
||||||
display_connection_string(
|
display_connection_string(
|
||||||
connection,
|
connection,
|
||||||
@@ -84,10 +85,10 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let output_adressess_data = |write_to_stdout: &mut (dyn FnMut(String) + Send),
|
let output_adressess_data = |write_to_stdout: &mut (dyn FnMut(&str) + Send),
|
||||||
no_traffic: &mut bool| {
|
no_traffic: &mut bool| {
|
||||||
for (remote_address, remote_address_network_data) in &state.remote_addresses {
|
for (remote_address, remote_address_network_data) in &state.remote_addresses {
|
||||||
write_to_stdout(format!(
|
write_to_stdout(&format!(
|
||||||
"remote_address: <{timestamp}> {} up/down Bps: {}/{} connections: {}",
|
"remote_address: <{timestamp}> {} up/down Bps: {}/{} connections: {}",
|
||||||
display_ip_or_host(*remote_address, ip_to_host),
|
display_ip_or_host(*remote_address, ip_to_host),
|
||||||
remote_address_network_data.total_bytes_uploaded,
|
remote_address_network_data.total_bytes_uploaded,
|
||||||
@@ -99,7 +100,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
// header
|
// header
|
||||||
write_to_stdout("Refreshing:".into());
|
write_to_stdout("Refreshing:");
|
||||||
|
|
||||||
// body1
|
// body1
|
||||||
if self.opts.processes {
|
if self.opts.processes {
|
||||||
@@ -119,14 +120,14 @@ where
|
|||||||
|
|
||||||
// body2: In case no traffic is detected
|
// body2: In case no traffic is detected
|
||||||
if no_traffic {
|
if no_traffic {
|
||||||
write_to_stdout("<NO TRAFFIC>".into());
|
write_to_stdout("<NO TRAFFIC>");
|
||||||
}
|
}
|
||||||
|
|
||||||
// footer
|
// footer
|
||||||
write_to_stdout("".into());
|
write_to_stdout("");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&mut self, paused: bool, show_dns: bool, elapsed_time: Duration, ui_offset: usize) {
|
pub fn draw(&mut self, paused: bool, elapsed_time: Duration, table_cycle_offset: usize) {
|
||||||
let layout = Layout {
|
let layout = Layout {
|
||||||
header: HeaderDetails {
|
header: HeaderDetails {
|
||||||
state: &self.state,
|
state: &self.state,
|
||||||
@@ -134,10 +135,13 @@ where
|
|||||||
paused,
|
paused,
|
||||||
},
|
},
|
||||||
children: self.get_tables_to_display(),
|
children: self.get_tables_to_display(),
|
||||||
footer: HelpText { paused, show_dns },
|
footer: HelpText {
|
||||||
|
paused,
|
||||||
|
show_dns: self.state.show_dns,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
self.terminal
|
self.terminal
|
||||||
.draw(|frame| layout.render(frame, frame.area(), ui_offset))
|
.draw(|frame| layout.render(frame, frame.area(), table_cycle_offset))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ pub struct UIState {
|
|||||||
pub total_bytes_downloaded: u128,
|
pub total_bytes_downloaded: u128,
|
||||||
pub total_bytes_uploaded: u128,
|
pub total_bytes_uploaded: u128,
|
||||||
pub cumulative_mode: bool,
|
pub cumulative_mode: bool,
|
||||||
|
pub show_dns: bool,
|
||||||
pub unit_family: BandwidthUnitFamily,
|
pub unit_family: BandwidthUnitFamily,
|
||||||
pub utilization_data: VecDeque<UtilizationData>,
|
pub utilization_data: VecDeque<UtilizationData>,
|
||||||
pub processes_map: HashMap<ProcessInfo, NetworkData>,
|
pub processes_map: HashMap<ProcessInfo, NetworkData>,
|
||||||
|
|||||||
24
src/main.rs
24
src/main.rs
@@ -82,7 +82,7 @@ pub struct OsInputOutput {
|
|||||||
pub get_open_sockets: fn() -> OpenSockets,
|
pub get_open_sockets: fn() -> OpenSockets,
|
||||||
pub terminal_events: Box<dyn Iterator<Item = Event> + Send>,
|
pub terminal_events: Box<dyn Iterator<Item = Event> + Send>,
|
||||||
pub dns_client: Option<dns::Client>,
|
pub dns_client: Option<dns::Client>,
|
||||||
pub write_to_stdout: Box<dyn FnMut(String) + Send>,
|
pub write_to_stdout: Box<dyn FnMut(&str) + Send>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start<B>(terminal_backend: B, os_input: OsInputOutput, opts: Opt)
|
pub fn start<B>(terminal_backend: B, os_input: OsInputOutput, opts: Opt)
|
||||||
@@ -93,8 +93,7 @@ where
|
|||||||
let paused = Arc::new(AtomicBool::new(false));
|
let paused = Arc::new(AtomicBool::new(false));
|
||||||
let last_start_time = Arc::new(RwLock::new(Instant::now()));
|
let last_start_time = Arc::new(RwLock::new(Instant::now()));
|
||||||
let cumulative_time = Arc::new(RwLock::new(Duration::new(0, 0)));
|
let cumulative_time = Arc::new(RwLock::new(Duration::new(0, 0)));
|
||||||
let ui_offset = Arc::new(AtomicUsize::new(0));
|
let table_cycle_offset = Arc::new(AtomicUsize::new(0));
|
||||||
let dns_shown = opts.show_dns;
|
|
||||||
|
|
||||||
let mut active_threads = vec![];
|
let mut active_threads = vec![];
|
||||||
|
|
||||||
@@ -113,7 +112,7 @@ where
|
|||||||
.spawn({
|
.spawn({
|
||||||
let running = running.clone();
|
let running = running.clone();
|
||||||
let paused = paused.clone();
|
let paused = paused.clone();
|
||||||
let ui_offset = ui_offset.clone();
|
let table_cycle_offset = table_cycle_offset.clone();
|
||||||
|
|
||||||
let network_utilization = network_utilization.clone();
|
let network_utilization = network_utilization.clone();
|
||||||
let last_start_time = last_start_time.clone();
|
let last_start_time = last_start_time.clone();
|
||||||
@@ -123,7 +122,7 @@ where
|
|||||||
move || {
|
move || {
|
||||||
while running.load(Ordering::Acquire) {
|
while running.load(Ordering::Acquire) {
|
||||||
let render_start_time = Instant::now();
|
let render_start_time = Instant::now();
|
||||||
let utilization = { network_utilization.lock().unwrap().clone_and_reset() };
|
let utilization = network_utilization.lock().unwrap().clone_and_reset();
|
||||||
let OpenSockets { sockets_to_procs } = get_open_sockets();
|
let OpenSockets { sockets_to_procs } = get_open_sockets();
|
||||||
let mut ip_to_host = IpTable::new();
|
let mut ip_to_host = IpTable::new();
|
||||||
if let Some(dns_client) = dns_client.as_mut() {
|
if let Some(dns_client) = dns_client.as_mut() {
|
||||||
@@ -139,7 +138,7 @@ where
|
|||||||
{
|
{
|
||||||
let mut ui = ui.lock().unwrap();
|
let mut ui = ui.lock().unwrap();
|
||||||
let paused = paused.load(Ordering::SeqCst);
|
let paused = paused.load(Ordering::SeqCst);
|
||||||
let ui_offset = ui_offset.load(Ordering::SeqCst);
|
let table_cycle_offset = table_cycle_offset.load(Ordering::SeqCst);
|
||||||
if !paused {
|
if !paused {
|
||||||
ui.update_state(sockets_to_procs, utilization, ip_to_host);
|
ui.update_state(sockets_to_procs, utilization, ip_to_host);
|
||||||
}
|
}
|
||||||
@@ -152,7 +151,7 @@ where
|
|||||||
if raw_mode {
|
if raw_mode {
|
||||||
ui.output_text(&mut write_to_stdout);
|
ui.output_text(&mut write_to_stdout);
|
||||||
} else {
|
} else {
|
||||||
ui.draw(paused, dns_shown, elapsed_time, ui_offset);
|
ui.draw(paused, elapsed_time, table_cycle_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let render_duration = render_start_time.elapsed();
|
let render_duration = render_start_time.elapsed();
|
||||||
@@ -183,13 +182,12 @@ where
|
|||||||
let paused = paused.load(Ordering::SeqCst);
|
let paused = paused.load(Ordering::SeqCst);
|
||||||
ui.draw(
|
ui.draw(
|
||||||
paused,
|
paused,
|
||||||
dns_shown,
|
|
||||||
elapsed_time(
|
elapsed_time(
|
||||||
*last_start_time.read().unwrap(),
|
*last_start_time.read().unwrap(),
|
||||||
*cumulative_time.read().unwrap(),
|
*cumulative_time.read().unwrap(),
|
||||||
paused,
|
paused,
|
||||||
),
|
),
|
||||||
ui_offset.load(Ordering::SeqCst),
|
table_cycle_offset.load(Ordering::SeqCst),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Event::Key(KeyEvent {
|
Event::Key(KeyEvent {
|
||||||
@@ -250,9 +248,9 @@ where
|
|||||||
paused,
|
paused,
|
||||||
);
|
);
|
||||||
let table_count = ui.get_table_count();
|
let table_count = ui.get_table_count();
|
||||||
let new = ui_offset.load(Ordering::SeqCst) + 1 % table_count;
|
let new = table_cycle_offset.load(Ordering::SeqCst) + 1 % table_count;
|
||||||
ui_offset.store(new, Ordering::SeqCst);
|
table_cycle_offset.store(new, Ordering::SeqCst);
|
||||||
ui.draw(paused, dns_shown, elapsed_time, new);
|
ui.draw(paused, elapsed_time, new);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
@@ -280,7 +278,7 @@ where
|
|||||||
|
|
||||||
while running.load(Ordering::Acquire) {
|
while running.load(Ordering::Acquire) {
|
||||||
if let Some(segment) = sniffer.next() {
|
if let Some(segment) = sniffer.next() {
|
||||||
network_utilization.lock().unwrap().update(segment);
|
network_utilization.lock().unwrap().ingest(segment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -93,19 +93,19 @@ macro_rules! extract_transport_protocol {
|
|||||||
pub struct Sniffer {
|
pub struct Sniffer {
|
||||||
network_interface: NetworkInterface,
|
network_interface: NetworkInterface,
|
||||||
network_frames: Box<dyn DataLinkReceiver>,
|
network_frames: Box<dyn DataLinkReceiver>,
|
||||||
dns_shown: bool,
|
show_dns: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sniffer {
|
impl Sniffer {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
network_interface: NetworkInterface,
|
network_interface: NetworkInterface,
|
||||||
network_frames: Box<dyn DataLinkReceiver>,
|
network_frames: Box<dyn DataLinkReceiver>,
|
||||||
dns_shown: bool,
|
show_dns: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Sniffer {
|
Sniffer {
|
||||||
network_interface,
|
network_interface,
|
||||||
network_frames,
|
network_frames,
|
||||||
dns_shown,
|
show_dns,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn next(&mut self) -> Option<Segment> {
|
pub fn next(&mut self) -> Option<Segment> {
|
||||||
@@ -138,7 +138,7 @@ impl Sniffer {
|
|||||||
let version = ip_packet.get_version();
|
let version = ip_packet.get_version();
|
||||||
|
|
||||||
match version {
|
match version {
|
||||||
4 => Self::handle_v4(ip_packet, &self.network_interface, self.dns_shown),
|
4 => Self::handle_v4(ip_packet, &self.network_interface, self.show_dns),
|
||||||
6 => Self::handle_v6(
|
6 => Self::handle_v6(
|
||||||
Ipv6Packet::new(&bytes[payload_offset..])?,
|
Ipv6Packet::new(&bytes[payload_offset..])?,
|
||||||
&self.network_interface,
|
&self.network_interface,
|
||||||
@@ -149,7 +149,7 @@ impl Sniffer {
|
|||||||
EtherTypes::Ipv4 => Self::handle_v4(
|
EtherTypes::Ipv4 => Self::handle_v4(
|
||||||
Ipv4Packet::new(pkg.payload())?,
|
Ipv4Packet::new(pkg.payload())?,
|
||||||
&self.network_interface,
|
&self.network_interface,
|
||||||
self.dns_shown,
|
self.show_dns,
|
||||||
),
|
),
|
||||||
EtherTypes::Ipv6 => {
|
EtherTypes::Ipv6 => {
|
||||||
Self::handle_v6(Ipv6Packet::new(pkg.payload())?, &self.network_interface)
|
Self::handle_v6(Ipv6Packet::new(pkg.payload())?, &self.network_interface)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ impl Utilization {
|
|||||||
self.connections.clear();
|
self.connections.clear();
|
||||||
clone
|
clone
|
||||||
}
|
}
|
||||||
pub fn update(&mut self, seg: Segment) {
|
pub fn ingest(&mut self, seg: Segment) {
|
||||||
let total_bandwidth = self
|
let total_bandwidth = self
|
||||||
.connections
|
.connections
|
||||||
.entry(seg.connection)
|
.entry(seg.connection)
|
||||||
|
|||||||
@@ -80,10 +80,10 @@ fn get_interface(interface_name: &str) -> Option<NetworkInterface> {
|
|||||||
.find(|iface| iface.name == interface_name)
|
.find(|iface| iface.name == interface_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_write_to_stdout() -> Box<dyn FnMut(String) + Send> {
|
fn create_write_to_stdout() -> Box<dyn FnMut(&str) + Send> {
|
||||||
let mut stdout = io::stdout();
|
let mut stdout = io::stdout();
|
||||||
Box::new({
|
Box::new({
|
||||||
move |output: String| match writeln!(stdout, "{}", output) {
|
move |output| match writeln!(stdout, "{}", output) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) if e.kind() == ErrorKind::BrokenPipe => {
|
Err(e) if e.kind() == ErrorKind::BrokenPipe => {
|
||||||
// A process that was listening to bandwhich stdout has exited
|
// A process that was listening to bandwhich stdout has exited
|
||||||
|
|||||||
@@ -257,14 +257,14 @@ pub fn os_input_output_factory(
|
|||||||
) -> OsInputOutput {
|
) -> OsInputOutput {
|
||||||
let interfaces_with_frames = get_interfaces_with_frames(network_frames);
|
let interfaces_with_frames = get_interfaces_with_frames(network_frames);
|
||||||
|
|
||||||
let write_to_stdout: Box<dyn FnMut(String) + Send> = match stdout {
|
let write_to_stdout: Box<dyn FnMut(&str) + Send> = match stdout {
|
||||||
Some(stdout) => Box::new({
|
Some(stdout) => Box::new({
|
||||||
move |output: String| {
|
move |output| {
|
||||||
let mut stdout = stdout.lock().unwrap();
|
let mut stdout = stdout.lock().unwrap();
|
||||||
writeln!(&mut stdout, "{}", output).unwrap();
|
writeln!(&mut stdout, "{}", output).unwrap();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
None => Box::new(move |_output: String| {}),
|
None => Box::new(|_output| {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
OsInputOutput {
|
OsInputOutput {
|
||||||
|
|||||||
@@ -657,7 +657,7 @@ fn traffic_with_host_names(network_frames: Vec<Box<dyn DataLinkReceiver>>) {
|
|||||||
String::from("i-like-cheese.com"),
|
String::from("i-like-cheese.com"),
|
||||||
);
|
);
|
||||||
let dns_client = create_fake_dns_client(ips_to_hostnames);
|
let dns_client = create_fake_dns_client(ips_to_hostnames);
|
||||||
let write_to_stdout = Box::new(move |_output: String| {});
|
let write_to_stdout = Box::new(|_output: &_| {});
|
||||||
|
|
||||||
let os_input = OsInputOutput {
|
let os_input = OsInputOutput {
|
||||||
interfaces_with_frames,
|
interfaces_with_frames,
|
||||||
@@ -696,7 +696,7 @@ fn truncate_long_hostnames(network_frames: Vec<Box<dyn DataLinkReceiver>>) {
|
|||||||
String::from("i-like-cheese.com"),
|
String::from("i-like-cheese.com"),
|
||||||
);
|
);
|
||||||
let dns_client = create_fake_dns_client(ips_to_hostnames);
|
let dns_client = create_fake_dns_client(ips_to_hostnames);
|
||||||
let write_to_stdout = Box::new(move |_output: String| {});
|
let write_to_stdout = Box::new(|_output: &_| {});
|
||||||
|
|
||||||
let os_input = OsInputOutput {
|
let os_input = OsInputOutput {
|
||||||
interfaces_with_frames,
|
interfaces_with_frames,
|
||||||
@@ -735,7 +735,7 @@ fn no_resolve_mode(network_frames: Vec<Box<dyn DataLinkReceiver>>) {
|
|||||||
String::from("i-like-cheese.com"),
|
String::from("i-like-cheese.com"),
|
||||||
);
|
);
|
||||||
let dns_client = None;
|
let dns_client = None;
|
||||||
let write_to_stdout = Box::new(move |_output: String| {});
|
let write_to_stdout = Box::new(|_output: &_| {});
|
||||||
|
|
||||||
let os_input = OsInputOutput {
|
let os_input = OsInputOutput {
|
||||||
interfaces_with_frames,
|
interfaces_with_frames,
|
||||||
@@ -768,7 +768,7 @@ fn traffic_with_winch_event() {
|
|||||||
let (terminal_events, terminal_draw_events, backend) = test_backend_factory(190, 50);
|
let (terminal_events, terminal_draw_events, backend) = test_backend_factory(190, 50);
|
||||||
|
|
||||||
let dns_client = create_fake_dns_client(HashMap::new());
|
let dns_client = create_fake_dns_client(HashMap::new());
|
||||||
let write_to_stdout = Box::new(move |_output: String| {});
|
let write_to_stdout = Box::new(|_output: &_| {});
|
||||||
|
|
||||||
let os_input = OsInputOutput {
|
let os_input = OsInputOutput {
|
||||||
interfaces_with_frames,
|
interfaces_with_frames,
|
||||||
|
|||||||
Reference in New Issue
Block a user