Skip to content

feat: add WebSocket heartbeat ping/pong with configurable interval and max-missed - #7

Merged
winguse merged 3 commits into
mainfrom
copilot/add-heart-beat-feature
May 19, 2026
Merged

feat: add WebSocket heartbeat ping/pong with configurable interval and max-missed#7
winguse merged 3 commits into
mainfrom
copilot/add-heart-beat-feature

Conversation

Copilot AI commented May 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements the heartbeat (ping/pong) feature for the WebSocket tunnel between the expose-rs client and server.

Both sides send a WebSocket Ping frame periodically. If no Pong is received for too many consecutive pings, the connection is closed. The client retries after closure; the server only cleans up resources.

Changes

expose-common

  • Added HeartbeatConfig struct with:
    • interval: Duration — how often to send a ping (default: 15 s, configurable via CLI)
    • max_missed: u32 — how many consecutive missed pongs before closing (default: 2, configurable via CLI)
  • Added constants DEFAULT_HEARTBEAT_INTERVAL_SECS and DEFAULT_HEARTBEAT_MAX_MISSED
  • All new items are re-exported from both expose_client and expose_server

expose-client

  • Changed the WS writer channel from mpsc::UnboundedSender<Vec<u8>> to mpsc::UnboundedSender<Message> so that both binary frames and Ping control frames flow through the same writer task
  • Spawns a heartbeat timer task in run_client that sends pings every interval and closes the connection after max_missed consecutive missed pongs
  • Handles Message::Pong in the receive loop to reset the missed-pong counter
  • Updated run_client_once_with_channel_config to accept HeartbeatConfig; run_client_once uses defaults
  • Added --heartbeat-interval and --heartbeat-max-missed CLI arguments (with defaults 15 / 2)

expose-server

  • Same channel-type change, heartbeat task, pong handling, and signature update as the client
  • run_server_with_channel_config now accepts HeartbeatConfig; run_server uses defaults
  • Added --heartbeat-interval and --heartbeat-max-missed CLI arguments

Integration tests

  • Updated all call sites to pass HeartbeatConfig::default() (no behaviour change for existing tests)
  • Added test_heartbeat_closes_dead_tunnel: verifies that when the client stops sending pongs, the server detects the timeout and closes the tunnel, and that a new client can reconnect cleanly afterwards

Testing

All 15 integration tests and 20 unit tests pass, including the new heartbeat test.

Agent-Logs-Url: https://github.com/winguse/expose-rs/sessions/e326adf9-d49e-4739-88de-aee38e35c689

Co-authored-by: winguse <1443504+winguse@users.noreply.github.com>
@winguse
winguse merged commit 30371f4 into main May 19, 2026
3 checks passed
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.

2 participants