From 70cfd8b70f2fbf224e3d103f8418acdc2f05dc38 Mon Sep 17 00:00:00 2001 From: IceDynamix Date: Tue, 23 Apr 2024 17:01:52 +0200 Subject: [PATCH 1/7] log network device capture errors --- src/main.rs | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index b12105d..b07a1f0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ use std::sync::{mpsc, Mutex}; use std::time::Duration; use clap::Parser; -use pcap::{ConnectionStatus, Device}; +use pcap::{ConnectionStatus, Device, Error}; use reliquary::network::{ConnectionPacket, GamePacket, GameSniffer}; use reliquary::network::gen::command_id::{PlayerLoginFinishScRsp, PlayerLoginScRsp}; use tracing::{debug, error, info, instrument, trace, warn}; @@ -239,12 +239,36 @@ fn capture_device(device: Device, tx: mpsc::Sender>) { debug!("listening"); - while let Ok(packet) = capture.next_packet() { - trace!("captured packet"); - if let Err(e) = tx.send(packet.data.to_vec()) { - debug!("channel closed: {e}"); - return; + let mut has_captured = false; + + loop { + match capture.next_packet() { + Ok(packet) => { + trace!("captured packet"); + if let Err(e) = tx.send(packet.data.to_vec()) { + debug!("channel closed: {e}"); + return; + } + + has_captured = true; + } + Err(e) => { + // we only really care about capture errors on devices that we already know + // are relevant (have sent packets before) and send those errors on warn level. + // + // if a capture errors right after initialization or on a device that did + // not receive any relevant packets, error is less useful to the user, + // so we lower the logging level + if has_captured { + warn!(?e); + } else { + debug!(?e); + } + return; + } } } + + debug!("stop listening"); } From b0782a1d961eac51d8d4c0e4fac03972d1d69991 Mon Sep 17 00:00:00 2001 From: IceDynamix Date: Tue, 23 Apr 2024 17:14:56 +0200 Subject: [PATCH 2/7] drop original sender after spawning capture threads --- src/main.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main.rs b/src/main.rs index b07a1f0..7087d48 100644 --- a/src/main.rs +++ b/src/main.rs @@ -148,6 +148,9 @@ fn live_capture(args: &Args, mut exporter: E, mut sniffer: GameSniffer) -> Op let (tx, rx) = mpsc::channel(); let mut join_handles = Vec::new(); + // we need to specify a specific network device when using pcap to capture network packets. + // to lessen the burden on the user, we instead just capture *all* valid network devices + // by capturing each on a different thread and sending the captured packets to a mpsc channel for device in Device::list() .unwrap() .into_iter() @@ -160,6 +163,12 @@ fn live_capture(args: &Args, mut exporter: E, mut sniffer: GameSniffer) -> Op join_handles.push(handle); } + // we clone tx into every thread, but at the end the original tx still remains. + // rx.recv will continue to listen while at least one tx is still alive. + // we drop the original tx to make sure that there are no tx alive after all threads + // have dropped theirs + drop(tx); + let mut invalid = 0; let mut warning_sent = false; From a7766fcb00a5f7ce5423d7ca7549154775c89edd Mon Sep 17 00:00:00 2001 From: IceDynamix Date: Tue, 23 Apr 2024 17:25:41 +0200 Subject: [PATCH 3/7] break capture loop instead of returning --- src/main.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7087d48..7fee536 100644 --- a/src/main.rs +++ b/src/main.rs @@ -256,7 +256,7 @@ fn capture_device(device: Device, tx: mpsc::Sender>) { trace!("captured packet"); if let Err(e) = tx.send(packet.data.to_vec()) { debug!("channel closed: {e}"); - return; + break; } has_captured = true; @@ -273,7 +273,8 @@ fn capture_device(device: Device, tx: mpsc::Sender>) { } else { debug!(?e); } - return; + + break; } } } From 3d4458701fb8c3fa84f6ccd2146c901f621443fb Mon Sep 17 00:00:00 2001 From: IceDynamix Date: Tue, 23 Apr 2024 17:30:54 +0200 Subject: [PATCH 4/7] disable ansi output for now closes #4 --- src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.rs b/src/main.rs index 7fee536..0e445b0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -80,6 +80,7 @@ fn tracing_init(args: &Args) { .from_env_lossy(); let stdout_log = tracing_subscriber::fmt::layer() + .with_ansi(false) .with_filter(env_filter); let subscriber = Registry::default().with(stdout_log); From c6878b7861af775fbb119db25c1ebc458d432f90 Mon Sep 17 00:00:00 2001 From: IceDynamix <22303902+IceDynamix@users.noreply.github.com> Date: Tue, 23 Apr 2024 22:37:36 +0200 Subject: [PATCH 5/7] bump pcap to 2.0.0 --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- src/main.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5165892..82d150f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -342,12 +342,12 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" -version = "0.6.7" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "winapi", + "windows-targets", ] [[package]] @@ -419,9 +419,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "pcap" -version = "1.3.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e935fc73d54a89fff576526c2ccd42bbf8247aae05b358693475b14fd4ff79" +checksum = "45f1686828a29fd8002fbf9c01506b4b2dd575c2305e1b884da3731abae8b9e0" dependencies = [ "bitflags", "errno", diff --git a/Cargo.toml b/Cargo.toml index e928e38..cd6b3eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ homepage = "https://github.com/IceDynamix/reliquary-archiver" base64 = "0.22.0" clap = { version = "4.5.4", features = ["derive"] } color-eyre = "0.6.3" -pcap = "1.3.0" +pcap = "2.0.0" serde = { version = "1.0.198", features = ["derive"] } serde_json = "1.0.116" tracing = "0.1.40" diff --git a/src/main.rs b/src/main.rs index 0e445b0..414bef6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ use std::sync::{mpsc, Mutex}; use std::time::Duration; use clap::Parser; -use pcap::{ConnectionStatus, Device, Error}; +use pcap::{ConnectionStatus, Device}; use reliquary::network::{ConnectionPacket, GamePacket, GameSniffer}; use reliquary::network::gen::command_id::{PlayerLoginFinishScRsp, PlayerLoginScRsp}; use tracing::{debug, error, info, instrument, trace, warn}; From bb21d941674f5b6c18ea43e8ed3dc5865b67bfd0 Mon Sep 17 00:00:00 2001 From: IceDynamix <22303902+IceDynamix@users.noreply.github.com> Date: Tue, 23 Apr 2024 22:51:44 +0200 Subject: [PATCH 6/7] record current trailblazer path --- src/export/fribbels.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/export/fribbels.rs b/src/export/fribbels.rs index f49d838..7be569e 100644 --- a/src/export/fribbels.rs +++ b/src/export/fribbels.rs @@ -46,12 +46,14 @@ pub struct Export { pub struct Metadata { pub uid: Option, pub trailblazer: Option<&'static str>, + pub current_trailblazer_path: Option<&'static str>, } pub struct OptimizerExporter { database: Database, uid: Option, trailblazer: Option<&'static str>, + current_trailblazer_path: Option<&'static str>, light_cones: Vec, relics: Vec, characters: Vec, @@ -64,6 +66,7 @@ impl OptimizerExporter { database, uid: None, trailblazer: None, + current_trailblazer_path: None, light_cones: vec![], relics: vec![], characters: vec![], @@ -89,6 +92,13 @@ impl OptimizerExporter { .filter_map(|b| export_proto_hero(&self.database, &b)) .collect(); + self.current_trailblazer_path = trailblazer_id_to_path(hero.cur_basic_type.value() as u32); + if let Some(path) = self.current_trailblazer_path { + info!(path, "found current trailblazer path"); + } else { + warn!("unknown path for current trailblazer"); + } + info!(num=builds.len(), "found trailblazer builds"); self.trailblazer_characters.append(&mut builds); } @@ -223,6 +233,7 @@ impl Exporter for OptimizerExporter { metadata: Metadata { uid: self.uid, trailblazer: self.trailblazer, + current_trailblazer_path: self.current_trailblazer_path, }, light_cones: self.light_cones, relics: self.relics, From 3364de65f0d0df019d7964c7c88bcbf07c1dcca5 Mon Sep 17 00:00:00 2001 From: IceDynamix <22303902+IceDynamix@users.noreply.github.com> Date: Fri, 26 Apr 2024 13:29:56 +0200 Subject: [PATCH 7/7] set promiscuous mode and ignore timeout errors --- src/main.rs | 54 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/src/main.rs b/src/main.rs index 414bef6..9de09ef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ use std::sync::{mpsc, Mutex}; use std::time::Duration; use clap::Parser; -use pcap::{ConnectionStatus, Device}; +use pcap::{ConnectionStatus, Device, Error}; use reliquary::network::{ConnectionPacket, GamePacket, GameSniffer}; use reliquary::network::gen::command_id::{PlayerLoginFinishScRsp, PlayerLoginScRsp}; use tracing::{debug, error, info, instrument, trace, warn}; @@ -48,7 +48,7 @@ fn main() { let export = match args.pcap { Some(_) => file_capture(&args, exporter, sniffer), - None => live_capture(&args, exporter, sniffer) + None => live_capture(&args, exporter, sniffer), }; if let Some(export) = export { @@ -74,8 +74,10 @@ fn tracing_init(args: &Args) { 0 => "reliquary_archiver=info", 1 => "info", 2 => "debug", - _ => "trace" - }.parse().unwrap() + _ => "trace", + } + .parse() + .unwrap(), ) .from_env_lossy(); @@ -98,16 +100,16 @@ fn tracing_init(args: &Args) { let subscriber = subscriber.with(file_log); - tracing::subscriber::set_global_default(subscriber) - .expect("unable to set up logging"); + tracing::subscriber::set_global_default(subscriber).expect("unable to set up logging"); } #[instrument(skip_all)] fn file_capture(args: &Args, mut exporter: E, mut sniffer: GameSniffer) -> Option - where E: Exporter +where + E: Exporter, { - let mut capture = pcap::Capture::from_file(args.pcap.as_ref().unwrap()) - .expect("could not read pcap file"); + let mut capture = + pcap::Capture::from_file(args.pcap.as_ref().unwrap()).expect("could not read pcap file"); capture.filter(PACKET_FILTER, false).unwrap(); @@ -144,7 +146,8 @@ fn file_capture(args: &Args, mut exporter: E, mut sniffer: GameSniffer) -> Op #[instrument(skip_all)] fn live_capture(args: &Args, mut exporter: E, mut sniffer: GameSniffer) -> Option - where E: Exporter +where + E: Exporter, { let (tx, rx) = mpsc::channel(); let mut join_handles = Vec::new(); @@ -197,8 +200,12 @@ fn live_capture(args: &Args, mut exporter: E, mut sniffer: GameSniffer) -> Op invalid += 1; if invalid >= 25 && !warning_sent { - error!("received a large number of packets that could not be parsed"); - warn!("you probably started capturing when you were already in-game"); + error!( + "received a large number of packets that could not be parsed" + ); + warn!( + "you probably started capturing when you were already in-game" + ); warn!("please log out and log back in"); warning_sent = true; } @@ -237,15 +244,17 @@ fn live_capture(args: &Args, mut exporter: E, mut sniffer: GameSniffer) -> Op Some(exporter.export()) } -#[instrument("thread", skip_all, fields(device = device.name))] +#[instrument(skip_all, fields(device = device.desc))] fn capture_device(device: Device, tx: mpsc::Sender>) { let mut capture = pcap::Capture::from_device(device) .unwrap() .immediate_mode(true) + .promisc(true) + .timeout(0) // explicitly disable timeout?? .open() .unwrap(); - capture.filter(PACKET_FILTER, false).unwrap(); + capture.filter(PACKET_FILTER, true).unwrap(); debug!("listening"); @@ -269,17 +278,22 @@ fn capture_device(device: Device, tx: mpsc::Sender>) { // if a capture errors right after initialization or on a device that did // not receive any relevant packets, error is less useful to the user, // so we lower the logging level - if has_captured { - warn!(?e); - } else { + + if !has_captured { + debug!(?e); + break; + } else if matches!(e, Error::TimeoutExpired) { + // somehow a timeout error can still happen even if i explicitly + // disable the timeout?? why :sob: debug!(?e); + continue; + } else { + warn!(?e); + break; } - - break; } } } debug!("stop listening"); } -