Skip to content

fix: add connect timeout to prevent indefinite hang on silent packet drops#36

Merged
jak merged 1 commit into
mainfrom
fix/connect-timeout-issue-35
Apr 12, 2026
Merged

fix: add connect timeout to prevent indefinite hang on silent packet drops#36
jak merged 1 commit into
mainfrom
fix/connect-timeout-issue-35

Conversation

@jak
Copy link
Copy Markdown
Owner

@jak jak commented Apr 12, 2026

Summary

  • Client.connect() now rejects within the configured timeout (default 4s) when the host silently drops SYN packets, instead of hanging until the OS-level TCP timeout (~75s+).
  • Emits onDebug events on connect start and success so consumers see progress before polling begins.
  • Persistent data/close/error handlers attach only after successful connect, fixing a latent double-error binding.

Fixes #35.

Details

createConnection was wrapped without any timeout. When an inverter's WiFi dongle goes offline or a firewall blackholes port 8899, SYN packets are dropped silently and the socket neither connects nor errors for over a minute. Downstream (Homey app) reports showed Inverter.connect() hanging with no debug signal, and Homey's init-timeout then killed and restarted the app in a loop.

Fix reuses the existing timeout option via a setTimeout guard that destroys the socket and rejects with a clear message like connect timeout after 4000ms to 10.29.0.197:8899.

Test plan

  • New unit test: connect() rejects within the configured timeout when pointed at 192.0.2.1:1 (TEST-NET-1 blackhole).
  • New unit test: debug events fire on connect start and success.
  • Fixed pre-existing race in the "connects to inverter" test (client 'connect' can fire before server's 'connection' event is processed) by waiting for the server-side socket before asserting.
  • Full test suite: 368/368 passing.
  • Verified against real inverter at 10.29.0.197 via npm run script:snapshot — connect/poll cycle still works end-to-end.

…drops

Client.connect() wrapped net.createConnection() without a timeout, so a
host that silently drops SYN packets (inverter WiFi dongle offline, firewall
blackhole) left connect() hanging until the OS-level TCP timeout (~75s+).
Downstream consumers (e.g. the Homey app) saw device init hang with no
error and no progress signal.

Guard connect() with a setTimeout using the existing client timeout
option (default 4s). On fire, destroy the socket and reject with a
clear error. Emit debug events on connect start and success so consumers
get progress signals before polling begins.

Persistent data/close/error handlers now attach only after a successful
connect, avoiding a latent double-error path that could have both
rejected and triggered _failAllPending on pre-connect errors.

Fixes #35
@jak jak merged commit fe883a5 into main Apr 12, 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.

Client.connect() has no timeout — hangs indefinitely when host drops packets silently

1 participant