summaryrefslogtreecommitdiff
path: root/src/network/network.cpp
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/network.cpp
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/network.cpp')
-rw-r--r--src/network/network.cpp41
1 files changed, 29 insertions, 12 deletions
diff --git a/src/network/network.cpp b/src/network/network.cpp
index 83a93a22e..bbf6bb5de 100644
--- a/src/network/network.cpp
+++ b/src/network/network.cpp
@@ -502,6 +502,19 @@ std::string_view ParseFullConnectionString(const std::string &connection_string,
}
/**
+ * Normalize a connection string. That is, ensure there is a port in the string.
+ * @param connection_string The connection string to normalize.
+ * @param default_port The port to use if none is given.
+ * @return The normalized connection string.
+ */
+std::string NormalizeConnectionString(const std::string &connection_string, uint16 default_port)
+{
+ uint16 port = default_port;
+ std::string_view ip = ParseFullConnectionString(connection_string, port);
+ return std::string(ip) + ":" + std::to_string(port);
+}
+
+/**
* Convert a string containing either "hostname" or "hostname:ip" to a
* NetworkAddress.
*
@@ -1131,23 +1144,27 @@ static void NetworkGenerateServerId()
seprintf(_settings_client.network.network_id, lastof(_settings_client.network.network_id), "%s", hex_output);
}
-void NetworkStartDebugLog(const std::string &connection_string)
-{
- extern SOCKET _debug_socket; // Comes from debug.c
+class TCPNetworkDebugConnecter : TCPConnecter {
+public:
+ TCPNetworkDebugConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_DEFAULT_DEBUGLOG_PORT) {}
- NetworkAddress address = ParseConnectionString(connection_string, NETWORK_DEFAULT_DEBUGLOG_PORT);
+ void OnFailure() override
+ {
+ DEBUG(net, 0, "Failed to open connection to %s for redirecting DEBUG()", this->connection_string.c_str());
+ }
- DEBUG(net, 0, "Redirecting DEBUG() to %s", address.GetAddressAsString().c_str());
+ void OnConnect(SOCKET s) override
+ {
+ DEBUG(net, 0, "Redirecting DEBUG() to %s", this->connection_string.c_str());
- SOCKET s = address.Connect();
- if (s == INVALID_SOCKET) {
- DEBUG(net, 0, "Failed to open socket for redirection DEBUG()");
- return;
+ extern SOCKET _debug_socket;
+ _debug_socket = s;
}
+};
- _debug_socket = s;
-
- DEBUG(net, 0, "DEBUG() is now redirected");
+void NetworkStartDebugLog(const std::string &connection_string)
+{
+ new TCPNetworkDebugConnecter(connection_string);
}
/** This tries to launch the network for a given OS */