diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..56ba2fa Binary files /dev/null and b/.DS_Store differ diff --git a/Cargo.toml b/Cargo.toml index f14a4cb..db408f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "crates/test_probe", "crates/ptrace_probe", "crates/log_probe", + "crates/pcap_probe", ] # Specify a subset of member crates that compile on all supported architectures. @@ -16,6 +17,7 @@ default-members = [ "crates/composer", "crates/test_probe", "crates/log_probe", + "crates/pcap_probe", ] # Explicitly set resolver due to virtual workspace, see diff --git a/crates/pcap_probe/Cargo.toml b/crates/pcap_probe/Cargo.toml new file mode 100644 index 0000000..f1d5ac9 --- /dev/null +++ b/crates/pcap_probe/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "pcap_probe" +version = "0.1.0" +edition = "2021" + +[dependencies] +clap = { version = "4.2", features = ["derive"] } +color-eyre = "0.6" +composer_api = { path = "../composer_api" } +eyre = "0.6" +pcap = "2.2.0" diff --git a/crates/pcap_probe/src/main.rs b/crates/pcap_probe/src/main.rs new file mode 100644 index 0000000..2011a91 --- /dev/null +++ b/crates/pcap_probe/src/main.rs @@ -0,0 +1,54 @@ +#![warn(clippy::all, clippy::clone_on_ref_ptr)] + +use std::time::Duration; + +use clap::{command, Parser}; +use composer_api::{Client, Event, EventKind, Packet}; +use eyre::Result; +use pcap::Capture; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +#[command(propagate_version = true)] +struct Args { + /// Server address to receive events. + #[arg(short, long)] + address: Option, +} + +fn main() -> Result<()> { + color_eyre::install()?; + + let args = Args::parse(); + let client = match args.address { + Some(address) => Client::new(address), + None => Client::try_default(), + }?; + + let device = pcap::Device::lookup() + .expect("cal list devices") + .expect("there's a default network device"); + println!("using device: {device:?}"); + + let mut capture = Capture::from_device(device) + .unwrap() + .immediate_mode(true) + .open() + .expect("can open the device for capture"); + + while let Ok(cap) = capture.next_packet() { + let ts = Duration::new( + cap.header.ts.tv_sec.unsigned_abs(), + // One microsecond is 1000 nanoseconds. + cap.header.ts.tv_usec.unsigned_abs() * 1000, + ); + + let event = Event::with_timestamp(EventKind::TestTick, ts); + + if let Err(err) = client.send(&Packet::from_event(event)) { + eprintln!("Could not send packet {:?}", err) + }; + } + + Ok(()) +}