Skip to content

feat(quic): NAT traversal observability (rebind diagnostics + active sessions) - #21

Open
David Mireles (louzt) wants to merge 2 commits into
mainfrom
feat/nat-traversal-observability
Open

feat(quic): NAT traversal observability (rebind diagnostics + active sessions)#21
David Mireles (louzt) wants to merge 2 commits into
mainfrom
feat/nat-traversal-observability

Conversation

@louzt

@louzt louzt commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

NAT Traversal Observability — 3 additive changes

SnapPipe v0.2.1 exposes three new lock-free observability surfaces for QUIC
path migration and NAT rebinding events.

D1: feat(quic): path-rebind diagnostic surface

Files: src/quic/rebind.rs (new), src/quic/mod.rs, tests/quic_rebind_diagnostics.rs

QUIC connections silently migrate paths (laptop Wi-Fi → 5G, carrier NAT rebinding).
Quinn does not surface a typed "path changed" event. The correct strategy is
periodic polling of ConnectionStats.

RebindDiagnostics exposes lock-free counters:

  • poll_count — total polls performed
  • rx_bytes / tx_bytes — UDP bytes received/transmitted (from stats.udp_rx.bytes)
  • rtt_min_us / rtt_max_us — min/max RTT observed (from stats.path.rtt)
  • rebind_count — incremented when local IP address hash changes between polls
  • last_local_addr_hash — previous local IP hash for change detection

spawn_observer(conn, interval, diag, cancel) polls conn.stats() every
interval and calls diag.record_poll().

Quinn 0.11.9 API used:

  • conn.stats() -> ConnectionStats where stats.path: PathStats (field, not method)
  • stats.udp_rx.bytes / stats.udp_tx.bytes: u64
  • stats.path.rtt: Duration
  • conn.local_ip() -> Option<IpAddr>

D2: feat(session): NAT rebinding tolerance observability

Files: src/session.rs

SessionMetrics exposes 5 atomic handshake outcome counters:

  • successful — ticket valid, issuer trusted, subject matched
  • expired_or_invalid — ticket expired or signature invalid
  • issuer_not_trusted — issuer not in trust store
  • subject_mismatch — subject did not match
  • other_errors — protocol error or I/O failure

Complements RebindDiagnostics (transport layer) with handshake outcome
observability (session layer).

The module docstring now includes a "NAT rebinding tolerance" section
documenting how QuicTransportProfile::keep_alive_interval_ms and
RebindDiagnostics together give operators visibility into path migrations.

D3: feat(metrics): relay-side active-sessions counter

Files: src/relay/mod.rs

Relay now tracks active_sessions: Arc<AtomicU64>. The counter is
incremented before handle_connection starts and decremented when it
finishes (including early rejection paths: trust rejection, rate limiting).

Relay::active_sessions() -> u64 exposes the current count.

Scope boundary

  • All changes are additive — no existing APIs modified
  • SessionMetrics is declared but not yet instantiated (increment site is
    a future change to the session handshake)
  • No disk I/O, no external dependencies, no TLS changes

Validation

cargo test --locked              # 75 tests
cargo clippy --locked --all-targets -- -D warnings  # 0 warnings

Dependencies

  • D3 depends on C1 (feat(relay): real Quinn socket listener, already merged)
  • D1 and D2 are independent of each other and of D3

Adds §Layer 0: SnapPipe-gated QUIC to OPERATIONAL-DEPLOYMENT.md.
Cross-links to the 5-tier gist case study and to src/relay/listener.rs.
Documents the ordered operations: 5-tier fallback → SnapPipe relay
accept loop → server_handshake on stream 0 → streams 1..N forwarded.
No code changes.
… metrics

D1: RebindDiagnostics struct (AtomicU64/I64 counters) + spawn_observer
  that polls conn.stats() periodically to detect local IP changes,
  RTT min/max, and UDP throughput. Uses Quinn 0.11.9 ConnectionStats
  API (stats.path field, stats.udp_rx.bytes, conn.local_ip()).

D2: SessionMetrics struct exposing 5 atomic handshake outcome counters
  (successful, expired_or_invalid, issuer_not_trusted, subject_mismatch,
  other_errors). Module docstring updated with NAT rebinding tolerance
  section referencing QuicTransportProfile keep_alive_interval_ms.

D3: Relay.active_sessions() counter incremented before handle_connection
  starts and decremented when it finishes (including early rejection
  paths). Uses AtomicU64 with Relaxed ordering.

All changes additive. No existing APIs modified.
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@louzt, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 10 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 59520118-71a0-403f-8cdb-b8ea949ddade

📥 Commits

Reviewing files that changed from the base of the PR and between ad3df11 and 0d5dc6e.

📒 Files selected for processing (6)
  • docs/OPERATIONAL-DEPLOYMENT.md
  • src/quic/mod.rs
  • src/quic/rebind.rs
  • src/relay/mod.rs
  • src/session.rs
  • tests/quic_rebind_diagnostics.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/nat-traversal-observability

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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