1. High-Level Summary (TL;DR)
- Impact: High - Significantly improves the resilience and concurrency of the proxy tunnel by introducing session resets, keepalives, and resolving a concurrency bottleneck.
- Key Changes:
- Protocol Extension: Introduced a
Resetmessage to handle server restarts gracefully. - Keepalive & Timeout: Added a 15-second SSE keepalive on the server and a 30-second read timeout on the client to quickly recover dead connections.
- Concurrency Fix: Removed a mutex guard that was held across async channel sends, preventing slow consumers from blocking all connections.
- Protocol Extension: Introduced a
2. Visual Overview (Code & Logic Map)
3. Detailed Change Analysis
🐛 Concurrency Optimization
- What Changed: In the client tunnel (
src/tunnel.rs), the response channel transmitter (tx) is now cloned beforeawaiting the send operation. - Why it Matters: Previously, the
response_channels.lock().awaitmutex was held duringtx.send(TunnelEvent::...).await. A slow consumer (a full channel) would stall the entire dispatch loop, blocking data delivery for all other connections.
✨ Protocol & Session Management
- What Changed: Added
Message::Resetto the protocol enum (Source:src/protocol.rs). - Server Side: If
handle_streamdetermines a session is brand new (e.g., the server restarted but the client reconnected with an old ID), it immediately dispatches aMessage::Resetto the client. It also drops the localsse_txclone to ensure the RX side hangs up cleanly when the session drops (Source:src/server.rs). - Client Side: Upon receiving
Message::Reset, the client clears all pendingresponse_channels, safely tearing down SOCKS5/HTTP clients that the server no longer knows about (Source:src/tunnel.rs).
⏱️ Keepalives and Timeouts
- What Changed:
- Server: Added a
tokio::time::intervalticking every 15s to push an empty SSE comment:\n\n. - Client: Wrapped the SSE stream reader in a 30-second
tokio::time::timeout.
- Server: Added a
- Why it Matters: The 15s keepalive prevents reverse proxies or load balancers from dropping idle connections. The 30s timeout on the client ensures that if the server crashes silently or network drops, the client will proactively disconnect and reconnect.
📦 Package & Release Updates
- What Changed: Version bump and checksum updates for Homebrew formulas.
| Package / Artifact | Old Value | New Value | Description |
|---|---|---|---|
| Cargo Version | 0.2.2
| 0.2.3
| Project version bump. |
| macOS ARM64 SHA | 6fa2...b063
| 74d3...faf2
| Updated Homebrew hash for v0.2.3. |
| Linux x86_64 SHA | bd99...342f
| 15f0...daa8
| Updated Homebrew hash for v0.2.3. |
4. Impact & Risk Assessment
- Breaking Changes: The addition of
Message::Resetrequires both the server and client to be updated. An older client connecting to a newer server will silently drop theResetmessage (handled by the wildcard_ => {}match), which means it won't benefit from the orphan cleanup but will not crash. - Testing Suggestions:
- Server Restart Simulation: Connect a client, start a long-running download, kill the server, and restart it. Verify the client receives the
Resetmessage and tears down the pending download cleanly. - Idle Timeout: Leave a connection completely idle for > 30 seconds and ensure the client does not disconnect (thanks to the new 15s server keepalive).
- Network Partition: Block network traffic to the client and verify it disconnects and attempts to reconnect after 30 seconds.
- Server Restart Simulation: Connect a client, start a long-running download, kill the server, and restart it. Verify the client receives the