Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: use Happy Eyeballs to make network connections (TCP-only) #9199

Merged
merged 1 commit into from May 6, 2021

Conversation

TrueBrain
Copy link
Member

@TrueBrain TrueBrain commented May 6, 2021

Motivation / Problem

From time to time we get reports that the Online Content list not loading (#9198, #8582, https://www.tt-forums.net/viewtopic.php?f=31&t=66905 ) is the most common case. In 99.99% of these cases, the problem is the IPv6 setup of the local machine: the OS things IPv6 is functional (getaddrinfo reports IPv6 as preferred, an IPv6 socket can be created, etc), but the connection is never really established. As this is a problem on OS level, OpenTTD cannot really resolve the issue.

This problem is most noticeable with TCP, as for UDP we basically just send out our request on what-ever interface we can find, and it is more likely it will find its way (up-side of stateless sockets). So we do not see many reports of people that cannot load the multiplayer list.

With the upcoming STUN support, we switch the multiplayer list to TCP too. This means that it is more likely people will notice this problem, and cannot play multiplayer. So, the question is: can't we do a similar solution like browers: try both IPv6 and IPv4, and see which one works. This, as dwfreed on IRC pointed out, is called Happy Eyeballs.

This PR sets out to implement exactly this: try both IPv6 and IPv4 (if available), in a smart way to not hurt our servers too much. As added benefit, it also means the round-robin DNS we use is used a bit smarter: if the first IPv4 doesn't work (times out), the second is already tried after 250ms instead of after 3s.

Description

Hostnames like "content.openttd.org" resolve into multiple IPv4 and IPv6.
It is possible that either of the IPs is not working, either due to
a poorly configured OS (having IPv6 but no valid route), broken network
paths, or a service that is temporary unavailable.

Instead of trying the IPs one by one, waiting for a 3s timeout between
each, be a bit more like browsers, and stack attempts on top of each
other with slight delays. This is called Happy Eyebells.

Initially, try the first IPv6 address. If within 250ms there is no
connection yet, try the first IPv4 address. 250ms later, try the
second IPv6 address, etc, till all addresses are tried.

If any connection is created, abort all the other (pending) connections
and use the one that is created. If all fail 3s after the last connect(),
trigger a timeout for all.

Limitations

Checklist for review

Some things are not automated, and forgotten often. This list is a reminder for the reviewers.

  • The bug fix is important enough to be backported? (label: 'backport requested')
  • This PR affects the save game format? (label 'savegame upgrade')
  • This PR affects the GS/AI API? (label 'needs review: Script API')
    • ai_changelog.hpp, gs_changelog.hpp need updating.
    • The compatibility wrappers (compat_*.nut) need updating.
  • This PR affects the NewGRF API? (label 'needs review: NewGRF')

@TrueBrain TrueBrain force-pushed the happy-eyeballs branch 8 times, most recently from 0efffe0 to 239661f Compare May 6, 2021 17:47
@TrueBrain TrueBrain marked this pull request as ready for review May 6, 2021 17:47
@TrueBrain TrueBrain force-pushed the happy-eyeballs branch 3 times, most recently from 3718d3b to 678e0b5 Compare May 6, 2021 17:59
src/network/core/tcp_connect.cpp Outdated Show resolved Hide resolved
src/network/core/tcp_connect.cpp Outdated Show resolved Hide resolved
src/network/core/tcp_connect.cpp Outdated Show resolved Hide resolved
src/network/core/tcp_connect.cpp Outdated Show resolved Hide resolved
src/network/core/tcp_connect.cpp Outdated Show resolved Hide resolved
@TrueBrain TrueBrain force-pushed the happy-eyeballs branch 2 times, most recently from 3f3ab60 to 36a7af9 Compare May 6, 2021 19:00
src/network/core/tcp_connect.cpp Show resolved Hide resolved
src/network/core/tcp_connect.cpp Outdated Show resolved Hide resolved
src/network/core/tcp_connect.cpp Outdated Show resolved Hide resolved
src/network/core/tcp_connect.cpp Outdated Show resolved Hide resolved
src/network/core/tcp_connect.cpp Outdated Show resolved Hide resolved
src/network/core/tcp_connect.cpp Show resolved Hide resolved
src/network/network_udp.cpp Outdated Show resolved Hide resolved
@TrueBrain TrueBrain force-pushed the happy-eyeballs branch 2 times, most recently from bf5114f to 8bba206 Compare May 6, 2021 20:27
Hostnames like "content.openttd.org" resolve into multiple IPv4 and IPv6.
It is possible that either of the IPs is not working, either due to
a poorly configured OS (having IPv6 but no valid route), broken network
paths, or a service that is temporary unavailable.

Instead of trying the IPs one by one, waiting for a 3s timeout between
each, be a bit more like browsers, and stack attempts on top of each
other with slight delays. This is called Happy Eyebells.

Initially, try the first IPv6 address. If within 250ms there is no
connection yet, try the first IPv4 address. 250ms later, try the
second IPv6 address, etc, till all addresses are tried.

If any connection is created, abort all the other (pending) connections
and use the one that is created. If all fail 3s after the last connect(),
trigger a timeout for all.
@TrueBrain TrueBrain merged commit f7e390b into OpenTTD:master May 6, 2021
@TrueBrain TrueBrain deleted the happy-eyeballs branch May 6, 2021 21:13
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.

None yet

2 participants