summaryrefslogtreecommitdiff
path: root/src/network/core/tcp.h
diff options
context:
space:
mode:
authorPatric Stout <truebrain@openttd.org>2021-05-06 23:13:35 +0200
committerGitHub <noreply@github.com>2021-05-06 23:13:35 +0200
commitf7e390bdc084a20462fe833373087fd9106c5972 (patch)
tree26122beb7a783b37132bbe60ba13966ac87843b1 /src/network/core/tcp.h
parentf1dfa661a1898cde06a38ab4cb230c95912b245b (diff)
downloadopenttd-f7e390bdc084a20462fe833373087fd9106c5972.tar.xz
Feature: use Happy Eyeballs to make network connections (TCP-only) (#9199)
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.
Diffstat (limited to 'src/network/core/tcp.h')
-rw-r--r--src/network/core/tcp.h28
1 files changed, 17 insertions, 11 deletions
diff --git a/src/network/core/tcp.h b/src/network/core/tcp.h
index 5acf9d12e..b90ce0232 100644
--- a/src/network/core/tcp.h
+++ b/src/network/core/tcp.h
@@ -15,6 +15,7 @@
#include "address.h"
#include "packet.h"
+#include <chrono>
#include <atomic>
/** The states of sending the packets. */
@@ -63,23 +64,28 @@ public:
*/
class TCPConnecter {
private:
- std::atomic<bool> connected;///< Whether we succeeded in making the connection
- std::atomic<bool> aborted; ///< Whether we bailed out (i.e. connection making failed)
- bool killed; ///< Whether we got killed
- SOCKET sock; ///< The socket we're connecting with
+ addrinfo *ai = nullptr; ///< getaddrinfo() allocated linked-list of resolved addresses.
+ std::vector<addrinfo *> addresses; ///< Addresses we can connect to.
+ size_t current_address = 0; ///< Current index in addresses we are trying.
- void Connect();
+ std::vector<SOCKET> sockets; ///< Pending connect() attempts.
+ std::chrono::steady_clock::time_point last_attempt; ///< Time we last tried to connect.
- static void ThreadEntry(TCPConnecter *param);
+ std::atomic<bool> is_resolved = false; ///< Whether resolving is done.
-protected:
- /** Address we're connecting to */
- NetworkAddress address;
+ void Resolve();
+ void OnResolved(addrinfo *ai);
+ bool TryNextAddress();
+ void Connect(addrinfo *address);
+ bool CheckActivity();
+
+ static void ResolveThunk(TCPConnecter *connecter);
public:
+ std::string connection_string; ///< Current address we are connecting to (before resolving).
+
TCPConnecter(const std::string &connection_string, uint16 default_port);
- /** Silence the warnings */
- virtual ~TCPConnecter() {}
+ virtual ~TCPConnecter();
/**
* Callback when the connection succeeded.