OpenTTD Source  12.0-beta2
network_coordinator.cpp
Go to the documentation of this file.
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 
10 #include "../stdafx.h"
11 #include "../debug.h"
12 #include "../error.h"
13 #include "../rev.h"
14 #include "../settings_type.h"
15 #include "../strings_func.h"
16 #include "../window_func.h"
17 #include "../window_type.h"
18 #include "network.h"
19 #include "network_coordinator.h"
20 #include "network_gamelist.h"
21 #include "network_gui.h"
22 #include "network_internal.h"
23 #include "network_server.h"
24 #include "network_stun.h"
25 #include "table/strings.h"
26 
27 #include "../safeguards.h"
28 
29 static const auto NETWORK_COORDINATOR_DELAY_BETWEEN_UPDATES = std::chrono::seconds(30);
32 std::string _network_server_invite_code = "";
33 
36 private:
37  std::string token;
39 
40 public:
48  NetworkDirectConnecter(const std::string &hostname, uint16 port, const std::string &token, uint8 tracking_number) : TCPConnecter(hostname, port), token(token), tracking_number(tracking_number) {}
49 
50  void OnFailure() override
51  {
52  _network_coordinator_client.ConnectFailure(this->token, this->tracking_number);
53  }
54 
55  void OnConnect(SOCKET s) override
56  {
58  _network_coordinator_client.ConnectSuccess(this->token, s, address);
59  }
60 };
61 
64 private:
65  std::string token;
67  uint8 family;
68 
69 public:
79  NetworkReuseStunConnecter(const std::string &hostname, uint16 port, const NetworkAddress &bind_address, std::string token, uint8 tracking_number, uint8 family) :
80  TCPConnecter(hostname, port, bind_address),
81  token(token),
83  family(family)
84  {
85  }
86 
87  void OnFailure() override
88  {
89  /* Close the STUN connection too, as it is no longer of use. */
90  _network_coordinator_client.CloseStunHandler(this->token, this->family);
91 
92  _network_coordinator_client.ConnectFailure(this->token, this->tracking_number);
93  }
94 
95  void OnConnect(SOCKET s) override
96  {
98  _network_coordinator_client.ConnectSuccess(this->token, s, address);
99  }
100 };
101 
104 public:
110 
111  void OnFailure() override
112  {
115  }
116 
117  void OnConnect(SOCKET s) override
118  {
119  assert(_network_coordinator_client.sock == INVALID_SOCKET);
120 
122  _network_coordinator_client.last_activity = std::chrono::steady_clock::now();
124  }
125 };
126 
128 {
130  std::string detail = p->Recv_string(NETWORK_ERROR_DETAIL_LENGTH);
131 
132  switch (error) {
134  this->CloseConnection();
135  return false;
136 
138  ShowErrorMessage(STR_NETWORK_ERROR_COORDINATOR_REGISTRATION_FAILED, INVALID_STRING_ID, WL_ERROR);
139 
140  /* To prevent that we constantly try to reconnect, switch to local game. */
141  _settings_client.network.server_game_type = SERVER_GAME_TYPE_LOCAL;
142 
143  this->CloseConnection();
144  return false;
145 
147  auto connecter_pre_it = this->connecter_pre.find(detail);
148  if (connecter_pre_it != this->connecter_pre.end()) {
149  connecter_pre_it->second->SetFailure();
150  this->connecter_pre.erase(connecter_pre_it);
151  }
152 
153  /* Mark the server as offline. */
154  NetworkGameList *item = NetworkGameListAddItem(detail);
155  item->online = false;
156 
158  return true;
159  }
160 
162  ShowErrorMessage(STR_NETWORK_ERROR_COORDINATOR_REUSE_OF_INVITE_CODE, INVALID_STRING_ID, WL_ERROR);
163 
164  /* To prevent that we constantly battle for the same invite-code, switch to local game. */
165  _settings_client.network.server_game_type = SERVER_GAME_TYPE_LOCAL;
166 
167  this->CloseConnection();
168  return false;
169 
170  default:
171  Debug(net, 0, "Invalid error type {} received from Game Coordinator", error);
172  this->CloseConnection();
173  return false;
174  }
175 }
176 
178 {
179  /* Schedule sending an update. */
180  this->next_update = std::chrono::steady_clock::now();
181 
185 
187  ShowErrorMessage(STR_NETWORK_ERROR_COORDINATOR_ISOLATED, STR_NETWORK_ERROR_COORDINATOR_ISOLATED_DETAIL, WL_ERROR);
188  }
189 
190  /* Users can change the invite code in the settings, but this has no effect
191  * on the invite code as assigned by the server. So
192  * _network_server_invite_code contains the current invite code,
193  * and _settings_client.network.server_invite_code contains the one we will
194  * attempt to re-use when registering again. */
196 
198 
199  if (_network_dedicated) {
200  std::string connection_type;
202  case CONNECTION_TYPE_ISOLATED: connection_type = "Remote players can't connect"; break;
203  case CONNECTION_TYPE_DIRECT: connection_type = "Public"; break;
204  case CONNECTION_TYPE_STUN: connection_type = "Behind NAT"; break;
205  case CONNECTION_TYPE_TURN: connection_type = "Via relay"; break;
206 
207  case CONNECTION_TYPE_UNKNOWN: // Never returned from Game Coordinator.
208  default: connection_type = "Unknown"; break; // Should never happen, but don't fail if it does.
209  }
210 
211  std::string game_type;
213  case SERVER_GAME_TYPE_INVITE_ONLY: game_type = "Invite only"; break;
214  case SERVER_GAME_TYPE_PUBLIC: game_type = "Public"; break;
215 
216  case SERVER_GAME_TYPE_LOCAL: // Impossible to register local servers.
217  default: game_type = "Unknown"; break; // Should never happen, but don't fail if it does.
218  }
219 
220  Debug(net, 3, "----------------------------------------");
221  Debug(net, 3, "Your server is now registered with the Game Coordinator:");
222  Debug(net, 3, " Game type: {}", game_type);
223  Debug(net, 3, " Connection type: {}", connection_type);
224  Debug(net, 3, " Invite code: {}", _network_server_invite_code);
225  Debug(net, 3, "----------------------------------------");
226  } else {
227  Debug(net, 3, "Game Coordinator registered our server with invite code '{}'", _network_server_invite_code);
228  }
229 
230  return true;
231 }
232 
234 {
235  uint8 servers = p->Recv_uint16();
236 
237  /* End of list; we can now remove all expired items from the list. */
238  if (servers == 0) {
240  return true;
241  }
242 
243  for (; servers > 0; servers--) {
244  std::string connection_string = p->Recv_string(NETWORK_HOSTNAME_PORT_LENGTH);
245 
246  /* Read the NetworkGameInfo from the packet. */
247  NetworkGameInfo ngi = {};
249 
250  /* Now we know the connection string, we can add it to our list. */
251  NetworkGameList *item = NetworkGameListAddItem(connection_string);
252 
253  /* Clear any existing GRFConfig chain. */
255  /* Copy the new NetworkGameInfo info. */
256  item->info = ngi;
257  /* Check for compatability with the client. */
259  /* Mark server as online. */
260  item->online = true;
261  /* Mark the item as up-to-date. */
263  }
264 
266  return true;
267 }
268 
270 {
271  std::string token = p->Recv_string(NETWORK_TOKEN_LENGTH);
272  std::string invite_code = p->Recv_string(NETWORK_INVITE_CODE_LENGTH);
273 
274  /* Find the connecter based on the invite code. */
275  auto connecter_pre_it = this->connecter_pre.find(invite_code);
276  if (connecter_pre_it == this->connecter_pre.end()) {
277  this->CloseConnection();
278  return false;
279  }
280 
281  /* Now store it based on the token. */
282  this->connecter[token] = {invite_code, connecter_pre_it->second};
283  this->connecter_pre.erase(connecter_pre_it);
284 
285  return true;
286 }
287 
289 {
290  std::string token = p->Recv_string(NETWORK_TOKEN_LENGTH);
291  this->CloseToken(token);
292 
293  return true;
294 }
295 
297 {
298  std::string token = p->Recv_string(NETWORK_TOKEN_LENGTH);
299  uint8 tracking_number = p->Recv_uint8();
300  std::string hostname = p->Recv_string(NETWORK_HOSTNAME_LENGTH);
301  uint16 port = p->Recv_uint16();
302 
303  /* Ensure all other pending connection attempts are killed. */
304  if (this->game_connecter != nullptr) {
305  this->game_connecter->Kill();
306  this->game_connecter = nullptr;
307  }
308 
309  this->game_connecter = new NetworkDirectConnecter(hostname, port, token, tracking_number);
310  return true;
311 }
312 
314 {
315  std::string token = p->Recv_string(NETWORK_TOKEN_LENGTH);
316 
317  this->stun_handlers[token][AF_INET6] = ClientNetworkStunSocketHandler::Stun(token, AF_INET6);
318  this->stun_handlers[token][AF_INET] = ClientNetworkStunSocketHandler::Stun(token, AF_INET);
319  return true;
320 }
321 
323 {
324  std::string token = p->Recv_string(NETWORK_TOKEN_LENGTH);
325  uint8 tracking_number = p->Recv_uint8();
326  uint8 family = p->Recv_uint8();
327  std::string host = p->Recv_string(NETWORK_HOSTNAME_PORT_LENGTH);
328  uint16 port = p->Recv_uint16();
329 
330  /* Check if we know this token. */
331  auto stun_it = this->stun_handlers.find(token);
332  if (stun_it == this->stun_handlers.end()) return true;
333  auto family_it = stun_it->second.find(family);
334  if (family_it == stun_it->second.end()) return true;
335 
336  /* Ensure all other pending connection attempts are killed. */
337  if (this->game_connecter != nullptr) {
338  this->game_connecter->Kill();
339  this->game_connecter = nullptr;
340  }
341 
342  /* We now mark the connection as closed, but we do not really close the
343  * socket yet. We do this when the NetworkReuseStunConnecter is connected.
344  * This prevents any NAT to already remove the route while we create the
345  * second connection on top of the first. */
346  family_it->second->CloseConnection(false);
347 
348  /* Connect to our peer from the same local address as we use for the
349  * STUN server. This means that if there is any NAT in the local network,
350  * the public ip:port is still pointing to the local address, and as such
351  * a connection can be established. */
352  this->game_connecter = new NetworkReuseStunConnecter(host, port, family_it->second->local_addr, token, tracking_number, family);
353  return true;
354 }
355 
357 {
359 
360  uint16 newgrfs = p->Recv_uint16();
361  for (; newgrfs> 0; newgrfs--) {
362  uint32 index = p->Recv_uint32();
364  }
365  return true;
366 }
367 
369 {
370  std::string token = p->Recv_string(NETWORK_TOKEN_LENGTH);
371  uint8 tracking_number = p->Recv_uint8();
372  std::string ticket = p->Recv_string(NETWORK_TOKEN_LENGTH);
373  std::string connection_string = p->Recv_string(NETWORK_HOSTNAME_PORT_LENGTH);
374 
375  /* Ensure all other pending connection attempts are killed. */
376  if (this->game_connecter != nullptr) {
377  this->game_connecter->Kill();
378  this->game_connecter = nullptr;
379  }
380 
381  Debug(misc, 0, "{}", ticket);
382  this->turn_handlers[token] = ClientNetworkTurnSocketHandler::Turn(token, tracking_number, ticket, connection_string);
383 
384  if (!_network_server) {
385  auto connecter_it = this->connecter.find(token);
386  if (connecter_it == this->connecter.end()) {
387  /* Make sure we are still interested in connecting to this server. */
388  this->ConnectFailure(token, 0);
389  return true;
390  }
391 
393  case URS_NEVER:
394  this->ConnectFailure(token, 0);
395  break;
396 
397  case URS_ASK:
398  ShowNetworkAskRelay(connecter_it->second.first, connection_string, token);
399  break;
400 
401  case URS_ALLOW:
402  this->StartTurnConnection(token);
403  break;
404  }
405  } else {
406  this->StartTurnConnection(token);
407  }
408 
409  return true;
410 }
411 
412 void ClientNetworkCoordinatorSocketHandler::StartTurnConnection(std::string &token)
413 {
414  auto turn_it = this->turn_handlers.find(token);
415  if (turn_it == this->turn_handlers.end()) return;
416 
417  turn_it->second->Connect();
418 }
419 
420 void ClientNetworkCoordinatorSocketHandler::Connect()
421 {
422  /* We are either already connected or are trying to connect. */
423  if (this->sock != INVALID_SOCKET || this->connecting) return;
424 
425  this->Reopen();
426 
427  this->connecting = true;
428  this->last_activity = std::chrono::steady_clock::now();
429 
431 }
432 
434 {
436 
437  this->CloseSocket();
438  this->connecting = false;
439 
441  this->next_update = {};
442 
443  this->CloseAllConnections();
444 
446 
448 }
449 
454 {
456  this->next_update = {};
457 
459 
460  this->Connect();
461 
467  p->Send_string("");
468  p->Send_string("");
469  } else {
472  }
473 
474  this->SendPacket(p);
475 }
476 
481 {
482  Debug(net, 6, "Sending server update to Game Coordinator");
483 
486  SerializeNetworkGameInfo(p, GetCurrentNetworkServerGameInfo(), this->next_update.time_since_epoch() != std::chrono::nanoseconds::zero());
487 
488  this->SendPacket(p);
489 
490  this->next_update = std::chrono::steady_clock::now() + NETWORK_COORDINATOR_DELAY_BETWEEN_UPDATES;
491 }
492 
497 {
498  this->Connect();
499 
501 
505  p->Send_string(_openttd_revision);
507 
508  this->SendPacket(p);
509 }
510 
516 void ClientNetworkCoordinatorSocketHandler::ConnectToServer(const std::string &invite_code, TCPServerConnecter *connecter)
517 {
518  assert(StrStartsWith(invite_code, "+"));
519 
520  if (this->connecter_pre.find(invite_code) != this->connecter_pre.end()) {
521  /* If someone is hammering the refresh key, one can sent out two
522  * requests for the same invite code. There isn't really a great way
523  * of handling this, so just ignore this request. */
524  connecter->SetFailure();
525  return;
526  }
527 
528  /* Initially we store based on invite code; on first reply we know the
529  * token, and will start using that key instead. */
530  this->connecter_pre[invite_code] = connecter;
531 
532  this->Connect();
533 
536  p->Send_string(invite_code);
537 
538  this->SendPacket(p);
539 }
540 
546 void ClientNetworkCoordinatorSocketHandler::ConnectFailure(const std::string &token, uint8 tracking_number)
547 {
548  /* Connecter will destroy itself. */
549  this->game_connecter = nullptr;
550 
553  p->Send_string(token);
554  p->Send_uint8(tracking_number);
555 
556  this->SendPacket(p);
557 
558  /* We do not close the associated connecter here yet, as the
559  * Game Coordinator might have other methods of connecting available. */
560 }
561 
568 void ClientNetworkCoordinatorSocketHandler::ConnectSuccess(const std::string &token, SOCKET sock, NetworkAddress &address)
569 {
570  /* Connecter will destroy itself. */
571  this->game_connecter = nullptr;
572 
573  if (_network_server) {
574  if (!ServerNetworkGameSocketHandler::ValidateClient(sock, address)) return;
575  Debug(net, 3, "[{}] Client connected from {} on frame {}", ServerNetworkGameSocketHandler::GetName(), address.GetHostname(), _frame_counter);
577  } else {
578  /* The client informs the Game Coordinator about the success. The server
579  * doesn't have to, as it is implied by the client telling. */
582  p->Send_string(token);
583  this->SendPacket(p);
584 
585  /* Find the connecter; it can happen it no longer exist, in cases where
586  * we aborted the connect but the Game Coordinator was already in the
587  * processes of connecting us. */
588  auto connecter_it = this->connecter.find(token);
589  if (connecter_it != this->connecter.end()) {
590  connecter_it->second.second->SetConnected(sock);
591  this->connecter.erase(connecter_it);
592  }
593  }
594 
595  /* Close all remaining connections. */
596  this->CloseToken(token);
597 }
598 
606 void ClientNetworkCoordinatorSocketHandler::StunResult(const std::string &token, uint8 family, bool result)
607 {
610  p->Send_string(token);
611  p->Send_uint8(family);
612  p->Send_bool(result);
613  this->SendPacket(p);
614 }
615 
621 void ClientNetworkCoordinatorSocketHandler::CloseStunHandler(const std::string &token, uint8 family)
622 {
623  auto stun_it = this->stun_handlers.find(token);
624  if (stun_it == this->stun_handlers.end()) return;
625 
626  if (family == AF_UNSPEC) {
627  for (auto &[family, stun_handler] : stun_it->second) {
628  stun_handler->CloseConnection();
629  stun_handler->CloseSocket();
630  }
631 
632  this->stun_handlers.erase(stun_it);
633  } else {
634  auto family_it = stun_it->second.find(family);
635  if (family_it == stun_it->second.end()) return;
636 
637  family_it->second->CloseConnection();
638  family_it->second->CloseSocket();
639 
640  stun_it->second.erase(family_it);
641  }
642 }
643 
649 {
651 
652  auto turn_it = this->turn_handlers.find(token);
653  if (turn_it == this->turn_handlers.end()) return;
654 
655  turn_it->second->CloseConnection();
656  turn_it->second->CloseSocket();
657 
658  /* We don't remove turn_handler here, as we can be called from within that
659  * turn_handler instance, so our object cannot be free'd yet. Instead, we
660  * check later if the connection is closed, and free the object then. */
661 }
662 
668 {
669  /* Close all remaining STUN / TURN connections. */
670  this->CloseStunHandler(token);
671  this->CloseTurnHandler(token);
672 
673  /* Close the caller of the connection attempt. */
674  auto connecter_it = this->connecter.find(token);
675  if (connecter_it != this->connecter.end()) {
676  connecter_it->second.second->SetFailure();
677  this->connecter.erase(connecter_it);
678  }
679 }
680 
685 {
686  /* Ensure all other pending connection attempts are also killed. */
687  if (this->game_connecter != nullptr) {
688  this->game_connecter->Kill();
689  this->game_connecter = nullptr;
690  }
691 
692  /* Mark any pending connecters as failed. */
693  for (auto &[token, it] : this->connecter) {
694  this->CloseStunHandler(token);
695  this->CloseTurnHandler(token);
696  it.second->SetFailure();
697 
698  /* Inform the Game Coordinator he can stop trying to connect us to the server. */
699  this->ConnectFailure(token, 0);
700  }
701  this->stun_handlers.clear();
702  this->turn_handlers.clear();
703  this->connecter.clear();
704 
705  /* Also close any pending invite-code requests. */
706  for (auto &[invite_code, it] : this->connecter_pre) {
707  it->SetFailure();
708  }
709  this->connecter_pre.clear();
710 }
711 
717 {
718  /* Private games are not listed via the Game Coordinator. */
719  if (_network_server && _settings_client.network.server_game_type == SERVER_GAME_TYPE_LOCAL) {
720  if (this->sock != INVALID_SOCKET) {
721  this->CloseConnection();
722  }
723  return;
724  }
725 
726  static int last_attempt_backoff = 1;
727  static bool first_reconnect = true;
728 
729  if (this->sock == INVALID_SOCKET) {
730  static std::chrono::steady_clock::time_point last_attempt = {};
731 
732  /* Don't auto-reconnect when we are not a server. */
733  if (!_network_server) return;
734  /* Don't reconnect if we are connecting. */
735  if (this->connecting) return;
736  /* Throttle how often we try to reconnect. */
737  if (std::chrono::steady_clock::now() < last_attempt + std::chrono::seconds(1) * last_attempt_backoff) return;
738 
739  last_attempt = std::chrono::steady_clock::now();
740  /* Delay reconnecting with up to 32 seconds. */
741  if (last_attempt_backoff < 32) {
742  last_attempt_backoff *= 2;
743  }
744 
745  /* Do not reconnect on the first attempt, but only initialize the
746  * last_attempt variables. Otherwise after an outage all servers
747  * reconnect at the same time, potentially overwhelming the
748  * Game Coordinator. */
749  if (first_reconnect) {
750  first_reconnect = false;
751  return;
752  }
753 
754  Debug(net, 1, "Connection with Game Coordinator lost; reconnecting...");
755  this->Register();
756  return;
757  }
758 
759  last_attempt_backoff = 1;
760  first_reconnect = true;
761 
762  if (_network_server && _network_server_connection_type != CONNECTION_TYPE_UNKNOWN && std::chrono::steady_clock::now() > this->next_update) {
763  this->SendServerUpdate();
764  }
765 
766  if (!_network_server && std::chrono::steady_clock::now() > this->last_activity + IDLE_TIMEOUT) {
767  this->CloseConnection();
768  return;
769  }
770 
771  if (this->CanSendReceive()) {
772  if (this->ReceivePackets()) {
773  this->last_activity = std::chrono::steady_clock::now();
774  }
775  }
776 
777  this->SendPackets();
778 
779  for (const auto &[token, families] : this->stun_handlers) {
780  for (const auto &[family, stun_handler] : families) {
781  stun_handler->SendReceive();
782  }
783  }
784 
785  /* Check for handlers that are not connecting nor connected. Destroy those objects. */
786  for (auto turn_it = this->turn_handlers.begin(); turn_it != this->turn_handlers.end(); /* nothing */) {
787  if (turn_it->second->connect_started && turn_it->second->connecter == nullptr && !turn_it->second->IsConnected()) {
788  turn_it = this->turn_handlers.erase(turn_it);
789  } else {
790  turn_it++;
791  }
792  }
793 
794  for (const auto &[token, turn_handler] : this->turn_handlers) {
795  turn_handler->SendReceive();
796  }
797 }
SerializeNetworkGameInfo
void SerializeNetworkGameInfo(Packet *p, const NetworkServerGameInfo *info, bool send_newgrf_names)
Serializes the NetworkGameInfo struct to the packet.
Definition: game_info.cpp:185
NetworkGameInfo
The game information that is sent from the server to the clients with extra information only required...
Definition: game_info.h:117
_frame_counter
uint32 _frame_counter
The current frame.
Definition: network.cpp:70
ClientNetworkCoordinatorSocketHandler::ConnectFailure
void ConnectFailure(const std::string &token, uint8 tracking_number)
Callback from a Connecter to let the Game Coordinator know the connection failed.
Definition: network_coordinator.cpp:546
CONNECTION_TYPE_ISOLATED
@ CONNECTION_TYPE_ISOLATED
The Game Coordinator failed to find a way to connect to your server. Nobody will be able to join.
Definition: tcp_coordinator.h:54
NetworkDirectConnecter::NetworkDirectConnecter
NetworkDirectConnecter(const std::string &hostname, uint16 port, const std::string &token, uint8 tracking_number)
Try to establish a direct (hostname:port based) connection.
Definition: network_coordinator.cpp:48
SetWindowDirty
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3120
TCPConnecter::connection_string
std::string connection_string
Current address we are connecting to (before resolving).
Definition: tcp.h:100
NETWORK_COORDINATOR_SERVER_PORT
static const uint16 NETWORK_COORDINATOR_SERVER_PORT
The default port of the Game Coordinator server (TCP)
Definition: config.h:23
ClearGRFConfigList
void ClearGRFConfigList(GRFConfig **config)
Clear a GRF Config list, freeing all nodes.
Definition: newgrf_config.cpp:400
_network_server_connection_type
ConnectionType _network_server_connection_type
What type of connection the Game Coordinator detected we are on.
Definition: network_coordinator.cpp:31
NetworkCoordinatorErrorType
NetworkCoordinatorErrorType
The type of error from the Game Coordinator.
Definition: tcp_coordinator.h:63
NETWORK_INVITE_CODE_SECRET_LENGTH
static const uint NETWORK_INVITE_CODE_SECRET_LENGTH
The maximum length of the invite code secret, in bytes including '\0'.
Definition: config.h:75
NetworkSettings::server_port
uint16 server_port
port the server listens on
Definition: settings_type.h:273
TCPConnecter
"Helper" class for creating TCP connections in a non-blocking manner
Definition: tcp.h:71
PACKET_COORDINATOR_CLIENT_CONNECTED
@ PACKET_COORDINATOR_CLIENT_CONNECTED
Client informs the Game Coordinator the connection with the server is established.
Definition: tcp_coordinator.h:39
_network_server
bool _network_server
network-server is active
Definition: network.cpp:57
NetworkCoordinatorConnectionString
const char * NetworkCoordinatorConnectionString()
Get the connection string for the game coordinator from the environment variable OTTD_COORDINATOR_CS,...
Definition: config.cpp:36
NetworkSettings::server_invite_code_secret
std::string server_invite_code_secret
Secret to proof we got this invite code from the Game Coordinator.
Definition: settings_type.h:278
WC_CLIENT_LIST
@ WC_CLIENT_LIST
Client list; Window numbers:
Definition: window_type.h:470
CONNECTION_TYPE_DIRECT
@ CONNECTION_TYPE_DIRECT
The Game Coordinator can directly connect to your server.
Definition: tcp_coordinator.h:55
ClientNetworkCoordinatorSocketHandler::Receive_GC_CONNECT_FAILED
bool Receive_GC_CONNECT_FAILED(Packet *p) override
Game Coordinator informs the Client that it failed to find a way to connect the Client to the Server.
Definition: network_coordinator.cpp:288
ClientNetworkCoordinatorSocketHandler::ConnectSuccess
void ConnectSuccess(const std::string &token, SOCKET sock, NetworkAddress &address)
Callback from a Connecter to let the Game Coordinator know the connection to the game server is estab...
Definition: network_coordinator.cpp:568
network_stun.h
ClientNetworkCoordinatorSocketHandler::Receive_GC_STUN_CONNECT
bool Receive_GC_STUN_CONNECT(Packet *p) override
Game Coordinator informs the client/server of its STUN peer (the host:ip of the other side).
Definition: network_coordinator.cpp:322
TCPConnecter::Kill
void Kill()
Kill this connecter.
Definition: tcp_connect.cpp:85
NetworkTCPSocketHandler::sock
SOCKET sock
The socket currently connected to.
Definition: tcp.h:39
ServerNetworkGameSocketHandler::GetName
static const char * GetName()
Get the name used by the listener.
Definition: network_server.h:111
ClientNetworkCoordinatorSocketHandler::Receive_GC_ERROR
bool Receive_GC_ERROR(Packet *p) override
Game Coordinator indicates there was an error.
Definition: network_coordinator.cpp:127
NetworkReuseStunConnecter::OnFailure
void OnFailure() override
Callback for when the connection attempt failed.
Definition: network_coordinator.cpp:87
_settings_client
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:52
UpdateNetworkGameWindow
void UpdateNetworkGameWindow()
Update the network new window because a new server is found on the network.
Definition: network_gui.cpp:66
NetworkGameListAddItem
NetworkGameList * NetworkGameListAddItem(const std::string &connection_string)
Add a new item to the linked gamelist.
Definition: network_gamelist.cpp:32
NETWORK_COORDINATOR_DELAY_BETWEEN_UPDATES
static const auto NETWORK_COORDINATOR_DELAY_BETWEEN_UPDATES
How many time between updates the server sends to the Game Coordinator.
Definition: network_coordinator.cpp:29
network_gui.h
NETWORK_TOKEN_LENGTH
static const uint NETWORK_TOKEN_LENGTH
The maximum length of a token, in bytes including '\0'.
Definition: config.h:76
NetworkSettings::use_relay_service
UseRelayService use_relay_service
Use relay service?
Definition: settings_type.h:299
Packet::Send_uint8
void Send_uint8(uint8 data)
Package a 8 bits integer in the packet.
Definition: packet.cpp:129
NETWORK_COORDINATOR_ERROR_REUSE_OF_INVITE_CODE
@ NETWORK_COORDINATOR_ERROR_REUSE_OF_INVITE_CODE
The invite code is used by another (newer) server.
Definition: tcp_coordinator.h:67
NetworkAddress::GetPeerAddress
static NetworkAddress GetPeerAddress(SOCKET sock)
Get the peer address of a socket as NetworkAddress.
Definition: address.cpp:407
ShowErrorMessage
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=nullptr, uint textref_stack_size=0, const uint32 *textref_stack=nullptr)
Display an error message in a window.
Definition: error_gui.cpp:383
Packet::Send_uint32
void Send_uint32(uint32 data)
Package a 32 bits integer in the packet.
Definition: packet.cpp:150
PACKET_COORDINATOR_CLIENT_LISTING
@ PACKET_COORDINATOR_CLIENT_LISTING
Client is requesting a listing of all public servers.
Definition: tcp_coordinator.h:33
ClientNetworkCoordinatorSocketHandler::CloseAllConnections
void CloseAllConnections()
Close all pending connection tokens.
Definition: network_coordinator.cpp:684
Packet::Recv_string
std::string Recv_string(size_t length, StringValidationSettings settings=SVS_REPLACE_WITH_QUESTION_MARK)
Reads characters (bytes) from the packet until it finds a '\0', or reaches a maximum of length charac...
Definition: packet.cpp:380
ClientNetworkCoordinatorSocketHandler::Receive_GC_STUN_REQUEST
bool Receive_GC_STUN_REQUEST(Packet *p) override
Game Coordinator requests the client/server to do a STUN request to the STUN server.
Definition: network_coordinator.cpp:313
network_coordinator.h
NetworkReuseStunConnecter::token
std::string token
Token of this connection.
Definition: network_coordinator.cpp:65
NETWORK_ERROR_DETAIL_LENGTH
static const uint NETWORK_ERROR_DETAIL_LENGTH
The maximum length of the error detail, in bytes including '\0'.
Definition: config.h:73
Packet::Recv_uint32
uint32 Recv_uint32()
Read a 32 bits integer from the packet.
Definition: packet.cpp:335
NetworkReuseStunConnecter::tracking_number
uint8 tracking_number
Tracking number of this connection.
Definition: network_coordinator.cpp:66
NETWORK_COORDINATOR_ERROR_INVALID_INVITE_CODE
@ NETWORK_COORDINATOR_ERROR_INVALID_INVITE_CODE
The invite code given is invalid.
Definition: tcp_coordinator.h:66
ClientNetworkCoordinatorSocketHandler::ConnectToServer
void ConnectToServer(const std::string &invite_code, TCPServerConnecter *connecter)
Join a server based on an invite code.
Definition: network_coordinator.cpp:516
NetworkSocketHandler::Reopen
void Reopen()
Reopen the socket so we can send/receive stuff again.
Definition: core.h:73
ClientNetworkCoordinatorSocketHandler::Receive_GC_TURN_CONNECT
bool Receive_GC_TURN_CONNECT(Packet *p) override
Game Coordinator requests that we make a connection to the indicated peer, which is a TURN server.
Definition: network_coordinator.cpp:368
PACKET_COORDINATOR_SERCLI_STUN_RESULT
@ PACKET_COORDINATOR_SERCLI_STUN_RESULT
Client/server informs the Game Coordinator of the result of the STUN request.
Definition: tcp_coordinator.h:42
NetworkDirectConnecter::token
std::string token
Token of this connection.
Definition: network_coordinator.cpp:37
ClientNetworkCoordinatorSocketHandler::stun_handlers
std::map< std::string, std::map< int, std::unique_ptr< ClientNetworkStunSocketHandler > > > stun_handlers
All pending STUN handlers, stored by token:family.
Definition: network_coordinator.h:59
ClientNetworkCoordinatorSocketHandler::game_connecter
TCPConnecter * game_connecter
Pending connecter to the game server.
Definition: network_coordinator.h:61
StrStartsWith
bool StrStartsWith(const std::string_view str, const std::string_view prefix)
Check whether the given string starts with the given prefix.
Definition: string.cpp:367
ClientNetworkCoordinatorSocketHandler::CloseConnection
NetworkRecvStatus CloseConnection(bool error=true) override
This will put this socket handler in a close state.
Definition: network_coordinator.cpp:433
PACKET_COORDINATOR_CLIENT_CONNECT
@ PACKET_COORDINATOR_CLIENT_CONNECT
Client wants to connect to a server based on an invite code.
Definition: tcp_coordinator.h:35
PACKET_COORDINATOR_SERVER_REGISTER
@ PACKET_COORDINATOR_SERVER_REGISTER
Server registration.
Definition: tcp_coordinator.h:30
Packet::Send_uint16
void Send_uint16(uint16 data)
Package a 16 bits integer in the packet.
Definition: packet.cpp:139
NetworkTCPSocketHandler::SendPacket
virtual void SendPacket(Packet *packet)
This function puts the packet in the send-queue and it is send as soon as possible.
Definition: tcp.cpp:81
NetworkReuseStunConnecter::NetworkReuseStunConnecter
NetworkReuseStunConnecter(const std::string &hostname, uint16 port, const NetworkAddress &bind_address, std::string token, uint8 tracking_number, uint8 family)
Try to establish a STUN-based connection.
Definition: network_coordinator.cpp:79
NetworkTCPSocketHandler::CloseConnection
virtual NetworkRecvStatus CloseConnection(bool error=true)
This will put this socket handler in a close state.
Definition: tcp.cpp:65
NetworkGameList::version
int version
Used to see which servers are no longer available on the Game Coordinator and can be removed.
Definition: network_gamelist.h:26
NetworkCoordinatorConnecter
Connect to the Game Coordinator server.
Definition: network_coordinator.cpp:103
ClientNetworkCoordinatorSocketHandler::StunResult
void StunResult(const std::string &token, uint8 family, bool result)
Callback from the STUN connecter to inform the Game Coordinator about the result of the STUN.
Definition: network_coordinator.cpp:606
TCP_MTU
static const uint16 TCP_MTU
Number of bytes we can pack in a single TCP packet.
Definition: config.h:47
ClientNetworkCoordinatorSocketHandler::GetListing
void GetListing()
Request a listing of all public servers.
Definition: network_coordinator.cpp:496
network_server.h
_network_dedicated
bool _network_dedicated
are we a dedicated server?
Definition: network.cpp:59
ClientNetworkCoordinatorSocketHandler::Register
void Register()
Register our server to receive our invite code.
Definition: network_coordinator.cpp:453
Packet
Internal entity of a packet.
Definition: packet.h:44
ClientNetworkCoordinatorSocketHandler::newgrf_lookup_table_cursor
uint32 newgrf_lookup_table_cursor
Last received cursor for the GameInfoNewGRFLookupTable updates.
Definition: network_coordinator.h:63
ServerNetworkGameSocketHandler::AcceptConnection
static void AcceptConnection(SOCKET s, const NetworkAddress &address)
Handle the accepting of a connection to the server.
Definition: network.cpp:550
ConnectionType
ConnectionType
The type of connection the Game Coordinator can detect we have.
Definition: tcp_coordinator.h:52
NETWORK_COORDINATOR_ERROR_UNKNOWN
@ NETWORK_COORDINATOR_ERROR_UNKNOWN
There was an unknown error.
Definition: tcp_coordinator.h:64
NetworkGameListRemoveExpired
void NetworkGameListRemoveExpired()
Remove all servers that have not recently been updated.
Definition: network_gamelist.cpp:91
NETWORK_HOSTNAME_PORT_LENGTH
static const uint NETWORK_HOSTNAME_PORT_LENGTH
The maximum length of the host name + port, in bytes including '\0'. The extra six is ":" + port numb...
Definition: config.h:58
DeserializeNetworkGameInfo
void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info, const GameInfoNewGRFLookupTable *newgrf_lookup_table)
Deserializes the NetworkGameInfo struct from the packet.
Definition: game_info.cpp:256
CONNECTION_TYPE_UNKNOWN
@ CONNECTION_TYPE_UNKNOWN
The Game Coordinator hasn't informed us yet what type of connection we have.
Definition: tcp_coordinator.h:53
GetCurrentNetworkServerGameInfo
const NetworkServerGameInfo * GetCurrentNetworkServerGameInfo()
Get the NetworkServerGameInfo structure with the latest information of the server.
Definition: game_info.cpp:143
Packet::Send_bool
void Send_bool(bool data)
Package a boolean in the packet.
Definition: packet.cpp:120
NetworkReuseStunConnecter::family
uint8 family
Family of this connection.
Definition: network_coordinator.cpp:67
NetworkDirectConnecter::OnFailure
void OnFailure() override
Callback for when the connection attempt failed.
Definition: network_coordinator.cpp:50
NetworkDirectConnecter::OnConnect
void OnConnect(SOCKET s) override
Callback when the connection succeeded.
Definition: network_coordinator.cpp:55
ClientNetworkCoordinatorSocketHandler::newgrf_lookup_table
GameInfoNewGRFLookupTable newgrf_lookup_table
Table to look up NewGRFs in the GC_LISTING packets.
Definition: network_coordinator.h:64
ClientNetworkCoordinatorSocketHandler::Receive_GC_LISTING
bool Receive_GC_LISTING(Packet *p) override
Game Coordinator replies with a list of all public servers.
Definition: network_coordinator.cpp:233
NetworkSettings::server_game_type
ServerGameType server_game_type
Server type: local / public / invite-only.
Definition: settings_type.h:276
NetworkTCPSocketHandler::SendPackets
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
Definition: tcp.cpp:99
ClientNetworkCoordinatorSocketHandler::Receive_GC_DIRECT_CONNECT
bool Receive_GC_DIRECT_CONNECT(Packet *p) override
Game Coordinator requests that the Client makes a direct connection to the indicated peer,...
Definition: network_coordinator.cpp:296
NetworkAddress
Wrapper for (un)resolved network addresses; there's no reason to transform a numeric IP to a string a...
Definition: address.h:30
ClientNetworkCoordinatorSocketHandler::connecter_pre
std::map< std::string, TCPServerConnecter * > connecter_pre
Based on invite codes, the current connecters that are pending.
Definition: network_coordinator.h:58
ClientNetworkCoordinatorSocketHandler::Receive_GC_NEWGRF_LOOKUP
bool Receive_GC_NEWGRF_LOOKUP(Packet *p) override
Game Coordinator informs the client of updates for the NewGRFs lookup table as used by the NewGRF des...
Definition: network_coordinator.cpp:356
NetworkTCPSocketHandler::CanSendReceive
bool CanSendReceive()
Check whether this socket can send or receive something.
Definition: tcp.cpp:218
NetworkReuseStunConnecter::OnConnect
void OnConnect(SOCKET s) override
Callback when the connection succeeded.
Definition: network_coordinator.cpp:95
ClientNetworkCoordinatorSocketHandler::SendReceive
void SendReceive()
Check whether we received/can send some data from/to the Game Coordinator server and when that's the ...
Definition: network_coordinator.cpp:716
CloseWindowByClass
void CloseWindowByClass(WindowClass cls)
Close all windows of a given class.
Definition: window.cpp:1188
NetworkRecvStatus
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
Definition: core.h:22
ClientNetworkCoordinatorSocketHandler::last_activity
std::chrono::steady_clock::time_point last_activity
The last time there was network activity.
Definition: network_coordinator.h:82
ClientNetworkCoordinatorSocketHandler
Game Coordinator communication.
Definition: network_coordinator.h:54
NETWORK_INVITE_CODE_LENGTH
static const uint NETWORK_INVITE_CODE_LENGTH
The maximum length of the invite code, in bytes including '\0'.
Definition: config.h:74
NetworkReuseStunConnecter
Connecter used after STUN exchange to connect from both sides to each other.
Definition: network_coordinator.cpp:63
_network_coordinator_client
ClientNetworkCoordinatorSocketHandler _network_coordinator_client
The connection to the Game Coordinator.
Definition: network_coordinator.cpp:30
network_internal.h
NetworkSettings::server_invite_code
std::string server_invite_code
Invite code to use when registering as server.
Definition: settings_type.h:277
NetworkAddress::GetHostname
const std::string & GetHostname()
Get the hostname; in case it wasn't given the IPv4 dotted representation is given.
Definition: address.cpp:23
WC_NETWORK_ASK_RELAY
@ WC_NETWORK_ASK_RELAY
Network ask relay window; Window numbers:
Definition: window_type.h:483
ClientNetworkCoordinatorSocketHandler::SendServerUpdate
void SendServerUpdate()
Send an update of our server status to the Game Coordinator.
Definition: network_coordinator.cpp:480
CONNECTION_TYPE_TURN
@ CONNECTION_TYPE_TURN
The Game Coordinator needs you to connect to a relay.
Definition: tcp_coordinator.h:57
NetworkCoordinatorConnecter::NetworkCoordinatorConnecter
NetworkCoordinatorConnecter(const std::string &connection_string)
Initiate the connecting.
Definition: network_coordinator.cpp:109
Packet::Recv_uint8
uint8 Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:306
ClientNetworkCoordinatorSocketHandler::next_update
std::chrono::steady_clock::time_point next_update
When to send the next update (if server and public).
Definition: network_coordinator.h:56
WL_ERROR
@ WL_ERROR
Errors (eg. saving/loading failed)
Definition: error.h:24
TCPServerConnecter
Definition: tcp.h:138
ClientNetworkStunSocketHandler::Stun
static std::unique_ptr< ClientNetworkStunSocketHandler > Stun(const std::string &token, uint8 family)
Send a STUN packet to the STUN server.
Definition: network_stun.cpp:83
NetworkCoordinatorConnecter::OnFailure
void OnFailure() override
Callback for when the connection attempt failed.
Definition: network_coordinator.cpp:111
NetworkCoordinatorConnecter::OnConnect
void OnConnect(SOCKET s) override
Callback when the connection succeeded.
Definition: network_coordinator.cpp:117
error
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
Definition: openttd.cpp:132
CheckGameCompatibility
void CheckGameCompatibility(NetworkGameInfo &ngi)
Check if an game entry is compatible with our client.
Definition: game_info.cpp:107
NetworkGameList
Structure with information shown in the game list (GUI)
Definition: network_gamelist.h:18
network.h
Packet::Send_string
void Send_string(const std::string_view data)
Sends a string over the network.
Definition: packet.cpp:181
ClientNetworkCoordinatorSocketHandler::turn_handlers
std::map< std::string, std::unique_ptr< ClientNetworkTurnSocketHandler > > turn_handlers
Pending TURN handler (if any), stored by token.
Definition: network_coordinator.h:60
DeserializeGRFIdentifierWithName
void DeserializeGRFIdentifierWithName(Packet *p, NamedGRFIdentifier *grf)
Deserializes the NamedGRFIdentifier (GRF ID, MD5 checksum and name) from the packet.
Definition: game_info.cpp:391
Debug
#define Debug(name, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
ClientSettings::network
NetworkSettings network
settings related to the network
Definition: settings_type.h:594
CONNECTION_TYPE_STUN
@ CONNECTION_TYPE_STUN
The Game Coordinator can connect to your server via a STUN request.
Definition: tcp_coordinator.h:56
NetworkDirectConnecter
Connect to a game server by IP:port.
Definition: network_coordinator.cpp:35
NETWORK_HOSTNAME_LENGTH
static const uint NETWORK_HOSTNAME_LENGTH
The maximum length of the host name, in bytes including '\0'.
Definition: config.h:57
NETWORK_RECV_STATUS_OKAY
@ NETWORK_RECV_STATUS_OKAY
Everything is okay.
Definition: core.h:23
network_gamelist.h
ClientNetworkCoordinatorSocketHandler::CloseToken
void CloseToken(const std::string &token)
Close everything related to this connection token.
Definition: network_coordinator.cpp:667
NETWORK_COORDINATOR_VERSION
static const byte NETWORK_COORDINATOR_VERSION
What version of game-coordinator-protocol do we use?
Definition: config.h:53
ClientNetworkCoordinatorSocketHandler::CloseTurnHandler
void CloseTurnHandler(const std::string &token)
Close the TURN handler.
Definition: network_coordinator.cpp:648
ClientNetworkCoordinatorSocketHandler::Receive_GC_REGISTER_ACK
bool Receive_GC_REGISTER_ACK(Packet *p) override
Game Coordinator acknowledges the registration.
Definition: network_coordinator.cpp:177
NETWORK_GAME_INFO_VERSION
static const byte NETWORK_GAME_INFO_VERSION
What version of game-info do we use?
Definition: config.h:51
NetworkCoordinatorSocketHandler::ReceivePackets
bool ReceivePackets()
Receive a packet at TCP level.
Definition: tcp_coordinator.cpp:58
NetworkGameList::info
NetworkGameInfo info
The game information of this server.
Definition: network_gamelist.h:21
ClientNetworkTurnSocketHandler::Turn
static std::unique_ptr< ClientNetworkTurnSocketHandler > Turn(const std::string &token, uint8 tracking_number, const std::string &ticket, const std::string &connection_string)
Prepare a TURN connection.
Definition: network_turn.cpp:89
NetworkDirectConnecter::tracking_number
uint8 tracking_number
Tracking number of this connection.
Definition: network_coordinator.cpp:38
PACKET_COORDINATOR_SERCLI_CONNECT_FAILED
@ PACKET_COORDINATOR_SERCLI_CONNECT_FAILED
Client/server tells the Game Coordinator the current connection attempt failed.
Definition: tcp_coordinator.h:37
_network_game_list_version
int _network_game_list_version
Current version of all items in the list.
Definition: network_gamelist.cpp:24
_network_server_invite_code
std::string _network_server_invite_code
Our invite code as indicated by the Game Coordinator.
Definition: network_coordinator.cpp:32
NetworkGameList::online
bool online
False if the server did not respond (default status)
Definition: network_gamelist.h:23
NetworkServerGameInfo::grfconfig
GRFConfig * grfconfig
List of NewGRF files used.
Definition: game_info.h:94
TCPConnecter::bind_address
NetworkAddress bind_address
Address we're binding to, if any.
Definition: tcp.h:101
ClientNetworkCoordinatorSocketHandler::connecter
std::map< std::string, std::pair< std::string, TCPServerConnecter * > > connecter
Based on tokens, the current (invite-code, connecter) that are pending.
Definition: network_coordinator.h:57
NetworkTCPSocketHandler::CloseSocket
void CloseSocket()
Close the actual socket of the connection.
Definition: tcp.cpp:53
PACKET_COORDINATOR_SERVER_UPDATE
@ PACKET_COORDINATOR_SERVER_UPDATE
Server sends an set intervals an update of the server.
Definition: tcp_coordinator.h:32
INVALID_STRING_ID
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
NETWORK_COORDINATOR_ERROR_REGISTRATION_FAILED
@ NETWORK_COORDINATOR_ERROR_REGISTRATION_FAILED
Your request for registration failed.
Definition: tcp_coordinator.h:65
Packet::Recv_uint16
uint16 Recv_uint16()
Read a 16 bits integer from the packet.
Definition: packet.cpp:320
ClientNetworkCoordinatorSocketHandler::connecting
bool connecting
Are we connecting to the Game Coordinator?
Definition: network_coordinator.h:83
ShowNetworkAskRelay
void ShowNetworkAskRelay(const std::string &server_connection_string, const std::string &relay_connection_string, const std::string &token)
Show a modal confirmation window with "no" / "yes, once" / "yes, always" buttons.
Definition: network_gui.cpp:2464
ClientNetworkCoordinatorSocketHandler::IDLE_TIMEOUT
static constexpr std::chrono::seconds IDLE_TIMEOUT
The idle timeout; when to close the connection because it's idle.
Definition: network_coordinator.h:80
ClientNetworkCoordinatorSocketHandler::CloseStunHandler
void CloseStunHandler(const std::string &token, uint8 family=AF_UNSPEC)
Close the STUN handler.
Definition: network_coordinator.cpp:621
ClientNetworkCoordinatorSocketHandler::Receive_GC_CONNECTING
bool Receive_GC_CONNECTING(Packet *p) override
Game Coordinator informs the Client under what token it will start the attempt to connect the Server ...
Definition: network_coordinator.cpp:269