OpenTTD Source  20241108-master-g80f628063a
network.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 
12 #include "../strings_func.h"
13 #include "../command_func.h"
14 #include "../timer/timer_game_tick.h"
15 #include "../timer/timer_game_economy.h"
16 #include "network_admin.h"
17 #include "network_client.h"
18 #include "network_query.h"
19 #include "network_server.h"
20 #include "network_content.h"
21 #include "network_udp.h"
22 #include "network_gamelist.h"
23 #include "network_base.h"
24 #include "network_coordinator.h"
25 #include "core/udp.h"
26 #include "core/host.h"
27 #include "network_gui.h"
28 #include "../console_func.h"
29 #include "../3rdparty/md5/md5.h"
30 #include "../core/random_func.hpp"
31 #include "../window_func.h"
32 #include "../company_func.h"
33 #include "../company_base.h"
34 #include "../landscape_type.h"
35 #include "../rev.h"
36 #include "../core/pool_func.hpp"
37 #include "../gfx_func.h"
38 #include "../error.h"
39 #include "../misc_cmd.h"
40 #ifdef DEBUG_DUMP_COMMANDS
41 # include "../fileio_func.h"
42 #endif
43 #include <charconv>
44 #include <sstream>
45 #include <iomanip>
46 
47 #include "../safeguards.h"
48 
49 #ifdef DEBUG_DUMP_COMMANDS
55 bool _ddc_fastforward = true;
56 #endif /* DEBUG_DUMP_COMMANDS */
57 
60 
64 
78 uint32_t _frame_counter;
79 uint32_t _last_sync_frame;
81 uint32_t _sync_seed_1;
82 #ifdef NETWORK_SEND_DOUBLE_SEED
83 uint32_t _sync_seed_2;
84 #endif
85 uint32_t _sync_frame;
87 
89 
92 
93 extern std::string GenerateUid(std::string_view subject);
94 
99 bool HasClients()
100 {
101  return !NetworkClientSocket::Iterate().empty();
102 }
103 
108 {
109  /* Delete the chat window, if you were chatting with this client. */
111 }
112 
119 {
121  if (ci->client_id == client_id) return ci;
122  }
123 
124  return nullptr;
125 }
126 
133 {
134  Company *c = Company::GetIfValid(company_id);
135  return c != nullptr && c->allow_list.Contains(this->public_key);
136 }
137 
144 {
146  return info != nullptr && info->CanJoinCompany(company_id);
147 }
148 
155 {
156  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
157  if (cs->client_id == client_id) return cs;
158  }
159 
160  return nullptr;
161 }
162 
163 
170 static auto FindKey(auto *authorized_keys, std::string_view authorized_key)
171 {
172  return std::find_if(authorized_keys->begin(), authorized_keys->end(), [authorized_key](auto &value) { return StrEqualsIgnoreCase(value, authorized_key); });
173 }
174 
180 bool NetworkAuthorizedKeys::Contains(std::string_view key) const
181 {
182  return FindKey(this, key) != this->end();
183 }
184 
190 bool NetworkAuthorizedKeys::Add(std::string_view key)
191 {
192  if (key.empty()) return false;
193 
194  auto iter = FindKey(this, key);
195  if (iter != this->end()) return false;
196 
197  this->emplace_back(key);
198  return true;
199 }
200 
206 bool NetworkAuthorizedKeys::Remove(std::string_view key)
207 {
208  auto iter = FindKey(this, key);
209  if (iter == this->end()) return false;
210 
211  this->erase(iter);
212  return true;
213 }
214 
215 
216 uint8_t NetworkSpectatorCount()
217 {
218  uint8_t count = 0;
219 
220  for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
221  if (ci->client_playas == COMPANY_SPECTATOR) count++;
222  }
223 
224  /* Don't count a dedicated server as spectator */
225  if (_network_dedicated) count--;
226 
227  return count;
228 }
229 
230 
231 /* This puts a text-message to the console, or in the future, the chat-box,
232  * (to keep it all a bit more general)
233  * If 'self_send' is true, this is the client who is sending the message */
234 void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const std::string &name, const std::string &str, int64_t data, const std::string &data_str)
235 {
236  StringID strid;
237  switch (action) {
238  case NETWORK_ACTION_SERVER_MESSAGE:
239  /* Ignore invalid messages */
240  strid = STR_NETWORK_SERVER_MESSAGE;
241  colour = CC_DEFAULT;
242  break;
243  case NETWORK_ACTION_COMPANY_SPECTATOR:
244  colour = CC_DEFAULT;
245  strid = STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE;
246  break;
247  case NETWORK_ACTION_COMPANY_JOIN:
248  colour = CC_DEFAULT;
249  strid = STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN;
250  break;
251  case NETWORK_ACTION_COMPANY_NEW:
252  colour = CC_DEFAULT;
253  strid = STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW;
254  break;
255  case NETWORK_ACTION_JOIN:
256  /* Show the Client ID for the server but not for the client. */
257  strid = _network_server ? STR_NETWORK_MESSAGE_CLIENT_JOINED_ID : STR_NETWORK_MESSAGE_CLIENT_JOINED;
258  break;
259  case NETWORK_ACTION_LEAVE: strid = STR_NETWORK_MESSAGE_CLIENT_LEFT; break;
260  case NETWORK_ACTION_NAME_CHANGE: strid = STR_NETWORK_MESSAGE_NAME_CHANGE; break;
261  case NETWORK_ACTION_GIVE_MONEY: strid = STR_NETWORK_MESSAGE_GIVE_MONEY; break;
262  case NETWORK_ACTION_CHAT_COMPANY: strid = self_send ? STR_NETWORK_CHAT_TO_COMPANY : STR_NETWORK_CHAT_COMPANY; break;
263  case NETWORK_ACTION_CHAT_CLIENT: strid = self_send ? STR_NETWORK_CHAT_TO_CLIENT : STR_NETWORK_CHAT_CLIENT; break;
264  case NETWORK_ACTION_KICKED: strid = STR_NETWORK_MESSAGE_KICKED; break;
265  case NETWORK_ACTION_EXTERNAL_CHAT: strid = STR_NETWORK_CHAT_EXTERNAL; break;
266  default: strid = STR_NETWORK_CHAT_ALL; break;
267  }
268 
269  SetDParamStr(0, name);
270  SetDParamStr(1, str);
271  SetDParam(2, data);
272  SetDParamStr(3, data_str);
273 
274  /* All of these strings start with "***". These characters are interpreted as both left-to-right and
275  * right-to-left characters depending on the context. As the next text might be an user's name, the
276  * user name's characters will influence the direction of the "***" instead of the language setting
277  * of the game. Manually set the direction of the "***" by inserting a text-direction marker. */
278  std::ostringstream stream;
279  std::ostreambuf_iterator<char> iterator(stream);
281  std::string message = stream.str() + GetString(strid);
282 
283  Debug(desync, 1, "msg: {:08x}; {:02x}; {}", TimerGameEconomy::date, TimerGameEconomy::date_fract, message);
284  IConsolePrint(colour, message);
286 }
287 
288 /* Calculate the frame-lag of a client */
289 uint NetworkCalculateLag(const NetworkClientSocket *cs)
290 {
291  int lag = cs->last_frame_server - cs->last_frame;
292  /* This client has missed their ACK packet after 1 DAY_TICKS..
293  * so we increase their lag for every frame that passes!
294  * The packet can be out by a max of _net_frame_freq */
295  if (cs->last_frame_server + Ticks::DAY_TICKS + _settings_client.network.frame_freq < _frame_counter) {
296  lag += _frame_counter - (cs->last_frame_server + Ticks::DAY_TICKS + _settings_client.network.frame_freq);
297  }
298  return lag;
299 }
300 
301 
302 /* There was a non-recoverable error, drop back to the main menu with a nice
303  * error */
304 void ShowNetworkError(StringID error_string)
305 {
308 }
309 
316 {
317  /* List of possible network errors, used by
318  * PACKET_SERVER_ERROR and PACKET_CLIENT_ERROR */
319  static const StringID network_error_strings[] = {
320  STR_NETWORK_ERROR_CLIENT_GENERAL,
321  STR_NETWORK_ERROR_CLIENT_DESYNC,
322  STR_NETWORK_ERROR_CLIENT_SAVEGAME,
323  STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST,
324  STR_NETWORK_ERROR_CLIENT_PROTOCOL_ERROR,
325  STR_NETWORK_ERROR_CLIENT_NEWGRF_MISMATCH,
326  STR_NETWORK_ERROR_CLIENT_NOT_AUTHORIZED,
327  STR_NETWORK_ERROR_CLIENT_NOT_EXPECTED,
328  STR_NETWORK_ERROR_CLIENT_WRONG_REVISION,
329  STR_NETWORK_ERROR_CLIENT_NAME_IN_USE,
330  STR_NETWORK_ERROR_CLIENT_WRONG_PASSWORD,
331  STR_NETWORK_ERROR_CLIENT_COMPANY_MISMATCH,
332  STR_NETWORK_ERROR_CLIENT_KICKED,
333  STR_NETWORK_ERROR_CLIENT_CHEATER,
334  STR_NETWORK_ERROR_CLIENT_SERVER_FULL,
335  STR_NETWORK_ERROR_CLIENT_TOO_MANY_COMMANDS,
336  STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD,
337  STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER,
338  STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP,
339  STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN,
340  STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME,
341  STR_NETWORK_ERROR_CLIENT_NOT_ON_ALLOW_LIST,
342  STR_NETWORK_ERROR_CLIENT_NO_AUTHENTICATION_METHOD_AVAILABLE,
343  };
344  static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
345 
346  if (err >= (ptrdiff_t)lengthof(network_error_strings)) err = NETWORK_ERROR_GENERAL;
347 
348  return network_error_strings[err];
349 }
350 
356 void NetworkHandlePauseChange(PauseMode prev_mode, PauseMode changed_mode)
357 {
358  if (!_networking) return;
359 
360  switch (changed_mode) {
361  case PM_PAUSED_NORMAL:
362  case PM_PAUSED_JOIN:
365  case PM_PAUSED_LINK_GRAPH: {
366  bool changed = ((_pause_mode == PM_UNPAUSED) != (prev_mode == PM_UNPAUSED));
367  bool paused = (_pause_mode != PM_UNPAUSED);
368  if (!paused && !changed) return;
369 
370  StringID str;
371  if (!changed) {
372  int i = -1;
373 
374  if ((_pause_mode & PM_PAUSED_NORMAL) != PM_UNPAUSED) SetDParam(++i, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL);
375  if ((_pause_mode & PM_PAUSED_JOIN) != PM_UNPAUSED) SetDParam(++i, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS);
376  if ((_pause_mode & PM_PAUSED_GAME_SCRIPT) != PM_UNPAUSED) SetDParam(++i, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT);
377  if ((_pause_mode & PM_PAUSED_ACTIVE_CLIENTS) != PM_UNPAUSED) SetDParam(++i, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS);
378  if ((_pause_mode & PM_PAUSED_LINK_GRAPH) != PM_UNPAUSED) SetDParam(++i, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH);
379  str = STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_1 + i;
380  } else {
381  switch (changed_mode) {
382  case PM_PAUSED_NORMAL: SetDParam(0, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL); break;
383  case PM_PAUSED_JOIN: SetDParam(0, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS); break;
384  case PM_PAUSED_GAME_SCRIPT: SetDParam(0, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT); break;
385  case PM_PAUSED_ACTIVE_CLIENTS: SetDParam(0, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS); break;
386  case PM_PAUSED_LINK_GRAPH: SetDParam(0, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH); break;
387  default: NOT_REACHED();
388  }
389  str = paused ? STR_NETWORK_SERVER_MESSAGE_GAME_PAUSED : STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED;
390  }
391 
392  NetworkTextMessage(NETWORK_ACTION_SERVER_MESSAGE, CC_DEFAULT, false, "", GetString(str));
393  break;
394  }
395 
396  default:
397  return;
398  }
399 }
400 
401 
410 static void CheckPauseHelper(bool pause, PauseMode pm)
411 {
412  if (pause == ((_pause_mode & pm) != PM_UNPAUSED)) return;
413 
414  Command<CMD_PAUSE>::Post(pm, pause);
415 }
416 
423 {
424  uint count = 0;
425 
426  for (const NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
427  if (cs->status != NetworkClientSocket::STATUS_ACTIVE) continue;
428  if (!Company::IsValidID(cs->GetInfo()->client_playas)) continue;
429  count++;
430  }
431 
432  return count;
433 }
434 
439 {
443  return;
444  }
446 }
447 
453 {
454  for (const NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
455  if (cs->status >= NetworkClientSocket::STATUS_AUTHORIZED && cs->status < NetworkClientSocket::STATUS_ACTIVE) return true;
456  }
457 
458  return false;
459 }
460 
464 static void CheckPauseOnJoin()
465 {
468  return;
469  }
471 }
472 
479 std::string_view ParseCompanyFromConnectionString(const std::string &connection_string, CompanyID *company_id)
480 {
481  std::string_view ip = connection_string;
482  if (company_id == nullptr) return ip;
483 
484  size_t offset = ip.find_last_of('#');
485  if (offset != std::string::npos) {
486  std::string_view company_string = ip.substr(offset + 1);
487  ip = ip.substr(0, offset);
488 
489  uint8_t company_value;
490  auto [_, err] = std::from_chars(company_string.data(), company_string.data() + company_string.size(), company_value);
491  if (err == std::errc()) {
492  if (company_value != COMPANY_NEW_COMPANY && company_value != COMPANY_SPECTATOR) {
493  if (company_value > MAX_COMPANIES || company_value == 0) {
494  *company_id = COMPANY_SPECTATOR;
495  } else {
496  /* "#1" means the first company, which has index 0. */
497  *company_id = (CompanyID)(company_value - 1);
498  }
499  } else {
500  *company_id = (CompanyID)company_value;
501  }
502  }
503  }
504 
505  return ip;
506 }
507 
523 std::string_view ParseFullConnectionString(const std::string &connection_string, uint16_t &port, CompanyID *company_id)
524 {
525  std::string_view ip = ParseCompanyFromConnectionString(connection_string, company_id);
526 
527  size_t port_offset = ip.find_last_of(':');
528  size_t ipv6_close = ip.find_last_of(']');
529  if (port_offset != std::string::npos && (ipv6_close == std::string::npos || ipv6_close < port_offset)) {
530  std::string_view port_string = ip.substr(port_offset + 1);
531  ip = ip.substr(0, port_offset);
532  std::from_chars(port_string.data(), port_string.data() + port_string.size(), port);
533  }
534  return ip;
535 }
536 
543 std::string NormalizeConnectionString(const std::string &connection_string, uint16_t default_port)
544 {
545  uint16_t port = default_port;
546  std::string_view ip = ParseFullConnectionString(connection_string, port);
547  return std::string(ip) + ":" + std::to_string(port);
548 }
549 
558 NetworkAddress ParseConnectionString(const std::string &connection_string, uint16_t default_port)
559 {
560  uint16_t port = default_port;
561  std::string_view ip = ParseFullConnectionString(connection_string, port);
562  return NetworkAddress(ip, port);
563 }
564 
570 /* static */ void ServerNetworkGameSocketHandler::AcceptConnection(SOCKET s, const NetworkAddress &address)
571 {
572  /* Register the login */
574 
576  cs->client_address = address; // Save the IP of the client
577 
579 }
580 
585 static void InitializeNetworkPools(bool close_admins = true)
586 {
587  PoolBase::Clean(PT_NCLIENT | (close_admins ? PT_NADMIN : PT_NONE));
588 }
589 
594 void NetworkClose(bool close_admins)
595 {
596  if (_network_server) {
597  if (close_admins) {
599  as->CloseConnection(true);
600  }
601  }
602 
603  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
604  cs->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT);
605  }
608 
610  } else {
611  if (MyClient::my_client != nullptr) {
614  }
615 
617  }
618  NetworkGameSocketHandler::ProcessDeferredDeletions();
619 
621 
622  _networking = false;
623  _network_server = false;
624 
626 
627  InitializeNetworkPools(close_admins);
628 }
629 
630 /* Initializes the network (cleans sockets and stuff) */
631 static void NetworkInitialize(bool close_admins = true)
632 {
633  InitializeNetworkPools(close_admins);
634 
635  _sync_frame = 0;
636  _network_first_time = true;
637 
638  _network_reconnect = 0;
639 }
640 
643 private:
644  std::string connection_string;
645 
646 public:
647  TCPQueryConnecter(const std::string &connection_string) : TCPServerConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {}
648 
649  void OnFailure() override
650  {
651  Debug(net, 9, "Query::OnFailure(): connection_string={}", this->connection_string);
652 
653  NetworkGameList *item = NetworkGameListAddItem(connection_string);
654  item->status = NGLS_OFFLINE;
655  item->refreshing = false;
656 
658  }
659 
660  void OnConnect(SOCKET s) override
661  {
662  Debug(net, 9, "Query::OnConnect(): connection_string={}", this->connection_string);
663 
664  QueryNetworkGameSocketHandler::QueryServer(s, this->connection_string);
665  }
666 };
667 
672 void NetworkQueryServer(const std::string &connection_string)
673 {
674  if (!_network_available) return;
675 
676  Debug(net, 9, "NetworkQueryServer(): connection_string={}", connection_string);
677 
678  /* Mark the entry as refreshing, so the GUI can show the refresh is pending. */
679  NetworkGameList *item = NetworkGameListAddItem(connection_string);
680  item->refreshing = true;
681 
682  TCPConnecter::Create<TCPQueryConnecter>(connection_string);
683 }
684 
694 NetworkGameList *NetworkAddServer(const std::string &connection_string, bool manually, bool never_expire)
695 {
696  if (connection_string.empty()) return nullptr;
697 
698  /* Ensure the item already exists in the list */
699  NetworkGameList *item = NetworkGameListAddItem(connection_string);
700  if (item->info.server_name.empty()) {
702  item->info.server_name = connection_string;
703 
705 
706  NetworkQueryServer(connection_string);
707  }
708 
709  if (manually) item->manually = true;
710  if (never_expire) item->version = INT32_MAX;
711 
712  return item;
713 }
714 
720 void GetBindAddresses(NetworkAddressList *addresses, uint16_t port)
721 {
722  for (const auto &iter : _network_bind_list) {
723  addresses->emplace_back(iter.c_str(), port);
724  }
725 
726  /* No address, so bind to everything. */
727  if (addresses->empty()) {
728  addresses->emplace_back("", port);
729  }
730 }
731 
732 /* Generates the list of manually added hosts from NetworkGameList and
733  * dumps them into the array _network_host_list. This array is needed
734  * by the function that generates the config file. */
735 void NetworkRebuildHostList()
736 {
737  _network_host_list.clear();
738 
739  for (NetworkGameList *item = _network_game_list; item != nullptr; item = item->next) {
740  if (item->manually) _network_host_list.emplace_back(item->connection_string);
741  }
742 }
743 
746 private:
747  std::string connection_string;
748 
749 public:
750  TCPClientConnecter(const std::string &connection_string) : TCPServerConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {}
751 
752  void OnFailure() override
753  {
754  Debug(net, 9, "Client::OnFailure(): connection_string={}", this->connection_string);
755 
756  ShowNetworkError(STR_NETWORK_ERROR_NOCONNECTION);
757  }
758 
759  void OnConnect(SOCKET s) override
760  {
761  Debug(net, 9, "Client::OnConnect(): connection_string={}", this->connection_string);
762 
763  _networking = true;
765  new ClientNetworkGameSocketHandler(s, this->connection_string);
766  IConsoleCmdExec("exec scripts/on_client.scr 0");
768  }
769 };
770 
787 bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const std::string &join_server_password)
788 {
789  Debug(net, 9, "NetworkClientConnectGame(): connection_string={}", connection_string);
790 
791  CompanyID join_as = default_company;
792  std::string resolved_connection_string = ServerAddress::Parse(connection_string, NETWORK_DEFAULT_PORT, &join_as).connection_string;
793 
794  if (!_network_available) return false;
795  if (!NetworkValidateOurClientName()) return false;
796 
797  _network_join.connection_string = resolved_connection_string;
798  _network_join.company = join_as;
799  _network_join.server_password = join_server_password;
800 
801  if (_game_mode == GM_MENU) {
802  /* From the menu we can immediately continue with the actual join. */
804  } else {
805  /* When already playing a game, first go back to the main menu. This
806  * disconnects the user from the current game, meaning we can safely
807  * load in the new. After all, there is little point in continueing to
808  * play on a server if we are connecting to another one.
809  */
811  }
812  return true;
813 }
814 
821 {
823  NetworkInitialize();
824 
826  Debug(net, 9, "status = CONNECTING");
827  _network_join_status = NETWORK_JOIN_STATUS_CONNECTING;
828  ShowJoinStatusWindow();
829 
830  TCPConnecter::Create<TCPClientConnecter>(_network_join.connection_string);
831 }
832 
833 static void NetworkInitGameInfo()
834 {
835  FillStaticNetworkServerGameInfo();
836  /* The server is a client too */
837  _network_game_info.clients_on = _network_dedicated ? 0 : 1;
838 
839  /* There should be always space for the server. */
843 
845 
848 }
849 
860 bool NetworkValidateServerName(std::string &server_name)
861 {
862  StrTrimInPlace(server_name);
863  if (!server_name.empty()) return true;
864 
865  ShowErrorMessage(STR_NETWORK_ERROR_BAD_SERVER_NAME, INVALID_STRING_ID, WL_ERROR);
866  return false;
867 }
868 
876 {
877  static const std::string fallback_client_name = "Unnamed Client";
879  if (_settings_client.network.client_name.empty() || _settings_client.network.client_name.compare(fallback_client_name) == 0) {
880  Debug(net, 1, "No \"client_name\" has been set, using \"{}\" instead. Please set this now using the \"name <new name>\" command", fallback_client_name);
881  _settings_client.network.client_name = fallback_client_name;
882  }
883 
884  static const std::string fallback_server_name = "Unnamed Server";
886  if (_settings_client.network.server_name.empty() || _settings_client.network.server_name.compare(fallback_server_name) == 0) {
887  Debug(net, 1, "No \"server_name\" has been set, using \"{}\" instead. Please set this now using the \"server_name <new name>\" command", fallback_server_name);
888  _settings_client.network.server_name = fallback_server_name;
889  }
890 }
891 
892 bool NetworkServerStart()
893 {
894  if (!_network_available) return false;
895 
896  /* Call the pre-scripts */
897  IConsoleCmdExec("exec scripts/pre_server.scr 0");
898  if (_network_dedicated) IConsoleCmdExec("exec scripts/pre_dedicated.scr 0");
899 
900  /* Check for the client and server names to be set, but only after the scripts had a chance to set them.*/
902 
903  NetworkDisconnect(false);
904  NetworkInitialize(false);
906  Debug(net, 5, "Starting listeners for clients");
908 
909  /* Only listen for admins when the authentication is configured. */
910  if (_settings_client.network.AdminAuthenticationConfigured()) {
911  Debug(net, 5, "Starting listeners for admins");
913  }
914 
915  /* Try to start UDP-server */
916  Debug(net, 5, "Starting listeners for incoming server queries");
918 
919  _network_server = true;
920  _networking = true;
921  _frame_counter = 0;
923  _frame_counter_max = 0;
924  _last_sync_frame = 0;
926 
928 
929  NetworkInitGameInfo();
930 
931  if (_settings_client.network.server_game_type != SERVER_GAME_TYPE_LOCAL) {
933  }
934 
935  /* execute server initialization script */
936  IConsoleCmdExec("exec scripts/on_server.scr 0");
937  /* if the server is dedicated ... add some other script */
938  if (_network_dedicated) IConsoleCmdExec("exec scripts/on_dedicated.scr 0");
939 
940  return true;
941 }
942 
948 {
949  if (!_network_server) return;
950 
951  /* Update the static game info to set the values from the new game. */
953 
955 
956  if (!_network_dedicated) {
959  if (c != nullptr && ci != nullptr) {
960  ci->client_playas = c->index;
961 
962  /*
963  * If the company has not been named yet, the company was just started.
964  * Otherwise it would have gotten a name already, so announce it as a new company.
965  */
966  if (c->name_1 == STR_SV_UNNAMED && c->name.empty()) NetworkServerNewCompany(c, ci);
967  }
968 
969  ShowClientList();
970  } else {
971  /* welcome possibly still connected admins - this can only happen on a dedicated server. */
973  }
974 }
975 
976 /* The server is rebooting...
977  * The only difference with NetworkDisconnect, is the packets that is sent */
978 void NetworkReboot()
979 {
980  if (_network_server) {
981  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
982  cs->SendNewGame();
983  cs->SendPackets();
984  }
985 
987  as->SendNewGame();
988  as->SendPackets();
989  }
990  }
991 
992  /* For non-dedicated servers we have to kick the admins as we are not
993  * certain that we will end up in a new network game. */
995 }
996 
1001 void NetworkDisconnect(bool close_admins)
1002 {
1003  if (_network_server) {
1004  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1005  cs->SendShutdown();
1006  cs->SendPackets();
1007  }
1008 
1009  if (close_admins) {
1011  as->SendShutdown();
1012  as->SendPackets();
1013  }
1014  }
1015  }
1016 
1018 
1019  NetworkClose(close_admins);
1020 
1021  /* Reinitialize the UDP stack, i.e. close all existing connections. */
1023 }
1024 
1030 {
1031  if (!_networking) return;
1032 
1034  case SERVER_GAME_TYPE_LOCAL:
1036  break;
1037 
1038  case SERVER_GAME_TYPE_INVITE_ONLY:
1039  case SERVER_GAME_TYPE_PUBLIC:
1041  break;
1042 
1043  default:
1044  NOT_REACHED();
1045  }
1046 }
1047 
1052 static bool NetworkReceive()
1053 {
1054  bool result;
1055  if (_network_server) {
1058  } else {
1060  }
1061  NetworkGameSocketHandler::ProcessDeferredDeletions();
1062  return result;
1063 }
1064 
1065 /* This sends all buffered commands (if possible) */
1066 static void NetworkSend()
1067 {
1068  if (_network_server) {
1071  } else {
1073  }
1074  NetworkGameSocketHandler::ProcessDeferredDeletions();
1075 }
1076 
1083 {
1089  NetworkGameSocketHandler::ProcessDeferredDeletions();
1090 
1092 }
1093 
1094 /* The main loop called from ttd.c
1095  * Here we also have to do StateGameLoop if needed! */
1096 void NetworkGameLoop()
1097 {
1098  if (!_networking) return;
1099 
1100  if (!NetworkReceive()) return;
1101 
1102  if (_network_server) {
1103  /* Log the sync state to check for in-syncedness of replays. */
1104  if (TimerGameEconomy::date_fract == 0) {
1105  /* We don't want to log multiple times if paused. */
1106  static TimerGameEconomy::Date last_log;
1107  if (last_log != TimerGameEconomy::date) {
1108  Debug(desync, 1, "sync: {:08x}; {:02x}; {:08x}; {:08x}", TimerGameEconomy::date, TimerGameEconomy::date_fract, _random.state[0], _random.state[1]);
1109  last_log = TimerGameEconomy::date;
1110  }
1111  }
1112 
1113 #ifdef DEBUG_DUMP_COMMANDS
1114  /* Loading of the debug commands from -ddesync>=1 */
1115  static auto f = FioFOpenFile("commands.log", "rb", SAVE_DIR);
1116  static TimerGameEconomy::Date next_date(0);
1117  static uint32_t next_date_fract;
1118  static CommandPacket *cp = nullptr;
1119  static bool check_sync_state = false;
1120  static uint32_t sync_state[2];
1121  if (!f.has_value() && next_date == 0) {
1122  Debug(desync, 0, "Cannot open commands.log");
1123  next_date = TimerGameEconomy::Date(1);
1124  }
1125 
1126  while (f.has_value() && !feof(*f)) {
1127  if (TimerGameEconomy::date == next_date && TimerGameEconomy::date_fract == next_date_fract) {
1128  if (cp != nullptr) {
1129  NetworkSendCommand(cp->cmd, cp->err_msg, nullptr, cp->company, cp->data);
1130  Debug(desync, 0, "Injecting: {:08x}; {:02x}; {:02x}; {:08x}; {} ({})", TimerGameEconomy::date, TimerGameEconomy::date_fract, (int)_current_company, cp->cmd, FormatArrayAsHex(cp->data), GetCommandName(cp->cmd));
1131  delete cp;
1132  cp = nullptr;
1133  }
1134  if (check_sync_state) {
1135  if (sync_state[0] == _random.state[0] && sync_state[1] == _random.state[1]) {
1136  Debug(desync, 0, "Sync check: {:08x}; {:02x}; match", TimerGameEconomy::date, TimerGameEconomy::date_fract);
1137  } else {
1138  Debug(desync, 0, "Sync check: {:08x}; {:02x}; mismatch expected {{{:08x}, {:08x}}}, got {{{:08x}, {:08x}}}",
1139  TimerGameEconomy::date, TimerGameEconomy::date_fract, sync_state[0], sync_state[1], _random.state[0], _random.state[1]);
1140  NOT_REACHED();
1141  }
1142  check_sync_state = false;
1143  }
1144  }
1145 
1146  /* Skip all entries in the command-log till we caught up with the current game again. */
1147  if (TimerGameEconomy::date > next_date || (TimerGameEconomy::date == next_date && TimerGameEconomy::date_fract > next_date_fract)) {
1148  Debug(desync, 0, "Skipping to next command at {:08x}:{:02x}", next_date, next_date_fract);
1149  if (cp != nullptr) {
1150  delete cp;
1151  cp = nullptr;
1152  }
1153  check_sync_state = false;
1154  }
1155 
1156  if (cp != nullptr || check_sync_state) break;
1157 
1158  char buff[4096];
1159  if (fgets(buff, lengthof(buff), *f) == nullptr) break;
1160 
1161  char *p = buff;
1162  /* Ignore the "[date time] " part of the message */
1163  if (*p == '[') {
1164  p = strchr(p, ']');
1165  if (p == nullptr) break;
1166  p += 2;
1167  }
1168 
1169  if (strncmp(p, "cmd: ", 5) == 0
1170 #ifdef DEBUG_FAILED_DUMP_COMMANDS
1171  || strncmp(p, "cmdf: ", 6) == 0
1172 #endif
1173  ) {
1174  p += 5;
1175  if (*p == ' ') p++;
1176  cp = new CommandPacket();
1177  int company;
1178  uint cmd;
1179  char buffer[256];
1180  uint32_t next_date_raw;
1181  int ret = sscanf(p, "%x; %x; %x; %x; %x; %255s", &next_date_raw, &next_date_fract, &company, &cmd, &cp->err_msg, buffer);
1182  assert(ret == 6);
1183  next_date = TimerGameEconomy::Date((int32_t)next_date_raw);
1184  cp->company = (CompanyID)company;
1185  cp->cmd = (Commands)cmd;
1186 
1187  /* Parse command data. */
1188  std::vector<uint8_t> args;
1189  size_t arg_len = strlen(buffer);
1190  for (size_t i = 0; i + 1 < arg_len; i += 2) {
1191  uint8_t e = 0;
1192  std::from_chars(buffer + i, buffer + i + 2, e, 16);
1193  args.emplace_back(e);
1194  }
1195  cp->data = args;
1196  } else if (strncmp(p, "join: ", 6) == 0) {
1197  /* Manually insert a pause when joining; this way the client can join at the exact right time. */
1198  uint32_t next_date_raw;
1199  int ret = sscanf(p + 6, "%x; %x", &next_date_raw, &next_date_fract);
1200  next_date = TimerGameEconomy::Date((int32_t)next_date_raw);
1201  assert(ret == 2);
1202  Debug(desync, 0, "Injecting pause for join at {:08x}:{:02x}; please join when paused", next_date, next_date_fract);
1203  cp = new CommandPacket();
1204  cp->company = COMPANY_SPECTATOR;
1205  cp->cmd = CMD_PAUSE;
1207  _ddc_fastforward = false;
1208  } else if (strncmp(p, "sync: ", 6) == 0) {
1209  uint32_t next_date_raw;
1210  int ret = sscanf(p + 6, "%x; %x; %x; %x", &next_date_raw, &next_date_fract, &sync_state[0], &sync_state[1]);
1211  next_date = TimerGameEconomy::Date((int32_t)next_date_raw);
1212  assert(ret == 4);
1213  check_sync_state = true;
1214  } else if (strncmp(p, "msg: ", 5) == 0 || strncmp(p, "client: ", 8) == 0 ||
1215  strncmp(p, "load: ", 6) == 0 || strncmp(p, "save: ", 6) == 0 ||
1216  strncmp(p, "warning: ", 9) == 0) {
1217  /* A message that is not very important to the log playback, but part of the log. */
1218 #ifndef DEBUG_FAILED_DUMP_COMMANDS
1219  } else if (strncmp(p, "cmdf: ", 6) == 0) {
1220  Debug(desync, 0, "Skipping replay of failed command: {}", p + 6);
1221 #endif
1222  } else {
1223  /* Can't parse a line; what's wrong here? */
1224  Debug(desync, 0, "Trying to parse: {}", p);
1225  NOT_REACHED();
1226  }
1227  }
1228  if (f.has_value() && feof(*f)) {
1229  Debug(desync, 0, "End of commands.log");
1230  f.reset();
1231  }
1232 #endif /* DEBUG_DUMP_COMMANDS */
1234  /* Only check for active clients just before we're going to send out
1235  * the commands so we don't send multiple pause/unpause commands when
1236  * the frame_freq is more than 1 tick. Same with distributing commands. */
1237  CheckPauseOnJoin();
1240  }
1241 
1242  bool send_frame = false;
1243 
1244  /* We first increase the _frame_counter */
1245  _frame_counter++;
1246  /* Update max-frame-counter */
1249  send_frame = true;
1250  }
1251 
1253 
1254  /* Then we make the frame */
1255  StateGameLoop();
1256 
1257  _sync_seed_1 = _random.state[0];
1258 #ifdef NETWORK_SEND_DOUBLE_SEED
1259  _sync_seed_2 = _random.state[1];
1260 #endif
1261 
1262  NetworkServer_Tick(send_frame);
1263  } else {
1264  /* Client */
1265 
1266  /* Make sure we are at the frame were the server is (quick-frames) */
1268  /* Run a number of frames; when things go bad, get out. */
1271  }
1272  } else {
1273  /* Else, keep on going till _frame_counter_max */
1275  /* Run one frame; if things went bad, get out. */
1277  }
1278  }
1279  }
1280 
1281  NetworkSend();
1282 }
1283 
1286 {
1287  Debug(net, 3, "Starting network");
1288 
1289  /* Network is available */
1291  _network_dedicated = false;
1292 
1293  _network_game_info = {};
1294 
1295  NetworkInitialize();
1297  Debug(net, 3, "Network online, multiplayer available");
1300 }
1301 
1304 {
1307  NetworkUDPClose();
1308 
1309  Debug(net, 3, "Shutting down network");
1310 
1311  _network_available = false;
1312 
1314 }
1315 
1316 #ifdef __EMSCRIPTEN__
1317 extern "C" {
1318 
1319 void CDECL em_openttd_add_server(const char *connection_string)
1320 {
1321  NetworkAddServer(connection_string, false, true);
1322 }
1323 
1324 }
1325 #endif
std::vector< NetworkAddress > NetworkAddressList
Type for a list of addresses.
Definition: address.h:19
void SendReceive()
Check whether we received/can send some data from/to the content server and when that's the case hand...
void Register()
Register our server to receive our invite code.
void SendReceive()
Check whether we received/can send some data from/to the Game Coordinator server and when that's the ...
void CloseAllConnections()
Close all pending connection tokens.
NetworkRecvStatus CloseConnection(bool error=true) override
This will put this socket handler in a close state.
Class for handling the client side of the game connection.
static ClientNetworkGameSocketHandler * my_client
This is us!
static NetworkRecvStatus SendQuit()
Tell the server we would like to quit.
static bool Receive()
Check whether we received/can send some data from/to the server and when that's the case handle it ap...
static bool GameLoop()
Actual game loop for the client.
static void Send()
Send the packets of this socket handler.
NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override
Close the network connection due to the given status.
Endian-aware buffer adapter that always writes values in little endian order.
Wrapper for (un)resolved network addresses; there's no reason to transform a numeric IP to a string a...
Definition: address.h:28
static void EnsureValidSecretKeyAndUpdatePublicKey(std::string &secret_key, std::string &public_key)
Ensures that the given secret key is valid, and when not overwrite it with a valid secret key.
bool Contains(std::string_view key) const
Check whether the given key is contains in these authorized keys.
Definition: network.cpp:180
bool Add(std::string_view key)
Add the given key to the authorized keys, when it is not already contained.
Definition: network.cpp:190
bool Remove(std::string_view key)
Remove the given key from the authorized keys, when it is exists.
Definition: network.cpp:206
ClientID client_id
Client identifier.
Definition: tcp_game.h:486
static void HTTPReceive()
Do the receiving for all HTTP connections.
Definition: http_curl.cpp:107
static void QueryServer(SOCKET s, const std::string &connection_string)
Start to query a server based on an open socket.
Definition: network_query.h:46
static void SendReceive()
Check if any query needs to send or receive.
std::string connection_string
The connection string for this ServerAddress.
Definition: address.h:210
static ServerAddress Parse(const std::string &connection_string, uint16_t default_port, CompanyID *company_id=nullptr)
Convert a string containing either "hostname", "hostname:port" or invite code to a ServerAddress,...
Definition: address.cpp:450
Class for handling the server side of the game connection.
Definition: network_admin.h:25
static void Send()
Send the packets for the server sockets.
static Pool::IterateWrapperFiltered< ServerNetworkAdminSocketHandler, ServerNetworkAdminSocketHandlerFilter > IterateActive(size_t from=0)
Returns an iterable ensemble of all active admin sockets.
static void WelcomeAll()
Send a Welcome packet to all connected admins.
Class for handling the server side of the game connection.
static ServerNetworkGameSocketHandler * GetByClientID(ClientID client_id)
Return the client state given it's client-identifier.
Definition: network.cpp:154
static void Send()
Send the packets for the server sockets.
static void AcceptConnection(SOCKET s, const NetworkAddress &address)
Handle the accepting of a connection to the server.
Definition: network.cpp:570
NetworkAddress client_address
IP-address of the client (so they can be banned)
ServerNetworkGameSocketHandler(SOCKET s)
Create a new socket for the server side of the game connection.
Non blocking connection create to actually connect to servers.
Definition: network.cpp:745
void OnFailure() override
Callback for when the connection attempt failed.
Definition: network.cpp:752
static void CheckCallbacks()
Check whether we need to call the callback, i.e.
static void KillAll()
Kill all connection attempts.
Non blocking connection to query servers for their game info.
Definition: network.cpp:642
void OnFailure() override
Callback for when the connection attempt failed.
Definition: network.cpp:649
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
static Date date
Current date in days (day counter).
static DateFract date_fract
Fractional part of the day.
const char * GetCommandName(Commands cmd)
This function mask the parameter with CMD_ID_MASK and returns the name which belongs to the given com...
Definition: command.cpp:132
void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *callback, CompanyID company, const CommandDataBuffer &cmd_data)
Prepare a DoCommand to be send over the network.
Commands
List of commands.
Definition: command_type.h:187
@ CMD_PAUSE
pause the game
Definition: command_type.h:276
CompanyID GetFirstPlayableCompanyID()
Get the index of the first available company.
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
static const uint MAX_LENGTH_COMPANY_NAME_CHARS
The maximum length of a company name in characters including '\0'.
Definition: company_type.h:41
Owner
Enum for all companies/owners.
Definition: company_type.h:18
@ COMPANY_SPECTATOR
The client is spectating.
Definition: company_type.h:35
@ COMPANY_NEW_COMPANY
The client wants a new company.
Definition: company_type.h:34
@ MAX_COMPANIES
Maximum number of companies.
Definition: company_type.h:23
static const uint NETWORK_COMPANY_NAME_LENGTH
The maximum length of the company name, in bytes including '\0'.
Definition: config.h:54
static const uint16_t NETWORK_DEFAULT_PORT
The default port of the game server (TCP & UDP)
Definition: config.h:25
void IConsoleCmdExec(const std::string &command_string, const uint recurse_count)
Execute a given command passed to us.
Definition: console.cpp:291
void IConsolePrint(TextColour colour_code, const std::string &string)
Handle the printing of text entered into the console or redirected there by any other means.
Definition: console.cpp:89
static const TextColour CC_DEFAULT
Default colour of the console.
Definition: console_type.h:23
void NetworkCoreShutdown()
Shuts down the network core (as that is needed for some platforms.
Definition: core.cpp:44
bool NetworkCoreInitialize()
Initializes the network core (as that is needed for some platforms.
Definition: core.cpp:24
@ NETWORK_RECV_STATUS_CLIENT_QUIT
The connection is lost gracefully. Other clients are already informed of this leaving client.
Definition: core.h:28
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
Definition: error_gui.cpp:367
@ WL_ERROR
Errors (eg. saving/loading failed)
Definition: error.h:26
@ WL_CRITICAL
Critical errors, the MessageBox is shown in all cases.
Definition: error.h:27
std::optional< FileHandle > FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
Definition: fileio.cpp:242
@ SAVE_DIR
Base directory for all savegames.
Definition: fileio_type.h:117
PauseMode _pause_mode
The current pause mode.
Definition: gfx.cpp:50
SwitchMode _switch_mode
The next mainloop command.
Definition: gfx.cpp:49
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition: gfx_type.h:260
void NetworkFindBroadcastIPs(NetworkAddressList *broadcast)
Find the IPv4 broadcast addresses; IPv6 uses a completely different strategy for broadcasting.
Definition: host.cpp:86
Resolving of hostnames/IPs.
void NetworkHTTPInitialize()
Initialize the HTTP socket handler.
Definition: http_curl.cpp:242
void NetworkHTTPUninitialize()
Uninitialize the HTTP socket handler.
Definition: http_curl.cpp:277
uint32_t _last_sync_frame
Used in the server to store the last time a sync packet was sent to clients.
Definition: network.cpp:79
void NetworkStartUp()
This tries to launch the network for a given OS.
Definition: network.cpp:1285
bool _is_network_server
Does this client wants to be a network-server?
Definition: network.cpp:69
NetworkClientInfoPool _networkclientinfo_pool("NetworkClientInfo")
Make sure both pools have the same size.
static uint NetworkCountActiveClients()
Counts the number of active clients connected.
Definition: network.cpp:422
StringList _network_host_list
The servers we know.
Definition: network.cpp:74
StringID GetNetworkErrorMsg(NetworkErrorCode err)
Retrieve the string id of an internal error number.
Definition: network.cpp:315
uint32_t _frame_counter_server
The frame_counter of the server, if in network-mode.
Definition: network.cpp:76
static void CheckPauseOnJoin()
Check whether we should pause on join.
Definition: network.cpp:464
NetworkAddressList _broadcast_list
List of broadcast addresses.
Definition: network.cpp:80
void NetworkQueryServer(const std::string &connection_string)
Query a server to fetch the game-info.
Definition: network.cpp:672
std::string NormalizeConnectionString(const std::string &connection_string, uint16_t default_port)
Normalize a connection string.
Definition: network.cpp:543
void NetworkClientJoinGame()
Actually perform the joining to the server.
Definition: network.cpp:820
static bool NetworkHasJoiningClient()
Checks whether there is a joining client.
Definition: network.cpp:452
static auto FindKey(auto *authorized_keys, std::string_view authorized_key)
Simple helper to find the location of the given authorized key in the authorized keys.
Definition: network.cpp:170
ClientID _redirect_console_to_client
If not invalid, redirect the console output to a client.
Definition: network.cpp:71
static void CheckClientAndServerName()
Check whether the client and server name are set, for a dedicated server and if not set them to some ...
Definition: network.cpp:875
void NetworkOnGameStart()
Perform tasks when the server is started.
Definition: network.cpp:947
std::string_view ParseCompanyFromConnectionString(const std::string &connection_string, CompanyID *company_id)
Parse the company part ("#company" postfix) of a connecting string.
Definition: network.cpp:479
uint32_t _frame_counter
The current frame.
Definition: network.cpp:78
bool _network_available
is network mode available?
Definition: network.cpp:67
uint8_t _network_reconnect
Reconnect timeout.
Definition: network.cpp:72
bool _networking
are we in networking mode?
Definition: network.cpp:65
static void InitializeNetworkPools(bool close_admins=true)
Resets the pools used for network clients, and the admin pool if needed.
Definition: network.cpp:585
StringList _network_ban_list
The banned clients.
Definition: network.cpp:75
std::string_view ParseFullConnectionString(const std::string &connection_string, uint16_t &port, CompanyID *company_id)
Converts a string to ip/port/company Format: IP:port::company.
Definition: network.cpp:523
bool _network_dedicated
are we a dedicated server?
Definition: network.cpp:68
bool HasClients()
Return whether there is any client connected or trying to connect at all.
Definition: network.cpp:99
static bool NetworkReceive()
Receives something from the network.
Definition: network.cpp:1052
void NetworkDisconnect(bool close_admins)
We want to disconnect from the host/clients.
Definition: network.cpp:1001
bool _network_server
network-server is active
Definition: network.cpp:66
std::string GenerateUid(std::string_view subject)
Generate an unique ID.
Definition: misc.cpp:66
uint32_t _sync_seed_1
Seed to compare during sync checks.
Definition: network.cpp:81
uint32_t _sync_frame
The frame to perform the sync check.
Definition: network.cpp:85
void NetworkBackgroundLoop()
We have to do some (simple) background stuff that runs normally, even when we are not in multiplayer.
Definition: network.cpp:1082
StringList _network_bind_list
The addresses to bind on.
Definition: network.cpp:73
static void CheckMinActiveClients()
Check if the minimum number of active clients has been reached and pause or unpause the game as appro...
Definition: network.cpp:438
ClientID _network_own_client_id
Our client identifier.
Definition: network.cpp:70
static void CheckPauseHelper(bool pause, PauseMode pm)
Helper function for the pause checkers.
Definition: network.cpp:410
bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const std::string &join_server_password)
Join a client to the server at with the given connection string.
Definition: network.cpp:787
void NetworkHandlePauseChange(PauseMode prev_mode, PauseMode changed_mode)
Handle the pause mode change so we send the right messages to the chat.
Definition: network.cpp:356
bool _network_first_time
Whether we have finished joining or not.
Definition: network.cpp:86
NetworkGameList * NetworkAddServer(const std::string &connection_string, bool manually, bool never_expire)
Validates an address entered as a string and adds the server to the list.
Definition: network.cpp:694
void NetworkShutDown()
This shuts the network down.
Definition: network.cpp:1303
uint8_t _network_clients_connected
The amount of clients connected.
Definition: network.cpp:91
void GetBindAddresses(NetworkAddressList *addresses, uint16_t port)
Get the addresses to bind to.
Definition: network.cpp:720
NetworkAddress ParseConnectionString(const std::string &connection_string, uint16_t default_port)
Convert a string containing either "hostname" or "hostname:ip" to a NetworkAddress.
Definition: network.cpp:558
void NetworkUpdateServerGameType()
The setting server_game_type was updated; possibly we need to take some action.
Definition: network.cpp:1029
bool NetworkCanJoinCompany(CompanyID company_id)
Returns whether the given company can be joined by this client.
Definition: network.cpp:143
void NetworkClose(bool close_admins)
Close current connections.
Definition: network.cpp:594
uint32_t _frame_counter_max
To where we may go with our clients.
Definition: network.cpp:77
bool NetworkValidateServerName(std::string &server_name)
Trim the given server name in place, i.e.
Definition: network.cpp:860
Server part of the admin network protocol.
Base core network types and some helper functions to access them.
void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const std::string &message)
Add a text message to the 'chat window' to be shown.
NetworkJoinInfo _network_join
Information about the game to join to.
bool NetworkValidateOurClientName()
Convenience method for NetworkValidateClientName on _settings_client.network.client_name.
void NetworkClient_Connected()
Is called after a client is connected to the server.
Client part of the network protocol.
void NetworkFreeLocalCommandQueue()
Free the local command queues.
void NetworkExecuteLocalCommandQueue()
Execute all commands on the local command queue that ought to be executed this frame.
void NetworkDistributeCommands()
Distribute the commands of ourself and the clients.
ClientNetworkContentSocketHandler _network_content_client
The client we use to connect to the server.
Part of the network protocol handling content distribution.
ClientNetworkCoordinatorSocketHandler _network_coordinator_client
The connection to the Game Coordinator.
Part of the network protocol handling Game Coordinator requests.
void NetworkServerNewCompany(const Company *company, NetworkClientInfo *ci)
Perform all the server specific administration of a new company.
void NetworkServerUpdateGameInfo()
Update the server's NetworkServerGameInfo due to changes in settings.
NetworkGameList * NetworkGameListAddItem(const std::string &connection_string)
Add a new item to the linked gamelist.
NetworkGameList * _network_game_list
Game list of this client.
Handling of the list of games.
@ NGLS_OFFLINE
Server is offline (or cannot be queried).
NetworkJoinStatus _network_join_status
The status of joining.
void UpdateNetworkGameWindow()
Update the network new window because a new server is found on the network.
Definition: network_gui.cpp:66
GUIs related to networking.
Query part of the network protocol.
void ChangeNetworkRestartTime(bool reset)
Reset the automatic network restart time interval.
void NetworkServer_Tick(bool send_frame)
This is called every tick if this is a _network_server.
Server part of the network protocol.
@ DESTTYPE_CLIENT
Send message/notice to only a certain client (Private)
Definition: network_type.h:82
NetworkAction
Actions that can be used for NetworkTextMessage.
Definition: network_type.h:90
ClientID
'Unique' identifier to be given to clients
Definition: network_type.h:49
@ CLIENT_ID_SERVER
Servers always have this ID.
Definition: network_type.h:51
NetworkErrorCode
The error codes we send around in the protocols.
Definition: network_type.h:110
void NetworkUDPClose()
Close all UDP related stuff.
void NetworkUDPInitialize()
Initialize the whole UDP bit.
void NetworkUDPServerListen()
Start the listening of the UDP server component.
void NetworkBackgroundUDPLoop()
Receive the UDP packets.
Sending and receiving UDP messages.
void ClearGRFConfigList(GRFConfig **config)
Clear a GRF Config list, freeing all nodes.
void StateGameLoop()
State controlling game loop.
Definition: openttd.cpp:1212
@ SM_JOIN_GAME
Join a network game.
Definition: openttd.h:41
@ SM_MENU
Switch to game intro menu.
Definition: openttd.h:33
PauseMode
Modes of pausing we've got.
Definition: openttd.h:68
@ PM_UNPAUSED
A normal unpaused game.
Definition: openttd.h:69
@ PM_PAUSED_ACTIVE_CLIENTS
A game paused for 'min_active_clients'.
Definition: openttd.h:74
@ PM_PAUSED_ERROR
A game paused because a (critical) error.
Definition: openttd.h:73
@ PM_PAUSED_GAME_SCRIPT
A game paused by a game script.
Definition: openttd.h:75
@ PM_PAUSED_JOIN
A game paused for 'pause_on_join'.
Definition: openttd.h:72
@ PM_PAUSED_LINK_GRAPH
A game paused due to the link graph schedule lagging.
Definition: openttd.h:76
@ PM_PAUSED_NORMAL
A game normally paused.
Definition: openttd.h:70
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Definition: pool_func.hpp:237
@ PT_NONE
No pool is selected.
Definition: pool_type.hpp:17
@ PT_NADMIN
Network admin pool.
Definition: pool_type.hpp:20
@ PT_NCLIENT
Network client pools.
Definition: pool_type.hpp:19
Randomizer _random
Random used in the game state calculations.
Definition: random_func.cpp:37
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:56
#define lengthof(array)
Return the length of an fixed size array.
Definition: stdafx.h:280
std::string FormatArrayAsHex(std::span< const uint8_t > data)
Format a byte array into a continuous hex string.
Definition: string.cpp:81
void StrTrimInPlace(std::string &str)
Trim the spaces from given string in place, i.e.
Definition: string.cpp:260
size_t Utf8Encode(T buf, char32_t c)
Encode a unicode character and place it in the buffer.
Definition: string.cpp:460
static const char32_t CHAR_TD_LRM
The next character acts like a left-to-right character.
Definition: string_type.h:35
static const char32_t CHAR_TD_RLM
The next character acts like a right-to-left character.
Definition: string_type.h:36
std::vector< std::string > StringList
Type for a list of strings.
Definition: string_type.h:60
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings.cpp:104
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Definition: strings.cpp:319
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:56
void SetDParamStr(size_t n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:357
@ TD_LTR
Text is written left-to-right by default.
Definition: strings_type.h:23
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
static const int MAX_CHAR_LENGTH
Max. length of UTF-8 encoded unicode character.
Definition: strings_type.h:18
NetworkSettings network
settings related to the network
GUISettings gui
settings related to the GUI
Everything we need to know about a command to be able to execute it.
StringID err_msg
string ID of error message to use.
CommandDataBuffer data
command parameters.
CompanyID company
company that is executing the command
Commands cmd
command being executed.
Defines the traits of a command.
Definition: command_type.h:453
NetworkAuthorizedKeys allow_list
Public keys of clients that are allowed to join this company.
Definition: company_base.h:78
StringID name_1
Name of the company if the user did not change it.
Definition: company_base.h:71
std::string name
Name of the company if the user changed it.
Definition: company_base.h:72
uint16_t network_chat_timeout
timeout of chat messages in seconds
Container for all information known about a client.
Definition: network_base.h:24
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it's client-identifier.
Definition: network.cpp:118
~NetworkClientInfo()
Basically a client is leaving us right now.
Definition: network.cpp:107
bool CanJoinCompany(CompanyID company_id) const
Returns whether the given company can be joined by this client.
Definition: network.cpp:132
CompanyID client_playas
As which company is this client playing (CompanyID)
Definition: network_base.h:28
ClientID client_id
Client identifier (same as ClientState->client_id)
Definition: network_base.h:25
std::string client_name
Name of the client.
Definition: network_base.h:26
std::string public_key
The public key of the client.
Definition: network_base.h:27
Structure with information shown in the game list (GUI)
int version
Used to see which servers are no longer available on the Game Coordinator and can be removed.
bool refreshing
Whether this server is being queried.
bool manually
True if the server was added manually.
NetworkGameList * next
Next pointer to make a linked game list.
NetworkGameListStatus status
Stats of the server.
NetworkGameInfo info
The game information of this server.
std::string connection_string
The address of the server to join.
std::string server_password
The password of the server to join.
CompanyID company
The company to join.
std::string server_name
Server name.
GRFConfig * grfconfig
List of NewGRF files used.
uint8_t clients_on
Current count of clients on server.
std::string client_secret_key
The secret key of the client for authorized key logins.
std::string client_name
name of the player (as client)
ServerGameType server_game_type
Server type: local / public / invite-only.
std::string client_public_key
The public key of the client for authorized key logins.
uint8_t frame_freq
how often do we send commands to the clients
uint8_t min_active_clients
minimum amount of active clients to unpause the game
uint16_t server_port
port the server listens on
std::string last_joined
Last joined server.
std::string server_name
name of the server
uint16_t server_admin_port
port the server listens on for the admin network
bool pause_on_join
pause the game when people join
static void Clean(PoolType)
Clean all pools of given type.
Definition: pool_func.cpp:30
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:328
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition: pool_type.hpp:309
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:350
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
Base class for all pools.
Definition: pool_type.hpp:80
static constexpr size_t MAX_SIZE
Make template parameter accessible from outside.
Definition: pool_type.hpp:84
uint32_t state[2]
The state of the randomizer.
Definition: random_func.hpp:29
Basic functions to receive and send UDP packets.
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition: window.cpp:1140
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition: window.cpp:3211
@ WN_NETWORK_STATUS_WINDOW_JOIN
Network join status.
Definition: window_type.h:39
@ WC_SEND_NETWORK_MSG
Chatbox; Window numbers:
Definition: window_type.h:509
@ WC_CLIENT_LIST
Client list; Window numbers:
Definition: window_type.h:484
@ WC_NETWORK_STATUS_WINDOW
Network status window; Window numbers:
Definition: window_type.h:491