From 8afd77c94f98be2d3b9650ca2e6474cd1ec2d9f3 Mon Sep 17 00:00:00 2001 From: GyulyVGC Date: Thu, 30 Oct 2025 21:08:53 +0100 Subject: [PATCH] pause/resume packet captures by applying proper BPF programs --- src/gui/sniffer.rs | 4 ++- src/networking/parse_packets.rs | 37 ++++++++++++++++++------- src/networking/types/capture_context.rs | 16 +++++++++++ 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/gui/sniffer.rs b/src/gui/sniffer.rs index 9f4a49c2..2c2cdc73 100644 --- a/src/gui/sniffer.rs +++ b/src/gui/sniffer.rs @@ -773,6 +773,7 @@ impl Sniffer { .change_capture_source(matches!(capture_source, CaptureSource::Device(_))); let (tx, rx) = async_channel::unbounded(); let (freeze_tx, freeze_rx) = std::sync::mpsc::channel(); + let filters = self.conf.filters.clone(); let _ = thread::Builder::new() .name("thread_parse_packets".to_string()) .spawn(move || { @@ -781,8 +782,9 @@ impl Sniffer { capture_source, &mmdb_readers, capture_context, + filters, &tx, - &freeze_rx, + freeze_rx, ); }) .log_err(location!()); diff --git a/src/networking/parse_packets.rs b/src/networking/parse_packets.rs index 0c76311c..369e03af 100644 --- a/src/networking/parse_packets.rs +++ b/src/networking/parse_packets.rs @@ -1,5 +1,6 @@ //! Module containing functions executed by the thread in charge of parsing sniffed packets +use crate::gui::types::filters::Filters; use crate::location; use crate::mmdb::asn::get_asn; use crate::mmdb::country::get_country; @@ -29,6 +30,7 @@ use etherparse::{EtherType, LaxPacketHeaders}; use pcap::{Address, Packet, PacketHeader}; use std::collections::HashMap; use std::net::IpAddr; +use std::sync::mpsc::Receiver; use std::sync::{Arc, Mutex}; use std::thread; use std::time::{Duration, Instant}; @@ -39,8 +41,9 @@ pub fn parse_packets( mut cs: CaptureSource, mmdb_readers: &MmdbReaders, capture_context: CaptureContext, + filters: Filters, tx: &Sender, - freeze_rx: &std::sync::mpsc::Receiver<()>, + freeze_rx: Receiver<()>, ) { let my_link_type = capture_context.my_link_type(); let (cap, mut savefile) = capture_context.consume(); @@ -53,20 +56,22 @@ pub fn parse_packets( // instant of the first parsed packet plus multiples of 1 second (only used in live captures) let mut first_packet_ticks = None; - let (pcap_tx, pcap_rx) = std::sync::mpsc::sync_channel(0); + let (pcap_tx, pcap_rx) = std::sync::mpsc::sync_channel(10_000); let _ = thread::Builder::new() .name("thread_packet_stream".to_string()) - .spawn(move || packet_stream(cap, &pcap_tx)) + .spawn(move || packet_stream(cap, &pcap_tx, &freeze_rx, &filters)) .log_err(location!()); loop { - // check if we need to freeze the parsing - if freeze_rx.try_recv().is_ok() { - // wait until unfreeze - let _ = freeze_rx.recv(); - // reset the first packet ticks - first_packet_ticks = Some(Instant::now()); - } + // // check if we need to freeze the parsing + // if freeze_rx.try_recv().is_ok() { + // // wait until unfreeze + // let _ = freeze_rx.recv(); + // // discard old buffered packets + // + // // reset the first packet ticks + // first_packet_ticks = Some(Instant::now()); + // } let (packet_res, cap_stats) = pcap_rx .recv_timeout(Duration::from_millis(150)) @@ -495,8 +500,20 @@ fn maybe_send_tick_run_offline( fn packet_stream( mut cap: CaptureType, tx: &std::sync::mpsc::SyncSender<(Result, Option)>, + freeze_rx: &Receiver<()>, + filters: &Filters, ) { loop { + // check if we need to freeze the parsing + if freeze_rx.try_recv().is_ok() { + // pause the capture + cap.pause(); + // wait until unfreeze + let _ = freeze_rx.recv(); + // resume the capture + cap.resume(filters); + } + let packet_res = cap.next_packet(); let packet_owned = packet_res.map(|p| PacketOwned { header: *p.header, diff --git a/src/networking/types/capture_context.rs b/src/networking/types/capture_context.rs index f89620b7..12fc363c 100644 --- a/src/networking/types/capture_context.rs +++ b/src/networking/types/capture_context.rs @@ -150,6 +150,22 @@ impl CaptureType { Self::Offline(cap) => cap.filter(bpf, true), } } + + pub fn pause(&mut self) { + if let Self::Live(cap) = self { + let _ = cap.filter("less 2", true).log_err(location!()); + } + } + + pub fn resume(&mut self, filters: &Filters) { + if let Self::Live(cap) = self { + if filters.is_some_filter_active() { + let _ = cap.filter(filters.bpf(), true).log_err(location!()); + } else if cap.filter("", true).log_err(location!()).is_err() { + let _ = cap.filter("greater 0", true).log_err(location!()); + } + } + } } #[derive(Clone)]