Skip to content

device: keep a router's connection when it says keep-alive; client: a router's fault ends a walk (2.0.3) - #15

Merged
MorningLightMountain713 merged 1 commit into
RunOnFlux:mainfrom
MorningLightMountain713:fix/keep-alive-connections
Oct 19, 2026
Merged

MorningLightMountain713 merged 1 commit into
RunOnFlux:mainfrom
MorningLightMountain713:fix/keep-alive-connections

Conversation

@MorningLightMountain713

Copy link
Copy Markdown

Every request asks the router to keep its connection, and a connection is reused only when the router's answer says Connection: keep-alive. A walk of the mapping table ends at the first index the router answers with a fault, whatever its code.

Connections

TP-Link's TPOS and VxWorks routers (Archer A6, Archer A64, Mercusys AC12G) reset new connections that arrive faster than about one every 6 ms once some 30 have been opened. A back-to-back walk with a new connection per request does that within 50 ms, so their tables could not be listed. They keep a connection when asked, and are now walked over one.

miniupnpd answers Connection: close, and libupnp answers with no Connection header and closes anyway, so both still get a new connection per request: a connection kept on HTTP/1.1's default would be reused after libupnp dropped it.

A kept connection is closed after 3 s idle, before those routers close one themselves (4 to 5 s). A request on a kept connection that fails with no answer is sent once more on a new connection; a failure on a new connection is not sent again. SOAP requests follow no redirects, so axios returns Node's own request and its reusedSocket.

End of a walk

713 and 714 are the standard's end of table, MikroTik and TP-Link/Omada answer 402, and Mercusys answers 501 (Invalid NewPortMappingIndex). Any fault the router gives for an index now ends the table. A fault about the action itself (401 Invalid Action, 602 Not Implemented, 606 Not Authorized) throws, as does an index with no answer or no SOAP reply.

Tests

  • npm test: 882 passing. The connection behaviour is tested against a raw TCP router on loopback that answers keep-alive, close or nothing, closes idle connections, and resets a reused or a new connection. Each new branch was broken on its own (9 mutations) and each turns its test red.
  • npm run flux-test:igd2: green against IGD v2 and IGD v1.
  • Listed read-only on eight real routers: Archer A6 (46 entries), Archer A64 (39) and Mercusys AC12G (48) over one connection each, where 2.0.2 failed after about 30 requests; two FRITZ!Box 7590 models over one connection; miniupnpd, MikroTik and a libupnp router with a new connection per request, as before.

🤖 Generated with Claude Code

… router's fault ends a walk (2.0.3)

Every request asks the router to keep its connection, and the agent keeps
one only when the router's answer says Connection: keep-alive. miniupnpd
answers close, and libupnp answers with no Connection header and closes,
so both still get a new connection per request; a connection kept on
HTTP/1.1's default would be reused after libupnp dropped it. TP-Link's
TPOS and VxWorks routers keep it, and are walked over one connection:
they reset new connections that arrive faster than about one every 6 ms
once some 30 have been opened, which a back-to-back walk does within
50 ms, so no listing of their table completed.

A kept connection is closed after 3 s idle, before those routers close
it themselves at 4 to 5 s. A request on a kept connection that fails with
no answer is sent once more on a new connection; a failure on a new
connection is not. SOAP requests follow no redirects, so axios hands back
Node's own request and its reusedSocket.

A walk of the mapping table ends at the first index the router answers
with a fault, whatever the code: 713 and 714, 402 from MikroTik and
TP-Link/Omada, 501 from Mercusys. A fault about the action itself (401,
602, 606) throws, as does an index with no answer or no SOAP reply.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MorningLightMountain713
MorningLightMountain713 merged commit 35cd545 into RunOnFlux:main Oct 19, 2026
5 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.

1 participant