Files
Bose-SoundTouch/pkg
Tobias Gesellchen 2b0172c21b fix(ssh): reuse one SSH connection across RevertMigration's ~17 calls
Confirmed on real hardware (192.168.178.28): RevertMigration's full call
graph (revertXMLConfig/revertHosts/revertResolvConf/revertAftertouchHook/
removeRcLocalHooks/revertCACert) makes 17 separate client.Run() calls, and
pkg/ssh.Client.Run/UploadContent each dialed a brand-new SSH connection
per call with no reuse. Hitting a resource-constrained speaker with 17
rapid reconnects overwhelmed it -- confirmed via a follow-up plain SSH
command timing out at the TCP level, and the speaker going visibly
unresponsive.

Gives pkg/ssh.Client an opt-in persistent connection: Connect() dials
once and caches it, Close() releases it, and a shared dial() helper makes
Run/UploadContent reuse the cached connection when one's open, falling
back to today's per-call dial otherwise. RevertMigration now calls
Connect() once and defer Close(), collapsing 17 connections into 1. The
other ~21 m.NewSSH() call sites in pkg/service/setup never call Connect,
so their behavior is completely unchanged -- this only touches the one
function that was actually causing real-world problems.

SSHClient interface gained Connect()/Close(); both test mocks
(pkg/service/setup/setup_test.go, pkg/service/handlers/handlers_setup_test.go)
got no-op stubs. Added TestClose_NoOpWithoutConnect and
TestConnect_DialFailureLeavesConnNil in pkg/ssh/ssh_test.go -- these don't
prove connection reuse against a real server (Client.Run hardcodes :22,
no configurable port for a test listener), so that specific behavior is
verified by code review (a single `if c.conn != nil` branch) plus the
real-hardware confirmation above, not an automated integration test.

Also fixes the web UI's "Revert to Defaults" button, which calls the same
RevertMigration code path.
2026-08-16 15:54:00 +02:00
..