Changed
- Single-port TCP mode (#16) - TCP tests now use only port 5201 for all connections, making them firewall-friendly. Data connections identify themselves via
DataHellomessage instead of using ephemeral ports. - Protocol version bump to 1.1 - Signals DataHello support; adds
single_port_tcpcapability for backward compatibility detection - Client capabilities in Hello - Client now advertises supported capabilities (tcp, udp, quic, multistream, single_port_tcp); server falls back to multi-port TCP for legacy clients without
single_port_tcp - Numeric version comparison -
versions_compatible()now parses major version as integer instead of string comparison
Fixed
- QUIC IPv6 support (#17) - QUIC clients can now connect to IPv6 addresses without requiring
-6flag; endpoint now binds to matching address family - mDNS discovery (#15) - Server now advertises addresses via
enable_addr_auto(); client uses non-blocking receive with proper timeout handling - TCP RTT and retransmits display (#13) - TUI now shows correct retransmit count from stream results (captured after transfer); TCP_INFO captured after transfer for accurate RTT/cwnd
- Data connections no longer consume rate-limit/semaphore slots - Only control (Hello) connections acquire permits; DataHello connections route directly without resource consumption
- Cancel messages processed during TCP stream collection - Interval loop now starts immediately; stream collection runs concurrently in background
- Client OOB panic on port mismatch - Added bounds check when server returns fewer ports than requested streams
- DoS guard on oversized lines -
read_first_line_unbuffered()now returns error instead of truncating - DataHello serialization panic - Replaced
unwrap()with proper error handling in spawned task - One-off mode deadlock -
--one-offno longer blocks the accept loop waiting for test completion; uses shutdown channel to signal exit after test finishes - QUIC one-off mode - QUIC accept loop now responds to shutdown signal for proper
--one-offexit - cancel.changed() busy-loop - Handle sender-dropped error in stream collection select! to prevent CPU spin
- IPv4-mapped IPv6 comparison - DataHello IP validation now normalizes
::ffff:x.x.x.xaddresses for correct matching on dual-stack systems
Security
- DataHello IP validation - Server validates DataHello connections come from same IP as control connection to prevent connection hijacking
- Slow-loris protection - Accept loop now spawns per-connection tasks with 5-second initial read timeout; slow clients can no longer block the listener
- DataHello flood protection - Server validates test_id exists in active_tests before processing DataHello connections; unknown test_ids are dropped immediately
- Pre-handshake connection gate - Limits concurrent unclassified connections (4x max_concurrent) to prevent connection-flood DoS before Hello/DataHello routing
- Multi-port TCP fallback IP validation - Per-stream listeners validate connecting peer IP against control connection, preventing unauthorized data stream injection
- One-off mode hardened - Failed handshakes and auth failures no longer trigger server shutdown in
--one-offmode; only successful test completion exits
Testing
- Added regression test for QUIC IPv6 connectivity
- Added
test_tcp_one_off_multi_stream- verifies 4-stream TCP in--one-offmode with stream count assertion - Added
test_quic_one_off- verifies 2-stream QUIC in--one-offmode with stream count assertion
Code Quality
- Log panics from
join_allin QUIC, UDP, and TCP stream handlers instead of silently discarding JoinErrors - Multi-port fallback listener tasks cleaned up via cancel signal (no leaked tasks on partial connections)
Install: brew install lance0/tap/xfr or cargo install xfr
Full Changelog: v0.4.4...v0.5.0