# Patterns and conventions ## Error handling The project uses a layered error strategy: - `thiserror` enums for domain-specific errors (`TlsError`, `AuthError`, `TunnelError`, `HostError`, `Socks5Error`, `FrameError`). These live in `src/errors.rs` and `src/socks5.rs` / `src/framing.rs`. - `anyhow` for application-level propagation. CLI commands return `anyhow::Result` and `main` exits with `process::exit(exit_code)`. - All errors are designed to be actionable and fail-closed. There are no silent degradation paths to insecure modes. ## Secret handling - The `Redacted` wrapper in `src/redact.rs` must be used before logging any secret. - `Redacted::inner()` and `into_inner()` are marked `#[allow(dead_code)]` to discourage use, but available for file writes. - `is_sensitive()` detects PEM private key blocks. `is_auth_token()` detects long alphanumeric strings. - `is_connection_key()` detects strings starting with `rtun1.`. ## Async patterns - Tokio's multi-threaded runtime is used on both listener and connector sides. - `tokio::spawn` is used for per-connection and per-stream tasks. - `tokio::select!` with `biased;` prioritizes shutdown signals over new connections. - `watch::channel` is used for publishing the active `StreamMux` to the SOCKS5 proxy (supports reconnect). - `mpsc::channel` and `oneshot::channel` are used for stream data and CONNECT_REPLY coordination. ## Constant-time comparison Auth token comparison in `src/tunnel.rs` uses a manual constant-time XOR loop to prevent timing attacks: ```rust fn constant_time_compare(a: &str, b: &str) -> bool { let a_bytes = a.as_bytes(); let b_bytes = b.as_bytes(); if a_bytes.len() != b_bytes.len() { return false; } let mut result: u8 = 0; for (x, y) in a_bytes.iter().zip(b_bytes.iter()) { result |= x ^ y; } result == 0 } ``` ## Frame reader partial read discipline `FrameReader` in `src/framing.rs` never consumes bytes from the buffer until a complete frame (header + payload) is available. This prevents corruption when TCP segments arrive in arbitrary chunks. ## TLS material as enum Both `ServerTlsMaterial` and `ClientTlsMaterial` are enums with `Paths` and `Pem` variants. This lets the listener and connector accept either file paths (from CLI args) or embedded PEM strings (from connection keys). ## Insecure mode `--insecure-skip-tls-verify` exists for DPI/intercepted environments only. When enabled, the listener skips client certificate verification and the connector skips server certificate verification. This is logged at `warn` level.