1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
8 /**
9  * @file tcp_connect.cpp Basic functions to create connections without blocking.
10  */
11 
12 #include "../../stdafx.h"
13 #include "../../thread.h"
14 
15 #include "tcp.h"
16 #include "../network_coordinator.h"
17 #include "../network_internal.h"
18 
19 #include <deque>
20 
21 #include "../../safeguards.h"
22 
23 /** List of connections that are currently being created */
24 static std::vector<TCPConnecter *> _tcp_connecters;
25 
26 /**
27  * Create a new connecter for the given address.
28  * @param connection_string The address to connect to.
29  * @param default_port If not indicated in connection_string, what port to use.
30  * @param bind_address The local bind address to use. Defaults to letting the OS find one.
31  */
TCPConnecter(const std::string & connection_string,uint16 default_port,NetworkAddress bind_address,int family)32 TCPConnecter::TCPConnecter(const std::string &connection_string, uint16 default_port, NetworkAddress bind_address, int family) :
33 	bind_address(bind_address),
34 	family(family)
35 {
36 	this->connection_string = NormalizeConnectionString(connection_string, default_port);
37 
38 	_tcp_connecters.push_back(this);
39 }
40 
41 /**
42  * Create a new connecter for the server.
43  * @param connection_string The address to connect to.
44  * @param default_port If not indicated in connection_string, what port to use.
45  */
TCPServerConnecter(const std::string & connection_string,uint16 default_port)46 TCPServerConnecter::TCPServerConnecter(const std::string &connection_string, uint16 default_port) :
47 	server_address(ServerAddress::Parse(connection_string, default_port))
48 {
49 	switch (this->server_address.type) {
50 		case SERVER_ADDRESS_DIRECT:
51 			this->connection_string = this->server_address.connection_string;
52 			break;
53 
54 		case SERVER_ADDRESS_INVITE_CODE:
55 			this->status = Status::CONNECTING;
56 			_network_coordinator_client.ConnectToServer(this->server_address.connection_string, this);
57 			break;
58 
59 		default:
60 			NOT_REACHED();
61 	}
62 
63 	_tcp_connecters.push_back(this);
64 }
65 
~TCPConnecter()66 TCPConnecter::~TCPConnecter()
67 {
68 	if (this->resolve_thread.joinable()) {
69 		this->resolve_thread.join();
70 	}
71 
72 	for (const auto &socket : this->sockets) {
73 		closesocket(socket);
74 	}
75 	this->sockets.clear();
76 	this->sock_to_address.clear();
77 
78 	if (this->ai != nullptr) freeaddrinfo(this->ai);
79 }
80 
81 /**
82  * Kill this connecter.
83  * It will abort as soon as it can and not call any of the callbacks.
84  */
Kill()85 void TCPConnecter::Kill()
86 {
87 	/* Delay the removing of the socket till the next CheckActivity(). */
88 	this->killed = true;
89 }
90 
91 /**
92  * Start a connection to the indicated address.
93  * @param address The address to connection to.
94  */
Connect(addrinfo * address)95 void TCPConnecter::Connect(addrinfo *address)
96 {
97 	SOCKET sock = socket(address->ai_family, address->ai_socktype, address->ai_protocol);
98 	if (sock == INVALID_SOCKET) {
99 		Debug(net, 0, "Could not create {} {} socket: {}", NetworkAddress::SocketTypeAsString(address->ai_socktype), NetworkAddress::AddressFamilyAsString(address->ai_family), NetworkError::GetLast().AsString());
100 		return;
101 	}
102 
103 	if (!SetReusePort(sock)) {
104 		Debug(net, 0, "Setting reuse-port mode failed: {}", NetworkError::GetLast().AsString());
105 	}
106 
107 	if (this->bind_address.GetPort() > 0) {
108 		if (bind(sock, (const sockaddr *)this->bind_address.GetAddress(), this->bind_address.GetAddressLength()) != 0) {
109 			Debug(net, 1, "Could not bind socket on {}: {}", this->bind_address.GetAddressAsString(), NetworkError::GetLast().AsString());
110 			closesocket(sock);
111 			return;
112 		}
113 	}
114 
115 	if (!SetNoDelay(sock)) {
116 		Debug(net, 1, "Setting TCP_NODELAY failed: {}", NetworkError::GetLast().AsString());
117 	}
118 	if (!SetNonBlocking(sock)) {
119 		Debug(net, 0, "Setting non-blocking mode failed: {}", NetworkError::GetLast().AsString());
120 	}
121 
122 	NetworkAddress network_address = NetworkAddress(address->ai_addr, (int)address->ai_addrlen);
123 	Debug(net, 5, "Attempting to connect to {}", network_address.GetAddressAsString());
124 
125 	int err = connect(sock, address->ai_addr, (int)address->ai_addrlen);
126 	if (err != 0 && !NetworkError::GetLast().IsConnectInProgress()) {
127 		closesocket(sock);
128 
129 		Debug(net, 1, "Could not connect to {}: {}", network_address.GetAddressAsString(), NetworkError::GetLast().AsString());
130 		return;
131 	}
132 
133 	this->sock_to_address[sock] = network_address;
134 	this->sockets.push_back(sock);
135 }
136 
137 /**
138  * Start the connect() for the next address in the list.
139  * @return True iff a new connect() is attempted.
140  */
TryNextAddress()141 bool TCPConnecter::TryNextAddress()
142 {
143 	if (this->current_address >= this->addresses.size()) return false;
144 
145 	this->last_attempt = std::chrono::steady_clock::now();
146 	this->Connect(this->addresses[this->current_address++]);
147 
148 	return true;
149 }
150 
151 /**
152  * Callback when resolving is done.
153  * @param ai A linked-list of address information.
154  */
OnResolved(addrinfo * ai)155 void TCPConnecter::OnResolved(addrinfo *ai)
156 {
157 	std::deque<addrinfo *> addresses_ipv4, addresses_ipv6;
158 
159 	/* Apply "Happy Eyeballs" if it is likely IPv6 is functional. */
160 
161 	/* Detect if IPv6 is likely to succeed or not. */
162 	bool seen_ipv6 = false;
163 	bool resort = true;
164 	for (addrinfo *runp = ai; runp != nullptr; runp = runp->ai_next) {
165 		if (runp->ai_family == AF_INET6) {
166 			seen_ipv6 = true;
167 		} else if (!seen_ipv6) {
168 			/* We see an IPv4 before an IPv6; this most likely means there is
169 			 * no IPv6 available on the system, so keep the order of this
170 			 * list. */
171 			resort = false;
172 			break;
173 		}
174 	}
175 
176 	/* Convert the addrinfo into NetworkAddresses. */
177 	for (addrinfo *runp = ai; runp != nullptr; runp = runp->ai_next) {
178 		/* Skip entries if the family is set and it is not matching. */
179 		if (this->family != AF_UNSPEC && this->family != runp->ai_family) continue;
180 
181 		if (resort) {
182 			if (runp->ai_family == AF_INET6) {
183 				addresses_ipv6.emplace_back(runp);
184 			} else {
185 				addresses_ipv4.emplace_back(runp);
186 			}
187 		} else {
188 			this->addresses.emplace_back(runp);
189 		}
190 	}
191 
192 	/* If we want to resort, make the list like IPv6 / IPv4 / IPv6 / IPv4 / ..
193 	 * for how ever many (round-robin) DNS entries we have. */
194 	if (resort) {
195 		while (!addresses_ipv4.empty() || !addresses_ipv6.empty()) {
196 			if (!addresses_ipv6.empty()) {
197 				this->addresses.push_back(addresses_ipv6.front());
198 				addresses_ipv6.pop_front();
199 			}
200 			if (!addresses_ipv4.empty()) {
201 				this->addresses.push_back(addresses_ipv4.front());
202 				addresses_ipv4.pop_front();
203 			}
204 		}
205 	}
206 
207 	if (_debug_net_level >= 6) {
208 		if (this->addresses.size() == 0) {
209 			Debug(net, 6, "{} did not resolve", this->connection_string);
210 		} else {
211 			Debug(net, 6, "{} resolved in:", this->connection_string);
212 			for (const auto &address : this->addresses) {
213 				Debug(net, 6, "- {}", NetworkAddress(address->ai_addr, (int)address->ai_addrlen).GetAddressAsString());
214 			}
215 		}
216 	}
217 
218 	this->current_address = 0;
219 }
220 
221 /**
222  * Start resolving the hostname.
223  *
224  * This function must change "status" to either Status::FAILURE
225  * or Status::CONNECTING before returning.
226  */
Resolve()227 void TCPConnecter::Resolve()
228 {
229 	/* Port is already guaranteed part of the connection_string. */
230 	NetworkAddress address = ParseConnectionString(this->connection_string, 0);
231 
232 	addrinfo hints;
233 	memset(&hints, 0, sizeof(hints));
234 	hints.ai_family = AF_UNSPEC;
235 	hints.ai_flags = AI_ADDRCONFIG;
236 	hints.ai_socktype = SOCK_STREAM;
237 
238 	char port_name[6];
239 	seprintf(port_name, lastof(port_name), "%u", address.GetPort());
240 
241 	static bool getaddrinfo_timeout_error_shown = false;
242 	auto start = std::chrono::steady_clock::now();
243 
244 	addrinfo *ai;
245 	int error = getaddrinfo(address.GetHostname().c_str(), port_name, &hints, &ai);
246 
247 	auto end = std::chrono::steady_clock::now();
248 	auto duration = std::chrono::duration_cast<std::chrono::seconds>(end - start);
249 	if (!getaddrinfo_timeout_error_shown && duration >= std::chrono::seconds(5)) {
250 		Debug(net, 0, "getaddrinfo() for address \"{}\" took {} seconds", this->connection_string, duration.count());
251 		Debug(net, 0, "  This is likely an issue in the DNS name resolver's configuration causing it to time out");
252 		getaddrinfo_timeout_error_shown = true;
253 	}
254 
255 	if (error != 0) {
256 		Debug(net, 0, "Failed to resolve DNS for {}", this->connection_string);
257 		this->status = Status::FAILURE;
258 		return;
259 	}
260 
261 	this->ai = ai;
262 	this->OnResolved(ai);
263 
264 	this->status = Status::CONNECTING;
265 }
266 
267 /**
268  * Thunk to start Resolve() on the right instance.
269  */
ResolveThunk(TCPConnecter * connecter)270 /* static */ void TCPConnecter::ResolveThunk(TCPConnecter *connecter)
271 {
272 	connecter->Resolve();
273 }
274 
275 /**
276  * Check if there was activity for this connecter.
277  * @return True iff the TCPConnecter is done and can be cleaned up.
278  */
CheckActivity()279 bool TCPConnecter::CheckActivity()
280 {
281 	if (this->killed) return true;
282 
283 	switch (this->status) {
284 		case Status::INIT:
285 			/* Start the thread delayed, so the vtable is loaded. This allows classes
286 			 * to overload functions used by Resolve() (in case threading is disabled). */
287 			if (StartNewThread(&this->resolve_thread, "ottd:resolve", &TCPConnecter::ResolveThunk, this)) {
288 				this->status = Status::RESOLVING;
289 				return false;
290 			}
291 
292 			/* No threads, do a blocking resolve. */
293 			this->Resolve();
294 
295 			/* Continue as we are either failed or can start the first
296 			 * connection. The rest of this function handles exactly that. */
297 			break;
298 
299 		case Status::RESOLVING:
300 			/* Wait till Resolve() comes back with an answer (in case it runs threaded). */
301 			return false;
302 
303 		case Status::FAILURE:
304 			/* Ensure the OnFailure() is called from the game-thread instead of the
305 			 * resolve-thread, as otherwise we can get into some threading issues. */
306 			this->OnFailure();
307 			return true;
308 
309 		case Status::CONNECTING:
310 		case Status::CONNECTED:
311 			break;
312 	}
313 
314 	/* If there are no attempts pending, connect to the next. */
315 	if (this->sockets.empty()) {
316 		if (!this->TryNextAddress()) {
317 			/* There were no more addresses to try, so we failed. */
318 			this->OnFailure();
319 			return true;
320 		}
321 		return false;
322 	}
323 
324 	fd_set write_fd;
325 	FD_ZERO(&write_fd);
326 	for (const auto &socket : this->sockets) {
327 		FD_SET(socket, &write_fd);
328 	}
329 
330 	timeval tv;
331 	tv.tv_usec = 0;
332 	tv.tv_sec = 0;
333 	int n = select(FD_SETSIZE, nullptr, &write_fd, nullptr, &tv);
334 	/* select() failed; hopefully next try it doesn't. */
335 	if (n < 0) {
336 		/* select() normally never fails; so hopefully it works next try! */
337 		Debug(net, 1, "select() failed: {}", NetworkError::GetLast().AsString());
338 		return false;
339 	}
340 
341 	/* No socket updates. */
342 	if (n == 0) {
343 		/* Wait 250ms between attempting another address. */
344 		if (std::chrono::steady_clock::now() < this->last_attempt + std::chrono::milliseconds(250)) return false;
345 
346 		/* Try the next address in the list. */
347 		if (this->TryNextAddress()) return false;
348 
349 		/* Wait up to 3 seconds since the last connection we started. */
350 		if (std::chrono::steady_clock::now() < this->last_attempt + std::chrono::milliseconds(3000)) return false;
351 
352 		/* More than 3 seconds no socket reported activity, and there are no
353 		 * more address to try. Timeout the attempt. */
354 		Debug(net, 0, "Timeout while connecting to {}", this->connection_string);
355 
356 		for (const auto &socket : this->sockets) {
357 			closesocket(socket);
358 		}
359 		this->sockets.clear();
360 		this->sock_to_address.clear();
361 
362 		this->OnFailure();
363 		return true;
364 	}
365 
366 	/* Check for errors on any of the sockets. */
367 	for (auto it = this->sockets.begin(); it != this->sockets.end(); /* nothing */) {
368 		NetworkError socket_error = GetSocketError(*it);
369 		if (socket_error.HasError()) {
370 			Debug(net, 1, "Could not connect to {}: {}", this->sock_to_address[*it].GetAddressAsString(), socket_error.AsString());
371 			closesocket(*it);
372 			this->sock_to_address.erase(*it);
373 			it = this->sockets.erase(it);
374 		} else {
375 			it++;
376 		}
377 	}
378 
379 	/* In case all sockets had an error, queue a new one. */
380 	if (this->sockets.empty()) {
381 		if (!this->TryNextAddress()) {
382 			/* There were no more addresses to try, so we failed. */
383 			this->OnFailure();
384 			return true;
385 		}
386 		return false;
387 	}
388 
389 	/* At least one socket is connected. The first one that does is the one
390 	 * we will be using, and we close all other sockets. */
391 	SOCKET connected_socket = INVALID_SOCKET;
392 	for (auto it = this->sockets.begin(); it != this->sockets.end(); /* nothing */) {
393 		if (connected_socket == INVALID_SOCKET && FD_ISSET(*it, &write_fd)) {
394 			connected_socket = *it;
395 		} else {
396 			closesocket(*it);
397 		}
398 		this->sock_to_address.erase(*it);
399 		it = this->sockets.erase(it);
400 	}
401 	assert(connected_socket != INVALID_SOCKET);
402 
403 	Debug(net, 3, "Connected to {}", this->connection_string);
404 	if (_debug_net_level >= 5) {
405 		Debug(net, 5, "- using {}", NetworkAddress::GetPeerName(connected_socket));
406 	}
407 
408 	this->OnConnect(connected_socket);
409 	this->status = Status::CONNECTED;
410 	return true;
411 }
412 
413 /**
414  * Check if there was activity for this connecter.
415  * @return True iff the TCPConnecter is done and can be cleaned up.
416  */
CheckActivity()417 bool TCPServerConnecter::CheckActivity()
418 {
419 	if (this->killed) return true;
420 
421 	switch (this->server_address.type) {
422 		case SERVER_ADDRESS_DIRECT:
423 			return TCPConnecter::CheckActivity();
424 
425 		case SERVER_ADDRESS_INVITE_CODE:
426 			/* Check if a result has come in. */
427 			switch (this->status) {
428 				case Status::FAILURE:
429 					this->OnFailure();
430 					return true;
431 
432 				case Status::CONNECTED:
433 					this->OnConnect(this->socket);
434 					return true;
435 
436 				default:
437 					break;
438 			}
439 
440 			return false;
441 
442 		default:
443 			NOT_REACHED();
444 	}
445 }
446 
447 /**
448  * The connection was successfully established.
449  * This socket is fully setup and ready to send/recv game protocol packets.
450  * @param sock The socket of the established connection.
451  */
SetConnected(SOCKET sock)452 void TCPServerConnecter::SetConnected(SOCKET sock)
453 {
454 	this->socket = sock;
455 	this->status = Status::CONNECTED;
456 }
457 
458 /**
459  * The connection couldn't be established.
460  */
SetFailure()461 void TCPServerConnecter::SetFailure()
462 {
463 	this->status = Status::FAILURE;
464 }
465 
466 /**
467  * Check whether we need to call the callback, i.e. whether we
468  * have connected or aborted and call the appropriate callback
469  * for that. It's done this way to ease on the locking that
470  * would otherwise be needed everywhere.
471  */
CheckCallbacks()472 /* static */ void TCPConnecter::CheckCallbacks()
473 {
474 	for (auto iter = _tcp_connecters.begin(); iter < _tcp_connecters.end(); /* nothing */) {
475 		TCPConnecter *cur = *iter;
476 
477 		if (cur->CheckActivity()) {
478 			iter = _tcp_connecters.erase(iter);
479 			delete cur;
480 		} else {
481 			iter++;
482 		}
483 	}
484 }
485 
486 /** Kill all connection attempts. */
KillAll()487 /* static */ void TCPConnecter::KillAll()
488 {
489 	for (auto iter = _tcp_connecters.begin(); iter < _tcp_connecters.end(); /* nothing */) {
490 		TCPConnecter *cur = *iter;
491 		iter = _tcp_connecters.erase(iter);
492 		delete cur;
493 	}
494 }
495