OpenTTD Source 20250515-master-g6c84dd1f32
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 "../core/string_consumer.hpp"
13#include "../strings_func.h"
14#include "../command_func.h"
15#include "../timer/timer_game_tick.h"
16#include "../timer/timer_game_economy.h"
17#include "network_admin.h"
18#include "network_client.h"
19#include "network_query.h"
20#include "network_server.h"
21#include "network_content.h"
22#include "network_udp.h"
23#include "network_gamelist.h"
24#include "network_base.h"
25#include "network_coordinator.h"
26#include "core/udp.h"
27#include "core/host.h"
28#include "network_gui.h"
29#include "../console_func.h"
30#include "../3rdparty/md5/md5.h"
31#include "../core/random_func.hpp"
32#include "../window_func.h"
33#include "../company_func.h"
34#include "../company_base.h"
35#include "../landscape_type.h"
36#include "../rev.h"
37#include "../core/pool_func.hpp"
38#include "../gfx_func.h"
39#include "../error.h"
40#include "../misc_cmd.h"
41#include "../core/string_builder.hpp"
42#ifdef DEBUG_DUMP_COMMANDS
43# include "../fileio_func.h"
44#endif
45#include <charconv>
46
47#include "table/strings.h"
48
49#include "../safeguards.h"
50
51#ifdef DEBUG_DUMP_COMMANDS
57bool _ddc_fastforward = true;
58#endif /* DEBUG_DUMP_COMMANDS */
59
62
66
83uint32_t _sync_seed_1;
84#ifdef NETWORK_SEND_DOUBLE_SEED
85uint32_t _sync_seed_2;
86#endif
87uint32_t _sync_frame;
89
92
93extern std::string GenerateUid(std::string_view subject);
94
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{
157 if (cs->client_id == client_id) return cs;
158 }
159
160 return nullptr;
161}
162
163
170static auto FindKey(auto *authorized_keys, std::string_view authorized_key)
171{
172 return std::ranges::find_if(*authorized_keys, [authorized_key](auto &value) { return StrEqualsIgnoreCase(value, authorized_key); });
173}
174
180bool NetworkAuthorizedKeys::Contains(std::string_view key) const
181{
182 return FindKey(this, key) != this->end();
183}
184
190bool 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
206bool 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
216uint8_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 */
234void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, std::string_view name, std::string_view str, StringParameter &&data)
235{
236 std::string message;
237 StringBuilder builder(message);
238
239 /* All of these strings start with "***". These characters are interpreted as both left-to-right and
240 * right-to-left characters depending on the context. As the next text might be an user's name, the
241 * user name's characters will influence the direction of the "***" instead of the language setting
242 * of the game. Manually set the direction of the "***" by inserting a text-direction marker. */
243 builder.PutUtf8(_current_text_dir == TD_LTR ? CHAR_TD_LRM : CHAR_TD_RLM);
244
245 switch (action) {
246 case NETWORK_ACTION_SERVER_MESSAGE:
247 /* Ignore invalid messages */
248 builder += GetString(STR_NETWORK_SERVER_MESSAGE, str);
249 colour = CC_DEFAULT;
250 break;
251 case NETWORK_ACTION_COMPANY_SPECTATOR:
252 colour = CC_DEFAULT;
253 builder += GetString(STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE, name);
254 break;
255 case NETWORK_ACTION_COMPANY_JOIN:
256 colour = CC_DEFAULT;
257 builder += GetString(STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN, name, str);
258 break;
259 case NETWORK_ACTION_COMPANY_NEW:
260 colour = CC_DEFAULT;
261 builder += GetString(STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW, name, std::move(data));
262 break;
263 case NETWORK_ACTION_JOIN:
264 /* Show the Client ID for the server but not for the client. */
265 builder += _network_server ?
266 GetString(STR_NETWORK_MESSAGE_CLIENT_JOINED_ID, name, std::move(data)) :
267 GetString(STR_NETWORK_MESSAGE_CLIENT_JOINED, name);
268 break;
269 case NETWORK_ACTION_LEAVE: builder += GetString(STR_NETWORK_MESSAGE_CLIENT_LEFT, name, std::move(data)); break;
270 case NETWORK_ACTION_NAME_CHANGE: builder += GetString(STR_NETWORK_MESSAGE_NAME_CHANGE, name, str); break;
271 case NETWORK_ACTION_GIVE_MONEY: builder += GetString(STR_NETWORK_MESSAGE_GIVE_MONEY, name, std::move(data), str); break;
272 case NETWORK_ACTION_KICKED: builder += GetString(STR_NETWORK_MESSAGE_KICKED, name, str); break;
273 case NETWORK_ACTION_CHAT_COMPANY: builder += GetString(self_send ? STR_NETWORK_CHAT_TO_COMPANY : STR_NETWORK_CHAT_COMPANY, name, str); break;
274 case NETWORK_ACTION_CHAT_CLIENT: builder += GetString(self_send ? STR_NETWORK_CHAT_TO_CLIENT : STR_NETWORK_CHAT_CLIENT, name, str); break;
275 case NETWORK_ACTION_EXTERNAL_CHAT: builder += GetString(STR_NETWORK_CHAT_EXTERNAL, std::move(data), name, str); break;
276 default: builder += GetString(STR_NETWORK_CHAT_ALL, name, str); break;
277 }
278
279 Debug(desync, 1, "msg: {:08x}; {:02x}; {}", TimerGameEconomy::date, TimerGameEconomy::date_fract, message);
280 IConsolePrint(colour, message);
282}
283
284/* Calculate the frame-lag of a client */
285uint NetworkCalculateLag(const NetworkClientSocket *cs)
286{
287 int lag = cs->last_frame_server - cs->last_frame;
288 /* This client has missed their ACK packet after 1 DAY_TICKS..
289 * so we increase their lag for every frame that passes!
290 * The packet can be out by a max of _net_frame_freq */
291 if (cs->last_frame_server + Ticks::DAY_TICKS + _settings_client.network.frame_freq < _frame_counter) {
292 lag += _frame_counter - (cs->last_frame_server + Ticks::DAY_TICKS + _settings_client.network.frame_freq);
293 }
294 return lag;
295}
296
297
298/* There was a non-recoverable error, drop back to the main menu with a nice
299 * error */
300void ShowNetworkError(StringID error_string)
301{
304}
305
312{
313 /* List of possible network errors, used by
314 * PACKET_SERVER_ERROR and PACKET_CLIENT_ERROR */
315 static const StringID network_error_strings[] = {
316 STR_NETWORK_ERROR_CLIENT_GENERAL,
317 STR_NETWORK_ERROR_CLIENT_DESYNC,
318 STR_NETWORK_ERROR_CLIENT_SAVEGAME,
319 STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST,
320 STR_NETWORK_ERROR_CLIENT_PROTOCOL_ERROR,
321 STR_NETWORK_ERROR_CLIENT_NEWGRF_MISMATCH,
322 STR_NETWORK_ERROR_CLIENT_NOT_AUTHORIZED,
323 STR_NETWORK_ERROR_CLIENT_NOT_EXPECTED,
324 STR_NETWORK_ERROR_CLIENT_WRONG_REVISION,
325 STR_NETWORK_ERROR_CLIENT_NAME_IN_USE,
326 STR_NETWORK_ERROR_CLIENT_WRONG_PASSWORD,
327 STR_NETWORK_ERROR_CLIENT_COMPANY_MISMATCH,
328 STR_NETWORK_ERROR_CLIENT_KICKED,
329 STR_NETWORK_ERROR_CLIENT_CHEATER,
330 STR_NETWORK_ERROR_CLIENT_SERVER_FULL,
331 STR_NETWORK_ERROR_CLIENT_TOO_MANY_COMMANDS,
332 STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD,
333 STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER,
334 STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP,
335 STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN,
336 STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME,
337 STR_NETWORK_ERROR_CLIENT_NOT_ON_ALLOW_LIST,
338 STR_NETWORK_ERROR_CLIENT_NO_AUTHENTICATION_METHOD_AVAILABLE,
339 };
340 static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
341
342 if (err >= (ptrdiff_t)lengthof(network_error_strings)) err = NETWORK_ERROR_GENERAL;
343
344 return network_error_strings[err];
345}
346
352void NetworkHandlePauseChange(PauseModes prev_mode, PauseMode changed_mode)
353{
354 if (!_networking) return;
355
356 switch (changed_mode) {
358 case PauseMode::Join:
362 bool changed = _pause_mode.None() != prev_mode.None();
363 bool paused = _pause_mode.Any();
364 if (!paused && !changed) return;
365
366 std::string str;
367 if (!changed) {
368 std::array<StringParameter, 5> params{};
369 auto it = params.begin();
370 if (_pause_mode.Test(PauseMode::Normal)) *it++ = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL;
371 if (_pause_mode.Test(PauseMode::Join)) *it++ = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS;
372 if (_pause_mode.Test(PauseMode::GameScript)) *it++ = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT;
373 if (_pause_mode.Test(PauseMode::ActiveClients)) *it++ = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS;
374 if (_pause_mode.Test(PauseMode::LinkGraph)) *it++ = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH;
375 str = GetStringWithArgs(STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_1 + std::distance(params.begin(), it) - 1, {params.begin(), it});
376 } else {
377 StringID reason;
378 switch (changed_mode) {
379 case PauseMode::Normal: reason = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL; break;
380 case PauseMode::Join: reason = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS; break;
381 case PauseMode::GameScript: reason = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT; break;
382 case PauseMode::ActiveClients: reason = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS; break;
383 case PauseMode::LinkGraph: reason = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH; break;
384 default: NOT_REACHED();
385 }
386 str = GetString(paused ? STR_NETWORK_SERVER_MESSAGE_GAME_PAUSED : STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED, reason);
387 }
388
389 NetworkTextMessage(NETWORK_ACTION_SERVER_MESSAGE, CC_DEFAULT, false, "", str);
390 break;
391 }
392
393 default:
394 return;
395 }
396}
397
398
407static void CheckPauseHelper(bool pause, PauseMode pm)
408{
409 if (pause == _pause_mode.Test(pm)) return;
410
411 Command<CMD_PAUSE>::Post(pm, pause);
412}
413
420{
421 uint count = 0;
422
423 for (const NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
424 if (cs->status != NetworkClientSocket::STATUS_ACTIVE) continue;
425 if (!Company::IsValidID(cs->GetInfo()->client_playas)) continue;
426 count++;
427 }
428
429 return count;
430}
431
444
450{
451 for (const NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
452 if (cs->status >= NetworkClientSocket::STATUS_AUTHORIZED && cs->status < NetworkClientSocket::STATUS_ACTIVE) return true;
453 }
454
455 return false;
456}
457
469
476std::string_view ParseCompanyFromConnectionString(std::string_view connection_string, CompanyID *company_id)
477{
478 std::string_view ip = connection_string;
479 if (company_id == nullptr) return ip;
480
481 size_t offset = ip.find_last_of('#');
482 if (offset != std::string::npos) {
483 std::string_view company_string = ip.substr(offset + 1);
484 ip = ip.substr(0, offset);
485
486 uint8_t company_value;
487 auto [_, err] = std::from_chars(company_string.data(), company_string.data() + company_string.size(), company_value);
488 if (err == std::errc()) {
489 if (company_value != COMPANY_NEW_COMPANY && company_value != COMPANY_SPECTATOR) {
490 if (company_value > MAX_COMPANIES || company_value == 0) {
491 *company_id = COMPANY_SPECTATOR;
492 } else {
493 /* "#1" means the first company, which has index 0. */
494 *company_id = (CompanyID)(company_value - 1);
495 }
496 } else {
497 *company_id = (CompanyID)company_value;
498 }
499 }
500 }
501
502 return ip;
503}
504
520std::string_view ParseFullConnectionString(std::string_view connection_string, uint16_t &port, CompanyID *company_id)
521{
522 std::string_view ip = ParseCompanyFromConnectionString(connection_string, company_id);
523
524 size_t port_offset = ip.find_last_of(':');
525 size_t ipv6_close = ip.find_last_of(']');
526 if (port_offset != std::string::npos && (ipv6_close == std::string::npos || ipv6_close < port_offset)) {
527 std::string_view port_string = ip.substr(port_offset + 1);
528 ip = ip.substr(0, port_offset);
529 std::from_chars(port_string.data(), port_string.data() + port_string.size(), port);
530 }
531 return ip;
532}
533
540std::string NormalizeConnectionString(std::string_view connection_string, uint16_t default_port)
541{
542 uint16_t port = default_port;
543 std::string_view ip = ParseFullConnectionString(connection_string, port);
544 return fmt::format("{}:{}", ip, port);
545}
546
555NetworkAddress ParseConnectionString(std::string_view connection_string, uint16_t default_port)
556{
557 uint16_t port = default_port;
558 std::string_view ip = ParseFullConnectionString(connection_string, port);
559 return NetworkAddress(ip, port);
560}
561
567/* static */ void ServerNetworkGameSocketHandler::AcceptConnection(SOCKET s, const NetworkAddress &address)
568{
569 /* Register the login */
571
573 cs->client_address = address; // Save the IP of the client
574
576}
577
582static void InitializeNetworkPools(bool close_admins = true)
583{
585 if (close_admins) to_clean.Set(PoolType::NetworkAdmin);
586 PoolBase::Clean(to_clean);
587}
588
593void NetworkClose(bool close_admins)
594{
595 if (_network_server) {
596 if (close_admins) {
598 as->CloseConnection(true);
599 }
600 }
601
602 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
603 cs->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT);
604 }
607
609 } else {
610 if (MyClient::my_client != nullptr) {
613 }
614
616 }
617 NetworkGameSocketHandler::ProcessDeferredDeletions();
618
620
621 _networking = false;
622 _network_server = false;
623
625
626 InitializeNetworkPools(close_admins);
627}
628
629/* Initializes the network (cleans sockets and stuff) */
630static void NetworkInitialize(bool close_admins = true)
631{
632 InitializeNetworkPools(close_admins);
633
634 _sync_frame = 0;
635 _network_first_time = true;
636
638}
639
642private:
643 std::string connection_string;
644
645public:
646 TCPQueryConnecter(std::string_view connection_string) : TCPServerConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {}
647
648 void OnFailure() override
649 {
650 Debug(net, 9, "Query::OnFailure(): connection_string={}", this->connection_string);
651
652 NetworkGame *item = NetworkGameListAddItem(connection_string);
653 item->status = NGLS_OFFLINE;
654 item->refreshing = false;
655
657 }
658
659 void OnConnect(SOCKET s) override
660 {
661 Debug(net, 9, "Query::OnConnect(): connection_string={}", this->connection_string);
662
663 QueryNetworkGameSocketHandler::QueryServer(s, this->connection_string);
664 }
665};
666
671void NetworkQueryServer(std::string_view connection_string)
672{
673 if (!_network_available) return;
674
675 Debug(net, 9, "NetworkQueryServer(): connection_string={}", connection_string);
676
677 /* Mark the entry as refreshing, so the GUI can show the refresh is pending. */
678 NetworkGame *item = NetworkGameListAddItem(connection_string);
679 item->refreshing = true;
680
681 TCPConnecter::Create<TCPQueryConnecter>(connection_string);
682}
683
693NetworkGame *NetworkAddServer(std::string_view connection_string, bool manually, bool never_expire)
694{
695 if (connection_string.empty()) return nullptr;
696
697 /* Ensure the item already exists in the list */
698 NetworkGame *item = NetworkGameListAddItem(connection_string);
699 if (item->info.server_name.empty()) {
701 item->info.server_name = connection_string;
702
704
705 NetworkQueryServer(connection_string);
706 }
707
708 if (manually) item->manually = true;
709 if (never_expire) item->version = INT32_MAX;
710
711 return item;
712}
713
719void GetBindAddresses(NetworkAddressList *addresses, uint16_t port)
720{
721 for (const auto &iter : _network_bind_list) {
722 addresses->emplace_back(iter, port);
723 }
724
725 /* No address, so bind to everything. */
726 if (addresses->empty()) {
727 addresses->emplace_back("", port);
728 }
729}
730
731/* Generates the list of manually added hosts from NetworkGame and
732 * dumps them into the array _network_host_list. This array is needed
733 * by the function that generates the config file. */
734void NetworkRebuildHostList()
735{
736 _network_host_list.clear();
737
738 for (const auto &item : _network_game_list) {
739 if (item->manually) _network_host_list.emplace_back(item->connection_string);
740 }
741}
742
745private:
746 std::string connection_string;
747
748public:
749 TCPClientConnecter(std::string_view connection_string) : TCPServerConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {}
750
751 void OnFailure() override
752 {
753 Debug(net, 9, "Client::OnFailure(): connection_string={}", this->connection_string);
754
755 ShowNetworkError(STR_NETWORK_ERROR_NOCONNECTION);
756 }
757
758 void OnConnect(SOCKET s) override
759 {
760 Debug(net, 9, "Client::OnConnect(): connection_string={}", this->connection_string);
761
762 _networking = true;
764 new ClientNetworkGameSocketHandler(s, this->connection_string);
765 IConsoleCmdExec("exec scripts/on_client.scr 0");
767 }
768};
769
786bool NetworkClientConnectGame(std::string_view connection_string, CompanyID default_company, const std::string &join_server_password)
787{
788 Debug(net, 9, "NetworkClientConnectGame(): connection_string={}", connection_string);
789
790 CompanyID join_as = default_company;
791 std::string resolved_connection_string = ServerAddress::Parse(connection_string, NETWORK_DEFAULT_PORT, &join_as).connection_string;
792
793 if (!_network_available) return false;
794 if (!NetworkValidateOurClientName()) return false;
795
796 _network_join.connection_string = std::move(resolved_connection_string);
797 _network_join.company = join_as;
798 _network_join.server_password = join_server_password;
799
800 if (_game_mode == GM_MENU) {
801 /* From the menu we can immediately continue with the actual join. */
803 } else {
804 /* When already playing a game, first go back to the main menu. This
805 * disconnects the user from the current game, meaning we can safely
806 * load in the new. After all, there is little point in continuing to
807 * play on a server if we are connecting to another one.
808 */
810 }
811 return true;
812}
813
820{
822 NetworkInitialize();
823
825 Debug(net, 9, "status = CONNECTING");
826 _network_join_status = NETWORK_JOIN_STATUS_CONNECTING;
827 ShowJoinStatusWindow();
828
829 TCPConnecter::Create<TCPClientConnecter>(_network_join.connection_string);
830}
831
832static void NetworkInitGameInfo()
833{
834 FillStaticNetworkServerGameInfo();
835 /* The server is a client too */
836 _network_game_info.clients_on = _network_dedicated ? 0 : 1;
837
838 /* There should be always space for the server. */
842
844
847}
848
859bool NetworkValidateServerName(std::string &server_name)
860{
861 StrTrimInPlace(server_name);
862 if (!server_name.empty()) return true;
863
864 ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_BAD_SERVER_NAME), {}, WL_ERROR);
865 return false;
866}
867
875{
876 static const std::string fallback_client_name = "Unnamed Client";
878 if (_settings_client.network.client_name.empty() || _settings_client.network.client_name.compare(fallback_client_name) == 0) {
879 Debug(net, 1, "No \"client_name\" has been set, using \"{}\" instead. Please set this now using the \"name <new name>\" command", fallback_client_name);
880 _settings_client.network.client_name = fallback_client_name;
881 }
882
883 static const std::string fallback_server_name = "Unnamed Server";
885 if (_settings_client.network.server_name.empty() || _settings_client.network.server_name.compare(fallback_server_name) == 0) {
886 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);
887 _settings_client.network.server_name = fallback_server_name;
888 }
889}
890
891bool NetworkServerStart()
892{
893 if (!_network_available) return false;
894
895 /* Call the pre-scripts */
896 IConsoleCmdExec("exec scripts/pre_server.scr 0");
897 if (_network_dedicated) IConsoleCmdExec("exec scripts/pre_dedicated.scr 0");
898
899 /* Check for the client and server names to be set, but only after the scripts had a chance to set them.*/
901
902 NetworkDisconnect(false);
903 NetworkInitialize(false);
905 Debug(net, 5, "Starting listeners for clients");
907
908 /* Only listen for admins when the authentication is configured. */
909 if (_settings_client.network.AdminAuthenticationConfigured()) {
910 Debug(net, 5, "Starting listeners for admins");
912 }
913
914 /* Try to start UDP-server */
915 Debug(net, 5, "Starting listeners for incoming server queries");
917
918 _network_server = true;
919 _networking = true;
920 _frame_counter = 0;
925
927
928 NetworkInitGameInfo();
929
930 if (_settings_client.network.server_game_type != SERVER_GAME_TYPE_LOCAL) {
932 }
933
934 /* execute server initialization script */
935 IConsoleCmdExec("exec scripts/on_server.scr 0");
936 /* if the server is dedicated ... add some other script */
937 if (_network_dedicated) IConsoleCmdExec("exec scripts/on_dedicated.scr 0");
938
939 return true;
940}
941
947{
948 if (!_network_server) return;
949
950 /* Update the static game info to set the values from the new game. */
952
954
955 if (!_network_dedicated) {
958 if (c != nullptr && ci != nullptr) {
959 ci->client_playas = c->index;
960
961 /*
962 * If the company has not been named yet, the company was just started.
963 * Otherwise it would have gotten a name already, so announce it as a new company.
964 */
965 if (c->name_1 == STR_SV_UNNAMED && c->name.empty()) NetworkServerNewCompany(c, ci);
966 }
967
968 ShowClientList();
969 } else {
970 /* welcome possibly still connected admins - this can only happen on a dedicated server. */
972 }
973}
974
975/* The server is rebooting...
976 * The only difference with NetworkDisconnect, is the packets that is sent */
977void NetworkReboot()
978{
979 if (_network_server) {
980 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
981 cs->SendNewGame();
982 cs->SendPackets();
983 }
984
986 as->SendNewGame();
987 as->SendPackets();
988 }
989 }
990
991 /* For non-dedicated servers we have to kick the admins as we are not
992 * certain that we will end up in a new network game. */
994}
995
1000void NetworkDisconnect(bool close_admins)
1001{
1002 if (_network_server) {
1003 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1004 cs->SendShutdown();
1005 cs->SendPackets();
1006 }
1007
1008 if (close_admins) {
1010 as->SendShutdown();
1011 as->SendPackets();
1012 }
1013 }
1014 }
1015
1017
1018 NetworkClose(close_admins);
1019
1020 /* Reinitialize the UDP stack, i.e. close all existing connections. */
1022}
1023
1029{
1030 if (!_networking) return;
1031
1033 case SERVER_GAME_TYPE_LOCAL:
1035 break;
1036
1037 case SERVER_GAME_TYPE_INVITE_ONLY:
1038 case SERVER_GAME_TYPE_PUBLIC:
1040 break;
1041
1042 default:
1043 NOT_REACHED();
1044 }
1045}
1046
1051static bool NetworkReceive()
1052{
1053 bool result;
1054 if (_network_server) {
1057 } else {
1059 }
1060 NetworkGameSocketHandler::ProcessDeferredDeletions();
1061 return result;
1062}
1063
1064/* This sends all buffered commands (if possible) */
1065static void NetworkSend()
1066{
1067 if (_network_server) {
1070 } else {
1072 }
1073 NetworkGameSocketHandler::ProcessDeferredDeletions();
1074}
1075
1092
1093/* The main loop called from ttd.c
1094 * Here we also have to do StateGameLoop if needed! */
1095void NetworkGameLoop()
1096{
1097 if (!_networking) return;
1098
1099 if (!NetworkReceive()) return;
1100
1101 if (_network_server) {
1102 /* Log the sync state to check for in-syncedness of replays. */
1104 /* We don't want to log multiple times if paused. */
1105 static TimerGameEconomy::Date last_log;
1106 if (last_log != TimerGameEconomy::date) {
1107 Debug(desync, 1, "sync: {:08x}; {:02x}; {:08x}; {:08x}", TimerGameEconomy::date, TimerGameEconomy::date_fract, _random.state[0], _random.state[1]);
1108 last_log = TimerGameEconomy::date;
1109 }
1110 }
1111
1112#ifdef DEBUG_DUMP_COMMANDS
1113 /* Loading of the debug commands from -ddesync>=1 */
1114 static auto f = FioFOpenFile("commands.log", "rb", SAVE_DIR);
1115 static TimerGameEconomy::Date next_date(0);
1116 static uint32_t next_date_fract;
1117 static CommandPacket *cp = nullptr;
1118 static bool check_sync_state = false;
1119 static uint32_t sync_state[2];
1120 if (!f.has_value() && next_date == 0) {
1121 Debug(desync, 0, "Cannot open commands.log");
1122 next_date = TimerGameEconomy::Date(1);
1123 }
1124
1125 while (f.has_value() && !feof(*f)) {
1126 if (TimerGameEconomy::date == next_date && TimerGameEconomy::date_fract == next_date_fract) {
1127 if (cp != nullptr) {
1128 NetworkSendCommand(cp->cmd, cp->err_msg, nullptr, cp->company, cp->data);
1129 Debug(desync, 0, "Injecting: {:08x}; {:02x}; {:02x}; {:08x}; {} ({})", TimerGameEconomy::date, TimerGameEconomy::date_fract, _current_company.base(), cp->cmd, FormatArrayAsHex(cp->data), GetCommandName(cp->cmd));
1130 delete cp;
1131 cp = nullptr;
1132 }
1133 if (check_sync_state) {
1134 if (sync_state[0] == _random.state[0] && sync_state[1] == _random.state[1]) {
1135 Debug(desync, 0, "Sync check: {:08x}; {:02x}; match", TimerGameEconomy::date, TimerGameEconomy::date_fract);
1136 } else {
1137 Debug(desync, 0, "Sync check: {:08x}; {:02x}; mismatch expected {{{:08x}, {:08x}}}, got {{{:08x}, {:08x}}}",
1138 TimerGameEconomy::date, TimerGameEconomy::date_fract, sync_state[0], sync_state[1], _random.state[0], _random.state[1]);
1139 NOT_REACHED();
1140 }
1141 check_sync_state = false;
1142 }
1143 }
1144
1145 /* Skip all entries in the command-log till we caught up with the current game again. */
1146 if (TimerGameEconomy::date > next_date || (TimerGameEconomy::date == next_date && TimerGameEconomy::date_fract > next_date_fract)) {
1147 Debug(desync, 0, "Skipping to next command at {:08x}:{:02x}", next_date, next_date_fract);
1148 if (cp != nullptr) {
1149 delete cp;
1150 cp = nullptr;
1151 }
1152 check_sync_state = false;
1153 }
1154
1155 if (cp != nullptr || check_sync_state) break;
1156
1157 char buff[4096];
1158 if (fgets(buff, lengthof(buff), *f) == nullptr) break;
1159
1160 StringConsumer consumer{std::string_view{buff}};
1161 /* Ignore the "[date time] " part of the message */
1162 if (consumer.ReadCharIf('[')) {
1164 consumer.SkipCharIf(' ');
1165 }
1166
1167 if (consumer.ReadIf("cmd: ")
1168#ifdef DEBUG_FAILED_DUMP_COMMANDS
1169 || consumer.ReadIf("cmdf: ")
1170#endif
1171 ) {
1172 cp = new CommandPacket();
1173 next_date = TimerGameEconomy::Date(consumer.ReadIntegerBase<uint32_t>(16));
1174 bool valid = consumer.ReadIf("; ");
1175 next_date_fract = consumer.ReadIntegerBase<uint32_t>(16);
1176 valid &= consumer.ReadIf("; ");
1177 cp->company = static_cast<CompanyID>(consumer.ReadIntegerBase<uint16_t>(16));
1178 valid &= consumer.ReadIf("; ");
1179 cp->cmd = static_cast<Commands>(consumer.ReadIntegerBase<uint32_t>(16));
1180 valid &= consumer.ReadIf("; ");
1181 cp->err_msg = consumer.ReadIntegerBase<uint32_t>(16);
1182 valid &= consumer.ReadIf("; ");
1183 auto args = consumer.ReadUntilChar(' ', StringConsumer::SKIP_ONE_SEPARATOR);
1184 assert(valid);
1185
1186 /* Parse command data. */
1187 cp->data.clear();
1188 for (size_t i = 0; i + 1 < args.size(); i += 2) {
1189 uint8_t e = 0;
1190 std::from_chars(args.data() + i, args.data() + i + 2, e, 16);
1191 cp->data.push_back(e);
1192 }
1193 } else if (consumer.ReadIf("join: ")) {
1194 /* Manually insert a pause when joining; this way the client can join at the exact right time. */
1195 next_date = TimerGameEconomy::Date(consumer.ReadIntegerBase<uint32_t>(16));
1196 bool valid = consumer.ReadIf("; ");
1197 next_date_fract = consumer.ReadIntegerBase<uint32_t>(16);
1198 assert(valid);
1199 Debug(desync, 0, "Injecting pause for join at {:08x}:{:02x}; please join when paused", next_date, next_date_fract);
1200 cp = new CommandPacket();
1202 cp->cmd = CMD_PAUSE;
1204 _ddc_fastforward = false;
1205 } else if (consumer.ReadIf("sync: ")) {
1206 next_date = TimerGameEconomy::Date(consumer.ReadIntegerBase<uint32_t>(16));
1207 bool valid = consumer.ReadIf("; ");
1208 next_date_fract = consumer.ReadIntegerBase<uint32_t>(16);
1209 valid &= consumer.ReadIf("; ");
1210 sync_state[0] = consumer.ReadIntegerBase<uint32_t>(16);
1211 valid &= consumer.ReadIf("; ");
1212 sync_state[1] = consumer.ReadIntegerBase<uint32_t>(16);
1213 assert(valid);
1214 check_sync_state = true;
1215 } else if (consumer.ReadIf("msg: ") || consumer.ReadIf("client: ") ||
1216 consumer.ReadIf("load: ") || consumer.ReadIf("save: ") ||
1217 consumer.ReadIf("warning: ")) {
1218 /* A message that is not very important to the log playback, but part of the log. */
1219#ifndef DEBUG_FAILED_DUMP_COMMANDS
1220 } else if (consumer.ReadIf("cmdf: ")) {
1221 Debug(desync, 0, "Skipping replay of failed command: {}", consumer.Read(StringConsumer::npos));
1222#endif
1223 } else {
1224 /* Can't parse a line; what's wrong here? */
1225 Debug(desync, 0, "Trying to parse: {}", consumer.Read(StringConsumer::npos));
1226 NOT_REACHED();
1227 }
1228 }
1229 if (f.has_value() && feof(*f)) {
1230 Debug(desync, 0, "End of commands.log");
1231 f.reset();
1232 }
1233#endif /* DEBUG_DUMP_COMMANDS */
1235 /* Only check for active clients just before we're going to send out
1236 * the commands so we don't send multiple pause/unpause commands when
1237 * the frame_freq is more than 1 tick. Same with distributing commands. */
1241 }
1242
1243 bool send_frame = false;
1244
1245 /* We first increase the _frame_counter */
1247 /* Update max-frame-counter */
1250 send_frame = true;
1251 }
1252
1254
1255 /* Then we make the frame */
1256 StateGameLoop();
1257
1259#ifdef NETWORK_SEND_DOUBLE_SEED
1260 _sync_seed_2 = _random.state[1];
1261#endif
1262
1263 NetworkServer_Tick(send_frame);
1264 } else {
1265 /* Client */
1266
1267 /* Make sure we are at the frame were the server is (quick-frames) */
1269 /* Run a number of frames; when things go bad, get out. */
1272 }
1273 } else {
1274 /* Else, keep on going till _frame_counter_max */
1276 /* Run one frame; if things went bad, get out. */
1278 }
1279 }
1280 }
1281
1282 NetworkSend();
1283}
1284
1287{
1288 Debug(net, 3, "Starting network");
1289
1290 /* Network is available */
1292 _network_dedicated = false;
1293
1294 _network_game_info = {};
1295
1296 NetworkInitialize();
1298 Debug(net, 3, "Network online, multiplayer available");
1301}
1302
1305{
1309
1310 Debug(net, 3, "Shutting down network");
1311
1312 _network_available = false;
1313
1315}
1316
1317#ifdef __EMSCRIPTEN__
1318extern "C" {
1319
1320void CDECL em_openttd_add_server(const char *connection_string)
1321{
1322 NetworkAddServer(connection_string, false, true);
1323}
1324
1325}
1326#endif
std::vector< NetworkAddress > NetworkAddressList
Type for a list of addresses.
Definition address.h:20
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr bool None() const
Test if none of the values are set.
constexpr Timpl & Set()
Set all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
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.
Enum-as-bit-set wrapper.
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.
static void SendReceive()
Check if any query needs to send or receive.
static void QueryServer(SOCKET s, std::string_view connection_string)
Start to query a server based on an open socket.
std::string connection_string
The connection string for this ServerAddress.
Definition address.h:198
static ServerAddress Parse(std::string_view 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:444
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: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:567
NetworkAddress client_address
IP-address of the client (so they can be banned)
Compose data into a growing std::string.
Parse data from a string / buffer.
void SkipUntilChar(char c, SeparatorUsage sep)
Skip data until the first occurrence of 8-bit char 'c'.
@ SKIP_ONE_SEPARATOR
Read and discard one separator, do not include it in the result.
static constexpr size_type npos
Special value for "end of data".
Non blocking connection create to actually connect to servers.
Definition network.cpp:744
void OnConnect(SOCKET s) override
Callback when the connection succeeded.
Definition network.cpp:758
void OnFailure() override
Callback for when the connection attempt failed.
Definition network.cpp:751
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:641
void OnConnect(SOCKET s) override
Callback when the connection succeeded.
Definition network.cpp:659
void OnFailure() override
Callback for when the connection attempt failed.
Definition network.cpp:648
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.
std::string_view 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.
static constexpr CompanyID COMPANY_SPECTATOR
The client is spectating.
static constexpr CompanyID COMPANY_NEW_COMPANY
The client wants a new company.
static const uint16_t NETWORK_DEFAULT_PORT
The default port of the game server (TCP & UDP)
Definition config.h:25
void IConsoleCmdExec(std::string_view command_string, const uint recurse_count)
Execute a given command passed to us.
Definition console.cpp:269
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:90
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,...)
Output a line of debugging information.
Definition debug.h:37
@ 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
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
std::optional< FileHandle > FioFOpenFile(std::string_view filename, std::string_view 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:89
PauseModes _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:302
void NetworkFindBroadcastIPs(NetworkAddressList *broadcast)
Find the IPv4 broadcast addresses; IPv6 uses a completely different strategy for broadcasting.
Definition host.cpp:84
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:81
NetworkAddress ParseConnectionString(std::string_view connection_string, uint16_t default_port)
Convert a string containing either "hostname" or "hostname:ip" to a NetworkAddress.
Definition network.cpp:555
void NetworkStartUp()
This tries to launch the network for a given OS.
Definition network.cpp:1286
bool _is_network_server
Does this client wants to be a network-server?
Definition network.cpp:71
NetworkClientInfoPool _networkclientinfo_pool("NetworkClientInfo")
Make sure both pools have the same size.
void NetworkHandlePauseChange(PauseModes prev_mode, PauseMode changed_mode)
Handle the pause mode change so we send the right messages to the chat.
Definition network.cpp:352
static uint NetworkCountActiveClients()
Counts the number of active clients connected.
Definition network.cpp:419
StringList _network_host_list
The servers we know.
Definition network.cpp:76
StringID GetNetworkErrorMsg(NetworkErrorCode err)
Retrieve the string id of an internal error number.
Definition network.cpp:311
uint32_t _frame_counter_server
The frame_counter of the server, if in network-mode.
Definition network.cpp:78
static void CheckPauseOnJoin()
Check whether we should pause on join.
Definition network.cpp:461
NetworkAddressList _broadcast_list
List of broadcast addresses.
Definition network.cpp:82
void NetworkClientJoinGame()
Actually perform the joining to the server.
Definition network.cpp:819
static bool NetworkHasJoiningClient()
Checks whether there is a joining client.
Definition network.cpp:449
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:73
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:874
void NetworkOnGameStart()
Perform tasks when the server is started.
Definition network.cpp:946
uint32_t _frame_counter
The current frame.
Definition network.cpp:80
bool _network_available
is network mode available?
Definition network.cpp:69
uint8_t _network_reconnect
Reconnect timeout.
Definition network.cpp:74
bool _networking
are we in networking mode?
Definition network.cpp:67
void NetworkQueryServer(std::string_view connection_string)
Query a server to fetch the game-info.
Definition network.cpp:671
static void InitializeNetworkPools(bool close_admins=true)
Resets the pools used for network clients, and the admin pool if needed.
Definition network.cpp:582
StringList _network_ban_list
The banned clients.
Definition network.cpp:77
bool _network_dedicated
are we a dedicated server?
Definition network.cpp:70
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:1051
void NetworkDisconnect(bool close_admins)
We want to disconnect from the host/clients.
Definition network.cpp:1000
bool _network_server
network-server is active
Definition network.cpp:68
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:83
NetworkGame * NetworkAddServer(std::string_view connection_string, bool manually, bool never_expire)
Validates an address entered as a string and adds the server to the list.
Definition network.cpp:693
uint32_t _sync_frame
The frame to perform the sync check.
Definition network.cpp:87
void NetworkBackgroundLoop()
We have to do some (simple) background stuff that runs normally, even when we are not in multiplayer.
Definition network.cpp:1081
StringList _network_bind_list
The addresses to bind on.
Definition network.cpp:75
std::string NormalizeConnectionString(std::string_view connection_string, uint16_t default_port)
Normalize a connection string.
Definition network.cpp:540
bool NetworkClientConnectGame(std::string_view 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:786
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:435
ClientID _network_own_client_id
Our client identifier.
Definition network.cpp:72
std::string_view ParseCompanyFromConnectionString(std::string_view connection_string, CompanyID *company_id)
Parse the company part ("#company" postfix) of a connecting string.
Definition network.cpp:476
static void CheckPauseHelper(bool pause, PauseMode pm)
Helper function for the pause checkers.
Definition network.cpp:407
bool _network_first_time
Whether we have finished joining or not.
Definition network.cpp:88
void NetworkShutDown()
This shuts the network down.
Definition network.cpp:1304
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:719
std::string_view ParseFullConnectionString(std::string_view connection_string, uint16_t &port, CompanyID *company_id)
Converts a string to ip/port/company Format: IP:port::company.
Definition network.cpp:520
void NetworkUpdateServerGameType()
The setting server_game_type was updated; possibly we need to take some action.
Definition network.cpp:1028
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:593
uint32_t _frame_counter_max
To where we may go with our clients.
Definition network.cpp:79
bool NetworkValidateServerName(std::string &server_name)
Trim the given server name in place, i.e.
Definition network.cpp:859
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.
NetworkGame * NetworkGameListAddItem(std::string_view connection_string)
Add a new item to the linked gamelist.
std::vector< std::unique_ptr< NetworkGame > > _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)
NetworkErrorCode
The error codes we send around in the protocols.
NetworkAction
Actions that can be used for NetworkTextMessage.
ClientID
'Unique' identifier to be given to clients
@ CLIENT_ID_SERVER
Servers always have this ID.
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(GRFConfigList &config)
Clear a GRF Config list, freeing all nodes.
void StateGameLoop()
State controlling game loop.
Definition openttd.cpp:1211
PauseMode
Modes of pausing we've got.
Definition openttd.h:68
@ LinkGraph
A game paused due to the link graph schedule lagging.
@ Error
A game paused because a (critical) error.
@ GameScript
A game paused by a game script.
@ ActiveClients
A game paused for 'min_active_clients'.
@ Normal
A game normally paused.
@ Join
A game paused for 'pause_on_join'.
@ SM_JOIN_GAME
Join a network game.
Definition openttd.h:41
@ SM_MENU
Switch to game intro menu.
Definition openttd.h:33
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
@ NetworkClient
Network client pools.
@ NetworkAdmin
Network admin pool.
Randomizer _random
Random used in the game state calculations.
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:59
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
std::string FormatArrayAsHex(std::span< const uint8_t > data)
Format a byte array into a continuous hex string.
Definition string.cpp:75
bool StrEqualsIgnoreCase(std::string_view str1, std::string_view str2)
Compares two string( view)s for equality, while ignoring the case of the characters.
Definition string.cpp:321
void StrTrimInPlace(std::string &str)
Trim the spaces from given string in place, i.e.
Definition string.cpp:226
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 GetStringWithArgs(StringBuilder &builder, StringID string, StringParameters &args, uint case_index, bool game_script)
Get a parsed string with most special stringcodes replaced by the string parameters.
Definition strings.cpp:327
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:91
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:415
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:57
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
@ TD_LTR
Text is written left-to-right by default.
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: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)
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)
bool refreshing
Whether this server is being queried.
int version
Used to see which servers are no longer available on the Game Coordinator and can be removed.
NetworkGameInfo info
The game information of this server.
bool manually
True if the server was added manually.
NetworkGameStatus status
Stats of the 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.
GRFConfigList grfconfig
List of NewGRF files used.
std::string server_name
Server name.
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(PoolTypes)
Clean all pools of given type.
Definition pool_func.cpp:30
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Tindex index
Index of this pool item.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Titem * GetIfValid(auto index)
Returns Titem with given index.
Base class for all pools.
static constexpr size_t MAX_SIZE
Make template parameter accessible from outside.
uint32_t state[2]
The state of the randomizer.
The data required to format and validate a single parameter of a string.
Templated helper to make a type-safe 'typedef' representing a single POD value.
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:1176
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:3244
@ WN_NETWORK_STATUS_WINDOW_JOIN
Network join status.
Definition window_type.h:41
@ WC_SEND_NETWORK_MSG
Chatbox; Window numbers:
@ WC_CLIENT_LIST
Client list; Window numbers:
@ WC_NETWORK_STATUS_WINDOW
Network status window; Window numbers: