Skip to content

Bound TCP proxy setup and cancel retry backoff with the owning context - #84

Closed
dr-hoseyn wants to merge 2 commits into
AminMGMT:mainfrom
dr-hoseyn:codex/fix-tcp-proxy-dial-budget
Closed

dr-hoseyn wants to merge 2 commits into
AminMGMT:mainfrom
dr-hoseyn:codex/fix-tcp-proxy-dial-budget

Conversation

@dr-hoseyn

@dr-hoseyn dr-hoseyn commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

TCP setup could exceed its configured dial timeout by giving source DNS, socket connection and proxy negotiation separate windows. A cancelled direct, HTTP CONNECT or SOCKS5 dial also stayed in the one-second retry sleep before returning.

Use one context deadline per attempt across DNS, TCP setup and proxy negotiation; pass only the remaining budget to the proxy. Close the captured setup socket on cancellation and clear setup deadlines before normal traffic. Retry backoff now waits on the owning context, and an already-cancelled context cannot start another attempt. Successful connections retain their existing lifetime.

Validation on Linux amd64 with Go 1.26.6: the new direct/HTTP/SOCKS5 cancellation and deadline regression fails on the previous PR head at approximately one second, then passes three repetitions at approximately 50 ms with this change. The combined review branch contains all 28 current PR heads (6581903); full tests, full race tests and vet pass on Linux amd64 / Go 1.26.6. Staticcheck and govulncheck could not be installed because module/checksum DNS requests time out. Local test traffic does not establish WAN performance.

Only existing production and test files change; no configuration or wire-format changes. Previous shared-budget proxy/DNS coverage remains in place.

@dr-hoseyn dr-hoseyn changed the title Bound source DNS TCP setup and proxy negotiation by one dial budget Bound TCP proxy setup and cancel retry backoff with the owning context Oct 9, 2026
AminMGMT pushed a commit that referenced this pull request Oct 9, 2026
…d openUDPPaths wrapper

These three branches were the only ones of the 32 that could not be merged directly: each conflicted in exactly one file against a sibling that had already landed, and the branches live on a fork this session cannot push to.

Resolutions, each verified rather than guessed:

- #87 (reverse QUIC DNS bounded by the dial timeout) conflicted with #71 in internal/utils/network/quic.go, in the import block alone. Both sides' imports are kept: strings, sync and sync/atomic.

- #84 (TCP proxy setup bounded, retry backoff cancellable) conflicted with #66 in internal/utils/network/tcp_dialer.go. main's copy of that file was byte-identical to #66's, so #66 was its only other author, and #84's version is a superset of it: it keeps #66's cancellable retry timer and AfterFunc guard and adds the per-attempt deadline. #84's version is taken whole.

- #60 (direct tunnel recovery) conflicted with #85 in internal/tunnel/limits/limits.go. main's copy is byte-identical to #85's, which already carries #60's ctx/cancel/Close plus the pacingDeadline work, so it supersedes #60's change to that file and is kept. #60's other ten files apply unchanged.

Separately, #76 kept openUDPPaths as a context.Background() shim after moving its only caller to openUDPPathsContext. Nothing calls it, so staticcheck fails the audit job with U1000 — red on main since #76 landed, and clean on main before it. The shim is removed and its explanation moved onto the function that does the work.

Verified on the result: gofmt clean, go build ./... and go vet ./... pass, staticcheck clean, and go test ./... plus go test -race ./... match main's baseline (internal/socks fails only because this container has no IPv6, which fails on plain main too).

Co-authored-by: dr-hoseyn <95236112+dr-hoseyn@users.noreply.github.com>

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019wBoD8a2hetHgBWnfsRAuY

AminMGMT commented Oct 9, 2026

Copy link
Copy Markdown
Owner

Closing: this landed on main through #93, in 34577eb, with you as co-author.

It conflicted with #66 in internal/utils/network/tcp_dialer.go. main's copy of that file was byte-identical to #66's, so #66 was its only other author, and this branch's version is a superset of it — it keeps #66's cancellable retry timer and AfterFunc proxy guard and adds the per-attempt deadline and remaining-budget handoff. So this branch's version was taken whole; the other four files apply unchanged. The branch is on a fork, so the resolution went through #93.

Thank you.


Generated by Claude Code

@AminMGMT AminMGMT closed this Oct 9, 2026
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