OpenTTD Source  1.10.3
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 
158  {
159  if (this->current == nullptr) return;
160 
161  this->current->next = this->packets;
162  this->packets = this->current;
163  this->current = nullptr;
164  }
165 
166  void Write(byte *buf, size_t size) override
167  {
168  /* We want to abort the saving when the socket is closed. */
169  if (this->cs == nullptr) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
170 
171  if (this->current == nullptr) this->current = new Packet(PACKET_SERVER_MAP_DATA);
172 
173  std::lock_guard<std::mutex> lock(this->mutex);
174 
175  byte *bufe = buf + size;
176  while (buf != bufe) {
177  size_t to_write = min(SEND_MTU - this->current->size, bufe - buf);
178  memcpy(this->current->buffer + this->current->size, buf, to_write);
179  this->current->size += (PacketSize)to_write;
180  buf += to_write;
181 
182  if (this->current->size == SEND_MTU) {
183  this->AppendQueue();
184  if (buf != bufe) this->current = new Packet(PACKET_SERVER_MAP_DATA);
185  }
186  }
187 
188  this->total_size += size;
189  }
190 
191  void Finish() override
192  {
193  /* We want to abort the saving when the socket is closed. */
194  if (this->cs == nullptr) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
195 
196  std::lock_guard<std::mutex> lock(this->mutex);
197 
198  /* Make sure the last packet is flushed. */
199  this->AppendQueue();
200 
201  /* Add a packet stating that this is the end to the queue. */
202  this->current = new Packet(PACKET_SERVER_MAP_DONE);
203  this->AppendQueue();
204 
205  /* Fast-track the size to the client. */
206  this->current = new Packet(PACKET_SERVER_MAP_SIZE);
207  this->current->Send_uint32((uint32)this->total_size);
208  this->PrependQueue();
209  }
210 };
211 
212 
218 {
219  this->status = STATUS_INACTIVE;
220  this->client_id = _network_client_id++;
222 
223  /* The Socket and Info pools need to be the same in size. After all,
224  * each Socket will be associated with at most one Info object. As
225  * such if the Socket was allocated the Info object can as well. */
227 }
228 
233 {
236 
237  if (this->savegame != nullptr) {
238  this->savegame->Destroy();
239  this->savegame = nullptr;
240  }
241 }
242 
244 {
245  /* Only allow receiving when we have some buffer free; this value
246  * can go negative, but eventually it will become positive again. */
247  if (this->receive_limit <= 0) return nullptr;
248 
249  /* We can receive a packet, so try that and if needed account for
250  * the amount of received data. */
252  if (p != nullptr) this->receive_limit -= p->size;
253  return p;
254 }
255 
257 {
258  assert(status != NETWORK_RECV_STATUS_OKAY);
259  /*
260  * Sending a message just before leaving the game calls cs->SendPackets.
261  * This might invoke this function, which means that when we close the
262  * connection after cs->SendPackets we will close an already closed
263  * connection. This handles that case gracefully without having to make
264  * that code any more complex or more aware of the validity of the socket.
265  */
266  if (this->sock == INVALID_SOCKET) return status;
267 
268  if (status != NETWORK_RECV_STATUS_CONN_LOST && !this->HasClientQuit() && this->status >= STATUS_AUTHORIZED) {
269  /* We did not receive a leave message from this client... */
270  char client_name[NETWORK_CLIENT_NAME_LENGTH];
271 
272  this->GetClientName(client_name, lastof(client_name));
273 
274  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST);
275 
276  /* Inform other clients of this... strange leaving ;) */
277  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
278  if (new_cs->status > STATUS_AUTHORIZED && this != new_cs) {
279  new_cs->SendErrorQuit(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
280  }
281  }
282  }
283 
284  NetworkAdminClientError(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
285  DEBUG(net, 1, "Closed client connection %d", this->client_id);
286 
287  /* We just lost one client :( */
288  if (this->status >= STATUS_AUTHORIZED) _network_game_info.clients_on--;
289  extern byte _network_clients_connected;
290  _network_clients_connected--;
291 
294 
295  this->SendPackets(true);
296 
297  delete this->GetInfo();
298  delete this;
299 
300  return status;
301 }
302 
308 {
309  extern byte _network_clients_connected;
310  bool accept = _network_clients_connected < MAX_CLIENTS && _network_game_info.clients_on < _settings_client.network.max_clients;
311 
312  /* We can't go over the MAX_CLIENTS limit here. However, the
313  * pool must have place for all clients and ourself. */
316  return accept;
317 }
318 
321 {
322  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
323  if (cs->writable) {
324  if (cs->SendPackets() != SPS_CLOSED && cs->status == STATUS_MAP) {
325  /* This client is in the middle of a map-send, call the function for that */
326  cs->SendMap();
327  }
328  }
329  }
330 }
331 
332 static void NetworkHandleCommandQueue(NetworkClientSocket *cs);
333 
334 /***********
335  * Sending functions
336  * DEF_SERVER_SEND_COMMAND has parameter: NetworkClientSocket *cs
337  ************/
338 
344 {
345  if (ci->client_id != INVALID_CLIENT_ID) {
347  p->Send_uint32(ci->client_id);
348  p->Send_uint8 (ci->client_playas);
349  p->Send_string(ci->client_name);
350 
351  this->SendPacket(p);
352  }
354 }
355 
358 {
359  /* Fetch the latest version of the stats */
360  NetworkCompanyStats company_stats[MAX_COMPANIES];
361  NetworkPopulateCompanyStats(company_stats);
362 
363  /* Make a list of all clients per company */
364  char clients[MAX_COMPANIES][NETWORK_CLIENTS_LENGTH];
365  memset(clients, 0, sizeof(clients));
366 
367  /* Add the local player (if not dedicated) */
369  if (ci != nullptr && Company::IsValidID(ci->client_playas)) {
370  strecpy(clients[ci->client_playas], ci->client_name, lastof(clients[ci->client_playas]));
371  }
372 
373  for (NetworkClientSocket *csi : NetworkClientSocket::Iterate()) {
374  char client_name[NETWORK_CLIENT_NAME_LENGTH];
375 
376  ((ServerNetworkGameSocketHandler*)csi)->GetClientName(client_name, lastof(client_name));
377 
378  ci = csi->GetInfo();
379  if (ci != nullptr && Company::IsValidID(ci->client_playas)) {
380  if (!StrEmpty(clients[ci->client_playas])) {
381  strecat(clients[ci->client_playas], ", ", lastof(clients[ci->client_playas]));
382  }
383 
384  strecat(clients[ci->client_playas], client_name, lastof(clients[ci->client_playas]));
385  }
386  }
387 
388  /* Now send the data */
389 
390  Packet *p;
391 
392  for (const Company *company : Company::Iterate()) {
394 
396  p->Send_bool (true);
397  this->SendCompanyInformation(p, company, &company_stats[company->index]);
398 
399  if (StrEmpty(clients[company->index])) {
400  p->Send_string("<none>");
401  } else {
402  p->Send_string(clients[company->index]);
403  }
404 
405  this->SendPacket(p);
406  }
407 
409 
411  p->Send_bool (false);
412 
413  this->SendPacket(p);
415 }
416 
423 {
424  char str[100];
426 
427  p->Send_uint8(error);
428  if (reason != nullptr) p->Send_string(reason);
429  this->SendPacket(p);
430 
431  StringID strid = GetNetworkErrorMsg(error);
432  GetString(str, strid, lastof(str));
433 
434  /* Only send when the current client was in game */
435  if (this->status > STATUS_AUTHORIZED) {
436  char client_name[NETWORK_CLIENT_NAME_LENGTH];
437 
438  this->GetClientName(client_name, lastof(client_name));
439 
440  DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
441 
442  if (error == NETWORK_ERROR_KICKED && reason != nullptr) {
443  NetworkTextMessage(NETWORK_ACTION_KICKED, CC_DEFAULT, false, client_name, reason, strid);
444  } else {
445  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid);
446  }
447 
448  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
449  if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
450  /* Some errors we filter to a more general error. Clients don't have to know the real
451  * reason a joining failed. */
452  if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION) {
453  error = NETWORK_ERROR_ILLEGAL_PACKET;
454  }
455  new_cs->SendErrorQuit(this->client_id, error);
456  }
457  }
458 
459  NetworkAdminClientError(this->client_id, error);
460  } else {
461  DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", this->client_id, str);
462  }
463 
464  /* The client made a mistake, so drop his connection now! */
466 }
467 
470 {
472  const GRFConfig *c;
473  uint grf_count = 0;
474 
475  for (c = _grfconfig; c != nullptr; c = c->next) {
476  if (!HasBit(c->flags, GCF_STATIC)) grf_count++;
477  }
478 
479  p->Send_uint8 (grf_count);
480  for (c = _grfconfig; c != nullptr; c = c->next) {
481  if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident);
482  }
483 
484  this->SendPacket(p);
486 }
487 
490 {
491  /* Invalid packet when status is STATUS_AUTH_GAME or higher */
493 
494  this->status = STATUS_AUTH_GAME;
495  /* Reset 'lag' counters */
497 
499  this->SendPacket(p);
501 }
502 
505 {
506  /* Invalid packet when status is STATUS_AUTH_COMPANY or higher */
508 
509  this->status = STATUS_AUTH_COMPANY;
510  /* Reset 'lag' counters */
512 
516  this->SendPacket(p);
518 }
519 
522 {
523  Packet *p;
524 
525  /* Invalid packet when status is AUTH or higher */
527 
528  this->status = STATUS_AUTHORIZED;
529  /* Reset 'lag' counters */
531 
533 
534  p = new Packet(PACKET_SERVER_WELCOME);
535  p->Send_uint32(this->client_id);
538  this->SendPacket(p);
539 
540  /* Transmit info about all the active clients */
541  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
542  if (new_cs != this && new_cs->status > STATUS_AUTHORIZED) {
543  this->SendClientInfo(new_cs->GetInfo());
544  }
545  }
546  /* Also send the info of the server */
548 }
549 
552 {
553  int waiting = 0;
554  Packet *p;
555 
556  /* Count how many clients are waiting in the queue, in front of you! */
557  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
558  if (new_cs->status != STATUS_MAP_WAIT) continue;
559  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++;
560  }
561 
562  p = new Packet(PACKET_SERVER_WAIT);
563  p->Send_uint8(waiting);
564  this->SendPacket(p);
566 }
567 
570 {
571  static uint sent_packets; // How many packets we did send successfully last time
572 
573  if (this->status < STATUS_AUTHORIZED) {
574  /* Illegal call, return error and ignore the packet */
575  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
576  }
577 
578  if (this->status == STATUS_AUTHORIZED) {
579  this->savegame = new PacketWriter(this);
580 
581  /* Now send the _frame_counter and how many packets are coming */
584  this->SendPacket(p);
585 
587  this->status = STATUS_MAP;
588  /* Mark the start of download */
589  this->last_frame = _frame_counter;
591 
592  sent_packets = 4; // We start with trying 4 packets
593 
594  /* Make a dump of the current game */
595  if (SaveWithFilter(this->savegame, true) != SL_OK) usererror("network savedump failed");
596  }
597 
598  if (this->status == STATUS_MAP) {
599  bool last_packet = false;
600  bool has_packets = false;
601 
602  for (uint i = 0; (has_packets = this->savegame->HasPackets()) && i < sent_packets; i++) {
603  Packet *p = this->savegame->PopPacket();
604  last_packet = p->buffer[2] == PACKET_SERVER_MAP_DONE;
605 
606  this->SendPacket(p);
607 
608  if (last_packet) {
609  /* There is no more data, so break the for */
610  break;
611  }
612  }
613 
614  if (last_packet) {
615  /* Done reading, make sure saving is done as well */
616  this->savegame->Destroy();
617  this->savegame = nullptr;
618 
619  /* Set the status to DONE_MAP, no we will wait for the client
620  * to send it is ready (maybe that happens like never ;)) */
621  this->status = STATUS_DONE_MAP;
622 
623  /* Find the best candidate for joining, i.e. the first joiner. */
624  NetworkClientSocket *best = nullptr;
625  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
626  if (new_cs->status == STATUS_MAP_WAIT) {
627  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)) {
628  best = new_cs;
629  }
630  }
631  }
632 
633  /* Is there someone else to join? */
634  if (best != nullptr) {
635  /* Let the first start joining. */
636  best->status = STATUS_AUTHORIZED;
637  best->SendMap();
638 
639  /* And update the rest. */
640  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
641  if (new_cs->status == STATUS_MAP_WAIT) new_cs->SendWait();
642  }
643  }
644  }
645 
646  switch (this->SendPackets()) {
647  case SPS_CLOSED:
649 
650  case SPS_ALL_SENT:
651  /* All are sent, increase the sent_packets */
652  if (has_packets) sent_packets *= 2;
653  break;
654 
655  case SPS_PARTLY_SENT:
656  /* Only a part is sent; leave the transmission state. */
657  break;
658 
659  case SPS_NONE_SENT:
660  /* Not everything is sent, decrease the sent_packets */
661  if (sent_packets > 1) sent_packets /= 2;
662  break;
663  }
664  }
666 }
667 
673 {
674  Packet *p = new Packet(PACKET_SERVER_JOIN);
675 
676  p->Send_uint32(client_id);
677 
678  this->SendPacket(p);
680 }
681 
684 {
688 #ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
690 #ifdef NETWORK_SEND_DOUBLE_SEED
691  p->Send_uint32(_sync_seed_2);
692 #endif
693 #endif
694 
695  /* If token equals 0, we need to make a new token and send that. */
696  if (this->last_token == 0) {
697  this->last_token = InteractiveRandomRange(UINT8_MAX - 1) + 1;
698  p->Send_uint8(this->last_token);
699  }
700 
701  this->SendPacket(p);
703 }
704 
707 {
708  Packet *p = new Packet(PACKET_SERVER_SYNC);
711 
712 #ifdef NETWORK_SEND_DOUBLE_SEED
713  p->Send_uint32(_sync_seed_2);
714 #endif
715  this->SendPacket(p);
717 }
718 
724 {
726 
728  p->Send_uint32(cp->frame);
729  p->Send_bool (cp->my_cmd);
730 
731  this->SendPacket(p);
733 }
734 
744 {
746 
747  Packet *p = new Packet(PACKET_SERVER_CHAT);
748 
749  p->Send_uint8 (action);
750  p->Send_uint32(client_id);
751  p->Send_bool (self_send);
752  p->Send_string(msg);
753  p->Send_uint64(data);
754 
755  this->SendPacket(p);
757 }
758 
765 {
767 
768  p->Send_uint32(client_id);
769  p->Send_uint8 (errorno);
770 
771  this->SendPacket(p);
773 }
774 
780 {
781  Packet *p = new Packet(PACKET_SERVER_QUIT);
782 
783  p->Send_uint32(client_id);
784 
785  this->SendPacket(p);
787 }
788 
791 {
793  this->SendPacket(p);
795 }
796 
799 {
801  this->SendPacket(p);
803 }
804 
811 {
812  Packet *p = new Packet(PACKET_SERVER_RCON);
813 
814  p->Send_uint16(colour);
815  p->Send_string(command);
816  this->SendPacket(p);
818 }
819 
826 {
827  Packet *p = new Packet(PACKET_SERVER_MOVE);
828 
829  p->Send_uint32(client_id);
830  p->Send_uint8(company_id);
831  this->SendPacket(p);
833 }
834 
837 {
839 
841  this->SendPacket(p);
843 }
844 
847 {
849 
852  this->SendPacket(p);
854 }
855 
856 /***********
857  * Receiving functions
858  * DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientSocket *cs, Packet *p
859  ************/
860 
862 {
863  return this->SendCompanyInfo();
864 }
865 
867 {
868  if (this->status != STATUS_NEWGRFS_CHECK) {
869  /* Illegal call, return error and ignore the packet */
870  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
871  }
872 
873  NetworkClientInfo *ci = this->GetInfo();
874 
875  /* We now want a password from the client else we do not allow him in! */
877  return this->SendNeedGamePassword();
878  }
879 
881  return this->SendNeedCompanyPassword();
882  }
883 
884  return this->SendWelcome();
885 }
886 
888 {
889  if (this->status != STATUS_INACTIVE) {
890  /* Illegal call, return error and ignore the packet */
891  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
892  }
893 
894  char name[NETWORK_CLIENT_NAME_LENGTH];
895  CompanyID playas;
896  NetworkLanguage client_lang;
897  char client_revision[NETWORK_REVISION_LENGTH];
898 
899  p->Recv_string(client_revision, sizeof(client_revision));
900  uint32 newgrf_version = p->Recv_uint32();
901 
902  /* Check if the client has revision control enabled */
903  if (!IsNetworkCompatibleVersion(client_revision) || _openttd_newgrf_version != newgrf_version) {
904  /* Different revisions!! */
905  return this->SendError(NETWORK_ERROR_WRONG_REVISION);
906  }
907 
908  p->Recv_string(name, sizeof(name));
909  playas = (Owner)p->Recv_uint8();
910  client_lang = (NetworkLanguage)p->Recv_uint8();
911 
912  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
913 
914  /* join another company does not affect these values */
915  switch (playas) {
916  case COMPANY_NEW_COMPANY: // New company
918  return this->SendError(NETWORK_ERROR_FULL);
919  }
920  break;
921  case COMPANY_SPECTATOR: // Spectator
922  if (NetworkSpectatorCount() >= _settings_client.network.max_spectators) {
923  return this->SendError(NETWORK_ERROR_FULL);
924  }
925  break;
926  default: // Join another company (companies 1-8 (index 0-7))
927  if (!Company::IsValidHumanID(playas)) {
928  return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
929  }
930  break;
931  }
932 
933  /* We need a valid name.. make it Player */
934  if (StrEmpty(name)) strecpy(name, "Player", lastof(name));
935 
936  if (!NetworkFindName(name, lastof(name))) { // Change name if duplicate
937  /* We could not create a name for this client */
938  return this->SendError(NETWORK_ERROR_NAME_IN_USE);
939  }
940 
943  this->SetInfo(ci);
944  ci->join_date = _date;
945  strecpy(ci->client_name, name, lastof(ci->client_name));
946  ci->client_playas = playas;
947  ci->client_lang = client_lang;
948  DEBUG(desync, 1, "client: %08x; %02x; %02x; %02x", _date, _date_fract, (int)ci->client_playas, (int)ci->index);
949 
950  /* Make sure companies to which people try to join are not autocleaned */
952 
954 
955  if (_grfconfig == nullptr) {
956  /* Behave as if we received PACKET_CLIENT_NEWGRFS_CHECKED */
957  return this->Receive_CLIENT_NEWGRFS_CHECKED(nullptr);
958  }
959 
960  return this->SendNewGRFCheck();
961 }
962 
964 {
965  if (this->status != STATUS_AUTH_GAME) {
966  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
967  }
968 
969  char password[NETWORK_PASSWORD_LENGTH];
970  p->Recv_string(password, sizeof(password));
971 
972  /* Check game password. Allow joining if we cleared the password meanwhile */
974  strcmp(password, _settings_client.network.server_password) != 0) {
975  /* Password is invalid */
976  return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
977  }
978 
979  const NetworkClientInfo *ci = this->GetInfo();
981  return this->SendNeedCompanyPassword();
982  }
983 
984  /* Valid password, allow user */
985  return this->SendWelcome();
986 }
987 
989 {
990  if (this->status != STATUS_AUTH_COMPANY) {
991  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
992  }
993 
994  char password[NETWORK_PASSWORD_LENGTH];
995  p->Recv_string(password, sizeof(password));
996 
997  /* Check company password. Allow joining if we cleared the password meanwhile.
998  * Also, check the company is still valid - client could be moved to spectators
999  * in the middle of the authorization process */
1000  CompanyID playas = this->GetInfo()->client_playas;
1001  if (Company::IsValidID(playas) && !StrEmpty(_network_company_states[playas].password) &&
1002  strcmp(password, _network_company_states[playas].password) != 0) {
1003  /* Password is invalid */
1004  return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
1005  }
1006 
1007  return this->SendWelcome();
1008 }
1009 
1011 {
1012  /* The client was never joined.. so this is impossible, right?
1013  * Ignore the packet, give the client a warning, and close his connection */
1014  if (this->status < STATUS_AUTHORIZED || this->HasClientQuit()) {
1015  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1016  }
1017 
1018  /* Check if someone else is receiving the map */
1019  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
1020  if (new_cs->status == STATUS_MAP) {
1021  /* Tell the new client to wait */
1022  this->status = STATUS_MAP_WAIT;
1023  return this->SendWait();
1024  }
1025  }
1026 
1027  /* We receive a request to upload the map.. give it to the client! */
1028  return this->SendMap();
1029 }
1030 
1032 {
1033  /* Client has the map, now start syncing */
1034  if (this->status == STATUS_DONE_MAP && !this->HasClientQuit()) {
1035  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1036 
1037  this->GetClientName(client_name, lastof(client_name));
1038 
1039  NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, nullptr, this->client_id);
1040 
1041  /* Mark the client as pre-active, and wait for an ACK
1042  * so we know he is done loading and in sync with us */
1043  this->status = STATUS_PRE_ACTIVE;
1045  this->SendFrame();
1046  this->SendSync();
1047 
1048  /* This is the frame the client receives
1049  * we need it later on to make sure the client is not too slow */
1050  this->last_frame = _frame_counter;
1052 
1053  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
1054  if (new_cs->status > STATUS_AUTHORIZED) {
1055  new_cs->SendClientInfo(this->GetInfo());
1056  new_cs->SendJoin(this->client_id);
1057  }
1058  }
1059 
1060  NetworkAdminClientInfo(this, true);
1061 
1062  /* also update the new client with our max values */
1063  this->SendConfigUpdate();
1064 
1065  /* quickly update the syncing client with company details */
1066  return this->SendCompanyUpdate();
1067  }
1068 
1069  /* Wrong status for this packet, give a warning to client, and close connection */
1070  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1071 }
1072 
1078 {
1079  /* The client was never joined.. so this is impossible, right?
1080  * Ignore the packet, give the client a warning, and close his connection */
1081  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1082  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1083  }
1084 
1086  return this->SendError(NETWORK_ERROR_TOO_MANY_COMMANDS);
1087  }
1088 
1089  CommandPacket cp;
1090  const char *err = this->ReceiveCommand(p, &cp);
1091 
1092  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
1093 
1094  NetworkClientInfo *ci = this->GetInfo();
1095 
1096  if (err != nullptr) {
1097  IConsolePrintF(CC_ERROR, "WARNING: %s from client %d (IP: %s).", err, ci->client_id, this->GetClientIP());
1098  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1099  }
1100 
1101 
1102  if ((GetCommandFlags(cp.cmd) & CMD_SERVER) && ci->client_id != CLIENT_ID_SERVER) {
1103  IConsolePrintF(CC_ERROR, "WARNING: server only command from: client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
1104  return this->SendError(NETWORK_ERROR_KICKED);
1105  }
1106 
1108  IConsolePrintF(CC_ERROR, "WARNING: spectator issuing command from client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
1109  return this->SendError(NETWORK_ERROR_KICKED);
1110  }
1111 
1117  if (!(cp.cmd == CMD_COMPANY_CTRL && cp.p1 == 0 && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) {
1118  IConsolePrintF(CC_ERROR, "WARNING: client %d (IP: %s) tried to execute a command as company %d, kicking...",
1119  ci->client_playas + 1, this->GetClientIP(), cp.company + 1);
1120  return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
1121  }
1122 
1123  if (cp.cmd == CMD_COMPANY_CTRL) {
1124  if (cp.p1 != 0 || cp.company != COMPANY_SPECTATOR) {
1125  return this->SendError(NETWORK_ERROR_CHEATER);
1126  }
1127 
1128  /* 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! */
1130  NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_CLIENT, ci->client_id, "cannot create new company, server full", CLIENT_ID_SERVER);
1131  return NETWORK_RECV_STATUS_OKAY;
1132  }
1133  }
1134 
1135  if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) cp.p2 = this->client_id;
1136 
1137  this->incoming_queue.Append(&cp);
1138  return NETWORK_RECV_STATUS_OKAY;
1139 }
1140 
1142 {
1143  /* This packets means a client noticed an error and is reporting this
1144  * to us. Display the error and report it to the other clients */
1145  char str[100];
1146  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1148 
1149  /* The client was never joined.. thank the client for the packet, but ignore it */
1150  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1152  }
1153 
1154  this->GetClientName(client_name, lastof(client_name));
1155 
1156  StringID strid = GetNetworkErrorMsg(errorno);
1157  GetString(str, strid, lastof(str));
1158 
1159  DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
1160 
1161  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid);
1162 
1163  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
1164  if (new_cs->status > STATUS_AUTHORIZED) {
1165  new_cs->SendErrorQuit(this->client_id, errorno);
1166  }
1167  }
1168 
1169  NetworkAdminClientError(this->client_id, errorno);
1170 
1172 }
1173 
1175 {
1176  /* The client wants to leave. Display this and report it to the other
1177  * clients. */
1178  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1179 
1180  /* The client was never joined.. thank the client for the packet, but ignore it */
1181  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1183  }
1184 
1185  this->GetClientName(client_name, lastof(client_name));
1186 
1187  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
1188 
1189  for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
1190  if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
1191  new_cs->SendQuit(this->client_id);
1192  }
1193  }
1194 
1196 
1198 }
1199 
1201 {
1202  if (this->status < STATUS_AUTHORIZED) {
1203  /* Illegal call, return error and ignore the packet */
1204  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1205  }
1206 
1207  uint32 frame = p->Recv_uint32();
1208 
1209  /* The client is trying to catch up with the server */
1210  if (this->status == STATUS_PRE_ACTIVE) {
1211  /* The client is not yet caught up? */
1212  if (frame + DAY_TICKS < _frame_counter) return NETWORK_RECV_STATUS_OKAY;
1213 
1214  /* Now he is! Unpause the game */
1215  this->status = STATUS_ACTIVE;
1217 
1218  /* Execute script for, e.g. MOTD */
1219  IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
1220  }
1221 
1222  /* Get, and validate the token. */
1223  uint8 token = p->Recv_uint8();
1224  if (token == this->last_token) {
1225  /* We differentiate between last_token_frame and last_frame so the lag
1226  * test uses the actual lag of the client instead of the lag for getting
1227  * the token back and forth; after all, the token is only sent every
1228  * time we receive a PACKET_CLIENT_ACK, after which we will send a new
1229  * token to the client. If the lag would be one day, then we would not
1230  * be sending the new token soon enough for the new daily scheduled
1231  * PACKET_CLIENT_ACK. This would then register the lag of the client as
1232  * two days, even when it's only a single day. */
1234  /* Request a new token. */
1235  this->last_token = 0;
1236  }
1237 
1238  /* The client received the frame, make note of it */
1239  this->last_frame = frame;
1240  /* With those 2 values we can calculate the lag realtime */
1242  return NETWORK_RECV_STATUS_OKAY;
1243 }
1244 
1245 
1256 void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, ClientID from_id, int64 data, bool from_admin)
1257 {
1258  const NetworkClientInfo *ci, *ci_own, *ci_to;
1259 
1260  switch (desttype) {
1261  case DESTTYPE_CLIENT:
1262  /* Are we sending to the server? */
1263  if ((ClientID)dest == CLIENT_ID_SERVER) {
1264  ci = NetworkClientInfo::GetByClientID(from_id);
1265  /* Display the text locally, and that is it */
1266  if (ci != nullptr) {
1267  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1268 
1270  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1271  }
1272  }
1273  } else {
1274  /* Else find the client to send the message to */
1275  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1276  if (cs->client_id == (ClientID)dest) {
1277  cs->SendChat(action, from_id, false, msg, data);
1278  break;
1279  }
1280  }
1281  }
1282 
1283  /* Display the message locally (so you know you have sent it) */
1284  if (from_id != (ClientID)dest) {
1285  if (from_id == CLIENT_ID_SERVER) {
1286  ci = NetworkClientInfo::GetByClientID(from_id);
1288  if (ci != nullptr && ci_to != nullptr) {
1289  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), true, ci_to->client_name, msg, data);
1290  }
1291  } else {
1292  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1293  if (cs->client_id == from_id) {
1294  cs->SendChat(action, (ClientID)dest, true, msg, data);
1295  break;
1296  }
1297  }
1298  }
1299  }
1300  break;
1301  case DESTTYPE_TEAM: {
1302  /* If this is false, the message is already displayed on the client who sent it. */
1303  bool show_local = true;
1304  /* Find all clients that belong to this company */
1305  ci_to = nullptr;
1306  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1307  ci = cs->GetInfo();
1308  if (ci != nullptr && ci->client_playas == (CompanyID)dest) {
1309  cs->SendChat(action, from_id, false, msg, data);
1310  if (cs->client_id == from_id) show_local = false;
1311  ci_to = ci; // Remember a client that is in the company for company-name
1312  }
1313  }
1314 
1315  /* if the server can read it, let the admin network read it, too. */
1317  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1318  }
1319 
1320  ci = NetworkClientInfo::GetByClientID(from_id);
1322  if (ci != nullptr && ci_own != nullptr && ci_own->client_playas == dest) {
1323  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1324  if (from_id == CLIENT_ID_SERVER) show_local = false;
1325  ci_to = ci_own;
1326  }
1327 
1328  /* There is no such client */
1329  if (ci_to == nullptr) break;
1330 
1331  /* Display the message locally (so you know you have sent it) */
1332  if (ci != nullptr && show_local) {
1333  if (from_id == CLIENT_ID_SERVER) {
1334  char name[NETWORK_NAME_LENGTH];
1335  StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
1336  SetDParam(0, ci_to->client_playas);
1337  GetString(name, str, lastof(name));
1338  NetworkTextMessage(action, GetDrawStringCompanyColour(ci_own->client_playas), true, name, msg, data);
1339  } else {
1340  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1341  if (cs->client_id == from_id) {
1342  cs->SendChat(action, ci_to->client_id, true, msg, data);
1343  }
1344  }
1345  }
1346  }
1347  break;
1348  }
1349  default:
1350  DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
1351  FALLTHROUGH;
1352 
1353  case DESTTYPE_BROADCAST:
1354  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1355  cs->SendChat(action, from_id, false, msg, data);
1356  }
1357 
1358  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1359 
1360  ci = NetworkClientInfo::GetByClientID(from_id);
1361  if (ci != nullptr) {
1362  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1363  }
1364  break;
1365  }
1366 }
1367 
1369 {
1370  if (this->status < STATUS_PRE_ACTIVE) {
1371  /* Illegal call, return error and ignore the packet */
1372  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1373  }
1374 
1375  NetworkAction action = (NetworkAction)p->Recv_uint8();
1376  DestType desttype = (DestType)p->Recv_uint8();
1377  int dest = p->Recv_uint32();
1378  char msg[NETWORK_CHAT_LENGTH];
1379 
1381  int64 data = p->Recv_uint64();
1382 
1383  NetworkClientInfo *ci = this->GetInfo();
1384  switch (action) {
1385  case NETWORK_ACTION_GIVE_MONEY:
1386  if (!Company::IsValidID(ci->client_playas)) break;
1387  FALLTHROUGH;
1388  case NETWORK_ACTION_CHAT:
1389  case NETWORK_ACTION_CHAT_CLIENT:
1390  case NETWORK_ACTION_CHAT_COMPANY:
1391  NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data);
1392  break;
1393  default:
1394  IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, this->GetClientIP());
1395  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1396  }
1397  return NETWORK_RECV_STATUS_OKAY;
1398 }
1399 
1401 {
1402  if (this->status != STATUS_ACTIVE) {
1403  /* Illegal call, return error and ignore the packet */
1404  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1405  }
1406 
1407  char password[NETWORK_PASSWORD_LENGTH];
1408  const NetworkClientInfo *ci;
1409 
1410  p->Recv_string(password, sizeof(password));
1411  ci = this->GetInfo();
1412 
1414  return NETWORK_RECV_STATUS_OKAY;
1415 }
1416 
1418 {
1419  if (this->status != STATUS_ACTIVE) {
1420  /* Illegal call, return error and ignore the packet */
1421  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1422  }
1423 
1424  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1425  NetworkClientInfo *ci;
1426 
1427  p->Recv_string(client_name, sizeof(client_name));
1428  ci = this->GetInfo();
1429 
1430  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
1431 
1432  if (ci != nullptr) {
1433  /* Display change */
1434  if (NetworkFindName(client_name, lastof(client_name))) {
1435  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name);
1436  strecpy(ci->client_name, client_name, lastof(ci->client_name));
1438  }
1439  }
1440  return NETWORK_RECV_STATUS_OKAY;
1441 }
1442 
1444 {
1445  if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1446 
1447  char pass[NETWORK_PASSWORD_LENGTH];
1448  char command[NETWORK_RCONCOMMAND_LENGTH];
1449 
1451 
1452  p->Recv_string(pass, sizeof(pass));
1453  p->Recv_string(command, sizeof(command));
1454 
1455  if (strcmp(pass, _settings_client.network.rcon_password) != 0) {
1456  DEBUG(net, 0, "[rcon] wrong password from client-id %d", this->client_id);
1457  return NETWORK_RECV_STATUS_OKAY;
1458  }
1459 
1460  DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", this->client_id, command);
1461 
1463  IConsoleCmdExec(command);
1465  return NETWORK_RECV_STATUS_OKAY;
1466 }
1467 
1469 {
1470  if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1471 
1472  CompanyID company_id = (Owner)p->Recv_uint8();
1473 
1474  /* Check if the company is valid, we don't allow moving to AI companies */
1475  if (company_id != COMPANY_SPECTATOR && !Company::IsValidHumanID(company_id)) return NETWORK_RECV_STATUS_OKAY;
1476 
1477  /* Check if we require a password for this company */
1478  if (company_id != COMPANY_SPECTATOR && !StrEmpty(_network_company_states[company_id].password)) {
1479  /* we need a password from the client - should be in this packet */
1480  char password[NETWORK_PASSWORD_LENGTH];
1481  p->Recv_string(password, sizeof(password));
1482 
1483  /* Incorrect password sent, return! */
1484  if (strcmp(password, _network_company_states[company_id].password) != 0) {
1485  DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", this->client_id, company_id + 1);
1486  return NETWORK_RECV_STATUS_OKAY;
1487  }
1488  }
1489 
1490  /* if we get here we can move the client */
1491  NetworkServerDoMove(this->client_id, company_id);
1492  return NETWORK_RECV_STATUS_OKAY;
1493 }
1494 
1503 {
1504  /* Grab the company name */
1505  char company_name[NETWORK_COMPANY_NAME_LENGTH];
1506  SetDParam(0, c->index);
1507 
1508  assert(max_len <= lengthof(company_name));
1509  GetString(company_name, STR_COMPANY_NAME, company_name + max_len - 1);
1510 
1511  /* Get the income */
1512  Money income = 0;
1513  if (_cur_year - 1 == c->inaugurated_year) {
1514  /* The company is here just 1 year, so display [2], else display[1] */
1515  for (uint i = 0; i < lengthof(c->yearly_expenses[2]); i++) {
1516  income -= c->yearly_expenses[2][i];
1517  }
1518  } else {
1519  for (uint i = 0; i < lengthof(c->yearly_expenses[1]); i++) {
1520  income -= c->yearly_expenses[1][i];
1521  }
1522  }
1523 
1524  /* Send the information */
1525  p->Send_uint8 (c->index);
1526  p->Send_string(company_name);
1529  p->Send_uint64(c->money);
1530  p->Send_uint64(income);
1532 
1533  /* Send 1 if there is a password for the company else send 0 */
1535 
1536  for (uint i = 0; i < NETWORK_VEH_END; i++) {
1537  p->Send_uint16(stats->num_vehicle[i]);
1538  }
1539 
1540  for (uint i = 0; i < NETWORK_VEH_END; i++) {
1541  p->Send_uint16(stats->num_station[i]);
1542  }
1543 
1544  p->Send_bool(c->is_ai);
1545 }
1546 
1552 {
1553  memset(stats, 0, sizeof(*stats) * MAX_COMPANIES);
1554 
1555  /* Go through all vehicles and count the type of vehicles */
1556  for (const Vehicle *v : Vehicle::Iterate()) {
1557  if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
1558  byte type = 0;
1559  switch (v->type) {
1560  case VEH_TRAIN: type = NETWORK_VEH_TRAIN; break;
1561  case VEH_ROAD: type = RoadVehicle::From(v)->IsBus() ? NETWORK_VEH_BUS : NETWORK_VEH_LORRY; break;
1562  case VEH_AIRCRAFT: type = NETWORK_VEH_PLANE; break;
1563  case VEH_SHIP: type = NETWORK_VEH_SHIP; break;
1564  default: continue;
1565  }
1566  stats[v->owner].num_vehicle[type]++;
1567  }
1568 
1569  /* Go through all stations and count the types of stations */
1570  for (const Station *s : Station::Iterate()) {
1571  if (Company::IsValidID(s->owner)) {
1572  NetworkCompanyStats *npi = &stats[s->owner];
1573 
1574  if (s->facilities & FACIL_TRAIN) npi->num_station[NETWORK_VEH_TRAIN]++;
1575  if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[NETWORK_VEH_LORRY]++;
1576  if (s->facilities & FACIL_BUS_STOP) npi->num_station[NETWORK_VEH_BUS]++;
1577  if (s->facilities & FACIL_AIRPORT) npi->num_station[NETWORK_VEH_PLANE]++;
1578  if (s->facilities & FACIL_DOCK) npi->num_station[NETWORK_VEH_SHIP]++;
1579  }
1580  }
1581 }
1582 
1588 {
1590 
1591  if (ci == nullptr) return;
1592 
1593  DEBUG(desync, 1, "client: %08x; %02x; %02x; %04x", _date, _date_fract, (int)ci->client_playas, client_id);
1594 
1595  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1596  cs->SendClientInfo(ci);
1597  }
1598 
1600 }
1601 
1604 {
1606  DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
1607 
1610  case FT_SAVEGAME:
1611  case FT_SCENARIO:
1613  break;
1614 
1615  case FT_HEIGHTMAP:
1617  break;
1618 
1619  default:
1621  }
1622  }
1623 }
1624 
1632 {
1633  bool clients_in_company[MAX_COMPANIES];
1634  int vehicles_in_company[MAX_COMPANIES];
1635 
1637 
1638  memset(clients_in_company, 0, sizeof(clients_in_company));
1639 
1640  /* Detect the active companies */
1641  for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
1642  if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
1643  }
1644 
1645  if (!_network_dedicated) {
1647  if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
1648  }
1649 
1651  memset(vehicles_in_company, 0, sizeof(vehicles_in_company));
1652 
1653  for (const Vehicle *v : Vehicle::Iterate()) {
1654  if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
1655  vehicles_in_company[v->owner]++;
1656  }
1657  }
1658 
1659  /* Go through all the companies */
1660  for (const Company *c : Company::Iterate()) {
1661  /* Skip the non-active once */
1662  if (c->is_ai) continue;
1663 
1664  if (!clients_in_company[c->index]) {
1665  /* The company is empty for one month more */
1667 
1668  /* Is the company empty for autoclean_unprotected-months, and is there no protection? */
1670  /* Shut the company down */
1671  DoCommandP(0, CCA_DELETE | c->index << 16 | CRR_AUTOCLEAN << 24, 0, CMD_COMPANY_CTRL);
1672  IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no password", c->index + 1);
1673  }
1674  /* Is the company empty for autoclean_protected-months, and there is a protection? */
1676  /* Unprotect the company */
1677  _network_company_states[c->index].password[0] = '\0';
1678  IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", c->index + 1);
1679  _network_company_states[c->index].months_empty = 0;
1680  NetworkServerUpdateCompanyPassworded(c->index, false);
1681  }
1682  /* Is the company empty for autoclean_novehicles-months, and has no vehicles? */
1684  /* Shut the company down */
1685  DoCommandP(0, CCA_DELETE | c->index << 16 | CRR_AUTOCLEAN << 24, 0, CMD_COMPANY_CTRL);
1686  IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no vehicles", c->index + 1);
1687  }
1688  } else {
1689  /* It is not empty, reset the date */
1690  _network_company_states[c->index].months_empty = 0;
1691  }
1692  }
1693 }
1694 
1701 bool NetworkFindName(char *new_name, const char *last)
1702 {
1703  bool found_name = false;
1704  uint number = 0;
1705  char original_name[NETWORK_CLIENT_NAME_LENGTH];
1706 
1707  strecpy(original_name, new_name, lastof(original_name));
1708 
1709  while (!found_name) {
1710  found_name = true;
1711  for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
1712  if (strcmp(ci->client_name, new_name) == 0) {
1713  /* Name already in use */
1714  found_name = false;
1715  break;
1716  }
1717  }
1718  /* Check if it is the same as the server-name */
1720  if (ci != nullptr) {
1721  if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
1722  }
1723 
1724  if (!found_name) {
1725  /* Try a new name (<name> #1, <name> #2, and so on) */
1726 
1727  /* Something's really wrong when there're more names than clients */
1728  if (number++ > MAX_CLIENTS) break;
1729  seprintf(new_name, last, "%s #%d", original_name, number);
1730  }
1731  }
1732 
1733  return found_name;
1734 }
1735 
1743 {
1744  /* Check if the name's already in use */
1746  if (strcmp(ci->client_name, new_name) == 0) return false;
1747  }
1748 
1750  if (ci == nullptr) return false;
1751 
1752  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, true, ci->client_name, new_name);
1753 
1754  strecpy(ci->client_name, new_name, lastof(ci->client_name));
1755 
1756  NetworkUpdateClientInfo(client_id);
1757  return true;
1758 }
1759 
1766 void NetworkServerSetCompanyPassword(CompanyID company_id, const char *password, bool already_hashed)
1767 {
1768  if (!Company::IsValidHumanID(company_id)) return;
1769 
1770  if (!already_hashed) {
1772  }
1773 
1774  strecpy(_network_company_states[company_id].password, password, lastof(_network_company_states[company_id].password));
1775  NetworkServerUpdateCompanyPassworded(company_id, !StrEmpty(_network_company_states[company_id].password));
1776 }
1777 
1782 static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
1783 {
1784  CommandPacket *cp;
1785  while ((cp = cs->outgoing_queue.Pop()) != nullptr) {
1786  cs->SendCommand(cp);
1787  free(cp);
1788  }
1789 }
1790 
1795 void NetworkServer_Tick(bool send_frame)
1796 {
1797 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1798  bool send_sync = false;
1799 #endif
1800 
1801 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1804  send_sync = true;
1805  }
1806 #endif
1807 
1808  /* Now we are done with the frame, inform the clients that they can
1809  * do their frame! */
1810  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1811  /* We allow a number of bytes per frame, but only to the burst amount
1812  * to be available for packet receiving at any particular time. */
1813  cs->receive_limit = min(cs->receive_limit + _settings_client.network.bytes_per_frame,
1815 
1816  /* Check if the speed of the client is what we can expect from a client */
1817  uint lag = NetworkCalculateLag(cs);
1818  switch (cs->status) {
1819  case NetworkClientSocket::STATUS_ACTIVE:
1821  /* Client did still not report in within the specified limit. */
1822  IConsolePrintF(CC_ERROR, cs->last_packet + lag * MILLISECONDS_PER_TICK > _realtime_tick ?
1823  /* A packet was received in the last three game days, so the client is likely lagging behind. */
1824  "Client #%d is dropped because the client's game state is more than %d ticks behind" :
1825  /* No packet was received in the last three game days; sounds like a lost connection. */
1826  "Client #%d is dropped because the client did not respond for more than %d ticks",
1827  cs->client_id, lag);
1828  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1829  continue;
1830  }
1831 
1832  /* Report once per time we detect the lag, and only when we
1833  * received a packet in the last 2000 milliseconds. If we
1834  * did not receive a packet, then the client is not just
1835  * slow, but the connection is likely severed. Mentioning
1836  * frame_freq is not useful in this case. */
1837  if (lag > (uint)DAY_TICKS && cs->lag_test == 0 && cs->last_packet + 2000 > _realtime_tick) {
1838  IConsolePrintF(CC_WARNING, "[%d] Client #%d is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id);
1839  cs->lag_test = 1;
1840  }
1841 
1842  if (cs->last_frame_server - cs->last_token_frame >= _settings_client.network.max_lag_time) {
1843  /* This is a bad client! It didn't send the right token back within time. */
1844  IConsolePrintF(CC_ERROR, "Client #%d is dropped because it fails to send valid acks", cs->client_id);
1845  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1846  continue;
1847  }
1848  break;
1849 
1850  case NetworkClientSocket::STATUS_INACTIVE:
1851  case NetworkClientSocket::STATUS_NEWGRFS_CHECK:
1852  case NetworkClientSocket::STATUS_AUTHORIZED:
1853  /* NewGRF check and authorized states should be handled almost instantly.
1854  * So give them some lee-way, likewise for the query with inactive. */
1856  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);
1857  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1858  continue;
1859  }
1860  break;
1861 
1862  case NetworkClientSocket::STATUS_MAP:
1863  /* Downloading the map... this is the amount of time since starting the saving. */
1865  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);
1866  cs->SendError(NETWORK_ERROR_TIMEOUT_MAP);
1867  continue;
1868  }
1869  break;
1870 
1871  case NetworkClientSocket::STATUS_DONE_MAP:
1872  case NetworkClientSocket::STATUS_PRE_ACTIVE:
1873  /* The map has been sent, so this is for loading the map and syncing up. */
1875  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);
1876  cs->SendError(NETWORK_ERROR_TIMEOUT_JOIN);
1877  continue;
1878  }
1879  break;
1880 
1881  case NetworkClientSocket::STATUS_AUTH_GAME:
1882  case NetworkClientSocket::STATUS_AUTH_COMPANY:
1883  /* These don't block? */
1885  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);
1886  cs->SendError(NETWORK_ERROR_TIMEOUT_PASSWORD);
1887  continue;
1888  }
1889  break;
1890 
1891  case NetworkClientSocket::STATUS_MAP_WAIT:
1892  /* This is an internal state where we do not wait
1893  * on the client to move to a different state. */
1894  break;
1895 
1896  case NetworkClientSocket::STATUS_END:
1897  /* Bad server/code. */
1898  NOT_REACHED();
1899  }
1900 
1901  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) {
1902  /* Check if we can send command, and if we have anything in the queue */
1904 
1905  /* Send an updated _frame_counter_max to the client */
1906  if (send_frame) cs->SendFrame();
1907 
1908 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1909  /* Send a sync-check packet */
1910  if (send_sync) cs->SendSync();
1911 #endif
1912  }
1913  }
1914 
1915  /* See if we need to advertise */
1917 }
1918 
1921 {
1924 }
1925 
1928 {
1932 }
1933 
1936 {
1939 }
1940 
1946 {
1947  return this->client_address.GetHostname();
1948 }
1949 
1952 {
1953  static const char * const stat_str[] = {
1954  "inactive",
1955  "checking NewGRFs",
1956  "authorizing (server password)",
1957  "authorizing (company password)",
1958  "authorized",
1959  "waiting",
1960  "loading map",
1961  "map done",
1962  "ready",
1963  "active"
1964  };
1965  assert_compile(lengthof(stat_str) == NetworkClientSocket::STATUS_END);
1966 
1967  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1968  NetworkClientInfo *ci = cs->GetInfo();
1969  if (ci == nullptr) continue;
1970  uint lag = NetworkCalculateLag(cs);
1971  const char *status;
1972 
1973  status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
1974  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s",
1975  cs->client_id, ci->client_name, status, lag,
1976  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
1977  cs->GetClientIP());
1978  }
1979 }
1980 
1985 {
1986  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1987  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendConfigUpdate();
1988  }
1989 }
1990 
1996 void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded)
1997 {
1998  if (NetworkCompanyIsPassworded(company_id) == passworded) return;
1999 
2000  SB(_network_company_passworded, company_id, 1, !!passworded);
2002 
2003  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
2004  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendCompanyUpdate();
2005  }
2006 
2008 }
2009 
2017 {
2018  /* Only allow non-dedicated servers and normal clients to be moved */
2019  if (client_id == CLIENT_ID_SERVER && _network_dedicated) return;
2020 
2022 
2023  /* No need to waste network resources if the client is in the company already! */
2024  if (ci->client_playas == company_id) return;
2025 
2026  ci->client_playas = company_id;
2027 
2028  if (client_id == CLIENT_ID_SERVER) {
2029  SetLocalCompany(company_id);
2030  } else {
2031  NetworkClientSocket *cs = NetworkClientSocket::GetByClientID(client_id);
2032  /* When the company isn't authorized we can't move them yet. */
2033  if (cs->status < NetworkClientSocket::STATUS_AUTHORIZED) return;
2034  cs->SendMove(client_id, company_id);
2035  }
2036 
2037  /* announce the client's move */
2038  NetworkUpdateClientInfo(client_id);
2039 
2040  NetworkAction action = (company_id == COMPANY_SPECTATOR) ? NETWORK_ACTION_COMPANY_SPECTATOR : NETWORK_ACTION_COMPANY_JOIN;
2041  NetworkServerSendChat(action, DESTTYPE_BROADCAST, 0, "", client_id, company_id + 1);
2042 }
2043 
2050 void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string)
2051 {
2052  NetworkClientSocket::GetByClientID(client_id)->SendRConResult(colour_code, string);
2053 }
2054 
2060 void NetworkServerKickClient(ClientID client_id, const char *reason)
2061 {
2062  if (client_id == CLIENT_ID_SERVER) return;
2063  NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED, reason);
2064 }
2065 
2072 uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const char *reason)
2073 {
2074  return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban, reason);
2075 }
2076 
2083 uint NetworkServerKickOrBanIP(const char *ip, bool ban, const char *reason)
2084 {
2085  /* Add address to ban-list */
2086  if (ban) {
2087  bool contains = false;
2088  for (const auto &iter : _network_ban_list) {
2089  if (iter == ip) {
2090  contains = true;
2091  break;
2092  }
2093  }
2094  if (!contains) _network_ban_list.emplace_back(ip);
2095  }
2096 
2097  uint n = 0;
2098 
2099  /* There can be multiple clients with the same IP, kick them all but don't kill the server,
2100  * or the client doing the rcon. The latter can't be kicked because kicking frees closes
2101  * and subsequently free the connection related instances, which we would be reading from
2102  * and writing to after returning. So we would read or write data from freed memory up till
2103  * the segfault triggers. */
2104  for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
2105  if (cs->client_id == CLIENT_ID_SERVER) continue;
2106  if (cs->client_id == _redirect_console_to_client) continue;
2107  if (cs->client_address.IsInNetmask(ip)) {
2108  NetworkServerKickClient(cs->client_id, reason);
2109  n++;
2110  }
2111  }
2112 
2113  return n;
2114 }
2115 
2122 {
2123  for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
2124  if (ci->client_playas == company) return true;
2125  }
2126  return false;
2127 }
2128 
2129 
2135 void ServerNetworkGameSocketHandler::GetClientName(char *client_name, const char *last) const
2136 {
2137  const NetworkClientInfo *ci = this->GetInfo();
2138 
2139  if (ci == nullptr || StrEmpty(ci->client_name)) {
2140  seprintf(client_name, last, "Client #%4d", this->client_id);
2141  } else {
2142  strecpy(client_name, ci->client_name, last);
2143  }
2144 }
2145 
2150 {
2152  if (_network_server) {
2153  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d IP: %s",
2154  ci->client_id,
2155  ci->client_name,
2156  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
2157  ci->client_id == CLIENT_ID_SERVER ? "server" : NetworkClientSocket::GetByClientID(ci->client_id)->GetClientIP());
2158  } else {
2159  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d",
2160  ci->client_id,
2161  ci->client_name,
2162  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0));
2163  }
2164  }
2165 }
2166 
2173 {
2174  assert(c != nullptr);
2175 
2176  if (!_network_server) return;
2177 
2179  _network_company_states[c->index].password[0] = '\0';
2181 
2182  if (ci != nullptr) {
2183  /* ci is nullptr when replaying, or for AIs. In neither case there is a client. */
2184  ci->client_playas = c->index;
2186  NetworkSendCommand(0, 0, 0, CMD_RENAME_PRESIDENT, nullptr, ci->client_name, c->index);
2187  }
2188 
2189  /* Announce new company on network. */
2190  NetworkAdminCompanyInfo(c, true);
2191 
2192  if (ci != nullptr) {
2193  /* ci is nullptr when replaying, or for AIs. In neither case there is a client.
2194  We need to send Admin port update here so that they first know about the new company
2195  and then learn about a possibly joining client (see FS#6025) */
2196  NetworkServerSendChat(NETWORK_ACTION_COMPANY_NEW, DESTTYPE_BROADCAST, 0, "", ci->client_id, c->index + 1);
2197  }
2198 }
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:82
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:34
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:22
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:110
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:2556
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:84
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:402
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:93
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.
void PrependQueue()
Prepend the current packet to the queue.
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:25
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:23
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:113
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:24
NetworkRecvStatus SendShutdown()
Tell the client we&#39;re shutting down.
static const uint16 SEND_MTU
Number of bytes we can pack in a single packet.
Definition: config.h: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:83
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:81
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:91
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