Skip to content

fix(truapi-provider): track tunnel liveness by flag, not by dialling - #445

Merged
TarikGul merged 3 commits into
mainfrom
tg/wss-tunnel-hardening
Aug 19, 2026
Merged

fix(truapi-provider): track tunnel liveness by flag, not by dialling#445
TarikGul merged 3 commits into
mainfrom
tg/wss-tunnel-hardening

Conversation

@TarikGul

Copy link
Copy Markdown
Member

Follow-up to #276.

ensure_tunnel decides whether a cached tunnel is still usable by reading a flag the accept loop clears when it exits. Nothing dials the loopback port to find out, so reusing a tunnel costs no upstream TLS handshake and the tunnel map is
never held across a blocking connect. AliveUntilDropped owns the clearing, so a setup failure and a panic both report the same way.

redacted falls back to scheme and host when set_username or set_password reject the URL, so a cannot-be-a-base URL cannot print the credentials the function exists to strip.

Tests cover the tunnel lifecycle: a live tunnel is reused, a dead one is rebound, and distinct hosts and distinct ports are distinct upstreams. Redaction is covered for a username, a username with a password, and a URL with no userinfo.

The relay path itself is still untested. That needs a local TLS stub server, so it belongs in its own PR.

`ensure_tunnel` decided whether a cached tunnel was still alive by connecting to
its loopback port. That connection is itself accepted and relayed, so every reuse
cost an upstream TLS handshake to a public bootnode, and the blocking connect ran
while the tunnel map was locked.

The accept loop now carries a flag it clears on exit, including on panic, and the
cache hit reads that instead. `AliveUntilDropped` owns the clearing so the three
early-return setup failures and an unwind all report the same way.

Also stop `redacted` from returning a URL with its credentials intact: both
setters reject a cannot-be-a-base URL, and serializing the clone anyway emitted
exactly what the function exists to remove. It now falls back to scheme and host.

Covers the tunnel lifecycle, which had no tests: reuse, replacement of a dead
tunnel, and that distinct hosts and distinct ports are distinct upstreams. Plus
redaction of a username, a username with a password, and the unchanged no-userinfo
case.
@TarikGul
TarikGul requested a review from a team August 18, 2026 14:28
…le branch

An adversarial review found the previous commit's own contribution untested:
gutting `AliveUntilDropped` left every test passing, because the dead-tunnel
test set the flag by hand instead of driving the guard.

`the_guard_clears_the_flag_when_the_loop_ends` runs the guard on a real thread
and fails when it is removed. The dead-tunnel tests assert the replacement is
live rather than that its port differs, since a genuinely dead tunnel releases
its port and the kernel may hand the same one back.

`redacted` drops its fallback branch: both setters reject only a URL with no
host, an empty domain, or the `file` scheme, none of which can carry the
userinfo that reaches that code, so the branch was unreachable and its comment
named the wrong condition.

The guard's doc no longer claims panic coverage, which the release profile's
`panic = "abort"` does not provide, and `run_tunnel` no longer describes an
`ensure_tunnel` probe this branch removed.
@TarikGul
TarikGul added this pull request to the merge queue Aug 19, 2026
Merged via the queue into main with commit 698f49c Aug 19, 2026
17 checks passed
@TarikGul
TarikGul deleted the tg/wss-tunnel-hardening branch August 19, 2026 02:06
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.

2 participants