github aeroxy/tunnix 0.2.3
tunnix v0.2.3

3 hours ago

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 Reset message 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.

2. Visual Overview (Code & Logic Map)

Tunnel Session Reconnection-2026-05-18-123224

3. Detailed Change Analysis

🐛 Concurrency Optimization

  • What Changed: In the client tunnel (src/tunnel.rs), the response channel transmitter (tx) is now cloned before awaiting the send operation.
  • Why it Matters: Previously, the response_channels.lock().await mutex was held during tx.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::Reset to the protocol enum (Source: src/protocol.rs).
  • Server Side: If handle_stream determines a session is brand new (e.g., the server restarted but the client reconnected with an old ID), it immediately dispatches a Message::Reset to the client. It also drops the local sse_tx clone 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 pending response_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::interval ticking every 15s to push an empty SSE comment :\n\n.
    • Client: Wrapped the SSE stream reader in a 30-second tokio::time::timeout.
  • 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::Reset requires both the server and client to be updated. An older client connecting to a newer server will silently drop the Reset message (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 Reset message 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.

Don't miss a new tunnix release

NewReleases is sending notifications on new releases.