OpenTTD Source 20241224-master-gf74b0cf984
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
55bool _ddc_fastforward = true;
56#endif /* DEBUG_DUMP_COMMANDS */
57
60
64
81uint32_t _sync_seed_1;
82#ifdef NETWORK_SEND_DOUBLE_SEED
83uint32_t _sync_seed_2;
84#endif
85uint32_t _sync_frame;
87
90
91extern std::string GenerateUid(std::string_view subject);
92
98{
99 return !NetworkClientSocket::Iterate().empty();
100}
101
106{
107 /* Delete the chat window, if you were chatting with this client. */
109}
110
117{
119 if (ci->client_id == client_id) return ci;
120 }
121
122 return nullptr;
123}
124
131{
132 Company *c = Company::GetIfValid(company_id);
133 return c != nullptr && c->allow_list.Contains(this->public_key);
134}
135
142{
144 return info != nullptr && info->CanJoinCompany(company_id);
145}
146
153{
155 if (cs->client_id == client_id) return cs;
156 }
157
158 return nullptr;
159}
160
161
168static auto FindKey(auto *authorized_keys, std::string_view authorized_key)
169{
170 return std::ranges::find_if(*authorized_keys, [authorized_key](auto &value) { return StrEqualsIgnoreCase(value, authorized_key); });
171}
172
178bool NetworkAuthorizedKeys::Contains(std::string_view key) const
179{
180 return FindKey(this, key) != this->end();
181}
182
188bool NetworkAuthorizedKeys::Add(std::string_view key)
189{
190 if (key.empty()) return false;
191
192 auto iter = FindKey(this, key);
193 if (iter != this->end()) return false;
194
195 this->emplace_back(key);
196 return true;
197}
198
204bool NetworkAuthorizedKeys::Remove(std::string_view key)
205{
206 auto iter = FindKey(this, key);
207 if (iter == this->end()) return false;
208
209 this->erase(iter);
210 return true;
211}
212
213
214uint8_t NetworkSpectatorCount()
215{
216 uint8_t count = 0;
217
218 for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
219 if (ci->client_playas == COMPANY_SPECTATOR) count++;
220 }
221
222 /* Don't count a dedicated server as spectator */
223 if (_network_dedicated) count--;
224
225 return count;
226}
227
228
229/* This puts a text-message to the console, or in the future, the chat-box,
230 * (to keep it all a bit more general)
231 * If 'self_send' is true, this is the client who is sending the message */
232void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const std::string &name, const std::string &str, int64_t data, const std::string &data_str)
233{
234 StringID strid;
235 switch (action) {
236 case NETWORK_ACTION_SERVER_MESSAGE:
237 /* Ignore invalid messages */
238 strid = STR_NETWORK_SERVER_MESSAGE;
239 colour = CC_DEFAULT;
240 break;
241 case NETWORK_ACTION_COMPANY_SPECTATOR:
242 colour = CC_DEFAULT;
243 strid = STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE;
244 break;
245 case NETWORK_ACTION_COMPANY_JOIN:
246 colour = CC_DEFAULT;
247 strid = STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN;
248 break;
249 case NETWORK_ACTION_COMPANY_NEW:
250 colour = CC_DEFAULT;
251 strid = STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW;
252 break;
253 case NETWORK_ACTION_JOIN:
254 /* Show the Client ID for the server but not for the client. */
255 strid = _network_server ? STR_NETWORK_MESSAGE_CLIENT_JOINED_ID : STR_NETWORK_MESSAGE_CLIENT_JOINED;
256 break;
257 case NETWORK_ACTION_LEAVE: strid = STR_NETWORK_MESSAGE_CLIENT_LEFT; break;
258 case NETWORK_ACTION_NAME_CHANGE: strid = STR_NETWORK_MESSAGE_NAME_CHANGE; break;
259 case NETWORK_ACTION_GIVE_MONEY: strid = STR_NETWORK_MESSAGE_GIVE_MONEY; break;
260 case NETWORK_ACTION_CHAT_COMPANY: strid = self_send ? STR_NETWORK_CHAT_TO_COMPANY : STR_NETWORK_CHAT_COMPANY; break;
261 case NETWORK_ACTION_CHAT_CLIENT: strid = self_send ? STR_NETWORK_CHAT_TO_CLIENT : STR_NETWORK_CHAT_CLIENT; break;
262 case NETWORK_ACTION_KICKED: strid = STR_NETWORK_MESSAGE_KICKED; break;
263 case NETWORK_ACTION_EXTERNAL_CHAT: strid = STR_NETWORK_CHAT_EXTERNAL; break;
264 default: strid = STR_NETWORK_CHAT_ALL; break;
265 }
266
267 SetDParamStr(0, name);
268 SetDParamStr(1, str);
269 SetDParam(2, data);
270 SetDParamStr(3, data_str);
271
272 /* All of these strings start with "***". These characters are interpreted as both left-to-right and
273 * right-to-left characters depending on the context. As the next text might be an user's name, the
274 * user name's characters will influence the direction of the "***" instead of the language setting
275 * of the game. Manually set the direction of the "***" by inserting a text-direction marker. */
276 std::ostringstream stream;
277 std::ostreambuf_iterator<char> iterator(stream);
279 std::string message = stream.str() + GetString(strid);
280
281 Debug(desync, 1, "msg: {:08x}; {:02x}; {}", TimerGameEconomy::date, TimerGameEconomy::date_fract, message);
282 IConsolePrint(colour, message);
284}
285
286/* Calculate the frame-lag of a client */
287uint NetworkCalculateLag(const NetworkClientSocket *cs)
288{
289 int lag = cs->last_frame_server - cs->last_frame;
290 /* This client has missed their ACK packet after 1 DAY_TICKS..
291 * so we increase their lag for every frame that passes!
292 * The packet can be out by a max of _net_frame_freq */
293 if (cs->last_frame_server + Ticks::DAY_TICKS + _settings_client.network.frame_freq < _frame_counter) {
294 lag += _frame_counter - (cs->last_frame_server + Ticks::DAY_TICKS + _settings_client.network.frame_freq);
295 }
296 return lag;
297}
298
299
300/* There was a non-recoverable error, drop back to the main menu with a nice
301 * error */
302void ShowNetworkError(StringID error_string)
303{
306}
307
314{
315 /* List of possible network errors, used by
316 * PACKET_SERVER_ERROR and PACKET_CLIENT_ERROR */
317 static const StringID network_error_strings[] = {
318 STR_NETWORK_ERROR_CLIENT_GENERAL,
319 STR_NETWORK_ERROR_CLIENT_DESYNC,
320 STR_NETWORK_ERROR_CLIENT_SAVEGAME,
321 STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST,
322 STR_NETWORK_ERROR_CLIENT_PROTOCOL_ERROR,
323 STR_NETWORK_ERROR_CLIENT_NEWGRF_MISMATCH,
324 STR_NETWORK_ERROR_CLIENT_NOT_AUTHORIZED,
325 STR_NETWORK_ERROR_CLIENT_NOT_EXPECTED,
326 STR_NETWORK_ERROR_CLIENT_WRONG_REVISION,
327 STR_NETWORK_ERROR_CLIENT_NAME_IN_USE,
328 STR_NETWORK_ERROR_CLIENT_WRONG_PASSWORD,
329 STR_NETWORK_ERROR_CLIENT_COMPANY_MISMATCH,
330 STR_NETWORK_ERROR_CLIENT_KICKED,
331 STR_NETWORK_ERROR_CLIENT_CHEATER,
332 STR_NETWORK_ERROR_CLIENT_SERVER_FULL,
333 STR_NETWORK_ERROR_CLIENT_TOO_MANY_COMMANDS,
334 STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD,
335 STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER,
336 STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP,
337 STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN,
338 STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME,
339 STR_NETWORK_ERROR_CLIENT_NOT_ON_ALLOW_LIST,
340 STR_NETWORK_ERROR_CLIENT_NO_AUTHENTICATION_METHOD_AVAILABLE,
341 };
342 static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
343
344 if (err >= (ptrdiff_t)lengthof(network_error_strings)) err = NETWORK_ERROR_GENERAL;
345
346 return network_error_strings[err];
347}
348
354void NetworkHandlePauseChange(PauseMode prev_mode, PauseMode changed_mode)
355{
356 if (!_networking) return;
357
358 switch (changed_mode) {
359 case PM_PAUSED_NORMAL:
360 case PM_PAUSED_JOIN:
364 bool changed = ((_pause_mode == PM_UNPAUSED) != (prev_mode == PM_UNPAUSED));
365 bool paused = (_pause_mode != PM_UNPAUSED);
366 if (!paused && !changed) return;
367
368 StringID str;
369 if (!changed) {
370 int i = -1;
371
372 if ((_pause_mode & PM_PAUSED_NORMAL) != PM_UNPAUSED) SetDParam(++i, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL);
373 if ((_pause_mode & PM_PAUSED_JOIN) != PM_UNPAUSED) SetDParam(++i, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS);
374 if ((_pause_mode & PM_PAUSED_GAME_SCRIPT) != PM_UNPAUSED) SetDParam(++i, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT);
375 if ((_pause_mode & PM_PAUSED_ACTIVE_CLIENTS) != PM_UNPAUSED) SetDParam(++i, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS);
376 if ((_pause_mode & PM_PAUSED_LINK_GRAPH) != PM_UNPAUSED) SetDParam(++i, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH);
377 str = STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_1 + i;
378 } else {
379 switch (changed_mode) {
380 case PM_PAUSED_NORMAL: SetDParam(0, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL); break;
381 case PM_PAUSED_JOIN: SetDParam(0, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS); break;
382 case PM_PAUSED_GAME_SCRIPT: SetDParam(0, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT); break;
383 case PM_PAUSED_ACTIVE_CLIENTS: SetDParam(0, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS); break;
384 case PM_PAUSED_LINK_GRAPH: SetDParam(0, STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH); break;
385 default: NOT_REACHED();
386 }
387 str = paused ? STR_NETWORK_SERVER_MESSAGE_GAME_PAUSED : STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED;
388 }
389
390 NetworkTextMessage(NETWORK_ACTION_SERVER_MESSAGE, CC_DEFAULT, false, "", GetString(str));
391 break;
392 }
393
394 default:
395 return;
396 }
397}
398
399
408static void CheckPauseHelper(bool pause, PauseMode pm)
409{
410 if (pause == ((_pause_mode & pm) != PM_UNPAUSED)) return;
411
412 Command<CMD_PAUSE>::Post(pm, pause);
413}
414
421{
422 uint count = 0;
423
424 for (const NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
425 if (cs->status != NetworkClientSocket::STATUS_ACTIVE) continue;
426 if (!Company::IsValidID(cs->GetInfo()->client_playas)) continue;
427 count++;
428 }
429
430 return count;
431}
432
445
451{
452 for (const NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
453 if (cs->status >= NetworkClientSocket::STATUS_AUTHORIZED && cs->status < NetworkClientSocket::STATUS_ACTIVE) return true;
454 }
455
456 return false;
457}
458
470
477std::string_view ParseCompanyFromConnectionString(const std::string &connection_string, CompanyID *company_id)
478{
479 std::string_view ip = connection_string;
480 if (company_id == nullptr) return ip;
481
482 size_t offset = ip.find_last_of('#');
483 if (offset != std::string::npos) {
484 std::string_view company_string = ip.substr(offset + 1);
485 ip = ip.substr(0, offset);
486
487 uint8_t company_value;
488 auto [_, err] = std::from_chars(company_string.data(), company_string.data() + company_string.size(), company_value);
489 if (err == std::errc()) {
490 if (company_value != COMPANY_NEW_COMPANY && company_value != COMPANY_SPECTATOR) {
491 if (company_value > MAX_COMPANIES || company_value == 0) {
492 *company_id = COMPANY_SPECTATOR;
493 } else {
494 /* "#1" means the first company, which has index 0. */
495 *company_id = (CompanyID)(company_value - 1);
496 }
497 } else {
498 *company_id = (CompanyID)company_value;
499 }
500 }
501 }
502
503 return ip;
504}
505
521std::string_view ParseFullConnectionString(const std::string &connection_string, uint16_t &port, CompanyID *company_id)
522{
523 std::string_view ip = ParseCompanyFromConnectionString(connection_string, company_id);
524
525 size_t port_offset = ip.find_last_of(':');
526 size_t ipv6_close = ip.find_last_of(']');
527 if (port_offset != std::string::npos && (ipv6_close == std::string::npos || ipv6_close < port_offset)) {
528 std::string_view port_string = ip.substr(port_offset + 1);
529 ip = ip.substr(0, port_offset);
530 std::from_chars(port_string.data(), port_string.data() + port_string.size(), port);
531 }
532 return ip;
533}
534
541std::string NormalizeConnectionString(const std::string &connection_string, uint16_t default_port)
542{
543 uint16_t port = default_port;
544 std::string_view ip = ParseFullConnectionString(connection_string, port);
545 return std::string(ip) + ":" + std::to_string(port);
546}
547
556NetworkAddress ParseConnectionString(const std::string &connection_string, uint16_t default_port)
557{
558 uint16_t port = default_port;
559 std::string_view ip = ParseFullConnectionString(connection_string, port);
560 return NetworkAddress(ip, port);
561}
562
568/* static */ void ServerNetworkGameSocketHandler::AcceptConnection(SOCKET s, const NetworkAddress &address)
569{
570 /* Register the login */
572
574 cs->client_address = address; // Save the IP of the client
575
577}
578
583static void InitializeNetworkPools(bool close_admins = true)
584{
585 PoolBase::Clean(PT_NCLIENT | (close_admins ? PT_NADMIN : PT_NONE));
586}
587
592void NetworkClose(bool close_admins)
593{
594 if (_network_server) {
595 if (close_admins) {
597 as->CloseConnection(true);
598 }
599 }
600
601 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
602 cs->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT);
603 }
606
608 } else {
609 if (MyClient::my_client != nullptr) {
612 }
613
615 }
616 NetworkGameSocketHandler::ProcessDeferredDeletions();
617
619
620 _networking = false;
621 _network_server = false;
622
624
625 InitializeNetworkPools(close_admins);
626}
627
628/* Initializes the network (cleans sockets and stuff) */
629static void NetworkInitialize(bool close_admins = true)
630{
631 InitializeNetworkPools(close_admins);
632
633 _sync_frame = 0;
634 _network_first_time = true;
635
637}
638
641private:
642 std::string connection_string;
643
644public:
645 TCPQueryConnecter(const std::string &connection_string) : TCPServerConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {}
646
647 void OnFailure() override
648 {
649 Debug(net, 9, "Query::OnFailure(): connection_string={}", this->connection_string);
650
651 NetworkGameList *item = NetworkGameListAddItem(connection_string);
652 item->status = NGLS_OFFLINE;
653 item->refreshing = false;
654
656 }
657
658 void OnConnect(SOCKET s) override
659 {
660 Debug(net, 9, "Query::OnConnect(): connection_string={}", this->connection_string);
661
662 QueryNetworkGameSocketHandler::QueryServer(s, this->connection_string);
663 }
664};
665
670void NetworkQueryServer(const std::string &connection_string)
671{
672 if (!_network_available) return;
673
674 Debug(net, 9, "NetworkQueryServer(): connection_string={}", connection_string);
675
676 /* Mark the entry as refreshing, so the GUI can show the refresh is pending. */
677 NetworkGameList *item = NetworkGameListAddItem(connection_string);
678 item->refreshing = true;
679
680 TCPConnecter::Create<TCPQueryConnecter>(connection_string);
681}
682
692NetworkGameList *NetworkAddServer(const std::string &connection_string, bool manually, bool never_expire)
693{
694 if (connection_string.empty()) return nullptr;
695
696 /* Ensure the item already exists in the list */
697 NetworkGameList *item = NetworkGameListAddItem(connection_string);
698 if (item->info.server_name.empty()) {
700 item->info.server_name = connection_string;
701
703
704 NetworkQueryServer(connection_string);
705 }
706
707 if (manually) item->manually = true;
708 if (never_expire) item->version = INT32_MAX;
709
710 return item;
711}
712
718void GetBindAddresses(NetworkAddressList *addresses, uint16_t port)
719{
720 for (const auto &iter : _network_bind_list) {
721 addresses->emplace_back(iter.c_str(), port);
722 }
723
724 /* No address, so bind to everything. */
725 if (addresses->empty()) {
726 addresses->emplace_back("", port);
727 }
728}
729
730/* Generates the list of manually added hosts from NetworkGameList and
731 * dumps them into the array _network_host_list. This array is needed
732 * by the function that generates the config file. */
733void NetworkRebuildHostList()
734{
735 _network_host_list.clear();
736
737 for (NetworkGameList *item = _network_game_list; item != nullptr; item = item->next) {
738 if (item->manually) _network_host_list.emplace_back(item->connection_string);
739 }
740}
741
744private:
745 std::string connection_string;
746
747public:
748 TCPClientConnecter(const std::string &connection_string) : TCPServerConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {}
749
750 void OnFailure() override
751 {
752 Debug(net, 9, "Client::OnFailure(): connection_string={}", this->connection_string);
753
754 ShowNetworkError(STR_NETWORK_ERROR_NOCONNECTION);
755 }
756
757 void OnConnect(SOCKET s) override
758 {
759 Debug(net, 9, "Client::OnConnect(): connection_string={}", this->connection_string);
760
761 _networking = true;
763 new ClientNetworkGameSocketHandler(s, this->connection_string);
764 IConsoleCmdExec("exec scripts/on_client.scr 0");
766 }
767};
768
785bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const std::string &join_server_password)
786{
787 Debug(net, 9, "NetworkClientConnectGame(): connection_string={}", connection_string);
788
789 CompanyID join_as = default_company;
790 std::string resolved_connection_string = ServerAddress::Parse(connection_string, NETWORK_DEFAULT_PORT, &join_as).connection_string;
791
792 if (!_network_available) return false;
793 if (!NetworkValidateOurClientName()) return false;
794
795 _network_join.connection_string = resolved_connection_string;
796 _network_join.company = join_as;
797 _network_join.server_password = join_server_password;
798
799 if (_game_mode == GM_MENU) {
800 /* From the menu we can immediately continue with the actual join. */
802 } else {
803 /* When already playing a game, first go back to the main menu. This
804 * disconnects the user from the current game, meaning we can safely
805 * load in the new. After all, there is little point in continueing to
806 * play on a server if we are connecting to another one.
807 */
809 }
810 return true;
811}
812
819{
821 NetworkInitialize();
822
824 Debug(net, 9, "status = CONNECTING");
825 _network_join_status = NETWORK_JOIN_STATUS_CONNECTING;
826 ShowJoinStatusWindow();
827
828 TCPConnecter::Create<TCPClientConnecter>(_network_join.connection_string);
829}
830
831static void NetworkInitGameInfo()
832{
833 FillStaticNetworkServerGameInfo();
834 /* The server is a client too */
835 _network_game_info.clients_on = _network_dedicated ? 0 : 1;
836
837 /* There should be always space for the server. */
841
843
846}
847
858bool NetworkValidateServerName(std::string &server_name)
859{
860 StrTrimInPlace(server_name);
861 if (!server_name.empty()) return true;
862
863 ShowErrorMessage(STR_NETWORK_ERROR_BAD_SERVER_NAME, INVALID_STRING_ID, WL_ERROR);
864 return false;
865}
866
874{
875 static const std::string fallback_client_name = "Unnamed Client";
877 if (_settings_client.network.client_name.empty() || _settings_client.network.client_name.compare(fallback_client_name) == 0) {
878 Debug(net, 1, "No \"client_name\" has been set, using \"{}\" instead. Please set this now using the \"name <new name>\" command", fallback_client_name);
879 _settings_client.network.client_name = fallback_client_name;
880 }
881
882 static const std::string fallback_server_name = "Unnamed Server";
884 if (_settings_client.network.server_name.empty() || _settings_client.network.server_name.compare(fallback_server_name) == 0) {
885 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);
886 _settings_client.network.server_name = fallback_server_name;
887 }
888}
889
890bool NetworkServerStart()
891{
892 if (!_network_available) return false;
893
894 /* Call the pre-scripts */
895 IConsoleCmdExec("exec scripts/pre_server.scr 0");
896 if (_network_dedicated) IConsoleCmdExec("exec scripts/pre_dedicated.scr 0");
897
898 /* Check for the client and server names to be set, but only after the scripts had a chance to set them.*/
900
901 NetworkDisconnect(false);
902 NetworkInitialize(false);
904 Debug(net, 5, "Starting listeners for clients");
906
907 /* Only listen for admins when the authentication is configured. */
908 if (_settings_client.network.AdminAuthenticationConfigured()) {
909 Debug(net, 5, "Starting listeners for admins");
911 }
912
913 /* Try to start UDP-server */
914 Debug(net, 5, "Starting listeners for incoming server queries");
916
917 _network_server = true;
918 _networking = true;
919 _frame_counter = 0;
924
926
927 NetworkInitGameInfo();
928
929 if (_settings_client.network.server_game_type != SERVER_GAME_TYPE_LOCAL) {
931 }
932
933 /* execute server initialization script */
934 IConsoleCmdExec("exec scripts/on_server.scr 0");
935 /* if the server is dedicated ... add some other script */
936 if (_network_dedicated) IConsoleCmdExec("exec scripts/on_dedicated.scr 0");
937
938 return true;
939}
940
946{
947 if (!_network_server) return;
948
949 /* Update the static game info to set the values from the new game. */
951
953
954 if (!_network_dedicated) {
957 if (c != nullptr && ci != nullptr) {
958 ci->client_playas = c->index;
959
960 /*
961 * If the company has not been named yet, the company was just started.
962 * Otherwise it would have gotten a name already, so announce it as a new company.
963 */
964 if (c->name_1 == STR_SV_UNNAMED && c->name.empty()) NetworkServerNewCompany(c, ci);
965 }
966
967 ShowClientList();
968 } else {
969 /* welcome possibly still connected admins - this can only happen on a dedicated server. */
971 }
972}
973
974/* The server is rebooting...
975 * The only difference with NetworkDisconnect, is the packets that is sent */
976void NetworkReboot()
977{
978 if (_network_server) {
979 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
980 cs->SendNewGame();
981 cs->SendPackets();
982 }
983
985 as->SendNewGame();
986 as->SendPackets();
987 }
988 }
989
990 /* For non-dedicated servers we have to kick the admins as we are not
991 * certain that we will end up in a new network game. */
993}
994
999void NetworkDisconnect(bool close_admins)
1000{
1001 if (_network_server) {
1002 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1003 cs->SendShutdown();
1004 cs->SendPackets();
1005 }
1006
1007 if (close_admins) {
1009 as->SendShutdown();
1010 as->SendPackets();
1011 }
1012 }
1013 }
1014
1016
1017 NetworkClose(close_admins);
1018
1019 /* Reinitialize the UDP stack, i.e. close all existing connections. */
1021}
1022
1028{
1029 if (!_networking) return;
1030
1032 case SERVER_GAME_TYPE_LOCAL:
1034 break;
1035
1036 case SERVER_GAME_TYPE_INVITE_ONLY:
1037 case SERVER_GAME_TYPE_PUBLIC:
1039 break;
1040
1041 default:
1042 NOT_REACHED();
1043 }
1044}
1045
1050static bool NetworkReceive()
1051{
1052 bool result;
1053 if (_network_server) {
1056 } else {
1058 }
1059 NetworkGameSocketHandler::ProcessDeferredDeletions();
1060 return result;
1061}
1062
1063/* This sends all buffered commands (if possible) */
1064static void NetworkSend()
1065{
1066 if (_network_server) {
1069 } else {
1071 }
1072 NetworkGameSocketHandler::ProcessDeferredDeletions();
1073}
1074
1091
1092/* The main loop called from ttd.c
1093 * Here we also have to do StateGameLoop if needed! */
1094void NetworkGameLoop()
1095{
1096 if (!_networking) return;
1097
1098 if (!NetworkReceive()) return;
1099
1100 if (_network_server) {
1101 /* Log the sync state to check for in-syncedness of replays. */
1103 /* We don't want to log multiple times if paused. */
1104 static TimerGameEconomy::Date last_log;
1105 if (last_log != TimerGameEconomy::date) {
1106 Debug(desync, 1, "sync: {:08x}; {:02x}; {:08x}; {:08x}", TimerGameEconomy::date, TimerGameEconomy::date_fract, _random.state[0], _random.state[1]);
1107 last_log = TimerGameEconomy::date;
1108 }
1109 }
1110
1111#ifdef DEBUG_DUMP_COMMANDS
1112 /* Loading of the debug commands from -ddesync>=1 */
1113 static auto f = FioFOpenFile("commands.log", "rb", SAVE_DIR);
1114 static TimerGameEconomy::Date next_date(0);
1115 static uint32_t next_date_fract;
1116 static CommandPacket *cp = nullptr;
1117 static bool check_sync_state = false;
1118 static uint32_t sync_state[2];
1119 if (!f.has_value() && next_date == 0) {
1120 Debug(desync, 0, "Cannot open commands.log");
1121 next_date = TimerGameEconomy::Date(1);
1122 }
1123
1124 while (f.has_value() && !feof(*f)) {
1125 if (TimerGameEconomy::date == next_date && TimerGameEconomy::date_fract == next_date_fract) {
1126 if (cp != nullptr) {
1127 NetworkSendCommand(cp->cmd, cp->err_msg, nullptr, cp->company, cp->data);
1128 Debug(desync, 0, "Injecting: {:08x}; {:02x}; {:02x}; {:08x}; {} ({})", TimerGameEconomy::date, TimerGameEconomy::date_fract, (int)_current_company, cp->cmd, FormatArrayAsHex(cp->data), GetCommandName(cp->cmd));
1129 delete cp;
1130 cp = nullptr;
1131 }
1132 if (check_sync_state) {
1133 if (sync_state[0] == _random.state[0] && sync_state[1] == _random.state[1]) {
1134 Debug(desync, 0, "Sync check: {:08x}; {:02x}; match", TimerGameEconomy::date, TimerGameEconomy::date_fract);
1135 } else {
1136 Debug(desync, 0, "Sync check: {:08x}; {:02x}; mismatch expected {{{:08x}, {:08x}}}, got {{{:08x}, {:08x}}}",
1137 TimerGameEconomy::date, TimerGameEconomy::date_fract, sync_state[0], sync_state[1], _random.state[0], _random.state[1]);
1138 NOT_REACHED();
1139 }
1140 check_sync_state = false;
1141 }
1142 }
1143
1144 /* Skip all entries in the command-log till we caught up with the current game again. */
1145 if (TimerGameEconomy::date > next_date || (TimerGameEconomy::date == next_date && TimerGameEconomy::date_fract > next_date_fract)) {
1146 Debug(desync, 0, "Skipping to next command at {:08x}:{:02x}", next_date, next_date_fract);
1147 if (cp != nullptr) {
1148 delete cp;
1149 cp = nullptr;
1150 }
1151 check_sync_state = false;
1152 }
1153
1154 if (cp != nullptr || check_sync_state) break;
1155
1156 char buff[4096];
1157 if (fgets(buff, lengthof(buff), *f) == nullptr) break;
1158
1159 char *p = buff;
1160 /* Ignore the "[date time] " part of the message */
1161 if (*p == '[') {
1162 p = strchr(p, ']');
1163 if (p == nullptr) break;
1164 p += 2;
1165 }
1166
1167 if (strncmp(p, "cmd: ", 5) == 0
1168#ifdef DEBUG_FAILED_DUMP_COMMANDS
1169 || strncmp(p, "cmdf: ", 6) == 0
1170#endif
1171 ) {
1172 p += 5;
1173 if (*p == ' ') p++;
1174 cp = new CommandPacket();
1175 int company;
1176 uint cmd;
1177 char buffer[256];
1178 uint32_t next_date_raw;
1179 int ret = sscanf(p, "%x; %x; %x; %x; %x; %255s", &next_date_raw, &next_date_fract, &company, &cmd, &cp->err_msg, buffer);
1180 assert(ret == 6);
1181 next_date = TimerGameEconomy::Date((int32_t)next_date_raw);
1182 cp->company = (CompanyID)company;
1183 cp->cmd = (Commands)cmd;
1184
1185 /* Parse command data. */
1186 std::vector<uint8_t> args;
1187 size_t arg_len = strlen(buffer);
1188 for (size_t i = 0; i + 1 < arg_len; i += 2) {
1189 uint8_t e = 0;
1190 std::from_chars(buffer + i, buffer + i + 2, e, 16);
1191 args.emplace_back(e);
1192 }
1193 cp->data = args;
1194 } else if (strncmp(p, "join: ", 6) == 0) {
1195 /* Manually insert a pause when joining; this way the client can join at the exact right time. */
1196 uint32_t next_date_raw;
1197 int ret = sscanf(p + 6, "%x; %x", &next_date_raw, &next_date_fract);
1198 next_date = TimerGameEconomy::Date((int32_t)next_date_raw);
1199 assert(ret == 2);
1200 Debug(desync, 0, "Injecting pause for join at {:08x}:{:02x}; please join when paused", next_date, next_date_fract);
1201 cp = new CommandPacket();
1203 cp->cmd = CMD_PAUSE;
1205 _ddc_fastforward = false;
1206 } else if (strncmp(p, "sync: ", 6) == 0) {
1207 uint32_t next_date_raw;
1208 int ret = sscanf(p + 6, "%x; %x; %x; %x", &next_date_raw, &next_date_fract, &sync_state[0], &sync_state[1]);
1209 next_date = TimerGameEconomy::Date((int32_t)next_date_raw);
1210 assert(ret == 4);
1211 check_sync_state = true;
1212 } else if (strncmp(p, "msg: ", 5) == 0 || strncmp(p, "client: ", 8) == 0 ||
1213 strncmp(p, "load: ", 6) == 0 || strncmp(p, "save: ", 6) == 0 ||
1214 strncmp(p, "warning: ", 9) == 0) {
1215 /* A message that is not very important to the log playback, but part of the log. */
1216#ifndef DEBUG_FAILED_DUMP_COMMANDS
1217 } else if (strncmp(p, "cmdf: ", 6) == 0) {
1218 Debug(desync, 0, "Skipping replay of failed command: {}", p + 6);
1219#endif
1220 } else {
1221 /* Can't parse a line; what's wrong here? */
1222 Debug(desync, 0, "Trying to parse: {}", p);
1223 NOT_REACHED();
1224 }
1225 }
1226 if (f.has_value() && feof(*f)) {
1227 Debug(desync, 0, "End of commands.log");
1228 f.reset();
1229 }
1230#endif /* DEBUG_DUMP_COMMANDS */
1232 /* Only check for active clients just before we're going to send out
1233 * the commands so we don't send multiple pause/unpause commands when
1234 * the frame_freq is more than 1 tick. Same with distributing commands. */
1238 }
1239
1240 bool send_frame = false;
1241
1242 /* We first increase the _frame_counter */
1244 /* Update max-frame-counter */
1247 send_frame = true;
1248 }
1249
1251
1252 /* Then we make the frame */
1253 StateGameLoop();
1254
1256#ifdef NETWORK_SEND_DOUBLE_SEED
1257 _sync_seed_2 = _random.state[1];
1258#endif
1259
1260 NetworkServer_Tick(send_frame);
1261 } else {
1262 /* Client */
1263
1264 /* Make sure we are at the frame were the server is (quick-frames) */
1266 /* Run a number of frames; when things go bad, get out. */
1269 }
1270 } else {
1271 /* Else, keep on going till _frame_counter_max */
1273 /* Run one frame; if things went bad, get out. */
1275 }
1276 }
1277 }
1278
1279 NetworkSend();
1280}
1281
1284{
1285 Debug(net, 3, "Starting network");
1286
1287 /* Network is available */
1289 _network_dedicated = false;
1290
1291 _network_game_info = {};
1292
1293 NetworkInitialize();
1295 Debug(net, 3, "Network online, multiplayer available");
1298}
1299
1302{
1306
1307 Debug(net, 3, "Shutting down network");
1308
1309 _network_available = false;
1310
1312}
1313
1314#ifdef __EMSCRIPTEN__
1315extern "C" {
1316
1317void CDECL em_openttd_add_server(const char *connection_string)
1318{
1319 NetworkAddServer(connection_string, false, true);
1320}
1321
1322}
1323#endif
std::vector< NetworkAddress > NetworkAddressList
Type for a list of addresses.
Definition address.h:20
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:178
bool Add(std::string_view key)
Add the given key to the authorized keys, when it is not already contained.
Definition network.cpp:188
bool Remove(std::string_view key)
Remove the given key from the authorized keys, when it is exists.
Definition network.cpp:204
ClientID client_id
Client identifier.
Definition tcp_game.h:486
static void HTTPReceive()
Do the receiving for all HTTP connections.
static void QueryServer(SOCKET s, const std::string &connection_string)
Start to query a server based on an open socket.
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.
static void Send()
Send the packets for the server sockets.
static void WelcomeAll()
Send a Welcome packet to all connected admins.
static Pool::IterateWrapperFiltered< ServerNetworkAdminSocketHandler, ServerNetworkAdminSocketHandlerFilter > IterateActive(size_t from=0)
Returns an iterable ensemble of all active admin sockets.
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:152
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:568
NetworkAddress client_address
IP-address of the client (so they can be banned)
Non blocking connection create to actually connect to servers.
Definition network.cpp:743
void OnConnect(SOCKET s) override
Callback when the connection succeeded.
Definition network.cpp:757
void OnFailure() override
Callback for when the connection attempt failed.
Definition network.cpp:750
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:640
void OnConnect(SOCKET s) override
Callback when the connection succeeded.
Definition network.cpp:658
void OnFailure() override
Callback for when the connection attempt failed.
Definition network.cpp:647
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.
@ CMD_PAUSE
pause the game
CompanyID GetFirstPlayableCompanyID()
Get the index of the first available company.
CompanyID _current_company
Company currently doing an action.
Owner
Enum for all companies/owners.
@ COMPANY_SPECTATOR
The client is spectating.
@ COMPANY_NEW_COMPANY
The client wants a new company.
@ MAX_COMPANIES
Maximum number of companies.
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.
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.
@ 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.
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.
void NetworkHTTPUninitialize()
Uninitialize the HTTP socket handler.
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:1283
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:420
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:313
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:462
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:670
std::string NormalizeConnectionString(const std::string &connection_string, uint16_t default_port)
Normalize a connection string.
Definition network.cpp:541
void NetworkClientJoinGame()
Actually perform the joining to the server.
Definition network.cpp:818
static bool NetworkHasJoiningClient()
Checks whether there is a joining client.
Definition network.cpp:450
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:168
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:873
void NetworkOnGameStart()
Perform tasks when the server is started.
Definition network.cpp:945
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:477
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:583
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:521
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:97
static bool NetworkReceive()
Receives something from the network.
Definition network.cpp:1050
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:692
void NetworkDisconnect(bool close_admins)
We want to disconnect from the host/clients.
Definition network.cpp:999
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:1080
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:436
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:408
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:785
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:354
bool _network_first_time
Whether we have finished joining or not.
Definition network.cpp:86
void NetworkShutDown()
This shuts the network down.
Definition network.cpp:1301
uint8_t _network_clients_connected
The amount of clients connected.
Definition network.cpp:89
void GetBindAddresses(NetworkAddressList *addresses, uint16_t port)
Get the addresses to bind to.
Definition network.cpp:718
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:556
void NetworkUpdateServerGameType()
The setting server_game_type was updated; possibly we need to take some action.
Definition network.cpp:1027
bool NetworkCanJoinCompany(CompanyID company_id)
Returns whether the given company can be joined by this client.
Definition network.cpp:141
void NetworkClose(bool close_admins)
Close current connections.
Definition network.cpp:592
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:858
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.
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)
NetworkAction
Actions that can be used for NetworkTextMessage.
ClientID
'Unique' identifier to be given to clients
@ CLIENT_ID_SERVER
Servers always have this ID.
NetworkErrorCode
The error codes we send around in the protocols.
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.
@ 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.
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
bool StrEqualsIgnoreCase(const std::string_view str1, const std::string_view str2)
Compares two string( view)s for equality, while ignoring the case of the characters.
Definition string.cpp:347
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:333
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:371
@ TD_LTR
Text is written left-to-right by default.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
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.
NetworkAuthorizedKeys allow_list
Public keys of clients that are allowed to join this company.
StringID name_1
Name of the company if the user did not change it.
std::string name
Name of the company if the user changed it.
uint16_t network_chat_timeout
timeout of chat messages in seconds
Container for all information known about a client.
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it's client-identifier.
Definition network.cpp:116
~NetworkClientInfo()
Basically a client is leaving us right now.
Definition network.cpp:105
bool CanJoinCompany(CompanyID company_id) const
Returns whether the given company can be joined by this client.
Definition network.cpp:130
CompanyID client_playas
As which company is this client playing (CompanyID)
ClientID client_id
Client identifier (same as ClientState->client_id)
std::string client_name
Name of the client.
std::string public_key
The public key of the client.
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.
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
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.
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:3219
@ WN_NETWORK_STATUS_WINDOW_JOIN
Network join status.
Definition window_type.h:39
@ WC_SEND_NETWORK_MSG
Chatbox; Window numbers:
@ WC_CLIENT_LIST
Client list; Window numbers:
@ WC_NETWORK_STATUS_WINDOW
Network status window; Window numbers: