OpenTTD
network_server.cpp
Go to the documentation of this file.
1 /* $Id: network_server.cpp 26975 2014-10-07 17:32:29Z rubidium $ */
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 
46 assert_compile(MAX_CLIENT_SLOTS > MAX_CLIENTS);
48 assert_compile(NetworkClientSocketPool::MAX_SIZE == MAX_CLIENT_SLOTS);
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 
141  Packet *PopPacket()
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. */
321  assert_compile(NetworkClientSocketPool::MAX_SIZE == MAX_CLIENTS + 1);
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 
751 NetworkRecvStatus ServerNetworkGameSocketHandler::SendChat(NetworkAction action, ClientID client_id, bool self_send, const char *msg, int64 data)
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  /* FALL THROUGH */
1365  case DESTTYPE_BROADCAST:
1367  cs->SendChat(action, from_id, false, msg, data);
1368  }
1369 
1370  NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
1371 
1372  ci = NetworkClientInfo::GetByClientID(from_id);
1373  if (ci != NULL) {
1374  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
1375  }
1376  break;
1377  }
1378 }
1379 
1381 {
1382  if (this->status < STATUS_PRE_ACTIVE) {
1383  /* Illegal call, return error and ignore the packet */
1384  return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
1385  }
1386 
1387  NetworkAction action = (NetworkAction)p->Recv_uint8();
1388  DestType desttype = (DestType)p->Recv_uint8();
1389  int dest = p->Recv_uint32();
1390  char msg[NETWORK_CHAT_LENGTH];
1391 
1393  int64 data = p->Recv_uint64();
1394 
1395  NetworkClientInfo *ci = this->GetInfo();
1396  switch (action) {
1397  case NETWORK_ACTION_GIVE_MONEY:
1398  if (!Company::IsValidID(ci->client_playas)) break;
1399  /* FALL THROUGH */
1400  case NETWORK_ACTION_CHAT:
1401  case NETWORK_ACTION_CHAT_CLIENT:
1402  case NETWORK_ACTION_CHAT_COMPANY:
1403  NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data);
1404  break;
1405  default:
1406  IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, this->GetClientIP());
1407  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1408  }
1409  return NETWORK_RECV_STATUS_OKAY;
1410 }
1411 
1413 {
1414  if (this->status != STATUS_ACTIVE) {
1415  /* Illegal call, return error and ignore the packet */
1416  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1417  }
1418 
1419  char password[NETWORK_PASSWORD_LENGTH];
1420  const NetworkClientInfo *ci;
1421 
1422  p->Recv_string(password, sizeof(password));
1423  ci = this->GetInfo();
1424 
1426  return NETWORK_RECV_STATUS_OKAY;
1427 }
1428 
1430 {
1431  if (this->status != STATUS_ACTIVE) {
1432  /* Illegal call, return error and ignore the packet */
1433  return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1434  }
1435 
1436  char client_name[NETWORK_CLIENT_NAME_LENGTH];
1437  NetworkClientInfo *ci;
1438 
1439  p->Recv_string(client_name, sizeof(client_name));
1440  ci = this->GetInfo();
1441 
1442  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
1443 
1444  if (ci != NULL) {
1445  /* Display change */
1446  if (NetworkFindName(client_name, lastof(client_name))) {
1447  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name);
1448  strecpy(ci->client_name, client_name, lastof(ci->client_name));
1450  }
1451  }
1452  return NETWORK_RECV_STATUS_OKAY;
1453 }
1454 
1456 {
1457  if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1458 
1459  char pass[NETWORK_PASSWORD_LENGTH];
1460  char command[NETWORK_RCONCOMMAND_LENGTH];
1461 
1463 
1464  p->Recv_string(pass, sizeof(pass));
1465  p->Recv_string(command, sizeof(command));
1466 
1467  if (strcmp(pass, _settings_client.network.rcon_password) != 0) {
1468  DEBUG(net, 0, "[rcon] wrong password from client-id %d", this->client_id);
1469  return NETWORK_RECV_STATUS_OKAY;
1470  }
1471 
1472  DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", this->client_id, command);
1473 
1475  IConsoleCmdExec(command);
1477  return NETWORK_RECV_STATUS_OKAY;
1478 }
1479 
1481 {
1482  if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
1483 
1484  CompanyID company_id = (Owner)p->Recv_uint8();
1485 
1486  /* Check if the company is valid, we don't allow moving to AI companies */
1487  if (company_id != COMPANY_SPECTATOR && !Company::IsValidHumanID(company_id)) return NETWORK_RECV_STATUS_OKAY;
1488 
1489  /* Check if we require a password for this company */
1490  if (company_id != COMPANY_SPECTATOR && !StrEmpty(_network_company_states[company_id].password)) {
1491  /* we need a password from the client - should be in this packet */
1492  char password[NETWORK_PASSWORD_LENGTH];
1493  p->Recv_string(password, sizeof(password));
1494 
1495  /* Incorrect password sent, return! */
1496  if (strcmp(password, _network_company_states[company_id].password) != 0) {
1497  DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", this->client_id, company_id + 1);
1498  return NETWORK_RECV_STATUS_OKAY;
1499  }
1500  }
1501 
1502  /* if we get here we can move the client */
1503  NetworkServerDoMove(this->client_id, company_id);
1504  return NETWORK_RECV_STATUS_OKAY;
1505 }
1506 
1515 {
1516  /* Grab the company name */
1517  char company_name[NETWORK_COMPANY_NAME_LENGTH];
1518  SetDParam(0, c->index);
1519 
1520  assert(max_len <= lengthof(company_name));
1521  GetString(company_name, STR_COMPANY_NAME, company_name + max_len - 1);
1522 
1523  /* Get the income */
1524  Money income = 0;
1525  if (_cur_year - 1 == c->inaugurated_year) {
1526  /* The company is here just 1 year, so display [2], else display[1] */
1527  for (uint i = 0; i < lengthof(c->yearly_expenses[2]); i++) {
1528  income -= c->yearly_expenses[2][i];
1529  }
1530  } else {
1531  for (uint i = 0; i < lengthof(c->yearly_expenses[1]); i++) {
1532  income -= c->yearly_expenses[1][i];
1533  }
1534  }
1535 
1536  /* Send the information */
1537  p->Send_uint8 (c->index);
1538  p->Send_string(company_name);
1541  p->Send_uint64(c->money);
1542  p->Send_uint64(income);
1544 
1545  /* Send 1 if there is a password for the company else send 0 */
1547 
1548  for (uint i = 0; i < NETWORK_VEH_END; i++) {
1549  p->Send_uint16(stats->num_vehicle[i]);
1550  }
1551 
1552  for (uint i = 0; i < NETWORK_VEH_END; i++) {
1553  p->Send_uint16(stats->num_station[i]);
1554  }
1555 
1556  p->Send_bool(c->is_ai);
1557 }
1558 
1564 {
1565  const Vehicle *v;
1566  const Station *s;
1567 
1568  memset(stats, 0, sizeof(*stats) * MAX_COMPANIES);
1569 
1570  /* Go through all vehicles and count the type of vehicles */
1571  FOR_ALL_VEHICLES(v) {
1572  if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
1573  byte type = 0;
1574  switch (v->type) {
1575  case VEH_TRAIN: type = NETWORK_VEH_TRAIN; break;
1576  case VEH_ROAD: type = RoadVehicle::From(v)->IsBus() ? NETWORK_VEH_BUS : NETWORK_VEH_LORRY; break;
1577  case VEH_AIRCRAFT: type = NETWORK_VEH_PLANE; break;
1578  case VEH_SHIP: type = NETWORK_VEH_SHIP; break;
1579  default: continue;
1580  }
1581  stats[v->owner].num_vehicle[type]++;
1582  }
1583 
1584  /* Go through all stations and count the types of stations */
1585  FOR_ALL_STATIONS(s) {
1586  if (Company::IsValidID(s->owner)) {
1587  NetworkCompanyStats *npi = &stats[s->owner];
1588 
1589  if (s->facilities & FACIL_TRAIN) npi->num_station[NETWORK_VEH_TRAIN]++;
1590  if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[NETWORK_VEH_LORRY]++;
1591  if (s->facilities & FACIL_BUS_STOP) npi->num_station[NETWORK_VEH_BUS]++;
1592  if (s->facilities & FACIL_AIRPORT) npi->num_station[NETWORK_VEH_PLANE]++;
1593  if (s->facilities & FACIL_DOCK) npi->num_station[NETWORK_VEH_SHIP]++;
1594  }
1595  }
1596 }
1597 
1603 {
1604  NetworkClientSocket *cs;
1606 
1607  if (ci == NULL) return;
1608 
1609  DEBUG(desync, 1, "client: %08x; %02x; %02x; %04x", _date, _date_fract, (int)ci->client_playas, client_id);
1610 
1612  cs->SendClientInfo(ci);
1613  }
1614 
1616 }
1617 
1620 {
1622  DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
1623 
1625  }
1626 }
1627 
1635 {
1636  const NetworkClientInfo *ci;
1637  const Company *c;
1638  bool clients_in_company[MAX_COMPANIES];
1639  int vehicles_in_company[MAX_COMPANIES];
1640 
1642 
1643  memset(clients_in_company, 0, sizeof(clients_in_company));
1644 
1645  /* Detect the active companies */
1646  FOR_ALL_CLIENT_INFOS(ci) {
1647  if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
1648  }
1649 
1650  if (!_network_dedicated) {
1652  if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
1653  }
1654 
1656  memset(vehicles_in_company, 0, sizeof(vehicles_in_company));
1657 
1658  const Vehicle *v;
1659  FOR_ALL_VEHICLES(v) {
1660  if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
1661  vehicles_in_company[v->owner]++;
1662  }
1663  }
1664 
1665  /* Go through all the companies */
1666  FOR_ALL_COMPANIES(c) {
1667  /* Skip the non-active once */
1668  if (c->is_ai) continue;
1669 
1670  if (!clients_in_company[c->index]) {
1671  /* The company is empty for one month more */
1673 
1674  /* Is the company empty for autoclean_unprotected-months, and is there no protection? */
1676  /* Shut the company down */
1677  DoCommandP(0, 2 | c->index << 16, CRR_AUTOCLEAN, CMD_COMPANY_CTRL);
1678  IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no password", c->index + 1);
1679  }
1680  /* Is the company empty for autoclean_protected-months, and there is a protection? */
1682  /* Unprotect the company */
1683  _network_company_states[c->index].password[0] = '\0';
1684  IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", c->index + 1);
1687  }
1688  /* Is the company empty for autoclean_novehicles-months, and has no vehicles? */
1690  /* Shut the company down */
1691  DoCommandP(0, 2 | c->index << 16, CRR_AUTOCLEAN, CMD_COMPANY_CTRL);
1692  IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no vehicles", c->index + 1);
1693  }
1694  } else {
1695  /* It is not empty, reset the date */
1697  }
1698  }
1699 }
1700 
1707 bool NetworkFindName(char *new_name, const char *last)
1708 {
1709  bool found_name = false;
1710  uint number = 0;
1711  char original_name[NETWORK_CLIENT_NAME_LENGTH];
1712 
1713  strecpy(original_name, new_name, lastof(original_name));
1714 
1715  while (!found_name) {
1716  const NetworkClientInfo *ci;
1717 
1718  found_name = true;
1719  FOR_ALL_CLIENT_INFOS(ci) {
1720  if (strcmp(ci->client_name, new_name) == 0) {
1721  /* Name already in use */
1722  found_name = false;
1723  break;
1724  }
1725  }
1726  /* Check if it is the same as the server-name */
1728  if (ci != NULL) {
1729  if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
1730  }
1731 
1732  if (!found_name) {
1733  /* Try a new name (<name> #1, <name> #2, and so on) */
1734 
1735  /* Something's really wrong when there're more names than clients */
1736  if (number++ > MAX_CLIENTS) break;
1737  seprintf(new_name, last, "%s #%d", original_name, number);
1738  }
1739  }
1740 
1741  return found_name;
1742 }
1743 
1750 bool NetworkServerChangeClientName(ClientID client_id, const char *new_name)
1751 {
1752  NetworkClientInfo *ci;
1753  /* Check if the name's already in use */
1754  FOR_ALL_CLIENT_INFOS(ci) {
1755  if (strcmp(ci->client_name, new_name) == 0) return false;
1756  }
1757 
1758  ci = NetworkClientInfo::GetByClientID(client_id);
1759  if (ci == NULL) return false;
1760 
1761  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, true, ci->client_name, new_name);
1762 
1763  strecpy(ci->client_name, new_name, lastof(ci->client_name));
1764 
1765  NetworkUpdateClientInfo(client_id);
1766  return true;
1767 }
1768 
1775 void NetworkServerSetCompanyPassword(CompanyID company_id, const char *password, bool already_hashed)
1776 {
1777  if (!Company::IsValidHumanID(company_id)) return;
1778 
1779  if (!already_hashed) {
1781  }
1782 
1783  strecpy(_network_company_states[company_id].password, password, lastof(_network_company_states[company_id].password));
1784  NetworkServerUpdateCompanyPassworded(company_id, !StrEmpty(_network_company_states[company_id].password));
1785 }
1786 
1791 static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
1792 {
1793  CommandPacket *cp;
1794  while ((cp = cs->outgoing_queue.Pop()) != NULL) {
1795  cs->SendCommand(cp);
1796  free(cp);
1797  }
1798 }
1799 
1804 void NetworkServer_Tick(bool send_frame)
1805 {
1806  NetworkClientSocket *cs;
1807 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1808  bool send_sync = false;
1809 #endif
1810 
1811 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1814  send_sync = true;
1815  }
1816 #endif
1817 
1818  /* Now we are done with the frame, inform the clients that they can
1819  * do their frame! */
1821  /* We allow a number of bytes per frame, but only to the burst amount
1822  * to be available for packet receiving at any particular time. */
1823  cs->receive_limit = min(cs->receive_limit + _settings_client.network.bytes_per_frame,
1825 
1826  /* Check if the speed of the client is what we can expect from a client */
1827  uint lag = NetworkCalculateLag(cs);
1828  switch (cs->status) {
1829  case NetworkClientSocket::STATUS_ACTIVE:
1831  /* Client did still not report in within the specified limit. */
1832  IConsolePrintF(CC_ERROR, cs->last_packet + lag * MILLISECONDS_PER_TICK > _realtime_tick ?
1833  /* A packet was received in the last three game days, so the client is likely lagging behind. */
1834  "Client #%d is dropped because the client's game state is more than %d ticks behind" :
1835  /* No packet was received in the last three game days; sounds like a lost connection. */
1836  "Client #%d is dropped because the client did not respond for more than %d ticks",
1837  cs->client_id, lag);
1838  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1839  continue;
1840  }
1841 
1842  /* Report once per time we detect the lag, and only when we
1843  * received a packet in the last 2000 milliseconds. If we
1844  * did not receive a packet, then the client is not just
1845  * slow, but the connection is likely severed. Mentioning
1846  * frame_freq is not useful in this case. */
1847  if (lag > (uint)DAY_TICKS && cs->lag_test == 0 && cs->last_packet + 2000 > _realtime_tick) {
1848  IConsolePrintF(CC_WARNING, "[%d] Client #%d is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id);
1849  cs->lag_test = 1;
1850  }
1851 
1852  if (cs->last_frame_server - cs->last_token_frame >= _settings_client.network.max_lag_time) {
1853  /* This is a bad client! It didn't send the right token back within time. */
1854  IConsolePrintF(CC_ERROR, "Client #%d is dropped because it fails to send valid acks", cs->client_id);
1855  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1856  continue;
1857  }
1858  break;
1859 
1860  case NetworkClientSocket::STATUS_INACTIVE:
1861  case NetworkClientSocket::STATUS_NEWGRFS_CHECK:
1862  case NetworkClientSocket::STATUS_AUTHORIZED:
1863  /* NewGRF check and authorized states should be handled almost instantly.
1864  * So give them some lee-way, likewise for the query with inactive. */
1866  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);
1867  cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
1868  continue;
1869  }
1870  break;
1871 
1872  case NetworkClientSocket::STATUS_MAP:
1873  /* Downloading the map... this is the amount of time since starting the saving. */
1875  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);
1876  cs->SendError(NETWORK_ERROR_TIMEOUT_MAP);
1877  continue;
1878  }
1879  break;
1880 
1881  case NetworkClientSocket::STATUS_DONE_MAP:
1882  case NetworkClientSocket::STATUS_PRE_ACTIVE:
1883  /* The map has been sent, so this is for loading the map and syncing up. */
1885  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);
1886  cs->SendError(NETWORK_ERROR_TIMEOUT_JOIN);
1887  continue;
1888  }
1889  break;
1890 
1891  case NetworkClientSocket::STATUS_AUTH_GAME:
1892  case NetworkClientSocket::STATUS_AUTH_COMPANY:
1893  /* These don't block? */
1895  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);
1896  cs->SendError(NETWORK_ERROR_TIMEOUT_PASSWORD);
1897  continue;
1898  }
1899  break;
1900 
1901  case NetworkClientSocket::STATUS_MAP_WAIT:
1902  /* This is an internal state where we do not wait
1903  * on the client to move to a different state. */
1904  break;
1905 
1906  case NetworkClientSocket::STATUS_END:
1907  /* Bad server/code. */
1908  NOT_REACHED();
1909  }
1910 
1911  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) {
1912  /* Check if we can send command, and if we have anything in the queue */
1914 
1915  /* Send an updated _frame_counter_max to the client */
1916  if (send_frame) cs->SendFrame();
1917 
1918 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
1919  /* Send a sync-check packet */
1920  if (send_sync) cs->SendSync();
1921 #endif
1922  }
1923  }
1924 
1925  /* See if we need to advertise */
1927 }
1928 
1931 {
1934 }
1935 
1938 {
1942 }
1943 
1946 {
1949 }
1950 
1956 {
1957  return this->client_address.GetHostname();
1958 }
1959 
1962 {
1963  static const char * const stat_str[] = {
1964  "inactive",
1965  "checking NewGRFs",
1966  "authorizing (server password)",
1967  "authorizing (company password)",
1968  "authorized",
1969  "waiting",
1970  "loading map",
1971  "map done",
1972  "ready",
1973  "active"
1974  };
1975  assert_compile(lengthof(stat_str) == NetworkClientSocket::STATUS_END);
1976 
1977  NetworkClientSocket *cs;
1979  NetworkClientInfo *ci = cs->GetInfo();
1980  if (ci == NULL) continue;
1981  uint lag = NetworkCalculateLag(cs);
1982  const char *status;
1983 
1984  status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
1985  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s",
1986  cs->client_id, ci->client_name, status, lag,
1987  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
1988  cs->GetClientIP());
1989  }
1990 }
1991 
1996 {
1997  NetworkClientSocket *cs;
1998 
2000  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendConfigUpdate();
2001  }
2002 }
2003 
2009 void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded)
2010 {
2011  if (NetworkCompanyIsPassworded(company_id) == passworded) return;
2012 
2013  SB(_network_company_passworded, company_id, 1, !!passworded);
2015 
2016  NetworkClientSocket *cs;
2018  if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendCompanyUpdate();
2019  }
2020 
2022 }
2023 
2030 void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
2031 {
2032  /* Only allow non-dedicated servers and normal clients to be moved */
2033  if (client_id == CLIENT_ID_SERVER && _network_dedicated) return;
2034 
2036 
2037  /* No need to waste network resources if the client is in the company already! */
2038  if (ci->client_playas == company_id) return;
2039 
2040  ci->client_playas = company_id;
2041 
2042  if (client_id == CLIENT_ID_SERVER) {
2043  SetLocalCompany(company_id);
2044  } else {
2045  NetworkClientSocket *cs = NetworkClientSocket::GetByClientID(client_id);
2046  /* When the company isn't authorized we can't move them yet. */
2047  if (cs->status < NetworkClientSocket::STATUS_AUTHORIZED) return;
2048  cs->SendMove(client_id, company_id);
2049  }
2050 
2051  /* announce the client's move */
2052  NetworkUpdateClientInfo(client_id);
2053 
2054  NetworkAction action = (company_id == COMPANY_SPECTATOR) ? NETWORK_ACTION_COMPANY_SPECTATOR : NETWORK_ACTION_COMPANY_JOIN;
2055  NetworkServerSendChat(action, DESTTYPE_BROADCAST, 0, "", client_id, company_id + 1);
2056 }
2057 
2064 void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string)
2065 {
2066  NetworkClientSocket::GetByClientID(client_id)->SendRConResult(colour_code, string);
2067 }
2068 
2074 {
2075  if (client_id == CLIENT_ID_SERVER) return;
2076  NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED);
2077 }
2078 
2084 uint NetworkServerKickOrBanIP(ClientID client_id, bool ban)
2085 {
2086  return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban);
2087 }
2088 
2094 uint NetworkServerKickOrBanIP(const char *ip, bool ban)
2095 {
2096  /* Add address to ban-list */
2097  if (ban) {
2098  bool contains = false;
2099  for (char **iter = _network_ban_list.Begin(); iter != _network_ban_list.End(); iter++) {
2100  if (strcmp(*iter, ip) == 0) {
2101  contains = true;
2102  break;
2103  }
2104  }
2105  if (!contains) *_network_ban_list.Append() = stredup(ip);
2106  }
2107 
2108  uint n = 0;
2109 
2110  /* There can be multiple clients with the same IP, kick them all */
2111  NetworkClientSocket *cs;
2113  if (cs->client_id == CLIENT_ID_SERVER) continue;
2114  if (cs->client_address.IsInNetmask(const_cast<char *>(ip))) {
2115  NetworkServerKickClient(cs->client_id);
2116  n++;
2117  }
2118  }
2119 
2120  return n;
2121 }
2122 
2129 {
2130  const NetworkClientInfo *ci;
2131  FOR_ALL_CLIENT_INFOS(ci) {
2132  if (ci->client_playas == company) return true;
2133  }
2134  return false;
2135 }
2136 
2137 
2143 void ServerNetworkGameSocketHandler::GetClientName(char *client_name, const char *last) const
2144 {
2145  const NetworkClientInfo *ci = this->GetInfo();
2146 
2147  if (ci == NULL || StrEmpty(ci->client_name)) {
2148  seprintf(client_name, last, "Client #%4d", this->client_id);
2149  } else {
2150  strecpy(client_name, ci->client_name, last);
2151  }
2152 }
2153 
2158 {
2159  NetworkClientInfo *ci;
2160  FOR_ALL_CLIENT_INFOS(ci) {
2161  if (_network_server) {
2162  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d IP: %s",
2163  ci->client_id,
2164  ci->client_name,
2165  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
2166  ci->client_id == CLIENT_ID_SERVER ? "server" : NetworkClientSocket::GetByClientID(ci->client_id)->GetClientIP());
2167  } else {
2168  IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d",
2169  ci->client_id,
2170  ci->client_name,
2171  ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0));
2172  }
2173  }
2174 }
2175 
2182 {
2183  assert(c != NULL);
2184 
2185  if (!_network_server) return;
2186 
2188  _network_company_states[c->index].password[0] = '\0';
2190 
2191  if (ci != NULL) {
2192  /* ci is NULL when replaying, or for AIs. In neither case there is a client. */
2193  ci->client_playas = c->index;
2195  NetworkSendCommand(0, 0, 0, CMD_RENAME_PRESIDENT, NULL, ci->client_name, c->index);
2196  }
2197 
2198  /* Announce new company on network. */
2199  NetworkAdminCompanyInfo(c, true);
2200 
2201  if (ci != NULL) {
2202  /* ci is NULL when replaying, or for AIs. In neither case there is a client.
2203  We need to send Admin port update here so that they first know about the new company
2204  and then learn about a possibly joining client (see FS#6025) */
2205  NetworkServerSendChat(NETWORK_ACTION_COMPANY_NEW, DESTTYPE_BROADCAST, 0, "", ci->client_id, c->index + 1);
2206  }
2207 }
2208 
2209 #endif /* ENABLE_NETWORK */