OpenTTD Source 20260218-master-g2123fca5ea
network_server.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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "../stdafx.h"
11#include "../strings_func.h"
13#include "network_admin.h"
14#include "network_server.h"
15#include "network_udp.h"
16#include "network_base.h"
17#include "../console_func.h"
18#include "../company_base.h"
19#include "../command_func.h"
22#include "../station_base.h"
23#include "../genworld.h"
24#include "../company_func.h"
25#include "../company_gui.h"
26#include "../company_cmd.h"
27#include "../roadveh.h"
28#include "../order_backup.h"
29#include "../core/pool_func.hpp"
31#include "../company_cmd.h"
32#include "../rev.h"
33#include "../timer/timer.h"
37#include <mutex>
38#include <condition_variable>
39
40#include "table/strings.h"
41
42#include "../safeguards.h"
43
44
45/* This file handles all the server-commands */
46
50
52static_assert(NetworkClientSocketPool::MAX_SIZE > MAX_CLIENTS);
53
56INSTANTIATE_POOL_METHODS(NetworkClientSocket)
57
60
64
65
69 std::unique_ptr<Packet> current;
70 size_t total_size;
71 std::deque<std::unique_ptr<Packet>> packets;
72 std::mutex mutex;
73 std::condition_variable exit_sig;
74
82
84 ~PacketWriter() override
85 {
86 std::unique_lock<std::mutex> lock(this->mutex);
87
88 while (this->cs != nullptr) this->exit_sig.wait(lock);
89
90 /* This must all wait until the Destroy function is called. */
91
92 this->packets.clear();
93 this->current = nullptr;
94 }
95
106 void Destroy()
107 {
108 std::unique_lock<std::mutex> lock(this->mutex);
109
110 this->cs = nullptr;
111
112 this->exit_sig.notify_all();
113 lock.unlock();
114
115 /* Make sure the saving is completely cancelled. Yes,
116 * we need to handle the save finish as well as the
117 * next connection might just be requesting a map. */
118 WaitTillSaved();
119 }
120
127 {
128 /* Unsafe check for the queue being empty or not. */
129 if (this->packets.empty()) return false;
130
131 std::lock_guard<std::mutex> lock(this->mutex);
132
133 while (!this->packets.empty()) {
134 bool last_packet = this->packets.front()->GetPacketType() == PACKET_SERVER_MAP_DONE;
135 this->cs->SendPacket(std::move(this->packets.front()));
136 this->packets.pop_front();
137
138 if (last_packet) return true;
139 }
140
141 return false;
142 }
143
144 void Write(uint8_t *buf, size_t size) override
145 {
146 std::lock_guard<std::mutex> lock(this->mutex);
147
148 /* We want to abort the saving when the socket is closed. */
149 if (this->cs == nullptr) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
150
151 if (this->current == nullptr) this->current = std::make_unique<Packet>(this->cs, PACKET_SERVER_MAP_DATA, TCP_MTU);
152
153 std::span<const uint8_t> to_write(buf, size);
154 while (!to_write.empty()) {
155 to_write = this->current->Send_bytes(to_write);
156
157 if (!this->current->CanWriteToPacket(1)) {
158 this->packets.push_back(std::move(this->current));
159 if (!to_write.empty()) this->current = std::make_unique<Packet>(this->cs, PACKET_SERVER_MAP_DATA, TCP_MTU);
160 }
161 }
162
163 this->total_size += size;
164 }
165
166 void Finish() override
167 {
168 std::lock_guard<std::mutex> lock(this->mutex);
169
170 /* We want to abort the saving when the socket is closed. */
171 if (this->cs == nullptr) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
172
173 /* Make sure the last packet is flushed. */
174 if (this->current != nullptr) this->packets.push_back(std::move(this->current));
175
176 /* Add a packet stating that this is the end to the queue. */
177 this->packets.push_back(std::make_unique<Packet>(this->cs, PACKET_SERVER_MAP_DONE));
178
179 /* Fast-track the size to the client. */
180 auto p = std::make_unique<Packet>(this->cs, PACKET_SERVER_MAP_SIZE);
181 p->Send_uint32((uint32_t)this->total_size);
182 this->packets.push_front(std::move(p));
183 }
184};
185
186
193 NetworkClientSocketPool::PoolItem<&_networkclientsocket_pool>(index), NetworkGameSocketHandler(s)
194{
196 this->receive_limit = _settings_client.network.bytes_per_frame_burst;
197
198 Debug(net, 9, "client[{}] status = INACTIVE", this->client_id);
199
200 /* The Socket and Info pools need to be the same in size. After all,
201 * each Socket will be associated with at most one Info object. As
202 * such if the Socket was allocated the Info object can as well. */
204}
205
210{
211 delete this->GetInfo();
212
215
216 if (this->savegame != nullptr) {
217 this->savegame->Destroy();
218 this->savegame = nullptr;
219 }
220
222}
223
225{
226 /* Only allow receiving when we have some buffer free; this value
227 * can go negative, but eventually it will become positive again. */
228 if (this->receive_limit <= 0) return nullptr;
229
230 /* We can receive a packet, so try that and if needed account for
231 * the amount of received data. */
232 std::unique_ptr<Packet> p = this->NetworkTCPSocketHandler::ReceivePacket();
233 if (p != nullptr) this->receive_limit -= p->Size();
234 return p;
235}
236
238{
240 /*
241 * Sending a message just before leaving the game calls cs->SendPackets.
242 * This might invoke this function, which means that when we close the
243 * connection after cs->SendPackets we will close an already closed
244 * connection. This handles that case gracefully without having to make
245 * that code any more complex or more aware of the validity of the socket.
246 */
247 if (this->IsPendingDeletion() || this->sock == INVALID_SOCKET) return status;
248
250 /* We did not receive a leave message from this client... */
251 std::string client_name = this->GetClientName();
252
253 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST);
254
255 /* Inform other clients of this... strange leaving ;) */
257 if (new_cs->status >= STATUS_AUTHORIZED && this != new_cs) {
258 new_cs->SendErrorQuit(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
259 }
260 }
261 }
262
263 /* If we were transferring a map to this client, stop the savegame creation
264 * process and queue the next client to receive the map. */
265 if (this->status == STATUS_MAP) {
266 /* Ensure the saving of the game is stopped too. */
267 this->savegame->Destroy();
268 this->savegame = nullptr;
269
270 this->CheckNextClientToSendMap(this);
271 }
272
273 NetworkAdminClientError(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
274 Debug(net, 3, "[{}] Client #{} closed connection", ServerNetworkGameSocketHandler::GetName(), this->client_id);
275
276 /* We just lost one client :( */
277 if (this->status >= STATUS_AUTHORIZED) _network_game_info.clients_on--;
278 extern uint8_t _network_clients_connected;
280
281 this->SendPackets(true);
282
283 this->DeferDeletion();
284
285 return status;
286}
287
293{
294 extern uint8_t _network_clients_connected;
296
297 /* We can't go over the MAX_CLIENTS limit here. However, the
298 * pool must have place for all clients and ourself. */
301 return accept;
302}
303
306{
308 if (cs->writable) {
309 if (cs->SendPackets() != SPS_CLOSED && cs->status == STATUS_MAP) {
310 /* This client is in the middle of a map-send, call the function for that */
311 cs->SendMap();
312 }
313 }
314 }
315}
316
317static void NetworkHandleCommandQueue(NetworkClientSocket *cs);
318
319/***********
320 * Sending functions
321 ************/
322
329{
330 Debug(net, 9, "client[{}] SendClientInfo(): client_id={}", this->client_id, ci->client_id);
331
332 if (ci->client_id != INVALID_CLIENT_ID) {
333 auto p = std::make_unique<Packet>(this, PACKET_SERVER_CLIENT_INFO);
334 p->Send_uint32(ci->client_id);
335 p->Send_uint8 (ci->client_playas);
336 p->Send_string(ci->client_name);
337 p->Send_string(ci->public_key);
338
339 this->SendPacket(std::move(p));
340 }
342}
343
349{
350 Debug(net, 9, "client[{}] SendGameInfo()", this->client_id);
351
352 auto p = std::make_unique<Packet>(this, PACKET_SERVER_GAME_INFO, TCP_MTU);
354
355 this->SendPacket(std::move(p));
356
358}
359
367{
368 Debug(net, 9, "client[{}] SendError(): error={}", this->client_id, error);
369
370 auto p = std::make_unique<Packet>(this, PACKET_SERVER_ERROR);
371
372 p->Send_uint8(error);
373 if (!reason.empty()) p->Send_string(reason);
374 this->SendPacket(std::move(p));
375
376 StringID strid = GetNetworkErrorMsg(error);
377
378 /* Only send when the current client was in game */
379 if (this->status >= STATUS_AUTHORIZED) {
380 std::string client_name = this->GetClientName();
381
382 Debug(net, 1, "'{}' made an error and has been disconnected: {}", client_name, GetString(strid));
383
384 if (error == NETWORK_ERROR_KICKED && !reason.empty()) {
385 NetworkTextMessage(NETWORK_ACTION_KICKED, CC_DEFAULT, false, client_name, reason, strid);
386 } else {
387 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", strid);
388 }
389
391 if (new_cs->status >= STATUS_AUTHORIZED && new_cs != this) {
392 /* Some errors we filter to a more general error. Clients don't have to know the real
393 * reason a joining failed. */
394 if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION) {
395 error = NETWORK_ERROR_ILLEGAL_PACKET;
396 }
397 new_cs->SendErrorQuit(this->client_id, error);
398 }
399 }
400
402 } else {
403 Debug(net, 1, "Client {} made an error and has been disconnected: {}", this->client_id, GetString(strid));
404 }
405
406 /* The client made a mistake, so drop the connection now! */
408}
409
415{
416 Debug(net, 9, "client[{}] SendNewGRFCheck()", this->client_id);
417
418 /* Invalid packet when status is anything but STATUS_IDENTIFY. */
420
421 Debug(net, 9, "client[{}] status = NEWGRFS_CHECK", this->client_id);
423
424 if (_grfconfig.empty()) {
425 /* There are no NewGRFs, so they're welcome. */
426 return this->SendWelcome();
427 }
428
429 auto p = std::make_unique<Packet>(this, PACKET_SERVER_CHECK_NEWGRFS, TCP_MTU);
430
431 uint grf_count = std::ranges::count_if(_grfconfig, [](const auto &c){ return !c->flags.Test(GRFConfigFlag::Static); });
432 p->Send_uint8 (grf_count);
433
434 for (const auto &c : _grfconfig) {
435 if (!c->flags.Test(GRFConfigFlag::Static)) SerializeGRFIdentifier(*p, c->ident);
436 }
437
438 this->SendPacket(std::move(p));
440}
441
447{
448 Debug(net, 9, "client[{}] SendAuthRequest()", this->client_id);
449
450 /* Invalid packet when status is anything but STATUS_INACTIVE or STATUS_AUTH_GAME. */
452
453 Debug(net, 9, "client[{}] status = AUTH_GAME", this->client_id);
454 this->status = STATUS_AUTH_GAME;
455
456 /* Reset 'lag' counters */
458
459 if (this->authentication_handler == nullptr) {
461 }
462
463 auto p = std::make_unique<Packet>(this, PACKET_SERVER_AUTH_REQUEST);
464 this->authentication_handler->SendRequest(*p);
465
466 this->SendPacket(std::move(p));
468}
469
475{
476 Debug(net, 9, "client[{}] SendEnableEncryption()", this->client_id);
477
478 /* Invalid packet when status is anything but STATUS_AUTH_GAME. */
480
481 auto p = std::make_unique<Packet>(this, PACKET_SERVER_ENABLE_ENCRYPTION);
482 this->authentication_handler->SendEnableEncryption(*p);
483 this->SendPacket(std::move(p));
485}
486
492{
493 Debug(net, 9, "client[{}] SendWelcome()", this->client_id);
494
495 /* Invalid packet when status is anything but STATUS_NEWGRFS_CHECK. */
497
498 Debug(net, 9, "client[{}] status = AUTHORIZED", this->client_id);
500
501 /* Reset 'lag' counters */
503
504 _network_game_info.clients_on++;
505
506 auto p = std::make_unique<Packet>(this, PACKET_SERVER_WELCOME);
507 p->Send_uint32(this->client_id);
508 this->SendPacket(std::move(p));
509
510 /* Transmit info about all the active clients */
512 if (new_cs != this && new_cs->status >= STATUS_AUTHORIZED) {
513 this->SendClientInfo(new_cs->GetInfo());
514 }
515 }
516 /* Also send the info of the server */
518}
519
525{
526 Debug(net, 9, "client[{}] SendWait()", this->client_id);
527
528 int waiting = 1; // current player getting the map counts as 1
529
530 /* Count how many clients are waiting in the queue, in front of you! */
532 if (new_cs->status != STATUS_MAP_WAIT) continue;
533 if (new_cs->GetInfo()->join_date < this->GetInfo()->join_date || (new_cs->GetInfo()->join_date == this->GetInfo()->join_date && new_cs->client_id < this->client_id)) waiting++;
534 }
535
536 auto p = std::make_unique<Packet>(this, PACKET_SERVER_WAIT);
537 p->Send_uint8(waiting);
538 this->SendPacket(std::move(p));
540}
541
542void ServerNetworkGameSocketHandler::CheckNextClientToSendMap(NetworkClientSocket *ignore_cs)
543{
544 Debug(net, 9, "client[{}] CheckNextClientToSendMap()", this->client_id);
545
546 /* Find the best candidate for joining, i.e. the first joiner. */
547 NetworkClientSocket *best = nullptr;
548 for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
549 if (ignore_cs == new_cs) continue;
550
551 if (new_cs->status == STATUS_MAP_WAIT) {
552 if (best == nullptr || best->GetInfo()->join_date > new_cs->GetInfo()->join_date || (best->GetInfo()->join_date == new_cs->GetInfo()->join_date && best->client_id > new_cs->client_id)) {
553 best = new_cs;
554 }
555 }
556 }
557
558 /* Is there someone else to join? */
559 if (best != nullptr) {
560 /* Let the first start joining. */
561 best->status = STATUS_AUTHORIZED;
562 best->SendMap();
563
564 /* And update the rest. */
566 if (new_cs->status == STATUS_MAP_WAIT) new_cs->SendWait();
567 }
568 }
569}
570
576{
577 if (this->status < STATUS_AUTHORIZED) {
578 /* Illegal call, return error and ignore the packet */
579 return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
580 }
581
582 if (this->status == STATUS_AUTHORIZED) {
583 Debug(net, 9, "client[{}] SendMap(): first_packet", this->client_id);
584
585 WaitTillSaved();
586 this->savegame = std::make_shared<PacketWriter>(this);
587
588 /* Now send the _frame_counter and how many packets are coming */
589 auto p = std::make_unique<Packet>(this, PACKET_SERVER_MAP_BEGIN);
590 p->Send_uint32(_frame_counter);
591 this->SendPacket(std::move(p));
592
594 Debug(net, 9, "client[{}] status = MAP", this->client_id);
595 this->status = STATUS_MAP;
596 /* Mark the start of download */
599
600 /* Make a dump of the current game */
601 if (SaveWithFilter(this->savegame, true) != SL_OK) UserError("network savedump failed");
602 }
603
604 if (this->status == STATUS_MAP) {
605 bool last_packet = this->savegame->TransferToNetworkQueue();
606 if (last_packet) {
607 Debug(net, 9, "client[{}] SendMap(): last_packet", this->client_id);
608
609 /* Done reading, make sure saving is done as well */
610 this->savegame->Destroy();
611 this->savegame = nullptr;
612
613 /* Set the status to DONE_MAP, no we will wait for the client
614 * to send it is ready (maybe that happens like never ;)) */
615 Debug(net, 9, "client[{}] status = DONE_MAP", this->client_id);
616 this->status = STATUS_DONE_MAP;
617
618 this->CheckNextClientToSendMap();
619 }
620 }
622}
623
630{
631 Debug(net, 9, "client[{}] SendJoin(): client_id={}", this->client_id, client_id);
632
633 auto p = std::make_unique<Packet>(this, PACKET_SERVER_JOIN);
634
635 p->Send_uint32(client_id);
636
637 this->SendPacket(std::move(p));
639}
640
646{
647 auto p = std::make_unique<Packet>(this, PACKET_SERVER_FRAME);
648 p->Send_uint32(_frame_counter);
649 p->Send_uint32(_frame_counter_max);
650#ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
651 p->Send_uint32(_sync_seed_1);
652#ifdef NETWORK_SEND_DOUBLE_SEED
653 p->Send_uint32(_sync_seed_2);
654#endif
655#endif
656
657 /* If token equals 0, we need to make a new token and send that. */
658 if (this->last_token == 0) {
659 this->last_token = InteractiveRandomRange(UINT8_MAX - 1) + 1;
660 p->Send_uint8(this->last_token);
661 }
662
663 this->SendPacket(std::move(p));
665}
666
672{
673 Debug(net, 9, "client[{}] SendSync(), frame_counter={}, sync_seed_1={}", this->client_id, _frame_counter, _sync_seed_1);
674
675 auto p = std::make_unique<Packet>(this, PACKET_SERVER_SYNC);
676 p->Send_uint32(_frame_counter);
677 p->Send_uint32(_sync_seed_1);
678
679#ifdef NETWORK_SEND_DOUBLE_SEED
680 p->Send_uint32(_sync_seed_2);
681#endif
682 this->SendPacket(std::move(p));
684}
685
692{
693 Debug(net, 9, "client[{}] SendCommand(): cmd={}", this->client_id, cp.cmd);
694
695 auto p = std::make_unique<Packet>(this, PACKET_SERVER_COMMAND);
696
698 p->Send_uint32(cp.frame);
699 p->Send_bool (cp.my_cmd);
700
701 this->SendPacket(std::move(p));
703}
704
714NetworkRecvStatus ServerNetworkGameSocketHandler::SendChat(NetworkAction action, ClientID client_id, bool self_send, std::string_view msg, int64_t data)
715{
716 Debug(net, 9, "client[{}] SendChat(): action={}, client_id={}, self_send={}", this->client_id, action, client_id, self_send);
717
719
720 auto p = std::make_unique<Packet>(this, PACKET_SERVER_CHAT);
721
722 p->Send_uint8 (action);
723 p->Send_uint32(client_id);
724 p->Send_bool (self_send);
725 p->Send_string(msg);
726 p->Send_uint64(data);
727
728 this->SendPacket(std::move(p));
730}
731
740NetworkRecvStatus ServerNetworkGameSocketHandler::SendExternalChat(std::string_view source, TextColour colour, std::string_view user, std::string_view msg)
741{
742 Debug(net, 9, "client[{}] SendExternalChat(): source={}", this->client_id, source);
743
745
746 auto p = std::make_unique<Packet>(this, PACKET_SERVER_EXTERNAL_CHAT);
747
748 p->Send_string(source);
749 p->Send_uint16(colour);
750 p->Send_string(user);
751 p->Send_string(msg);
752
753 this->SendPacket(std::move(p));
755}
756
764{
765 Debug(net, 9, "client[{}] SendErrorQuit(): client_id={}, errorno={}", this->client_id, client_id, errorno);
766
767 auto p = std::make_unique<Packet>(this, PACKET_SERVER_ERROR_QUIT);
768
769 p->Send_uint32(client_id);
770 p->Send_uint8 (errorno);
771
772 this->SendPacket(std::move(p));
774}
775
782{
783 Debug(net, 9, "client[{}] SendQuit(): client_id={}", this->client_id, client_id);
784
785 auto p = std::make_unique<Packet>(this, PACKET_SERVER_QUIT);
786
787 p->Send_uint32(client_id);
788
789 this->SendPacket(std::move(p));
791}
792
798{
799 Debug(net, 9, "client[{}] SendShutdown()", this->client_id);
800
801 auto p = std::make_unique<Packet>(this, PACKET_SERVER_SHUTDOWN);
802 this->SendPacket(std::move(p));
804}
805
811{
812 Debug(net, 9, "client[{}] SendNewGame()", this->client_id);
813
814 auto p = std::make_unique<Packet>(this, PACKET_SERVER_NEWGAME);
815 this->SendPacket(std::move(p));
817}
818
826{
827 Debug(net, 9, "client[{}] SendRConResult()", this->client_id);
828
829 auto p = std::make_unique<Packet>(this, PACKET_SERVER_RCON);
830
831 p->Send_uint16(colour);
832 p->Send_string(command);
833 this->SendPacket(std::move(p));
835}
836
844{
845 Debug(net, 9, "client[{}] SendMove(): client_id={}", this->client_id, client_id);
846
847 auto p = std::make_unique<Packet>(this, PACKET_SERVER_MOVE);
848
849 p->Send_uint32(client_id);
850 p->Send_uint8(company_id);
851 this->SendPacket(std::move(p));
853}
854
860{
861 Debug(net, 9, "client[{}] SendConfigUpdate()", this->client_id);
862
863 auto p = std::make_unique<Packet>(this, PACKET_SERVER_CONFIG_UPDATE);
864
865 p->Send_uint8(_settings_client.network.max_companies);
866 p->Send_string(_settings_client.network.server_name);
867 this->SendPacket(std::move(p));
869}
870
871/***********
872 * Receiving functions
873 ************/
874
876{
877 Debug(net, 9, "client[{}] Receive_CLIENT_GAME_INFO()", this->client_id);
878
879 return this->SendGameInfo();
880}
881
883{
884 if (this->status != STATUS_NEWGRFS_CHECK) {
885 /* Illegal call, return error and ignore the packet */
886 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
887 }
888
889 Debug(net, 9, "client[{}] Receive_CLIENT_NEWGRFS_CHECKED()", this->client_id);
890
891 return this->SendWelcome();
892}
893
895{
896 if (this->status != STATUS_INACTIVE) {
897 /* Illegal call, return error and ignore the packet */
898 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
899 }
900
901 if (_network_game_info.clients_on >= _settings_client.network.max_clients) {
902 /* Turns out we are full. Inform the user about this. */
903 return this->SendError(NETWORK_ERROR_FULL);
904 }
905
906 std::string client_revision = p.Recv_string(NETWORK_REVISION_LENGTH);
907 uint32_t newgrf_version = p.Recv_uint32();
908
909 Debug(net, 9, "client[{}] Receive_CLIENT_JOIN(): client_revision={}, newgrf_version={}", this->client_id, client_revision, newgrf_version);
910
911 /* Check if the client has revision control enabled */
912 if (!IsNetworkCompatibleVersion(client_revision) || _openttd_newgrf_version != newgrf_version) {
913 /* Different revisions!! */
914 return this->SendError(NETWORK_ERROR_WRONG_REVISION);
915 }
916
917 return this->SendAuthRequest();
918}
919
921{
922 if (this->status != STATUS_IDENTIFY) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
923
924 Debug(net, 9, "client[{}] Receive_CLIENT_IDENTIFY()", this->client_id);
925
926 std::string client_name = p.Recv_string(NETWORK_CLIENT_NAME_LENGTH);
927 CompanyID playas = (Owner)p.Recv_uint8();
928
930
931 /* join another company does not affect these values */
932 switch (playas.base()) {
933 case COMPANY_NEW_COMPANY.base(): // New company
934 if (Company::GetNumItems() >= _settings_client.network.max_companies) {
935 return this->SendError(NETWORK_ERROR_FULL);
936 }
937 break;
938 case COMPANY_SPECTATOR.base(): // Spectator
939 break;
940 default: // Join another company (companies 1..MAX_COMPANIES (index 0..(MAX_COMPANIES-1)))
941 if (!Company::IsValidHumanID(playas)) {
942 return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
943 }
944
945 const Company *c = Company::Get(playas);
946 if (!c->allow_any && !c->allow_list.Contains(this->peer_public_key)) {
947 /* When we're not authorized, just bump us to a spectator. */
948 playas = COMPANY_SPECTATOR;
949 }
950 break;
951 }
952
953 if (!NetworkIsValidClientName(client_name)) {
954 /* An invalid client name was given. However, the client ensures the name
955 * is valid before it is sent over the network, so something went horribly
956 * wrong. This is probably someone trying to troll us. */
957 return this->SendError(NETWORK_ERROR_INVALID_CLIENT_NAME);
958 }
959
960 if (!NetworkMakeClientNameUnique(client_name)) { // Change name if duplicate
961 /* We could not create a name for this client */
962 return this->SendError(NETWORK_ERROR_NAME_IN_USE);
963 }
964
967 this->SetInfo(ci);
969 ci->client_name = std::move(client_name);
970 ci->client_playas = playas;
971 ci->public_key = this->peer_public_key;
972 Debug(desync, 1, "client: {:08x}; {:02x}; {:02x}; {:02x}", TimerGameEconomy::date, TimerGameEconomy::date_fract, ci->client_playas, ci->index);
973
974 /* Make sure companies to which people try to join are not autocleaned */
975 Company *c = Company::GetIfValid(playas);
976 if (c != nullptr) c->months_empty = 0;
977
978 return this->SendNewGRFCheck();
979}
980
981static NetworkErrorCode GetErrorForAuthenticationMethod(NetworkAuthenticationMethod method)
982{
983 switch (method) {
985 return NETWORK_ERROR_WRONG_PASSWORD;
987 return NETWORK_ERROR_NOT_ON_ALLOW_LIST;
988
989 default:
990 NOT_REACHED();
991 }
992}
993
995{
996 if (this->status != STATUS_AUTH_GAME) {
997 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
998 }
999
1000 Debug(net, 9, "client[{}] Receive_CLIENT_AUTH_RESPONSE()", this->client_id);
1001
1002 auto authentication_method = this->authentication_handler->GetAuthenticationMethod();
1003 switch (this->authentication_handler->ReceiveResponse(p)) {
1005 break;
1006
1008 return this->SendAuthRequest();
1009
1011 default:
1012 return this->SendError(GetErrorForAuthenticationMethod(authentication_method));
1013 }
1014
1016 if (status != NETWORK_RECV_STATUS_OKAY) return status;
1017
1018 this->peer_public_key = this->authentication_handler->GetPeerPublicKey();
1019 this->receive_encryption_handler = this->authentication_handler->CreateClientToServerEncryptionHandler();
1020 this->send_encryption_handler = this->authentication_handler->CreateServerToClientEncryptionHandler();
1021 this->authentication_handler = nullptr;
1022
1023 Debug(net, 9, "client[{}] status = IDENTIFY", this->client_id);
1024 this->status = STATUS_IDENTIFY;
1025
1026 /* Reset 'lag' counters */
1028
1030}
1031
1033{
1034 /* The client was never joined.. so this is impossible, right?
1035 * Ignore the packet, give the client a warning, and close the connection */
1037 return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1038 }
1039
1040 Debug(net, 9, "client[{}] Receive_CLIENT_GETMAP()", this->client_id);
1041
1042 /* Check if someone else is receiving the map */
1044 if (new_cs->status == STATUS_MAP) {
1045 /* Tell the new client to wait */
1046 Debug(net, 9, "client[{}] status = MAP_WAIT", this->client_id);
1047 this->status = STATUS_MAP_WAIT;
1048 return this->SendWait();
1049 }
1050 }
1051
1052 /* We receive a request to upload the map.. give it to the client! */
1053 return this->SendMap();
1054}
1055
1057{
1058 /* Client has the map, now start syncing */
1059 if (this->status == STATUS_DONE_MAP && !this->HasClientQuit()) {
1060 Debug(net, 9, "client[{}] Receive_CLIENT_MAP_OK()", this->client_id);
1061
1062 std::string client_name = this->GetClientName();
1063
1064 NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, "", this->client_id);
1066
1067 Debug(net, 3, "[{}] Client #{} ({}) joined as {}", ServerNetworkGameSocketHandler::GetName(), this->client_id, this->GetClientIP(), client_name);
1068
1069 /* Mark the client as pre-active, and wait for an ACK
1070 * so we know it is done loading and in sync with us */
1071 Debug(net, 9, "client[{}] status = PRE_ACTIVE", this->client_id);
1072 this->status = STATUS_PRE_ACTIVE;
1074 this->SendFrame();
1075 this->SendSync();
1076
1077 /* This is the frame the client receives
1078 * we need it later on to make sure the client is not too slow */
1079 this->last_frame = _frame_counter;
1081
1083 if (new_cs->status >= STATUS_AUTHORIZED) {
1084 new_cs->SendClientInfo(this->GetInfo());
1085 new_cs->SendJoin(this->client_id);
1086 }
1087 }
1088
1089 NetworkAdminClientInfo(this, true);
1090
1091 /* also update the new client with our max values */
1092 return this->SendConfigUpdate();
1093 }
1094
1095 /* Wrong status for this packet, give a warning to client, and close connection */
1096 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1097}
1098
1100{
1101 /* The client was never joined.. so this is impossible, right?
1102 * Ignore the packet, give the client a warning, and close the connection */
1104 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1105 }
1106
1107 if (this->incoming_queue.size() >= _settings_client.network.max_commands_in_queue) {
1108 return this->SendError(NETWORK_ERROR_TOO_MANY_COMMANDS);
1109 }
1110
1111 Debug(net, 9, "client[{}] Receive_CLIENT_COMMAND()", this->client_id);
1112
1113 CommandPacket cp;
1114 auto err = this->ReceiveCommand(p, cp);
1115
1117
1118 NetworkClientInfo *ci = this->GetInfo();
1119
1120 if (err.has_value()) {
1121 IConsolePrint(CC_WARNING, "Dropping client #{} (IP: {}) due to {}.", ci->client_id, this->GetClientIP(), *err);
1122 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1123 }
1124
1126 IConsolePrint(CC_WARNING, "Kicking client #{} (IP: {}) due to calling a server only command {}.", ci->client_id, this->GetClientIP(), cp.cmd);
1127 return this->SendError(NETWORK_ERROR_KICKED);
1128 }
1129
1131 IConsolePrint(CC_WARNING, "Kicking client #{} (IP: {}) due to calling a non-spectator command {}.", ci->client_id, this->GetClientIP(), cp.cmd);
1132 return this->SendError(NETWORK_ERROR_KICKED);
1133 }
1134
1142 IConsolePrint(CC_WARNING, "Kicking client #{} (IP: {}) due to calling a command as another company {}.",
1143 ci->client_playas + 1, this->GetClientIP(), cp.company + 1);
1144 return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
1145 }
1146
1147 if (cp.cmd == Commands::CompanyControl) {
1148 if (cca != CompanyCtrlAction::New || cp.company != COMPANY_SPECTATOR) {
1149 return this->SendError(NETWORK_ERROR_CHEATER);
1150 }
1151
1152 /* Check if we are full - else it's possible for spectators to send a Commands::CompanyControl and the company is created regardless of max_companies! */
1153 if (Company::GetNumItems() >= _settings_client.network.max_companies) {
1154 NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_CLIENT, ci->client_id, "cannot create new company, server full", CLIENT_ID_SERVER);
1156 }
1157 }
1158
1160 /* Maybe the client just got moved before allowing? */
1162
1163 /* Only allow clients to add/remove currently joined clients. The server owner does not go via this method, so is allowed to do more. */
1164 std::string public_key = std::get<1>(EndianBufferReader::ToValue<CommandTraits<Commands::CompanyAllowListControl>::Args>(cp.data));
1165 if (!public_key.empty()) {
1166 bool found = false;
1168 if (info->public_key == public_key) {
1169 found = true;
1170 break;
1171 }
1172 }
1173
1174 /* Maybe the client just left? */
1175 if (!found) return NETWORK_RECV_STATUS_OKAY;
1176 }
1177 }
1178
1179 if (GetCommandFlags(cp.cmd).Test(CommandFlag::ClientID)) NetworkReplaceCommandClientId(cp, this->client_id);
1180
1181 this->incoming_queue.push_back(std::move(cp));
1183}
1184
1186{
1187 /* This packets means a client noticed an error and is reporting this
1188 * to us. Display the error and report it to the other clients */
1190
1191 Debug(net, 9, "client[{}] Receive_CLIENT_ERROR(): errorno={}", this->client_id, errorno);
1192
1193 /* The client was never joined.. thank the client for the packet, but ignore it */
1196 }
1197
1198 std::string client_name = this->GetClientName();
1199 StringID strid = GetNetworkErrorMsg(errorno);
1200
1201 Debug(net, 1, "'{}' reported an error and is closing its connection: {}", client_name, GetString(strid));
1202
1203 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", strid);
1204
1206 if (new_cs->status >= STATUS_AUTHORIZED) {
1207 new_cs->SendErrorQuit(this->client_id, errorno);
1208 }
1209 }
1210
1211 NetworkAdminClientError(this->client_id, errorno);
1212
1214}
1215
1217{
1218 /* The client was never joined.. thank the client for the packet, but ignore it */
1221 }
1222
1223 Debug(net, 9, "client[{}] Receive_CLIENT_QUIT()", this->client_id);
1224
1225 /* The client wants to leave. Display this and report it to the other clients. */
1226 std::string client_name = this->GetClientName();
1227 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", STR_NETWORK_MESSAGE_CLIENT_LEAVING);
1228
1230 if (new_cs->status >= STATUS_AUTHORIZED && new_cs != this) {
1231 new_cs->SendQuit(this->client_id);
1232 }
1233 }
1234
1236
1238}
1239
1241{
1242 if (this->status < STATUS_AUTHORIZED) {
1243 /* Illegal call, return error and ignore the packet */
1244 return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1245 }
1246
1247 uint32_t frame = p.Recv_uint32();
1248
1249 Debug(net, 9, "client[{}] Receive_CLIENT_ACK(): frame={}", this->client_id, frame);
1250
1251 /* The client is trying to catch up with the server */
1252 if (this->status == STATUS_PRE_ACTIVE) {
1253 /* The client is not yet caught up? */
1255
1256 /* Now it is! Unpause the game */
1257 Debug(net, 9, "client[{}] status = ACTIVE", this->client_id);
1258 this->status = STATUS_ACTIVE;
1260
1261 /* Execute script for, e.g. MOTD */
1262 IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
1263 }
1264
1265 /* Get, and validate the token. */
1266 uint8_t token = p.Recv_uint8();
1267 if (token == this->last_token) {
1268 /* We differentiate between last_token_frame and last_frame so the lag
1269 * test uses the actual lag of the client instead of the lag for getting
1270 * the token back and forth; after all, the token is only sent every
1271 * time we receive a PACKET_CLIENT_ACK, after which we will send a new
1272 * token to the client. If the lag would be one day, then we would not
1273 * be sending the new token soon enough for the new daily scheduled
1274 * PACKET_CLIENT_ACK. This would then register the lag of the client as
1275 * two days, even when it's only a single day. */
1277 /* Request a new token. */
1278 this->last_token = 0;
1279 }
1280
1281 /* The client received the frame, make note of it */
1282 this->last_frame = frame;
1283 /* With those 2 values we can calculate the lag realtime */
1286}
1287
1288
1299void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, std::string_view msg, ClientID from_id, int64_t data, bool from_admin)
1300{
1301 const NetworkClientInfo *ci, *ci_own, *ci_to;
1302
1303 switch (desttype) {
1304 case DESTTYPE_CLIENT:
1305 /* Are we sending to the server? */
1306 if ((ClientID)dest == CLIENT_ID_SERVER) {
1308 /* Display the text locally, and that is it */
1309 if (ci != nullptr) {
1310 NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1311
1312 if (_settings_client.network.server_admin_chat) {
1313 NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1314 }
1315 }
1316 } else {
1317 /* Else find the client to send the message to */
1318 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1319 if (cs->client_id == (ClientID)dest && cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
1320 cs->SendChat(action, from_id, false, msg, data);
1321 break;
1322 }
1323 }
1324 }
1325
1326 /* Display the message locally (so you know you have sent it) */
1327 if (from_id != (ClientID)dest) {
1328 if (from_id == CLIENT_ID_SERVER) {
1331 if (ci != nullptr && ci_to != nullptr) {
1332 NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), true, ci_to->client_name, msg, data);
1333 }
1334 } else {
1335 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1336 if (cs->client_id == from_id && cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
1337 cs->SendChat(action, (ClientID)dest, true, msg, data);
1338 break;
1339 }
1340 }
1341 }
1342 }
1343 break;
1344 case DESTTYPE_TEAM: {
1345 /* If this is false, the message is already displayed on the client who sent it. */
1346 bool show_local = true;
1347 /* Find all clients that belong to this company */
1348 ci_to = nullptr;
1349 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1350 ci = cs->GetInfo();
1351 if (ci != nullptr && ci->client_playas == (CompanyID)dest && cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
1352 cs->SendChat(action, from_id, false, msg, data);
1353 if (cs->client_id == from_id) show_local = false;
1354 ci_to = ci; // Remember a client that is in the company for company-name
1355 }
1356 }
1357
1358 /* if the server can read it, let the admin network read it, too. */
1359 if (_local_company == (CompanyID)dest && _settings_client.network.server_admin_chat) {
1360 NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1361 }
1362
1365 if (ci != nullptr && ci_own != nullptr && ci_own->client_playas == dest) {
1366 NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1367 if (from_id == CLIENT_ID_SERVER) show_local = false;
1368 ci_to = ci_own;
1369 }
1370
1371 /* There is no such client */
1372 if (ci_to == nullptr) break;
1373
1374 /* Display the message locally (so you know you have sent it) */
1375 if (ci != nullptr && show_local) {
1376 if (from_id == CLIENT_ID_SERVER) {
1377 StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
1378 std::string name = GetString(str, ci_to->client_playas);
1379 NetworkTextMessage(action, GetDrawStringCompanyColour(ci_own->client_playas), true, name, msg, data);
1380 } else {
1381 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1382 if (cs->client_id == from_id && cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
1383 cs->SendChat(action, ci_to->client_id, true, msg, data);
1384 }
1385 }
1386 }
1387 }
1388 break;
1389 }
1390 default:
1391 Debug(net, 1, "Received unknown chat destination type {}; doing broadcast instead", desttype);
1392 [[fallthrough]];
1393
1394 case DESTTYPE_BROADCAST:
1395 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1396 if (cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) cs->SendChat(action, from_id, false, msg, data);
1397 }
1398
1399 NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1400
1402 if (ci != nullptr) {
1403 NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1404 }
1405 break;
1406 }
1407}
1408
1416void NetworkServerSendExternalChat(std::string_view source, TextColour colour, std::string_view user, std::string_view msg)
1417{
1418 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1419 if (cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) cs->SendExternalChat(source, colour, user, msg);
1420 }
1421 NetworkTextMessage(NETWORK_ACTION_EXTERNAL_CHAT, colour, false, user, msg, source);
1422}
1423
1425{
1426 if (this->status < STATUS_PRE_ACTIVE) {
1427 /* Illegal call, return error and ignore the packet */
1428 return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1429 }
1430
1432 DestType desttype = (DestType)p.Recv_uint8();
1433 int dest = p.Recv_uint32();
1434
1435 Debug(net, 9, "client[{}] Receive_CLIENT_CHAT(): action={}, desttype={}, dest={}", this->client_id, action, desttype, dest);
1436
1437 std::string msg = p.Recv_string(NETWORK_CHAT_LENGTH);
1438 int64_t data = p.Recv_uint64();
1439
1440 NetworkClientInfo *ci = this->GetInfo();
1441 switch (action) {
1442 case NETWORK_ACTION_CHAT:
1443 case NETWORK_ACTION_CHAT_CLIENT:
1444 case NETWORK_ACTION_CHAT_COMPANY:
1445 NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data);
1446 break;
1447 default:
1448 IConsolePrint(CC_WARNING, "Kicking client #{} (IP: {}) due to unknown chact action.", ci->client_id, this->GetClientIP());
1449 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1450 }
1452}
1453
1455{
1456 if (this->status != STATUS_ACTIVE) {
1457 /* Illegal call, return error and ignore the packet */
1458 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1459 }
1460
1461 Debug(net, 9, "client[{}] Receive_CLIENT_SET_NAME()", this->client_id);
1462
1464
1465 std::string client_name = p.Recv_string(NETWORK_CLIENT_NAME_LENGTH);
1466 ci = this->GetInfo();
1467
1469
1470 if (ci != nullptr) {
1471 if (!NetworkIsValidClientName(client_name)) {
1472 /* An invalid client name was given. However, the client ensures the name
1473 * is valid before it is sent over the network, so something went horribly
1474 * wrong. This is probably someone trying to troll us. */
1475 return this->SendError(NETWORK_ERROR_INVALID_CLIENT_NAME);
1476 }
1477
1478 /* Display change */
1479 if (NetworkMakeClientNameUnique(client_name)) {
1480 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name);
1481 ci->client_name = std::move(client_name);
1483 }
1484 }
1486}
1487
1489{
1490 if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1491
1492 Debug(net, 9, "client[{}] Receive_CLIENT_RCON()", this->client_id);
1493
1494 std::string password = p.Recv_string(NETWORK_PASSWORD_LENGTH);
1495 std::string command = p.Recv_string(NETWORK_RCONCOMMAND_LENGTH);
1496
1497 if (_rcon_authorized_key_handler.IsAllowed(this->peer_public_key)) {
1498 /* We are allowed, nothing more to validate. */
1499 } else if (_settings_client.network.rcon_password.empty()) {
1501 } else if (_settings_client.network.rcon_password != password) {
1502 Debug(net, 1, "[rcon] Wrong password from client-id {}", this->client_id);
1504 }
1505
1506 Debug(net, 3, "[rcon] Client-id {} executed: {}", this->client_id, command);
1507
1509 IConsoleCmdExec(command);
1512}
1513
1515{
1516 if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1517
1518 CompanyID company_id = (Owner)p.Recv_uint8();
1519
1520 Debug(net, 9, "client[{}] Receive_CLIENT_MOVE(): company_id={}", this->client_id, company_id);
1521
1522 /* Check if the company is valid, we don't allow moving to AI companies */
1523 if (company_id != COMPANY_SPECTATOR) {
1524 if (!Company::IsValidHumanID(company_id)) return NETWORK_RECV_STATUS_OKAY;
1525
1526 const Company *c = Company::Get(company_id);
1527 if (!c->allow_any && !c->allow_list.Contains(this->peer_public_key)) {
1528 Debug(net, 2, "Wrong public key from client-id #{} for company #{}", this->client_id, company_id + 1);
1530 }
1531 }
1532
1533 /* if we get here we can move the client */
1534 NetworkServerDoMove(this->client_id, company_id);
1536}
1537
1542NetworkCompanyStatsArray NetworkGetCompanyStats()
1543{
1544 NetworkCompanyStatsArray stats = {};
1545
1546 /* Go through all vehicles and count the type of vehicles */
1547 for (const Vehicle *v : Vehicle::Iterate()) {
1548 if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
1549 uint8_t type = 0;
1550 switch (v->type) {
1551 case VEH_TRAIN: type = NETWORK_VEH_TRAIN; break;
1552 case VEH_ROAD: type = RoadVehicle::From(v)->IsBus() ? NETWORK_VEH_BUS : NETWORK_VEH_LORRY; break;
1553 case VEH_AIRCRAFT: type = NETWORK_VEH_PLANE; break;
1554 case VEH_SHIP: type = NETWORK_VEH_SHIP; break;
1555 default: continue;
1556 }
1557 stats[v->owner].num_vehicle[type]++;
1558 }
1559
1560 /* Go through all stations and count the types of stations */
1561 for (const Station *s : Station::Iterate()) {
1562 if (Company::IsValidID(s->owner)) {
1563 NetworkCompanyStats *npi = &stats[s->owner];
1564
1565 if (s->facilities.Test(StationFacility::Train)) npi->num_station[NETWORK_VEH_TRAIN]++;
1566 if (s->facilities.Test(StationFacility::TruckStop)) npi->num_station[NETWORK_VEH_LORRY]++;
1567 if (s->facilities.Test(StationFacility::BusStop)) npi->num_station[NETWORK_VEH_BUS]++;
1568 if (s->facilities.Test(StationFacility::Airport)) npi->num_station[NETWORK_VEH_PLANE]++;
1569 if (s->facilities.Test(StationFacility::Dock)) npi->num_station[NETWORK_VEH_SHIP]++;
1570 }
1571 }
1572
1573 return stats;
1574}
1575
1581{
1583
1584 if (ci == nullptr) return;
1585
1586 Debug(desync, 1, "client: {:08x}; {:02x}; {:02x}; {:04x}", TimerGameEconomy::date, TimerGameEconomy::date_fract, ci->client_playas, client_id);
1587
1588 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1590 cs->SendClientInfo(ci);
1591 }
1592 }
1593
1595}
1596
1603{
1604 CompanyMask has_clients{};
1605 CompanyMask has_vehicles{};
1606
1607 if (!_settings_client.network.autoclean_companies) return;
1608
1609 /* Detect the active companies */
1610 for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
1611 if (Company::IsValidID(ci->client_playas)) has_clients.Set(ci->client_playas);
1612 }
1613
1614 if (!_network_dedicated) {
1616 assert(ci != nullptr);
1617 if (Company::IsValidID(ci->client_playas)) has_clients.Set(ci->client_playas);
1618 }
1619
1620 if (_settings_client.network.autoclean_novehicles != 0) {
1621 for (const Company *c : Company::Iterate()) {
1622 if (std::any_of(std::begin(c->group_all), std::end(c->group_all), [](const GroupStatistics &gs) { return gs.num_vehicle != 0; })) has_vehicles.Set(c->index);
1623 }
1624 }
1625
1626 /* Go through all the companies */
1627 for (Company *c : Company::Iterate()) {
1628 /* Skip the non-active once */
1629 if (c->is_ai) continue;
1630
1631 if (!has_clients.Test(c->index)) {
1632 /* The company is empty for one month more */
1633 if (c->months_empty != std::numeric_limits<decltype(c->months_empty)>::max()) c->months_empty++;
1634
1635 /* Is the company empty for autoclean_protected-months? */
1636 if (_settings_client.network.autoclean_protected != 0 && c->months_empty > _settings_client.network.autoclean_protected) {
1637 /* Shut the company down */
1638 Command<Commands::CompanyControl>::Post(CompanyCtrlAction::Delete, c->index, CompanyRemoveReason::Autoclean, INVALID_CLIENT_ID);
1639 IConsolePrint(CC_INFO, "Auto-cleaned company #{}.", c->index + 1);
1640 }
1641 /* Is the company empty for autoclean_novehicles-months, and has no vehicles? */
1642 if (_settings_client.network.autoclean_novehicles != 0 && c->months_empty > _settings_client.network.autoclean_novehicles && !has_vehicles.Test(c->index)) {
1643 /* Shut the company down */
1644 Command<Commands::CompanyControl>::Post(CompanyCtrlAction::Delete, c->index, CompanyRemoveReason::Autoclean, INVALID_CLIENT_ID);
1645 IConsolePrint(CC_INFO, "Auto-cleaned company #{} with no vehicles.", c->index + 1);
1646 }
1647 } else {
1648 /* It is not empty, reset the date */
1649 c->months_empty = 0;
1650 }
1651 }
1652}
1653
1659bool NetworkMakeClientNameUnique(std::string &name)
1660{
1661 bool is_name_unique = false;
1662 std::string original_name = name;
1663
1664 for (uint number = 1; !is_name_unique && number <= MAX_CLIENTS; number++) { // Something's really wrong when there're more names than clients
1665 is_name_unique = true;
1666 for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
1667 if (ci->client_name == name) {
1668 /* Name already in use */
1669 is_name_unique = false;
1670 break;
1671 }
1672 }
1673 /* Check if it is the same as the server-name */
1675 if (ci != nullptr) {
1676 if (ci->client_name == name) is_name_unique = false; // name already in use
1677 }
1678
1679 if (!is_name_unique) {
1680 /* Try a new name (<name> #1, <name> #2, and so on) */
1681 name = fmt::format("{} #{}", original_name, number);
1682
1683 /* The constructed client name is larger than the limit,
1684 * so... bail out as no valid name can be created. */
1685 if (name.size() >= NETWORK_CLIENT_NAME_LENGTH) return false;
1686 }
1687 }
1688
1689 return is_name_unique;
1690}
1691
1698bool NetworkServerChangeClientName(ClientID client_id, const std::string &new_name)
1699{
1700 /* Check if the name's already in use */
1702 if (ci->client_name == new_name) return false;
1703 }
1704
1706 if (ci == nullptr) return false;
1707
1708 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, true, ci->client_name, new_name);
1709
1710 ci->client_name = new_name;
1711
1712 NetworkUpdateClientInfo(client_id);
1713 return true;
1714}
1715
1720static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
1721{
1722 for (auto &cp : cs->outgoing_queue) cs->SendCommand(cp);
1723 cs->outgoing_queue.clear();
1724}
1725
1730void NetworkServer_Tick(bool send_frame)
1731{
1732#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1733 bool send_sync = false;
1734#endif
1735
1736#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1737 if (_frame_counter >= _last_sync_frame + _settings_client.network.sync_freq) {
1739 send_sync = true;
1740 }
1741#endif
1742
1743 /* Now we are done with the frame, inform the clients that they can
1744 * do their frame! */
1745 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1746 /* We allow a number of bytes per frame, but only to the burst amount
1747 * to be available for packet receiving at any particular time. */
1748 cs->receive_limit = std::min<size_t>(cs->receive_limit + _settings_client.network.bytes_per_frame,
1749 _settings_client.network.bytes_per_frame_burst);
1750
1751 /* Check if the speed of the client is what we can expect from a client */
1752 uint lag = NetworkCalculateLag(cs);
1753 switch (cs->status) {
1754 case NetworkClientSocket::STATUS_ACTIVE:
1755 if (lag > _settings_client.network.max_lag_time) {
1756 /* Client did still not report in within the specified limit. */
1757
1758 if (cs->last_packet + std::chrono::milliseconds(lag * MILLISECONDS_PER_TICK) > std::chrono::steady_clock::now()) {
1759 /* A packet was received in the last three game days, so the client is likely lagging behind. */
1760 IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because the client's game state is more than {} ticks behind.", cs->client_id, cs->GetClientIP(), lag);
1761 } else {
1762 /* No packet was received in the last three game days; sounds like a lost connection. */
1763 IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because the client did not respond for more than {} ticks.", cs->client_id, cs->GetClientIP(), lag);
1764 }
1765 cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1766 continue;
1767 }
1768
1769 /* Report once per time we detect the lag, and only when we
1770 * received a packet in the last 2 seconds. If we
1771 * did not receive a packet, then the client is not just
1772 * slow, but the connection is likely severed. Mentioning
1773 * frame_freq is not useful in this case. */
1774 if (lag > (uint)Ticks::DAY_TICKS && cs->lag_test == 0 && cs->last_packet + std::chrono::seconds(2) > std::chrono::steady_clock::now()) {
1775 IConsolePrint(CC_WARNING, "[{}] Client #{} is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id);
1776 cs->lag_test = 1;
1777 }
1778
1779 if (cs->last_frame_server - cs->last_token_frame >= _settings_client.network.max_lag_time) {
1780 /* This is a bad client! It didn't send the right token back within time. */
1781 IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because it fails to send valid acks.", cs->client_id, cs->GetClientIP());
1782 cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1783 continue;
1784 }
1785 break;
1786
1787 case NetworkClientSocket::STATUS_INACTIVE:
1788 case NetworkClientSocket::STATUS_IDENTIFY:
1789 case NetworkClientSocket::STATUS_NEWGRFS_CHECK:
1790 case NetworkClientSocket::STATUS_AUTHORIZED:
1791 /* NewGRF check and authorized states should be handled almost instantly.
1792 * So give them some lee-way, likewise for the query with inactive. */
1793 if (lag > _settings_client.network.max_init_time) {
1794 IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because it took longer than {} ticks to start the joining process.", cs->client_id, cs->GetClientIP(), _settings_client.network.max_init_time);
1795 cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1796 continue;
1797 }
1798 break;
1799
1800 case NetworkClientSocket::STATUS_MAP_WAIT:
1801 /* Send every two seconds a packet to the client, to make sure
1802 * it knows the server is still there; just someone else is
1803 * still receiving the map. */
1804 if (std::chrono::steady_clock::now() > cs->last_packet + std::chrono::seconds(2)) {
1805 cs->SendWait();
1806 /* We need to reset the timer, as otherwise we will be
1807 * spamming the client. Strictly speaking this variable
1808 * tracks when we last received a packet from the client,
1809 * but as it is waiting, it will not send us any till we
1810 * start sending them data. */
1811 cs->last_packet = std::chrono::steady_clock::now();
1812 }
1813 break;
1814
1815 case NetworkClientSocket::STATUS_MAP:
1816 /* Downloading the map... this is the amount of time since starting the saving. */
1817 if (lag > _settings_client.network.max_download_time) {
1818 IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because it took longer than {} ticks to download the map.", cs->client_id, cs->GetClientIP(), _settings_client.network.max_download_time);
1819 cs->SendError(NETWORK_ERROR_TIMEOUT_MAP);
1820 continue;
1821 }
1822 break;
1823
1824 case NetworkClientSocket::STATUS_DONE_MAP:
1825 case NetworkClientSocket::STATUS_PRE_ACTIVE:
1826 /* The map has been sent, so this is for loading the map and syncing up. */
1827 if (lag > _settings_client.network.max_join_time) {
1828 IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because it took longer than {} ticks to join.", cs->client_id, cs->GetClientIP(), _settings_client.network.max_join_time);
1829 cs->SendError(NETWORK_ERROR_TIMEOUT_JOIN);
1830 continue;
1831 }
1832 break;
1833
1834 case NetworkClientSocket::STATUS_AUTH_GAME:
1835 /* These don't block? */
1836 if (lag > _settings_client.network.max_password_time) {
1837 IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because it took longer than {} ticks to enter the password.", cs->client_id, cs->GetClientIP(), _settings_client.network.max_password_time);
1838 cs->SendError(NETWORK_ERROR_TIMEOUT_PASSWORD);
1839 continue;
1840 }
1841 break;
1842
1843 case NetworkClientSocket::STATUS_END:
1844 /* Bad server/code. */
1845 NOT_REACHED();
1846 }
1847
1848 if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) {
1849 /* Check if we can send command, and if we have anything in the queue */
1851
1852 /* Send an updated _frame_counter_max to the client */
1853 if (send_frame) cs->SendFrame();
1854
1855#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1856 /* Send a sync-check packet */
1857 if (send_sync) cs->SendSync();
1858#endif
1859 }
1860 }
1861}
1862
1865{
1866 _settings_newgame.game_creation.generation_seed = GENERATE_NEW_SEED;
1867 switch (_file_to_saveload.ftype.abstract) {
1868 case FT_SAVEGAME:
1869 case FT_SCENARIO:
1871 break;
1872
1873 case FT_HEIGHTMAP:
1875 break;
1876
1877 default:
1879 }
1880}
1881
1884{
1885 if (!_network_server) return;
1886
1887 /* If setting is 0, this feature is disabled. */
1888 if (_settings_client.network.restart_hours == 0) return;
1889
1890 Debug(net, 3, "Auto-restarting map: {} hours played", _settings_client.network.restart_hours);
1892});
1893
1899{
1900 if (!_network_server) return;
1901
1902 _network_restart_map_timer.SetInterval({ std::chrono::hours(_settings_client.network.restart_hours), TimerGameRealtime::Trigger::Unpaused }, reset);
1903}
1904
1907{
1908 /* If setting is 0, this feature is disabled. */
1909 if (_settings_client.network.restart_game_year == 0) return;
1910
1911 if (TimerGameCalendar::year >= _settings_client.network.restart_game_year) {
1912 Debug(net, 3, "Auto-restarting map: year {} reached", TimerGameCalendar::year);
1914 }
1915}
1916
1918static const IntervalTimer<TimerGameCalendar> _calendar_network_yearly({ TimerGameCalendar::Trigger::Year, TimerGameCalendar::Priority::None }, [](auto) {
1919 if (!_network_server) return;
1920
1922});
1923
1925static const IntervalTimer<TimerGameEconomy> _economy_network_yearly({TimerGameEconomy::Trigger::Year, TimerGameEconomy::Priority::None}, [](auto)
1926{
1927 if (!_network_server) return;
1928
1930});
1931
1933static const IntervalTimer<TimerGameEconomy> _network_quarterly({TimerGameEconomy::Trigger::Quarter, TimerGameEconomy::Priority::None}, [](auto)
1934{
1935 if (!_network_server) return;
1936
1939});
1940
1942static const IntervalTimer<TimerGameEconomy> _network_monthly({TimerGameEconomy::Trigger::Month, TimerGameEconomy::Priority::None}, [](auto)
1943{
1944 if (!_network_server) return;
1945
1948});
1949
1951static const IntervalTimer<TimerGameEconomy> _network_weekly({TimerGameEconomy::Trigger::Week, TimerGameEconomy::Priority::None}, [](auto)
1952{
1953 if (!_network_server) return;
1954
1956});
1957
1959static const IntervalTimer<TimerGameEconomy> _economy_network_daily({TimerGameEconomy::Trigger::Day, TimerGameEconomy::Priority::None}, [](auto)
1960{
1961 if (!_network_server) return;
1962
1964});
1965
1971{
1972 return this->client_address.GetHostname();
1973}
1974
1977{
1978 static const std::string_view stat_str[] = {
1979 "inactive",
1980 "authorizing",
1981 "identifying client",
1982 "checking NewGRFs",
1983 "authorized",
1984 "waiting",
1985 "loading map",
1986 "map done",
1987 "ready",
1988 "active"
1989 };
1990 static_assert(lengthof(stat_str) == NetworkClientSocket::STATUS_END);
1991
1992 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1993 NetworkClientInfo *ci = cs->GetInfo();
1994 if (ci == nullptr) continue;
1995 uint lag = NetworkCalculateLag(cs);
1996
1997 std::string_view status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
1998 IConsolePrint(CC_INFO, "Client #{} name: '{}' status: '{}' frame-lag: {} company: {} IP: {}",
1999 cs->client_id, ci->client_name, status, lag,
2000 ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
2001 cs->GetClientIP());
2002 }
2003}
2004
2009{
2010 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
2011 if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendConfigUpdate();
2012 }
2013}
2014
2020
2026void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
2027{
2028 /* Only allow non-dedicated servers and normal clients to be moved */
2029 if (client_id == CLIENT_ID_SERVER && _network_dedicated) return;
2030
2032 assert(ci != nullptr);
2033
2034 /* No need to waste network resources if the client is in the company already! */
2035 if (ci->client_playas == company_id) return;
2036
2037 ci->client_playas = company_id;
2038
2039 if (client_id == CLIENT_ID_SERVER) {
2040 SetLocalCompany(company_id);
2041 } else {
2042 NetworkClientSocket *cs = NetworkClientSocket::GetByClientID(client_id);
2043 /* When the company isn't authorized we can't move them yet. */
2044 if (cs->status < NetworkClientSocket::STATUS_AUTHORIZED) return;
2045 cs->SendMove(client_id, company_id);
2046 }
2047
2048 /* Announce the client's move. */
2049 NetworkUpdateClientInfo(client_id);
2050
2051 if (company_id == COMPANY_SPECTATOR) {
2052 /* The client has joined spectators. */
2053 NetworkServerSendChat(NETWORK_ACTION_COMPANY_SPECTATOR, DESTTYPE_BROADCAST, 0, "", client_id);
2054 } else {
2055 /* The client has joined another company. */
2056 std::string company_name = GetString(STR_COMPANY_NAME, company_id);
2057 NetworkServerSendChat(NETWORK_ACTION_COMPANY_JOIN, DESTTYPE_BROADCAST, 0, company_name, client_id);
2058 }
2059
2061}
2062
2069void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, std::string_view string)
2070{
2071 NetworkClientSocket::GetByClientID(client_id)->SendRConResult(colour_code, string);
2072}
2073
2079void NetworkServerKickClient(ClientID client_id, std::string_view reason)
2080{
2081 if (client_id == CLIENT_ID_SERVER) return;
2082 NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED, reason);
2083}
2084
2092uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, std::string_view reason)
2093{
2094 return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban, reason);
2095}
2096
2104uint NetworkServerKickOrBanIP(std::string_view ip, bool ban, std::string_view reason)
2105{
2106 /* Add address to ban-list */
2107 if (ban) {
2108 bool contains = false;
2109 for (const auto &iter : _network_ban_list) {
2110 if (iter == ip) {
2111 contains = true;
2112 break;
2113 }
2114 }
2115 if (!contains) _network_ban_list.emplace_back(ip);
2116 }
2117
2118 uint n = 0;
2119
2120 /* There can be multiple clients with the same IP, kick them all but don't kill the server,
2121 * or the client doing the rcon. The latter can't be kicked because kicking frees closes
2122 * and subsequently free the connection related instances, which we would be reading from
2123 * and writing to after returning. So we would read or write data from freed memory up till
2124 * the segfault triggers. */
2125 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
2126 if (cs->client_id == CLIENT_ID_SERVER) continue;
2127 if (cs->client_id == _redirect_console_to_client) continue;
2128 if (cs->client_address.IsInNetmask(ip)) {
2129 NetworkServerKickClient(cs->client_id, reason);
2130 n++;
2131 }
2132 }
2133
2134 return n;
2135}
2136
2142bool NetworkCompanyHasClients(CompanyID company)
2143{
2144 for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
2145 if (ci->client_playas == company) return true;
2146 }
2147 return false;
2148}
2149
2150
2156{
2157 const NetworkClientInfo *ci = this->GetInfo();
2158 if (ci != nullptr && !ci->client_name.empty()) return ci->client_name;
2159
2160 return fmt::format("Client #{}", this->client_id);
2161}
2162
2167{
2169 if (_network_server) {
2170 IConsolePrint(CC_INFO, "Client #{} name: '{}' company: {} IP: {}",
2171 ci->client_id,
2172 ci->client_name,
2173 ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
2174 ci->client_id == CLIENT_ID_SERVER ? "server" : NetworkClientSocket::GetByClientID(ci->client_id)->GetClientIP());
2175 } else {
2176 IConsolePrint(CC_INFO, "Client #{} name: '{}' company: {}",
2177 ci->client_id,
2178 ci->client_name,
2179 ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0));
2180 }
2181 }
2182}
2183
2189std::string_view NetworkGetPublicKeyOfClient(ClientID client_id)
2190{
2191 auto socket = NetworkClientSocket::GetByClientID(client_id);
2192 return socket == nullptr ? "" : socket->GetPeerPublicKey();
2193}
2194
2195
2202{
2203 assert(c != nullptr);
2204
2205 if (!_network_server) return;
2206
2207 if (ci != nullptr) {
2208 /* ci is nullptr when replaying, or for AIs. In neither case there is a client. */
2209 ci->client_playas = c->index;
2211
2212 /*
2213 * This function is called from a command, but is only called for the server.
2214 * The client information is managed out-of-band from the commands, so to not have a
2215 * different state/president/company name in the different clients, we need to
2216 * circumvent the normal ::Post logic and go directly to sending the command.
2217 */
2218 Command<Commands::CompanyAllowListControl>::SendNet(STR_NULL, c->index, CompanyAllowListCtrlAction::AddKey, ci->public_key);
2219 Command<Commands::RenamePresident>::SendNet(STR_NULL, c->index, ci->client_name);
2220
2221 NetworkServerSendChat(NETWORK_ACTION_COMPANY_NEW, DESTTYPE_BROADCAST, 0, "", ci->client_id, c->index + 1);
2222 }
2223}
std::map< SOCKET, NetworkAddress > SocketList
Type for a mapping between address and socket.
Definition address.h:21
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Set()
Set all bits.
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition timer.h:76
Default implementation for the authorized key handler.
Default implementation of the password provider.
static std::unique_ptr< NetworkAuthenticationServerHandler > Create(const NetworkAuthenticationPasswordProvider *password_provider, const NetworkAuthenticationAuthorizedKeyHandler *authorized_key_handler, NetworkAuthenticationMethodMask client_supported_method_mask={NetworkAuthenticationMethod::X25519_KeyExchangeOnly, NetworkAuthenticationMethod::X25519_PAKE, NetworkAuthenticationMethod::X25519_AuthorizedKey})
Create a NetworkAuthenticationServerHandler.
@ RetryNextMethod
The client failed to authenticate, but there is another method to try.
@ NotAuthenticated
All authentications for this handler have been exhausted.
@ Authenticated
The client was authenticated successfully.
bool Contains(std::string_view key) const
Check whether the given key is contains in these authorized keys.
Definition network.cpp:179
NetworkGameSocketHandler(SOCKET s)
Create a new socket for the game connection.
Definition tcp_game.cpp:28
uint32_t last_frame
Last frame we have executed.
Definition tcp_game.h:526
NetworkClientInfo * GetInfo() const
Gets the client info of this socket handler.
Definition tcp_game.h:555
std::optional< std::string_view > ReceiveCommand(Packet &p, CommandPacket &cp)
Receives a command from the network.
ClientID client_id
Client identifier.
Definition tcp_game.h:525
CommandQueue incoming_queue
The command-queue awaiting handling.
Definition tcp_game.h:528
std::chrono::steady_clock::time_point last_packet
Time we received the last frame.
Definition tcp_game.h:529
void SetInfo(NetworkClientInfo *info)
Sets the client info for this socket handler.
Definition tcp_game.h:545
uint32_t last_frame_server
Last frame the server has executed.
Definition tcp_game.h:527
NetworkClientInfo * info
Client info related to this socket.
Definition tcp_game.h:141
void SendCommand(Packet &p, const CommandPacket &cp)
Sends a command over the network.
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition core.h:72
std::unique_ptr< class NetworkEncryptionHandler > send_encryption_handler
The handler for encrypting sent packets.
Definition core.h:48
std::unique_ptr< class NetworkEncryptionHandler > receive_encryption_handler
The handler for decrypting received packets.
Definition core.h:47
virtual std::unique_ptr< Packet > ReceivePacket()
Receives a packet for the given client.
Definition tcp.cpp:117
SOCKET sock
The socket currently connected to.
Definition tcp.h:36
virtual void SendPacket(std::unique_ptr< Packet > &&packet)
This function puts the packet in the send-queue and it is send as soon as possible.
Definition tcp.cpp:56
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
Definition tcp.cpp:74
Class for handling the server side of the game connection.
NetworkRecvStatus Receive_CLIENT_SET_NAME(Packet &p) override
Gives the client a new name: string New name of the client.
static std::string_view GetName()
Get the name used by the listener.
size_t receive_limit
Amount of bytes that we can receive at this moment.
std::shared_ptr< struct PacketWriter > savegame
Writer used to write the savegame.
static void Send()
Send the packets for the server sockets.
NetworkRecvStatus Receive_CLIENT_MOVE(Packet &p) override
Request the server to move this client into another company: uint8_t ID of the company the client wan...
NetworkRecvStatus SendQuit(ClientID client_id)
Tell the client another client quit.
NetworkRecvStatus Receive_CLIENT_ACK(Packet &p) override
Tell the server we are done with this frame: uint32_t Current frame counter of the client.
NetworkRecvStatus Receive_CLIENT_AUTH_RESPONSE(Packet &p) override
Send the response to the authentication request: 32 * uint8_t Public key of the client.
std::unique_ptr< Packet > ReceivePacket() override
Receives a packet for the given client.
@ STATUS_PRE_ACTIVE
The client is catching up the delayed frames.
@ STATUS_IDENTIFY
The client is identifying itself.
@ STATUS_AUTH_GAME
The client is authorizing with game (server) password.
@ STATUS_NEWGRFS_CHECK
The client is checking NewGRFs.
@ STATUS_AUTHORIZED
The client is authorized.
@ STATUS_INACTIVE
The client is not connected nor active.
@ STATUS_MAP
The client is downloading the map.
@ STATUS_DONE_MAP
The client has downloaded the map.
@ STATUS_ACTIVE
The client is active within in the game.
@ STATUS_MAP_WAIT
The client is waiting as someone else is downloading the map.
NetworkRecvStatus Receive_CLIENT_COMMAND(Packet &p) override
Send a DoCommand to the Server: uint8_t ID of the company (0..MAX_COMPANIES-1).
NetworkRecvStatus SendRConResult(uint16_t colour, std::string_view command)
Send the result of a console action.
NetworkRecvStatus Receive_CLIENT_QUIT(Packet &p) override
The client is quitting the game.
NetworkRecvStatus SendChat(NetworkAction action, ClientID client_id, bool self_send, std::string_view msg, int64_t data)
Send a chat message.
NetworkRecvStatus SendWelcome()
Send the client a welcome message with some basic information.
NetworkRecvStatus SendAuthRequest()
Request the game password.
std::string GetClientName() const
Get the name of the client, if the user did not send it yet, Client ID is used.
uint8_t last_token
The last random token we did send to verify the client is listening.
NetworkRecvStatus SendFrame()
Tell the client that they may run to a particular frame.
NetworkRecvStatus Receive_CLIENT_ERROR(Packet &p) override
The client made an error and is quitting the game.
NetworkRecvStatus SendGameInfo()
Send the client information about the server.
NetworkRecvStatus SendJoin(ClientID client_id)
Tell that a client joined.
~ServerNetworkGameSocketHandler() override
Clear everything related to this client.
std::string peer_public_key
The public key of our client.
NetworkRecvStatus Receive_CLIENT_CHAT(Packet &p) override
Sends a chat-packet to the server: uint8_t ID of the action (see NetworkAction).
NetworkRecvStatus SendClientInfo(NetworkClientInfo *ci)
Send the client information about a client.
static bool AllowConnection()
Whether an connection is allowed or not at this moment.
NetworkRecvStatus SendEnableEncryption()
Notify the client that the authentication has completed and tell that for the remainder of this socke...
NetworkRecvStatus Receive_CLIENT_JOIN(Packet &p) override
Try to join the server: string OpenTTD revision (norev0000 if no revision).
NetworkRecvStatus Receive_CLIENT_GAME_INFO(Packet &p) override
Request game information.
NetworkRecvStatus SendExternalChat(std::string_view source, TextColour colour, std::string_view user, std::string_view msg)
Send a chat message from external source.
ServerNetworkGameSocketHandler(ClientPoolID index, SOCKET s)
Create a new socket for the server side of the game connection.
NetworkRecvStatus SendErrorQuit(ClientID client_id, NetworkErrorCode errorno)
Tell the client another client quit with an error.
NetworkAddress client_address
IP-address of the client (so they can be banned).
NetworkRecvStatus SendNewGame()
Tell the client we're starting a new game.
NetworkRecvStatus Receive_CLIENT_GETMAP(Packet &p) override
Request the map from the server.
NetworkRecvStatus SendSync()
Request the client to sync.
std::unique_ptr< class NetworkAuthenticationServerHandler > authentication_handler
The handler for the authentication.
NetworkRecvStatus SendMove(ClientID client_id, CompanyID company_id)
Tell that a client moved to another company.
NetworkRecvStatus Receive_CLIENT_RCON(Packet &p) override
Send an RCon command to the server: string RCon password.
NetworkRecvStatus SendError(NetworkErrorCode error, std::string_view reason={})
Send an error to the client, and close its connection.
NetworkRecvStatus Receive_CLIENT_IDENTIFY(Packet &p) override
The client tells the server about the identity of the client: string Name of the client (max NETWORK_...
NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override
Close the network connection due to the given status.
NetworkRecvStatus SendMap()
This sends the map to the client.
NetworkRecvStatus Receive_CLIENT_NEWGRFS_CHECKED(Packet &p) override
Tell the server that we have the required GRFs.
uint32_t last_token_frame
The last frame we received the right token.
NetworkRecvStatus Receive_CLIENT_MAP_OK(Packet &p) override
Tell the server that we are done receiving/loading the map.
NetworkRecvStatus SendShutdown()
Tell the client we're shutting down.
ClientStatus status
Status of this client.
NetworkRecvStatus SendNewGRFCheck()
Send the check for the NewGRFs.
std::string_view GetClientIP()
Get the IP address/hostname of the connected client.
NetworkRecvStatus SendConfigUpdate()
Send an update about the max company/spectator counts.
NetworkRecvStatus SendWait()
Tell the client that its put in a waiting queue.
NetworkRecvStatus SendCommand(const CommandPacket &cp)
Send a command to the client to execute.
Template for TCP listeners.
Definition tcp_listen.h:28
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
static Year year
Current year, starting at 0.
static Date date
Current date in days (day counter).
static DateFract date_fract
Fractional part of the day.
@ Unpaused
Only run when not paused.
CommandFlags GetCommandFlags(Commands cmd)
Get the command flags associated with the given command.
Definition command.cpp:113
Functions related to commands.
@ Spectator
the command may be initiated by a spectator
@ Server
the command can only be initiated by the server
@ ClientID
set p2 with the ClientID of the sending client.
@ CompanyControl
used in multiplayer to create a new companies etc.
@ CompanyAllowListControl
Used in multiplayer to add/remove a client's public key to/from the company's allow list.
Definition of stuff that is very close to a company, like the company struct itself.
TextColour GetDrawStringCompanyColour(CompanyID company)
Get the colour for DrawString-subroutines which matches the colour of the company.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
void SetLocalCompany(CompanyID new_company)
Sets the local company and updates the settings that are set on a per-company basis to reflect the co...
Command definitions related to companies.
Functions related to companies.
GUI Functions related to companies.
CompanyCtrlAction
The action to do with Commands::CompanyControl.
@ New
Create a new company.
@ Delete
Delete a company.
static constexpr CompanyID COMPANY_SPECTATOR
The client is spectating.
@ AddKey
Create a public key.
static constexpr CompanyID COMPANY_NEW_COMPANY
The client wants a new company.
@ Autoclean
The company is removed due to autoclean.
static const size_t TCP_MTU
Number of bytes we can pack in a single TCP packet.
Definition config.h:43
static const uint NETWORK_CLIENT_NAME_LENGTH
The maximum length of a client's name, in bytes including '\0'.
Definition config.h:56
static const uint NETWORK_CHAT_LENGTH
The maximum length of a chat message, in bytes including '\0'.
Definition config.h:59
static const uint NETWORK_REVISION_LENGTH
The maximum length of the revision, in bytes including '\0'.
Definition config.h:54
static const uint NETWORK_RCONCOMMAND_LENGTH
The maximum length of a rconsole command, in bytes including '\0'.
Definition config.h:57
static const uint NETWORK_PASSWORD_LENGTH
The maximum length of the password, in bytes including '\0'.
Definition config.h:55
void IConsoleCmdExec(std::string_view command_string, const uint recurse_count)
Execute a given command passed to us.
Definition console.cpp:271
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
Console functions used outside of the console code.
static const TextColour CC_INFO
Colour for information lines.
static const TextColour CC_WARNING
Colour for warning lines.
static const TextColour CC_DEFAULT
Default colour of the console.
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
Definition core.h:21
@ NETWORK_RECV_STATUS_CLIENT_QUIT
The connection is lost gracefully. Other clients are already informed of this leaving client.
Definition core.h:26
@ NETWORK_RECV_STATUS_SERVER_ERROR
The server told us we made an error.
Definition core.h:28
@ NETWORK_RECV_STATUS_OKAY
Everything is okay.
Definition core.h:22
@ NETWORK_RECV_STATUS_MALFORMED_PACKET
We apparently send a malformed packet.
Definition core.h:27
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
#define DECLARE_INCREMENT_DECREMENT_OPERATORS(enum_type)
For some enums it is useful to have pre/post increment/decrement operators.
Definition enum_type.hpp:86
@ FT_SCENARIO
old or new scenario
Definition fileio_type.h:20
@ FT_HEIGHTMAP
heightmap file
Definition fileio_type.h:21
@ FT_SAVEGAME
old or new savegame
Definition fileio_type.h:19
Functions related to world/map generation.
static const uint32_t GENERATE_NEW_SEED
Create a new random seed.
Definition genworld.h:25
SwitchMode _switch_mode
The next mainloop command.
Definition gfx.cpp:50
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:307
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
Definition gfx_type.h:370
uint32_t _last_sync_frame
Used in the server to store the last time a sync packet was sent to clients.
Definition network.cpp:80
StringID GetNetworkErrorMsg(NetworkErrorCode err)
Retrieve the string id of an internal error number.
Definition network.cpp:310
ClientID _redirect_console_to_client
If not invalid, redirect the console output to a client.
Definition network.cpp:72
uint32_t _frame_counter
The current frame.
Definition network.cpp:79
StringList _network_ban_list
The banned clients.
Definition network.cpp:76
bool _network_dedicated
are we a dedicated server?
Definition network.cpp:69
bool _network_server
network-server is active
Definition network.cpp:67
uint32_t _sync_seed_1
Seed to compare during sync checks.
Definition network.cpp:82
uint8_t _network_clients_connected
The amount of clients connected.
Definition network.cpp:90
uint32_t _frame_counter_max
To where we may go with our clients.
Definition network.cpp:78
void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
Notify the admin network of a client update (if they did opt in for the respective update).
void NetworkAdminClientQuit(ClientID client_id)
Notify the admin network that a client quit (if they have opt in for the respective update).
void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, std::string_view msg, int64_t data, bool from_admin)
Send chat to the admin network (if they did opt in for the respective update).
void NetworkAdminUpdate(AdminUpdateFrequency freq)
Send (push) updates to the admin network as they have registered for these updates.
void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client)
Notify the admin network of a new client (if they did opt in for the respective update).
void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code)
Notify the admin network of a client error (if they have opt in for the respective update).
Server part of the admin network protocol.
Base core network types and some helper functions to access them.
bool NetworkIsValidClientName(std::string_view client_name)
Check whether the given client name is deemed valid for use in network games.
void NetworkSyncCommandQueue(NetworkClientSocket *cs)
Sync our local command queue to the command queue of the given socket.
NetworkAuthenticationMethod
The authentication method that can be used.
@ X25519_PAKE
Authentication using x25519 password-authenticated key agreement.
@ X25519_AuthorizedKey
Authentication using x22519 key exchange and authorized keys.
void NetworkUpdateClientInfo(ClientID client_id)
Send updated client info of a particular client.
void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
Handle the tid-bits of moving a client from one company to another.
void NetworkServerSendChat(NetworkAction action, DestType type, int dest, std::string_view msg, ClientID from_id, int64_t data=0, bool from_admin=false)
Send an actual chat message.
void SerializeNetworkGameInfo(Packet &p, const NetworkServerGameInfo &info, bool send_newgrf_names)
Serializes the NetworkGameInfo struct to the packet.
const NetworkServerGameInfo & GetCurrentNetworkServerGameInfo()
Get the NetworkServerGameInfo structure with the latest information of the server.
void SerializeGRFIdentifier(Packet &p, const GRFIdentifier &grf)
Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet.
void FillStaticNetworkServerGameInfo()
Fill a NetworkServerGameInfo structure with the static content, or things that are so static they can...
NetworkServerGameInfo _network_game_info
Information about our game.
bool IsNetworkCompatibleVersion(std::string_view other)
Checks whether the given version string is compatible with our version.
Convert NetworkGameInfo to Packet and back.
bool NetworkMakeClientNameUnique(std::string &new_name)
Check whether a name is unique, and otherwise try to make it unique.
static NetworkAuthenticationDefaultAuthorizedKeyHandler _authorized_key_handler
Provides the authorized key handling for the game authentication.
bool NetworkServerChangeClientName(ClientID client_id, const std::string &new_name)
Change the client name of the given client.
void NetworkServerSendExternalChat(std::string_view source, TextColour colour, std::string_view user, std::string_view msg)
Send a chat message from external source.
static IntervalTimer< TimerGameRealtime > _network_restart_map_timer({std::chrono::hours::zero(), TimerGameRealtime::Trigger::Unpaused}, [](auto) { if(!_network_server) return;if(_settings_client.network.restart_hours==0) return;Debug(net, 3, "Auto-restarting map: {} hours played", _settings_client.network.restart_hours);NetworkRestartMap();})
Timer to restart a network server automatically based on real-time hours played.
void NetworkPrintClients()
Print all the clients to the console.
void NetworkServerUpdateGameInfo()
Update the server's NetworkServerGameInfo due to changes in settings.
static const IntervalTimer< TimerGameEconomy > _network_monthly({TimerGameEconomy::Trigger::Month, TimerGameEconomy::Priority::None}, [](auto) { if(!_network_server) return;NetworkAutoCleanCompanies();NetworkAdminUpdate(AdminUpdateFrequency::Monthly);})
Economy monthly "callback".
NetworkCompanyStatsArray NetworkGetCompanyStats()
Get the company stats.
void NetworkUpdateClientInfo(ClientID client_id)
Send updated client info of a particular client.
void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, std::string_view msg, ClientID from_id, int64_t data, bool from_admin)
Send an actual chat message.
void NetworkServerSendConfigUpdate()
Send Config Update.
static const IntervalTimer< TimerGameEconomy > _network_quarterly({TimerGameEconomy::Trigger::Quarter, TimerGameEconomy::Priority::None}, [](auto) { if(!_network_server) return;NetworkAutoCleanCompanies();NetworkAdminUpdate(AdminUpdateFrequency::Quarterly);})
Quarterly "callback".
static const IntervalTimer< TimerGameCalendar > _calendar_network_yearly({ TimerGameCalendar::Trigger::Year, TimerGameCalendar::Priority::None }, [](auto) { if(!_network_server) return;NetworkCheckRestartMapYear();})
Calendar yearly "callback".
void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
Handle the tid-bits of moving a client from one company to another.
static NetworkAuthenticationDefaultPasswordProvider _password_provider
Provides the password validation for the game's password.
static const IntervalTimer< TimerGameEconomy > _economy_network_yearly({TimerGameEconomy::Trigger::Year, TimerGameEconomy::Priority::None}, [](auto) { if(!_network_server) return;NetworkAdminUpdate(AdminUpdateFrequency::Annually);})
Economy yearly "callback".
void ChangeNetworkRestartTime(bool reset)
Reset the automatic network restart time interval.
bool NetworkCompanyHasClients(CompanyID company)
Check whether a particular company has clients.
static void NetworkRestartMap()
Helper function to restart the map.
void NetworkServerKickClient(ClientID client_id, std::string_view reason)
Kick a single client.
static void NetworkCheckRestartMapYear()
Check if we want to restart the map based on the year.
bool NetworkMakeClientNameUnique(std::string &name)
Check whether a name is unique, and otherwise try to make it unique.
static ClientID _network_client_id
The identifier counter for new clients (is never decreased).
std::string_view NetworkGetPublicKeyOfClient(ClientID client_id)
Get the public key of the client with the given id.
static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
Handle the command-queue of a socket.
static const IntervalTimer< TimerGameEconomy > _economy_network_daily({TimerGameEconomy::Trigger::Day, TimerGameEconomy::Priority::None}, [](auto) { if(!_network_server) return;NetworkAdminUpdate(AdminUpdateFrequency::Daily);})
Daily "callback".
static const IntervalTimer< TimerGameEconomy > _network_weekly({TimerGameEconomy::Trigger::Week, TimerGameEconomy::Priority::None}, [](auto) { if(!_network_server) return;NetworkAdminUpdate(AdminUpdateFrequency::Weekly);})
Economy weekly "callback".
void NetworkServerShowStatusToConsole()
Show the status message of all clients on the console.
void NetworkServerNewCompany(const Company *c, NetworkClientInfo *ci)
Perform all the server specific administration of a new company.
void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, std::string_view string)
Send an rcon reply to the client.
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, std::string_view reason)
Ban, or kick, everyone joined from the given client's IP.
void NetworkServer_Tick(bool send_frame)
This is called every tick if this is a _network_server.
NetworkClientSocketPool _networkclientsocket_pool("NetworkClientSocket")
Make very sure the preconditions given in network_type.h are actually followed.
static void NetworkAutoCleanCompanies()
Remove companies that have not been used depending on the autoclean_companies setting and values for ...
static NetworkAuthenticationDefaultAuthorizedKeyHandler _rcon_authorized_key_handler
Provides the authorized key validation for rcon.
Server part of the network protocol.
ServerNetworkGameSocketHandler NetworkClientSocket
Make the code look slightly nicer/simpler.
Pool< NetworkClientSocket, ClientPoolID, 8, PoolType::NetworkClient > NetworkClientSocketPool
Pool with all client sockets.
DestType
Destination of our chat messages.
@ DESTTYPE_CLIENT
Send message/notice to only a certain client (Private).
@ DESTTYPE_TEAM
Send message/notice to everyone playing the same company (Team).
@ DESTTYPE_BROADCAST
Send message/notice to all clients (All).
NetworkErrorCode
The error codes we send around in the protocols.
NetworkAction
Actions that can be used for NetworkTextMessage.
static const uint MAX_CLIENTS
How many clients can we have.
ClientID
'Unique' identifier to be given to clients
@ INVALID_CLIENT_ID
Client is not part of anything.
@ CLIENT_ID_SERVER
Servers always have this ID.
@ CLIENT_ID_FIRST
The first client ID.
PoolID< uint16_t, struct ClientPoolIDTag, MAX_CLIENTS+1, 0xFFFF > ClientPoolID
Indices into the client related pools.
Sending and receiving UDP messages.
GRFConfigList _grfconfig
First item in list of current GRF set up.
@ Static
GRF file is used statically (can be used in any MP game).
@ SM_START_HEIGHTMAP
Load a heightmap and start a new game from it.
Definition openttd.h:38
@ SM_LOAD_GAME
Load game, Play Scenario.
Definition openttd.h:32
@ SM_NEWGAME
New Game --> 'Random game'.
Definition openttd.h:28
Functions related to order backups.
Some methods of Pool are placed here in order to reduce compilation time and binary size.
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Pseudo random number generator.
Declaration of OTTD revision dependent variables.
Road vehicle states.
A number of safeguards to prevent using unsafe methods.
void SlError(StringID string, const std::string &extra_msg)
Error handler.
Definition saveload.cpp:339
SaveOrLoadResult SaveWithFilter(std::shared_ptr< SaveFilter > writer, bool threaded)
Save the game using a (writer) filter.
FileToSaveLoad _file_to_saveload
File to save or load in the openttd loop.
Definition saveload.cpp:78
Functions/types related to saving and loading games.
@ SL_OK
completed successfully
Definition saveload.h:423
Declaration of filters used for saving and loading savegames.
GameSettings _settings_newgame
Game settings for new games (updated from the intro screen).
Definition settings.cpp:62
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
Base classes/functions for stations.
@ Dock
Station with a dock.
@ TruckStop
Station with truck stops.
@ Train
Station with train station.
@ Airport
Station with an airport.
@ BusStop
Station with bus stops.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Everything we need to know about a command to be able to execute it.
CommandDataBuffer data
command parameters.
uint32_t frame
the frame in which this packet is executed
CompanyID company
company that is executing the command
bool my_cmd
did the command originate from "me"
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.
bool allow_any
Set if anyone is allowed to join this company.
uint8_t months_empty
NOSAVE: Number of months this company has not had a client in multiplayer.
static bool IsValidHumanID(auto index)
Is this company a valid company, not controlled by a NoAI program?
Statistics and caches on the vehicles in a group.
Definition group.h:25
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:117
TimerGameEconomy::Date join_date
Gamedate the client has joined.
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.
Simple calculated statistics of a company.
uint16_t num_station[NETWORK_VEH_END]
How many stations are there of this type?
static void ResetUser(uint32_t user)
Reset an user's OrderBackup if needed.
void Write(uint8_t *buf, size_t size) override
Write a given number of bytes into the savegame.
std::unique_ptr< Packet > current
The packet we're currently writing to.
PacketWriter(ServerNetworkGameSocketHandler *cs)
Create the packet writer.
size_t total_size
Total size of the compressed savegame.
std::condition_variable exit_sig
Signal for threaded destruction of this packet writer.
void Finish() override
Prepare everything to finish writing the savegame.
~PacketWriter() override
Make sure everything is cleaned up.
ServerNetworkGameSocketHandler * cs
Socket we are associated with.
std::mutex mutex
Mutex for making threaded saving safe.
void Destroy()
Begin the destruction of this packet writer.
bool TransferToNetworkQueue()
Transfer all packets from here to the network's queue while holding the lock on our mutex.
std::deque< std::unique_ptr< Packet > > packets
Packet queue of the savegame; send these "slowly" to the client. Cannot be a std::queue as we want to...
uint64_t Recv_uint64()
Read a 64 bits integer from the packet.
Definition packet.cpp:362
uint32_t Recv_uint32()
Read a 32 bits integer from the packet.
Definition packet.cpp:345
std::string Recv_string(size_t length, StringValidationSettings settings=StringValidationSetting::ReplaceWithQuestionMark)
Reads characters (bytes) from the packet until it finds a '\0', or reaches a maximum of length charac...
Definition packet.cpp:423
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
Definition packet.cpp:316
static Pool::IterateWrapper< NetworkClientSocket > Iterate(size_t from=0)
static Company * Get(auto index)
static Company * GetIfValid(auto index)
bool IsBus() const
Check whether a roadvehicle is a bus.
SaveFilter(std::shared_ptr< SaveFilter > chain)
Initialise this filter.
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
static RoadVehicle * From(Vehicle *v)
Station data structure.
Vehicle data structure.
@ SPS_CLOSED
The connection got closed.
Definition tcp.h:22
@ Annually
The admin gets information about this on a yearly basis.
Definition tcp_admin.h:99
@ Weekly
The admin gets information about this on a weekly basis.
Definition tcp_admin.h:96
@ Monthly
The admin gets information about this on a monthly basis.
Definition tcp_admin.h:97
@ Quarterly
The admin gets information about this on a quarterly basis.
Definition tcp_admin.h:98
@ Daily
The admin gets information about this on a daily basis.
Definition tcp_admin.h:95
@ PACKET_SERVER_JOIN
Tells clients that a new client has joined.
Definition tcp_game.h:84
@ PACKET_SERVER_MAP_SIZE
Server tells the client what the (compressed) size of the map is.
Definition tcp_game.h:79
@ PACKET_SERVER_RCON
Response of the executed command on the server.
Definition tcp_game.h:108
@ PACKET_SERVER_MAP_BEGIN
Server tells the client that it is beginning to send the map.
Definition tcp_game.h:78
@ PACKET_SERVER_SYNC
Server tells the client what the random state should be.
Definition tcp_game.h:95
@ PACKET_SERVER_WAIT
Server tells the client there are some people waiting for the map as well.
Definition tcp_game.h:77
@ PACKET_SERVER_CONFIG_UPDATE
Some network configuration important to the client changed.
Definition tcp_game.h:116
@ PACKET_SERVER_ENABLE_ENCRYPTION
The server tells that authentication has completed and requests to enable encryption with the keys of...
Definition tcp_game.h:62
@ PACKET_SERVER_GAME_INFO
Information about the server.
Definition tcp_game.h:42
@ PACKET_SERVER_ERROR_QUIT
A server tells that a client has hit an error and did quit.
Definition tcp_game.h:122
@ PACKET_SERVER_CLIENT_INFO
Server sends you information about a client.
Definition tcp_game.h:73
@ PACKET_SERVER_WELCOME
Server welcomes you and gives you your ClientID.
Definition tcp_game.h:72
@ PACKET_SERVER_BANNED
The server has banned you.
Definition tcp_game.h:31
@ PACKET_SERVER_FRAME
Server tells the client what frame it is in, and thus to where the client may progress.
Definition tcp_game.h:93
@ PACKET_SERVER_EXTERNAL_CHAT
Server distributing the message from external source.
Definition tcp_game.h:104
@ PACKET_SERVER_CHAT
Server distributing the message of a client (or itself).
Definition tcp_game.h:103
@ PACKET_SERVER_COMMAND
Server distributes a command to (all) the clients.
Definition tcp_game.h:99
@ PACKET_SERVER_SHUTDOWN
The server is shutting down.
Definition tcp_game.h:47
@ PACKET_SERVER_AUTH_REQUEST
The server requests the client to authenticate using a number of methods.
Definition tcp_game.h:60
@ PACKET_SERVER_NEWGAME
The server is preparing to start a new game.
Definition tcp_game.h:46
@ PACKET_SERVER_MOVE
Server tells everyone that someone is moved to another company.
Definition tcp_game.h:112
@ PACKET_SERVER_MAP_DATA
Server sends bits of the map to the client.
Definition tcp_game.h:80
@ PACKET_SERVER_FULL
The server is full and has no place for you.
Definition tcp_game.h:30
@ PACKET_SERVER_QUIT
A server tells that a client has quit.
Definition tcp_game.h:120
@ PACKET_SERVER_ERROR
Server sending an error message to the client.
Definition tcp_game.h:35
@ PACKET_SERVER_CHECK_NEWGRFS
Server sends NewGRF IDs and MD5 checksums for the client to check.
Definition tcp_game.h:68
@ PACKET_SERVER_MAP_DONE
Server tells it has just sent the last bits of the map to the client.
Definition tcp_game.h:81
Definition of Interval and OneShot timers.
Definition of the game-calendar-timer.
Definition of the game-economy-timer.
Definition of the real time game-timer.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.
std::mutex lock
synchronization for playback status fields
Definition win32_m.cpp:35
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:3307
@ WC_CLIENT_LIST
Client list; Window numbers: