pause/resume packet captures by applying proper BPF programs

This commit is contained in:
GyulyVGC 2025-10-30 21:08:53 +01:00
parent 85344cad45
commit 8afd77c94f
3 changed files with 46 additions and 11 deletions

View file

@ -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!());

View file

@ -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<BackendTrafficMessage>,
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<PacketOwned, pcap::Error>, Option<pcap::Stat>)>,
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,

View file

@ -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)]