OpenTTD
network_server.cpp
Go to the documentation of this file.
1 /* $Id: network_server.cpp 27893 2017-08-13 18:38:42Z frosch $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #ifdef ENABLE_NETWORK
13 
14 #include "../stdafx.h"
15 #include "../strings_func.h"
16 #include "../date_func.h"
17 #include "network_admin.h"
18 #include "network_server.h"
19 #include "network_udp.h"
20 #include "network_base.h"
21 #include "../console_func.h"
22 #include "../company_base.h"
23 #include "../command_func.h"
24 #include "../saveload/saveload.h"
25 #include "../saveload/saveload_filter.h"
26 #include "../station_base.h"
27 #include "../genworld.h"
28 #include "../company_func.h"
29 #include "../company_gui.h"
30 #include "../roadveh.h"
31 #include "../order_backup.h"
32 #include "../core/pool_func.hpp"
33 #include "../core/random_func.hpp"
34 #include "../rev.h"
35 
36 #include "../safeguards.h"
37 
38 
39 /* This file handles all the server-commands */
40 
44 
49 
52 INSTANTIATE_POOL_METHODS(NetworkClientSocket)
53 
56 
59  ServerNetworkGameSocketHandler *cs;
61  size_t total_size;
64 
69  PacketWriter(ServerNetworkGameSocketHandler *cs) : SaveFilter(NULL), cs(cs), current(NULL), total_size(0), packets(NULL)
70  {
71  this->mutex = ThreadMutex::New();
72  }
73 
76  {
77  if (this->mutex != NULL) this->mutex->BeginCritical();
78 
79  if (this->cs != NULL && this->mutex != NULL) {
80  this->mutex->WaitForSignal();
81  }
82 
83  /* This must all wait until the Destroy function is called. */
84 
85  while (this->packets != NULL) {
86  Packet *p = this->packets->next;
87  delete this->packets;
88  this->packets = p;
89  }
90 
91  delete this->current;
92 
93  if (this->mutex != NULL) this->mutex->EndCritical();
94 
95  delete this->mutex;
96  this->mutex = NULL;
97  }
98 
109  void Destroy()
110  {
111  if (this->mutex != NULL) this->mutex->BeginCritical();
112 
113  this->cs = NULL;
114 
115  if (this->mutex != NULL) this->mutex->SendSignal();
116 
117  if (this->mutex != NULL) this->mutex->EndCritical();
118 
119  /* Make sure the saving is completely cancelled. Yes,
120  * we need to handle the save finish as well as the
121  * next connection might just be requesting a map. */
122  WaitTillSaved();
124  }
125 
133  bool HasPackets()
134  {
135  return this->packets != NULL;
136  }
137 
142  {
143  if (this->mutex != NULL) this->mutex->BeginCritical();
144 
145  Packet *p = this->packets;
146  this->packets = p->next;
147  p->next = NULL;
148 
149  if (this->mutex != NULL) this->mutex->EndCritical();
150 
151  return p;
152  }
153 
155  void AppendQueue()
156  {
157  if (this->current == NULL) return;
158 
159  Packet **p = &this->packets;
160  while (*p != NULL) {
161  p = &(*p)->next;
162  }
163  *p = this->current;
164 
165  this->current = NULL;
166  }
167 
168  /* virtual */ void Write(byte *buf, size_t size)
169  {
170  /* We want to abort the saving when the socket is closed. */
171  if (this->cs == NULL) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
172 
173  if (this->current == NULL) this->current = new Packet(PACKET_SERVER_MAP_DATA);
174 
175  if (this->mutex != NULL) this->mutex->BeginCritical();
176 
177  byte *bufe = buf + size;
178  while (buf != bufe) {
179  size_t to_write = min(SEND_MTU - this->current->size, bufe - buf);
180  memcpy(this->current->buffer + this->current->size, buf, to_write);
181  this->current->size += (PacketSize)to_write;
182  buf += to_write;
183 
184  if (this->current->size == SEND_MTU) {
185  this->AppendQueue();
186  if (buf != bufe) this->current = new Packet(PACKET_SERVER_MAP_DATA);
187  }
188  }
189 
190  if (this->mutex != NULL) this->mutex->EndCritical();
191 
192  this->total_size += size;
193  }
194 
195  /* virtual */ void Finish()
196  {
197  /* We want to abort the saving when the socket is closed. */
198  if (this->cs == NULL) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
199 
200  if (this->mutex != NULL) this->mutex->BeginCritical();
201 
202  /* Make sure the last packet is flushed. */
203  this->AppendQueue();
204 
205  /* Add a packet stating that this is the end to the queue. */
206  this->current = new Packet(PACKET_SERVER_MAP_DONE);
207  this->AppendQueue();
208 
209  /* Fast-track the size to the client. */
211  p->Send_uint32((uint32)this->total_size);
212  this->cs->NetworkTCPSocketHandler::SendPacket(p);
213 
214  if (this->mutex != NULL) this->mutex->EndCritical();
215  }
216 };
217 
218 
224 {
225  this->status = STATUS_INACTIVE;
226  this->client_id = _network_client_id++;
228 
229  /* The Socket and Info pools need to be the same in size. After all,
230  * each Socket will be associated with at most one Info object. As
231  * such if the Socket was allocated the Info object can as well. */
233 }
234 
239 {
242 
243  if (this->savegame != NULL) {
244  this->savegame->Destroy();
245  this->savegame = NULL;
246  }
247 }
248 
250 {
251  /* Only allow receiving when we have some buffer free; this value
252  * can go negative, but eventually it will become positive again. */
253  if (this->receive_limit <= 0) return NULL;
254 
255  /* We can receive a packet, so try that and if needed account for
256  * the amount of received data. */
258  if (p != NULL) this->receive_limit -= p->size;
259  return p;
260 }
261 
263 {
264  assert(status != NETWORK_RECV_STATUS_OKAY);
265  /*
266  * Sending a message just before leaving the game calls cs->SendPackets.
267  * This might invoke this function, which means that when we close the
268  * connection after cs->SendPackets we will close an already closed
269  * connection. This handles that case gracefully without having to make
270  * that code any more complex or more aware of the validity of the socket.
271  */
272  if (this->sock == INVALID_SOCKET) return status;
273 
274  if (status != NETWORK_RECV_STATUS_CONN_LOST && !this->HasClientQuit() && this->status >= STATUS_AUTHORIZED) {
275  /* We did not receive a leave message from this client... */
276  char client_name[NETWORK_CLIENT_NAME_LENGTH];
277  NetworkClientSocket *new_cs;
278 
279  this->GetClientName(client_name, lastof(client_name));
280 
281  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST);
282 
283  /* Inform other clients of this... strange leaving ;) */
284  FOR_ALL_CLIENT_SOCKETS(new_cs) {
285  if (new_cs->status > STATUS_AUTHORIZED && this != new_cs) {
286  new_cs->SendErrorQuit(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
287  }
288  }
289  }
290 
291  NetworkAdminClientError(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
292  DEBUG(net, 1, "Closed client connection %d", this->client_id);
293 
294  /* We just lost one client :( */
295  if (this->status >= STATUS_AUTHORIZED) _network_game_info.clients_on--;
296  extern byte _network_clients_connected;
297  _network_clients_connected--;
298 
301 
302  this->SendPackets(true);
303 
304  delete this->GetInfo();
305  delete this;
306 
307  return status;
308 }
309 
315 {
316  extern byte _network_clients_connected;
317  bool accept = _network_clients_connected < MAX_CLIENTS && _network_game_info.clients_on < _settings_client.network.max_clients;
318 
319  /* We can't go over the MAX_CLIENTS limit here. However, the
320  * pool must have place for all clients and ourself. */
323  return accept;
324 }
325 
328 {
329  NetworkClientSocket *cs;
331  if (cs->writable) {
332  if (cs->SendPackets() != SPS_CLOSED && cs->status == STATUS_MAP) {
333  /* This client is in the middle of a map-send, call the function for that */
334  cs->SendMap();
335  }
336  }
337  }
338 }
339 
340 static void NetworkHandleCommandQueue(NetworkClientSocket *cs);
341 
342 /***********
343  * Sending functions
344  * DEF_SERVER_SEND_COMMAND has parameter: NetworkClientSocket *cs
345  ************/
346 
352 {
353  if (ci->client_id != INVALID_CLIENT_ID) {
355  p->Send_uint32(ci->client_id);
356  p->Send_uint8 (ci->client_playas);
357  p->Send_string(ci->client_name);
358 
359  this->SendPacket(p);
360  }
362 }
363 
366 {
367  /* Fetch the latest version of the stats */
368  NetworkCompanyStats company_stats[MAX_COMPANIES];
369  NetworkPopulateCompanyStats(company_stats);
370 
371  /* Make a list of all clients per company */
372  char clients[MAX_COMPANIES][NETWORK_CLIENTS_LENGTH];
373  NetworkClientSocket *csi;
374  memset(clients, 0, sizeof(clients));
375 
376  /* Add the local player (if not dedicated) */
378  if (ci != NULL && Company::IsValidID(ci->client_playas)) {
379  strecpy(clients[ci->client_playas], ci->client_name, lastof(clients[ci->client_playas]));
380  }
381 
383  char client_name[NETWORK_CLIENT_NAME_LENGTH];
384 
385  ((ServerNetworkGameSocketHandler*)csi)->GetClientName(client_name, lastof(client_name));
386 
387  ci = csi->GetInfo();
388  if (ci != NULL && Company::IsValidID(ci->client_playas)) {
389  if (!StrEmpty(clients[ci->client_playas])) {
390  strecat(clients[ci->client_playas], ", ", lastof(clients[ci->client_playas]));
391  }
392 
393  strecat(clients[ci->client_playas], client_name, lastof(clients[ci->client_playas]));
394  }
395  }
396 
397  /* Now send the data */
398 
399  Company *company;
400  Packet *p;
401 
402  FOR_ALL_COMPANIES(company) {
404 
406  p->Send_bool (true);
407  this->SendCompanyInformation(p, company, &company_stats[company->index]);
408 
409  if (StrEmpty(clients[company->index])) {
410  p->Send_string("<none>");
411  } else {
412  p->Send_string(clients[company->index]);
413  }
414 
415  this->SendPacket(p);
416  }
417 
419 
421  p->Send_bool (false);
422 
423  this->SendPacket(p);
425 }
426 
432 {
433  char str[100];
435 
436  p->Send_uint8(error);
437  this->SendPacket(p);
438 
439  StringID strid = GetNetworkErrorMsg(error);
440  GetString(str, strid, lastof(str));
441 
442  /* Only send when the current client was in game */
443  if (this->status > STATUS_AUTHORIZED) {
444  NetworkClientSocket *new_cs;
445  char client_name[NETWORK_CLIENT_NAME_LENGTH];
446 
447  this->GetClientName(client_name, lastof(client_name));
448 
449  DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
450 
451  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, strid);
452 
453  FOR_ALL_CLIENT_SOCKETS(new_cs) {
454  if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
455  /* Some errors we filter to a more general error. Clients don't have to know the real
456  * reason a joining failed. */
457  if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION) {
458  error = NETWORK_ERROR_ILLEGAL_PACKET;
459  }
460  new_cs->SendErrorQuit(this->client_id, error);
461  }
462  }
463 
464  NetworkAdminClientError(this->client_id, error);
465  } else {
466  DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", this->client_id, str);
467  }
468 
469  /* The client made a mistake, so drop his connection now! */
471 }
472 
475 {
477  const GRFConfig *c;
478  uint grf_count = 0;
479 
480  for (c = _grfconfig; c != NULL; c = c->next) {
481  if (!HasBit(c->flags, GCF_STATIC)) grf_count++;
482  }
483 
484  p->Send_uint8 (grf_count);
485  for (c = _grfconfig; c != NULL; c = c->next) {
486  if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident);
487  }
488 
489  this->SendPacket(p);
491 }
492 
495 {
496  /* Invalid packet when status is STATUS_AUTH_GAME or higher */
498 
499  this->status = STATUS_AUTH_GAME;
500  /* Reset 'lag' counters */
502 
504  this->SendPacket(p);
506 }
507 
510 {
511  /* Invalid packet when status is STATUS_AUTH_COMPANY or higher */
513 
514  this->status = STATUS_AUTH_COMPANY;
515  /* Reset 'lag' counters */
517 
521  this->SendPacket(p);
523 }
524 
527 {
528  Packet *p;
529  NetworkClientSocket *new_cs;
530 
531  /* Invalid packet when status is AUTH or higher */
533 
534  this->status = STATUS_AUTHORIZED;
535  /* Reset 'lag' counters */
537 
539 
540  p = new Packet(PACKET_SERVER_WELCOME);
541  p->Send_uint32(this->client_id);
544  this->SendPacket(p);
545 
546  /* Transmit info about all the active clients */
547  FOR_ALL_CLIENT_SOCKETS(new_cs) {
548  if (new_cs != this && new_cs->status > STATUS_AUTHORIZED) {
549  this->SendClientInfo(new_cs->GetInfo());
550  }
551  }
552  /* Also send the info of the server */
554 }
555 
558 {
559  int waiting = 0;
560  NetworkClientSocket *new_cs;
561  Packet *p;
562 
563  /* Count how many clients are waiting in the queue, in front of you! */
564  FOR_ALL_CLIENT_SOCKETS(new_cs) {
565  if (new_cs->status != STATUS_MAP_WAIT) continue;
566  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++;
567  }
568 
569  p = new Packet(PACKET_SERVER_WAIT);
570  p->Send_uint8(waiting);
571  this->SendPacket(p);
573 }
574 
577 {
578  static uint sent_packets; // How many packets we did send successfully last time
579 
580  if (this->status < STATUS_AUTHORIZED) {
581  /* Illegal call, return error and ignore the packet */
582  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
583  }
584 
585  if (this->status == STATUS_AUTHORIZED) {
586  this->savegame = new PacketWriter(this);
587 
588  /* Now send the _frame_counter and how many packets are coming */
591  this->SendPacket(p);
592 
594  this->status = STATUS_MAP;
595  /* Mark the start of download */
596  this->last_frame = _frame_counter;
598 
599  sent_packets = 4; // We start with trying 4 packets
600 
601  /* Make a dump of the current game */
602  if (SaveWithFilter(this->savegame, true) != SL_OK) usererror("network savedump failed");
603  }
604 
605  if (this->status == STATUS_MAP) {
606  bool last_packet = false;
607  bool has_packets = false;
608 
609  for (uint i = 0; (has_packets = this->savegame->HasPackets()) && i < sent_packets; i++) {
610  Packet *p = this->savegame->PopPacket();
611  last_packet = p->buffer[2] == PACKET_SERVER_MAP_DONE;
612 
613  this->SendPacket(p);
614 
615  if (last_packet) {
616  /* There is no more data, so break the for */
617  break;
618  }
619  }
620 
621  if (last_packet) {
622  /* Done reading, make sure saving is done as well */
623  this->savegame->Destroy();
624  this->savegame = NULL;
625 
626  /* Set the status to DONE_MAP, no we will wait for the client
627  * to send it is ready (maybe that happens like never ;)) */
628  this->status = STATUS_DONE_MAP;
629 
630  /* Find the best candidate for joining, i.e. the first joiner. */
631  NetworkClientSocket *new_cs;
632  NetworkClientSocket *best = NULL;
633  FOR_ALL_CLIENT_SOCKETS(new_cs) {
634  if (new_cs->status == STATUS_MAP_WAIT) {
635  if (best == NULL || 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)) {
636  best = new_cs;
637  }
638  }
639  }
640 
641  /* Is there someone else to join? */
642  if (best != NULL) {
643  /* Let the first start joining. */
644  best->status = STATUS_AUTHORIZED;
645  best->SendMap();
646 
647  /* And update the rest. */
648  FOR_ALL_CLIENT_SOCKETS(new_cs) {
649  if (new_cs->status == STATUS_MAP_WAIT) new_cs->SendWait();
650  }
651  }
652  }
653 
654  switch (this->SendPackets()) {
655  case SPS_CLOSED:
657 
658  case SPS_ALL_SENT:
659  /* All are sent, increase the sent_packets */
660  if (has_packets) sent_packets *= 2;
661  break;
662 
663  case SPS_PARTLY_SENT:
664  /* Only a part is sent; leave the transmission state. */
665  break;
666 
667  case SPS_NONE_SENT:
668  /* Not everything is sent, decrease the sent_packets */
669  if (sent_packets > 1) sent_packets /= 2;
670  break;
671  }
672  }
674 }
675 
681 {
682  Packet *p = new Packet(PACKET_SERVER_JOIN);
683 
684  p->Send_uint32(client_id);
685 
686  this->SendPacket(p);
688 }
689 
692 {
696 #ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
698 #ifdef NETWORK_SEND_DOUBLE_SEED
699  p->Send_uint32(_sync_seed_2);
700 #endif
701 #endif
702 
703  /* If token equals 0, we need to make a new token and send that. */
704  if (this->last_token == 0) {
705  this->last_token = InteractiveRandomRange(UINT8_MAX - 1) + 1;
706  p->Send_uint8(this->last_token);
707  }
708 
709  this->SendPacket(p);
711 }
712 
715 {
716  Packet *p = new Packet(PACKET_SERVER_SYNC);
719 
720 #ifdef NETWORK_SEND_DOUBLE_SEED
721  p->Send_uint32(_sync_seed_2);
722 #endif
723  this->SendPacket(p);
725 }
726 
732 {
734 
736  p->Send_uint32(cp->frame);
737  p->Send_bool (cp->my_cmd);
738 
739  this->SendPacket(p);
741 }
742 
752 {
754 
755  Packet *p = new Packet(PACKET_SERVER_CHAT);
756 
757  p->Send_uint8 (action);
758  p->Send_uint32(client_id);
759  p->Send_bool (self_send);
760  p->Send_string(msg);
761  p->Send_uint64(data);
762 
763  this->SendPacket(p);
765 }
766 
773 {
775 
776  p->Send_uint32(client_id);
777  p->Send_uint8 (errorno);
778 
779  this->SendPacket(p);
781 }
782 
788 {
789  Packet *p = new Packet(PACKET_SERVER_QUIT);
790 
791  p->Send_uint32(client_id);
792 
793  this->SendPacket(p);
795 }
796 
799 {
801  this->SendPacket(p);
803 }
804 
807 {
809  this->SendPacket(p);
811 }
812 
819 {
820  Packet *p = new Packet(PACKET_SERVER_RCON);
821 
822  p->Send_uint16(colour);
823  p->Send_string(command);
824  this->SendPacket(p);
826 }
827 
834 {
835  Packet *p = new Packet(PACKET_SERVER_MOVE);
836 
837  p->Send_uint32(client_id);
838  p->Send_uint8(company_id);
839  this->SendPacket(p);
841 }
842 
845 {
847 
849  this->SendPacket(p);
851 }
852 
855 {
857 
860  this->SendPacket(p);
862 }
863 
864 /***********
865  * Receiving functions
866  * DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientSocket *cs, Packet *p
867  ************/
868 
870 {
871  return this->SendCompanyInfo();
872 }
873 
875 {
876  if (this->status != STATUS_NEWGRFS_CHECK) {
877  /* Illegal call, return error and ignore the packet */
878  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
879  }
880 
881  NetworkClientInfo *ci = this->GetInfo();
882 
883  /* We now want a password from the client else we do not allow him in! */
885  return this->SendNeedGamePassword();
886  }
887 
889  return this->SendNeedCompanyPassword();
890  }
891 
892  return this->SendWelcome();
893 }
894 
896 {
897  if (this->status != STATUS_INACTIVE) {
898  /* Illegal call, return error and ignore the packet */
899  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
900  }
901 
902  char name[NETWORK_CLIENT_NAME_LENGTH];
903  CompanyID playas;
904  NetworkLanguage client_lang;
905  char client_revision[NETWORK_REVISION_LENGTH];
906 
907  p->Recv_string(client_revision, sizeof(client_revision));
908  uint32 newgrf_version = p->Recv_uint32();
909 
910  /* Check if the client has revision control enabled */
911  if (!IsNetworkCompatibleVersion(client_revision) || _openttd_newgrf_version != newgrf_version) {
912  /* Different revisions!! */
913  return this->SendError(NETWORK_ERROR_WRONG_REVISION);
914  }
915 
916  p->Recv_string(name, sizeof(name));
917  playas = (Owner)p->Recv_uint8();
918  client_lang = (NetworkLanguage)p->Recv_uint8();
919 
920  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
921 
922  /* join another company does not affect these values */
923  switch (playas) {
924  case COMPANY_NEW_COMPANY: // New company
926  return this->SendError(NETWORK_ERROR_FULL);
927  }
928  break;
929  case COMPANY_SPECTATOR: // Spectator
930  if (NetworkSpectatorCount() >= _settings_client.network.max_spectators) {
931  return this->SendError(NETWORK_ERROR_FULL);
932  }
933  break;
934  default: // Join another company (companies 1-8 (index 0-7))
935  if (!Company::IsValidHumanID(playas)) {
936  return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
937  }
938  break;
939  }
940 
941  /* We need a valid name.. make it Player */
942  if (StrEmpty(name)) strecpy(name, "Player", lastof(name));
943 
944  if (!NetworkFindName(name, lastof(name))) { // Change name if duplicate
945  /* We could not create a name for this client */
946  return this->SendError(NETWORK_ERROR_NAME_IN_USE);
947  }
948 
951  this->SetInfo(ci);
952  ci->join_date = _date;
953  strecpy(ci->client_name, name, lastof(ci->client_name));
954  ci->client_playas = playas;
955  ci->client_lang = client_lang;
956  DEBUG(desync, 1, "client: %08x; %02x; %02x; %02x", _date, _date_fract, (int)ci->client_playas, (int)ci->index);
957 
958  /* Make sure companies to which people try to join are not autocleaned */
960 
962 
963  if (_grfconfig == NULL) {
964  /* Behave as if we received PACKET_CLIENT_NEWGRFS_CHECKED */
965  return this->Receive_CLIENT_NEWGRFS_CHECKED(NULL);
966  }
967 
968  return this->SendNewGRFCheck();
969 }
970 
972 {
973  if (this->status != STATUS_AUTH_GAME) {
974  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
975  }
976 
977  char password[NETWORK_PASSWORD_LENGTH];
978  p->Recv_string(password, sizeof(password));
979 
980  /* Check game password. Allow joining if we cleared the password meanwhile */
982  strcmp(password, _settings_client.network.server_password) != 0) {
983  /* Password is invalid */
984  return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
985  }
986 
987  const NetworkClientInfo *ci = this->GetInfo();
989  return this->SendNeedCompanyPassword();
990  }
991 
992  /* Valid password, allow user */
993  return this->SendWelcome();
994 }
995 
997 {
998  if (this->status != STATUS_AUTH_COMPANY) {
999  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1000  }
1001 
1002  char password[NETWORK_PASSWORD_LENGTH];
1003  p->Recv_string(password, sizeof(password));
1004 
1005  /* Check company password. Allow joining if we cleared the password meanwhile.
1006  * Also, check the company is still valid - client could be moved to spectators
1007  * in the middle of the authorization process */
1008  CompanyID playas = this->GetInfo()->client_playas;
1009  if (Company::IsValidID(playas) && !StrEmpty(_network_company_states[playas].password) &&
1010  strcmp(password, _network_company_states[playas].password) != 0) {
1011  /* Password is invalid */
1012  return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
1013  }
1014 
1015  return this->SendWelcome();
1016 }
1017 
1019 {
1020  NetworkClientSocket *new_cs;
1021  /* The client was never joined.. so this is impossible, right?
1022  * Ignore the packet, give the client a warning, and close his connection */
1023  if (this->status < STATUS_AUTHORIZED || this->HasClientQuit()) {
1024  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1025  }
1026 
1027  /* Check if someone else is receiving the map */
1028  FOR_ALL_CLIENT_SOCKETS(new_cs) {
1029  if (new_cs->status == STATUS_MAP) {
1030  /* Tell the new client to wait */
1031  this->status = STATUS_MAP_WAIT;
1032  return this->SendWait();
1033  }
1034  }
1035 
1036  /* We receive a request to upload the map.. give it to the client! */
1037  return this->SendMap();
1038 }
1039 
1041 {
1042  /* Client has the map, now start syncing */
1043  if (this->status == STATUS_DONE_MAP && !this->HasClientQuit()) {
1044  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1045  NetworkClientSocket *new_cs;
1046 
1047  this->GetClientName(client_name, lastof(client_name));
1048 
1049  NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, NULL, this->client_id);
1050 
1051  /* Mark the client as pre-active, and wait for an ACK
1052  * so we know he is done loading and in sync with us */
1053  this->status = STATUS_PRE_ACTIVE;
1055  this->SendFrame();
1056  this->SendSync();
1057 
1058  /* This is the frame the client receives
1059  * we need it later on to make sure the client is not too slow */
1060  this->last_frame = _frame_counter;
1062 
1063  FOR_ALL_CLIENT_SOCKETS(new_cs) {
1064  if (new_cs->status > STATUS_AUTHORIZED) {
1065  new_cs->SendClientInfo(this->GetInfo());
1066  new_cs->SendJoin(this->client_id);
1067  }
1068  }
1069 
1070  NetworkAdminClientInfo(this, true);
1071 
1072  /* also update the new client with our max values */
1073  this->SendConfigUpdate();
1074 
1075  /* quickly update the syncing client with company details */
1076  return this->SendCompanyUpdate();
1077  }
1078 
1079  /* Wrong status for this packet, give a warning to client, and close connection */
1080  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1081 }
1082 
1088 {
1089  /* The client was never joined.. so this is impossible, right?
1090  * Ignore the packet, give the client a warning, and close his connection */
1091  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1092  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1093  }
1094 
1096  return this->SendError(NETWORK_ERROR_TOO_MANY_COMMANDS);
1097  }
1098 
1099  CommandPacket cp;
1100  const char *err = this->ReceiveCommand(p, &cp);
1101 
1102  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
1103 
1104  NetworkClientInfo *ci = this->GetInfo();
1105 
1106  if (err != NULL) {
1107  IConsolePrintF(CC_ERROR, "WARNING: %s from client %d (IP: %s).", err, ci->client_id, this->GetClientIP());
1108  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1109  }
1110 
1111 
1112  if ((GetCommandFlags(cp.cmd) & CMD_SERVER) && ci->client_id != CLIENT_ID_SERVER) {
1113  IConsolePrintF(CC_ERROR, "WARNING: server only command from: client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
1114  return this->SendError(NETWORK_ERROR_KICKED);
1115  }
1116 
1118  IConsolePrintF(CC_ERROR, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
1119  return this->SendError(NETWORK_ERROR_KICKED);
1120  }
1121 
1127  if (!(cp.cmd == CMD_COMPANY_CTRL && cp.p1 == 0 && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) {
1128  IConsolePrintF(CC_ERROR, "WARNING: client %d (IP: %s) tried to execute a command as company %d, kicking...",
1129  ci->client_playas + 1, this->GetClientIP(), cp.company + 1);
1130  return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
1131  }
1132 
1133  if (cp.cmd == CMD_COMPANY_CTRL) {
1134  if (cp.p1 != 0 || cp.company != COMPANY_SPECTATOR) {
1135  return this->SendError(NETWORK_ERROR_CHEATER);
1136  }
1137 
1138  /* 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! */
1140  NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_CLIENT, ci->client_id, "cannot create new company, server full", CLIENT_ID_SERVER);
1141  return NETWORK_RECV_STATUS_OKAY;
1142  }
1143  }
1144 
1145  if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) cp.p2 = this->client_id;
1146 
1147  this->incoming_queue.Append(&cp);
1148  return NETWORK_RECV_STATUS_OKAY;
1149 }
1150 
1152 {
1153  /* This packets means a client noticed an error and is reporting this
1154  * to us. Display the error and report it to the other clients */
1155  NetworkClientSocket *new_cs;
1156  char str[100];
1157  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1159 
1160  /* The client was never joined.. thank the client for the packet, but ignore it */
1161  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1163  }
1164 
1165  this->GetClientName(client_name, lastof(client_name));
1166 
1167  StringID strid = GetNetworkErrorMsg(errorno);
1168  GetString(str, strid, lastof(str));
1169 
1170  DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
1171 
1172  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, strid);
1173 
1174  FOR_ALL_CLIENT_SOCKETS(new_cs) {
1175  if (new_cs->status > STATUS_AUTHORIZED) {
1176  new_cs->SendErrorQuit(this->client_id, errorno);
1177  }
1178  }
1179 
1180  NetworkAdminClientError(this->client_id, errorno);
1181 
1183 }
1184 
1186 {
1187  /* The client wants to leave. Display this and report it to the other
1188  * clients. */
1189  NetworkClientSocket *new_cs;
1190  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1191 
1192  /* The client was never joined.. thank the client for the packet, but ignore it */
1193  if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
1195  }
1196 
1197  this->GetClientName(client_name, lastof(client_name));
1198 
1199  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
1200 
1201  FOR_ALL_CLIENT_SOCKETS(new_cs) {
1202  if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
1203  new_cs->SendQuit(this->client_id);
1204  }
1205  }
1206 
1208 
1210 }
1211 
1213 {
1214  if (this->status < STATUS_AUTHORIZED) {
1215  /* Illegal call, return error and ignore the packet */
1216  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1217  }
1218 
1219  uint32 frame = p->Recv_uint32();
1220 
1221  /* The client is trying to catch up with the server */
1222  if (this->status == STATUS_PRE_ACTIVE) {
1223  /* The client is not yet catched up? */
1224  if (frame + DAY_TICKS < _frame_counter) return NETWORK_RECV_STATUS_OKAY;
1225 
1226  /* Now he is! Unpause the game */
1227  this->status = STATUS_ACTIVE;
1229 
1230  /* Execute script for, e.g. MOTD */
1231  IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
1232  }
1233 
1234  /* Get, and validate the token. */
1235  uint8 token = p->Recv_uint8();
1236  if (token == this->last_token) {
1237  /* We differentiate between last_token_frame and last_frame so the lag
1238  * test uses the actual lag of the client instead of the lag for getting
1239  * the token back and forth; after all, the token is only sent every
1240  * time we receive a PACKET_CLIENT_ACK, after which we will send a new
1241  * token to the client. If the lag would be one day, then we would not
1242  * be sending the new token soon enough for the new daily scheduled
1243  * PACKET_CLIENT_ACK. This would then register the lag of the client as
1244  * two days, even when it's only a single day. */
1246  /* Request a new token. */
1247  this->last_token = 0;
1248  }
1249 
1250  /* The client received the frame, make note of it */
1251  this->last_frame = frame;
1252  /* With those 2 values we can calculate the lag realtime */
1254  return NETWORK_RECV_STATUS_OKAY;
1255 }
1256 
1257 
1268 void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, ClientID from_id, int64 data, bool from_admin)
1269 {
1270  NetworkClientSocket *cs;
1271  const NetworkClientInfo *ci, *ci_own, *ci_to;
1272 
1273  switch (desttype) {
1274  case DESTTYPE_CLIENT:
1275  /* Are we sending to the server? */
1276  if ((ClientID)dest == CLIENT_ID_SERVER) {
1277  ci = NetworkClientInfo::GetByClientID(from_id);
1278  /* Display the text locally, and that is it */
1279  if (ci != NULL) {
1280  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1281 
1283  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1284  }
1285  }
1286  } else {
1287  /* Else find the client to send the message to */
1289  if (cs->client_id == (ClientID)dest) {
1290  cs->SendChat(action, from_id, false, msg, data);
1291  break;
1292  }
1293  }
1294  }
1295 
1296  /* Display the message locally (so you know you have sent it) */
1297  if (from_id != (ClientID)dest) {
1298  if (from_id == CLIENT_ID_SERVER) {
1299  ci = NetworkClientInfo::GetByClientID(from_id);
1301  if (ci != NULL && ci_to != NULL) {
1302  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), true, ci_to->client_name, msg, data);
1303  }
1304  } else {
1306  if (cs->client_id == from_id) {
1307  cs->SendChat(action, (ClientID)dest, true, msg, data);
1308  break;
1309  }
1310  }
1311  }
1312  }
1313  break;
1314  case DESTTYPE_TEAM: {
1315  /* If this is false, the message is already displayed on the client who sent it. */
1316  bool show_local = true;
1317  /* Find all clients that belong to this company */
1318  ci_to = NULL;
1320  ci = cs->GetInfo();
1321  if (ci != NULL && ci->client_playas == (CompanyID)dest) {
1322  cs->SendChat(action, from_id, false, msg, data);
1323  if (cs->client_id == from_id) show_local = false;
1324  ci_to = ci; // Remember a client that is in the company for company-name
1325  }
1326  }
1327 
1328  /* if the server can read it, let the admin network read it, too. */
1330  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1331  }
1332 
1333  ci = NetworkClientInfo::GetByClientID(from_id);
1335  if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
1336  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1337  if (from_id == CLIENT_ID_SERVER) show_local = false;
1338  ci_to = ci_own;
1339  }
1340 
1341  /* There is no such client */
1342  if (ci_to == NULL) break;
1343 
1344  /* Display the message locally (so you know you have sent it) */
1345  if (ci != NULL && show_local) {
1346  if (from_id == CLIENT_ID_SERVER) {
1347  char name[NETWORK_NAME_LENGTH];
1348  StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
1349  SetDParam(0, ci_to->client_playas);
1350  GetString(name, str, lastof(name));
1351  NetworkTextMessage(action, GetDrawStringCompanyColour(ci_own->client_playas), true, name, msg, data);
1352  } else {
1354  if (cs->client_id == from_id) {
1355  cs->SendChat(action, ci_to->client_id, true, msg, data);
1356  }
1357  }
1358  }
1359  }
1360  break;
1361  }
1362  default:
1363  DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
1364  FALLTHROUGH;
1365 
1366  case DESTTYPE_BROADCAST:
1368  cs->SendChat(action, from_id, false, msg, data);
1369  }
1370 
1371  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1372 
1373  ci = NetworkClientInfo::GetByClientID(from_id);
1374  if (ci != NULL) {
1375  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1376  }
1377  break;
1378  }
1379 }
1380 
1382 {
1383  if (this->status < STATUS_PRE_ACTIVE) {
1384  /* Illegal call, return error and ignore the packet */
1385  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1386  }
1387 
1388  NetworkAction action = (NetworkAction)p->Recv_uint8();
1389  DestType desttype = (DestType)p->Recv_uint8();
1390  int dest = p->Recv_uint32();
1391  char msg[NETWORK_CHAT_LENGTH];
1392 
1394  int64 data = p->Recv_uint64();
1395 
1396  NetworkClientInfo *ci = this->GetInfo();
1397  switch (action) {
1398  case NETWORK_ACTION_GIVE_MONEY:
1399  if (!Company::IsValidID(ci->client_playas)) break;
1400  FALLTHROUGH;
1401  case NETWORK_ACTION_CHAT:
1402  case NETWORK_ACTION_CHAT_CLIENT:
1403  case NETWORK_ACTION_CHAT_COMPANY:
1404  NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data);
1405  break;
1406  default:
1407  IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, this->GetClientIP());
1408  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1409  }
1410  return NETWORK_RECV_STATUS_OKAY;
1411 }
1412 
1414 {
1415  if (this->status != STATUS_ACTIVE) {
1416  /* Illegal call, return error and ignore the packet */
1417  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1418  }
1419 
1420  char password[NETWORK_PASSWORD_LENGTH];
1421  const NetworkClientInfo *ci;
1422 
1423  p->Recv_string(password, sizeof(password));
1424  ci = this->GetInfo();
1425 
1427  return NETWORK_RECV_STATUS_OKAY;
1428 }
1429 
1431 {
1432  if (this->status != STATUS_ACTIVE) {
1433  /* Illegal call, return error and ignore the packet */
1434  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1435  }
1436 
1437  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1438  NetworkClientInfo *ci;
1439 
1440  p->Recv_string(client_name, sizeof(client_name));
1441  ci = this->GetInfo();
1442 
1443  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
1444 
1445  if (ci != NULL) {
1446  /* Display change */
1447  if (NetworkFindName(client_name, lastof(client_name))) {
1448  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name);
1449  strecpy(ci->client_name, client_name, lastof(ci->client_name));
1451  }
1452  }
1453  return NETWORK_RECV_STATUS_OKAY;
1454 }
1455 
1457 {
1458  if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1459 
1460  char pass[NETWORK_PASSWORD_LENGTH];
1461  char command[NETWORK_RCONCOMMAND_LENGTH];
1462 
1464 
1465  p->Recv_string(pass, sizeof(pass));
1466  p->Recv_string(command, sizeof(command));
1467 
1468  if (strcmp(pass, _settings_client.network.rcon_password) != 0) {
1469  DEBUG(net, 0, "[rcon] wrong password from client-id %d", this->client_id);
1470  return NETWORK_RECV_STATUS_OKAY;
1471  }
1472 
1473  DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", this->client_id, command);
1474 
1476  IConsoleCmdExec(command);
1478  return NETWORK_RECV_STATUS_OKAY;
1479 }
1480 
1482 {
1483  if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1484 
1485  CompanyID company_id = (Owner)p->Recv_uint8();
1486 
1487  /* Check if the company is valid, we don't allow moving to AI companies */
1488  if (company_id != COMPANY_SPECTATOR && !Company::IsValidHumanID(company_id)) return NETWORK_RECV_STATUS_OKAY;
1489 
1490  /* Check if we require a password for this company */
1491  if (company_id != COMPANY_SPECTATOR && !StrEmpty(_network_company_states[company_id].password)) {
1492  /* we need a password from the client - should be in this packet */
1493  char password[NETWORK_PASSWORD_LENGTH];
1494  p->Recv_string(password, sizeof(password));
1495 
1496  /* Incorrect password sent, return! */
1497  if (strcmp(password, _network_company_states[company_id].password) != 0) {
1498  DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", this->client_id, company_id + 1);
1499  return NETWORK_RECV_STATUS_OKAY;
1500  }
1501  }
1502 
1503  /* if we get here we can move the client */
1504  NetworkServerDoMove(this->client_id, company_id);
1505  return NETWORK_RECV_STATUS_OKAY;
1506 }
1507 
1516 {
1517  /* Grab the company name */
1518  char company_name[NETWORK_COMPANY_NAME_LENGTH];
1519  SetDParam(0, c->index);
1520 
1521  assert(max_len <= lengthof(company_name));
1522  GetString(company_name, STR_COMPANY_NAME, company_name + max_len - 1);
1523 
1524  /* Get the income */
1525  Money income = 0;
1526  if (_cur_year - 1 == c->inaugurated_year) {
1527  /* The company is here just 1 year, so display [2], else display[1] */
1528  for (uint i = 0; i < lengthof(c->yearly_expenses[2]); i++) {
1529  income -= c->yearly_expenses[2][i];
1530  }
1531  } else {
1532  for (uint i = 0; i < lengthof(c->yearly_expenses[1]); i++) {
1533  income -= c->yearly_expenses[1][i];
1534  }
1535  }
1536 
1537  /* Send the information */
1538  p->Send_uint8 (c->index);
1539  p->Send_string(company_name);
1542  p->Send_uint64(c->money);
1543  p->Send_uint64(income);
1545 
1546  /* Send 1 if there is a password for the company else send 0 */
1548 
1549  for (uint i = 0; i < NETWORK_VEH_END; i++) {
1550  p->Send_uint16(stats->num_vehicle[i]);
1551  }
1552 
1553  for (uint i = 0; i < NETWORK_VEH_END; i++) {
1554  p->Send_uint16(stats->num_station[i]);
1555  }
1556 
1557  p->Send_bool(c->is_ai);
1558 }
1559 
1565 {
1566  const Vehicle *v;
1567  const Station *s;
1568 
1569  memset(stats, 0, sizeof(*stats) * MAX_COMPANIES);
1570 
1571  /* Go through all vehicles and count the type of vehicles */
1572  FOR_ALL_VEHICLES(v) {
1573  if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
1574  byte type = 0;
1575  switch (v->type) {
1576  case VEH_TRAIN: type = NETWORK_VEH_TRAIN; break;
1577  case VEH_ROAD: type = RoadVehicle::From(v)->IsBus() ? NETWORK_VEH_BUS : NETWORK_VEH_LORRY; break;
1578  case VEH_AIRCRAFT: type = NETWORK_VEH_PLANE; break;
1579  case VEH_SHIP: type = NETWORK_VEH_SHIP; break;
1580  default: continue;
1581  }
1582  stats[v->owner].num_vehicle[type]++;
1583  }
1584 
1585  /* Go through all stations and count the types of stations */
1586  FOR_ALL_STATIONS(s) {
1587  if (Company::IsValidID(s->owner)) {
1588  NetworkCompanyStats *npi = &stats[s->owner];
1589 
1590  if (s->facilities & FACIL_TRAIN) npi->num_station[NETWORK_VEH_TRAIN]++;
1591  if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[NETWORK_VEH_LORRY]++;
1592  if (s->facilities & FACIL_BUS_STOP) npi->num_station[NETWORK_VEH_BUS]++;
1593  if (s->facilities & FACIL_AIRPORT) npi->num_station[NETWORK_VEH_PLANE]++;
1594  if (s->facilities & FACIL_DOCK) npi->num_station[NETWORK_VEH_SHIP]++;
1595  }
1596  }
1597 }
1598 
1604 {
1605  NetworkClientSocket *cs;
1607 
1608  if (ci == NULL) return;
1609 
1610  DEBUG(desync, 1, "client: %08x; %02x; %02x; %04x", _date, _date_fract, (int)ci->client_playas, client_id);
1611 
1613  cs->SendClientInfo(ci);
1614  }
1615 
1617 }
1618 
1621 {
1623  DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
1624 
1626  }
1627 }
1628 
1636 {
1637  const NetworkClientInfo *ci;
1638  const Company *c;
1639  bool clients_in_company[MAX_COMPANIES];
1640  int vehicles_in_company[MAX_COMPANIES];
1641 
1643 
1644  memset(clients_in_company, 0, sizeof(clients_in_company));
1645 
1646  /* Detect the active companies */
1647  FOR_ALL_CLIENT_INFOS(ci) {
1648  if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
1649  }
1650 
1651  if (!_network_dedicated) {
1653  if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
1654  }
1655 
1657  memset(vehicles_in_company, 0, sizeof(vehicles_in_company));
1658 
1659  const Vehicle *v;
1660  FOR_ALL_VEHICLES(v) {
1661  if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
1662  vehicles_in_company[v->owner]++;
1663  }
1664  }
1665 
1666  /* Go through all the companies */
1667  FOR_ALL_COMPANIES(c) {
1668  /* Skip the non-active once */
1669  if (c->is_ai) continue;
1670 
1671  if (!clients_in_company[c->index]) {
1672  /* The company is empty for one month more */
1674 
1675  /* Is the company empty for autoclean_unprotected-months, and is there no protection? */
1677  /* Shut the company down */
1678  DoCommandP(0, 2 | c->index << 16, CRR_AUTOCLEAN, CMD_COMPANY_CTRL);
1679  IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no password", c->index + 1);
1680  }
1681  /* Is the company empty for autoclean_protected-months, and there is a protection? */
1683  /* Unprotect the company */
1684  _network_company_states[c->index].password[0] = '\0';
1685  IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", c->index + 1);
1688  }
1689  /* Is the company empty for autoclean_novehicles-months, and has no vehicles? */
1691  /* Shut the company down */
1692  DoCommandP(0, 2 | c->index << 16, CRR_AUTOCLEAN, CMD_COMPANY_CTRL);
1693  IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no vehicles", c->index + 1);
1694  }
1695  } else {
1696  /* It is not empty, reset the date */
1698  }
1699  }
1700 }
1701 
1708 bool NetworkFindName(char *new_name, const char *last)
1709 {
1710  bool found_name = false;
1711  uint number = 0;
1712  char original_name[NETWORK_CLIENT_NAME_LENGTH];
1713 
1714  strecpy(original_name, new_name, lastof(original_name));
1715 
1716  while (!found_name) {
1717  const NetworkClientInfo *ci;
1718 
1719  found_name = true;
1720  FOR_ALL_CLIENT_INFOS(ci) {
1721  if (strcmp(ci->client_name, new_name) == 0) {
1722  /* Name already in use */
1723  found_name = false;
1724  break;
1725  }
1726  }
1727  /* Check if it is the same as the server-name */
1729  if (ci != NULL) {
1730  if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
1731  }
1732 
1733  if (!found_name) {
1734  /* Try a new name (<name> #1, <name> #2, and so on) */
1735 
1736  /* Something's really wrong when there're more names than clients */
1737  if (number++ > MAX_CLIENTS) break;
1738  seprintf(new_name, last, "%s #%d", original_name, number);
1739  }
1740  }
1741 
1742  return found_name;
1743 }
1744 
1752 {
1753  NetworkClientInfo *ci;
1754  /* Check if the name's already in use */
1755  FOR_ALL_CLIENT_INFOS(ci) {
1756  if (strcmp(ci->client_name, new_name) == 0) return false;
1757  }
1758 
1759  ci = NetworkClientInfo::GetByClientID(client_id);
1760  if (ci == NULL) return false;
1761 
1762  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, true, ci->client_name, new_name);
1763 
1764  strecpy(ci->client_name, new_name, lastof(ci->client_name));
1765 
1766  NetworkUpdateClientInfo(client_id);
1767  return true;
1768 }
1769 
1776 void NetworkServerSetCompanyPassword(CompanyID company_id, const char *password, bool already_hashed)
1777 {
1778  if (!Company::IsValidHumanID(company_id)) return;
1779 
1780  if (!already_hashed) {
1782  }
1783 
1784  strecpy(_network_company_states[company_id].password, password, lastof(_network_company_states[company_id].password));
1785  NetworkServerUpdateCompanyPassworded(company_id, !StrEmpty(_network_company_states[company_id].password));
1786 }
1787 
1792 static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
1793 {
1794  CommandPacket *cp;
1795  while ((cp = cs->outgoing_queue.Pop()) != NULL) {
1796  cs->SendCommand(cp);
1797  free(cp);
1798  }
1799 }
1800 
1805 void NetworkServer_Tick(bool send_frame)
1806 {
1807  NetworkClientSocket *cs;
1808 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1809  bool send_sync = false;
1810 #endif
1811 
1812 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1815  send_sync = true;
1816  }
1817 #endif
1818 
1819  /* Now we are done with the frame, inform the clients that they can
1820  * do their frame! */
1822  /* We allow a number of bytes per frame, but only to the burst amount
1823  * to be available for packet receiving at any particular time. */
1824  cs->receive_limit = min(cs->receive_limit + _settings_client.network.bytes_per_frame,
1826 
1827  /* Check if the speed of the client is what we can expect from a client */
1828  uint lag = NetworkCalculateLag(cs);
1829  switch (cs->status) {
1830  case NetworkClientSocket::STATUS_ACTIVE:
1832  /* Client did still not report in within the specified limit. */
1833  IConsolePrintF(CC_ERROR, cs->last_packet + lag * MILLISECONDS_PER_TICK > _realtime_tick ?
1834  /* A packet was received in the last three game days, so the client is likely lagging behind. */
1835  "Client #%d is dropped because the client's game state is more than %d ticks behind" :
1836  /* No packet was received in the last three game days; sounds like a lost connection. */
1837  "Client #%d is dropped because the client did not respond for more than %d ticks",
1838  cs->client_id, lag);
1839  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1840  continue;
1841  }
1842 
1843  /* Report once per time we detect the lag, and only when we
1844  * received a packet in the last 2000 milliseconds. If we
1845  * did not receive a packet, then the client is not just
1846  * slow, but the connection is likely severed. Mentioning
1847  * frame_freq is not useful in this case. */
1848  if (lag > (uint)DAY_TICKS && cs->lag_test == 0 && cs->last_packet + 2000 > _realtime_tick) {
1849  IConsolePrintF(CC_WARNING, "[%d] Client #%d is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id);
1850  cs->lag_test = 1;
1851  }
1852 
1853  if (cs->last_frame_server - cs->last_token_frame >= _settings_client.network.max_lag_time) {
1854  /* This is a bad client! It didn't send the right token back within time. */
1855  IConsolePrintF(CC_ERROR, "Client #%d is dropped because it fails to send valid acks", cs->client_id);
1856  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1857  continue;
1858  }
1859  break;
1860 
1861  case NetworkClientSocket::STATUS_INACTIVE:
1862  case NetworkClientSocket::STATUS_NEWGRFS_CHECK:
1863  case NetworkClientSocket::STATUS_AUTHORIZED:
1864  /* NewGRF check and authorized states should be handled almost instantly.
1865  * So give them some lee-way, likewise for the query with inactive. */
1867  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);
1868  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1869  continue;
1870  }
1871  break;
1872 
1873  case NetworkClientSocket::STATUS_MAP:
1874  /* Downloading the map... this is the amount of time since starting the saving. */
1876  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);
1877  cs->SendError(NETWORK_ERROR_TIMEOUT_MAP);
1878  continue;
1879  }
1880  break;
1881 
1882  case NetworkClientSocket::STATUS_DONE_MAP:
1883  case NetworkClientSocket::STATUS_PRE_ACTIVE:
1884  /* The map has been sent, so this is for loading the map and syncing up. */
1886  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);
1887  cs->SendError(NETWORK_ERROR_TIMEOUT_JOIN);
1888  continue;
1889  }
1890  break;
1891 
1892  case NetworkClientSocket::STATUS_AUTH_GAME:
1893  case NetworkClientSocket::STATUS_AUTH_COMPANY:
1894  /* These don't block? */
1896  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);
1897  cs->SendError(NETWORK_ERROR_TIMEOUT_PASSWORD);
1898  continue;
1899  }
1900  break;
1901 
1902  case NetworkClientSocket::STATUS_MAP_WAIT:
1903  /* This is an internal state where we do not wait
1904  * on the client to move to a different state. */
1905  break;
1906 
1907  case NetworkClientSocket::STATUS_END:
1908  /* Bad server/code. */
1909  NOT_REACHED();
1910  }
1911 
1912  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) {
1913  /* Check if we can send command, and if we have anything in the queue */
1915 
1916  /* Send an updated _frame_counter_max to the client */
1917  if (send_frame) cs->SendFrame();
1918 
1919 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1920  /* Send a sync-check packet */
1921  if (send_sync) cs->SendSync();
1922 #endif
1923  }
1924  }
1925 
1926  /* See if we need to advertise */
1928 }
1929 
1932 {
1935 }
1936 
1939 {
1943 }
1944 
1947 {
1950 }
1951 
1957 {
1958  return this->client_address.GetHostname();
1959 }
1960 
1963 {
1964  static const char * const stat_str[] = {
1965  "inactive",
1966  "checking NewGRFs",
1967  "authorizing (server password)",
1968  "authorizing (company password)",
1969  "authorized",
1970  "waiting",
1971  "loading map",
1972  "map done",
1973  "ready",
1974  "active"
1975  };
1976  assert_compile(lengthof(stat_str) == NetworkClientSocket::STATUS_END);
1977 
1978  NetworkClientSocket *cs;
1980  NetworkClientInfo *ci = cs->GetInfo();
1981  if (ci == NULL) continue;
1982  uint lag = NetworkCalculateLag(cs);
1983  const char *status;
1984 
1985  status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
1986  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s",
1987  cs->client_id, ci->client_name, status, lag,
1988  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
1989  cs->GetClientIP());
1990  }
1991 }
1992 
1997 {
1998  NetworkClientSocket *cs;
1999 
2001  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendConfigUpdate();
2002  }
2003 }
2004 
2010 void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded)
2011 {
2012  if (NetworkCompanyIsPassworded(company_id) == passworded) return;
2013 
2014  SB(_network_company_passworded, company_id, 1, !!passworded);
2016 
2017  NetworkClientSocket *cs;
2019  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendCompanyUpdate();
2020  }
2021 
2023 }
2024 
2032 {
2033  /* Only allow non-dedicated servers and normal clients to be moved */
2034  if (client_id == CLIENT_ID_SERVER && _network_dedicated) return;
2035 
2037 
2038  /* No need to waste network resources if the client is in the company already! */
2039  if (ci->client_playas == company_id) return;
2040 
2041  ci->client_playas = company_id;
2042 
2043  if (client_id == CLIENT_ID_SERVER) {
2044  SetLocalCompany(company_id);
2045  } else {
2046  NetworkClientSocket *cs = NetworkClientSocket::GetByClientID(client_id);
2047  /* When the company isn't authorized we can't move them yet. */
2048  if (cs->status < NetworkClientSocket::STATUS_AUTHORIZED) return;
2049  cs->SendMove(client_id, company_id);
2050  }
2051 
2052  /* announce the client's move */
2053  NetworkUpdateClientInfo(client_id);
2054 
2055  NetworkAction action = (company_id == COMPANY_SPECTATOR) ? NETWORK_ACTION_COMPANY_SPECTATOR : NETWORK_ACTION_COMPANY_JOIN;
2056  NetworkServerSendChat(action, DESTTYPE_BROADCAST, 0, "", client_id, company_id + 1);
2057 }
2058 
2065 void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string)
2066 {
2067  NetworkClientSocket::GetByClientID(client_id)->SendRConResult(colour_code, string);
2068 }
2069 
2075 {
2076  if (client_id == CLIENT_ID_SERVER) return;
2077  NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED);
2078 }
2079 
2086 {
2087  return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban);
2088 }
2089 
2095 uint NetworkServerKickOrBanIP(const char *ip, bool ban)
2096 {
2097  /* Add address to ban-list */
2098  if (ban) {
2099  bool contains = false;
2100  for (char **iter = _network_ban_list.Begin(); iter != _network_ban_list.End(); iter++) {
2101  if (strcmp(*iter, ip) == 0) {
2102  contains = true;
2103  break;
2104  }
2105  }
2106  if (!contains) *_network_ban_list.Append() = stredup(ip);
2107  }
2108 
2109  uint n = 0;
2110 
2111  /* There can be multiple clients with the same IP, kick them all */
2112  NetworkClientSocket *cs;
2114  if (cs->client_id == CLIENT_ID_SERVER) continue;
2115  if (cs->client_address.IsInNetmask(const_cast<char *>(ip))) {
2116  NetworkServerKickClient(cs->client_id);
2117  n++;
2118  }
2119  }
2120 
2121  return n;
2122 }
2123 
2130 {
2131  const NetworkClientInfo *ci;
2132  FOR_ALL_CLIENT_INFOS(ci) {
2133  if (ci->client_playas == company) return true;
2134  }
2135  return false;
2136 }
2137 
2138 
2144 void ServerNetworkGameSocketHandler::GetClientName(char *client_name, const char *last) const
2145 {
2146  const NetworkClientInfo *ci = this->GetInfo();
2147 
2148  if (ci == NULL || StrEmpty(ci->client_name)) {
2149  seprintf(client_name, last, "Client #%4d", this->client_id);
2150  } else {
2151  strecpy(client_name, ci->client_name, last);
2152  }
2153 }
2154 
2159 {
2160  NetworkClientInfo *ci;
2161  FOR_ALL_CLIENT_INFOS(ci) {
2162  if (_network_server) {
2163  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d IP: %s",
2164  ci->client_id,
2165  ci->client_name,
2166  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
2167  ci->client_id == CLIENT_ID_SERVER ? "server" : NetworkClientSocket::GetByClientID(ci->client_id)->GetClientIP());
2168  } else {
2169  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d",
2170  ci->client_id,
2171  ci->client_name,
2172  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0));
2173  }
2174  }
2175 }
2176 
2183 {
2184  assert(c != NULL);
2185 
2186  if (!_network_server) return;
2187 
2189  _network_company_states[c->index].password[0] = '\0';
2191 
2192  if (ci != NULL) {
2193  /* ci is NULL when replaying, or for AIs. In neither case there is a client. */
2194  ci->client_playas = c->index;
2196  NetworkSendCommand(0, 0, 0, CMD_RENAME_PRESIDENT, NULL, ci->client_name, c->index);
2197  }
2198 
2199  /* Announce new company on network. */
2200  NetworkAdminCompanyInfo(c, true);
2201 
2202  if (ci != NULL) {
2203  /* ci is NULL when replaying, or for AIs. In neither case there is a client.
2204  We need to send Admin port update here so that they first know about the new company
2205  and then learn about a possibly joining client (see FS#6025) */
2206  NetworkServerSendChat(NETWORK_ACTION_COMPANY_NEW, DESTTYPE_BROADCAST, 0, "", ci->client_id, c->index + 1);
2207  }
2208 }
2209 
2210 #endif /* ENABLE_NETWORK */
Everything is okay.
Definition: core.h:27
Packet * packets
Packet queue of the savegame; send these "slowly" to the client.
static const uint NETWORK_CLIENT_NAME_LENGTH
The maximum length of a client&#39;s name, in bytes including &#39;\0&#39;.
Definition: config.h:49
NetworkRecvStatus SendMap()
This sends the map to the client.
static const uint NETWORK_CLIENTS_LENGTH
The maximum length for the list of clients that controls a company, in bytes including &#39;\0&#39;...
Definition: config.h:48
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:83
void Write(byte *buf, size_t size)
Write a given number of bytes into the savegame.
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.
virtual NetworkRecvStatus Receive_CLIENT_ACK(Packet *p)
Tell the server we are done with this frame: uint32 Current frame counter of the client.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:77
used in multiplayer to create a new companies etc.
Definition: command_type.h:279
The client is catching up the delayed frames.
static bool AllowConnection()
Whether an connection is allowed or not at this moment.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:257
void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, ClientID from_id, int64 data, bool from_admin)
Send an actual chat message.
Information about a single company.
Definition: tcp_game.h:46
Server tells everyone that someone is moved to another company.
Definition: tcp_game.h:108
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:1107
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition: core.h:71
Container for all information known about a client.
Definition: network_base.h:27
The client has downloaded the map.
SOCKET sock
The socket currently connected to.
Definition: tcp.h:36
NetworkRecvStatus SendJoin(ClientID client_id)
Tell that a client joined.
uint32 _sync_seed_1
Seed to compare during sync checks.
Definition: network.cpp:75
uint32 _realtime_tick
The real time in the game.
Definition: debug.cpp:48
Internal entity of a packet.
Definition: packet.h:44
ServerNetworkGameSocketHandler * cs
Socket we are associated with.
The connection got closed.
Definition: tcp.h:24
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3120
GRFConfig * _grfconfig
First item in list of current GRF set up.
TextColour GetDrawStringCompanyColour(CompanyID company)
Get the colour for DrawString-subroutines which matches the colour of the company.
static char * strecat(char *dst, const char *src, const char *last)
Appends characters from one string to another.
Definition: depend.cpp:99
virtual NetworkRecvStatus Receive_CLIENT_RCON(Packet *p)
Send an RCon command to the server: string RCon password.
uint32 Recv_uint32()
Read a 32 bits integer from the packet.
Definition: packet.cpp:250
virtual NetworkRecvStatus Receive_CLIENT_GETMAP(Packet *p)
Request the map from the server.
NetworkRecvStatus SendError(NetworkErrorCode error)
Send an error to the client, and close its connection.
Client list; Window numbers:
Definition: window_type.h:474
void NetworkServerMonthlyLoop()
Monthly "callback".
uint16 max_init_time
maximum amount of time, in game ticks, a client may take to initiate joining
byte last_token
The last random token we did send to verify the client is listening.
set p2 with the ClientID of the sending client.
Definition: command_type.h:392
A server tells that a client has hit an error and did quit.
Definition: tcp_game.h:124
int32 performance_history
Company score (scale 0-1000)
Definition: company_base.h:27
ServerNetworkGameSocketHandler(SOCKET s)
Create a new socket for the server side of the game connection.
void StartNewGameWithoutGUI(uint seed)
Start a normal game without the GUI.
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:398
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:152
Year inaugurated_year
Year of starting the company.
Definition: company_base.h:79
The server is full and has no place for you.
Definition: tcp_game.h:37
static ClientID _network_client_id
The identifier counter for new clients (is never decreased)
NetworkRecvStatus CloseConnection(NetworkRecvStatus status)
Close the network connection due to the given status.
NetworkErrorCode
The error codes we send around in the protocols.
Definition: network_type.h:104
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:28
void NORETURN SlError(StringID string, const char *extra_msg)
Error handler.
Definition: saveload.cpp:533
void NetworkPopulateCompanyStats(NetworkCompanyStats *stats)
Populate the company stats.
The client is downloading the map.
Popup for the client list; Window numbers:
Definition: window_type.h:480
uint8 autoclean_novehicles
remove companies with no vehicles after this many months
ClientStatus status
Status of this client.
void Send_uint8(uint8 data)
Package a 8 bits integer in the packet.
Definition: packet.cpp:100
Cross-platform Mutex.
Definition: thread.h:56
NetworkRecvStatus SendClientInfo(NetworkClientInfo *ci)
Send the client information about a client.
uint32 p2
parameter p2.
Definition: command_type.h:475
NetworkRecvStatus SendWait()
Tell the client that its put in a waiting queue.
Template for TCP listeners.
Definition: tcp_listen.h:32
The client is authorizing with company password.
Vehicle data structure.
Definition: vehicle_base.h:212
static const uint MAX_CLIENTS
How many clients can we have.
Definition: network_type.h:20
Sending and receiving UDP messages.
virtual NetworkRecvStatus Receive_CLIENT_QUIT(Packet *p)
The client is quitting the game.
GRF file is used statically (can be used in any MP game)
Definition: newgrf_config.h:26
The client is active within in the game.
NetworkRecvStatus SendChat(NetworkAction action, ClientID client_id, bool self_send, const char *msg, int64 data)
Send a chat message.
const T * Begin() const
Get the pointer to the first item (const)
ClientID _redirect_console_to_client
If not invalid, redirect the console output to a client.
Definition: network.cpp:64
static const uint GENERATE_NEW_SEED
Create a new random seed.
Definition: genworld.h:25
SaveOrLoadResult SaveWithFilter(SaveFilter *writer, bool threaded)
Save the game using a (writer) filter.
Definition: saveload.cpp:2615
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
virtual NetworkRecvStatus Receive_CLIENT_CHAT(Packet *p)
Sends a chat-packet to the server: uint8 ID of the action (see NetworkAction).
static const int DAY_TICKS
1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885.
Definition: date_type.h:30
virtual NetworkRecvStatus Receive_CLIENT_COMPANY_PASSWORD(Packet *p)
Send a password to the server to authorize uint8 Password type (see NetworkPasswordType).
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:85
void Send_uint32(uint32 data)
Package a 32 bits integer in the packet.
Definition: packet.cpp:121
Server distributing the message of a client (or itself).
Definition: tcp_game.h:100
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:50
The client is spectating.
Definition: company_type.h:37
The client wants a new company.
Definition: company_type.h:36
static const TextColour CC_DEFAULT
Default colour of the console.
Definition: console_type.h:25
bool NetworkCompanyIsPassworded(CompanyID company_id)
Check if the company we want to join requires a password.
Definition: network.cpp:225
void NetworkPrintClients()
Print all the clients to the console.
Base core network types and some helper functions to access them.
uint16 bytes_per_frame_burst
how many bytes may, over a short period, be received?
bool HasPackets()
Checks whether there are packets.
void Append(CommandPacket *p)
Append a CommandPacket at the end of the queue.
Server tells the client what frame it is in, and thus to where the client may progress.
Definition: tcp_game.h:90
NetworkRecvStatus SendRConResult(uint16 colour, const char *command)
Send the result of a console action.
GRFIdentifier ident
grfid and md5sum to uniquely identify newgrfs
The admin gets information about this on a daily basis.
Definition: tcp_admin.h:95
CommandFlags GetCommandFlags(uint32 cmd)
Definition: command.cpp:379
The server told us we made an error.
Definition: core.h:33
virtual void EndCritical(bool allow_recursive=false)=0
End of the critical section.
Year _cur_year
Current year, starting at 0.
Definition: date.cpp:26
NetworkRecvStatus SendNewGRFCheck()
Send the check for the NewGRFs.
virtual Packet * ReceivePacket()
Receives a packet for the given client.
Definition: tcp.cpp:149
static RoadVehicle * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
virtual NetworkRecvStatus Receive_CLIENT_NEWGRFS_CHECKED(Packet *p)
Tell the server that we have the required GRFs.
const T * End() const
Get the pointer behind the last valid item (const)
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
Definition: tcp.cpp:99
Server tells the client what the random state should be.
Definition: tcp_game.h:92
Class for handling the server side of the game connection.
struct GRFConfig * next
NOSAVE: Next item in the linked list.
virtual NetworkRecvStatus Receive_CLIENT_GAME_PASSWORD(Packet *p)
Send a password to the server to authorize: uint8 Password type (see NetworkPasswordType).
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:310
Server welcomes you and gives you your ClientID.
Definition: tcp_game.h:69
Servers always have this ID.
Definition: network_type.h:45
virtual void SendSignal()=0
Send a signal and wake the &#39;thread&#39; that was waiting for it.
static bool IsValidHumanID(size_t index)
Is this company a valid company, not controlled by a NoAI program?
Definition: company_base.h:144
The admin gets information about this on a monthly basis.
Definition: tcp_admin.h:97
T * Append(uint to_add=1)
Append an item and return it.
bool _network_dedicated
are we a dedicated server?
Definition: network.cpp:59
Server tells the client that it is beginning to send the map.
Definition: tcp_game.h:75
CommandQueue incoming_queue
The command-queue awaiting handling.
Definition: tcp_game.h:524
assert_compile(MAX_CLIENT_SLOTS > MAX_CLIENTS)
Make very sure the preconditions given in network_type.h are actually followed.
CompanyByte _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
uint16 months_empty
How many months the company is empty.
Definition: network_type.h:70
bool autoclean_companies
automatically remove companies that are not in use
void ProcessAsyncSaveFinish()
Handle async save finishes.
Definition: saveload.cpp:586
Response of the executed command on the server.
Definition: tcp_game.h:104
uint16 num_vehicle[NETWORK_VEH_END]
How many vehicles are there of this type?
Definition: network_type.h:62
The first client ID.
Definition: network_type.h:46
static const size_t MAX_SIZE
Make template parameter accessible from outside.
Definition: pool_type.hpp:87
virtual NetworkRecvStatus Receive_CLIENT_JOIN(Packet *p)
Try to join the server: string OpenTTD revision (norev000 if no revision).
A server tells that a client has quit.
Definition: tcp_game.h:122
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:96
The company is removed due to autoclean.
Definition: company_type.h:61
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:69
Aircraft vehicle type.
Definition: vehicle_type.h:27
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:59
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 #<no> is used.
NetworkSettings network
settings related to the network
CompanyID client_playas
As which company is this client playing (CompanyID)
Definition: network_base.h:31
virtual bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Definition: vehicle_base.h:434
virtual NetworkRecvStatus Receive_CLIENT_SET_NAME(Packet *p)
Gives the client a new name: string New name of the client.
void NetworkUpdateClientInfo(ClientID client_id)
Send updated client info of a particular client.
static const uint NETWORK_RCONCOMMAND_LENGTH
The maximum length of a rconsole command, in bytes including &#39;\0&#39;.
Definition: config.h:50
uint32 last_frame
Last frame we have executed.
Definition: tcp_game.h:522
void Send_uint64(uint64 data)
Package a 64 bits integer in the packet.
Definition: packet.cpp:134
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:70
DateFract _date_fract
Fractional part of the day.
Definition: date.cpp:29
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
Definition: packet.h:56
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
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:29
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:110
uint32 p1
parameter p1.
Definition: command_type.h:474
Server sends bits of the map to the client.
Definition: tcp_game.h:77
void Finish()
Prepare everything to finish writing the savegame.
void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code)
Notify the admin network of a client error (if they have opt in for the respective update)...
void IConsoleCmdExec(const char *cmdstr)
Execute a given command passed to us.
Definition: console.cpp:409
Station with truck stops.
Definition: station_type.h:56
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:76
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:132
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:98
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:90
void SetLocalCompany(CompanyID new_company)
Sets the local company and updates the settings that are set on a per-company basis to reflect the co...
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition: gfx_type.h:247
static void NetworkCheckRestartMap()
Check if we want to restart the map.
NetworkRecvStatus SendNeedGamePassword()
Request the game password.
NetworkCompanyState * _network_company_states
Statistics about some companies.
Definition: network.cpp:62
The client is authorizing with game (server) password.
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
Definition: gfx_type.h:306
static ThreadMutex * New()
Create a new mutex.
Definition: thread_none.cpp:32
uint8 flags
NOSAVE: GCF_Flags, bitset.
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:126
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
Definition: core.h:26
Writing a savegame directly to a number of packets.
#define FOR_ALL_CLIENT_INFOS(var)
Iterate over all the clients.
Definition: network_base.h:55
const char * GetHostname()
Get the hostname; in case it wasn&#39;t given the IPv4 dotted representation is given.
Definition: address.cpp:26
All packets in the queue are sent.
Definition: tcp.h:27
byte clients_on
Current count of clients on server.
Definition: game.h:30
static const uint NETWORK_CHAT_LENGTH
The maximum length of a chat message, in bytes including &#39;\0&#39;.
Definition: config.h:52
bool is_ai
If true, the company is (also) controlled by the computer (a NoAI program).
Definition: company_base.h:94
Money money
Money owned by the company.
Definition: company_base.h:64
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:52
StationFacilityByte facilities
The facilities that this station has.
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:527
CompanyID company
company that is executing the command
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
NetworkServerGameInfo _network_game_info
Information about our game.
Definition: network.cpp:61
The buffer is still full, so no (parts of) packets could be sent.
Definition: tcp.h:25
uint last_packet
Time we received the last frame.
Definition: tcp_game.h:525
Road vehicle type.
Definition: vehicle_type.h:25
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
char rcon_password[NETWORK_PASSWORD_LENGTH]
password for rconsole (server side)
NetworkClientInfo * GetInfo() const
Gets the client info of this socket handler.
Definition: tcp_game.h:550
#define FOR_ALL_CLIENT_SOCKETS(var)
Iterate over all the sockets.
Station with a dock.
Definition: station_type.h:59
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:385
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
Server sending an error message to the client.
Definition: tcp_game.h:42
NetworkRecvStatus SendFrame()
Tell the client that they may run to a particular frame.
Maximum number of companies.
Definition: company_type.h:25
uint Count() const
Get the number of items in the queue.
Definition: tcp_game.h:148
virtual NetworkRecvStatus Receive_CLIENT_COMMAND(Packet *p)
The client has done a command and wants us to handle it.
NetworkRecvStatus SendNewGame()
Tell the client we&#39;re starting a new game.
Packet * next
The next packet.
Definition: packet.h:46
Date join_date
Gamedate the client has joined.
Definition: network_base.h:32
Packet * PopPacket()
Pop a single created packet from the queue with packets.
Base class for all pools.
Definition: pool_type.hpp:83
uint8 max_companies
maximum amount of companies
uint16 sync_freq
how often do we check whether we are still in-sync
NetworkRecvStatus SendQuit(ClientID client_id)
Tell the client another client quit.
Ship vehicle type.
Definition: vehicle_type.h:26
The connection is &#39;just&#39; lost.
Definition: core.h:31
the command may be initiated by a spectator
Definition: command_type.h:386
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:39
uint8 autoclean_unprotected
remove passwordless companies after this many months
ClientID client_id
Client identifier.
Definition: tcp_game.h:521
virtual NetworkRecvStatus Receive_CLIENT_ERROR(Packet *p)
The client made an error and is quitting the game.
Month _cur_month
Current month (0..11)
Definition: date.cpp:27
OwnerByte owner
The owner of this station.
NetworkRecvStatus SendSync()
Request the client to sync.
uint32 last_frame_server
Last frame the server has executed.
Definition: tcp_game.h:523
#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:1137
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
byte _network_clients_connected
The amount of clients connected.
Definition: network.cpp:95
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:80
uint8 Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:221
Tells clients that a new client has joined.
Definition: tcp_game.h:81
uint32 generation_seed
noise seed for world generation
Some network configuration important to the client changed.
Definition: tcp_game.h:114
The admin gets information about this on a yearly basis.
Definition: tcp_admin.h:99
NetworkRecvStatus SendCompanyInfo()
Send the client information about the companies.
void SetInfo(NetworkClientInfo *info)
Sets the client info for this socket handler.
Definition: tcp_game.h:540
uint32 _frame_counter
The current frame.
Definition: network.cpp:72
uint64 Recv_uint64()
Read a 64 bits integer from the packet.
Definition: packet.cpp:267
void Destroy()
Begin the destruction of this packet writer.
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:59
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:276
NetworkRecvStatus SendConfigUpdate()
Send an update about the max company/spectator counts.
char network_id[NETWORK_SERVER_ID_LENGTH]
network ID for servers
const char * GetClientIP()
Get the IP address/hostname of the connected client.
The admin gets information about this on a weekly basis.
Definition: tcp_admin.h:96
CompanyMask _network_company_passworded
Bitmask of the password status of all companies.
Definition: network.cpp:84
The server is preparing to start a new game.
Definition: tcp_game.h:117
void NetworkServerDailyLoop()
Daily "callback".
uint8 max_clients
maximum amount of clients
Client is not part of anything.
Definition: network_type.h:44
ClientID
&#39;Unique&#39; identifier to be given to clients
Definition: network_type.h:43
static const uint NETWORK_COMPANY_NAME_LENGTH
The maximum length of the company name, in bytes including &#39;\0&#39;.
Definition: config.h:43
PacketWriter(ServerNetworkGameSocketHandler *cs)
Create the packet writer.
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
Definition: openttd.cpp:110
OwnerByte owner
Which company owns the vehicle?
Definition: vehicle_base.h:273
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:78
Server tells the client what the (compressed) size of the map is.
Definition: tcp_game.h:76
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:63
CompanyEconomyEntry old_economy[MAX_HISTORY_QUARTERS]
Economic data of the company of the last MAX_HISTORY_QUARTERS quarters.
Definition: company_base.h:98
Server tells the client there are some people waiting for the map as well.
Definition: tcp_game.h:74
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: depend.cpp:68
void NetworkServerYearlyLoop()
Yearly "callback".
void AppendQueue()
Append the current packet to the queue.
virtual NetworkRecvStatus Receive_CLIENT_COMPANY_INFO(Packet *p)
Request company information (in detail).
void NetworkAdminCompanyInfo(const Company *company, bool new_company)
Notify the admin network of company details.
void NetworkServerSendConfigUpdate()
Send Config Update.
StringList _network_ban_list
The banned clients.
Definition: network.cpp:69
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:194
Station with train station.
Definition: station_type.h:55
const char * ReceiveCommand(Packet *p, CommandPacket *cp)
Receives a command from the network.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:216
NetworkClientSocketPool _networkclientsocket_pool("NetworkClientSocket")
The pool with clients.
bool NetworkFindName(char *new_name, const char *last)
Check whether a name is unique, and otherwise try to make it unique.
The packets are partly sent; there are more packets to be sent in the queue.
Definition: tcp.h:26
NetworkRecvStatus SendShutdown()
Tell the client we&#39;re shutting down.
static const uint16 SEND_MTU
Number of bytes we can pack in a single packet.
Definition: config.h:35
void NetworkServerKickClient(ClientID client_id)
Kick a single client.
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban)
Ban, or kick, everyone joined from the given client&#39;s IP.
bool _network_server
network-server is active
Definition: network.cpp:57
virtual void WaitForSignal()=0
Wait for a signal to be send.
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-NULL) Titem.
Definition: pool_type.hpp:235
~PacketWriter()
Make sure everything is cleaned up.
static const TextColour CC_ERROR
Colour for error lines.
Definition: console_type.h:26
uint32 _last_sync_frame
Used in the server to store the last time a sync packet was sent to clients.
Definition: network.cpp:73
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:27
Station with bus stops.
Definition: station_type.h:57
Server requests the (hashed) game password.
Definition: tcp_game.h:63
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 #Expenses category.
Definition: company_base.h:96
We apparently send a malformed packet.
Definition: core.h:32
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:114
Server requests the (hashed) company password.
Definition: tcp_game.h:65
static const uint NETWORK_NAME_LENGTH
The maximum length of the server name and map name, in bytes including &#39;\0&#39;.
Definition: config.h:42
virtual void SendPacket(Packet *packet)
This function puts the packet in the send-queue and it is send as soon as possible.
Definition: tcp.cpp:65
Simple calculated statistics of a company.
Definition: network_type.h:61
uint16 max_download_time
maximum amount of time, in game ticks, a client may take to download the map
static const uint NETWORK_PASSWORD_LENGTH
The maximum length of the password, in bytes including &#39;\0&#39; (must be >= NETWORK_SERVER_ID_LENGTH) ...
Definition: config.h:47
void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
Notify the admin network of a client update (if they did opt in for the respective update)...
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
completed successfully
Definition: saveload.h:20
#define FOR_ALL_VEHICLES(var)
Iterate over all vehicles.
Definition: vehicle_base.h:986
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:38
ThreadMutex * mutex
Mutex for making threaded saving safe.
uint8 autoclean_protected
remove the password from passworded companies after this many months
virtual void BeginCritical(bool allow_recursive=false)=0
Begin the critical section.
Base socket handler for all TCP sockets.
Definition: tcp_game.h:152
Owner
Enum for all companies/owners.
Definition: company_type.h:20
void Send_bool(bool data)
Package a boolean in the packet.
Definition: packet.cpp:91
uint16 max_join_time
maximum amount of time, in game ticks, a client may take to sync up during joining ...
Money company_value
The value of the company.
Definition: company_base.h:28
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it&#39;s client-identifier.
Definition: network.cpp:126
static const byte NETWORK_COMPANY_INFO_VERSION
What version of company info is this?
Definition: config.h:39
Interface for filtering a savegame till it is written.
char server_password[NETWORK_PASSWORD_LENGTH]
password for joining this server
void SendCommand(Packet *p, const CommandPacket *cp)
Sends a command over the network.
#define DECLARE_POSTFIX_INCREMENT(type)
Some enums need to have allowed incrementing (i.e.
Definition: enum_type.hpp:16
static const uint NETWORK_REVISION_LENGTH
The maximum length of the revision, in bytes including &#39;\0&#39;.
Definition: config.h:46
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3148
bool my_cmd
did the command originate from "me"
~ServerNetworkGameSocketHandler()
Clear everything related to this client.
void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
Handle the tid-bits of moving a client from one company to another.
Date _date
Current date in days (day counter)
Definition: date.cpp:28
The server is shutting down.
Definition: tcp_game.h:118
Company view; Window numbers:
Definition: window_type.h:364
uint16 PacketSize
Size of the whole packet.
Definition: packet.h:23
void NetworkServerShowStatusToConsole()
Show the status message of all clients on the console.
static const TextColour CC_WARNING
Colour for warning lines.
Definition: console_type.h:27
void SendGRFIdentifier(Packet *p, const GRFIdentifier *grf)
Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet.
Definition: core.cpp:108
Send message/notice to everyone playing the same company (Team)
Definition: network_type.h:84
VehicleTypeByte type
Type of vehicle.
Definition: vehicle_type.h:54
uint32 _frame_counter_max
To where we may go with our clients.
Definition: network.cpp:71
static void Send()
Send the packets for the server sockets.
Station data structure.
Definition: station_base.h:446
uint32 cmd
command being executed.
Definition: command_type.h:476
DestType
Destination of our chat messages.
Definition: network_type.h:82
byte client_lang
The language of the client.
Definition: network_base.h:30
Station with an airport.
Definition: station_type.h:58
virtual NetworkRecvStatus Receive_CLIENT_MOVE(Packet *p)
Request the server to move this client into another company: uint8 ID of the company the client wants...
NetworkAction
Actions that can be used for NetworkTextMessage.
Definition: network_type.h:89
Information (password) of a company changed.
Definition: tcp_game.h:113
static const TextColour CC_INFO
Colour for information lines.
Definition: console_type.h:28
Year restart_game_year
year the server restarts
virtual Packet * ReceivePacket()
Receives a packet for the given client.
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:290
Server part of the admin network protocol.
virtual NetworkRecvStatus Receive_CLIENT_MAP_OK(Packet *p)
Tell the server that we are done receiving/loading the map.
Packet * current
The packet we&#39;re currently writing to.
virtual NetworkRecvStatus Receive_CLIENT_SET_PASSWORD(Packet *p)
Set the password for the clients current company: string The password.
Train vehicle type.
Definition: vehicle_type.h:24
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:201