OpenTTD
network_server.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "../stdafx.h"
13 #include "../strings_func.h"
14 #include "../date_func.h"
15 #include "network_admin.h"
16 #include "network_server.h"
17 #include "network_udp.h"
18 #include "network_base.h"
19 #include "../console_func.h"
20 #include "../company_base.h"
21 #include "../command_func.h"
22 #include "../saveload/saveload.h"
23 #include "../saveload/saveload_filter.h"
24 #include "../station_base.h"
25 #include "../genworld.h"
26 #include "../company_func.h"
27 #include "../company_gui.h"
28 #include "../roadveh.h"
29 #include "../order_backup.h"
30 #include "../core/pool_func.hpp"
31 #include "../core/random_func.hpp"
32 #include "../rev.h"
33 #include <mutex>
34 #include <condition_variable>
35 
36 #include "../safeguards.h"
37 
38 
39 /* This file handles all the server-commands */
40 
44 
49 
52 INSTANTIATE_POOL_METHODS(NetworkClientSocket)
53 
56 
59  ServerNetworkGameSocketHandler *cs;
61  size_t total_size;
63  std::mutex mutex;
64  std::condition_variable exit_sig;
65 
70  PacketWriter(ServerNetworkGameSocketHandler *cs) : SaveFilter(nullptr), cs(cs), current(nullptr), total_size(0), packets(nullptr)
71  {
72  }
73 
76  {
77  std::unique_lock<std::mutex> lock(this->mutex);
78 
79  if (this->cs != nullptr) this->exit_sig.wait(lock);
80 
81  /* This must all wait until the Destroy function is called. */
82 
83  while (this->packets != nullptr) {
84  Packet *p = this->packets->next;
85  delete this->packets;
86  this->packets = p;
87  }
88 
89  delete this->current;
90  }
91 
102  void Destroy()
103  {
104  std::unique_lock<std::mutex> lock(this->mutex);
105 
106  this->cs = nullptr;
107 
108  this->exit_sig.notify_all();
109  lock.unlock();
110 
111  /* Make sure the saving is completely cancelled. Yes,
112  * we need to handle the save finish as well as the
113  * next connection might just be requesting a map. */
114  WaitTillSaved();
116  }
117 
125  bool HasPackets()
126  {
127  return this->packets != nullptr;
128  }
129 
134  {
135  std::lock_guard<std::mutex> lock(this->mutex);
136 
137  Packet *p = this->packets;
138  this->packets = p->next;
139  p->next = nullptr;
140 
141  return p;
142  }
143 
145  void AppendQueue()
146  {
147  if (this->current == nullptr) return;
148 
149  Packet **p = &this->packets;
150  while (*p != nullptr) {
151  p = &(*p)->next;
152  }
153  *p = this->current;
154 
155  this->current = nullptr;
156  }
157 
158  void Write(byte *buf, size_t size) override
159  {
160  /* We want to abort the saving when the socket is closed. */
161  if (this->cs == nullptr) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
162 
163  if (this->current == nullptr) this->current = new Packet(PACKET_SERVER_MAP_DATA);
164 
165  std::lock_guard<std::mutex> lock(this->mutex);
166 
167  byte *bufe = buf + size;
168  while (buf != bufe) {
169  size_t to_write = min(SEND_MTU - this->current->size, bufe - buf);
170  memcpy(this->current->buffer + this->current->size, buf, to_write);
171  this->current->size += (PacketSize)to_write;
172  buf += to_write;
173 
174  if (this->current->size == SEND_MTU) {
175  this->AppendQueue();
176  if (buf != bufe) this->current = new Packet(PACKET_SERVER_MAP_DATA);
177  }
178  }
179 
180  this->total_size += size;
181  }
182 
183  void Finish() override
184  {
185  /* We want to abort the saving when the socket is closed. */
186  if (this->cs == nullptr) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
187 
188  std::lock_guard<std::mutex> lock(this->mutex);
189 
190  /* Make sure the last packet is flushed. */
191  this->AppendQueue();
192 
193  /* Add a packet stating that this is the end to the queue. */
194  this->current = new Packet(PACKET_SERVER_MAP_DONE);
195  this->AppendQueue();
196 
197  /* Fast-track the size to the client. */
199  p->Send_uint32((uint32)this->total_size);
200  this->cs->NetworkTCPSocketHandler::SendPacket(p);
201  }
202 };
203 
204 
210 {
211  this->status = STATUS_INACTIVE;
212  this->client_id = _network_client_id++;
214 
215  /* The Socket and Info pools need to be the same in size. After all,
216  * each Socket will be associated with at most one Info object. As
217  * such if the Socket was allocated the Info object can as well. */
219 }
220 
225 {
228 
229  if (this->savegame != nullptr) {
230  this->savegame->Destroy();
231  this->savegame = nullptr;
232  }
233 }
234 
236 {
237  /* Only allow receiving when we have some buffer free; this value
238  * can go negative, but eventually it will become positive again. */
239  if (this->receive_limit <= 0) return nullptr;
240 
241  /* We can receive a packet, so try that and if needed account for
242  * the amount of received data. */
244  if (p != nullptr) this->receive_limit -= p->size;
245  return p;
246 }
247 
249 {
250  assert(status != NETWORK_RECV_STATUS_OKAY);
251  /*
252  * Sending a message just before leaving the game calls cs->SendPackets.
253  * This might invoke this function, which means that when we close the
254  * connection after cs->SendPackets we will close an already closed
255  * connection. This handles that case gracefully without having to make
256  * that code any more complex or more aware of the validity of the socket.
257  */
258  if (this->sock == INVALID_SOCKET) return status;
259 
260  if (status != NETWORK_RECV_STATUS_CONN_LOST && !this->HasClientQuit() && this->status >= STATUS_AUTHORIZED) {
261  /* We did not receive a leave message from this client... */
262  char client_name[NETWORK_CLIENT_NAME_LENGTH];
263  NetworkClientSocket *new_cs;
264 
265  this->GetClientName(client_name, lastof(client_name));
266 
267  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST);
268 
269  /* Inform other clients of this... strange leaving ;) */
270  FOR_ALL_CLIENT_SOCKETS(new_cs) {
271  if (new_cs->status > STATUS_AUTHORIZED && this != new_cs) {
272  new_cs->SendErrorQuit(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
273  }
274  }
275  }
276 
277  NetworkAdminClientError(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
278  DEBUG(net, 1, "Closed client connection %d", this->client_id);
279 
280  /* We just lost one client :( */
281  if (this->status >= STATUS_AUTHORIZED) _network_game_info.clients_on--;
282  extern byte _network_clients_connected;
283  _network_clients_connected--;
284 
287 
288  this->SendPackets(true);
289 
290  delete this->GetInfo();
291  delete this;
292 
293  return status;
294 }
295 
301 {
302  extern byte _network_clients_connected;
303  bool accept = _network_clients_connected < MAX_CLIENTS && _network_game_info.clients_on < _settings_client.network.max_clients;
304 
305  /* We can't go over the MAX_CLIENTS limit here. However, the
306  * pool must have place for all clients and ourself. */
309  return accept;
310 }
311 
314 {
315  NetworkClientSocket *cs;
317  if (cs->writable) {
318  if (cs->SendPackets() != SPS_CLOSED && cs->status == STATUS_MAP) {
319  /* This client is in the middle of a map-send, call the function for that */
320  cs->SendMap();
321  }
322  }
323  }
324 }
325 
326 static void NetworkHandleCommandQueue(NetworkClientSocket *cs);
327 
328 /***********
329  * Sending functions
330  * DEF_SERVER_SEND_COMMAND has parameter: NetworkClientSocket *cs
331  ************/
332 
338 {
339  if (ci->client_id != INVALID_CLIENT_ID) {
341  p->Send_uint32(ci->client_id);
342  p->Send_uint8 (ci->client_playas);
343  p->Send_string(ci->client_name);
344 
345  this->SendPacket(p);
346  }
348 }
349 
352 {
353  /* Fetch the latest version of the stats */
354  NetworkCompanyStats company_stats[MAX_COMPANIES];
355  NetworkPopulateCompanyStats(company_stats);
356 
357  /* Make a list of all clients per company */
358  char clients[MAX_COMPANIES][NETWORK_CLIENTS_LENGTH];
359  NetworkClientSocket *csi;
360  memset(clients, 0, sizeof(clients));
361 
362  /* Add the local player (if not dedicated) */
364  if (ci != nullptr && Company::IsValidID(ci->client_playas)) {
365  strecpy(clients[ci->client_playas], ci->client_name, lastof(clients[ci->client_playas]));
366  }
367 
369  char client_name[NETWORK_CLIENT_NAME_LENGTH];
370 
371  ((ServerNetworkGameSocketHandler*)csi)->GetClientName(client_name, lastof(client_name));
372 
373  ci = csi->GetInfo();
374  if (ci != nullptr && Company::IsValidID(ci->client_playas)) {
375  if (!StrEmpty(clients[ci->client_playas])) {
376  strecat(clients[ci->client_playas], ", ", lastof(clients[ci->client_playas]));
377  }
378 
379  strecat(clients[ci->client_playas], client_name, lastof(clients[ci->client_playas]));
380  }
381  }
382 
383  /* Now send the data */
384 
385  Company *company;
386  Packet *p;
387 
388  FOR_ALL_COMPANIES(company) {
390 
392  p->Send_bool (true);
393  this->SendCompanyInformation(p, company, &company_stats[company->index]);
394 
395  if (StrEmpty(clients[company->index])) {
396  p->Send_string("<none>");
397  } else {
398  p->Send_string(clients[company->index]);
399  }
400 
401  this->SendPacket(p);
402  }
403 
405 
407  p->Send_bool (false);
408 
409  this->SendPacket(p);
411 }
412 
418 {
419  char str[100];
421 
422  p->Send_uint8(error);
423  this->SendPacket(p);
424 
425  StringID strid = GetNetworkErrorMsg(error);
426  GetString(str, strid, lastof(str));
427 
428  /* Only send when the current client was in game */
429  if (this->status > STATUS_AUTHORIZED) {
430  NetworkClientSocket *new_cs;
431  char client_name[NETWORK_CLIENT_NAME_LENGTH];
432 
433  this->GetClientName(client_name, lastof(client_name));
434 
435  DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
436 
437  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid);
438 
439  FOR_ALL_CLIENT_SOCKETS(new_cs) {
440  if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
441  /* Some errors we filter to a more general error. Clients don't have to know the real
442  * reason a joining failed. */
443  if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION) {
444  error = NETWORK_ERROR_ILLEGAL_PACKET;
445  }
446  new_cs->SendErrorQuit(this->client_id, error);
447  }
448  }
449 
450  NetworkAdminClientError(this->client_id, error);
451  } else {
452  DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", this->client_id, str);
453  }
454 
455  /* The client made a mistake, so drop his connection now! */
457 }
458 
461 {
463  const GRFConfig *c;
464  uint grf_count = 0;
465 
466  for (c = _grfconfig; c != nullptr; c = c->next) {
467  if (!HasBit(c->flags, GCF_STATIC)) grf_count++;
468  }
469 
470  p->Send_uint8 (grf_count);
471  for (c = _grfconfig; c != nullptr; c = c->next) {
472  if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident);
473  }
474 
475  this->SendPacket(p);
477 }
478 
481 {
482  /* Invalid packet when status is STATUS_AUTH_GAME or higher */
484 
485  this->status = STATUS_AUTH_GAME;
486  /* Reset 'lag' counters */
488 
490  this->SendPacket(p);
492 }
493 
496 {
497  /* Invalid packet when status is STATUS_AUTH_COMPANY or higher */
499 
500  this->status = STATUS_AUTH_COMPANY;
501  /* Reset 'lag' counters */
503 
507  this->SendPacket(p);
509 }
510 
513 {
514  Packet *p;
515  NetworkClientSocket *new_cs;
516 
517  /* Invalid packet when status is AUTH or higher */
519 
520  this->status = STATUS_AUTHORIZED;
521  /* Reset 'lag' counters */
523 
525 
526  p = new Packet(PACKET_SERVER_WELCOME);
527  p->Send_uint32(this->client_id);
530  this->SendPacket(p);
531 
532  /* Transmit info about all the active clients */
533  FOR_ALL_CLIENT_SOCKETS(new_cs) {
534  if (new_cs != this && new_cs->status > STATUS_AUTHORIZED) {
535  this->SendClientInfo(new_cs->GetInfo());
536  }
537  }
538  /* Also send the info of the server */
540 }
541 
544 {
545  int waiting = 0;
546  NetworkClientSocket *new_cs;
547  Packet *p;
548 
549  /* Count how many clients are waiting in the queue, in front of you! */
550  FOR_ALL_CLIENT_SOCKETS(new_cs) {
551  if (new_cs->status != STATUS_MAP_WAIT) continue;
552  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++;
553  }
554 
555  p = new Packet(PACKET_SERVER_WAIT);
556  p->Send_uint8(waiting);
557  this->SendPacket(p);
559 }
560 
563 {
564  static uint sent_packets; // How many packets we did send successfully last time
565 
566  if (this->status < STATUS_AUTHORIZED) {
567  /* Illegal call, return error and ignore the packet */
568  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
569  }
570 
571  if (this->status == STATUS_AUTHORIZED) {
572  this->savegame = new PacketWriter(this);
573 
574  /* Now send the _frame_counter and how many packets are coming */
577  this->SendPacket(p);
578 
580  this->status = STATUS_MAP;
581  /* Mark the start of download */
582  this->last_frame = _frame_counter;
584 
585  sent_packets = 4; // We start with trying 4 packets
586 
587  /* Make a dump of the current game */
588  if (SaveWithFilter(this->savegame, true) != SL_OK) usererror("network savedump failed");
589  }
590 
591  if (this->status == STATUS_MAP) {
592  bool last_packet = false;
593  bool has_packets = false;
594 
595  for (uint i = 0; (has_packets = this->savegame->HasPackets()) && i < sent_packets; i++) {
596  Packet *p = this->savegame->PopPacket();
597  last_packet = p->buffer[2] == PACKET_SERVER_MAP_DONE;
598 
599  this->SendPacket(p);
600 
601  if (last_packet) {
602  /* There is no more data, so break the for */
603  break;
604  }
605  }
606 
607  if (last_packet) {
608  /* Done reading, make sure saving is done as well */
609  this->savegame->Destroy();
610  this->savegame = nullptr;
611 
612  /* Set the status to DONE_MAP, no we will wait for the client
613  * to send it is ready (maybe that happens like never ;)) */
614  this->status = STATUS_DONE_MAP;
615 
616  /* Find the best candidate for joining, i.e. the first joiner. */
617  NetworkClientSocket *new_cs;
618  NetworkClientSocket *best = nullptr;
619  FOR_ALL_CLIENT_SOCKETS(new_cs) {
620  if (new_cs->status == STATUS_MAP_WAIT) {
621  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)) {
622  best = new_cs;
623  }
624  }
625  }
626 
627  /* Is there someone else to join? */
628  if (best != nullptr) {
629  /* Let the first start joining. */
630  best->status = STATUS_AUTHORIZED;
631  best->SendMap();
632 
633  /* And update the rest. */
634  FOR_ALL_CLIENT_SOCKETS(new_cs) {
635  if (new_cs->status == STATUS_MAP_WAIT) new_cs->SendWait();
636  }
637  }
638  }
639 
640  switch (this->SendPackets()) {
641  case SPS_CLOSED:
643 
644  case SPS_ALL_SENT:
645  /* All are sent, increase the sent_packets */
646  if (has_packets) sent_packets *= 2;
647  break;
648 
649  case SPS_PARTLY_SENT:
650  /* Only a part is sent; leave the transmission state. */
651  break;
652 
653  case SPS_NONE_SENT:
654  /* Not everything is sent, decrease the sent_packets */
655  if (sent_packets > 1) sent_packets /= 2;
656  break;
657  }
658  }
660 }
661 
667 {
668  Packet *p = new Packet(PACKET_SERVER_JOIN);
669 
670  p->Send_uint32(client_id);
671 
672  this->SendPacket(p);
674 }
675 
678 {
682 #ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
684 #ifdef NETWORK_SEND_DOUBLE_SEED
685  p->Send_uint32(_sync_seed_2);
686 #endif
687 #endif
688 
689  /* If token equals 0, we need to make a new token and send that. */
690  if (this->last_token == 0) {
691  this->last_token = InteractiveRandomRange(UINT8_MAX - 1) + 1;
692  p->Send_uint8(this->last_token);
693  }
694 
695  this->SendPacket(p);
697 }
698 
701 {
702  Packet *p = new Packet(PACKET_SERVER_SYNC);
705 
706 #ifdef NETWORK_SEND_DOUBLE_SEED
707  p->Send_uint32(_sync_seed_2);
708 #endif
709  this->SendPacket(p);
711 }
712 
718 {
720 
722  p->Send_uint32(cp->frame);
723  p->Send_bool (cp->my_cmd);
724 
725  this->SendPacket(p);
727 }
728 
738 {
740 
741  Packet *p = new Packet(PACKET_SERVER_CHAT);
742 
743  p->Send_uint8 (action);
744  p->Send_uint32(client_id);
745  p->Send_bool (self_send);
746  p->Send_string(msg);
747  p->Send_uint64(data);
748 
749  this->SendPacket(p);
751 }
752 
759 {
761 
762  p->Send_uint32(client_id);
763  p->Send_uint8 (errorno);
764 
765  this->SendPacket(p);
767 }
768 
774 {
775  Packet *p = new Packet(PACKET_SERVER_QUIT);
776 
777  p->Send_uint32(client_id);
778 
779  this->SendPacket(p);
781 }
782 
785 {
787  this->SendPacket(p);
789 }
790 
793 {
795  this->SendPacket(p);
797 }
798 
805 {
806  Packet *p = new Packet(PACKET_SERVER_RCON);
807 
808  p->Send_uint16(colour);
809  p->Send_string(command);
810  this->SendPacket(p);
812 }
813 
820 {
821  Packet *p = new Packet(PACKET_SERVER_MOVE);
822 
823  p->Send_uint32(client_id);
824  p->Send_uint8(company_id);
825  this->SendPacket(p);
827 }
828 
831 {
833 
835  this->SendPacket(p);
837 }
838 
841 {
843 
846  this->SendPacket(p);
848 }
849 
850 /***********
851  * Receiving functions
852  * DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientSocket *cs, Packet *p
853  ************/
854 
856 {
857  return this->SendCompanyInfo();
858 }
859 
861 {
862  if (this->status != STATUS_NEWGRFS_CHECK) {
863  /* Illegal call, return error and ignore the packet */
864  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
865  }
866 
867  NetworkClientInfo *ci = this->GetInfo();
868 
869  /* We now want a password from the client else we do not allow him in! */
871  return this->SendNeedGamePassword();
872  }
873 
875  return this->SendNeedCompanyPassword();
876  }
877 
878  return this->SendWelcome();
879 }
880 
882 {
883  if (this->status != STATUS_INACTIVE) {
884  /* Illegal call, return error and ignore the packet */
885  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
886  }
887 
888  char name[NETWORK_CLIENT_NAME_LENGTH];
889  CompanyID playas;
890  NetworkLanguage client_lang;
891  char client_revision[NETWORK_REVISION_LENGTH];
892 
893  p->Recv_string(client_revision, sizeof(client_revision));
894  uint32 newgrf_version = p->Recv_uint32();
895 
896  /* Check if the client has revision control enabled */
897  if (!IsNetworkCompatibleVersion(client_revision) || _openttd_newgrf_version != newgrf_version) {
898  /* Different revisions!! */
899  return this->SendError(NETWORK_ERROR_WRONG_REVISION);
900  }
901 
902  p->Recv_string(name, sizeof(name));
903  playas = (Owner)p->Recv_uint8();
904  client_lang = (NetworkLanguage)p->Recv_uint8();
905 
906  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
907 
908  /* join another company does not affect these values */
909  switch (playas) {
910  case COMPANY_NEW_COMPANY: // New company
912  return this->SendError(NETWORK_ERROR_FULL);
913  }
914  break;
915  case COMPANY_SPECTATOR: // Spectator
916  if (NetworkSpectatorCount() >= _settings_client.network.max_spectators) {
917  return this->SendError(NETWORK_ERROR_FULL);
918  }
919  break;
920  default: // Join another company (companies 1-8 (index 0-7))
921  if (!Company::IsValidHumanID(playas)) {
922  return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
923  }
924  break;
925  }
926 
927  /* We need a valid name.. make it Player */
928  if (StrEmpty(name)) strecpy(name, "Player", lastof(name));
929 
930  if (!NetworkFindName(name, lastof(name))) { // Change name if duplicate
931  /* We could not create a name for this client */
932  return this->SendError(NETWORK_ERROR_NAME_IN_USE);
933  }
934 
937  this->SetInfo(ci);
938  ci->join_date = _date;
939  strecpy(ci->client_name, name, lastof(ci->client_name));
940  ci->client_playas = playas;
941  ci->client_lang = client_lang;
942  DEBUG(desync, 1, "client: %08x; %02x; %02x; %02x", _date, _date_fract, (int)ci->client_playas, (int)ci->index);
943 
944  /* Make sure companies to which people try to join are not autocleaned */
946 
948 
949  if (_grfconfig == nullptr) {
950  /* Behave as if we received PACKET_CLIENT_NEWGRFS_CHECKED */
951  return this->Receive_CLIENT_NEWGRFS_CHECKED(nullptr);
952  }
953 
954  return this->SendNewGRFCheck();
955 }
956 
958 {
959  if (this->status != STATUS_AUTH_GAME) {
960  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
961  }
962 
963  char password[NETWORK_PASSWORD_LENGTH];
964  p->Recv_string(password, sizeof(password));
965 
966  /* Check game password. Allow joining if we cleared the password meanwhile */
968  strcmp(password, _settings_client.network.server_password) != 0) {
969  /* Password is invalid */
970  return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
971  }
972 
973  const NetworkClientInfo *ci = this->GetInfo();
975  return this->SendNeedCompanyPassword();
976  }
977 
978  /* Valid password, allow user */
979  return this->SendWelcome();
980 }
981 
983 {
984  if (this->status != STATUS_AUTH_COMPANY) {
985  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
986  }
987 
988  char password[NETWORK_PASSWORD_LENGTH];
989  p->Recv_string(password, sizeof(password));
990 
991  /* Check company password. Allow joining if we cleared the password meanwhile.
992  * Also, check the company is still valid - client could be moved to spectators
993  * in the middle of the authorization process */
994  CompanyID playas = this->GetInfo()->client_playas;
995  if (Company::IsValidID(playas) && !StrEmpty(_network_company_states[playas].password) &&
996  strcmp(password, _network_company_states[playas].password) != 0) {
997  /* Password is invalid */
998  return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
999  }
1000 
1001  return this->SendWelcome();
1002 }
1003 
1005 {
1006  NetworkClientSocket *new_cs;
1007  /* The client was never joined.. so this is impossible, right?
1008  * Ignore the packet, give the client a warning, and close his connection */
1009  if (this->status < STATUS_AUTHORIZED || this->HasClientQuit()) {
1010  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1011  }
1012 
1013  /* Check if someone else is receiving the map */
1014  FOR_ALL_CLIENT_SOCKETS(new_cs) {
1015  if (new_cs->status == STATUS_MAP) {
1016  /* Tell the new client to wait */
1017  this->status = STATUS_MAP_WAIT;
1018  return this->SendWait();
1019  }
1020  }
1021 
1022  /* We receive a request to upload the map.. give it to the client! */
1023  return this->SendMap();
1024 }
1025 
1027 {
1028  /* Client has the map, now start syncing */
1029  if (this->status == STATUS_DONE_MAP && !this->HasClientQuit()) {
1030  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1031  NetworkClientSocket *new_cs;
1032 
1033  this->GetClientName(client_name, lastof(client_name));
1034 
1035  NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, nullptr, this->client_id);
1036 
1037  /* Mark the client as pre-active, and wait for an ACK
1038  * so we know he is done loading and in sync with us */
1039  this->status = STATUS_PRE_ACTIVE;
1041  this->SendFrame();
1042  this->SendSync();
1043 
1044  /* This is the frame the client receives
1045  * we need it later on to make sure the client is not too slow */
1046  this->last_frame = _frame_counter;
1048 
1049  FOR_ALL_CLIENT_SOCKETS(new_cs) {
1050  if (new_cs->status > STATUS_AUTHORIZED) {
1051  new_cs->SendClientInfo(this->GetInfo());
1052  new_cs->SendJoin(this->client_id);
1053  }
1054  }
1055 
1056  NetworkAdminClientInfo(this, true);
1057 
1058  /* also update the new client with our max values */
1059  this->SendConfigUpdate();
1060 
1061  /* quickly update the syncing client with company details */
1062  return this->SendCompanyUpdate();
1063  }
1064 
1065  /* Wrong status for this packet, give a warning to client, and close connection */
1066  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1067 }
1068 
1074 {
1075  /* The client was never joined.. so this is impossible, right?
1076  * Ignore the packet, give the client a warning, and close his connection */
1077  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1078  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1079  }
1080 
1082  return this->SendError(NETWORK_ERROR_TOO_MANY_COMMANDS);
1083  }
1084 
1085  CommandPacket cp;
1086  const char *err = this->ReceiveCommand(p, &cp);
1087 
1088  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
1089 
1090  NetworkClientInfo *ci = this->GetInfo();
1091 
1092  if (err != nullptr) {
1093  IConsolePrintF(CC_ERROR, "WARNING: %s from client %d (IP: %s).", err, ci->client_id, this->GetClientIP());
1094  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1095  }
1096 
1097 
1098  if ((GetCommandFlags(cp.cmd) & CMD_SERVER) && ci->client_id != CLIENT_ID_SERVER) {
1099  IConsolePrintF(CC_ERROR, "WARNING: server only command from: client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
1100  return this->SendError(NETWORK_ERROR_KICKED);
1101  }
1102 
1104  IConsolePrintF(CC_ERROR, "WARNING: spectator issuing command from client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
1105  return this->SendError(NETWORK_ERROR_KICKED);
1106  }
1107 
1113  if (!(cp.cmd == CMD_COMPANY_CTRL && cp.p1 == 0 && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) {
1114  IConsolePrintF(CC_ERROR, "WARNING: client %d (IP: %s) tried to execute a command as company %d, kicking...",
1115  ci->client_playas + 1, this->GetClientIP(), cp.company + 1);
1116  return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
1117  }
1118 
1119  if (cp.cmd == CMD_COMPANY_CTRL) {
1120  if (cp.p1 != 0 || cp.company != COMPANY_SPECTATOR) {
1121  return this->SendError(NETWORK_ERROR_CHEATER);
1122  }
1123 
1124  /* 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! */
1126  NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_CLIENT, ci->client_id, "cannot create new company, server full", CLIENT_ID_SERVER);
1127  return NETWORK_RECV_STATUS_OKAY;
1128  }
1129  }
1130 
1131  if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) cp.p2 = this->client_id;
1132 
1133  this->incoming_queue.Append(&cp);
1134  return NETWORK_RECV_STATUS_OKAY;
1135 }
1136 
1138 {
1139  /* This packets means a client noticed an error and is reporting this
1140  * to us. Display the error and report it to the other clients */
1141  NetworkClientSocket *new_cs;
1142  char str[100];
1143  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1145 
1146  /* The client was never joined.. thank the client for the packet, but ignore it */
1147  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1149  }
1150 
1151  this->GetClientName(client_name, lastof(client_name));
1152 
1153  StringID strid = GetNetworkErrorMsg(errorno);
1154  GetString(str, strid, lastof(str));
1155 
1156  DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
1157 
1158  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid);
1159 
1160  FOR_ALL_CLIENT_SOCKETS(new_cs) {
1161  if (new_cs->status > STATUS_AUTHORIZED) {
1162  new_cs->SendErrorQuit(this->client_id, errorno);
1163  }
1164  }
1165 
1166  NetworkAdminClientError(this->client_id, errorno);
1167 
1169 }
1170 
1172 {
1173  /* The client wants to leave. Display this and report it to the other
1174  * clients. */
1175  NetworkClientSocket *new_cs;
1176  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1177 
1178  /* The client was never joined.. thank the client for the packet, but ignore it */
1179  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1181  }
1182 
1183  this->GetClientName(client_name, lastof(client_name));
1184 
1185  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
1186 
1187  FOR_ALL_CLIENT_SOCKETS(new_cs) {
1188  if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
1189  new_cs->SendQuit(this->client_id);
1190  }
1191  }
1192 
1194 
1196 }
1197 
1199 {
1200  if (this->status < STATUS_AUTHORIZED) {
1201  /* Illegal call, return error and ignore the packet */
1202  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1203  }
1204 
1205  uint32 frame = p->Recv_uint32();
1206 
1207  /* The client is trying to catch up with the server */
1208  if (this->status == STATUS_PRE_ACTIVE) {
1209  /* The client is not yet caught up? */
1210  if (frame + DAY_TICKS < _frame_counter) return NETWORK_RECV_STATUS_OKAY;
1211 
1212  /* Now he is! Unpause the game */
1213  this->status = STATUS_ACTIVE;
1215 
1216  /* Execute script for, e.g. MOTD */
1217  IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
1218  }
1219 
1220  /* Get, and validate the token. */
1221  uint8 token = p->Recv_uint8();
1222  if (token == this->last_token) {
1223  /* We differentiate between last_token_frame and last_frame so the lag
1224  * test uses the actual lag of the client instead of the lag for getting
1225  * the token back and forth; after all, the token is only sent every
1226  * time we receive a PACKET_CLIENT_ACK, after which we will send a new
1227  * token to the client. If the lag would be one day, then we would not
1228  * be sending the new token soon enough for the new daily scheduled
1229  * PACKET_CLIENT_ACK. This would then register the lag of the client as
1230  * two days, even when it's only a single day. */
1232  /* Request a new token. */
1233  this->last_token = 0;
1234  }
1235 
1236  /* The client received the frame, make note of it */
1237  this->last_frame = frame;
1238  /* With those 2 values we can calculate the lag realtime */
1240  return NETWORK_RECV_STATUS_OKAY;
1241 }
1242 
1243 
1254 void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, ClientID from_id, int64 data, bool from_admin)
1255 {
1256  NetworkClientSocket *cs;
1257  const NetworkClientInfo *ci, *ci_own, *ci_to;
1258 
1259  switch (desttype) {
1260  case DESTTYPE_CLIENT:
1261  /* Are we sending to the server? */
1262  if ((ClientID)dest == CLIENT_ID_SERVER) {
1263  ci = NetworkClientInfo::GetByClientID(from_id);
1264  /* Display the text locally, and that is it */
1265  if (ci != nullptr) {
1266  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1267 
1269  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1270  }
1271  }
1272  } else {
1273  /* Else find the client to send the message to */
1275  if (cs->client_id == (ClientID)dest) {
1276  cs->SendChat(action, from_id, false, msg, data);
1277  break;
1278  }
1279  }
1280  }
1281 
1282  /* Display the message locally (so you know you have sent it) */
1283  if (from_id != (ClientID)dest) {
1284  if (from_id == CLIENT_ID_SERVER) {
1285  ci = NetworkClientInfo::GetByClientID(from_id);
1287  if (ci != nullptr && ci_to != nullptr) {
1288  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), true, ci_to->client_name, msg, data);
1289  }
1290  } else {
1292  if (cs->client_id == from_id) {
1293  cs->SendChat(action, (ClientID)dest, true, msg, data);
1294  break;
1295  }
1296  }
1297  }
1298  }
1299  break;
1300  case DESTTYPE_TEAM: {
1301  /* If this is false, the message is already displayed on the client who sent it. */
1302  bool show_local = true;
1303  /* Find all clients that belong to this company */
1304  ci_to = nullptr;
1306  ci = cs->GetInfo();
1307  if (ci != nullptr && ci->client_playas == (CompanyID)dest) {
1308  cs->SendChat(action, from_id, false, msg, data);
1309  if (cs->client_id == from_id) show_local = false;
1310  ci_to = ci; // Remember a client that is in the company for company-name
1311  }
1312  }
1313 
1314  /* if the server can read it, let the admin network read it, too. */
1316  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1317  }
1318 
1319  ci = NetworkClientInfo::GetByClientID(from_id);
1321  if (ci != nullptr && ci_own != nullptr && ci_own->client_playas == dest) {
1322  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1323  if (from_id == CLIENT_ID_SERVER) show_local = false;
1324  ci_to = ci_own;
1325  }
1326 
1327  /* There is no such client */
1328  if (ci_to == nullptr) break;
1329 
1330  /* Display the message locally (so you know you have sent it) */
1331  if (ci != nullptr && show_local) {
1332  if (from_id == CLIENT_ID_SERVER) {
1333  char name[NETWORK_NAME_LENGTH];
1334  StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
1335  SetDParam(0, ci_to->client_playas);
1336  GetString(name, str, lastof(name));
1337  NetworkTextMessage(action, GetDrawStringCompanyColour(ci_own->client_playas), true, name, msg, data);
1338  } else {
1340  if (cs->client_id == from_id) {
1341  cs->SendChat(action, ci_to->client_id, true, msg, data);
1342  }
1343  }
1344  }
1345  }
1346  break;
1347  }
1348  default:
1349  DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
1350  FALLTHROUGH;
1351 
1352  case DESTTYPE_BROADCAST:
1354  cs->SendChat(action, from_id, false, msg, data);
1355  }
1356 
1357  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1358 
1359  ci = NetworkClientInfo::GetByClientID(from_id);
1360  if (ci != nullptr) {
1361  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1362  }
1363  break;
1364  }
1365 }
1366 
1368 {
1369  if (this->status < STATUS_PRE_ACTIVE) {
1370  /* Illegal call, return error and ignore the packet */
1371  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1372  }
1373 
1374  NetworkAction action = (NetworkAction)p->Recv_uint8();
1375  DestType desttype = (DestType)p->Recv_uint8();
1376  int dest = p->Recv_uint32();
1377  char msg[NETWORK_CHAT_LENGTH];
1378 
1380  int64 data = p->Recv_uint64();
1381 
1382  NetworkClientInfo *ci = this->GetInfo();
1383  switch (action) {
1384  case NETWORK_ACTION_GIVE_MONEY:
1385  if (!Company::IsValidID(ci->client_playas)) break;
1386  FALLTHROUGH;
1387  case NETWORK_ACTION_CHAT:
1388  case NETWORK_ACTION_CHAT_CLIENT:
1389  case NETWORK_ACTION_CHAT_COMPANY:
1390  NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data);
1391  break;
1392  default:
1393  IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, this->GetClientIP());
1394  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1395  }
1396  return NETWORK_RECV_STATUS_OKAY;
1397 }
1398 
1400 {
1401  if (this->status != STATUS_ACTIVE) {
1402  /* Illegal call, return error and ignore the packet */
1403  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1404  }
1405 
1406  char password[NETWORK_PASSWORD_LENGTH];
1407  const NetworkClientInfo *ci;
1408 
1409  p->Recv_string(password, sizeof(password));
1410  ci = this->GetInfo();
1411 
1413  return NETWORK_RECV_STATUS_OKAY;
1414 }
1415 
1417 {
1418  if (this->status != STATUS_ACTIVE) {
1419  /* Illegal call, return error and ignore the packet */
1420  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1421  }
1422 
1423  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1424  NetworkClientInfo *ci;
1425 
1426  p->Recv_string(client_name, sizeof(client_name));
1427  ci = this->GetInfo();
1428 
1429  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
1430 
1431  if (ci != nullptr) {
1432  /* Display change */
1433  if (NetworkFindName(client_name, lastof(client_name))) {
1434  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name);
1435  strecpy(ci->client_name, client_name, lastof(ci->client_name));
1437  }
1438  }
1439  return NETWORK_RECV_STATUS_OKAY;
1440 }
1441 
1443 {
1444  if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1445 
1446  char pass[NETWORK_PASSWORD_LENGTH];
1447  char command[NETWORK_RCONCOMMAND_LENGTH];
1448 
1450 
1451  p->Recv_string(pass, sizeof(pass));
1452  p->Recv_string(command, sizeof(command));
1453 
1454  if (strcmp(pass, _settings_client.network.rcon_password) != 0) {
1455  DEBUG(net, 0, "[rcon] wrong password from client-id %d", this->client_id);
1456  return NETWORK_RECV_STATUS_OKAY;
1457  }
1458 
1459  DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", this->client_id, command);
1460 
1462  IConsoleCmdExec(command);
1464  return NETWORK_RECV_STATUS_OKAY;
1465 }
1466 
1468 {
1469  if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1470 
1471  CompanyID company_id = (Owner)p->Recv_uint8();
1472 
1473  /* Check if the company is valid, we don't allow moving to AI companies */
1474  if (company_id != COMPANY_SPECTATOR && !Company::IsValidHumanID(company_id)) return NETWORK_RECV_STATUS_OKAY;
1475 
1476  /* Check if we require a password for this company */
1477  if (company_id != COMPANY_SPECTATOR && !StrEmpty(_network_company_states[company_id].password)) {
1478  /* we need a password from the client - should be in this packet */
1479  char password[NETWORK_PASSWORD_LENGTH];
1480  p->Recv_string(password, sizeof(password));
1481 
1482  /* Incorrect password sent, return! */
1483  if (strcmp(password, _network_company_states[company_id].password) != 0) {
1484  DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", this->client_id, company_id + 1);
1485  return NETWORK_RECV_STATUS_OKAY;
1486  }
1487  }
1488 
1489  /* if we get here we can move the client */
1490  NetworkServerDoMove(this->client_id, company_id);
1491  return NETWORK_RECV_STATUS_OKAY;
1492 }
1493 
1502 {
1503  /* Grab the company name */
1504  char company_name[NETWORK_COMPANY_NAME_LENGTH];
1505  SetDParam(0, c->index);
1506 
1507  assert(max_len <= lengthof(company_name));
1508  GetString(company_name, STR_COMPANY_NAME, company_name + max_len - 1);
1509 
1510  /* Get the income */
1511  Money income = 0;
1512  if (_cur_year - 1 == c->inaugurated_year) {
1513  /* The company is here just 1 year, so display [2], else display[1] */
1514  for (uint i = 0; i < lengthof(c->yearly_expenses[2]); i++) {
1515  income -= c->yearly_expenses[2][i];
1516  }
1517  } else {
1518  for (uint i = 0; i < lengthof(c->yearly_expenses[1]); i++) {
1519  income -= c->yearly_expenses[1][i];
1520  }
1521  }
1522 
1523  /* Send the information */
1524  p->Send_uint8 (c->index);
1525  p->Send_string(company_name);
1528  p->Send_uint64(c->money);
1529  p->Send_uint64(income);
1531 
1532  /* Send 1 if there is a password for the company else send 0 */
1534 
1535  for (uint i = 0; i < NETWORK_VEH_END; i++) {
1536  p->Send_uint16(stats->num_vehicle[i]);
1537  }
1538 
1539  for (uint i = 0; i < NETWORK_VEH_END; i++) {
1540  p->Send_uint16(stats->num_station[i]);
1541  }
1542 
1543  p->Send_bool(c->is_ai);
1544 }
1545 
1551 {
1552  const Vehicle *v;
1553  const Station *s;
1554 
1555  memset(stats, 0, sizeof(*stats) * MAX_COMPANIES);
1556 
1557  /* Go through all vehicles and count the type of vehicles */
1558  FOR_ALL_VEHICLES(v) {
1559  if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
1560  byte type = 0;
1561  switch (v->type) {
1562  case VEH_TRAIN: type = NETWORK_VEH_TRAIN; break;
1563  case VEH_ROAD: type = RoadVehicle::From(v)->IsBus() ? NETWORK_VEH_BUS : NETWORK_VEH_LORRY; break;
1564  case VEH_AIRCRAFT: type = NETWORK_VEH_PLANE; break;
1565  case VEH_SHIP: type = NETWORK_VEH_SHIP; break;
1566  default: continue;
1567  }
1568  stats[v->owner].num_vehicle[type]++;
1569  }
1570 
1571  /* Go through all stations and count the types of stations */
1572  FOR_ALL_STATIONS(s) {
1573  if (Company::IsValidID(s->owner)) {
1574  NetworkCompanyStats *npi = &stats[s->owner];
1575 
1576  if (s->facilities & FACIL_TRAIN) npi->num_station[NETWORK_VEH_TRAIN]++;
1577  if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[NETWORK_VEH_LORRY]++;
1578  if (s->facilities & FACIL_BUS_STOP) npi->num_station[NETWORK_VEH_BUS]++;
1579  if (s->facilities & FACIL_AIRPORT) npi->num_station[NETWORK_VEH_PLANE]++;
1580  if (s->facilities & FACIL_DOCK) npi->num_station[NETWORK_VEH_SHIP]++;
1581  }
1582  }
1583 }
1584 
1590 {
1591  NetworkClientSocket *cs;
1593 
1594  if (ci == nullptr) return;
1595 
1596  DEBUG(desync, 1, "client: %08x; %02x; %02x; %04x", _date, _date_fract, (int)ci->client_playas, client_id);
1597 
1599  cs->SendClientInfo(ci);
1600  }
1601 
1603 }
1604 
1607 {
1609  DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
1610 
1612  }
1613 }
1614 
1622 {
1623  const NetworkClientInfo *ci;
1624  const Company *c;
1625  bool clients_in_company[MAX_COMPANIES];
1626  int vehicles_in_company[MAX_COMPANIES];
1627 
1629 
1630  memset(clients_in_company, 0, sizeof(clients_in_company));
1631 
1632  /* Detect the active companies */
1633  FOR_ALL_CLIENT_INFOS(ci) {
1634  if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
1635  }
1636 
1637  if (!_network_dedicated) {
1639  if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
1640  }
1641 
1643  memset(vehicles_in_company, 0, sizeof(vehicles_in_company));
1644 
1645  const Vehicle *v;
1646  FOR_ALL_VEHICLES(v) {
1647  if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
1648  vehicles_in_company[v->owner]++;
1649  }
1650  }
1651 
1652  /* Go through all the companies */
1653  FOR_ALL_COMPANIES(c) {
1654  /* Skip the non-active once */
1655  if (c->is_ai) continue;
1656 
1657  if (!clients_in_company[c->index]) {
1658  /* The company is empty for one month more */
1660 
1661  /* Is the company empty for autoclean_unprotected-months, and is there no protection? */
1663  /* Shut the company down */
1664  DoCommandP(0, CCA_DELETE | c->index << 16 | CRR_AUTOCLEAN << 24, 0, CMD_COMPANY_CTRL);
1665  IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no password", c->index + 1);
1666  }
1667  /* Is the company empty for autoclean_protected-months, and there is a protection? */
1669  /* Unprotect the company */
1670  _network_company_states[c->index].password[0] = '\0';
1671  IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", c->index + 1);
1674  }
1675  /* Is the company empty for autoclean_novehicles-months, and has no vehicles? */
1677  /* Shut the company down */
1678  DoCommandP(0, CCA_DELETE | c->index << 16 | CRR_AUTOCLEAN << 24, 0, CMD_COMPANY_CTRL);
1679  IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no vehicles", c->index + 1);
1680  }
1681  } else {
1682  /* It is not empty, reset the date */
1684  }
1685  }
1686 }
1687 
1694 bool NetworkFindName(char *new_name, const char *last)
1695 {
1696  bool found_name = false;
1697  uint number = 0;
1698  char original_name[NETWORK_CLIENT_NAME_LENGTH];
1699 
1700  strecpy(original_name, new_name, lastof(original_name));
1701 
1702  while (!found_name) {
1703  const NetworkClientInfo *ci;
1704 
1705  found_name = true;
1706  FOR_ALL_CLIENT_INFOS(ci) {
1707  if (strcmp(ci->client_name, new_name) == 0) {
1708  /* Name already in use */
1709  found_name = false;
1710  break;
1711  }
1712  }
1713  /* Check if it is the same as the server-name */
1715  if (ci != nullptr) {
1716  if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
1717  }
1718 
1719  if (!found_name) {
1720  /* Try a new name (<name> #1, <name> #2, and so on) */
1721 
1722  /* Something's really wrong when there're more names than clients */
1723  if (number++ > MAX_CLIENTS) break;
1724  seprintf(new_name, last, "%s #%d", original_name, number);
1725  }
1726  }
1727 
1728  return found_name;
1729 }
1730 
1738 {
1739  NetworkClientInfo *ci;
1740  /* Check if the name's already in use */
1741  FOR_ALL_CLIENT_INFOS(ci) {
1742  if (strcmp(ci->client_name, new_name) == 0) return false;
1743  }
1744 
1745  ci = NetworkClientInfo::GetByClientID(client_id);
1746  if (ci == nullptr) return false;
1747 
1748  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, true, ci->client_name, new_name);
1749 
1750  strecpy(ci->client_name, new_name, lastof(ci->client_name));
1751 
1752  NetworkUpdateClientInfo(client_id);
1753  return true;
1754 }
1755 
1762 void NetworkServerSetCompanyPassword(CompanyID company_id, const char *password, bool already_hashed)
1763 {
1764  if (!Company::IsValidHumanID(company_id)) return;
1765 
1766  if (!already_hashed) {
1768  }
1769 
1770  strecpy(_network_company_states[company_id].password, password, lastof(_network_company_states[company_id].password));
1771  NetworkServerUpdateCompanyPassworded(company_id, !StrEmpty(_network_company_states[company_id].password));
1772 }
1773 
1778 static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
1779 {
1780  CommandPacket *cp;
1781  while ((cp = cs->outgoing_queue.Pop()) != nullptr) {
1782  cs->SendCommand(cp);
1783  free(cp);
1784  }
1785 }
1786 
1791 void NetworkServer_Tick(bool send_frame)
1792 {
1793  NetworkClientSocket *cs;
1794 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1795  bool send_sync = false;
1796 #endif
1797 
1798 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1801  send_sync = true;
1802  }
1803 #endif
1804 
1805  /* Now we are done with the frame, inform the clients that they can
1806  * do their frame! */
1808  /* We allow a number of bytes per frame, but only to the burst amount
1809  * to be available for packet receiving at any particular time. */
1810  cs->receive_limit = min(cs->receive_limit + _settings_client.network.bytes_per_frame,
1812 
1813  /* Check if the speed of the client is what we can expect from a client */
1814  uint lag = NetworkCalculateLag(cs);
1815  switch (cs->status) {
1816  case NetworkClientSocket::STATUS_ACTIVE:
1818  /* Client did still not report in within the specified limit. */
1819  IConsolePrintF(CC_ERROR, cs->last_packet + lag * MILLISECONDS_PER_TICK > _realtime_tick ?
1820  /* A packet was received in the last three game days, so the client is likely lagging behind. */
1821  "Client #%d is dropped because the client's game state is more than %d ticks behind" :
1822  /* No packet was received in the last three game days; sounds like a lost connection. */
1823  "Client #%d is dropped because the client did not respond for more than %d ticks",
1824  cs->client_id, lag);
1825  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1826  continue;
1827  }
1828 
1829  /* Report once per time we detect the lag, and only when we
1830  * received a packet in the last 2000 milliseconds. If we
1831  * did not receive a packet, then the client is not just
1832  * slow, but the connection is likely severed. Mentioning
1833  * frame_freq is not useful in this case. */
1834  if (lag > (uint)DAY_TICKS && cs->lag_test == 0 && cs->last_packet + 2000 > _realtime_tick) {
1835  IConsolePrintF(CC_WARNING, "[%d] Client #%d is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id);
1836  cs->lag_test = 1;
1837  }
1838 
1839  if (cs->last_frame_server - cs->last_token_frame >= _settings_client.network.max_lag_time) {
1840  /* This is a bad client! It didn't send the right token back within time. */
1841  IConsolePrintF(CC_ERROR, "Client #%d is dropped because it fails to send valid acks", cs->client_id);
1842  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1843  continue;
1844  }
1845  break;
1846 
1847  case NetworkClientSocket::STATUS_INACTIVE:
1848  case NetworkClientSocket::STATUS_NEWGRFS_CHECK:
1849  case NetworkClientSocket::STATUS_AUTHORIZED:
1850  /* NewGRF check and authorized states should be handled almost instantly.
1851  * So give them some lee-way, likewise for the query with inactive. */
1853  IConsolePrintF(CC_ERROR, "Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->client_id, _settings_client.network.max_init_time);
1854  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1855  continue;
1856  }
1857  break;
1858 
1859  case NetworkClientSocket::STATUS_MAP:
1860  /* Downloading the map... this is the amount of time since starting the saving. */
1862  IConsolePrintF(CC_ERROR, "Client #%d is dropped because it took longer than %d ticks to download the map", cs->client_id, _settings_client.network.max_download_time);
1863  cs->SendError(NETWORK_ERROR_TIMEOUT_MAP);
1864  continue;
1865  }
1866  break;
1867 
1868  case NetworkClientSocket::STATUS_DONE_MAP:
1869  case NetworkClientSocket::STATUS_PRE_ACTIVE:
1870  /* The map has been sent, so this is for loading the map and syncing up. */
1872  IConsolePrintF(CC_ERROR, "Client #%d is dropped because it took longer than %d ticks to join", cs->client_id, _settings_client.network.max_join_time);
1873  cs->SendError(NETWORK_ERROR_TIMEOUT_JOIN);
1874  continue;
1875  }
1876  break;
1877 
1878  case NetworkClientSocket::STATUS_AUTH_GAME:
1879  case NetworkClientSocket::STATUS_AUTH_COMPANY:
1880  /* These don't block? */
1882  IConsolePrintF(CC_ERROR, "Client #%d is dropped because it took longer than %d ticks to enter the password", cs->client_id, _settings_client.network.max_password_time);
1883  cs->SendError(NETWORK_ERROR_TIMEOUT_PASSWORD);
1884  continue;
1885  }
1886  break;
1887 
1888  case NetworkClientSocket::STATUS_MAP_WAIT:
1889  /* This is an internal state where we do not wait
1890  * on the client to move to a different state. */
1891  break;
1892 
1893  case NetworkClientSocket::STATUS_END:
1894  /* Bad server/code. */
1895  NOT_REACHED();
1896  }
1897 
1898  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) {
1899  /* Check if we can send command, and if we have anything in the queue */
1901 
1902  /* Send an updated _frame_counter_max to the client */
1903  if (send_frame) cs->SendFrame();
1904 
1905 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1906  /* Send a sync-check packet */
1907  if (send_sync) cs->SendSync();
1908 #endif
1909  }
1910  }
1911 
1912  /* See if we need to advertise */
1914 }
1915 
1918 {
1921 }
1922 
1925 {
1929 }
1930 
1933 {
1936 }
1937 
1943 {
1944  return this->client_address.GetHostname();
1945 }
1946 
1949 {
1950  static const char * const stat_str[] = {
1951  "inactive",
1952  "checking NewGRFs",
1953  "authorizing (server password)",
1954  "authorizing (company password)",
1955  "authorized",
1956  "waiting",
1957  "loading map",
1958  "map done",
1959  "ready",
1960  "active"
1961  };
1962  assert_compile(lengthof(stat_str) == NetworkClientSocket::STATUS_END);
1963 
1964  NetworkClientSocket *cs;
1966  NetworkClientInfo *ci = cs->GetInfo();
1967  if (ci == nullptr) continue;
1968  uint lag = NetworkCalculateLag(cs);
1969  const char *status;
1970 
1971  status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
1972  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s",
1973  cs->client_id, ci->client_name, status, lag,
1974  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
1975  cs->GetClientIP());
1976  }
1977 }
1978 
1983 {
1984  NetworkClientSocket *cs;
1985 
1987  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendConfigUpdate();
1988  }
1989 }
1990 
1996 void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded)
1997 {
1998  if (NetworkCompanyIsPassworded(company_id) == passworded) return;
1999 
2000  SB(_network_company_passworded, company_id, 1, !!passworded);
2002 
2003  NetworkClientSocket *cs;
2005  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendCompanyUpdate();
2006  }
2007 
2009 }
2010 
2018 {
2019  /* Only allow non-dedicated servers and normal clients to be moved */
2020  if (client_id == CLIENT_ID_SERVER && _network_dedicated) return;
2021 
2023 
2024  /* No need to waste network resources if the client is in the company already! */
2025  if (ci->client_playas == company_id) return;
2026 
2027  ci->client_playas = company_id;
2028 
2029  if (client_id == CLIENT_ID_SERVER) {
2030  SetLocalCompany(company_id);
2031  } else {
2032  NetworkClientSocket *cs = NetworkClientSocket::GetByClientID(client_id);
2033  /* When the company isn't authorized we can't move them yet. */
2034  if (cs->status < NetworkClientSocket::STATUS_AUTHORIZED) return;
2035  cs->SendMove(client_id, company_id);
2036  }
2037 
2038  /* announce the client's move */
2039  NetworkUpdateClientInfo(client_id);
2040 
2041  NetworkAction action = (company_id == COMPANY_SPECTATOR) ? NETWORK_ACTION_COMPANY_SPECTATOR : NETWORK_ACTION_COMPANY_JOIN;
2042  NetworkServerSendChat(action, DESTTYPE_BROADCAST, 0, "", client_id, company_id + 1);
2043 }
2044 
2051 void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string)
2052 {
2053  NetworkClientSocket::GetByClientID(client_id)->SendRConResult(colour_code, string);
2054 }
2055 
2061 {
2062  if (client_id == CLIENT_ID_SERVER) return;
2063  NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED);
2064 }
2065 
2072 {
2073  return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban);
2074 }
2075 
2081 uint NetworkServerKickOrBanIP(const char *ip, bool ban)
2082 {
2083  /* Add address to ban-list */
2084  if (ban) {
2085  bool contains = false;
2086  for (const auto &iter : _network_ban_list) {
2087  if (iter == ip) {
2088  contains = true;
2089  break;
2090  }
2091  }
2092  if (!contains) _network_ban_list.emplace_back(ip);
2093  }
2094 
2095  uint n = 0;
2096 
2097  /* There can be multiple clients with the same IP, kick them all */
2098  NetworkClientSocket *cs;
2100  if (cs->client_id == CLIENT_ID_SERVER) continue;
2101  if (cs->client_address.IsInNetmask(ip)) {
2102  NetworkServerKickClient(cs->client_id);
2103  n++;
2104  }
2105  }
2106 
2107  return n;
2108 }
2109 
2116 {
2117  const NetworkClientInfo *ci;
2118  FOR_ALL_CLIENT_INFOS(ci) {
2119  if (ci->client_playas == company) return true;
2120  }
2121  return false;
2122 }
2123 
2124 
2130 void ServerNetworkGameSocketHandler::GetClientName(char *client_name, const char *last) const
2131 {
2132  const NetworkClientInfo *ci = this->GetInfo();
2133 
2134  if (ci == nullptr || StrEmpty(ci->client_name)) {
2135  seprintf(client_name, last, "Client #%4d", this->client_id);
2136  } else {
2137  strecpy(client_name, ci->client_name, last);
2138  }
2139 }
2140 
2145 {
2146  NetworkClientInfo *ci;
2147  FOR_ALL_CLIENT_INFOS(ci) {
2148  if (_network_server) {
2149  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d IP: %s",
2150  ci->client_id,
2151  ci->client_name,
2152  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
2153  ci->client_id == CLIENT_ID_SERVER ? "server" : NetworkClientSocket::GetByClientID(ci->client_id)->GetClientIP());
2154  } else {
2155  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d",
2156  ci->client_id,
2157  ci->client_name,
2158  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0));
2159  }
2160  }
2161 }
2162 
2169 {
2170  assert(c != nullptr);
2171 
2172  if (!_network_server) return;
2173 
2175  _network_company_states[c->index].password[0] = '\0';
2177 
2178  if (ci != nullptr) {
2179  /* ci is nullptr when replaying, or for AIs. In neither case there is a client. */
2180  ci->client_playas = c->index;
2182  NetworkSendCommand(0, 0, 0, CMD_RENAME_PRESIDENT, nullptr, ci->client_name, c->index);
2183  }
2184 
2185  /* Announce new company on network. */
2186  NetworkAdminCompanyInfo(c, true);
2187 
2188  if (ci != nullptr) {
2189  /* ci is nullptr when replaying, or for AIs. In neither case there is a client.
2190  We need to send Admin port update here so that they first know about the new company
2191  and then learn about a possibly joining client (see FS#6025) */
2192  NetworkServerSendChat(NETWORK_ACTION_COMPANY_NEW, DESTTYPE_BROADCAST, 0, "", ci->client_id, c->index + 1);
2193  }
2194 }
Everything is okay.
Definition: core.h:25
Packet * packets
Packet queue of the savegame; send these "slowly" to the client.
static const uint NETWORK_CLIENT_NAME_LENGTH
The maximum length of a client&#39;s name, in bytes including &#39;\0&#39;.
Definition: config.h:49
NetworkRecvStatus SendMap()
This sends the map to the client.
static const uint NETWORK_CLIENTS_LENGTH
The maximum length for the list of clients that controls a company, in bytes including &#39;\0&#39;...
Definition: config.h:48
Owner
Enum for all companies/owners.
Definition: company_type.h:20
void NetworkServer_Tick(bool send_frame)
This is called every tick if this is a _network_server.
Send message/notice to all clients (All)
Definition: network_type.h:81
bool server_admin_chat
allow private chat for the server to be distributed to the admin network
void NetworkAdminCompanyUpdate(const Company *company)
Notify the admin network of company updates.
StationFacility facilities
The facilities that this station has.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:81
used in multiplayer to create a new companies etc.
Definition: command_type.h:280
The client is catching up the delayed frames.
static bool AllowConnection()
Whether an connection is allowed or not at this moment.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:257
void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, ClientID from_id, int64 data, bool from_admin)
Send an actual chat message.
Information about a single company.
Definition: tcp_game.h:44
Server tells everyone that someone is moved to another company.
Definition: tcp_game.h:106
NetworkRecvStatus SendNeedCompanyPassword()
Request the company password.
static void NetworkAutoCleanCompanies()
Check if the server has autoclean_companies activated Two things happen: 1) If a company is not prote...
NetworkRecvStatus SendCompanyUpdate()
Send an update about the company password states.
void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, CompanyID company)
Prepare a DoCommand to be send over the network.
bool IsNetworkCompatibleVersion(const char *other)
Checks whether the given version string is compatible with our version.
Definition: network.cpp:1160
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition: core.h:69
Container for all information known about a client.
Definition: network_base.h:25
The client has downloaded the map.
SOCKET sock
The socket currently connected to.
Definition: tcp.h:34
NetworkRecvStatus SendJoin(ClientID client_id)
Tell that a client joined.
uint32 _sync_seed_1
Seed to compare during sync checks.
Definition: network.cpp:73
uint32 _realtime_tick
The real time in the game.
Definition: debug.cpp:50
Internal entity of a packet.
Definition: packet.h:42
ServerNetworkGameSocketHandler * cs
Socket we are associated with.
The connection got closed.
Definition: tcp.h:22
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3199
GRFConfig * _grfconfig
First item in list of current GRF set up.
TextColour GetDrawStringCompanyColour(CompanyID company)
Get the colour for DrawString-subroutines which matches the colour of the company.
static char * strecat(char *dst, const char *src, const char *last)
Appends characters from one string to another.
Definition: depend.cpp:99
uint32 Recv_uint32()
Read a 32 bits integer from the packet.
Definition: packet.cpp:248
NetworkRecvStatus SendError(NetworkErrorCode error)
Send an error to the client, and close its connection.
Client list; Window numbers:
Definition: window_type.h:474
void NetworkServerMonthlyLoop()
Monthly "callback".
uint16 max_init_time
maximum amount of time, in game ticks, a client may take to initiate joining
byte last_token
The last random token we did send to verify the client is listening.
Train vehicle type.
Definition: vehicle_type.h:26
set p2 with the ClientID of the sending client.
Definition: command_type.h:396
A server tells that a client has hit an error and did quit.
Definition: tcp_game.h:122
int32 performance_history
Company score (scale 0-1000)
Definition: company_base.h:27
NetworkRecvStatus Receive_CLIENT_CHAT(Packet *p) override
Sends a chat-packet to the server: uint8 ID of the action (see NetworkAction).
ServerNetworkGameSocketHandler(SOCKET s)
Create a new socket for the server side of the game connection.
void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string)
Send an rcon reply to the client.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
Definition: string.cpp:409
int receive_limit
Amount of bytes that we can receive at this moment.
static void ResetUser(uint32 user)
Reset an user&#39;s OrderBackup if needed.
void Send_string(const char *data)
Sends a string over the network.
Definition: packet.cpp:150
Year inaugurated_year
Year of starting the company.
Definition: company_base.h:80
The server is full and has no place for you.
Definition: tcp_game.h:35
static ClientID _network_client_id
The identifier counter for new clients (is never decreased)
NetworkErrorCode
The error codes we send around in the protocols.
Definition: network_type.h:102
Ship vehicle type.
Definition: vehicle_type.h:28
NetworkRecvStatus SendCommand(const CommandPacket *cp)
Send a command to the client to execute.
ClientID client_id
Client identifier (same as ClientState->client_id)
Definition: network_base.h:26
NetworkRecvStatus Receive_CLIENT_ERROR(Packet *p) override
The client made an error and is quitting the game.
void NORETURN SlError(StringID string, const char *extra_msg)
Error handler.
Definition: saveload.cpp:328
void NetworkPopulateCompanyStats(NetworkCompanyStats *stats)
Populate the company stats.
The client is downloading the map.
Popup for the client list; Window numbers:
Definition: window_type.h:480
void Write(byte *buf, size_t size) override
Write a given number of bytes into the savegame.
uint8 autoclean_novehicles
remove companies with no vehicles after this many months
NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override
Close the network connection due to the given status.
ClientStatus status
Status of this client.
The client wants a new company.
Definition: company_type.h:36
void Send_uint8(uint8 data)
Package a 8 bits integer in the packet.
Definition: packet.cpp:98
NetworkRecvStatus SendClientInfo(NetworkClientInfo *ci)
Send the client information about a client.
uint32 p2
parameter p2.
Definition: command_type.h:480
NetworkRecvStatus SendWait()
Tell the client that its put in a waiting queue.
Template for TCP listeners.
Definition: tcp_listen.h:30
The client is authorizing with company password.
Vehicle data structure.
Definition: vehicle_base.h:212
static const uint MAX_CLIENTS
How many clients can we have.
Definition: network_type.h:18
Sending and receiving UDP messages.
GRF file is used statically (can be used in any MP game)
Definition: newgrf_config.h:26
The client is active within in the game.
NetworkRecvStatus SendChat(NetworkAction action, ClientID client_id, bool self_send, const char *msg, int64 data)
Send a chat message.
ClientID _redirect_console_to_client
If not invalid, redirect the console output to a client.
Definition: network.cpp:62
SaveOrLoadResult SaveWithFilter(SaveFilter *writer, bool threaded)
Save the game using a (writer) filter.
Definition: saveload.cpp:2544
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
NetworkRecvStatus Receive_CLIENT_MOVE(Packet *p) override
Request the server to move this client into another company: uint8 ID of the company the client wants...
static const int DAY_TICKS
1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885.
Definition: date_type.h:30
bool NetworkServerChangeClientName(ClientID client_id, const char *new_name)
Change the client name of the given client.
Send message/notice to only a certain client (Private)
Definition: network_type.h:83
void Send_uint32(uint32 data)
Package a 32 bits integer in the packet.
Definition: packet.cpp:119
Server distributing the message of a client (or itself).
Definition: tcp_game.h:98
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:50
static const TextColour CC_DEFAULT
Default colour of the console.
Definition: console_type.h:25
bool NetworkCompanyIsPassworded(CompanyID company_id)
Check if the company we want to join requires a password.
Definition: network.cpp:223
void NetworkPrintClients()
Print all the clients to the console.
Base core network types and some helper functions to access them.
uint16 bytes_per_frame_burst
how many bytes may, over a short period, be received?
bool HasPackets()
Checks whether there are packets.
void Append(CommandPacket *p)
Append a CommandPacket at the end of the queue.
Server tells the client what frame it is in, and thus to where the client may progress.
Definition: tcp_game.h:88
NetworkRecvStatus SendRConResult(uint16 colour, const char *command)
Send the result of a console action.
GRFIdentifier ident
grfid and md5sum to uniquely identify newgrfs
ClientID
&#39;Unique&#39; identifier to be given to clients
Definition: network_type.h:41
The admin gets information about this on a daily basis.
Definition: tcp_admin.h:93
CommandFlags GetCommandFlags(uint32 cmd)
Definition: command.cpp:386
The first client ID.
Definition: network_type.h:44
The server told us we made an error.
Definition: core.h:31
Year _cur_year
Current year, starting at 0.
Definition: date.cpp:26
NetworkRecvStatus SendNewGRFCheck()
Send the check for the NewGRFs.
virtual Packet * ReceivePacket()
Receives a packet for the given client.
Definition: tcp.cpp:147
static RoadVehicle * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
Definition: tcp.cpp:97
Server tells the client what the random state should be.
Definition: tcp_game.h:90
Class for handling the server side of the game connection.
struct GRFConfig * next
NOSAVE: Next item in the linked list.
NetworkRecvStatus Receive_CLIENT_GETMAP(Packet *p) override
Request the map from the server.
The client is not connected nor active.
static T SB(T &x, const uint8 s, const uint8 n, const U d)
Set n bits in x starting at bit s to d.
void NetworkUDPAdvertise()
Register us to the master server This function checks if it needs to send an advertise.
StringID GetNetworkErrorMsg(NetworkErrorCode err)
Retrieve the string id of an internal error number.
Definition: network.cpp:308
Server welcomes you and gives you your ClientID.
Definition: tcp_game.h:67
NetworkRecvStatus Receive_CLIENT_COMMAND(Packet *p) override
The client has done a command and wants us to handle it.
static const uint32 GENERATE_NEW_SEED
Create a new random seed.
Definition: genworld.h:26
static bool IsValidHumanID(size_t index)
Is this company a valid company, not controlled by a NoAI program?
Definition: company_base.h:152
The admin gets information about this on a monthly basis.
Definition: tcp_admin.h:95
bool _network_dedicated
are we a dedicated server?
Definition: network.cpp:57
Server tells the client that it is beginning to send the map.
Definition: tcp_game.h:73
CommandQueue incoming_queue
The command-queue awaiting handling.
Definition: tcp_game.h:522
assert_compile(MAX_CLIENT_SLOTS > MAX_CLIENTS)
Make very sure the preconditions given in network_type.h are actually followed.
uint16 months_empty
How many months the company is empty.
Definition: network_type.h:68
bool autoclean_companies
automatically remove companies that are not in use
void ProcessAsyncSaveFinish()
Handle async save finishes.
Definition: saveload.cpp:400
Response of the executed command on the server.
Definition: tcp_game.h:102
uint16 num_vehicle[NETWORK_VEH_END]
How many vehicles are there of this type?
Definition: network_type.h:60
static const size_t MAX_SIZE
Make template parameter accessible from outside.
Definition: pool_type.hpp:87
A server tells that a client has quit.
Definition: tcp_game.h:120
void NetworkServerNewCompany(const Company *c, NetworkClientInfo *ci)
Perform all the server specific administration of a new company.
Server distributes a command to (all) the clients.
Definition: tcp_game.h:94
The company is removed due to autoclean.
Definition: company_type.h:59
void NetworkAdminClientQuit(ClientID client_id)
Notify the admin network that a client quit (if they have opt in for the respective update)...
void StartNewGameWithoutGUI(uint32 seed)
Start a normal game without the GUI.
char password[NETWORK_PASSWORD_LENGTH]
The password for the company.
Definition: network_type.h:67
size_t total_size
Total size of the compressed savegame.
Server sends NewGRF IDs and MD5 checksums for the client to check.
Definition: tcp_game.h:57
void NetworkAdminUpdate(AdminUpdateFrequency freq)
Send (push) updates to the admin network as they have registered for these updates.
void GetClientName(char *client_name, const char *last) const
Get the name of the client, if the user did not send it yet, Client ID is used.
NetworkSettings network
settings related to the network
CompanyID client_playas
As which company is this client playing (CompanyID)
Definition: network_base.h:29
virtual bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Definition: vehicle_base.h:433
void NetworkUpdateClientInfo(ClientID client_id)
Send updated client info of a particular client.
static const uint NETWORK_RCONCOMMAND_LENGTH
The maximum length of a rconsole command, in bytes including &#39;\0&#39;.
Definition: config.h:50
uint32 last_frame
Last frame we have executed.
Definition: tcp_game.h:520
void Send_uint64(uint64 data)
Package a 64 bits integer in the packet.
Definition: packet.cpp:132
void NetworkSyncCommandQueue(NetworkClientSocket *cs)
Sync our local command queue to the command queue of the given socket.
Server sends you information about a client.
Definition: tcp_game.h:68
DateFract _date_fract
Fractional part of the day.
Definition: date.cpp:29
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
Definition: packet.h:54
NetworkAddress client_address
IP-address of the client (so he can be banned)
uint16 max_lag_time
maximum amount of time, in game ticks, a client may be lagging behind the server
The client is spectating.
Definition: company_type.h:37
Information about GRF, used in the game and (part of it) in savegames.
void SendCompanyInformation(Packet *p, const struct Company *c, const struct NetworkCompanyStats *stats, uint max_len=NETWORK_COMPANY_NAME_LENGTH)
Package some generic company information into a packet.
char client_name[NETWORK_CLIENT_NAME_LENGTH]
Name of the client.
Definition: network_base.h:27
Server part of the network protocol.
uint8 max_spectators
maximum amount of spectators
void Send_uint16(uint16 data)
Package a 16 bits integer in the packet.
Definition: packet.cpp:108
uint32 p1
parameter p1.
Definition: command_type.h:479
Server sends bits of the map to the client.
Definition: tcp_game.h:75
NetworkRecvStatus Receive_CLIENT_MAP_OK(Packet *p) override
Tell the server that we are done receiving/loading the map.
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)...
void IConsoleCmdExec(const char *cmdstr)
Execute a given command passed to us.
Definition: console.cpp:403
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:80
void Finish() override
Prepare everything to finish writing the savegame.
std::mutex lock
synchronization for playback status fields
Definition: win32_m.cpp:36
void CDECL IConsolePrintF(TextColour colour_code, const char *format,...)
Handle the printing of text entered into the console or redirected there by any other means...
Definition: console.cpp:126
void NetworkServerSetCompanyPassword(CompanyID company_id, const char *password, bool already_hashed)
Set/Reset a company password on the server end.
The client is waiting as someone else is downloading the map.
The admin gets information about this on a quarterly basis.
Definition: tcp_admin.h:96
static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
Handle the command-queue of a socket.
void CDECL usererror(const char *s,...)
Error handling for fatal user errors.
Definition: openttd.cpp:94
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...
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition: gfx_type.h:247
static void NetworkCheckRestartMap()
Check if we want to restart the map.
NetworkRecvStatus SendNeedGamePassword()
Request the game password.
NetworkCompanyState * _network_company_states
Statistics about some companies.
Definition: network.cpp:60
The client is authorizing with game (server) password.
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
Definition: gfx_type.h:306
NetworkRecvStatus Receive_CLIENT_COMPANY_PASSWORD(Packet *p) override
Send a password to the server to authorize uint8 Password type (see NetworkPasswordType).
NetworkRecvStatus Receive_CLIENT_RCON(Packet *p) override
Send an RCon command to the server: string RCon password.
uint8 flags
NOSAVE: GCF_Flags, bitset.
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
Definition: core.h:24
Writing a savegame directly to a number of packets.
#define FOR_ALL_CLIENT_INFOS(var)
Iterate over all the clients.
Definition: network_base.h:53
const char * GetHostname()
Get the hostname; in case it wasn&#39;t given the IPv4 dotted representation is given.
Definition: address.cpp:24
All packets in the queue are sent.
Definition: tcp.h:25
byte clients_on
Current count of clients on server.
Definition: game.h:28
static const uint NETWORK_CHAT_LENGTH
The maximum length of a chat message, in bytes including &#39;\0&#39;.
Definition: config.h:52
bool is_ai
If true, the company is (also) controlled by the computer (a NoAI program).
Definition: company_base.h:95
Money money
Money owned by the company.
Definition: company_base.h:67
virtual Packet * ReceivePacket() override
Receives a packet for the given client.
uint16 max_commands_in_queue
how many commands may there be in the incoming queue before dropping the connection?
void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data, bool from_admin)
Send chat to the admin network (if they did opt in for the respective update).
PacketSize size
The size of the whole packet for received packets.
Definition: packet.h:50
NetworkLanguage
Language ids for server_lang and client_lang.
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:273
bool DoCommandP(const CommandContainer *container, bool my_cmd)
Shortcut for the long DoCommandP when having a container with the data.
Definition: command.cpp:534
CompanyID company
company that is executing the command
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
NetworkServerGameInfo _network_game_info
Information about our game.
Definition: network.cpp:59
The buffer is still full, so no (parts of) packets could be sent.
Definition: tcp.h:23
uint last_packet
Time we received the last frame.
Definition: tcp_game.h:523
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
char rcon_password[NETWORK_PASSWORD_LENGTH]
password for rconsole (server side)
NetworkClientInfo * GetInfo() const
Gets the client info of this socket handler.
Definition: tcp_game.h:548
#define FOR_ALL_CLIENT_SOCKETS(var)
Iterate over all the sockets.
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).
uint32 frame
the frame in which this packet is executed
the command can only be initiated by the server
Definition: command_type.h:389
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
Delete a company.
Definition: company_type.h:69
Server sending an error message to the client.
Definition: tcp_game.h:40
NetworkRecvStatus SendFrame()
Tell the client that they may run to a particular frame.
uint Count() const
Get the number of items in the queue.
Definition: tcp_game.h:146
NetworkRecvStatus SendNewGame()
Tell the client we&#39;re starting a new game.
Packet * next
The next packet.
Definition: packet.h:44
Date join_date
Gamedate the client has joined.
Definition: network_base.h:30
Packet * PopPacket()
Pop a single created packet from the queue with packets.
Base class for all pools.
Definition: pool_type.hpp:83
uint8 max_companies
maximum amount of companies
uint16 sync_freq
how often do we check whether we are still in-sync
NetworkRecvStatus SendQuit(ClientID client_id)
Tell the client another client quit.
The connection is &#39;just&#39; lost.
Definition: core.h:29
the command may be initiated by a spectator
Definition: command_type.h:390
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:37
uint8 autoclean_unprotected
remove passwordless companies after this many months
ClientID client_id
Client identifier.
Definition: tcp_game.h:519
Month _cur_month
Current month (0..11)
Definition: date.cpp:27
NetworkRecvStatus SendSync()
Request the client to sync.
uint32 last_frame_server
Last frame the server has executed.
Definition: tcp_game.h:521
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don&#39;t get linker errors.
Definition: pool_func.hpp:226
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1146
Station with an airport.
Definition: station_type.h:57
NetworkRecvStatus SendWelcome()
Send the client a welcome message with some basic information.
uint16 max_password_time
maximum amount of time, in game ticks, a client may take to enter the password
Station with a dock.
Definition: station_type.h:58
byte _network_clients_connected
The amount of clients connected.
Definition: network.cpp:93
bool NetworkCompanyHasClients(CompanyID company)
Check whether a particular company has clients.
bool IsBus() const
Check whether a roadvehicle is a bus.
Definition: roadveh_cmd.cpp:81
uint8 Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:219
NetworkRecvStatus Receive_CLIENT_JOIN(Packet *p) override
Try to join the server: string OpenTTD revision (norev000 if no revision).
Tells clients that a new client has joined.
Definition: tcp_game.h:79
uint32 generation_seed
noise seed for world generation
Some network configuration important to the client changed.
Definition: tcp_game.h:112
The admin gets information about this on a yearly basis.
Definition: tcp_admin.h:97
NetworkRecvStatus SendCompanyInfo()
Send the client information about the companies.
void SetInfo(NetworkClientInfo *info)
Sets the client info for this socket handler.
Definition: tcp_game.h:538
uint32 _frame_counter
The current frame.
Definition: network.cpp:70
uint64 Recv_uint64()
Read a 64 bits integer from the packet.
Definition: packet.cpp:265
void Destroy()
Begin the destruction of this packet writer.
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:59
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:276
NetworkRecvStatus SendConfigUpdate()
Send an update about the max company/spectator counts.
char network_id[NETWORK_SERVER_ID_LENGTH]
network ID for servers
const char * GetClientIP()
Get the IP address/hostname of the connected client.
The admin gets information about this on a weekly basis.
Definition: tcp_admin.h:94
CompanyMask _network_company_passworded
Bitmask of the password status of all companies.
Definition: network.cpp:82
The server is preparing to start a new game.
Definition: tcp_game.h:115
void NetworkServerDailyLoop()
Daily "callback".
uint8 max_clients
maximum amount of clients
std::condition_variable exit_sig
Signal for threaded destruction of this packet writer.
static const uint NETWORK_COMPANY_NAME_LENGTH
The maximum length of the company name, in bytes including &#39;\0&#39;.
Definition: config.h:43
PacketWriter(ServerNetworkGameSocketHandler *cs)
Create the packet writer.
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
Definition: openttd.cpp:114
void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded)
Tell that a particular company is (not) passworded.
Server tells it has just sent the last bits of the map to the client.
Definition: tcp_game.h:76
Server tells the client what the (compressed) size of the map is.
Definition: tcp_game.h:74
change the president name
Definition: command_type.h:247
uint16 num_station[NETWORK_VEH_END]
How many stations are there of this type?
Definition: network_type.h:61
CompanyEconomyEntry old_economy[MAX_HISTORY_QUARTERS]
Economic data of the company of the last MAX_HISTORY_QUARTERS quarters.
Definition: company_base.h:99
Server tells the client there are some people waiting for the map as well.
Definition: tcp_game.h:72
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: depend.cpp:68
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:54
void NetworkServerYearlyLoop()
Yearly "callback".
void AppendQueue()
Append the current packet to the queue.
void NetworkAdminCompanyInfo(const Company *company, bool new_company)
Notify the admin network of company details.
Maximum number of companies.
Definition: company_type.h:25
void NetworkServerSendConfigUpdate()
Send Config Update.
StringList _network_ban_list
The banned clients.
Definition: network.cpp:67
std::mutex mutex
Mutex for making threaded saving safe.
const char * GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed)
Hash the given password using server ID and game seed.
Definition: network.cpp:192
const char * ReceiveCommand(Packet *p, CommandPacket *cp)
Receives a command from the network.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:216
NetworkClientSocketPool _networkclientsocket_pool("NetworkClientSocket")
The pool with clients.
bool NetworkFindName(char *new_name, const char *last)
Check whether a name is unique, and otherwise try to make it unique.
The packets are partly sent; there are more packets to be sent in the queue.
Definition: tcp.h:24
NetworkRecvStatus SendShutdown()
Tell the client we&#39;re shutting down.
static const uint16 SEND_MTU
Number of bytes we can pack in a single packet.
Definition: config.h:35
void NetworkServerKickClient(ClientID client_id)
Kick a single client.
NetworkRecvStatus Receive_CLIENT_ACK(Packet *p) override
Tell the server we are done with this frame: uint32 Current frame counter of the client.
NetworkRecvStatus Receive_CLIENT_GAME_PASSWORD(Packet *p) override
Send a password to the server to authorize: uint8 Password type (see NetworkPasswordType).
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban)
Ban, or kick, everyone joined from the given client&#39;s IP.
bool _network_server
network-server is active
Definition: network.cpp:55
Owner owner
The owner of this station.
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:235
~PacketWriter()
Make sure everything is cleaned up.
static const TextColour CC_ERROR
Colour for error lines.
Definition: console_type.h:26
uint32 _last_sync_frame
Used in the server to store the last time a sync packet was sent to clients.
Definition: network.cpp:71
Everything we need to know about a command to be able to execute it.
static const uint MAX_CLIENT_SLOTS
The number of slots; must be at least 1 more than MAX_CLIENTS.
Definition: network_type.h:25
Station with bus stops.
Definition: station_type.h:56
Server requests the (hashed) game password.
Definition: tcp_game.h:61
Client is not part of anything.
Definition: network_type.h:42
NetworkRecvStatus SendMove(ClientID client_id, CompanyID company_id)
Tell that a client moved to another company.
NetworkRecvStatus SendErrorQuit(ClientID client_id, NetworkErrorCode errorno)
Tell the client another client quit with an error.
uint32 last_token_frame
The last frame we received the right token.
Money yearly_expenses[3][EXPENSES_END]
Expenses of the company for the last three years, in every ExpensesType category. ...
Definition: company_base.h:97
Aircraft vehicle type.
Definition: vehicle_type.h:29
We apparently send a malformed packet.
Definition: core.h:30
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:131
NetworkRecvStatus Receive_CLIENT_QUIT(Packet *p) override
The client is quitting the game.
Server requests the (hashed) company password.
Definition: tcp_game.h:63
static const uint NETWORK_NAME_LENGTH
The maximum length of the server name and map name, in bytes including &#39;\0&#39;.
Definition: config.h:42
virtual void SendPacket(Packet *packet)
This function puts the packet in the send-queue and it is send as soon as possible.
Definition: tcp.cpp:63
Simple calculated statistics of a company.
Definition: network_type.h:59
uint16 max_download_time
maximum amount of time, in game ticks, a client may take to download the map
static const uint NETWORK_PASSWORD_LENGTH
The maximum length of the password, in bytes including &#39;\0&#39; (must be >= NETWORK_SERVER_ID_LENGTH) ...
Definition: config.h:47
void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
Notify the admin network of a client update (if they did opt in for the respective update)...
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
completed successfully
Definition: saveload.h:312
#define FOR_ALL_VEHICLES(var)
Iterate over all vehicles.
Definition: vehicle_base.h:987
Station with truck stops.
Definition: station_type.h:55
Servers always have this ID.
Definition: network_type.h:43
#define DECLARE_POSTFIX_INCREMENT(enum_type)
Some enums need to have allowed incrementing (i.e.
Definition: enum_type.hpp:16
uint16 bytes_per_frame
how many bytes may, over a long period, be received per frame?
GameCreationSettings game_creation
settings used during the creation of a game (map)
The server has banned you.
Definition: tcp_game.h:36
NetworkRecvStatus Receive_CLIENT_NEWGRFS_CHECKED(Packet *p) override
Tell the server that we have the required GRFs.
uint8 autoclean_protected
remove the password from passworded companies after this many months
Base socket handler for all TCP sockets.
Definition: tcp_game.h:150
void Send_bool(bool data)
Package a boolean in the packet.
Definition: packet.cpp:89
Station with train station.
Definition: station_type.h:54
uint16 max_join_time
maximum amount of time, in game ticks, a client may take to sync up during joining ...
Money company_value
The value of the company.
Definition: company_base.h:28
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it&#39;s client-identifier.
Definition: network.cpp:124
static const byte NETWORK_COMPANY_INFO_VERSION
What version of company info is this?
Definition: config.h:39
Interface for filtering a savegame till it is written.
NetworkRecvStatus Receive_CLIENT_COMPANY_INFO(Packet *p) override
Request company information (in detail).
char server_password[NETWORK_PASSWORD_LENGTH]
password for joining this server
void SendCommand(Packet *p, const CommandPacket *cp)
Sends a command over the network.
static const uint NETWORK_REVISION_LENGTH
The maximum length of the revision, in bytes including &#39;\0&#39;.
Definition: config.h:46
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3227
bool my_cmd
did the command originate from "me"
~ServerNetworkGameSocketHandler()
Clear everything related to this client.
void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
Handle the tid-bits of moving a client from one company to another.
Date _date
Current date in days (day counter)
Definition: date.cpp:28
The server is shutting down.
Definition: tcp_game.h:116
Company view; Window numbers:
Definition: window_type.h:364
uint16 PacketSize
Size of the whole packet.
Definition: packet.h:21
void NetworkServerShowStatusToConsole()
Show the status message of all clients on the console.
static const TextColour CC_WARNING
Colour for warning lines.
Definition: console_type.h:27
void SendGRFIdentifier(Packet *p, const GRFIdentifier *grf)
Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet.
Definition: core.cpp:59
Send message/notice to everyone playing the same company (Team)
Definition: network_type.h:82
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
uint32 _frame_counter_max
To where we may go with our clients.
Definition: network.cpp:69
static void Send()
Send the packets for the server sockets.
Station data structure.
Definition: station_base.h:452
uint32 cmd
command being executed.
Definition: command_type.h:481
DestType
Destination of our chat messages.
Definition: network_type.h:80
NetworkRecvStatus Receive_CLIENT_SET_NAME(Packet *p) override
Gives the client a new name: string New name of the client.
byte client_lang
The language of the client.
Definition: network_base.h:28
Road vehicle type.
Definition: vehicle_type.h:27
NetworkAction
Actions that can be used for NetworkTextMessage.
Definition: network_type.h:87
NetworkRecvStatus Receive_CLIENT_SET_PASSWORD(Packet *p) override
Set the password for the clients current company: string The password.
Information (password) of a company changed.
Definition: tcp_game.h:111
static const TextColour CC_INFO
Colour for information lines.
Definition: console_type.h:28
Year restart_game_year
year the server restarts
struct PacketWriter * savegame
Writer used to write the savegame.
void Recv_string(char *buffer, size_t size, StringValidationSettings settings=SVS_REPLACE_WITH_QUESTION_MARK)
Reads a string till it finds a &#39;\0&#39; in the stream.
Definition: packet.cpp:288
Server part of the admin network protocol.
Packet * current
The packet we&#39;re currently writing to.
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:201