fix(network): a silent IPv6 address no longer holds up IPv4, so a PC with broken IPv6 reaches git.magicbean.dev #115
No reviewers
Labels
No labels
area/build
area/install
area/saves
area/tooling
area/ui
area/updates
ci: approved
good first issue
gpu/amd
gpu/intel
gpu/nvidia
help wanted
kind
bug
kind
chore
kind
docs
kind
feature
kind
performance
kind
question
platform/linux
platform/steam-deck
platform/windows
priority
critical
priority
high
priority
low
risk
high
risk
low
risk
medium
status
blocked
status
confirmed
status
duplicate
status
invalid
status
needs-info
status
wontfix
ci: approved
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/LongshotLauncher!115
Loading…
Reference in a new issue
No description provided.
Delete branch "madebyjordan/LongshotLauncher:feat/happy-eyeballs"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
On a PC whose IPv6 doesn't actually reach the internet, the launcher's update check fails with "git.magicbean.dev did not answer in time", while a browser on the same PC opens the site at once. .NET's own connect tries a name's addresses one after another, each to its end, and Windows prefers IPv6. The IPv6 connect waits about 21 s for nothing, longer than the check's 20 s timeout, so IPv4 is never reached. Browsers avoid this by trying IPv4 alongside a slow IPv6 (Happy Eyeballs). This does the same. It's one of the likely causes behind the "launcher can't connect" reports (Longshot#738, #support), and #106's log would show it as an IPv6 connect that is stopped at the timeout.
What changed
Core/Connections.cs, theConnectCallback#106 added (the launcher's only way to open a connection), now tries the addresses as browsers do (RFC 8305):Interleave).Stagger, RFC 8305's Connection Attempt Delay).SocketException, the last address'sSocketException, or the request's cancellation. SoNetFailure's words for a failure stay the same.connect <host> <address>: stopped after N ms, <winner> connected first. At the request's timeout, every connect still going readsno answer, stopped after N ms.What stays the same: a single address (an IP literal, or a proxy with one address) connects as before; the proxy handling;
DOTNET_SYSTEM_NET_DISABLEIPV6=1; and the 20 s / 60 s request timeouts.Tested
Windows 11, .NET SDK 10.0.404, on main @
f6a4123:python -I tests/test_launcher_core.py: 1292 checks pass. New inConnectionChecks.cs, all with a fake resolver and connect:2001:db8::1 192.0.2.1 2001:db8::2 192.0.2.2 2001:db8::3, and one family kept as it is);#106's checks pass unchanged: in-order failures, the timeout's address, IPv6 left out, DNS failure, and refused/DNS/not-TLS through
HttpFetcher.Real sockets, through this branch's Core in a console harness: an address that never answers (10.255.255.1) first, then a local server. It connected in 321 ms, with the first address stopped after 266 ms. Before, that connect would wait for the first address's TCP timeout (~21 s on Windows).
The real update check against the live servers: unchanged. It connected to the first Cloudflare address in 22 ms, and the run took 0.7 s.
dotnet build App -c Release -p:RestoreLockedMode=true -warnaserror: 0 warnings.dotnet format --verify-no-changeson the changed files: clean.Not tested: a PC with real broken IPv6 (this one has only a Teredo address, so Windows prefers IPv4 here), and Linux.
🤖 Generated with Claude Code