OpenTTD Source  20240917-master-g9ab0a47812
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;
38  uint8_t tracking_number;
39 
40 public:
48  NetworkDirectConnecter(const std::string &hostname, uint16_t port, const std::string &token, uint8_t 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;
66  uint8_t tracking_number;
67  uint8_t family;
68 
69 public:
79  NetworkReuseStunConnecter(const std::string &hostname, uint16_t port, const NetworkAddress &bind_address, std::string token, uint8_t tracking_number, uint8_t 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->status = NGLS_OFFLINE;
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_t 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 = {};
248  DeserializeNetworkGameInfo(p, ngi, &this->newgrf_lookup_table);
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. */
258  CheckGameCompatibility(item->info);
259  /* Mark server as online. */
260  item->status = NGLS_ONLINE;
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_t tracking_number = p.Recv_uint8();
300  std::string hostname = p.Recv_string(NETWORK_HOSTNAME_LENGTH);
301  uint16_t 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 = TCPConnecter::Create<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_t tracking_number = p.Recv_uint8();
326  uint8_t family = p.Recv_uint8();
327  std::string host = p.Recv_string(NETWORK_HOSTNAME_PORT_LENGTH);
328  uint16_t 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 = TCPConnecter::Create<NetworkReuseStunConnecter>(host, port, family_it->second->local_addr, token, tracking_number, family);
353  return true;
354 }
355 
357 {
359 
360  uint16_t newgrfs = p.Recv_uint16();
361  for (; newgrfs> 0; newgrfs--) {
362  uint32_t index = p.Recv_uint32();
363  DeserializeGRFIdentifierWithName(p, this->newgrf_lookup_table[index]);
364  }
365  return true;
366 }
367 
369 {
370  std::string token = p.Recv_string(NETWORK_TOKEN_LENGTH);
371  uint8_t 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  this->turn_handlers[token] = ClientNetworkTurnSocketHandler::Turn(token, tracking_number, ticket, connection_string);
382 
383  if (!_network_server) {
384  auto connecter_it = this->connecter.find(token);
385  if (connecter_it == this->connecter.end()) {
386  /* Make sure we are still interested in connecting to this server. */
387  this->ConnectFailure(token, 0);
388  return true;
389  }
390 
392  case URS_NEVER:
393  this->ConnectFailure(token, 0);
394  break;
395 
396  case URS_ASK:
397  ShowNetworkAskRelay(connecter_it->second.first, connection_string, token);
398  break;
399 
400  case URS_ALLOW:
401  this->StartTurnConnection(token);
402  break;
403  }
404  } else {
405  this->StartTurnConnection(token);
406  }
407 
408  return true;
409 }
410 
411 void ClientNetworkCoordinatorSocketHandler::StartTurnConnection(std::string &token)
412 {
413  auto turn_it = this->turn_handlers.find(token);
414  if (turn_it == this->turn_handlers.end()) return;
415 
416  turn_it->second->Connect();
417 }
418 
419 void ClientNetworkCoordinatorSocketHandler::Connect()
420 {
421  /* We are either already connected or are trying to connect. */
422  if (this->sock != INVALID_SOCKET || this->connecting) return;
423 
424  this->Reopen();
425 
426  this->connecting = true;
427  this->last_activity = std::chrono::steady_clock::now();
428 
429  TCPConnecter::Create<NetworkCoordinatorConnecter>(NetworkCoordinatorConnectionString());
430 }
431 
433 {
435 
436  this->CloseSocket();
437  this->connecting = false;
438 
440  this->next_update = {};
441 
442  this->CloseAllConnections();
443 
445 
447 }
448 
453 {
455  this->next_update = {};
456 
458 
459  this->Connect();
460 
461  auto p = std::make_unique<Packet>(this, PACKET_COORDINATOR_SERVER_REGISTER);
462  p->Send_uint8(NETWORK_COORDINATOR_VERSION);
464  p->Send_uint16(_settings_client.network.server_port);
466  p->Send_string("");
467  p->Send_string("");
468  } else {
471  }
472 
473  this->SendPacket(std::move(p));
474 }
475 
480 {
481  Debug(net, 6, "Sending server update to Game Coordinator");
482 
483  auto p = std::make_unique<Packet>(this, PACKET_COORDINATOR_SERVER_UPDATE, TCP_MTU);
484  p->Send_uint8(NETWORK_COORDINATOR_VERSION);
485  SerializeNetworkGameInfo(*p, GetCurrentNetworkServerGameInfo(), this->next_update.time_since_epoch() != std::chrono::nanoseconds::zero());
486 
487  this->SendPacket(std::move(p));
488 
489  this->next_update = std::chrono::steady_clock::now() + NETWORK_COORDINATOR_DELAY_BETWEEN_UPDATES;
490 }
491 
496 {
497  this->Connect();
498 
500 
501  auto p = std::make_unique<Packet>(this, PACKET_COORDINATOR_CLIENT_LISTING);
502  p->Send_uint8(NETWORK_COORDINATOR_VERSION);
503  p->Send_uint8(NETWORK_GAME_INFO_VERSION);
504  p->Send_string(_openttd_revision);
505  p->Send_uint32(this->newgrf_lookup_table_cursor);
506 
507  this->SendPacket(std::move(p));
508 }
509 
515 void ClientNetworkCoordinatorSocketHandler::ConnectToServer(const std::string &invite_code, TCPServerConnecter *connecter)
516 {
517  assert(invite_code.starts_with("+"));
518 
519  if (this->connecter_pre.find(invite_code) != this->connecter_pre.end()) {
520  /* If someone is hammering the refresh key, one can sent out two
521  * requests for the same invite code. There isn't really a great way
522  * of handling this, so just ignore this request. */
523  connecter->SetFailure();
524  return;
525  }
526 
527  /* Initially we store based on invite code; on first reply we know the
528  * token, and will start using that key instead. */
529  this->connecter_pre[invite_code] = connecter;
530 
531  this->Connect();
532 
533  auto p = std::make_unique<Packet>(this, PACKET_COORDINATOR_CLIENT_CONNECT);
534  p->Send_uint8(NETWORK_COORDINATOR_VERSION);
535  p->Send_string(invite_code);
536 
537  this->SendPacket(std::move(p));
538 }
539 
545 void ClientNetworkCoordinatorSocketHandler::ConnectFailure(const std::string &token, uint8_t tracking_number)
546 {
547  /* Connecter will destroy itself. */
548  this->game_connecter = nullptr;
549 
550  auto p = std::make_unique<Packet>(this, PACKET_COORDINATOR_SERCLI_CONNECT_FAILED);
551  p->Send_uint8(NETWORK_COORDINATOR_VERSION);
552  p->Send_string(token);
553  p->Send_uint8(tracking_number);
554 
555  this->SendPacket(std::move(p));
556 
557  /* We do not close the associated connecter here yet, as the
558  * Game Coordinator might have other methods of connecting available. */
559 }
560 
567 void ClientNetworkCoordinatorSocketHandler::ConnectSuccess(const std::string &token, SOCKET sock, NetworkAddress &address)
568 {
569  assert(sock != INVALID_SOCKET);
570 
571  /* Connecter will destroy itself. */
572  this->game_connecter = nullptr;
573 
574  if (_network_server) {
575  if (!ServerNetworkGameSocketHandler::ValidateClient(sock, address)) return;
576  Debug(net, 3, "[{}] Client connected from {} on frame {}", ServerNetworkGameSocketHandler::GetName(), address.GetHostname(), _frame_counter);
578  } else {
579  /* The client informs the Game Coordinator about the success. The server
580  * doesn't have to, as it is implied by the client telling. */
581  auto p = std::make_unique<Packet>(this, PACKET_COORDINATOR_CLIENT_CONNECTED);
582  p->Send_uint8(NETWORK_COORDINATOR_VERSION);
583  p->Send_string(token);
584  this->SendPacket(std::move(p));
585 
586  /* Find the connecter; it can happen it no longer exist, in cases where
587  * we aborted the connect but the Game Coordinator was already in the
588  * processes of connecting us. */
589  auto connecter_it = this->connecter.find(token);
590  if (connecter_it != this->connecter.end()) {
591  connecter_it->second.second->SetConnected(sock);
592  this->connecter.erase(connecter_it);
593  }
594  }
595 
596  /* Close all remaining connections. */
597  this->CloseToken(token);
598 }
599 
607 void ClientNetworkCoordinatorSocketHandler::StunResult(const std::string &token, uint8_t family, bool result)
608 {
609  auto p = std::make_unique<Packet>(this, PACKET_COORDINATOR_SERCLI_STUN_RESULT);
610  p->Send_uint8(NETWORK_COORDINATOR_VERSION);
611  p->Send_string(token);
612  p->Send_uint8(family);
613  p->Send_bool(result);
614  this->SendPacket(std::move(p));
615 }
616 
622 void ClientNetworkCoordinatorSocketHandler::CloseStunHandler(const std::string &token, uint8_t family)
623 {
624  auto stun_it = this->stun_handlers.find(token);
625  if (stun_it == this->stun_handlers.end()) return;
626 
627  if (family == AF_UNSPEC) {
628  for (auto &[family, stun_handler] : stun_it->second) {
629  stun_handler->CloseConnection();
630  stun_handler->CloseSocket();
631  }
632 
633  this->stun_handlers.erase(stun_it);
634  } else {
635  auto family_it = stun_it->second.find(family);
636  if (family_it == stun_it->second.end()) return;
637 
638  family_it->second->CloseConnection();
639  family_it->second->CloseSocket();
640 
641  stun_it->second.erase(family_it);
642  }
643 }
644 
650 {
652 
653  auto turn_it = this->turn_handlers.find(token);
654  if (turn_it == this->turn_handlers.end()) return;
655 
656  turn_it->second->CloseConnection();
657  turn_it->second->CloseSocket();
658 
659  /* We don't remove turn_handler here, as we can be called from within that
660  * turn_handler instance, so our object cannot be free'd yet. Instead, we
661  * check later if the connection is closed, and free the object then. */
662 }
663 
669 {
670  /* Close all remaining STUN / TURN connections. */
671  this->CloseStunHandler(token);
672  this->CloseTurnHandler(token);
673 
674  /* Close the caller of the connection attempt. */
675  auto connecter_it = this->connecter.find(token);
676  if (connecter_it != this->connecter.end()) {
677  connecter_it->second.second->SetFailure();
678  this->connecter.erase(connecter_it);
679  }
680 }
681 
686 {
687  /* Ensure all other pending connection attempts are also killed. */
688  if (this->game_connecter != nullptr) {
689  this->game_connecter->Kill();
690  this->game_connecter = nullptr;
691  }
692 
693  /* Mark any pending connecters as failed. */
694  for (auto &[token, it] : this->connecter) {
695  this->CloseStunHandler(token);
696  this->CloseTurnHandler(token);
697  it.second->SetFailure();
698 
699  /* Inform the Game Coordinator he can stop trying to connect us to the server. */
700  this->ConnectFailure(token, 0);
701  }
702  this->stun_handlers.clear();
703  this->turn_handlers.clear();
704  this->connecter.clear();
705 
706  /* Also close any pending invite-code requests. */
707  for (auto &[invite_code, it] : this->connecter_pre) {
708  it->SetFailure();
709  }
710  this->connecter_pre.clear();
711 }
712 
718 {
719  /* Private games are not listed via the Game Coordinator. */
720  if (_network_server && _settings_client.network.server_game_type == SERVER_GAME_TYPE_LOCAL) {
721  if (this->sock != INVALID_SOCKET) {
722  this->CloseConnection();
723  }
724  return;
725  }
726 
727  static int last_attempt_backoff = 1;
728  static bool first_reconnect = true;
729 
730  if (this->sock == INVALID_SOCKET) {
731  static std::chrono::steady_clock::time_point last_attempt = {};
732 
733  /* Don't auto-reconnect when we are not a server. */
734  if (!_network_server) return;
735  /* Don't reconnect if we are connecting. */
736  if (this->connecting) return;
737  /* Throttle how often we try to reconnect. */
738  if (std::chrono::steady_clock::now() < last_attempt + std::chrono::seconds(1) * last_attempt_backoff) return;
739 
740  last_attempt = std::chrono::steady_clock::now();
741  /* Delay reconnecting with up to 32 seconds. */
742  if (last_attempt_backoff < 32) {
743  last_attempt_backoff *= 2;
744  }
745 
746  /* Do not reconnect on the first attempt, but only initialize the
747  * last_attempt variables. Otherwise after an outage all servers
748  * reconnect at the same time, potentially overwhelming the
749  * Game Coordinator. */
750  if (first_reconnect) {
751  first_reconnect = false;
752  return;
753  }
754 
755  Debug(net, 1, "Connection with Game Coordinator lost; reconnecting...");
756  this->Register();
757  return;
758  }
759 
760  last_attempt_backoff = 1;
761  first_reconnect = true;
762 
763  if (_network_server && _network_server_connection_type != CONNECTION_TYPE_UNKNOWN && std::chrono::steady_clock::now() > this->next_update) {
764  this->SendServerUpdate();
765  }
766 
767  if (!_network_server && std::chrono::steady_clock::now() > this->last_activity + IDLE_TIMEOUT) {
768  this->CloseConnection();
769  return;
770  }
771 
772  if (this->CanSendReceive()) {
773  if (this->ReceivePackets()) {
774  this->last_activity = std::chrono::steady_clock::now();
775  }
776  }
777 
778  this->SendPackets();
779 
780  for (const auto &[token, families] : this->stun_handlers) {
781  for (const auto &[family, stun_handler] : families) {
782  stun_handler->SendReceive();
783  }
784  }
785 
786  /* Check for handlers that are not connecting nor connected. Destroy those objects. */
787  for (auto turn_it = this->turn_handlers.begin(); turn_it != this->turn_handlers.end(); /* nothing */) {
788  if (turn_it->second->connect_started && turn_it->second->connecter == nullptr && !turn_it->second->IsConnected()) {
789  turn_it = this->turn_handlers.erase(turn_it);
790  } else {
791  turn_it++;
792  }
793  }
794 
795  for (const auto &[token, turn_handler] : this->turn_handlers) {
796  turn_handler->SendReceive();
797  }
798 }
NetworkGameInfo
The game information that is sent from the server to the clients with extra information only required...
Definition: network_game_info.h:121
CloseWindowByClass
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition: window.cpp:1152
NETWORK_COORDINATOR_SERVER_PORT
static const uint16_t NETWORK_COORDINATOR_SERVER_PORT
The default port of the Game Coordinator server (TCP)
Definition: config.h:21
NetworkReuseStunConnecter::tracking_number
uint8_t tracking_number
Tracking number of this connection.
Definition: network_coordinator.cpp:66
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
SetWindowDirty
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3090
TCPConnecter::connection_string
std::string connection_string
Current address we are connecting to (before resolving).
Definition: tcp.h:99
ClientNetworkTurnSocketHandler::Turn
static std::unique_ptr< ClientNetworkTurnSocketHandler > Turn(const std::string &token, uint8_t tracking_number, const std::string &ticket, const std::string &connection_string)
Prepare a TURN connection.
Definition: network_turn.cpp:99
NetworkTCPSocketHandler::SendPacket
virtual void SendPacket(std::unique_ptr< Packet > &&packet)
This function puts the packet in the send-queue and it is send as soon as possible.
Definition: tcp.cpp:68
ShowErrorMessage
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
Definition: error_gui.cpp:367
ClearGRFConfigList
void ClearGRFConfigList(GRFConfig **config)
Clear a GRF Config list, freeing all nodes.
Definition: newgrf_config.cpp:352
_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:71
TCPConnecter
"Helper" class for creating TCP connections in a non-blocking manner
Definition: tcp.h:70
_network_server
bool _network_server
network-server is active
Definition: network.cpp:66
NetworkCoordinatorConnectionString
const char * NetworkCoordinatorConnectionString()
Get the connection string for the game coordinator from the environment variable OTTD_COORDINATOR_CS,...
Definition: config.cpp:35
PACKET_COORDINATOR_SERVER_UPDATE
@ PACKET_COORDINATOR_SERVER_UPDATE
Server sends an set intervals an update of the server.
Definition: tcp_coordinator.h:32
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:321
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
WC_CLIENT_LIST
@ WC_CLIENT_LIST
Client list; Window numbers:
Definition: window_type.h:484
ClientNetworkCoordinatorSocketHandler::ConnectFailure
void ConnectFailure(const std::string &token, uint8_t tracking_number)
Callback from a Connecter to let the Game Coordinator know the connection failed.
Definition: network_coordinator.cpp:545
NETWORK_COORDINATOR_VERSION
static const uint8_t NETWORK_COORDINATOR_VERSION
What version of game-coordinator-protocol do we use?
Definition: config.h:50
CONNECTION_TYPE_DIRECT
@ CONNECTION_TYPE_DIRECT
The Game Coordinator can directly connect to your server.
Definition: tcp_coordinator.h:55
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:567
network_stun.h
NetworkTCPSocketHandler::sock
SOCKET sock
The socket currently connected to.
Definition: tcp.h:38
ServerNetworkGameSocketHandler::GetName
static const char * GetName()
Get the name used by the listener.
Definition: network_server.h:113
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
ClientNetworkCoordinatorSocketHandler::CloseStunHandler
void CloseStunHandler(const std::string &token, uint8_t family=AF_UNSPEC)
Close the STUN handler.
Definition: network_coordinator.cpp:622
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:56
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:72
NetworkSettings::use_relay_service
UseRelayService use_relay_service
Use relay service?
Definition: settings_type.h:344
ClientNetworkCoordinatorSocketHandler::StunResult
void StunResult(const std::string &token, uint8_t family, bool result)
Callback from the STUN connecter to inform the Game Coordinator about the result of the STUN.
Definition: network_coordinator.cpp:607
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:403
Debug
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
ClientNetworkCoordinatorSocketHandler::Receive_GC_ERROR
bool Receive_GC_ERROR(Packet &p) override
Game Coordinator indicates there was an error.
Definition: network_coordinator.cpp:127
ClientNetworkCoordinatorSocketHandler::CloseAllConnections
void CloseAllConnections()
Close all pending connection tokens.
Definition: network_coordinator.cpp:685
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:425
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
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
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:69
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
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:515
NetworkSocketHandler::Reopen
void Reopen()
Reopen the socket so we can send/receive stuff again.
Definition: core.h:79
Packet::Recv_uint32
uint32_t Recv_uint32()
Read a 32 bits integer from the packet.
Definition: packet.cpp:347
NetworkReuseStunConnecter::NetworkReuseStunConnecter
NetworkReuseStunConnecter(const std::string &hostname, uint16_t port, const NetworkAddress &bind_address, std::string token, uint8_t tracking_number, uint8_t family)
Try to establish a STUN-based connection.
Definition: network_coordinator.cpp:79
NetworkDirectConnecter::token
std::string token
Token of this connection.
Definition: network_coordinator.cpp:37
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
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:58
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
ClientNetworkCoordinatorSocketHandler::CloseConnection
NetworkRecvStatus CloseConnection(bool error=true) override
This will put this socket handler in a close state.
Definition: network_coordinator.cpp:432
NetworkTCPSocketHandler::CloseConnection
virtual NetworkRecvStatus CloseConnection(bool error=true)
This will put this socket handler in a close state.
Definition: tcp.cpp:51
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:35
NetworkCoordinatorConnecter
Connect to the Game Coordinator server.
Definition: network_coordinator.cpp:103
ClientNetworkCoordinatorSocketHandler::newgrf_lookup_table_cursor
uint32_t newgrf_lookup_table_cursor
Last received cursor for the #GameInfoNewGRFLookupTable updates.
Definition: network_coordinator.h:62
TCP_MTU
static const size_t TCP_MTU
Number of bytes we can pack in a single TCP packet.
Definition: config.h:45
ClientNetworkCoordinatorSocketHandler::GetListing
void GetListing()
Request a listing of all public servers.
Definition: network_coordinator.cpp:495
ClientNetworkCoordinatorSocketHandler::game_connecter
std::shared_ptr< TCPConnecter > game_connecter
Pending connecter to the game server.
Definition: network_coordinator.h:60
network_server.h
_network_dedicated
bool _network_dedicated
are we a dedicated server?
Definition: network.cpp:68
ClientNetworkCoordinatorSocketHandler::Register
void Register()
Register our server to receive our invite code.
Definition: network_coordinator.cpp:452
Packet
Internal entity of a packet.
Definition: packet.h:42
ServerNetworkGameSocketHandler::AcceptConnection
static void AcceptConnection(SOCKET s, const NetworkAddress &address)
Handle the accepting of a connection to the server.
Definition: network.cpp:570
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:92
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:56
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
NetworkSettings::server_port
uint16_t server_port
port the server listens on
Definition: settings_type.h:316
NetworkDirectConnecter::OnFailure
void OnFailure() override
Callback for when the connection attempt failed.
Definition: network_coordinator.cpp:50
ClientNetworkCoordinatorSocketHandler::newgrf_lookup_table
GameInfoNewGRFLookupTable newgrf_lookup_table
Table to look up NewGRFs in the GC_LISTING packets.
Definition: network_coordinator.h:63
NetworkDirectConnecter::tracking_number
uint8_t tracking_number
Tracking number of this connection.
Definition: network_coordinator.cpp:38
NetworkSettings::server_game_type
ServerGameType server_game_type
Server type: local / public / invite-only.
Definition: settings_type.h:319
NetworkTCPSocketHandler::SendPackets
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
Definition: tcp.cpp:86
NetworkAddress
Wrapper for (un)resolved network addresses; there's no reason to transform a numeric IP to a string a...
Definition: address.h:28
ClientNetworkCoordinatorSocketHandler::connecter_pre
std::map< std::string, TCPServerConnecter * > connecter_pre
Based on invite codes, the current connecters that are pending.
Definition: network_coordinator.h:57
NetworkTCPSocketHandler::CanSendReceive
bool CanSendReceive()
Check whether this socket can send or receive something.
Definition: tcp.cpp:204
PACKET_COORDINATOR_CLIENT_LISTING
@ PACKET_COORDINATOR_CLIENT_LISTING
Client is requesting a listing of all public servers.
Definition: tcp_coordinator.h:33
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:717
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
_frame_counter
uint32_t _frame_counter
The current frame.
Definition: network.cpp:78
NetworkRecvStatus
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
Definition: core.h:23
ClientNetworkCoordinatorSocketHandler::last_activity
std::chrono::steady_clock::time_point last_activity
The last time there was network activity.
Definition: network_coordinator.h:81
ClientNetworkCoordinatorSocketHandler
Game Coordinator communication.
Definition: network_coordinator.h:53
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:70
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
NGLS_ONLINE
@ NGLS_ONLINE
Server is online.
Definition: network_gamelist.h:20
network_internal.h
NetworkSettings::server_invite_code
std::string server_invite_code
Invite code to use when registering as server.
Definition: settings_type.h:320
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:497
ClientNetworkStunSocketHandler::Stun
static std::unique_ptr< ClientNetworkStunSocketHandler > Stun(const std::string &token, uint8_t family)
Send a STUN packet to the STUN server.
Definition: network_stun.cpp:89
NetworkReuseStunConnecter::family
uint8_t family
Family of this connection.
Definition: network_coordinator.cpp:67
ClientNetworkCoordinatorSocketHandler::SendServerUpdate
void SendServerUpdate()
Send an update of our server status to the Game Coordinator.
Definition: network_coordinator.cpp:479
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
ClientNetworkCoordinatorSocketHandler::Receive_GC_REGISTER_ACK
bool Receive_GC_REGISTER_ACK(Packet &p) override
Game Coordinator acknowledges the registration.
Definition: network_coordinator.cpp:177
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:55
WL_ERROR
@ WL_ERROR
Errors (eg. saving/loading failed)
Definition: error.h:26
TCPServerConnecter
Definition: tcp.h:151
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
NetworkCoordinatorConnecter::OnFailure
void OnFailure() override
Callback for when the connection attempt failed.
Definition: network_coordinator.cpp:111
NetworkGameList
Structure with information shown in the game list (GUI)
Definition: network_gamelist.h:27
network.h
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:59
NGLS_OFFLINE
@ NGLS_OFFLINE
Server is offline (or cannot be queried).
Definition: network_gamelist.h:19
ClientSettings::network
NetworkSettings network
settings related to the network
Definition: settings_type.h:612
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_GAME_INFO_VERSION
static const uint8_t NETWORK_GAME_INFO_VERSION
What version of game-info do we use?
Definition: config.h:49
NETWORK_HOSTNAME_LENGTH
static const uint NETWORK_HOSTNAME_LENGTH
The maximum length of the host name, in bytes including '\0'.
Definition: config.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
NETWORK_RECV_STATUS_OKAY
@ NETWORK_RECV_STATUS_OKAY
Everything is okay.
Definition: core.h:24
network_gamelist.h
ClientNetworkCoordinatorSocketHandler::CloseToken
void CloseToken(const std::string &token)
Close everything related to this connection token.
Definition: network_coordinator.cpp:668
ClientNetworkCoordinatorSocketHandler::CloseTurnHandler
void CloseTurnHandler(const std::string &token)
Close the TURN handler.
Definition: network_coordinator.cpp:649
Packet::Recv_uint16
uint16_t Recv_uint16()
Read a 16 bits integer from the packet.
Definition: packet.cpp:332
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:30
_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
NRWCD_HANDLED
@ NRWCD_HANDLED
Relay request is handled, either by user or by timeout.
Definition: network_gui.h:43
PACKET_COORDINATOR_SERVER_REGISTER
@ PACKET_COORDINATOR_SERVER_REGISTER
Server registration.
Definition: tcp_coordinator.h:30
NetworkServerGameInfo::grfconfig
GRFConfig * grfconfig
List of NewGRF files used.
Definition: network_game_info.h:97
TCPConnecter::bind_address
NetworkAddress bind_address
Address we're binding to, if any.
Definition: tcp.h:100
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:56
NetworkTCPSocketHandler::CloseSocket
void CloseSocket()
Close the actual socket of the connection.
Definition: tcp.cpp:39
Packet::Recv_uint8
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:318
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
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
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
ClientNetworkCoordinatorSocketHandler::connecting
bool connecting
Are we connecting to the Game Coordinator?
Definition: network_coordinator.h:82
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:2331
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:79
NetworkGameList::status
NetworkGameListStatus status
Stats of the server.
Definition: network_gamelist.h:32
NetworkDirectConnecter::NetworkDirectConnecter
NetworkDirectConnecter(const std::string &hostname, uint16_t port, const std::string &token, uint8_t tracking_number)
Try to establish a direct (hostname:port based) connection.
Definition: network_coordinator.cpp:48