Skip to content

Send CoderVPN WakeRequest on system wake to recover tunnel paths #172

Description

@EhabY

Summary

After the machine sleeps and wakes, the Coder Connect tunnel can stay unusable for several minutes: new SSH dials fail with i/o timeout until magicsock's periodic re-STUN re-homes the path on its own. A short, same-network wake often produces no netmon link-change event, so the daemon's existing linkChange() recovery (Rebind + ReSTUN) never fires.

The same gap was first observed on macOS (coder/coder#26736), but it is OS-agnostic: the daemon-side fallback timer also stops after 45s idle, and sleep is idle by definition, so on wake there is no scheduled re-STUN until another trigger fires.

Background

coder/coder PR coder/coder#26739 adds the daemon-side hook. It introduces a new CoderVPN RPC (WakeRequest / WakeResponse, tunnel protocol 1.3) whose handler calls tailnet.Conn.Rebind() (magicConn.Rebind() + magicConn.ReSTUN("wake")), the same recovery path a major link change triggers.

The daemon side only exposes the hook. Coder Desktop must actually emit it. This is the Windows counterpart of coder/coder-desktop-macos#260.

What's needed in coder-desktop-windows

  1. Subscribe to a system resume event. In .NET this is Microsoft.Win32.SystemEvents.PowerModeChanged with PowerModes.Resume; for a service/headless context without a message pump, register for WM_POWERBROADCAST (PBT_APMRESUMESUSPEND / PBT_APMRESUMEAUTOMATIC) via RegisterPowerSettingNotification.
  2. On resume, send a ManagerMessage with the new WakeRequest over the existing CoderVPN tunnel RPC channel.
  3. Only send when the negotiated tunnel protocol version is >= 1.3 (older daemons won't handle the message). Regenerate the C# protobuf bindings from the updated vpn.proto once the coder/coder PR merges.
  4. Optionally surface WakeResponse.success / error_message in debug logs.

This is an event-driven kick on a known OS event, not a health check or poll. It forces path re-discovery and never tears down a live tunnel.

Refs

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions