OpenTTD Source  1.10.0-RC1
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 "../date_func.h"
13 #include "network_admin.h"
14 #include "network_server.h"
15 #include "network_udp.h"
16 #include "network_base.h"
17 #include "../console_func.h"
18 #include "../company_base.h"
19 #include "../command_func.h"
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 "../roadveh.h"
27 #include "../order_backup.h"
28 #include "../core/pool_func.hpp"
29 #include "../core/random_func.hpp"
30 #include "../rev.h"
31 #include <mutex>
32 #include <condition_variable>
33 
34 #include "../safeguards.h"
35 
36 
37 /* This file handles all the server-commands */
38 
42 
47 
50 INSTANTIATE_POOL_METHODS(NetworkClientSocket)
51 
54 
57  ServerNetworkGameSocketHandler *cs;
59  size_t total_size;
61  std::mutex mutex;
62  std::condition_variable exit_sig;
63 
68  PacketWriter(ServerNetworkGameSocketHandler *cs) : SaveFilter(nullptr), cs(cs), current(nullptr), total_size(0), packets(nullptr)
69  {
70  }
71 
74  {
75  std::unique_lock<std::mutex> lock(this->mutex);
76 
77  if (this->cs != nullptr) this->exit_sig.wait(lock);
78 
79  /* This must all wait until the Destroy function is called. */
80 
81  while (this->packets != nullptr) {
82  Packet *p = this->packets->next;
83  delete this->packets;
84  this->packets = p;
85  }
86 
87  delete this->current;
88  }
89 
100  void Destroy()
101  {
102  std::unique_lock<std::mutex> lock(this->mutex);
103 
104  this->cs = nullptr;
105 
106  this->exit_sig.notify_all();
107  lock.unlock();
108 
109  /* Make sure the saving is completely cancelled. Yes,
110  * we need to handle the save finish as well as the
111  * next connection might just be requesting a map. */
112  WaitTillSaved();
114  }
115 
123  bool HasPackets()
124  {
125  return this->packets != nullptr;
126  }
127 
132  {
133  std::lock_guard<std::mutex> lock(this->mutex);
134 
135  Packet *p = this->packets;
136  this->packets = p->next;
137  p->next = nullptr;
138 
139  return p;
140  }
141 
143  void AppendQueue()
144  {
145  if (this->current == nullptr) return;
146 
147  Packet **p = &this->packets;
148  while (*p != nullptr) {
149  p = &(*p)->next;
150  }
151  *p = this->current;
152 
153  this->current = nullptr;
154  }
155 
156  void Write(byte *buf, size_t size) override
157  {
158  /* We want to abort the saving when the socket is closed. */
159  if (this->cs == nullptr) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
160 
161  if (this->current == nullptr) this->current = new Packet(PACKET_SERVER_MAP_DATA);
162 
163  std::lock_guard<std::mutex> lock(this->mutex);
164 
165  byte *bufe = buf + size;
166  while (buf != bufe) {
167  size_t to_write = min(SEND_MTU - this->current->size, bufe - buf);
168  memcpy(this->current->buffer + this->current->size, buf, to_write);
169  this->current->size += (PacketSize)to_write;
170  buf += to_write;
171 
172  if (this->current->size == SEND_MTU) {
173  this->AppendQueue();
174  if (buf != bufe) this->current = new Packet(PACKET_SERVER_MAP_DATA);
175  }
176  }
177 
178  this->total_size += size;
179  }
180 
181  void Finish() override
182  {
183  /* We want to abort the saving when the socket is closed. */
184  if (this->cs == nullptr) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
185 
186  std::lock_guard<std::mutex> lock(this->mutex);
187 
188  /* Make sure the last packet is flushed. */
189  this->AppendQueue();
190 
191  /* Add a packet stating that this is the end to the queue. */
192  this->current = new Packet(PACKET_SERVER_MAP_DONE);
193  this->AppendQueue();
194 
195  /* Fast-track the size to the client. */
197  p->Send_uint32((uint32)this->total_size);
198  this->cs->NetworkTCPSocketHandler::SendPacket(p);
199  }
200 };
201 
202 
208 {
209  this->status = STATUS_INACTIVE;
210  this->client_id = _network_client_id++;
212 
213  /* The Socket and Info pools need to be the same in size. After all,
214  * each Socket will be associated with at most one Info object. As
215  * such if the Socket was allocated the Info object can as well. */
217 }
218 
223 {
226 
227  if (this->savegame != nullptr) {
228  this->savegame->Destroy();
229  this->savegame = nullptr;
230  }
231 }
232 
234 {
235  /* Only allow receiving when we have some buffer free; this value
236  * can go negative, but eventually it will become positive again. */
237  if (this->receive_limit <= 0) return nullptr;
238 
239  /* We can receive a packet, so try that and if needed account for
240  * the amount of received data. */
242  if (p != nullptr) this->receive_limit -= p->size;
243  return p;
244 }
245 
247 {
248  assert(status != NETWORK_RECV_STATUS_OKAY);
249  /*
250  * Sending a message just before leaving the game calls cs->SendPackets.
251  * This might invoke this function, which means that when we close the
252  * connection after cs->SendPackets we will close an already closed
253  * connection. This handles that case gracefully without having to make
254  * that code any more complex or more aware of the validity of the socket.
255  */
256  if (this->sock == INVALID_SOCKET) return status;
257 
258  if (status != NETWORK_RECV_STATUS_CONN_LOST && !this->HasClientQuit() && this->status >= STATUS_AUTHORIZED) {
259  /* We did not receive a leave message from this client... */
260  char client_name[NETWORK_CLIENT_NAME_LENGTH];
261 
262  this->GetClientName(client_name, lastof(client_name));
263 
264  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST);
265 
266  /* Inform other clients of this... strange leaving ;) */
267  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
268  if (new_cs->status > STATUS_AUTHORIZED && this != new_cs) {
269  new_cs->SendErrorQuit(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
270  }
271  }
272  }
273 
274  NetworkAdminClientError(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
275  DEBUG(net, 1, "Closed client connection %d", this->client_id);
276 
277  /* We just lost one client :( */
278  if (this->status >= STATUS_AUTHORIZED) _network_game_info.clients_on--;
279  extern byte _network_clients_connected;
280  _network_clients_connected--;
281 
284 
285  this->SendPackets(true);
286 
287  delete this->GetInfo();
288  delete this;
289 
290  return status;
291 }
292 
298 {
299  extern byte _network_clients_connected;
300  bool accept = _network_clients_connected < MAX_CLIENTS && _network_game_info.clients_on < _settings_client.network.max_clients;
301 
302  /* We can't go over the MAX_CLIENTS limit here. However, the
303  * pool must have place for all clients and ourself. */
306  return accept;
307 }
308 
311 {
312  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
313  if (cs->writable) {
314  if (cs->SendPackets() != SPS_CLOSED && cs->status == STATUS_MAP) {
315  /* This client is in the middle of a map-send, call the function for that */
316  cs->SendMap();
317  }
318  }
319  }
320 }
321 
322 static void NetworkHandleCommandQueue(NetworkClientSocket *cs);
323 
324 /***********
325  * Sending functions
326  * DEF_SERVER_SEND_COMMAND has parameter: NetworkClientSocket *cs
327  ************/
328 
334 {
335  if (ci->client_id != INVALID_CLIENT_ID) {
337  p->Send_uint32(ci->client_id);
338  p->Send_uint8 (ci->client_playas);
339  p->Send_string(ci->client_name);
340 
341  this->SendPacket(p);
342  }
344 }
345 
348 {
349  /* Fetch the latest version of the stats */
350  NetworkCompanyStats company_stats[MAX_COMPANIES];
351  NetworkPopulateCompanyStats(company_stats);
352 
353  /* Make a list of all clients per company */
354  char clients[MAX_COMPANIES][NETWORK_CLIENTS_LENGTH];
355  memset(clients, 0, sizeof(clients));
356 
357  /* Add the local player (if not dedicated) */
359  if (ci != nullptr && Company::IsValidID(ci->client_playas)) {
360  strecpy(clients[ci->client_playas], ci->client_name, lastof(clients[ci->client_playas]));
361  }
362 
363  for (NetworkClientSocket *csi : NetworkClientSocket::Iterate()) {
364  char client_name[NETWORK_CLIENT_NAME_LENGTH];
365 
366  ((ServerNetworkGameSocketHandler*)csi)->GetClientName(client_name, lastof(client_name));
367 
368  ci = csi->GetInfo();
369  if (ci != nullptr && Company::IsValidID(ci->client_playas)) {
370  if (!StrEmpty(clients[ci->client_playas])) {
371  strecat(clients[ci->client_playas], ", ", lastof(clients[ci->client_playas]));
372  }
373 
374  strecat(clients[ci->client_playas], client_name, lastof(clients[ci->client_playas]));
375  }
376  }
377 
378  /* Now send the data */
379 
380  Packet *p;
381 
382  for (const Company *company : Company::Iterate()) {
384 
386  p->Send_bool (true);
387  this->SendCompanyInformation(p, company, &company_stats[company->index]);
388 
389  if (StrEmpty(clients[company->index])) {
390  p->Send_string("<none>");
391  } else {
392  p->Send_string(clients[company->index]);
393  }
394 
395  this->SendPacket(p);
396  }
397 
399 
401  p->Send_bool (false);
402 
403  this->SendPacket(p);
405 }
406 
413 {
414  char str[100];
416 
417  p->Send_uint8(error);
418  if (reason != nullptr) p->Send_string(reason);
419  this->SendPacket(p);
420 
421  StringID strid = GetNetworkErrorMsg(error);
422  GetString(str, strid, lastof(str));
423 
424  /* Only send when the current client was in game */
425  if (this->status > STATUS_AUTHORIZED) {
426  char client_name[NETWORK_CLIENT_NAME_LENGTH];
427 
428  this->GetClientName(client_name, lastof(client_name));
429 
430  DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
431 
432  if (error == NETWORK_ERROR_KICKED && reason != nullptr) {
433  NetworkTextMessage(NETWORK_ACTION_KICKED, CC_DEFAULT, false, client_name, reason, strid);
434  } else {
435  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid);
436  }
437 
438  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
439  if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
440  /* Some errors we filter to a more general error. Clients don't have to know the real
441  * reason a joining failed. */
442  if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION) {
443  error = NETWORK_ERROR_ILLEGAL_PACKET;
444  }
445  new_cs->SendErrorQuit(this->client_id, error);
446  }
447  }
448 
449  NetworkAdminClientError(this->client_id, error);
450  } else {
451  DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", this->client_id, str);
452  }
453 
454  /* The client made a mistake, so drop his connection now! */
456 }
457 
460 {
462  const GRFConfig *c;
463  uint grf_count = 0;
464 
465  for (c = _grfconfig; c != nullptr; c = c->next) {
466  if (!HasBit(c->flags, GCF_STATIC)) grf_count++;
467  }
468 
469  p->Send_uint8 (grf_count);
470  for (c = _grfconfig; c != nullptr; c = c->next) {
471  if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident);
472  }
473 
474  this->SendPacket(p);
476 }
477 
480 {
481  /* Invalid packet when status is STATUS_AUTH_GAME or higher */
483 
484  this->status = STATUS_AUTH_GAME;
485  /* Reset 'lag' counters */
487 
489  this->SendPacket(p);
491 }
492 
495 {
496  /* Invalid packet when status is STATUS_AUTH_COMPANY or higher */
498 
499  this->status = STATUS_AUTH_COMPANY;
500  /* Reset 'lag' counters */
502 
506  this->SendPacket(p);
508 }
509 
512 {
513  Packet *p;
514 
515  /* Invalid packet when status is AUTH or higher */
517 
518  this->status = STATUS_AUTHORIZED;
519  /* Reset 'lag' counters */
521 
523 
524  p = new Packet(PACKET_SERVER_WELCOME);
525  p->Send_uint32(this->client_id);
528  this->SendPacket(p);
529 
530  /* Transmit info about all the active clients */
531  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
532  if (new_cs != this && new_cs->status > STATUS_AUTHORIZED) {
533  this->SendClientInfo(new_cs->GetInfo());
534  }
535  }
536  /* Also send the info of the server */
538 }
539 
542 {
543  int waiting = 0;
544  Packet *p;
545 
546  /* Count how many clients are waiting in the queue, in front of you! */
547  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
548  if (new_cs->status != STATUS_MAP_WAIT) continue;
549  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++;
550  }
551 
552  p = new Packet(PACKET_SERVER_WAIT);
553  p->Send_uint8(waiting);
554  this->SendPacket(p);
556 }
557 
560 {
561  static uint sent_packets; // How many packets we did send successfully last time
562 
563  if (this->status < STATUS_AUTHORIZED) {
564  /* Illegal call, return error and ignore the packet */
565  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
566  }
567 
568  if (this->status == STATUS_AUTHORIZED) {
569  this->savegame = new PacketWriter(this);
570 
571  /* Now send the _frame_counter and how many packets are coming */
574  this->SendPacket(p);
575 
577  this->status = STATUS_MAP;
578  /* Mark the start of download */
579  this->last_frame = _frame_counter;
581 
582  sent_packets = 4; // We start with trying 4 packets
583 
584  /* Make a dump of the current game */
585  if (SaveWithFilter(this->savegame, true) != SL_OK) usererror("network savedump failed");
586  }
587 
588  if (this->status == STATUS_MAP) {
589  bool last_packet = false;
590  bool has_packets = false;
591 
592  for (uint i = 0; (has_packets = this->savegame->HasPackets()) && i < sent_packets; i++) {
593  Packet *p = this->savegame->PopPacket();
594  last_packet = p->buffer[2] == PACKET_SERVER_MAP_DONE;
595 
596  this->SendPacket(p);
597 
598  if (last_packet) {
599  /* There is no more data, so break the for */
600  break;
601  }
602  }
603 
604  if (last_packet) {
605  /* Done reading, make sure saving is done as well */
606  this->savegame->Destroy();
607  this->savegame = nullptr;
608 
609  /* Set the status to DONE_MAP, no we will wait for the client
610  * to send it is ready (maybe that happens like never ;)) */
611  this->status = STATUS_DONE_MAP;
612 
613  /* Find the best candidate for joining, i.e. the first joiner. */
614  NetworkClientSocket *best = nullptr;
615  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
616  if (new_cs->status == STATUS_MAP_WAIT) {
617  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)) {
618  best = new_cs;
619  }
620  }
621  }
622 
623  /* Is there someone else to join? */
624  if (best != nullptr) {
625  /* Let the first start joining. */
626  best->status = STATUS_AUTHORIZED;
627  best->SendMap();
628 
629  /* And update the rest. */
630  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
631  if (new_cs->status == STATUS_MAP_WAIT) new_cs->SendWait();
632  }
633  }
634  }
635 
636  switch (this->SendPackets()) {
637  case SPS_CLOSED:
639 
640  case SPS_ALL_SENT:
641  /* All are sent, increase the sent_packets */
642  if (has_packets) sent_packets *= 2;
643  break;
644 
645  case SPS_PARTLY_SENT:
646  /* Only a part is sent; leave the transmission state. */
647  break;
648 
649  case SPS_NONE_SENT:
650  /* Not everything is sent, decrease the sent_packets */
651  if (sent_packets > 1) sent_packets /= 2;
652  break;
653  }
654  }
656 }
657 
663 {
664  Packet *p = new Packet(PACKET_SERVER_JOIN);
665 
666  p->Send_uint32(client_id);
667 
668  this->SendPacket(p);
670 }
671 
674 {
678 #ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
680 #ifdef NETWORK_SEND_DOUBLE_SEED
681  p->Send_uint32(_sync_seed_2);
682 #endif
683 #endif
684 
685  /* If token equals 0, we need to make a new token and send that. */
686  if (this->last_token == 0) {
687  this->last_token = InteractiveRandomRange(UINT8_MAX - 1) + 1;
688  p->Send_uint8(this->last_token);
689  }
690 
691  this->SendPacket(p);
693 }
694 
697 {
698  Packet *p = new Packet(PACKET_SERVER_SYNC);
701 
702 #ifdef NETWORK_SEND_DOUBLE_SEED
703  p->Send_uint32(_sync_seed_2);
704 #endif
705  this->SendPacket(p);
707 }
708 
714 {
716 
718  p->Send_uint32(cp->frame);
719  p->Send_bool (cp->my_cmd);
720 
721  this->SendPacket(p);
723 }
724 
734 {
736 
737  Packet *p = new Packet(PACKET_SERVER_CHAT);
738 
739  p->Send_uint8 (action);
740  p->Send_uint32(client_id);
741  p->Send_bool (self_send);
742  p->Send_string(msg);
743  p->Send_uint64(data);
744 
745  this->SendPacket(p);
747 }
748 
755 {
757 
758  p->Send_uint32(client_id);
759  p->Send_uint8 (errorno);
760 
761  this->SendPacket(p);
763 }
764 
770 {
771  Packet *p = new Packet(PACKET_SERVER_QUIT);
772 
773  p->Send_uint32(client_id);
774 
775  this->SendPacket(p);
777 }
778 
781 {
783  this->SendPacket(p);
785 }
786 
789 {
791  this->SendPacket(p);
793 }
794 
801 {
802  Packet *p = new Packet(PACKET_SERVER_RCON);
803 
804  p->Send_uint16(colour);
805  p->Send_string(command);
806  this->SendPacket(p);
808 }
809 
816 {
817  Packet *p = new Packet(PACKET_SERVER_MOVE);
818 
819  p->Send_uint32(client_id);
820  p->Send_uint8(company_id);
821  this->SendPacket(p);
823 }
824 
827 {
829 
831  this->SendPacket(p);
833 }
834 
837 {
839 
842  this->SendPacket(p);
844 }
845 
846 /***********
847  * Receiving functions
848  * DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientSocket *cs, Packet *p
849  ************/
850 
852 {
853  return this->SendCompanyInfo();
854 }
855 
857 {
858  if (this->status != STATUS_NEWGRFS_CHECK) {
859  /* Illegal call, return error and ignore the packet */
860  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
861  }
862 
863  NetworkClientInfo *ci = this->GetInfo();
864 
865  /* We now want a password from the client else we do not allow him in! */
867  return this->SendNeedGamePassword();
868  }
869 
871  return this->SendNeedCompanyPassword();
872  }
873 
874  return this->SendWelcome();
875 }
876 
878 {
879  if (this->status != STATUS_INACTIVE) {
880  /* Illegal call, return error and ignore the packet */
881  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
882  }
883 
884  char name[NETWORK_CLIENT_NAME_LENGTH];
885  CompanyID playas;
886  NetworkLanguage client_lang;
887  char client_revision[NETWORK_REVISION_LENGTH];
888 
889  p->Recv_string(client_revision, sizeof(client_revision));
890  uint32 newgrf_version = p->Recv_uint32();
891 
892  /* Check if the client has revision control enabled */
893  if (!IsNetworkCompatibleVersion(client_revision) || _openttd_newgrf_version != newgrf_version) {
894  /* Different revisions!! */
895  return this->SendError(NETWORK_ERROR_WRONG_REVISION);
896  }
897 
898  p->Recv_string(name, sizeof(name));
899  playas = (Owner)p->Recv_uint8();
900  client_lang = (NetworkLanguage)p->Recv_uint8();
901 
902  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
903 
904  /* join another company does not affect these values */
905  switch (playas) {
906  case COMPANY_NEW_COMPANY: // New company
908  return this->SendError(NETWORK_ERROR_FULL);
909  }
910  break;
911  case COMPANY_SPECTATOR: // Spectator
912  if (NetworkSpectatorCount() >= _settings_client.network.max_spectators) {
913  return this->SendError(NETWORK_ERROR_FULL);
914  }
915  break;
916  default: // Join another company (companies 1-8 (index 0-7))
917  if (!Company::IsValidHumanID(playas)) {
918  return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
919  }
920  break;
921  }
922 
923  /* We need a valid name.. make it Player */
924  if (StrEmpty(name)) strecpy(name, "Player", lastof(name));
925 
926  if (!NetworkFindName(name, lastof(name))) { // Change name if duplicate
927  /* We could not create a name for this client */
928  return this->SendError(NETWORK_ERROR_NAME_IN_USE);
929  }
930 
933  this->SetInfo(ci);
934  ci->join_date = _date;
935  strecpy(ci->client_name, name, lastof(ci->client_name));
936  ci->client_playas = playas;
937  ci->client_lang = client_lang;
938  DEBUG(desync, 1, "client: %08x; %02x; %02x; %02x", _date, _date_fract, (int)ci->client_playas, (int)ci->index);
939 
940  /* Make sure companies to which people try to join are not autocleaned */
942 
944 
945  if (_grfconfig == nullptr) {
946  /* Behave as if we received PACKET_CLIENT_NEWGRFS_CHECKED */
947  return this->Receive_CLIENT_NEWGRFS_CHECKED(nullptr);
948  }
949 
950  return this->SendNewGRFCheck();
951 }
952 
954 {
955  if (this->status != STATUS_AUTH_GAME) {
956  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
957  }
958 
959  char password[NETWORK_PASSWORD_LENGTH];
960  p->Recv_string(password, sizeof(password));
961 
962  /* Check game password. Allow joining if we cleared the password meanwhile */
964  strcmp(password, _settings_client.network.server_password) != 0) {
965  /* Password is invalid */
966  return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
967  }
968 
969  const NetworkClientInfo *ci = this->GetInfo();
971  return this->SendNeedCompanyPassword();
972  }
973 
974  /* Valid password, allow user */
975  return this->SendWelcome();
976 }
977 
979 {
980  if (this->status != STATUS_AUTH_COMPANY) {
981  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
982  }
983 
984  char password[NETWORK_PASSWORD_LENGTH];
985  p->Recv_string(password, sizeof(password));
986 
987  /* Check company password. Allow joining if we cleared the password meanwhile.
988  * Also, check the company is still valid - client could be moved to spectators
989  * in the middle of the authorization process */
990  CompanyID playas = this->GetInfo()->client_playas;
991  if (Company::IsValidID(playas) && !StrEmpty(_network_company_states[playas].password) &&
992  strcmp(password, _network_company_states[playas].password) != 0) {
993  /* Password is invalid */
994  return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
995  }
996 
997  return this->SendWelcome();
998 }
999 
1001 {
1002  /* The client was never joined.. so this is impossible, right?
1003  * Ignore the packet, give the client a warning, and close his connection */
1004  if (this->status < STATUS_AUTHORIZED || this->HasClientQuit()) {
1005  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1006  }
1007 
1008  /* Check if someone else is receiving the map */
1009  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
1010  if (new_cs->status == STATUS_MAP) {
1011  /* Tell the new client to wait */
1012  this->status = STATUS_MAP_WAIT;
1013  return this->SendWait();
1014  }
1015  }
1016 
1017  /* We receive a request to upload the map.. give it to the client! */
1018  return this->SendMap();
1019 }
1020 
1022 {
1023  /* Client has the map, now start syncing */
1024  if (this->status == STATUS_DONE_MAP && !this->HasClientQuit()) {
1025  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1026 
1027  this->GetClientName(client_name, lastof(client_name));
1028 
1029  NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, nullptr, this->client_id);
1030 
1031  /* Mark the client as pre-active, and wait for an ACK
1032  * so we know he is done loading and in sync with us */
1033  this->status = STATUS_PRE_ACTIVE;
1035  this->SendFrame();
1036  this->SendSync();
1037 
1038  /* This is the frame the client receives
1039  * we need it later on to make sure the client is not too slow */
1040  this->last_frame = _frame_counter;
1042 
1043  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
1044  if (new_cs->status > STATUS_AUTHORIZED) {
1045  new_cs->SendClientInfo(this->GetInfo());
1046  new_cs->SendJoin(this->client_id);
1047  }
1048  }
1049 
1050  NetworkAdminClientInfo(this, true);
1051 
1052  /* also update the new client with our max values */
1053  this->SendConfigUpdate();
1054 
1055  /* quickly update the syncing client with company details */
1056  return this->SendCompanyUpdate();
1057  }
1058 
1059  /* Wrong status for this packet, give a warning to client, and close connection */
1060  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1061 }
1062 
1068 {
1069  /* The client was never joined.. so this is impossible, right?
1070  * Ignore the packet, give the client a warning, and close his connection */
1071  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1072  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1073  }
1074 
1076  return this->SendError(NETWORK_ERROR_TOO_MANY_COMMANDS);
1077  }
1078 
1079  CommandPacket cp;
1080  const char *err = this->ReceiveCommand(p, &cp);
1081 
1082  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
1083 
1084  NetworkClientInfo *ci = this->GetInfo();
1085 
1086  if (err != nullptr) {
1087  IConsolePrintF(CC_ERROR, "WARNING: %s from client %d (IP: %s).", err, ci->client_id, this->GetClientIP());
1088  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1089  }
1090 
1091 
1092  if ((GetCommandFlags(cp.cmd) & CMD_SERVER) && ci->client_id != CLIENT_ID_SERVER) {
1093  IConsolePrintF(CC_ERROR, "WARNING: server only command from: client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
1094  return this->SendError(NETWORK_ERROR_KICKED);
1095  }
1096 
1098  IConsolePrintF(CC_ERROR, "WARNING: spectator issuing command from client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
1099  return this->SendError(NETWORK_ERROR_KICKED);
1100  }
1101 
1107  if (!(cp.cmd == CMD_COMPANY_CTRL && cp.p1 == 0 && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) {
1108  IConsolePrintF(CC_ERROR, "WARNING: client %d (IP: %s) tried to execute a command as company %d, kicking...",
1109  ci->client_playas + 1, this->GetClientIP(), cp.company + 1);
1110  return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
1111  }
1112 
1113  if (cp.cmd == CMD_COMPANY_CTRL) {
1114  if (cp.p1 != 0 || cp.company != COMPANY_SPECTATOR) {
1115  return this->SendError(NETWORK_ERROR_CHEATER);
1116  }
1117 
1118  /* 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! */
1120  NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_CLIENT, ci->client_id, "cannot create new company, server full", CLIENT_ID_SERVER);
1121  return NETWORK_RECV_STATUS_OKAY;
1122  }
1123  }
1124 
1125  if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) cp.p2 = this->client_id;
1126 
1127  this->incoming_queue.Append(&cp);
1128  return NETWORK_RECV_STATUS_OKAY;
1129 }
1130 
1132 {
1133  /* This packets means a client noticed an error and is reporting this
1134  * to us. Display the error and report it to the other clients */
1135  char str[100];
1136  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1138 
1139  /* The client was never joined.. thank the client for the packet, but ignore it */
1140  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1142  }
1143 
1144  this->GetClientName(client_name, lastof(client_name));
1145 
1146  StringID strid = GetNetworkErrorMsg(errorno);
1147  GetString(str, strid, lastof(str));
1148 
1149  DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
1150 
1151  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid);
1152 
1153  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
1154  if (new_cs->status > STATUS_AUTHORIZED) {
1155  new_cs->SendErrorQuit(this->client_id, errorno);
1156  }
1157  }
1158 
1159  NetworkAdminClientError(this->client_id, errorno);
1160 
1162 }
1163 
1165 {
1166  /* The client wants to leave. Display this and report it to the other
1167  * clients. */
1168  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1169 
1170  /* The client was never joined.. thank the client for the packet, but ignore it */
1171  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1173  }
1174 
1175  this->GetClientName(client_name, lastof(client_name));
1176 
1177  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
1178 
1179  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
1180  if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
1181  new_cs->SendQuit(this->client_id);
1182  }
1183  }
1184 
1186 
1188 }
1189 
1191 {
1192  if (this->status < STATUS_AUTHORIZED) {
1193  /* Illegal call, return error and ignore the packet */
1194  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1195  }
1196 
1197  uint32 frame = p->Recv_uint32();
1198 
1199  /* The client is trying to catch up with the server */
1200  if (this->status == STATUS_PRE_ACTIVE) {
1201  /* The client is not yet caught up? */
1202  if (frame + DAY_TICKS < _frame_counter) return NETWORK_RECV_STATUS_OKAY;
1203 
1204  /* Now he is! Unpause the game */
1205  this->status = STATUS_ACTIVE;
1207 
1208  /* Execute script for, e.g. MOTD */
1209  IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
1210  }
1211 
1212  /* Get, and validate the token. */
1213  uint8 token = p->Recv_uint8();
1214  if (token == this->last_token) {
1215  /* We differentiate between last_token_frame and last_frame so the lag
1216  * test uses the actual lag of the client instead of the lag for getting
1217  * the token back and forth; after all, the token is only sent every
1218  * time we receive a PACKET_CLIENT_ACK, after which we will send a new
1219  * token to the client. If the lag would be one day, then we would not
1220  * be sending the new token soon enough for the new daily scheduled
1221  * PACKET_CLIENT_ACK. This would then register the lag of the client as
1222  * two days, even when it's only a single day. */
1224  /* Request a new token. */
1225  this->last_token = 0;
1226  }
1227 
1228  /* The client received the frame, make note of it */
1229  this->last_frame = frame;
1230  /* With those 2 values we can calculate the lag realtime */
1232  return NETWORK_RECV_STATUS_OKAY;
1233 }
1234 
1235 
1246 void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, ClientID from_id, int64 data, bool from_admin)
1247 {
1248  const NetworkClientInfo *ci, *ci_own, *ci_to;
1249 
1250  switch (desttype) {
1251  case DESTTYPE_CLIENT:
1252  /* Are we sending to the server? */
1253  if ((ClientID)dest == CLIENT_ID_SERVER) {
1254  ci = NetworkClientInfo::GetByClientID(from_id);
1255  /* Display the text locally, and that is it */
1256  if (ci != nullptr) {
1257  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1258 
1260  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1261  }
1262  }
1263  } else {
1264  /* Else find the client to send the message to */
1265  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1266  if (cs->client_id == (ClientID)dest) {
1267  cs->SendChat(action, from_id, false, msg, data);
1268  break;
1269  }
1270  }
1271  }
1272 
1273  /* Display the message locally (so you know you have sent it) */
1274  if (from_id != (ClientID)dest) {
1275  if (from_id == CLIENT_ID_SERVER) {
1276  ci = NetworkClientInfo::GetByClientID(from_id);
1278  if (ci != nullptr && ci_to != nullptr) {
1279  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), true, ci_to->client_name, msg, data);
1280  }
1281  } else {
1282  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1283  if (cs->client_id == from_id) {
1284  cs->SendChat(action, (ClientID)dest, true, msg, data);
1285  break;
1286  }
1287  }
1288  }
1289  }
1290  break;
1291  case DESTTYPE_TEAM: {
1292  /* If this is false, the message is already displayed on the client who sent it. */
1293  bool show_local = true;
1294  /* Find all clients that belong to this company */
1295  ci_to = nullptr;
1296  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1297  ci = cs->GetInfo();
1298  if (ci != nullptr && ci->client_playas == (CompanyID)dest) {
1299  cs->SendChat(action, from_id, false, msg, data);
1300  if (cs->client_id == from_id) show_local = false;
1301  ci_to = ci; // Remember a client that is in the company for company-name
1302  }
1303  }
1304 
1305  /* if the server can read it, let the admin network read it, too. */
1307  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1308  }
1309 
1310  ci = NetworkClientInfo::GetByClientID(from_id);
1312  if (ci != nullptr && ci_own != nullptr && ci_own->client_playas == dest) {
1313  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1314  if (from_id == CLIENT_ID_SERVER) show_local = false;
1315  ci_to = ci_own;
1316  }
1317 
1318  /* There is no such client */
1319  if (ci_to == nullptr) break;
1320 
1321  /* Display the message locally (so you know you have sent it) */
1322  if (ci != nullptr && show_local) {
1323  if (from_id == CLIENT_ID_SERVER) {
1324  char name[NETWORK_NAME_LENGTH];
1325  StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
1326  SetDParam(0, ci_to->client_playas);
1327  GetString(name, str, lastof(name));
1328  NetworkTextMessage(action, GetDrawStringCompanyColour(ci_own->client_playas), true, name, msg, data);
1329  } else {
1330  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1331  if (cs->client_id == from_id) {
1332  cs->SendChat(action, ci_to->client_id, true, msg, data);
1333  }
1334  }
1335  }
1336  }
1337  break;
1338  }
1339  default:
1340  DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
1341  FALLTHROUGH;
1342 
1343  case DESTTYPE_BROADCAST:
1344  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1345  cs->SendChat(action, from_id, false, msg, data);
1346  }
1347 
1348  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1349 
1350  ci = NetworkClientInfo::GetByClientID(from_id);
1351  if (ci != nullptr) {
1352  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1353  }
1354  break;
1355  }
1356 }
1357 
1359 {
1360  if (this->status < STATUS_PRE_ACTIVE) {
1361  /* Illegal call, return error and ignore the packet */
1362  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1363  }
1364 
1365  NetworkAction action = (NetworkAction)p->Recv_uint8();
1366  DestType desttype = (DestType)p->Recv_uint8();
1367  int dest = p->Recv_uint32();
1368  char msg[NETWORK_CHAT_LENGTH];
1369 
1371  int64 data = p->Recv_uint64();
1372 
1373  NetworkClientInfo *ci = this->GetInfo();
1374  switch (action) {
1375  case NETWORK_ACTION_GIVE_MONEY:
1376  if (!Company::IsValidID(ci->client_playas)) break;
1377  FALLTHROUGH;
1378  case NETWORK_ACTION_CHAT:
1379  case NETWORK_ACTION_CHAT_CLIENT:
1380  case NETWORK_ACTION_CHAT_COMPANY:
1381  NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data);
1382  break;
1383  default:
1384  IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, this->GetClientIP());
1385  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1386  }
1387  return NETWORK_RECV_STATUS_OKAY;
1388 }
1389 
1391 {
1392  if (this->status != STATUS_ACTIVE) {
1393  /* Illegal call, return error and ignore the packet */
1394  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1395  }
1396 
1397  char password[NETWORK_PASSWORD_LENGTH];
1398  const NetworkClientInfo *ci;
1399 
1400  p->Recv_string(password, sizeof(password));
1401  ci = this->GetInfo();
1402 
1404  return NETWORK_RECV_STATUS_OKAY;
1405 }
1406 
1408 {
1409  if (this->status != STATUS_ACTIVE) {
1410  /* Illegal call, return error and ignore the packet */
1411  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1412  }
1413 
1414  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1415  NetworkClientInfo *ci;
1416 
1417  p->Recv_string(client_name, sizeof(client_name));
1418  ci = this->GetInfo();
1419 
1420  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
1421 
1422  if (ci != nullptr) {
1423  /* Display change */
1424  if (NetworkFindName(client_name, lastof(client_name))) {
1425  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name);
1426  strecpy(ci->client_name, client_name, lastof(ci->client_name));
1428  }
1429  }
1430  return NETWORK_RECV_STATUS_OKAY;
1431 }
1432 
1434 {
1435  if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1436 
1437  char pass[NETWORK_PASSWORD_LENGTH];
1438  char command[NETWORK_RCONCOMMAND_LENGTH];
1439 
1441 
1442  p->Recv_string(pass, sizeof(pass));
1443  p->Recv_string(command, sizeof(command));
1444 
1445  if (strcmp(pass, _settings_client.network.rcon_password) != 0) {
1446  DEBUG(net, 0, "[rcon] wrong password from client-id %d", this->client_id);
1447  return NETWORK_RECV_STATUS_OKAY;
1448  }
1449 
1450  DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", this->client_id, command);
1451 
1453  IConsoleCmdExec(command);
1455  return NETWORK_RECV_STATUS_OKAY;
1456 }
1457 
1459 {
1460  if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1461 
1462  CompanyID company_id = (Owner)p->Recv_uint8();
1463 
1464  /* Check if the company is valid, we don't allow moving to AI companies */
1465  if (company_id != COMPANY_SPECTATOR && !Company::IsValidHumanID(company_id)) return NETWORK_RECV_STATUS_OKAY;
1466 
1467  /* Check if we require a password for this company */
1468  if (company_id != COMPANY_SPECTATOR && !StrEmpty(_network_company_states[company_id].password)) {
1469  /* we need a password from the client - should be in this packet */
1470  char password[NETWORK_PASSWORD_LENGTH];
1471  p->Recv_string(password, sizeof(password));
1472 
1473  /* Incorrect password sent, return! */
1474  if (strcmp(password, _network_company_states[company_id].password) != 0) {
1475  DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", this->client_id, company_id + 1);
1476  return NETWORK_RECV_STATUS_OKAY;
1477  }
1478  }
1479 
1480  /* if we get here we can move the client */
1481  NetworkServerDoMove(this->client_id, company_id);
1482  return NETWORK_RECV_STATUS_OKAY;
1483 }
1484 
1493 {
1494  /* Grab the company name */
1495  char company_name[NETWORK_COMPANY_NAME_LENGTH];
1496  SetDParam(0, c->index);
1497 
1498  assert(max_len <= lengthof(company_name));
1499  GetString(company_name, STR_COMPANY_NAME, company_name + max_len - 1);
1500 
1501  /* Get the income */
1502  Money income = 0;
1503  if (_cur_year - 1 == c->inaugurated_year) {
1504  /* The company is here just 1 year, so display [2], else display[1] */
1505  for (uint i = 0; i < lengthof(c->yearly_expenses[2]); i++) {
1506  income -= c->yearly_expenses[2][i];
1507  }
1508  } else {
1509  for (uint i = 0; i < lengthof(c->yearly_expenses[1]); i++) {
1510  income -= c->yearly_expenses[1][i];
1511  }
1512  }
1513 
1514  /* Send the information */
1515  p->Send_uint8 (c->index);
1516  p->Send_string(company_name);
1519  p->Send_uint64(c->money);
1520  p->Send_uint64(income);
1522 
1523  /* Send 1 if there is a password for the company else send 0 */
1525 
1526  for (uint i = 0; i < NETWORK_VEH_END; i++) {
1527  p->Send_uint16(stats->num_vehicle[i]);
1528  }
1529 
1530  for (uint i = 0; i < NETWORK_VEH_END; i++) {
1531  p->Send_uint16(stats->num_station[i]);
1532  }
1533 
1534  p->Send_bool(c->is_ai);
1535 }
1536 
1542 {
1543  memset(stats, 0, sizeof(*stats) * MAX_COMPANIES);
1544 
1545  /* Go through all vehicles and count the type of vehicles */
1546  for (const Vehicle *v : Vehicle::Iterate()) {
1547  if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
1548  byte type = 0;
1549  switch (v->type) {
1550  case VEH_TRAIN: type = NETWORK_VEH_TRAIN; break;
1551  case VEH_ROAD: type = RoadVehicle::From(v)->IsBus() ? NETWORK_VEH_BUS : NETWORK_VEH_LORRY; break;
1552  case VEH_AIRCRAFT: type = NETWORK_VEH_PLANE; break;
1553  case VEH_SHIP: type = NETWORK_VEH_SHIP; break;
1554  default: continue;
1555  }
1556  stats[v->owner].num_vehicle[type]++;
1557  }
1558 
1559  /* Go through all stations and count the types of stations */
1560  for (const Station *s : Station::Iterate()) {
1561  if (Company::IsValidID(s->owner)) {
1562  NetworkCompanyStats *npi = &stats[s->owner];
1563 
1564  if (s->facilities & FACIL_TRAIN) npi->num_station[NETWORK_VEH_TRAIN]++;
1565  if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[NETWORK_VEH_LORRY]++;
1566  if (s->facilities & FACIL_BUS_STOP) npi->num_station[NETWORK_VEH_BUS]++;
1567  if (s->facilities & FACIL_AIRPORT) npi->num_station[NETWORK_VEH_PLANE]++;
1568  if (s->facilities & FACIL_DOCK) npi->num_station[NETWORK_VEH_SHIP]++;
1569  }
1570  }
1571 }
1572 
1578 {
1580 
1581  if (ci == nullptr) return;
1582 
1583  DEBUG(desync, 1, "client: %08x; %02x; %02x; %04x", _date, _date_fract, (int)ci->client_playas, client_id);
1584 
1585  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1586  cs->SendClientInfo(ci);
1587  }
1588 
1590 }
1591 
1594 {
1596  DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
1597 
1600  case FT_SAVEGAME:
1601  case FT_SCENARIO:
1603  break;
1604 
1605  case FT_HEIGHTMAP:
1607  break;
1608 
1609  default:
1611  }
1612  }
1613 }
1614 
1622 {
1623  bool clients_in_company[MAX_COMPANIES];
1624  int vehicles_in_company[MAX_COMPANIES];
1625 
1627 
1628  memset(clients_in_company, 0, sizeof(clients_in_company));
1629 
1630  /* Detect the active companies */
1631  for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
1632  if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
1633  }
1634 
1635  if (!_network_dedicated) {
1637  if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
1638  }
1639 
1641  memset(vehicles_in_company, 0, sizeof(vehicles_in_company));
1642 
1643  for (const Vehicle *v : Vehicle::Iterate()) {
1644  if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
1645  vehicles_in_company[v->owner]++;
1646  }
1647  }
1648 
1649  /* Go through all the companies */
1650  for (const Company *c : Company::Iterate()) {
1651  /* Skip the non-active once */
1652  if (c->is_ai) continue;
1653 
1654  if (!clients_in_company[c->index]) {
1655  /* The company is empty for one month more */
1657 
1658  /* Is the company empty for autoclean_unprotected-months, and is there no protection? */
1660  /* Shut the company down */
1661  DoCommandP(0, CCA_DELETE | c->index << 16 | CRR_AUTOCLEAN << 24, 0, CMD_COMPANY_CTRL);
1662  IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no password", c->index + 1);
1663  }
1664  /* Is the company empty for autoclean_protected-months, and there is a protection? */
1666  /* Unprotect the company */
1667  _network_company_states[c->index].password[0] = '\0';
1668  IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", c->index + 1);
1669  _network_company_states[c->index].months_empty = 0;
1670  NetworkServerUpdateCompanyPassworded(c->index, false);
1671  }
1672  /* Is the company empty for autoclean_novehicles-months, and has no vehicles? */
1674  /* Shut the company down */
1675  DoCommandP(0, CCA_DELETE | c->index << 16 | CRR_AUTOCLEAN << 24, 0, CMD_COMPANY_CTRL);
1676  IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no vehicles", c->index + 1);
1677  }
1678  } else {
1679  /* It is not empty, reset the date */
1680  _network_company_states[c->index].months_empty = 0;
1681  }
1682  }
1683 }
1684 
1691 bool NetworkFindName(char *new_name, const char *last)
1692 {
1693  bool found_name = false;
1694  uint number = 0;
1695  char original_name[NETWORK_CLIENT_NAME_LENGTH];
1696 
1697  strecpy(original_name, new_name, lastof(original_name));
1698 
1699  while (!found_name) {
1700  found_name = true;
1701  for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
1702  if (strcmp(ci->client_name, new_name) == 0) {
1703  /* Name already in use */
1704  found_name = false;
1705  break;
1706  }
1707  }
1708  /* Check if it is the same as the server-name */
1710  if (ci != nullptr) {
1711  if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
1712  }
1713 
1714  if (!found_name) {
1715  /* Try a new name (<name> #1, <name> #2, and so on) */
1716 
1717  /* Something's really wrong when there're more names than clients */
1718  if (number++ > MAX_CLIENTS) break;
1719  seprintf(new_name, last, "%s #%d", original_name, number);
1720  }
1721  }
1722 
1723  return found_name;
1724 }
1725 
1733 {
1734  /* Check if the name's already in use */
1736  if (strcmp(ci->client_name, new_name) == 0) return false;
1737  }
1738 
1740  if (ci == nullptr) return false;
1741 
1742  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, true, ci->client_name, new_name);
1743 
1744  strecpy(ci->client_name, new_name, lastof(ci->client_name));
1745 
1746  NetworkUpdateClientInfo(client_id);
1747  return true;
1748 }
1749 
1756 void NetworkServerSetCompanyPassword(CompanyID company_id, const char *password, bool already_hashed)
1757 {
1758  if (!Company::IsValidHumanID(company_id)) return;
1759 
1760  if (!already_hashed) {
1762  }
1763 
1764  strecpy(_network_company_states[company_id].password, password, lastof(_network_company_states[company_id].password));
1765  NetworkServerUpdateCompanyPassworded(company_id, !StrEmpty(_network_company_states[company_id].password));
1766 }
1767 
1772 static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
1773 {
1774  CommandPacket *cp;
1775  while ((cp = cs->outgoing_queue.Pop()) != nullptr) {
1776  cs->SendCommand(cp);
1777  free(cp);
1778  }
1779 }
1780 
1785 void NetworkServer_Tick(bool send_frame)
1786 {
1787 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1788  bool send_sync = false;
1789 #endif
1790 
1791 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1794  send_sync = true;
1795  }
1796 #endif
1797 
1798  /* Now we are done with the frame, inform the clients that they can
1799  * do their frame! */
1800  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1801  /* We allow a number of bytes per frame, but only to the burst amount
1802  * to be available for packet receiving at any particular time. */
1803  cs->receive_limit = min(cs->receive_limit + _settings_client.network.bytes_per_frame,
1805 
1806  /* Check if the speed of the client is what we can expect from a client */
1807  uint lag = NetworkCalculateLag(cs);
1808  switch (cs->status) {
1809  case NetworkClientSocket::STATUS_ACTIVE:
1811  /* Client did still not report in within the specified limit. */
1812  IConsolePrintF(CC_ERROR, cs->last_packet + lag * MILLISECONDS_PER_TICK > _realtime_tick ?
1813  /* A packet was received in the last three game days, so the client is likely lagging behind. */
1814  "Client #%d is dropped because the client's game state is more than %d ticks behind" :
1815  /* No packet was received in the last three game days; sounds like a lost connection. */
1816  "Client #%d is dropped because the client did not respond for more than %d ticks",
1817  cs->client_id, lag);
1818  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1819  continue;
1820  }
1821 
1822  /* Report once per time we detect the lag, and only when we
1823  * received a packet in the last 2000 milliseconds. If we
1824  * did not receive a packet, then the client is not just
1825  * slow, but the connection is likely severed. Mentioning
1826  * frame_freq is not useful in this case. */
1827  if (lag > (uint)DAY_TICKS && cs->lag_test == 0 && cs->last_packet + 2000 > _realtime_tick) {
1828  IConsolePrintF(CC_WARNING, "[%d] Client #%d is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id);
1829  cs->lag_test = 1;
1830  }
1831 
1832  if (cs->last_frame_server - cs->last_token_frame >= _settings_client.network.max_lag_time) {
1833  /* This is a bad client! It didn't send the right token back within time. */
1834  IConsolePrintF(CC_ERROR, "Client #%d is dropped because it fails to send valid acks", cs->client_id);
1835  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1836  continue;
1837  }
1838  break;
1839 
1840  case NetworkClientSocket::STATUS_INACTIVE:
1841  case NetworkClientSocket::STATUS_NEWGRFS_CHECK:
1842  case NetworkClientSocket::STATUS_AUTHORIZED:
1843  /* NewGRF check and authorized states should be handled almost instantly.
1844  * So give them some lee-way, likewise for the query with inactive. */
1846  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);
1847  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1848  continue;
1849  }
1850  break;
1851 
1852  case NetworkClientSocket::STATUS_MAP:
1853  /* Downloading the map... this is the amount of time since starting the saving. */
1855  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);
1856  cs->SendError(NETWORK_ERROR_TIMEOUT_MAP);
1857  continue;
1858  }
1859  break;
1860 
1861  case NetworkClientSocket::STATUS_DONE_MAP:
1862  case NetworkClientSocket::STATUS_PRE_ACTIVE:
1863  /* The map has been sent, so this is for loading the map and syncing up. */
1865  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);
1866  cs->SendError(NETWORK_ERROR_TIMEOUT_JOIN);
1867  continue;
1868  }
1869  break;
1870 
1871  case NetworkClientSocket::STATUS_AUTH_GAME:
1872  case NetworkClientSocket::STATUS_AUTH_COMPANY:
1873  /* These don't block? */
1875  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);
1876  cs->SendError(NETWORK_ERROR_TIMEOUT_PASSWORD);
1877  continue;
1878  }
1879  break;
1880 
1881  case NetworkClientSocket::STATUS_MAP_WAIT:
1882  /* This is an internal state where we do not wait
1883  * on the client to move to a different state. */
1884  break;
1885 
1886  case NetworkClientSocket::STATUS_END:
1887  /* Bad server/code. */
1888  NOT_REACHED();
1889  }
1890 
1891  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) {
1892  /* Check if we can send command, and if we have anything in the queue */
1894 
1895  /* Send an updated _frame_counter_max to the client */
1896  if (send_frame) cs->SendFrame();
1897 
1898 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1899  /* Send a sync-check packet */
1900  if (send_sync) cs->SendSync();
1901 #endif
1902  }
1903  }
1904 
1905  /* See if we need to advertise */
1907 }
1908 
1911 {
1914 }
1915 
1918 {
1922 }
1923 
1926 {
1929 }
1930 
1936 {
1937  return this->client_address.GetHostname();
1938 }
1939 
1942 {
1943  static const char * const stat_str[] = {
1944  "inactive",
1945  "checking NewGRFs",
1946  "authorizing (server password)",
1947  "authorizing (company password)",
1948  "authorized",
1949  "waiting",
1950  "loading map",
1951  "map done",
1952  "ready",
1953  "active"
1954  };
1955  assert_compile(lengthof(stat_str) == NetworkClientSocket::STATUS_END);
1956 
1957  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1958  NetworkClientInfo *ci = cs->GetInfo();
1959  if (ci == nullptr) continue;
1960  uint lag = NetworkCalculateLag(cs);
1961  const char *status;
1962 
1963  status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
1964  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s",
1965  cs->client_id, ci->client_name, status, lag,
1966  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
1967  cs->GetClientIP());
1968  }
1969 }
1970 
1975 {
1976  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1977  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendConfigUpdate();
1978  }
1979 }
1980 
1986 void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded)
1987 {
1988  if (NetworkCompanyIsPassworded(company_id) == passworded) return;
1989 
1990  SB(_network_company_passworded, company_id, 1, !!passworded);
1992 
1993  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1994  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendCompanyUpdate();
1995  }
1996 
1998 }
1999 
2007 {
2008  /* Only allow non-dedicated servers and normal clients to be moved */
2009  if (client_id == CLIENT_ID_SERVER && _network_dedicated) return;
2010 
2012 
2013  /* No need to waste network resources if the client is in the company already! */
2014  if (ci->client_playas == company_id) return;
2015 
2016  ci->client_playas = company_id;
2017 
2018  if (client_id == CLIENT_ID_SERVER) {
2019  SetLocalCompany(company_id);
2020  } else {
2021  NetworkClientSocket *cs = NetworkClientSocket::GetByClientID(client_id);
2022  /* When the company isn't authorized we can't move them yet. */
2023  if (cs->status < NetworkClientSocket::STATUS_AUTHORIZED) return;
2024  cs->SendMove(client_id, company_id);
2025  }
2026 
2027  /* announce the client's move */
2028  NetworkUpdateClientInfo(client_id);
2029 
2030  NetworkAction action = (company_id == COMPANY_SPECTATOR) ? NETWORK_ACTION_COMPANY_SPECTATOR : NETWORK_ACTION_COMPANY_JOIN;
2031  NetworkServerSendChat(action, DESTTYPE_BROADCAST, 0, "", client_id, company_id + 1);
2032 }
2033 
2040 void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string)
2041 {
2042  NetworkClientSocket::GetByClientID(client_id)->SendRConResult(colour_code, string);
2043 }
2044 
2050 void NetworkServerKickClient(ClientID client_id, const char *reason)
2051 {
2052  if (client_id == CLIENT_ID_SERVER) return;
2053  NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED, reason);
2054 }
2055 
2062 uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const char *reason)
2063 {
2064  return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban, reason);
2065 }
2066 
2073 uint NetworkServerKickOrBanIP(const char *ip, bool ban, const char *reason)
2074 {
2075  /* Add address to ban-list */
2076  if (ban) {
2077  bool contains = false;
2078  for (const auto &iter : _network_ban_list) {
2079  if (iter == ip) {
2080  contains = true;
2081  break;
2082  }
2083  }
2084  if (!contains) _network_ban_list.emplace_back(ip);
2085  }
2086 
2087  uint n = 0;
2088 
2089  /* There can be multiple clients with the same IP, kick them all but don't kill the server,
2090  * or the client doing the rcon. The latter can't be kicked because kicking frees closes
2091  * and subsequently free the connection related instances, which we would be reading from
2092  * and writing to after returning. So we would read or write data from freed memory up till
2093  * the segfault triggers. */
2094  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
2095  if (cs->client_id == CLIENT_ID_SERVER) continue;
2096  if (cs->client_id == _redirect_console_to_client) continue;
2097  if (cs->client_address.IsInNetmask(ip)) {
2098  NetworkServerKickClient(cs->client_id, reason);
2099  n++;
2100  }
2101  }
2102 
2103  return n;
2104 }
2105 
2112 {
2113  for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
2114  if (ci->client_playas == company) return true;
2115  }
2116  return false;
2117 }
2118 
2119 
2125 void ServerNetworkGameSocketHandler::GetClientName(char *client_name, const char *last) const
2126 {
2127  const NetworkClientInfo *ci = this->GetInfo();
2128 
2129  if (ci == nullptr || StrEmpty(ci->client_name)) {
2130  seprintf(client_name, last, "Client #%4d", this->client_id);
2131  } else {
2132  strecpy(client_name, ci->client_name, last);
2133  }
2134 }
2135 
2140 {
2142  if (_network_server) {
2143  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d IP: %s",
2144  ci->client_id,
2145  ci->client_name,
2146  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
2147  ci->client_id == CLIENT_ID_SERVER ? "server" : NetworkClientSocket::GetByClientID(ci->client_id)->GetClientIP());
2148  } else {
2149  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d",
2150  ci->client_id,
2151  ci->client_name,
2152  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0));
2153  }
2154  }
2155 }
2156 
2163 {
2164  assert(c != nullptr);
2165 
2166  if (!_network_server) return;
2167 
2169  _network_company_states[c->index].password[0] = '\0';
2171 
2172  if (ci != nullptr) {
2173  /* ci is nullptr when replaying, or for AIs. In neither case there is a client. */
2174  ci->client_playas = c->index;
2176  NetworkSendCommand(0, 0, 0, CMD_RENAME_PRESIDENT, nullptr, ci->client_name, c->index);
2177  }
2178 
2179  /* Announce new company on network. */
2180  NetworkAdminCompanyInfo(c, true);
2181 
2182  if (ci != nullptr) {
2183  /* ci is nullptr when replaying, or for AIs. In neither case there is a client.
2184  We need to send Admin port update here so that they first know about the new company
2185  and then learn about a possibly joining client (see FS#6025) */
2186  NetworkServerSendChat(NETWORK_ACTION_COMPANY_NEW, DESTTYPE_BROADCAST, 0, "", ci->client_id, c->index + 1);
2187  }
2188 }
Everything is okay.
Definition: core.h:23
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:47
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:46
Owner
Enum for all companies/owners.
Definition: company_type.h:18
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:79
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.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:80
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:340
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:42
Server tells everyone that someone is moved to another company.
Definition: tcp_game.h:104
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:1143
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition: core.h:67
Container for all information known about a client.
Definition: network_base.h:23
The client has downloaded the map.
SOCKET sock
The socket currently connected to.
Definition: tcp.h:32
NetworkRecvStatus SendJoin(ClientID client_id)
Tell that a client joined.
uint32 _sync_seed_1
Seed to compare during sync checks.
Definition: network.cpp:71
uint32 _realtime_tick
The real time in the game.
Definition: debug.cpp:48
Internal entity of a packet.
Definition: packet.h:40
ServerNetworkGameSocketHandler * cs
Socket we are associated with.
The connection got closed.
Definition: tcp.h:20
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3218
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:97
uint32 Recv_uint32()
Read a 32 bits integer from the packet.
Definition: packet.cpp:246
Client list; Window numbers:
Definition: window_type.h:472
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:24
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:120
int32 performance_history
Company score (scale 0-1000)
Definition: company_base.h:25
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:407
Load game, Play Scenario.
Definition: openttd.h:29
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:148
Year inaugurated_year
Year of starting the company.
Definition: company_base.h:78
The server is full and has no place for you.
Definition: tcp_game.h:33
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:101
Ship vehicle type.
Definition: vehicle_type.h:26
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:24
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:326
void NetworkPopulateCompanyStats(NetworkCompanyStats *stats)
Populate the company stats.
The client is downloading the map.
FileToSaveLoad _file_to_saveload
File to save or load in the openttd loop.
Definition: saveload.cpp:58
Popup for the client list; Window numbers:
Definition: window_type.h:478
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:34
void Send_uint8(uint8 data)
Package a 8 bits integer in the packet.
Definition: packet.cpp:96
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:28
The client is authorizing with company password.
Vehicle data structure.
Definition: vehicle_base.h:210
static const uint MAX_CLIENTS
How many clients can we have.
Definition: network_type.h:16
Sending and receiving UDP messages.
GRF file is used statically (can be used in any MP game)
Definition: newgrf_config.h:24
NetworkRecvStatus SendError(NetworkErrorCode error, const char *reason=nullptr)
Send an error to the client, and close its connection.
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:60
SaveOrLoadResult SaveWithFilter(SaveFilter *writer, bool threaded)
Save the game using a (writer) filter.
Definition: saveload.cpp:2552
Tindex index
Index of this pool item.
Definition: pool_type.hpp:227
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:28
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:81
void Send_uint32(uint32 data)
Package a 32 bits integer in the packet.
Definition: packet.cpp:117
Server distributing the message of a client (or itself).
Definition: tcp_game.h:96
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:48
static const TextColour CC_DEFAULT
Default colour of the console.
Definition: console_type.h:23
bool NetworkCompanyIsPassworded(CompanyID company_id)
Check if the company we want to join requires a password.
Definition: network.cpp:213
void NetworkPrintClients()
Print all the clients to the console.
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
Returns an iterable ensemble of all valid stations of type T.
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:86
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:39
The admin gets information about this on a daily basis.
Definition: tcp_admin.h:91
CommandFlags GetCommandFlags(uint32 cmd)
Definition: command.cpp:388
The first client ID.
Definition: network_type.h:42
The server told us we made an error.
Definition: core.h:29
Year _cur_year
Current year, starting at 0.
Definition: date.cpp:25
NetworkRecvStatus SendNewGRFCheck()
Send the check for the NewGRFs.
virtual Packet * ReceivePacket()
Receives a packet for the given client.
Definition: tcp.cpp:145
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:95
Server tells the client what the random state should be.
Definition: tcp_game.h:88
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:299
Server welcomes you and gives you your ClientID.
Definition: tcp_game.h:65
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:24
static bool IsValidHumanID(size_t index)
Is this company a valid company, not controlled by a NoAI program?
Definition: company_base.h:150
The admin gets information about this on a monthly basis.
Definition: tcp_admin.h:93
bool _network_dedicated
are we a dedicated server?
Definition: network.cpp:55
Server tells the client that it is beginning to send the map.
Definition: tcp_game.h:71
CommandQueue incoming_queue
The command-queue awaiting handling.
Definition: tcp_game.h:520
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:66
bool autoclean_companies
automatically remove companies that are not in use
void ProcessAsyncSaveFinish()
Handle async save finishes.
Definition: saveload.cpp:398
Response of the executed command on the server.
Definition: tcp_game.h:100
uint16 num_vehicle[NETWORK_VEH_END]
How many vehicles are there of this type?
Definition: network_type.h:58
static const size_t MAX_SIZE
Make template parameter accessible from outside.
Definition: pool_type.hpp:85
A server tells that a client has quit.
Definition: tcp_game.h:118
old or new savegame
Definition: fileio_type.h:18
old or new scenario
Definition: fileio_type.h:19
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:92
The company is removed due to autoclean.
Definition: company_type.h:57
void NetworkAdminClientQuit(ClientID client_id)
Notify the admin network that a client quit (if they have opt in for the respective update)...
char password[NETWORK_PASSWORD_LENGTH]
The password for the company.
Definition: network_type.h:65
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:55
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:27
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:48
Load a heightmap and start a new game from it.
Definition: openttd.h:35
uint32 last_frame
Last frame we have executed.
Definition: tcp_game.h:518
void Send_uint64(uint64 data)
Package a 64 bits integer in the packet.
Definition: packet.cpp:130
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:66
DateFract _date_fract
Fractional part of the day.
Definition: date.cpp:28
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
Definition: packet.h:52
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:35
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:25
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:106
uint32 p1
parameter p1.
Definition: command_type.h:479
Server sends bits of the map to the client.
Definition: tcp_game.h:73
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)...
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:79
void Finish() override
Prepare everything to finish writing the savegame.
std::mutex lock
synchronization for playback status fields
Definition: win32_m.cpp:34
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:125
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:94
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:92
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:245
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:58
GameSettings _settings_newgame
Game settings for new games (updated from the intro screen).
Definition: settings.cpp:81
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:305
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:22
Writing a savegame directly to a number of packets.
const char * GetHostname()
Get the hostname; in case it wasn&#39;t given the IPv4 dotted representation is given.
Definition: address.cpp:22
All packets in the queue are sent.
Definition: tcp.h:23
byte clients_on
Current count of clients on server.
Definition: game.h:26
static const uint NETWORK_CHAT_LENGTH
The maximum length of a chat message, in bytes including &#39;\0&#39;.
Definition: config.h:50
bool is_ai
If true, the company is (also) controlled by the computer (a NoAI program).
Definition: company_base.h:93
Money money
Money owned by the company.
Definition: company_base.h:65
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:48
NetworkLanguage
Language ids for server_lang and client_lang.
bool DoCommandP(const CommandContainer *container, bool my_cmd)
Shortcut for the long DoCommandP when having a container with the data.
Definition: command.cpp:536
CompanyID company
company that is executing the command
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:40
NetworkServerGameInfo _network_game_info
Information about our game.
Definition: network.cpp:57
The buffer is still full, so no (parts of) packets could be sent.
Definition: tcp.h:21
uint last_packet
Time we received the last frame.
Definition: tcp_game.h:521
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:40
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:546
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:16
Delete a company.
Definition: company_type.h:67
Server sending an error message to the client.
Definition: tcp_game.h:38
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:144
NetworkRecvStatus SendNewGame()
Tell the client we&#39;re starting a new game.
Packet * next
The next packet.
Definition: packet.h:42
Date join_date
Gamedate the client has joined.
Definition: network_base.h:28
Packet * PopPacket()
Pop a single created packet from the queue with packets.
Base class for all pools.
Definition: pool_type.hpp:81
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:27
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:35
uint8 autoclean_unprotected
remove passwordless companies after this many months
ClientID client_id
Client identifier.
Definition: tcp_game.h:517
Month _cur_month
Current month (0..11)
Definition: date.cpp:26
NetworkRecvStatus SendSync()
Request the client to sync.
uint32 last_frame_server
Last frame the server has executed.
Definition: tcp_game.h:519
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don&#39;t get linker errors.
Definition: pool_func.hpp:224
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1165
Station with an airport.
Definition: station_type.h:55
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:56
byte _network_clients_connected
The amount of clients connected.
Definition: network.cpp:91
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:79
uint8 Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:217
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:77
uint32 generation_seed
noise seed for world generation
Some network configuration important to the client changed.
Definition: tcp_game.h:110
The admin gets information about this on a yearly basis.
Definition: tcp_admin.h:95
NetworkRecvStatus SendCompanyInfo()
Send the client information about the companies.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:378
void SetInfo(NetworkClientInfo *info)
Sets the client info for this socket handler.
Definition: tcp_game.h:536
uint32 _frame_counter
The current frame.
Definition: network.cpp:68
uint64 Recv_uint64()
Read a 64 bits integer from the packet.
Definition: packet.cpp:263
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:57
void IConsoleCmdExec(const char *cmdstr, const uint recurse_count)
Execute a given command passed to us.
Definition: console.cpp:407
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:359
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:92
CompanyMask _network_company_passworded
Bitmask of the password status of all companies.
Definition: network.cpp:80
The server is preparing to start a new game.
Definition: tcp_game.h:113
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:41
PacketWriter(ServerNetworkGameSocketHandler *cs)
Create the packet writer.
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
Definition: openttd.cpp:112
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:74
Server tells the client what the (compressed) size of the map is.
Definition: tcp_game.h:72
change the president name
Definition: command_type.h:246
uint16 num_station[NETWORK_VEH_END]
How many stations are there of this type?
Definition: network_type.h:59
CompanyEconomyEntry old_economy[MAX_HISTORY_QUARTERS]
Economic data of the company of the last MAX_HISTORY_QUARTERS quarters.
Definition: company_base.h:97
Server tells the client there are some people waiting for the map as well.
Definition: tcp_game.h:70
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: depend.cpp:66
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:23
void NetworkServerSendConfigUpdate()
Send Config Update.
StringList _network_ban_list
The banned clients.
Definition: network.cpp:65
std::mutex mutex
Mutex for making threaded saving safe.
SwitchMode _switch_mode
The next mainloop command.
Definition: gfx.cpp:46
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:182
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:299
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:22
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:33
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).
bool _network_server
network-server is active
Definition: network.cpp:53
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:318
AbstractFileType abstract_ftype
Abstract type of file (scenario, heightmap, etc).
Definition: saveload.h:320
~PacketWriter()
Make sure everything is cleaned up.
static const TextColour CC_ERROR
Colour for error lines.
Definition: console_type.h:24
uint32 _last_sync_frame
Used in the server to store the last time a sync packet was sent to clients.
Definition: network.cpp:69
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:23
Station with bus stops.
Definition: station_type.h:54
Server requests the (hashed) game password.
Definition: tcp_game.h:59
Client is not part of anything.
Definition: network_type.h:40
heightmap file
Definition: fileio_type.h:20
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:95
Aircraft vehicle type.
Definition: vehicle_type.h:27
We apparently send a malformed packet.
Definition: core.h:28
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:129
NetworkRecvStatus Receive_CLIENT_QUIT(Packet *p) override
The client is quitting the game.
Server requests the (hashed) company password.
Definition: tcp_game.h:61
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:40
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:61
Simple calculated statistics of a company.
Definition: network_type.h:57
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:45
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:311
Station with truck stops.
Definition: station_type.h:53
Servers always have this ID.
Definition: network_type.h:41
#define DECLARE_POSTFIX_INCREMENT(enum_type)
Some enums need to have allowed incrementing (i.e.
Definition: enum_type.hpp:14
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:34
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const char *reason)
Ban, or kick, everyone joined from the given client&#39;s IP.
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:148
void Send_bool(bool data)
Package a boolean in the packet.
Definition: packet.cpp:87
Station with train station.
Definition: station_type.h:52
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:26
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it&#39;s client-identifier.
Definition: network.cpp:119
static const byte NETWORK_COMPANY_INFO_VERSION
What version of company info is this?
Definition: config.h:37
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:44
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3246
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:27
The server is shutting down.
Definition: tcp_game.h:114
Company view; Window numbers:
Definition: window_type.h:362
uint16 PacketSize
Size of the whole packet.
Definition: packet.h:19
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:25
void SendGRFIdentifier(Packet *p, const GRFIdentifier *grf)
Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet.
Definition: core.cpp:57
Send message/notice to everyone playing the same company (Team)
Definition: network_type.h:80
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:44
void NetworkServerKickClient(ClientID client_id, const char *reason)
Kick a single client.
uint32 _frame_counter_max
To where we may go with our clients.
Definition: network.cpp:67
static void Send()
Send the packets for the server sockets.
Station data structure.
Definition: station_base.h:450
uint32 cmd
command being executed.
Definition: command_type.h:481
DestType
Destination of our chat messages.
Definition: network_type.h:78
NetworkRecvStatus Receive_CLIENT_SET_NAME(Packet *p) override
Gives the client a new name: string New name of the client.
New Game –> &#39;Random game&#39;.
Definition: openttd.h:26
byte client_lang
The language of the client.
Definition: network_base.h:26
Road vehicle type.
Definition: vehicle_type.h:25
NetworkAction
Actions that can be used for NetworkTextMessage.
Definition: network_type.h:85
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:109
static const TextColour CC_INFO
Colour for information lines.
Definition: console_type.h:26
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:286
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:199