OpenTTD Source  20241120-master-g6d3adc6169
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 <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "../stdafx.h"
11 #include "../strings_func.h"
12 #include "core/network_game_info.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"
20 #include "../saveload/saveload.h"
21 #include "../saveload/saveload_filter.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"
30 #include "../core/random_func.hpp"
31 #include "../company_cmd.h"
32 #include "../rev.h"
33 #include "../timer/timer.h"
34 #include "../timer/timer_game_calendar.h"
35 #include "../timer/timer_game_economy.h"
36 #include "../timer/timer_game_realtime.h"
37 #include <mutex>
38 #include <condition_variable>
39 
40 #include "../safeguards.h"
41 
42 
43 /* This file handles all the server-commands */
44 
48 
50 static_assert(MAX_CLIENT_SLOTS > MAX_CLIENTS);
52 static_assert(NetworkClientSocketPool::MAX_SIZE == MAX_CLIENT_SLOTS);
53 
56 INSTANTIATE_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 
79  PacketWriter(ServerNetworkGameSocketHandler *cs) : SaveFilter(nullptr), cs(cs), total_size(0)
80  {
81  }
82 
85  {
86  std::unique_lock<std::mutex> lock(this->mutex);
87 
88  if (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 
192 {
193  this->status = STATUS_INACTIVE;
194  this->client_id = _network_client_id++;
196 
197  Debug(net, 9, "client[{}] status = INACTIVE", this->client_id);
198 
199  /* The Socket and Info pools need to be the same in size. After all,
200  * each Socket will be associated with at most one Info object. As
201  * such if the Socket was allocated the Info object can as well. */
203 }
204 
209 {
210  delete this->GetInfo();
211 
214 
215  if (this->savegame != nullptr) {
216  this->savegame->Destroy();
217  this->savegame = nullptr;
218  }
219 
221 }
222 
224 {
225  /* Only allow receiving when we have some buffer free; this value
226  * can go negative, but eventually it will become positive again. */
227  if (this->receive_limit <= 0) return nullptr;
228 
229  /* We can receive a packet, so try that and if needed account for
230  * the amount of received data. */
231  std::unique_ptr<Packet> p = this->NetworkTCPSocketHandler::ReceivePacket();
232  if (p != nullptr) this->receive_limit -= p->Size();
233  return p;
234 }
235 
237 {
238  assert(status != NETWORK_RECV_STATUS_OKAY);
239  /*
240  * Sending a message just before leaving the game calls cs->SendPackets.
241  * This might invoke this function, which means that when we close the
242  * connection after cs->SendPackets we will close an already closed
243  * connection. This handles that case gracefully without having to make
244  * that code any more complex or more aware of the validity of the socket.
245  */
246  if (this->IsPendingDeletion() || this->sock == INVALID_SOCKET) return status;
247 
249  /* We did not receive a leave message from this client... */
250  std::string client_name = this->GetClientName();
251 
252  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST);
253 
254  /* Inform other clients of this... strange leaving ;) */
255  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
256  if (new_cs->status >= STATUS_AUTHORIZED && this != new_cs) {
257  new_cs->SendErrorQuit(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
258  }
259  }
260  }
261 
262  /* If we were transfering a map to this client, stop the savegame creation
263  * process and queue the next client to receive the map. */
264  if (this->status == STATUS_MAP) {
265  /* Ensure the saving of the game is stopped too. */
266  this->savegame->Destroy();
267  this->savegame = nullptr;
268 
269  this->CheckNextClientToSendMap(this);
270  }
271 
272  NetworkAdminClientError(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
273  Debug(net, 3, "[{}] Client #{} closed connection", ServerNetworkGameSocketHandler::GetName(), this->client_id);
274 
275  /* We just lost one client :( */
276  if (this->status >= STATUS_AUTHORIZED) _network_game_info.clients_on--;
277  extern uint8_t _network_clients_connected;
279 
280  this->SendPackets(true);
281 
282  this->DeferDeletion();
283 
284  return status;
285 }
286 
292 {
293  extern uint8_t _network_clients_connected;
294  bool accept = _network_clients_connected < MAX_CLIENTS;
295 
296  /* We can't go over the MAX_CLIENTS limit here. However, the
297  * pool must have place for all clients and ourself. */
298  static_assert(NetworkClientSocketPool::MAX_SIZE == MAX_CLIENTS + 1);
300  return accept;
301 }
302 
305 {
306  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
307  if (cs->writable) {
308  if (cs->SendPackets() != SPS_CLOSED && cs->status == STATUS_MAP) {
309  /* This client is in the middle of a map-send, call the function for that */
310  cs->SendMap();
311  }
312  }
313  }
314 }
315 
316 static void NetworkHandleCommandQueue(NetworkClientSocket *cs);
317 
318 /***********
319  * Sending functions
320  ************/
321 
327 {
328  Debug(net, 9, "client[{}] SendClientInfo(): client_id={}", this->client_id, ci->client_id);
329 
330  if (ci->client_id != INVALID_CLIENT_ID) {
331  auto p = std::make_unique<Packet>(this, PACKET_SERVER_CLIENT_INFO);
332  p->Send_uint32(ci->client_id);
333  p->Send_uint8 (ci->client_playas);
334  p->Send_string(ci->client_name);
335  p->Send_string(ci->public_key);
336 
337  this->SendPacket(std::move(p));
338  }
340 }
341 
344 {
345  Debug(net, 9, "client[{}] SendGameInfo()", this->client_id);
346 
347  auto p = std::make_unique<Packet>(this, PACKET_SERVER_GAME_INFO, TCP_MTU);
348  SerializeNetworkGameInfo(*p, GetCurrentNetworkServerGameInfo());
349 
350  this->SendPacket(std::move(p));
351 
353 }
354 
361 {
362  Debug(net, 9, "client[{}] SendError(): error={}", this->client_id, error);
363 
364  auto p = std::make_unique<Packet>(this, PACKET_SERVER_ERROR);
365 
366  p->Send_uint8(error);
367  if (!reason.empty()) p->Send_string(reason);
368  this->SendPacket(std::move(p));
369 
370  StringID strid = GetNetworkErrorMsg(error);
371 
372  /* Only send when the current client was in game */
373  if (this->status >= STATUS_AUTHORIZED) {
374  std::string client_name = this->GetClientName();
375 
376  Debug(net, 1, "'{}' made an error and has been disconnected: {}", client_name, GetString(strid));
377 
378  if (error == NETWORK_ERROR_KICKED && !reason.empty()) {
379  NetworkTextMessage(NETWORK_ACTION_KICKED, CC_DEFAULT, false, client_name, reason, strid);
380  } else {
381  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", strid);
382  }
383 
384  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
385  if (new_cs->status >= STATUS_AUTHORIZED && new_cs != this) {
386  /* Some errors we filter to a more general error. Clients don't have to know the real
387  * reason a joining failed. */
388  if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION) {
389  error = NETWORK_ERROR_ILLEGAL_PACKET;
390  }
391  new_cs->SendErrorQuit(this->client_id, error);
392  }
393  }
394 
395  NetworkAdminClientError(this->client_id, error);
396  } else {
397  Debug(net, 1, "Client {} made an error and has been disconnected: {}", this->client_id, GetString(strid));
398  }
399 
400  /* The client made a mistake, so drop the connection now! */
402 }
403 
406 {
407  Debug(net, 9, "client[{}] SendNewGRFCheck()", this->client_id);
408 
409  /* Invalid packet when status is anything but STATUS_IDENTIFY. */
411 
412  Debug(net, 9, "client[{}] status = NEWGRFS_CHECK", this->client_id);
414 
415  if (_grfconfig == nullptr) {
416  /* There are no NewGRFs, so they're welcome. */
417  return this->SendWelcome();
418  }
419 
420  auto p = std::make_unique<Packet>(this, PACKET_SERVER_CHECK_NEWGRFS, TCP_MTU);
421  const GRFConfig *c;
422  uint grf_count = 0;
423 
424  for (c = _grfconfig; c != nullptr; c = c->next) {
425  if (!HasBit(c->flags, GCF_STATIC)) grf_count++;
426  }
427 
428  p->Send_uint8 (grf_count);
429  for (c = _grfconfig; c != nullptr; c = c->next) {
430  if (!HasBit(c->flags, GCF_STATIC)) SerializeGRFIdentifier(*p, c->ident);
431  }
432 
433  this->SendPacket(std::move(p));
435 }
436 
439 {
440  Debug(net, 9, "client[{}] SendAuthRequest()", this->client_id);
441 
442  /* Invalid packet when status is anything but STATUS_INACTIVE or STATUS_AUTH_GAME. */
444 
445  Debug(net, 9, "client[{}] status = AUTH_GAME", this->client_id);
446  this->status = STATUS_AUTH_GAME;
447 
448  /* Reset 'lag' counters */
450 
451  if (this->authentication_handler == nullptr) {
453  }
454 
455  auto p = std::make_unique<Packet>(this, PACKET_SERVER_AUTH_REQUEST);
456  this->authentication_handler->SendRequest(*p);
457 
458  this->SendPacket(std::move(p));
460 }
461 
464 {
465  Debug(net, 9, "client[{}] SendEnableEncryption()", this->client_id);
466 
467  /* Invalid packet when status is anything but STATUS_AUTH_GAME. */
469 
470  auto p = std::make_unique<Packet>(this, PACKET_SERVER_ENABLE_ENCRYPTION);
471  this->authentication_handler->SendEnableEncryption(*p);
472  this->SendPacket(std::move(p));
474 }
475 
478 {
479  Debug(net, 9, "client[{}] SendWelcome()", this->client_id);
480 
481  /* Invalid packet when status is anything but STATUS_NEWGRFS_CHECK. */
483 
484  Debug(net, 9, "client[{}] status = AUTHORIZED", this->client_id);
485  this->status = STATUS_AUTHORIZED;
486 
487  /* Reset 'lag' counters */
489 
490  _network_game_info.clients_on++;
491 
492  auto p = std::make_unique<Packet>(this, PACKET_SERVER_WELCOME);
493  p->Send_uint32(this->client_id);
494  this->SendPacket(std::move(p));
495 
496  /* Transmit info about all the active clients */
497  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
498  if (new_cs != this && new_cs->status >= STATUS_AUTHORIZED) {
499  this->SendClientInfo(new_cs->GetInfo());
500  }
501  }
502  /* Also send the info of the server */
504 }
505 
508 {
509  Debug(net, 9, "client[{}] SendWait()", this->client_id);
510 
511  int waiting = 1; // current player getting the map counts as 1
512 
513  /* Count how many clients are waiting in the queue, in front of you! */
514  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
515  if (new_cs->status != STATUS_MAP_WAIT) continue;
516  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++;
517  }
518 
519  auto p = std::make_unique<Packet>(this, PACKET_SERVER_WAIT);
520  p->Send_uint8(waiting);
521  this->SendPacket(std::move(p));
523 }
524 
525 void ServerNetworkGameSocketHandler::CheckNextClientToSendMap(NetworkClientSocket *ignore_cs)
526 {
527  Debug(net, 9, "client[{}] CheckNextClientToSendMap()", this->client_id);
528 
529  /* Find the best candidate for joining, i.e. the first joiner. */
530  NetworkClientSocket *best = nullptr;
531  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
532  if (ignore_cs == new_cs) continue;
533 
534  if (new_cs->status == STATUS_MAP_WAIT) {
535  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)) {
536  best = new_cs;
537  }
538  }
539  }
540 
541  /* Is there someone else to join? */
542  if (best != nullptr) {
543  /* Let the first start joining. */
544  best->status = STATUS_AUTHORIZED;
545  best->SendMap();
546 
547  /* And update the rest. */
548  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
549  if (new_cs->status == STATUS_MAP_WAIT) new_cs->SendWait();
550  }
551  }
552 }
553 
556 {
557  if (this->status < STATUS_AUTHORIZED) {
558  /* Illegal call, return error and ignore the packet */
559  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
560  }
561 
562  if (this->status == STATUS_AUTHORIZED) {
563  Debug(net, 9, "client[{}] SendMap(): first_packet", this->client_id);
564 
565  WaitTillSaved();
566  this->savegame = std::make_shared<PacketWriter>(this);
567 
568  /* Now send the _frame_counter and how many packets are coming */
569  auto p = std::make_unique<Packet>(this, PACKET_SERVER_MAP_BEGIN);
570  p->Send_uint32(_frame_counter);
571  this->SendPacket(std::move(p));
572 
574  Debug(net, 9, "client[{}] status = MAP", this->client_id);
575  this->status = STATUS_MAP;
576  /* Mark the start of download */
577  this->last_frame = _frame_counter;
579 
580  /* Make a dump of the current game */
581  if (SaveWithFilter(this->savegame, true) != SL_OK) UserError("network savedump failed");
582  }
583 
584  if (this->status == STATUS_MAP) {
585  bool last_packet = this->savegame->TransferToNetworkQueue();
586  if (last_packet) {
587  Debug(net, 9, "client[{}] SendMap(): last_packet", this->client_id);
588 
589  /* Done reading, make sure saving is done as well */
590  this->savegame->Destroy();
591  this->savegame = nullptr;
592 
593  /* Set the status to DONE_MAP, no we will wait for the client
594  * to send it is ready (maybe that happens like never ;)) */
595  Debug(net, 9, "client[{}] status = DONE_MAP", this->client_id);
596  this->status = STATUS_DONE_MAP;
597 
598  this->CheckNextClientToSendMap();
599  }
600  }
602 }
603 
609 {
610  Debug(net, 9, "client[{}] SendJoin(): client_id={}", this->client_id, client_id);
611 
612  auto p = std::make_unique<Packet>(this, PACKET_SERVER_JOIN);
613 
614  p->Send_uint32(client_id);
615 
616  this->SendPacket(std::move(p));
618 }
619 
622 {
623  auto p = std::make_unique<Packet>(this, PACKET_SERVER_FRAME);
624  p->Send_uint32(_frame_counter);
625  p->Send_uint32(_frame_counter_max);
626 #ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
627  p->Send_uint32(_sync_seed_1);
628 #ifdef NETWORK_SEND_DOUBLE_SEED
629  p->Send_uint32(_sync_seed_2);
630 #endif
631 #endif
632 
633  /* If token equals 0, we need to make a new token and send that. */
634  if (this->last_token == 0) {
635  this->last_token = InteractiveRandomRange(UINT8_MAX - 1) + 1;
636  p->Send_uint8(this->last_token);
637  }
638 
639  this->SendPacket(std::move(p));
641 }
642 
645 {
646  Debug(net, 9, "client[{}] SendSync(), frame_counter={}, sync_seed_1={}", this->client_id, _frame_counter, _sync_seed_1);
647 
648  auto p = std::make_unique<Packet>(this, PACKET_SERVER_SYNC);
649  p->Send_uint32(_frame_counter);
650  p->Send_uint32(_sync_seed_1);
651 
652 #ifdef NETWORK_SEND_DOUBLE_SEED
653  p->Send_uint32(_sync_seed_2);
654 #endif
655  this->SendPacket(std::move(p));
657 }
658 
664 {
665  Debug(net, 9, "client[{}] SendCommand(): cmd={}", this->client_id, cp.cmd);
666 
667  auto p = std::make_unique<Packet>(this, PACKET_SERVER_COMMAND);
668 
670  p->Send_uint32(cp.frame);
671  p->Send_bool (cp.my_cmd);
672 
673  this->SendPacket(std::move(p));
675 }
676 
685 NetworkRecvStatus ServerNetworkGameSocketHandler::SendChat(NetworkAction action, ClientID client_id, bool self_send, const std::string &msg, int64_t data)
686 {
687  Debug(net, 9, "client[{}] SendChat(): action={}, client_id={}, self_send={}", this->client_id, action, client_id, self_send);
688 
690 
691  auto p = std::make_unique<Packet>(this, PACKET_SERVER_CHAT);
692 
693  p->Send_uint8 (action);
694  p->Send_uint32(client_id);
695  p->Send_bool (self_send);
696  p->Send_string(msg);
697  p->Send_uint64(data);
698 
699  this->SendPacket(std::move(p));
701 }
702 
710 NetworkRecvStatus ServerNetworkGameSocketHandler::SendExternalChat(const std::string &source, TextColour colour, const std::string &user, const std::string &msg)
711 {
712  Debug(net, 9, "client[{}] SendExternalChat(): source={}", this->client_id, source);
713 
715 
716  auto p = std::make_unique<Packet>(this, PACKET_SERVER_EXTERNAL_CHAT);
717 
718  p->Send_string(source);
719  p->Send_uint16(colour);
720  p->Send_string(user);
721  p->Send_string(msg);
722 
723  this->SendPacket(std::move(p));
725 }
726 
733 {
734  Debug(net, 9, "client[{}] SendErrorQuit(): client_id={}, errorno={}", this->client_id, client_id, errorno);
735 
736  auto p = std::make_unique<Packet>(this, PACKET_SERVER_ERROR_QUIT);
737 
738  p->Send_uint32(client_id);
739  p->Send_uint8 (errorno);
740 
741  this->SendPacket(std::move(p));
743 }
744 
750 {
751  Debug(net, 9, "client[{}] SendQuit(): client_id={}", this->client_id, client_id);
752 
753  auto p = std::make_unique<Packet>(this, PACKET_SERVER_QUIT);
754 
755  p->Send_uint32(client_id);
756 
757  this->SendPacket(std::move(p));
759 }
760 
763 {
764  Debug(net, 9, "client[{}] SendShutdown()", this->client_id);
765 
766  auto p = std::make_unique<Packet>(this, PACKET_SERVER_SHUTDOWN);
767  this->SendPacket(std::move(p));
769 }
770 
773 {
774  Debug(net, 9, "client[{}] SendNewGame()", this->client_id);
775 
776  auto p = std::make_unique<Packet>(this, PACKET_SERVER_NEWGAME);
777  this->SendPacket(std::move(p));
779 }
780 
786 NetworkRecvStatus ServerNetworkGameSocketHandler::SendRConResult(uint16_t colour, const std::string &command)
787 {
788  Debug(net, 9, "client[{}] SendRConResult()", this->client_id);
789 
790  auto p = std::make_unique<Packet>(this, PACKET_SERVER_RCON);
791 
792  p->Send_uint16(colour);
793  p->Send_string(command);
794  this->SendPacket(std::move(p));
796 }
797 
804 {
805  Debug(net, 9, "client[{}] SendMove(): client_id={}", this->client_id, client_id);
806 
807  auto p = std::make_unique<Packet>(this, PACKET_SERVER_MOVE);
808 
809  p->Send_uint32(client_id);
810  p->Send_uint8(company_id);
811  this->SendPacket(std::move(p));
813 }
814 
817 {
818  Debug(net, 9, "client[{}] SendConfigUpdate()", this->client_id);
819 
820  auto p = std::make_unique<Packet>(this, PACKET_SERVER_CONFIG_UPDATE);
821 
822  p->Send_uint8(_settings_client.network.max_companies);
823  p->Send_string(_settings_client.network.server_name);
824  this->SendPacket(std::move(p));
826 }
827 
828 /***********
829  * Receiving functions
830  ************/
831 
833 {
834  Debug(net, 9, "client[{}] Receive_CLIENT_GAME_INFO()", this->client_id);
835 
836  return this->SendGameInfo();
837 }
838 
840 {
841  if (this->status != STATUS_NEWGRFS_CHECK) {
842  /* Illegal call, return error and ignore the packet */
843  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
844  }
845 
846  Debug(net, 9, "client[{}] Receive_CLIENT_NEWGRFS_CHECKED()", this->client_id);
847 
848  return this->SendWelcome();
849 }
850 
852 {
853  if (this->status != STATUS_INACTIVE) {
854  /* Illegal call, return error and ignore the packet */
855  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
856  }
857 
858  if (_network_game_info.clients_on >= _settings_client.network.max_clients) {
859  /* Turns out we are full. Inform the user about this. */
860  return this->SendError(NETWORK_ERROR_FULL);
861  }
862 
863  std::string client_revision = p.Recv_string(NETWORK_REVISION_LENGTH);
864  uint32_t newgrf_version = p.Recv_uint32();
865 
866  Debug(net, 9, "client[{}] Receive_CLIENT_JOIN(): client_revision={}, newgrf_version={}", this->client_id, client_revision, newgrf_version);
867 
868  /* Check if the client has revision control enabled */
869  if (!IsNetworkCompatibleVersion(client_revision) || _openttd_newgrf_version != newgrf_version) {
870  /* Different revisions!! */
871  return this->SendError(NETWORK_ERROR_WRONG_REVISION);
872  }
873 
874  return this->SendAuthRequest();
875 }
876 
878 {
879  if (this->status != STATUS_IDENTIFY) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
880 
881  Debug(net, 9, "client[{}] Receive_CLIENT_IDENTIFY()", this->client_id);
882 
883  std::string client_name = p.Recv_string(NETWORK_CLIENT_NAME_LENGTH);
884  CompanyID playas = (Owner)p.Recv_uint8();
885 
887 
888  /* join another company does not affect these values */
889  switch (playas) {
890  case COMPANY_NEW_COMPANY: // New company
892  return this->SendError(NETWORK_ERROR_FULL);
893  }
894  break;
895  case COMPANY_SPECTATOR: // Spectator
896  break;
897  default: // Join another company (companies 1..MAX_COMPANIES (index 0..(MAX_COMPANIES-1)))
898  if (!Company::IsValidHumanID(playas)) {
899  return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
900  }
901 
902  if (!Company::Get(playas)->allow_list.Contains(this->peer_public_key)) {
903  /* When we're not authorized, just bump us to a spectator. */
904  playas = COMPANY_SPECTATOR;
905  }
906  break;
907  }
908 
909  if (!NetworkIsValidClientName(client_name)) {
910  /* An invalid client name was given. However, the client ensures the name
911  * is valid before it is sent over the network, so something went horribly
912  * wrong. This is probably someone trying to troll us. */
913  return this->SendError(NETWORK_ERROR_INVALID_CLIENT_NAME);
914  }
915 
916  if (!NetworkMakeClientNameUnique(client_name)) { // Change name if duplicate
917  /* We could not create a name for this client */
918  return this->SendError(NETWORK_ERROR_NAME_IN_USE);
919  }
920 
923  this->SetInfo(ci);
925  ci->client_name = client_name;
926  ci->client_playas = playas;
927  ci->public_key = this->peer_public_key;
928  Debug(desync, 1, "client: {:08x}; {:02x}; {:02x}; {:02x}", TimerGameEconomy::date, TimerGameEconomy::date_fract, (int)ci->client_playas, (int)ci->index);
929 
930  /* Make sure companies to which people try to join are not autocleaned */
931  Company *c = Company::GetIfValid(playas);
932  if (c != nullptr) c->months_empty = 0;
933 
934  return this->SendNewGRFCheck();
935 }
936 
937 static NetworkErrorCode GetErrorForAuthenticationMethod(NetworkAuthenticationMethod method)
938 {
939  switch (method) {
941  return NETWORK_ERROR_WRONG_PASSWORD;
943  return NETWORK_ERROR_NOT_ON_ALLOW_LIST;
944 
945  default:
946  NOT_REACHED();
947  }
948 }
949 
951 {
952  if (this->status != STATUS_AUTH_GAME) {
953  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
954  }
955 
956  Debug(net, 9, "client[{}] Receive_CLIENT_AUTH_RESPONSE()", this->client_id);
957 
958  auto authentication_method = this->authentication_handler->GetAuthenticationMethod();
959  switch (this->authentication_handler->ReceiveResponse(p)) {
961  break;
962 
964  return this->SendAuthRequest();
965 
967  default:
968  return this->SendError(GetErrorForAuthenticationMethod(authentication_method));
969  }
970 
972  if (status != NETWORK_RECV_STATUS_OKAY) return status;
973 
974  this->peer_public_key = this->authentication_handler->GetPeerPublicKey();
975  this->receive_encryption_handler = this->authentication_handler->CreateClientToServerEncryptionHandler();
976  this->send_encryption_handler = this->authentication_handler->CreateServerToClientEncryptionHandler();
977  this->authentication_handler = nullptr;
978 
979  Debug(net, 9, "client[{}] status = IDENTIFY", this->client_id);
980  this->status = STATUS_IDENTIFY;
981 
982  /* Reset 'lag' counters */
984 
986 }
987 
989 {
990  /* The client was never joined.. so this is impossible, right?
991  * Ignore the packet, give the client a warning, and close the connection */
992  if (this->status < STATUS_AUTHORIZED || this->HasClientQuit()) {
993  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
994  }
995 
996  Debug(net, 9, "client[{}] Receive_CLIENT_GETMAP()", this->client_id);
997 
998  /* Check if someone else is receiving the map */
999  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
1000  if (new_cs->status == STATUS_MAP) {
1001  /* Tell the new client to wait */
1002  Debug(net, 9, "client[{}] status = MAP_WAIT", this->client_id);
1003  this->status = STATUS_MAP_WAIT;
1004  return this->SendWait();
1005  }
1006  }
1007 
1008  /* We receive a request to upload the map.. give it to the client! */
1009  return this->SendMap();
1010 }
1011 
1013 {
1014  /* Client has the map, now start syncing */
1015  if (this->status == STATUS_DONE_MAP && !this->HasClientQuit()) {
1016  Debug(net, 9, "client[{}] Receive_CLIENT_MAP_OK()", this->client_id);
1017 
1018  std::string client_name = this->GetClientName();
1019 
1020  NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, "", this->client_id);
1022 
1023  Debug(net, 3, "[{}] Client #{} ({}) joined as {}", ServerNetworkGameSocketHandler::GetName(), this->client_id, this->GetClientIP(), client_name);
1024 
1025  /* Mark the client as pre-active, and wait for an ACK
1026  * so we know it is done loading and in sync with us */
1027  Debug(net, 9, "client[{}] status = PRE_ACTIVE", this->client_id);
1028  this->status = STATUS_PRE_ACTIVE;
1030  this->SendFrame();
1031  this->SendSync();
1032 
1033  /* This is the frame the client receives
1034  * we need it later on to make sure the client is not too slow */
1035  this->last_frame = _frame_counter;
1037 
1038  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
1039  if (new_cs->status >= STATUS_AUTHORIZED) {
1040  new_cs->SendClientInfo(this->GetInfo());
1041  new_cs->SendJoin(this->client_id);
1042  }
1043  }
1044 
1045  NetworkAdminClientInfo(this, true);
1046 
1047  /* also update the new client with our max values */
1048  return this->SendConfigUpdate();
1049  }
1050 
1051  /* Wrong status for this packet, give a warning to client, and close connection */
1052  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1053 }
1054 
1060 {
1061  /* The client was never joined.. so this is impossible, right?
1062  * Ignore the packet, give the client a warning, and close the connection */
1063  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1064  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1065  }
1066 
1068  return this->SendError(NETWORK_ERROR_TOO_MANY_COMMANDS);
1069  }
1070 
1071  Debug(net, 9, "client[{}] Receive_CLIENT_COMMAND()", this->client_id);
1072 
1073  CommandPacket cp;
1074  const char *err = this->ReceiveCommand(p, cp);
1075 
1076  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT;
1077 
1078  NetworkClientInfo *ci = this->GetInfo();
1079 
1080  if (err != nullptr) {
1081  IConsolePrint(CC_WARNING, "Dropping client #{} (IP: {}) due to {}.", ci->client_id, this->GetClientIP(), err);
1082  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1083  }
1084 
1085 
1086  if ((GetCommandFlags(cp.cmd) & CMD_SERVER) && ci->client_id != CLIENT_ID_SERVER) {
1087  IConsolePrint(CC_WARNING, "Kicking client #{} (IP: {}) due to calling a server only command {}.", ci->client_id, this->GetClientIP(), cp.cmd);
1088  return this->SendError(NETWORK_ERROR_KICKED);
1089  }
1090 
1092  IConsolePrint(CC_WARNING, "Kicking client #{} (IP: {}) due to calling a non-spectator command {}.", ci->client_id, this->GetClientIP(), cp.cmd);
1093  return this->SendError(NETWORK_ERROR_KICKED);
1094  }
1095 
1101  CompanyCtrlAction cca = cp.cmd == CMD_COMPANY_CTRL ? std::get<0>(EndianBufferReader::ToValue<CommandTraits<CMD_COMPANY_CTRL>::Args>(cp.data)) : CCA_NEW;
1102  if (!(cp.cmd == CMD_COMPANY_CTRL && cca == CCA_NEW && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) {
1103  IConsolePrint(CC_WARNING, "Kicking client #{} (IP: {}) due to calling a command as another company {}.",
1104  ci->client_playas + 1, this->GetClientIP(), cp.company + 1);
1105  return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
1106  }
1107 
1108  if (cp.cmd == CMD_COMPANY_CTRL) {
1109  if (cca != CCA_NEW || cp.company != COMPANY_SPECTATOR) {
1110  return this->SendError(NETWORK_ERROR_CHEATER);
1111  }
1112 
1113  /* Check if we are full - else it's possible for spectators to send a CMD_COMPANY_CTRL and the company is created regardless of max_companies! */
1115  NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_CLIENT, ci->client_id, "cannot create new company, server full", CLIENT_ID_SERVER);
1116  return NETWORK_RECV_STATUS_OKAY;
1117  }
1118  }
1119 
1120  if (cp.cmd == CMD_COMPANY_ALLOW_LIST_CTRL) {
1121  /* Maybe the client just got moved before allowing? */
1123 
1124  /* Only allow clients to add/remove currently joined clients. The server owner does not go via this method, so is allowed to do more. */
1125  std::string public_key = std::get<1>(EndianBufferReader::ToValue<CommandTraits<CMD_COMPANY_ALLOW_LIST_CTRL>::Args>(cp.data));
1126  bool found = false;
1128  if (info->public_key == public_key) {
1129  found = true;
1130  break;
1131  }
1132  }
1133 
1134  /* Maybe the client just left? */
1135  if (!found) return NETWORK_RECV_STATUS_OKAY;
1136  }
1137 
1139 
1140  this->incoming_queue.push_back(cp);
1141  return NETWORK_RECV_STATUS_OKAY;
1142 }
1143 
1145 {
1146  /* This packets means a client noticed an error and is reporting this
1147  * to us. Display the error and report it to the other clients */
1149 
1150  Debug(net, 9, "client[{}] Receive_CLIENT_ERROR(): errorno={}", this->client_id, errorno);
1151 
1152  /* The client was never joined.. thank the client for the packet, but ignore it */
1153  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1155  }
1156 
1157  std::string client_name = this->GetClientName();
1158  StringID strid = GetNetworkErrorMsg(errorno);
1159 
1160  Debug(net, 1, "'{}' reported an error and is closing its connection: {}", client_name, GetString(strid));
1161 
1162  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", strid);
1163 
1164  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
1165  if (new_cs->status >= STATUS_AUTHORIZED) {
1166  new_cs->SendErrorQuit(this->client_id, errorno);
1167  }
1168  }
1169 
1170  NetworkAdminClientError(this->client_id, errorno);
1171 
1173 }
1174 
1176 {
1177  /* The client was never joined.. thank the client for the packet, but ignore it */
1178  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1180  }
1181 
1182  Debug(net, 9, "client[{}] Receive_CLIENT_QUIT()", this->client_id);
1183 
1184  /* The client wants to leave. Display this and report it to the other clients. */
1185  std::string client_name = this->GetClientName();
1186  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", STR_NETWORK_MESSAGE_CLIENT_LEAVING);
1187 
1188  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
1189  if (new_cs->status >= STATUS_AUTHORIZED && new_cs != this) {
1190  new_cs->SendQuit(this->client_id);
1191  }
1192  }
1193 
1195 
1197 }
1198 
1200 {
1201  if (this->status < STATUS_AUTHORIZED) {
1202  /* Illegal call, return error and ignore the packet */
1203  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1204  }
1205 
1206  uint32_t frame = p.Recv_uint32();
1207 
1208  Debug(net, 9, "client[{}] Receive_CLIENT_ACK(): frame={}", this->client_id, frame);
1209 
1210  /* The client is trying to catch up with the server */
1211  if (this->status == STATUS_PRE_ACTIVE) {
1212  /* The client is not yet caught up? */
1214 
1215  /* Now it is! Unpause the game */
1216  Debug(net, 9, "client[{}] status = ACTIVE", this->client_id);
1217  this->status = STATUS_ACTIVE;
1219 
1220  /* Execute script for, e.g. MOTD */
1221  IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
1222  }
1223 
1224  /* Get, and validate the token. */
1225  uint8_t token = p.Recv_uint8();
1226  if (token == this->last_token) {
1227  /* We differentiate between last_token_frame and last_frame so the lag
1228  * test uses the actual lag of the client instead of the lag for getting
1229  * the token back and forth; after all, the token is only sent every
1230  * time we receive a PACKET_CLIENT_ACK, after which we will send a new
1231  * token to the client. If the lag would be one day, then we would not
1232  * be sending the new token soon enough for the new daily scheduled
1233  * PACKET_CLIENT_ACK. This would then register the lag of the client as
1234  * two days, even when it's only a single day. */
1236  /* Request a new token. */
1237  this->last_token = 0;
1238  }
1239 
1240  /* The client received the frame, make note of it */
1241  this->last_frame = frame;
1242  /* With those 2 values we can calculate the lag realtime */
1244  return NETWORK_RECV_STATUS_OKAY;
1245 }
1246 
1247 
1258 void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const std::string &msg, ClientID from_id, int64_t data, bool from_admin)
1259 {
1260  const NetworkClientInfo *ci, *ci_own, *ci_to;
1261 
1262  switch (desttype) {
1263  case DESTTYPE_CLIENT:
1264  /* Are we sending to the server? */
1265  if ((ClientID)dest == CLIENT_ID_SERVER) {
1266  ci = NetworkClientInfo::GetByClientID(from_id);
1267  /* Display the text locally, and that is it */
1268  if (ci != nullptr) {
1269  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1270 
1272  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1273  }
1274  }
1275  } else {
1276  /* Else find the client to send the message to */
1277  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1278  if (cs->client_id == (ClientID)dest && cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
1279  cs->SendChat(action, from_id, false, msg, data);
1280  break;
1281  }
1282  }
1283  }
1284 
1285  /* Display the message locally (so you know you have sent it) */
1286  if (from_id != (ClientID)dest) {
1287  if (from_id == CLIENT_ID_SERVER) {
1288  ci = NetworkClientInfo::GetByClientID(from_id);
1290  if (ci != nullptr && ci_to != nullptr) {
1291  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), true, ci_to->client_name, msg, data);
1292  }
1293  } else {
1294  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1295  if (cs->client_id == from_id && cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
1296  cs->SendChat(action, (ClientID)dest, true, msg, data);
1297  break;
1298  }
1299  }
1300  }
1301  }
1302  break;
1303  case DESTTYPE_TEAM: {
1304  /* If this is false, the message is already displayed on the client who sent it. */
1305  bool show_local = true;
1306  /* Find all clients that belong to this company */
1307  ci_to = nullptr;
1308  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1309  ci = cs->GetInfo();
1310  if (ci != nullptr && ci->client_playas == (CompanyID)dest && cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
1311  cs->SendChat(action, from_id, false, msg, data);
1312  if (cs->client_id == from_id) show_local = false;
1313  ci_to = ci; // Remember a client that is in the company for company-name
1314  }
1315  }
1316 
1317  /* if the server can read it, let the admin network read it, too. */
1319  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1320  }
1321 
1322  ci = NetworkClientInfo::GetByClientID(from_id);
1324  if (ci != nullptr && ci_own != nullptr && ci_own->client_playas == dest) {
1325  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1326  if (from_id == CLIENT_ID_SERVER) show_local = false;
1327  ci_to = ci_own;
1328  }
1329 
1330  /* There is no such client */
1331  if (ci_to == nullptr) break;
1332 
1333  /* Display the message locally (so you know you have sent it) */
1334  if (ci != nullptr && show_local) {
1335  if (from_id == CLIENT_ID_SERVER) {
1336  StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
1337  SetDParam(0, ci_to->client_playas);
1338  std::string name = GetString(str);
1339  NetworkTextMessage(action, GetDrawStringCompanyColour(ci_own->client_playas), true, name, msg, data);
1340  } else {
1341  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1342  if (cs->client_id == from_id && cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
1343  cs->SendChat(action, ci_to->client_id, true, msg, data);
1344  }
1345  }
1346  }
1347  }
1348  break;
1349  }
1350  default:
1351  Debug(net, 1, "Received unknown chat destination type {}; doing broadcast instead", desttype);
1352  [[fallthrough]];
1353 
1354  case DESTTYPE_BROADCAST:
1355  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1356  if (cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) cs->SendChat(action, from_id, false, msg, data);
1357  }
1358 
1359  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1360 
1361  ci = NetworkClientInfo::GetByClientID(from_id);
1362  if (ci != nullptr) {
1363  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data, "");
1364  }
1365  break;
1366  }
1367 }
1368 
1376 void NetworkServerSendExternalChat(const std::string &source, TextColour colour, const std::string &user, const std::string &msg)
1377 {
1378  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1379  if (cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) cs->SendExternalChat(source, colour, user, msg);
1380  }
1381  NetworkTextMessage(NETWORK_ACTION_EXTERNAL_CHAT, colour, false, user, msg, 0, source);
1382 }
1383 
1385 {
1386  if (this->status < STATUS_PRE_ACTIVE) {
1387  /* Illegal call, return error and ignore the packet */
1388  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1389  }
1390 
1391  NetworkAction action = (NetworkAction)p.Recv_uint8();
1392  DestType desttype = (DestType)p.Recv_uint8();
1393  int dest = p.Recv_uint32();
1394 
1395  Debug(net, 9, "client[{}] Receive_CLIENT_CHAT(): action={}, desttype={}, dest={}", this->client_id, action, desttype, dest);
1396 
1397  std::string msg = p.Recv_string(NETWORK_CHAT_LENGTH);
1398  int64_t data = p.Recv_uint64();
1399 
1400  NetworkClientInfo *ci = this->GetInfo();
1401  switch (action) {
1402  case NETWORK_ACTION_CHAT:
1403  case NETWORK_ACTION_CHAT_CLIENT:
1404  case NETWORK_ACTION_CHAT_COMPANY:
1405  NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data);
1406  break;
1407  default:
1408  IConsolePrint(CC_WARNING, "Kicking client #{} (IP: {}) due to unknown chact action.", ci->client_id, this->GetClientIP());
1409  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1410  }
1411  return NETWORK_RECV_STATUS_OKAY;
1412 }
1413 
1415 {
1416  if (this->status != STATUS_ACTIVE) {
1417  /* Illegal call, return error and ignore the packet */
1418  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1419  }
1420 
1421  Debug(net, 9, "client[{}] Receive_CLIENT_SET_NAME()", this->client_id);
1422 
1423  NetworkClientInfo *ci;
1424 
1425  std::string client_name = p.Recv_string(NETWORK_CLIENT_NAME_LENGTH);
1426  ci = this->GetInfo();
1427 
1428  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT;
1429 
1430  if (ci != nullptr) {
1431  if (!NetworkIsValidClientName(client_name)) {
1432  /* An invalid client name was given. However, the client ensures the name
1433  * is valid before it is sent over the network, so something went horribly
1434  * wrong. This is probably someone trying to troll us. */
1435  return this->SendError(NETWORK_ERROR_INVALID_CLIENT_NAME);
1436  }
1437 
1438  /* Display change */
1439  if (NetworkMakeClientNameUnique(client_name)) {
1440  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name);
1441  ci->client_name = client_name;
1443  }
1444  }
1445  return NETWORK_RECV_STATUS_OKAY;
1446 }
1447 
1449 {
1450  if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1451 
1452  Debug(net, 9, "client[{}] Receive_CLIENT_RCON()", this->client_id);
1453 
1454  std::string password = p.Recv_string(NETWORK_PASSWORD_LENGTH);
1455  std::string command = p.Recv_string(NETWORK_RCONCOMMAND_LENGTH);
1456 
1457  if (_rcon_authorized_key_handler.IsAllowed(this->peer_public_key)) {
1458  /* We are allowed, nothing more to validate. */
1459  } else if (_settings_client.network.rcon_password.empty()) {
1460  return NETWORK_RECV_STATUS_OKAY;
1461  } else if (_settings_client.network.rcon_password.compare(password) != 0) {
1462  Debug(net, 1, "[rcon] Wrong password from client-id {}", this->client_id);
1463  return NETWORK_RECV_STATUS_OKAY;
1464  }
1465 
1466  Debug(net, 3, "[rcon] Client-id {} executed: {}", this->client_id, command);
1467 
1469  IConsoleCmdExec(command);
1471  return NETWORK_RECV_STATUS_OKAY;
1472 }
1473 
1475 {
1476  if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1477 
1478  CompanyID company_id = (Owner)p.Recv_uint8();
1479 
1480  Debug(net, 9, "client[{}] Receive_CLIENT_MOVE(): company_id={}", this->client_id, company_id);
1481 
1482  /* Check if the company is valid, we don't allow moving to AI companies */
1483  if (company_id != COMPANY_SPECTATOR && !Company::IsValidHumanID(company_id)) return NETWORK_RECV_STATUS_OKAY;
1484 
1485  if (company_id != COMPANY_SPECTATOR && !Company::Get(company_id)->allow_list.Contains(this->peer_public_key)) {
1486  Debug(net, 2, "Wrong public key from client-id #{} for company #{}", this->client_id, company_id + 1);
1487  return NETWORK_RECV_STATUS_OKAY;
1488  }
1489 
1490  /* if we get here we can move the client */
1491  NetworkServerDoMove(this->client_id, company_id);
1492  return NETWORK_RECV_STATUS_OKAY;
1493 }
1494 
1500 {
1501  memset(stats, 0, sizeof(*stats) * MAX_COMPANIES);
1502 
1503  /* Go through all vehicles and count the type of vehicles */
1504  for (const Vehicle *v : Vehicle::Iterate()) {
1505  if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
1506  uint8_t type = 0;
1507  switch (v->type) {
1508  case VEH_TRAIN: type = NETWORK_VEH_TRAIN; break;
1509  case VEH_ROAD: type = RoadVehicle::From(v)->IsBus() ? NETWORK_VEH_BUS : NETWORK_VEH_LORRY; break;
1510  case VEH_AIRCRAFT: type = NETWORK_VEH_PLANE; break;
1511  case VEH_SHIP: type = NETWORK_VEH_SHIP; break;
1512  default: continue;
1513  }
1514  stats[v->owner].num_vehicle[type]++;
1515  }
1516 
1517  /* Go through all stations and count the types of stations */
1518  for (const Station *s : Station::Iterate()) {
1519  if (Company::IsValidID(s->owner)) {
1520  NetworkCompanyStats *npi = &stats[s->owner];
1521 
1522  if (s->facilities & FACIL_TRAIN) npi->num_station[NETWORK_VEH_TRAIN]++;
1523  if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[NETWORK_VEH_LORRY]++;
1524  if (s->facilities & FACIL_BUS_STOP) npi->num_station[NETWORK_VEH_BUS]++;
1525  if (s->facilities & FACIL_AIRPORT) npi->num_station[NETWORK_VEH_PLANE]++;
1526  if (s->facilities & FACIL_DOCK) npi->num_station[NETWORK_VEH_SHIP]++;
1527  }
1528  }
1529 }
1530 
1536 {
1538 
1539  if (ci == nullptr) return;
1540 
1541  Debug(desync, 1, "client: {:08x}; {:02x}; {:02x}; {:04x}", TimerGameEconomy::date, TimerGameEconomy::date_fract, (int)ci->client_playas, client_id);
1542 
1543  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1545  cs->SendClientInfo(ci);
1546  }
1547  }
1548 
1550 }
1551 
1558 {
1559  CompanyMask has_clients = 0;
1560  CompanyMask has_vehicles = 0;
1561 
1563 
1564  /* Detect the active companies */
1565  for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
1566  if (Company::IsValidID(ci->client_playas)) SetBit(has_clients, ci->client_playas);
1567  }
1568 
1569  if (!_network_dedicated) {
1571  assert(ci != nullptr);
1572  if (Company::IsValidID(ci->client_playas)) SetBit(has_clients, ci->client_playas);
1573  }
1574 
1576  for (const Company *c : Company::Iterate()) {
1577  if (std::any_of(std::begin(c->group_all), std::end(c->group_all), [](const GroupStatistics &gs) { return gs.num_vehicle != 0; })) SetBit(has_vehicles, c->index);
1578  }
1579  }
1580 
1581  /* Go through all the companies */
1582  for (Company *c : Company::Iterate()) {
1583  /* Skip the non-active once */
1584  if (c->is_ai) continue;
1585 
1586  if (!HasBit(has_clients, c->index)) {
1587  /* The company is empty for one month more */
1588  if (c->months_empty != std::numeric_limits<decltype(c->months_empty)>::max()) c->months_empty++;
1589 
1590  /* Is the company empty for autoclean_protected-months? */
1592  /* Shut the company down */
1594  IConsolePrint(CC_INFO, "Auto-cleaned company #{}.", c->index + 1);
1595  }
1596  /* Is the company empty for autoclean_novehicles-months, and has no vehicles? */
1597  if (_settings_client.network.autoclean_novehicles != 0 && c->months_empty > _settings_client.network.autoclean_novehicles && !HasBit(has_vehicles, c->index)) {
1598  /* Shut the company down */
1600  IConsolePrint(CC_INFO, "Auto-cleaned company #{} with no vehicles.", c->index + 1);
1601  }
1602  } else {
1603  /* It is not empty, reset the date */
1604  c->months_empty = 0;
1605  }
1606  }
1607 }
1608 
1614 bool NetworkMakeClientNameUnique(std::string &name)
1615 {
1616  bool is_name_unique = false;
1617  std::string original_name = name;
1618 
1619  for (uint number = 1; !is_name_unique && number <= MAX_CLIENTS; number++) { // Something's really wrong when there're more names than clients
1620  is_name_unique = true;
1621  for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
1622  if (ci->client_name == name) {
1623  /* Name already in use */
1624  is_name_unique = false;
1625  break;
1626  }
1627  }
1628  /* Check if it is the same as the server-name */
1630  if (ci != nullptr) {
1631  if (ci->client_name == name) is_name_unique = false; // name already in use
1632  }
1633 
1634  if (!is_name_unique) {
1635  /* Try a new name (<name> #1, <name> #2, and so on) */
1636  name = original_name + " #" + std::to_string(number);
1637 
1638  /* The constructed client name is larger than the limit,
1639  * so... bail out as no valid name can be created. */
1640  if (name.size() >= NETWORK_CLIENT_NAME_LENGTH) return false;
1641  }
1642  }
1643 
1644  return is_name_unique;
1645 }
1646 
1653 bool NetworkServerChangeClientName(ClientID client_id, const std::string &new_name)
1654 {
1655  /* Check if the name's already in use */
1657  if (ci->client_name.compare(new_name) == 0) return false;
1658  }
1659 
1661  if (ci == nullptr) return false;
1662 
1663  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, true, ci->client_name, new_name);
1664 
1665  ci->client_name = new_name;
1666 
1667  NetworkUpdateClientInfo(client_id);
1668  return true;
1669 }
1670 
1675 static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
1676 {
1677  for (auto &cp : cs->outgoing_queue) cs->SendCommand(cp);
1678  cs->outgoing_queue.clear();
1679 }
1680 
1685 void NetworkServer_Tick(bool send_frame)
1686 {
1687 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1688  bool send_sync = false;
1689 #endif
1690 
1691 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1694  send_sync = true;
1695  }
1696 #endif
1697 
1698  /* Now we are done with the frame, inform the clients that they can
1699  * do their frame! */
1700  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1701  /* We allow a number of bytes per frame, but only to the burst amount
1702  * to be available for packet receiving at any particular time. */
1703  cs->receive_limit = std::min<size_t>(cs->receive_limit + _settings_client.network.bytes_per_frame,
1705 
1706  /* Check if the speed of the client is what we can expect from a client */
1707  uint lag = NetworkCalculateLag(cs);
1708  switch (cs->status) {
1709  case NetworkClientSocket::STATUS_ACTIVE:
1711  /* Client did still not report in within the specified limit. */
1712 
1713  if (cs->last_packet + std::chrono::milliseconds(lag * MILLISECONDS_PER_TICK) > std::chrono::steady_clock::now()) {
1714  /* A packet was received in the last three game days, so the client is likely lagging behind. */
1715  IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because the client's game state is more than {} ticks behind.", cs->client_id, cs->GetClientIP(), lag);
1716  } else {
1717  /* No packet was received in the last three game days; sounds like a lost connection. */
1718  IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because the client did not respond for more than {} ticks.", cs->client_id, cs->GetClientIP(), lag);
1719  }
1720  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1721  continue;
1722  }
1723 
1724  /* Report once per time we detect the lag, and only when we
1725  * received a packet in the last 2 seconds. If we
1726  * did not receive a packet, then the client is not just
1727  * slow, but the connection is likely severed. Mentioning
1728  * frame_freq is not useful in this case. */
1729  if (lag > (uint)Ticks::DAY_TICKS && cs->lag_test == 0 && cs->last_packet + std::chrono::seconds(2) > std::chrono::steady_clock::now()) {
1730  IConsolePrint(CC_WARNING, "[{}] Client #{} is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id);
1731  cs->lag_test = 1;
1732  }
1733 
1734  if (cs->last_frame_server - cs->last_token_frame >= _settings_client.network.max_lag_time) {
1735  /* This is a bad client! It didn't send the right token back within time. */
1736  IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because it fails to send valid acks.", cs->client_id, cs->GetClientIP());
1737  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1738  continue;
1739  }
1740  break;
1741 
1742  case NetworkClientSocket::STATUS_INACTIVE:
1743  case NetworkClientSocket::STATUS_IDENTIFY:
1744  case NetworkClientSocket::STATUS_NEWGRFS_CHECK:
1745  case NetworkClientSocket::STATUS_AUTHORIZED:
1746  /* NewGRF check and authorized states should be handled almost instantly.
1747  * So give them some lee-way, likewise for the query with inactive. */
1749  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);
1750  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1751  continue;
1752  }
1753  break;
1754 
1755  case NetworkClientSocket::STATUS_MAP_WAIT:
1756  /* Send every two seconds a packet to the client, to make sure
1757  * it knows the server is still there; just someone else is
1758  * still receiving the map. */
1759  if (std::chrono::steady_clock::now() > cs->last_packet + std::chrono::seconds(2)) {
1760  cs->SendWait();
1761  /* We need to reset the timer, as otherwise we will be
1762  * spamming the client. Strictly speaking this variable
1763  * tracks when we last received a packet from the client,
1764  * but as it is waiting, it will not send us any till we
1765  * start sending them data. */
1766  cs->last_packet = std::chrono::steady_clock::now();
1767  }
1768  break;
1769 
1770  case NetworkClientSocket::STATUS_MAP:
1771  /* Downloading the map... this is the amount of time since starting the saving. */
1773  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);
1774  cs->SendError(NETWORK_ERROR_TIMEOUT_MAP);
1775  continue;
1776  }
1777  break;
1778 
1779  case NetworkClientSocket::STATUS_DONE_MAP:
1780  case NetworkClientSocket::STATUS_PRE_ACTIVE:
1781  /* The map has been sent, so this is for loading the map and syncing up. */
1783  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);
1784  cs->SendError(NETWORK_ERROR_TIMEOUT_JOIN);
1785  continue;
1786  }
1787  break;
1788 
1789  case NetworkClientSocket::STATUS_AUTH_GAME:
1790  /* These don't block? */
1792  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);
1793  cs->SendError(NETWORK_ERROR_TIMEOUT_PASSWORD);
1794  continue;
1795  }
1796  break;
1797 
1798  case NetworkClientSocket::STATUS_END:
1799  /* Bad server/code. */
1800  NOT_REACHED();
1801  }
1802 
1803  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) {
1804  /* Check if we can send command, and if we have anything in the queue */
1806 
1807  /* Send an updated _frame_counter_max to the client */
1808  if (send_frame) cs->SendFrame();
1809 
1810 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1811  /* Send a sync-check packet */
1812  if (send_sync) cs->SendSync();
1813 #endif
1814  }
1815  }
1816 }
1817 
1819 static void NetworkRestartMap()
1820 {
1823  case FT_SAVEGAME:
1824  case FT_SCENARIO:
1826  break;
1827 
1828  case FT_HEIGHTMAP:
1830  break;
1831 
1832  default:
1834  }
1835 }
1836 
1839 {
1840  if (!_network_server) return;
1841 
1842  /* If setting is 0, this feature is disabled. */
1843  if (_settings_client.network.restart_hours == 0) return;
1844 
1845  Debug(net, 3, "Auto-restarting map: {} hours played", _settings_client.network.restart_hours);
1847 });
1848 
1854 {
1855  if (!_network_server) return;
1856 
1858 }
1859 
1862 {
1863  /* If setting is 0, this feature is disabled. */
1864  if (_settings_client.network.restart_game_year == 0) return;
1865 
1867  Debug(net, 3, "Auto-restarting map: year {} reached", TimerGameCalendar::year);
1869  }
1870 }
1871 
1873 static IntervalTimer<TimerGameCalendar> _calendar_network_yearly({ TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE }, [](auto) {
1874  if (!_network_server) return;
1875 
1877 });
1878 
1880 static IntervalTimer<TimerGameEconomy> _economy_network_yearly({TimerGameEconomy::YEAR, TimerGameEconomy::Priority::NONE}, [](auto)
1881 {
1882  if (!_network_server) return;
1883 
1885 });
1886 
1888 static IntervalTimer<TimerGameEconomy> _network_quarterly({TimerGameEconomy::QUARTER, TimerGameEconomy::Priority::NONE}, [](auto)
1889 {
1890  if (!_network_server) return;
1891 
1894 });
1895 
1897 static IntervalTimer<TimerGameEconomy> _network_monthly({TimerGameEconomy::MONTH, TimerGameEconomy::Priority::NONE}, [](auto)
1898 {
1899  if (!_network_server) return;
1900 
1903 });
1904 
1906 static IntervalTimer<TimerGameEconomy> _network_weekly({TimerGameEconomy::WEEK, TimerGameEconomy::Priority::NONE}, [](auto)
1907 {
1908  if (!_network_server) return;
1909 
1911 });
1912 
1914 static IntervalTimer<TimerGameEconomy> _economy_network_daily({TimerGameEconomy::DAY, TimerGameEconomy::Priority::NONE}, [](auto)
1915 {
1916  if (!_network_server) return;
1917 
1919 });
1920 
1926 {
1927  return this->client_address.GetHostname();
1928 }
1929 
1932 {
1933  static const char * const stat_str[] = {
1934  "inactive",
1935  "authorizing",
1936  "identifing client",
1937  "checking NewGRFs",
1938  "authorized",
1939  "waiting",
1940  "loading map",
1941  "map done",
1942  "ready",
1943  "active"
1944  };
1945  static_assert(lengthof(stat_str) == NetworkClientSocket::STATUS_END);
1946 
1947  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1948  NetworkClientInfo *ci = cs->GetInfo();
1949  if (ci == nullptr) continue;
1950  uint lag = NetworkCalculateLag(cs);
1951  const char *status;
1952 
1953  status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
1954  IConsolePrint(CC_INFO, "Client #{} name: '{}' status: '{}' frame-lag: {} company: {} IP: {}",
1955  cs->client_id, ci->client_name, status, lag,
1956  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
1957  cs->GetClientIP());
1958  }
1959 }
1960 
1965 {
1966  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1967  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendConfigUpdate();
1968  }
1969 }
1970 
1973 {
1974  if (_network_server) FillStaticNetworkServerGameInfo();
1975 }
1976 
1983 void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
1984 {
1985  /* Only allow non-dedicated servers and normal clients to be moved */
1986  if (client_id == CLIENT_ID_SERVER && _network_dedicated) return;
1987 
1989  assert(ci != nullptr);
1990 
1991  /* No need to waste network resources if the client is in the company already! */
1992  if (ci->client_playas == company_id) return;
1993 
1994  ci->client_playas = company_id;
1995 
1996  if (client_id == CLIENT_ID_SERVER) {
1997  SetLocalCompany(company_id);
1998  } else {
1999  NetworkClientSocket *cs = NetworkClientSocket::GetByClientID(client_id);
2000  /* When the company isn't authorized we can't move them yet. */
2001  if (cs->status < NetworkClientSocket::STATUS_AUTHORIZED) return;
2002  cs->SendMove(client_id, company_id);
2003  }
2004 
2005  /* announce the client's move */
2006  NetworkUpdateClientInfo(client_id);
2007 
2008  NetworkAction action = (company_id == COMPANY_SPECTATOR) ? NETWORK_ACTION_COMPANY_SPECTATOR : NETWORK_ACTION_COMPANY_JOIN;
2009  NetworkServerSendChat(action, DESTTYPE_BROADCAST, 0, "", client_id, company_id + 1);
2010 
2012 }
2013 
2020 void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const std::string &string)
2021 {
2022  NetworkClientSocket::GetByClientID(client_id)->SendRConResult(colour_code, string);
2023 }
2024 
2030 void NetworkServerKickClient(ClientID client_id, const std::string &reason)
2031 {
2032  if (client_id == CLIENT_ID_SERVER) return;
2033  NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED, reason);
2034 }
2035 
2042 uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const std::string &reason)
2043 {
2044  return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban, reason);
2045 }
2046 
2053 uint NetworkServerKickOrBanIP(const std::string &ip, bool ban, const std::string &reason)
2054 {
2055  /* Add address to ban-list */
2056  if (ban) {
2057  bool contains = false;
2058  for (const auto &iter : _network_ban_list) {
2059  if (iter == ip) {
2060  contains = true;
2061  break;
2062  }
2063  }
2064  if (!contains) _network_ban_list.emplace_back(ip);
2065  }
2066 
2067  uint n = 0;
2068 
2069  /* There can be multiple clients with the same IP, kick them all but don't kill the server,
2070  * or the client doing the rcon. The latter can't be kicked because kicking frees closes
2071  * and subsequently free the connection related instances, which we would be reading from
2072  * and writing to after returning. So we would read or write data from freed memory up till
2073  * the segfault triggers. */
2074  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
2075  if (cs->client_id == CLIENT_ID_SERVER) continue;
2076  if (cs->client_id == _redirect_console_to_client) continue;
2077  if (cs->client_address.IsInNetmask(ip)) {
2078  NetworkServerKickClient(cs->client_id, reason);
2079  n++;
2080  }
2081  }
2082 
2083  return n;
2084 }
2085 
2092 {
2093  for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
2094  if (ci->client_playas == company) return true;
2095  }
2096  return false;
2097 }
2098 
2099 
2106 {
2107  const NetworkClientInfo *ci = this->GetInfo();
2108  if (ci != nullptr && !ci->client_name.empty()) return ci->client_name;
2109 
2110  return fmt::format("Client #{}", this->client_id);
2111 }
2112 
2117 {
2119  if (_network_server) {
2120  IConsolePrint(CC_INFO, "Client #{} name: '{}' company: {} IP: {}",
2121  ci->client_id,
2122  ci->client_name,
2123  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
2124  ci->client_id == CLIENT_ID_SERVER ? "server" : NetworkClientSocket::GetByClientID(ci->client_id)->GetClientIP());
2125  } else {
2126  IConsolePrint(CC_INFO, "Client #{} name: '{}' company: {}",
2127  ci->client_id,
2128  ci->client_name,
2129  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0));
2130  }
2131  }
2132 }
2133 
2139 std::string_view NetworkGetPublicKeyOfClient(ClientID client_id)
2140 {
2141  auto socket = NetworkClientSocket::GetByClientID(client_id);
2142  return socket == nullptr ? "" : socket->GetPeerPublicKey();
2143 }
2144 
2145 
2152 {
2153  assert(c != nullptr);
2154 
2155  if (!_network_server) return;
2156 
2157  if (ci != nullptr) {
2158  /* ci is nullptr when replaying, or for AIs. In neither case there is a client. */
2159  ci->client_playas = c->index;
2161 
2162  /*
2163  * This function is called from a command, but is only called for the server.
2164  * The client information is managed out-of-band from the commands, so to not have a
2165  * different state/president/company name in the different clients, we need to
2166  * circumvent the normal ::Post logic and go directly to sending the command.
2167  */
2170 
2171  NetworkServerSendChat(NETWORK_ACTION_COMPANY_NEW, DESTTYPE_BROADCAST, 0, "", ci->client_id, c->index + 1);
2172  }
2173 }
std::map< SOCKET, NetworkAddress > SocketList
Type for a mapping between address and socket.
Definition: address.h:21
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition: timer.h:76
const std::string & GetHostname()
Get the hostname; in case it wasn't given the IPv4 dotted representation is given.
Definition: address.cpp:23
Default implementation for the authorized key handler.
bool IsAllowed(std::string_view peer_public_key) const override
Check whether the given public key of the peer is allowed in.
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=~static_cast< NetworkAuthenticationMethodMask >(0))
Create a NetworkAuthenticationServerHandler.
@ RETRY_NEXT_METHOD
The client failed to authenticate, but there is another method to try.
@ AUTHENTICATED
The client was authenticated successfully.
@ NOT_AUTHENTICATED
All authentications for this handler have been exhausted.
Base socket handler for all TCP sockets.
Definition: tcp_game.h:141
uint32_t last_frame
Last frame we have executed.
Definition: tcp_game.h:487
ClientID client_id
Client identifier.
Definition: tcp_game.h:486
CommandQueue incoming_queue
The command-queue awaiting handling.
Definition: tcp_game.h:489
std::chrono::steady_clock::time_point last_packet
Time we received the last frame.
Definition: tcp_game.h:490
void SetInfo(NetworkClientInfo *info)
Sets the client info for this socket handler.
Definition: tcp_game.h:505
NetworkClientInfo * GetInfo() const
Gets the client info of this socket handler.
Definition: tcp_game.h:515
const char * ReceiveCommand(Packet &p, CommandPacket &cp)
Receives a command from the network.
uint32_t last_frame_server
Last frame the server has executed.
Definition: tcp_game.h:488
NetworkClientInfo * info
Client info related to this socket.
Definition: tcp_game.h:144
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:74
std::unique_ptr< class NetworkEncryptionHandler > send_encryption_handler
The handler for encrypting sent packets.
Definition: core.h:50
std::unique_ptr< class NetworkEncryptionHandler > receive_encryption_handler
The handler for decrypting received packets.
Definition: core.h:49
virtual std::unique_ptr< Packet > ReceivePacket()
Receives a packet for the given client.
Definition: tcp.cpp:129
SOCKET sock
The socket currently connected to.
Definition: tcp.h:38
virtual void SendPacket(std::unique_ptr< Packet > &&packet)
This function puts the packet in the send-queue and it is send as soon as possible.
Definition: tcp.cpp:68
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
Definition: tcp.cpp:86
Class for handling the server side of the game connection.
NetworkRecvStatus SendRConResult(uint16_t colour, const std::string &command)
Send the result of a console action.
NetworkRecvStatus Receive_CLIENT_SET_NAME(Packet &p) override
Gives the client a new name: string New name of the client.
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.
NetworkRecvStatus Receive_CLIENT_COMMAND(Packet &p) override
The client has done a command and wants us to handle it.
NetworkRecvStatus Receive_CLIENT_QUIT(Packet &p) override
The client is quitting the game.
const std::string & GetClientIP()
Get the IP address/hostname of the connected client.
NetworkRecvStatus SendWelcome()
Send the client a welcome message with some basic information.
NetworkRecvStatus SendAuthRequest()
Request the game password.
~ServerNetworkGameSocketHandler()
Clear everything related to this client.
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 SendChat(NetworkAction action, ClientID client_id, bool self_send, const std::string &msg, int64_t data)
Send a chat message.
NetworkRecvStatus SendGameInfo()
Send the client information about the server.
NetworkRecvStatus SendJoin(ClientID client_id)
Tell that a client joined.
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 SendExternalChat(const std::string &source, TextColour colour, const std::string &user, const std::string &msg)
Send a chat message from external source.
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 SendError(NetworkErrorCode error, const std::string &reason={})
Send an error to the client, and close its connection.
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.
@ 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 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)
static const char * GetName()
Get the name used by the listener.
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.
ServerNetworkGameSocketHandler(SOCKET s)
Create a new socket for the server side of the game 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.
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)
This function mask the parameter with CMD_ID_MASK and returns the flags which belongs to the given co...
Definition: command.cpp:118
@ CMD_COMPANY_CTRL
used in multiplayer to create a new companies etc.
Definition: command_type.h:300
@ CMD_COMPANY_ALLOW_LIST_CTRL
Used in multiplayer to add/remove a client's public key to/from the company's allow list.
Definition: command_type.h:301
@ CMD_SPECTATOR
the command may be initiated by a spectator
Definition: command_type.h:398
@ CMD_SERVER
the command can only be initiated by the server
Definition: command_type.h:397
@ CMD_CLIENT_ID
set p2 with the ClientID of the sending client.
Definition: command_type.h:404
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.
Definition: company_cmd.cpp:52
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...
CompanyCtrlAction
The action to do with CMD_COMPANY_CTRL.
Definition: company_type.h:67
@ CCA_DELETE
Delete a company.
Definition: company_type.h:70
@ CCA_NEW
Create a new company.
Definition: company_type.h:68
@ CALCA_ADD
Create a public key.
Definition: company_type.h:77
Owner
Enum for all companies/owners.
Definition: company_type.h:18
@ COMPANY_SPECTATOR
The client is spectating.
Definition: company_type.h:35
@ COMPANY_NEW_COMPANY
The client wants a new company.
Definition: company_type.h:34
@ MAX_COMPANIES
Maximum number of companies.
Definition: company_type.h:23
@ CRR_AUTOCLEAN
The company is removed due to autoclean.
Definition: company_type.h:58
static const size_t TCP_MTU
Number of bytes we can pack in a single TCP packet.
Definition: config.h:45
static const uint NETWORK_CLIENT_NAME_LENGTH
The maximum length of a client's name, in bytes including '\0'.
Definition: config.h:58
static const uint NETWORK_CHAT_LENGTH
The maximum length of a chat message, in bytes including '\0'.
Definition: config.h:61
static const uint NETWORK_REVISION_LENGTH
The maximum length of the revision, in bytes including '\0'.
Definition: config.h:56
static const uint NETWORK_RCONCOMMAND_LENGTH
The maximum length of a rconsole command, in bytes including '\0'.
Definition: config.h:59
static const uint NETWORK_PASSWORD_LENGTH
The maximum length of the password, in bytes including '\0'.
Definition: config.h:57
void IConsoleCmdExec(const std::string &command_string, const uint recurse_count)
Execute a given command passed to us.
Definition: console.cpp:291
void IConsolePrint(TextColour colour_code, const std::string &string)
Handle the printing of text entered into the console or redirected there by any other means.
Definition: console.cpp:89
static const TextColour CC_INFO
Colour for information lines.
Definition: console_type.h:27
static const TextColour CC_WARNING
Colour for warning lines.
Definition: console_type.h:25
static const TextColour CC_DEFAULT
Default colour of the console.
Definition: console_type.h:23
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
Definition: core.h:23
@ NETWORK_RECV_STATUS_CLIENT_QUIT
The connection is lost gracefully. Other clients are already informed of this leaving client.
Definition: core.h:28
@ NETWORK_RECV_STATUS_SERVER_ERROR
The server told us we made an error.
Definition: core.h:30
@ NETWORK_RECV_STATUS_OKAY
Everything is okay.
Definition: core.h:24
@ NETWORK_RECV_STATUS_MALFORMED_PACKET
We apparently send a malformed packet.
Definition: core.h:29
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
#define DECLARE_POSTFIX_INCREMENT(enum_type)
Some enums need to have allowed incrementing (i.e.
Definition: enum_type.hpp:18
@ FT_SCENARIO
old or new scenario
Definition: fileio_type.h:19
@ FT_HEIGHTMAP
heightmap file
Definition: fileio_type.h:20
@ FT_SAVEGAME
old or new savegame
Definition: fileio_type.h:18
static const uint32_t GENERATE_NEW_SEED
Create a new random seed.
Definition: genworld.h:24
SwitchMode _switch_mode
The next mainloop command.
Definition: gfx.cpp:49
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition: gfx_type.h:260
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
Definition: gfx_type.h:325
uint32_t _last_sync_frame
Used in the server to store the last time a sync packet was sent to clients.
Definition: network.cpp:79
StringID GetNetworkErrorMsg(NetworkErrorCode err)
Retrieve the string id of an internal error number.
Definition: network.cpp:313
ClientID _redirect_console_to_client
If not invalid, redirect the console output to a client.
Definition: network.cpp:71
uint32_t _frame_counter
The current frame.
Definition: network.cpp:78
StringList _network_ban_list
The banned clients.
Definition: network.cpp:75
bool _network_dedicated
are we a dedicated server?
Definition: network.cpp:68
bool _network_server
network-server is active
Definition: network.cpp:66
uint32_t _sync_seed_1
Seed to compare during sync checks.
Definition: network.cpp:81
uint8_t _network_clients_connected
The amount of clients connected.
Definition: network.cpp:89
uint32_t _frame_counter_max
To where we may go with our clients.
Definition: network.cpp:77
void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
Notify the admin network of a client update (if they did opt in for the respective update).
void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const std::string &msg, int64_t data, bool from_admin)
Send chat to the admin network (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 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(const 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.
static void NetworkReplaceCommandClientId(CommandPacket &cp, ClientID client_id)
Insert a client ID into the command data in a command packet.
NetworkAuthenticationMethod
The authentication method that can be used.
@ NETWORK_AUTH_METHOD_X25519_PAKE
Authentication using x25519 password-authenticated key agreement.
@ NETWORK_AUTH_METHOD_X25519_AUTHORIZED_KEY
Authentication using x22519 key exchange and authorized keys.
static IntervalTimer< TimerGameEconomy > _economy_network_yearly({TimerGameEconomy::YEAR, TimerGameEconomy::Priority::NONE}, [](auto) { if(!_network_server) return;NetworkAdminUpdate(ADMIN_FREQUENCY_ANUALLY);})
Economy yearly "callback".
bool NetworkServerChangeClientName(ClientID client_id, const std::string &new_name)
Change the client name of the given client.
static IntervalTimer< TimerGameEconomy > _economy_network_daily({TimerGameEconomy::DAY, TimerGameEconomy::Priority::NONE}, [](auto) { if(!_network_server) return;NetworkAdminUpdate(ADMIN_FREQUENCY_DAILY);})
Daily "callback".
void NetworkPrintClients()
Print all the clients to the console.
void NetworkServerUpdateGameInfo()
Update the server's NetworkServerGameInfo due to changes in settings.
void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const std::string &string)
Send an rcon reply to the client.
void NetworkUpdateClientInfo(ClientID client_id)
Send updated client info of a particular client.
static NetworkAuthenticationDefaultAuthorizedKeyHandler _rcon_authorized_key_handler(_settings_client.network.rcon_authorized_keys)
Provides the authorized key validation for rcon.
static IntervalTimer< TimerGameEconomy > _network_weekly({TimerGameEconomy::WEEK, TimerGameEconomy::Priority::NONE}, [](auto) { if(!_network_server) return;NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY);})
Economy weekly "callback".
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const std::string &reason)
Ban, or kick, everyone joined from the given client's IP.
static NetworkAuthenticationDefaultPasswordProvider _password_provider(_settings_client.network.server_password)
Provides the password validation for the game's password.
void NetworkPopulateCompanyStats(NetworkCompanyStats *stats)
Populate the company stats.
static IntervalTimer< TimerGameEconomy > _network_monthly({TimerGameEconomy::MONTH, TimerGameEconomy::Priority::NONE}, [](auto) { if(!_network_server) return;NetworkAutoCleanCompanies();NetworkAdminUpdate(ADMIN_FREQUENCY_MONTHLY);})
Economy monthly "callback".
void NetworkServerSendConfigUpdate()
Send Config Update.
void NetworkServerKickClient(ClientID client_id, const std::string &reason)
Kick a single client.
void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
Handle the tid-bits of moving a client from one company to another.
static IntervalTimer< TimerGameCalendar > _calendar_network_yearly({ TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE }, [](auto) { if(!_network_server) return;NetworkCheckRestartMapYear();})
Calendar yearly "callback".
static IntervalTimer< TimerGameEconomy > _network_quarterly({TimerGameEconomy::QUARTER, TimerGameEconomy::Priority::NONE}, [](auto) { if(!_network_server) return;NetworkAutoCleanCompanies();NetworkAdminUpdate(ADMIN_FREQUENCY_QUARTERLY);})
Quarterly "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.
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 NetworkAuthenticationDefaultAuthorizedKeyHandler _authorized_key_handler(_settings_client.network.server_authorized_keys)
Provides the authorized key handling for the game authentication.
static IntervalTimer< TimerGameRealtime > _network_restart_map_timer({std::chrono::hours::zero(), TimerGameRealtime::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.
static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
Handle the command-queue of a socket.
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 NetworkServerSendExternalChat(const std::string &source, TextColour colour, const std::string &user, const std::string &msg)
Send a chat message from external source.
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 ...
void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const std::string &msg, ClientID from_id, int64_t data, bool from_admin)
Send an actual chat message.
Server part of the network protocol.
DestType
Destination of our chat messages.
Definition: network_type.h:79
@ DESTTYPE_CLIENT
Send message/notice to only a certain client (Private)
Definition: network_type.h:82
@ DESTTYPE_TEAM
Send message/notice to everyone playing the same company (Team)
Definition: network_type.h:81
@ DESTTYPE_BROADCAST
Send message/notice to all clients (All)
Definition: network_type.h:80
static const uint MAX_CLIENT_SLOTS
The number of slots; must be at least 1 more than MAX_CLIENTS.
Definition: network_type.h:23
static const uint MAX_CLIENTS
How many clients can we have.
Definition: network_type.h:16
NetworkAction
Actions that can be used for NetworkTextMessage.
Definition: network_type.h:90
ClientID
'Unique' identifier to be given to clients
Definition: network_type.h:49
@ INVALID_CLIENT_ID
Client is not part of anything.
Definition: network_type.h:50
@ CLIENT_ID_SERVER
Servers always have this ID.
Definition: network_type.h:51
@ CLIENT_ID_FIRST
The first client ID.
Definition: network_type.h:52
NetworkErrorCode
The error codes we send around in the protocols.
Definition: network_type.h:110
Sending and receiving UDP messages.
GRFConfig * _grfconfig
First item in list of current GRF set up.
@ GCF_STATIC
GRF file is used statically (can be used in any MP game)
Definition: newgrf_config.h:24
@ 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
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Definition: pool_func.hpp:237
void SlError(StringID string, const std::string &extra_msg)
Error handler.
Definition: saveload.cpp:321
SaveOrLoadResult SaveWithFilter(std::shared_ptr< SaveFilter > writer, bool threaded)
Save the game using a (writer) filter.
Definition: saveload.cpp:2917
FileToSaveLoad _file_to_saveload
File to save or load in the openttd loop.
Definition: saveload.cpp:60
@ SL_OK
completed successfully
Definition: saveload.h:402
GameSettings _settings_newgame
Game settings for new games (updated from the intro screen).
Definition: settings.cpp:58
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:56
@ FACIL_DOCK
Station with a dock.
Definition: station_type.h:58
@ FACIL_BUS_STOP
Station with bus stops.
Definition: station_type.h:56
@ FACIL_AIRPORT
Station with an airport.
Definition: station_type.h:57
@ FACIL_TRUCK_STOP
Station with truck stops.
Definition: station_type.h:55
@ FACIL_TRAIN
Station with train station.
Definition: station_type.h:54
#define lengthof(array)
Return the length of an fixed size array.
Definition: stdafx.h:280
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings.cpp:104
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Definition: strings.cpp:319
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
NetworkSettings network
settings related to the network
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.
Definition: command_type.h:453
uint8_t months_empty
NOSAVE: Number of months this company has not had a client in multiplayer.
Definition: company_base.h:97
static bool IsValidHumanID(size_t index)
Is this company a valid company, not controlled by a NoAI program?
Definition: company_base.h:171
AbstractFileType abstract_ftype
Abstract type of file (scenario, heightmap, etc).
Definition: saveload.h:411
Information about GRF, used in the game and (part of it) in savegames.
uint8_t flags
NOSAVE: GCF_Flags, bitset.
struct GRFConfig * next
NOSAVE: Next item in the linked list.
GRFIdentifier ident
grfid and md5sum to uniquely identify newgrfs
uint32_t generation_seed
noise seed for world generation
GameCreationSettings game_creation
settings used during the creation of a game (map)
Statistics and caches on the vehicles in a group.
Definition: group.h:24
Container for all information known about a client.
Definition: network_base.h:24
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it's client-identifier.
Definition: network.cpp:116
TimerGameEconomy::Date join_date
Gamedate the client has joined.
Definition: network_base.h:29
CompanyID client_playas
As which company is this client playing (CompanyID)
Definition: network_base.h:28
ClientID client_id
Client identifier (same as ClientState->client_id)
Definition: network_base.h:25
std::string client_name
Name of the client.
Definition: network_base.h:26
std::string public_key
The public key of the client.
Definition: network_base.h:27
Simple calculated statistics of a company.
Definition: network_type.h:67
uint16_t num_vehicle[NETWORK_VEH_END]
How many vehicles are there of this type?
Definition: network_type.h:68
uint16_t num_station[NETWORK_VEH_END]
How many stations are there of this type?
Definition: network_type.h:69
uint8_t clients_on
Current count of clients on server.
uint8_t max_clients
maximum amount of clients
uint16_t bytes_per_frame_burst
how many bytes may, over a short period, be received?
bool autoclean_companies
automatically remove companies that are not in use
bool server_admin_chat
allow private chat for the server to be distributed to the admin network
TimerGameCalendar::Year restart_game_year
year the server restarts
uint8_t max_companies
maximum amount of companies
uint8_t autoclean_protected
Remove companies after this many months.
uint16_t max_password_time
maximum amount of time, in game ticks, a client may take to enter the password
uint16_t max_join_time
maximum amount of time, in game ticks, a client may take to sync up during joining
uint16_t bytes_per_frame
how many bytes may, over a long period, be received per frame?
uint16_t max_init_time
maximum amount of time, in game ticks, a client may take to initiate joining
uint16_t max_lag_time
maximum amount of time, in game ticks, a client may be lagging behind the server
uint8_t autoclean_novehicles
remove companies with no vehicles after this many months
uint16_t max_commands_in_queue
how many commands may there be in the incoming queue before dropping the connection?
std::string server_name
name of the server
uint16_t restart_hours
number of hours to run the server before automatic restart
uint16_t max_download_time
maximum amount of time, in game ticks, a client may take to download the map
uint16_t sync_freq
how often do we check whether we are still in-sync
std::string rcon_password
password for rconsole (server side)
static void ResetUser(uint32_t user)
Reset an user's OrderBackup if needed.
Writing a savegame directly to a number of packets.
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.
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.
~PacketWriter()
Make sure everything is cleaned up.
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...
Internal entity of a packet.
Definition: packet.h:42
uint64_t Recv_uint64()
Read a 64 bits integer from the packet.
Definition: packet.cpp:364
uint32_t Recv_uint32()
Read a 32 bits integer from the packet.
Definition: packet.cpp:347
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:318
std::string Recv_string(size_t length, StringValidationSettings settings=SVS_REPLACE_WITH_QUESTION_MARK)
Reads characters (bytes) from the packet until it finds a '\0', or reaches a maximum of length charac...
Definition: packet.cpp:425
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:369
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:328
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition: pool_type.hpp:309
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:350
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
Base class for all pools.
Definition: pool_type.hpp:80
static constexpr size_t MAX_SIZE
Make template parameter accessible from outside.
Definition: pool_type.hpp:84
Interface for filtering a savegame till it is written.
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
Returns an iterable ensemble of all valid stations of type T.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Station data structure.
Definition: station_base.h:439
Vehicle data structure.
Definition: vehicle_base.h:244
@ SPS_CLOSED
The connection got closed.
Definition: tcp.h:24
@ ADMIN_FREQUENCY_MONTHLY
The admin gets information about this on a monthly basis.
Definition: tcp_admin.h:100
@ ADMIN_FREQUENCY_QUARTERLY
The admin gets information about this on a quarterly basis.
Definition: tcp_admin.h:101
@ ADMIN_FREQUENCY_ANUALLY
The admin gets information about this on a yearly basis.
Definition: tcp_admin.h:102
@ ADMIN_FREQUENCY_WEEKLY
The admin gets information about this on a weekly basis.
Definition: tcp_admin.h:99
@ ADMIN_FREQUENCY_DAILY
The admin gets information about this on a daily basis.
Definition: tcp_admin.h:98
@ PACKET_SERVER_JOIN
Tells clients that a new client has joined.
Definition: tcp_game.h:87
@ PACKET_SERVER_MAP_SIZE
Server tells the client what the (compressed) size of the map is.
Definition: tcp_game.h:82
@ PACKET_SERVER_RCON
Response of the executed command on the server.
Definition: tcp_game.h:111
@ PACKET_SERVER_MAP_BEGIN
Server tells the client that it is beginning to send the map.
Definition: tcp_game.h:81
@ PACKET_SERVER_SYNC
Server tells the client what the random state should be.
Definition: tcp_game.h:98
@ PACKET_SERVER_WAIT
Server tells the client there are some people waiting for the map as well.
Definition: tcp_game.h:80
@ PACKET_SERVER_CONFIG_UPDATE
Some network configuration important to the client changed.
Definition: tcp_game.h:119
@ PACKET_SERVER_ENABLE_ENCRYPTION
The server tells that authentication has completed and requests to enable encryption with the keys of...
Definition: tcp_game.h:65
@ PACKET_SERVER_GAME_INFO
Information about the server.
Definition: tcp_game.h:45
@ PACKET_SERVER_ERROR_QUIT
A server tells that a client has hit an error and did quit.
Definition: tcp_game.h:125
@ PACKET_SERVER_CLIENT_INFO
Server sends you information about a client.
Definition: tcp_game.h:76
@ PACKET_SERVER_WELCOME
Server welcomes you and gives you your ClientID.
Definition: tcp_game.h:75
@ PACKET_SERVER_BANNED
The server has banned you.
Definition: tcp_game.h:34
@ PACKET_SERVER_FRAME
Server tells the client what frame it is in, and thus to where the client may progress.
Definition: tcp_game.h:96
@ PACKET_SERVER_EXTERNAL_CHAT
Server distributing the message from external source.
Definition: tcp_game.h:107
@ PACKET_SERVER_CHAT
Server distributing the message of a client (or itself).
Definition: tcp_game.h:106
@ PACKET_SERVER_COMMAND
Server distributes a command to (all) the clients.
Definition: tcp_game.h:102
@ PACKET_SERVER_SHUTDOWN
The server is shutting down.
Definition: tcp_game.h:50
@ PACKET_SERVER_AUTH_REQUEST
The server requests the client to authenticate using a number of methods.
Definition: tcp_game.h:63
@ PACKET_SERVER_NEWGAME
The server is preparing to start a new game.
Definition: tcp_game.h:49
@ PACKET_SERVER_MOVE
Server tells everyone that someone is moved to another company.
Definition: tcp_game.h:115
@ PACKET_SERVER_MAP_DATA
Server sends bits of the map to the client.
Definition: tcp_game.h:83
@ PACKET_SERVER_FULL
The server is full and has no place for you.
Definition: tcp_game.h:33
@ PACKET_SERVER_QUIT
A server tells that a client has quit.
Definition: tcp_game.h:123
@ PACKET_SERVER_ERROR
Server sending an error message to the client.
Definition: tcp_game.h:38
@ PACKET_SERVER_CHECK_NEWGRFS
Server sends NewGRF IDs and MD5 checksums for the client to check.
Definition: tcp_game.h:71
@ PACKET_SERVER_MAP_DONE
Server tells it has just sent the last bits of the map to the client.
Definition: tcp_game.h:84
@ VEH_ROAD
Road vehicle type.
Definition: vehicle_type.h:25
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition: vehicle_type.h:27
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
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:3211
@ WC_CLIENT_LIST
Client list; Window numbers:
Definition: window_type.h:484