Skip to content

feat(tui): filter-edit and record hotkeys, plus a capture-loop hang fix - #1

Merged
jaymeklein merged 2 commits into
masterfrom
feat/tui-filter-and-record-hotkeys
Aug 6, 2026
Merged

jaymeklein merged 2 commits into
masterfrom
feat/tui-filter-and-record-hotkeys

Conversation

@jaymeklein

@jaymeklein jaymeklein commented Aug 6, 2026 •

Copy link
Copy Markdown
Owner

Adds two TUI hotkeys and fixes a pre-existing hang in the capture thread that both of them would otherwise trip over.

f / Ctrl-F — edit the capture filter

Opens a one-line BPF editor over the packet list, pre-filled with the filter in force. Ctrl-F again applies it, so the whole edit is one key, type, same key.

  • Completion matches the word under the caret against ~40 BPF entries (tcp, src port, ip proto, portrange, ether host, …), each with a one-line syntax reminder. Parentheses break a word like whitespace, so it keeps working inside (...) groups.
  • Full line editing: Tab to insert, ↑/↓ (or Ctrl-P/Ctrl-N) to navigate, Ctrl-W/Ctrl-U, Home/End, Ctrl-A/Ctrl-E.
  • Filters are compiled against a dead handle before being accepted, so a typo is reported inline (✗ can't parse filter expression: syntax error) with your text intact, rather than tearing the capture down to find out.
  • Applying restarts the capture clean: stats, packet list, throughput history and the --count / --duration / --max-file-size budgets all reset.

r — start / stop recording

Toggles whether packets reach the .pcap. The capture keeps running and the table keeps filling — only the writing stops. p freezes the display; r gates the file. A badge in the header always says which way it is.

  • Stopping flushes, so what's on disk is a complete, Wireshark-openable pcap while you keep watching live traffic.
  • Starting again appends to the same handle — it never reopens, which would truncate.
  • A run that never records leaves the output file untouched, and the summary reports recorded alongside packets whenever they differ.

The fix

libpcap's read timeout is not a promise: on Linux the kernel only wakes the reader once a packet has landed, so a filter matching nothing (host 192.168.0.2 on a network that has no such host) left next_packet parked indefinitely — and with it the stop flag, --duration, Ctrl-C and both new hotkeys. Quitting hung the app, and SIGTERM was swallowed by the Ctrl-C handler whose flag nobody was left to read.

This predates the hotkeys — it just showed up as q never quitting. The capture handle is now non-blocking with a 5 ms nap, so the flags are checked ~200×/second regardless of traffic, and immediate mode is on so packets are handed over as they arrive instead of sitting in a kernel block for up to a second.

Testing

cargo fmt, cargo clippy --all-targets -D warnings and 29 tests pass on both commits — the fix was peeled back out to confirm the feature-only tree stands on its own.

15 new tests cover the editor's completion and editing semantics, the overlay at 140×34 and 60×16, the rejection state, the recording badge in both states, and the recorder invariants (nothing opened while off, one open across a stop/start, one flush per transition, a late first recording still opening the file).

Not verified live: the reviewer should confirm on a real interface. The recorder tests run against a fake sink because the real path needs CAP_NET_RAW. Quickest check that the hang is gone — this ran past two minutes and ignored SIGTERM before:

rust-wire -i eth0 -f "host 192.168.0.2" --duration 3s --no-tui -o /tmp/x.pcap

`f` / Ctrl-F opens a one-line BPF editor over the packet list, pre-filled
with the filter in force and completing the BPF vocabulary against the word
under the caret. Ctrl-F applies and restarts the capture from a clean slate:
stats, packet list, throughput history and the stop-condition budgets all
reset. Expressions are compiled before they are accepted, so a typo is
reported inline and the editor keeps your text instead of tearing the
capture down to find out.

`r` toggles whether packets reach the pcap. The capture keeps running and
the table keeps filling — only the writing stops, so `r` gates the file the
way `p` freezes the display. Stopping flushes, leaving a complete pcap on
disk; starting again appends rather than reopening, which would truncate. A
run that never records leaves the output file untouched, and the summary
reports `recorded` alongside `packets` whenever they differ.

Supporting changes: the terminal is set up once for the session so a filter
restart doesn't flash the screen, and a single Ctrl-C handler now holds a
session-long stop flag shared by each capture thread.
libpcap's read timeout is not a promise. On Linux the kernel only wakes the
reader once a packet has landed, so a filter matching nothing — or simply a
silent link — left `next_packet` parked indefinitely, and with it the stop
flag, `--duration`, the record toggle and the filter restart. Quitting hung
the app, and SIGTERM was swallowed by the Ctrl-C handler whose flag nobody
was left to read, so the process had to be killed.

Poll non-blocking with a 5 ms nap instead: the flags are checked ~200 times
a second no matter what the link is doing. Also enable immediate mode, so
packets are handed over as they arrive rather than sitting in a kernel block
until the read timeout — on a quiet link they could show up a second late.
@jaymeklein
jaymeklein merged commit 1848e0f into master Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant