Repository navigation
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 intoOct 19, 2026
Conversation
… 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 noConnectionheader 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.🤖 Generated with Claude Code