diff --git a/Cargo.lock b/Cargo.lock index f3c23a59..44566c87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3679,6 +3679,14 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" +[[package]] +name = "picon" +version = "0.0.0" +dependencies = [ + "objc2-app-kit 0.3.1", + "objc2-foundation 0.3.1", +] + [[package]] name = "pin-project" version = "1.1.10" @@ -4775,6 +4783,7 @@ dependencies = [ "phf 0.12.1", "phf_codegen", "phf_shared 0.12.1", + "picon", "plotters", "plotters-iced", "reqwest", diff --git a/Cargo.toml b/Cargo.toml index f38266fc..663f7f82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,10 +58,7 @@ clap = { version = "4.5.41", features = ["derive"] } tokio = { version = "1.46.1", features = ["macros"] } async-channel = "2.5.0" listeners = { path = "../listeners" } -#cocoa = "0.24" -#objc = "0.2" -#libc = "0.2.174" -#image = "0.24" +picon = { path = "../picon" } [target.'cfg(windows)'.dependencies] gag = "1.0.0" diff --git a/src/gui/pages/overview_page.rs b/src/gui/pages/overview_page.rs index 75e1292e..460debe3 100644 --- a/src/gui/pages/overview_page.rs +++ b/src/gui/pages/overview_page.rs @@ -21,6 +21,7 @@ use crate::networking::types::data_info_host::DataInfoHost; use crate::networking::types::filters::Filters; use crate::networking::types::host::Host; +use crate::networking::types::process::Process; use crate::report::get_report_entries::{ get_host_entries, get_process_entries, get_service_entries, }; @@ -423,6 +424,10 @@ fn col_process<'a>(sniffer: &Sniffer) -> Column<'a, Message, StyleType> { .unwrap_or_default(); for (process, data_info) in &entries { + let Process::Known(listener_process) = process else { + continue; + }; + let content = simpler_bar( process.to_string(), data_info, @@ -436,11 +441,13 @@ fn col_process<'a>(sniffer: &Sniffer) -> Column<'a, Message, StyleType> { Row::new() .spacing(5) .align_y(Vertical::Center) - // .push_maybe( - // handle - // .clone() - // .map(|h| Image::new(h).height(FLAGS_HEIGHT_BIG)), - // ) + .push_maybe( + sniffer + .picons + .get(&listener_process.path) + .clone() + .map(|h| Image::new(h).height(FLAGS_HEIGHT_BIG)), + ) .push(content), ) .padding(Padding::new(5.0).right(15).left(10)) diff --git a/src/gui/sniffer.rs b/src/gui/sniffer.rs index acb5eb46..54cad2b4 100644 --- a/src/gui/sniffer.rs +++ b/src/gui/sniffer.rs @@ -60,7 +60,7 @@ use iced::keyboard::key::Named; use iced::keyboard::{Event, Key, Modifiers}; use iced::mouse::Event::ButtonPressed; -use iced::widget::Column; +use iced::widget::{Column, image}; use iced::window::{Id, Level}; use iced::{Element, Point, Size, Subscription, Task, window}; use pcap::Device; @@ -149,6 +149,8 @@ pub struct Sniffer { pub listeners: HashMap<(u16, listeners::Protocol), listeners::Process>, /// Processes with their DataInfo pub processes: HashMap, + /// Process icons + pub picons: HashMap, } impl Sniffer { @@ -198,6 +200,7 @@ pub fn new(configs: Configs) -> Self { import_pcap_path: String::new(), listeners: HashMap::new(), processes: HashMap::new(), + picons: HashMap::new(), } } @@ -712,7 +715,14 @@ fn fetch_listeners(&mut self) { for l in curr_listeners.into_iter().filter(|l| l.socket.port() != 0) { let port = l.socket.port(); let protocol = l.protocol; + let path = l.process.path.clone(); self.listeners.insert((port, protocol), l.process); + + if !self.picons.contains_key(&path) { + let bytes = picon::get_icon_by_path(&path); + let handle = image::Handle::from_bytes(bytes.bytes); + self.picons.insert(path, handle); + } } for (k, v) in self diff --git a/src/networking/manage_packets.rs b/src/networking/manage_packets.rs index 1bb219ed..81473483 100644 --- a/src/networking/manage_packets.rs +++ b/src/networking/manage_packets.rs @@ -265,8 +265,6 @@ pub fn modify_or_insert_in_map( ) -> (TrafficDirection, Service) { let mut traffic_direction = TrafficDirection::default(); let mut service = Service::Unknown; - // let mut process = "?".to_string(); - // let mut picon = None; if !info_traffic_msg.map.contains_key(key) { // first occurrence of key (in this time interval) @@ -284,43 +282,6 @@ pub fn modify_or_insert_in_map( ); // determine upper layer service service = get_service(key, traffic_direction, my_interface_addresses); - // determine process - // if let Some(local_port) = get_local_port(key, traffic_direction) { - // let processes = get_processes(); - // let pid = processes.get(&local_port).unwrap_or(&0); - // let path = get_executable_path(*pid as i32); - // let mut image: Option = None; - // // println!("Process: {} (PID: {})", path, p.pid); - // if let Some(app_path) = path { - // process = Path::new(&app_path) - // .file_name() - // .unwrap_or_default() - // .to_string_lossy() - // .to_string(); - // // println!("--> Exe path: {}", app_path); - // if let Some(bundle_path) = find_app_bundle_path(&app_path) { - // // println!("--> Bundle path: {}", bundle_path); - // if let Some(tiff) = get_icon_tiff_bytes(&bundle_path) { - // let img = image::load_from_memory(&tiff).expect("Failed to decode image"); - // // resize the image - // let resized = - // img.resize_exact(64, 64, image::imageops::FilterType::Lanczos3); - // let (width, height) = resized.dimensions(); - // // println!("--> Icon size: {}x{}", width, height); - // // crop the image - // let sub = image::imageops::crop_imm(&resized, 6, 6, 52, 52).to_image(); - // let (width, height) = sub.dimensions(); - // // println!("--> Cropped icon size: {}x{}", width, height); - // - // picon = Some(iced::widget::image::Handle::from_rgba( - // width, - // height, - // sub.into_raw(), - // )); - // } - // } - // } - // } } let timestamp = info_traffic_msg.last_packet_timestamp; @@ -373,66 +334,6 @@ pub fn modify_or_insert_in_map( (new_info.traffic_direction, new_info.service) } -// unsafe extern "C" { -// fn proc_pidpath(pid: c_int, buffer: *mut libc::c_void, buffersize: u32) -> c_int; -// } - -// fn get_executable_path(pid: i32) -> Option { -// let mut buf = vec![0u8; libc::PROC_PIDPATHINFO_MAXSIZE as usize]; -// let ret = unsafe { proc_pidpath(pid, buf.as_mut_ptr() as *mut _, buf.len() as u32) }; -// -// if ret > 0 { -// let path = CStr::from_bytes_until_nul(&buf).unwrap(); -// Some(path.to_string_lossy().into_owned()) -// } else { -// None -// } -// } - -fn find_app_bundle_path(exe_path: &str) -> Option { - let mut current = std::path::Path::new(exe_path); - let mut last_app_dir: Option = None; - - // Walk up the path, including the input - loop { - if let Some(file_name) = current.file_name() { - if file_name.to_string_lossy().ends_with(".app") { - last_app_dir = Some(current.to_path_buf()); - } - } - - match current.parent() { - Some(parent) => current = parent, - None => break, - } - } - - last_app_dir.map(|p| p.to_string_lossy().into_owned()) -} - -// fn get_icon_tiff_bytes(app_path: &str) -> Option> { -// unsafe { -// let ns_app_path: id = NSString::alloc(nil).init_str(app_path); -// let workspace: id = msg_send![class!(NSWorkspace), sharedWorkspace]; -// let icon: id = msg_send![workspace, iconForFile: ns_app_path]; -// -// if icon == nil { -// return None; -// } -// -// // Get TIFF representation (NSData) -// let tiff_data: id = msg_send![icon, TIFFRepresentation]; -// if tiff_data == nil { -// return None; -// } -// -// // Convert NSData to Vec -// let length: usize = msg_send![tiff_data, length]; -// let bytes: *const u8 = msg_send![tiff_data, bytes]; -// Some(std::slice::from_raw_parts(bytes, length).to_vec()) -// } -// } - /// Returns the traffic direction observed (incoming or outgoing) fn get_traffic_direction( source_ip: &IpAddr,