OpenTTD Source  1.10.0-RC1
network_client.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "../stdafx.h"
11 #include "network_gui.h"
12 #include "../saveload/saveload.h"
13 #include "../saveload/saveload_filter.h"
14 #include "../command_func.h"
15 #include "../console_func.h"
16 #include "../strings_func.h"
17 #include "../window_func.h"
18 #include "../company_func.h"
19 #include "../company_base.h"
20 #include "../company_gui.h"
21 #include "../core/random_func.hpp"
22 #include "../date_func.h"
23 #include "../gfx_func.h"
24 #include "../error.h"
25 #include "../rev.h"
26 #include "network.h"
27 #include "network_base.h"
28 #include "network_client.h"
29 #include "../core/backup_type.hpp"
30 #include "../thread.h"
31 
32 #include "table/strings.h"
33 
34 #include "../safeguards.h"
35 
36 /* This file handles all the client-commands */
37 
38 
41  static const size_t CHUNK = 32 * 1024;
42 
43  std::vector<byte *> blocks;
44  byte *buf;
45  byte *bufe;
46  byte **block;
47  size_t written_bytes;
48  size_t read_bytes;
49 
51  PacketReader() : LoadFilter(nullptr), buf(nullptr), bufe(nullptr), block(nullptr), written_bytes(0), read_bytes(0)
52  {
53  }
54 
55  ~PacketReader() override
56  {
57  for (auto p : this->blocks) {
58  free(p);
59  }
60  }
61 
66  void AddPacket(const Packet *p)
67  {
68  assert(this->read_bytes == 0);
69 
70  size_t in_packet = p->size - p->pos;
71  size_t to_write = min((size_t)(this->bufe - this->buf), in_packet);
72  const byte *pbuf = p->buffer + p->pos;
73 
74  this->written_bytes += in_packet;
75  if (to_write != 0) {
76  memcpy(this->buf, pbuf, to_write);
77  this->buf += to_write;
78  }
79 
80  /* Did everything fit in the current chunk, then we're done. */
81  if (to_write == in_packet) return;
82 
83  /* Allocate a new chunk and add the remaining data. */
84  pbuf += to_write;
85  to_write = in_packet - to_write;
86  this->blocks.push_back(this->buf = CallocT<byte>(CHUNK));
87  this->bufe = this->buf + CHUNK;
88 
89  memcpy(this->buf, pbuf, to_write);
90  this->buf += to_write;
91  }
92 
93  size_t Read(byte *rbuf, size_t size) override
94  {
95  /* Limit the amount to read to whatever we still have. */
96  size_t ret_size = size = min(this->written_bytes - this->read_bytes, size);
97  this->read_bytes += ret_size;
98  const byte *rbufe = rbuf + ret_size;
99 
100  while (rbuf != rbufe) {
101  if (this->buf == this->bufe) {
102  this->buf = *this->block++;
103  this->bufe = this->buf + CHUNK;
104  }
105 
106  size_t to_write = min(this->bufe - this->buf, rbufe - rbuf);
107  memcpy(rbuf, this->buf, to_write);
108  rbuf += to_write;
109  this->buf += to_write;
110  }
111 
112  return ret_size;
113  }
114 
115  void Reset() override
116  {
117  this->read_bytes = 0;
118 
119  this->block = this->blocks.data();
120  this->buf = *this->block++;
121  this->bufe = this->buf + CHUNK;
122  }
123 };
124 
125 
130 {
132  if (!_networking) return;
133 
134  const char *filename = "netsave.sav";
135  DEBUG(net, 0, "Client: Performing emergency save (%s)", filename);
136  SaveOrLoad(filename, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false);
137 }
138 
139 
144 ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler(SOCKET s) : NetworkGameSocketHandler(s), savegame(nullptr), status(STATUS_INACTIVE)
145 {
148 }
149 
152 {
155 
156  delete this->savegame;
157 }
158 
160 {
161  assert(status != NETWORK_RECV_STATUS_OKAY);
162  /*
163  * Sending a message just before leaving the game calls cs->SendPackets.
164  * This might invoke this function, which means that when we close the
165  * connection after cs->SendPackets we will close an already closed
166  * connection. This handles that case gracefully without having to make
167  * that code any more complex or more aware of the validity of the socket.
168  */
169  if (this->sock == INVALID_SOCKET) return status;
170 
171  DEBUG(net, 1, "Closed client connection %d", this->client_id);
172 
173  this->SendPackets(true);
174 
175  /* Wait a number of ticks so our leave message can reach the server.
176  * This is especially needed for Windows servers as they seem to get
177  * the "socket is closed" message before receiving our leave message,
178  * which would trigger the server to close the connection as well. */
180 
181  delete this->GetInfo();
182  delete this;
183 
184  return status;
185 }
186 
192 {
193  /* First, send a CLIENT_ERROR to the server, so he knows we are
194  * disconnection (and why!) */
195  NetworkErrorCode errorno;
196 
197  /* We just want to close the connection.. */
198  if (res == NETWORK_RECV_STATUS_CLOSE_QUERY) {
200  this->CloseConnection(res);
201  _networking = false;
202 
204  return;
205  }
206 
207  switch (res) {
208  case NETWORK_RECV_STATUS_DESYNC: errorno = NETWORK_ERROR_DESYNC; break;
209  case NETWORK_RECV_STATUS_SAVEGAME: errorno = NETWORK_ERROR_SAVEGAME_FAILED; break;
210  case NETWORK_RECV_STATUS_NEWGRF_MISMATCH: errorno = NETWORK_ERROR_NEWGRF_MISMATCH; break;
211  default: errorno = NETWORK_ERROR_GENERAL; break;
212  }
213 
214  /* This means we fucked up and the server closed the connection */
217  SendError(errorno);
218  }
219 
221 
223  this->CloseConnection(res);
224  _networking = false;
225 }
226 
227 
234 {
235  if (my_client->CanSendReceive()) {
237  if (res != NETWORK_RECV_STATUS_OKAY) {
238  /* The client made an error of which we can not recover.
239  * Close the connection and drop back to the main menu. */
240  my_client->ClientError(res);
241  return false;
242  }
243  }
244  return _networking;
245 }
246 
249 {
252 }
253 
259 {
260  _frame_counter++;
261 
263 
264  extern void StateGameLoop();
265  StateGameLoop();
266 
267  /* Check if we are in sync! */
268  if (_sync_frame != 0) {
269  if (_sync_frame == _frame_counter) {
270 #ifdef NETWORK_SEND_DOUBLE_SEED
271  if (_sync_seed_1 != _random.state[0] || _sync_seed_2 != _random.state[1]) {
272 #else
273  if (_sync_seed_1 != _random.state[0]) {
274 #endif
275  NetworkError(STR_NETWORK_ERROR_DESYNC);
276  DEBUG(desync, 1, "sync_err: %08x; %02x", _date, _date_fract);
277  DEBUG(net, 0, "Sync error detected!");
279  return false;
280  }
281 
282  /* If this is the first time we have a sync-frame, we
283  * need to let the server know that we are ready and at the same
284  * frame as he is.. so we can start playing! */
285  if (_network_first_time) {
286  _network_first_time = false;
287  SendAck();
288  }
289 
290  _sync_frame = 0;
291  } else if (_sync_frame < _frame_counter) {
292  DEBUG(net, 1, "Missed frame for sync-test (%d / %d)", _sync_frame, _frame_counter);
293  _sync_frame = 0;
294  }
295  }
296 
297  return true;
298 }
299 
300 
303 
305 static uint32 last_ack_frame;
306 
308 static uint32 _password_game_seed;
311 
316 
319 
321 const char *_network_join_server_password = nullptr;
323 const char *_network_join_company_password = nullptr;
324 
327 
328 /***********
329  * Sending functions
330  * DEF_CLIENT_SEND_COMMAND has no parameters
331  ************/
332 
335 {
337  _network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
339 
341  my_client->SendPacket(p);
343 }
344 
347 {
349  _network_join_status = NETWORK_JOIN_STATUS_AUTHORIZING;
351 
352  Packet *p = new Packet(PACKET_CLIENT_JOIN);
354  p->Send_uint32(_openttd_newgrf_version);
355  p->Send_string(_settings_client.network.client_name); // Client name
356  p->Send_uint8 (_network_join_as); // PlayAs
357  p->Send_uint8 (NETLANG_ANY); // Language
358  my_client->SendPacket(p);
360 }
361 
364 {
366  my_client->SendPacket(p);
368 }
369 
375 {
377  p->Send_string(password);
378  my_client->SendPacket(p);
380 }
381 
387 {
389  p->Send_string(GenerateCompanyPasswordHash(password, _password_server_id, _password_game_seed));
390  my_client->SendPacket(p);
392 }
393 
396 {
398 
400  my_client->SendPacket(p);
402 }
403 
406 {
408 
410  my_client->SendPacket(p);
412 }
413 
416 {
417  Packet *p = new Packet(PACKET_CLIENT_ACK);
418 
420  p->Send_uint8 (my_client->token);
421  my_client->SendPacket(p);
423 }
424 
430 {
432  my_client->NetworkGameSocketHandler::SendCommand(p, cp);
433 
434  my_client->SendPacket(p);
436 }
437 
439 NetworkRecvStatus ClientNetworkGameSocketHandler::SendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data)
440 {
441  Packet *p = new Packet(PACKET_CLIENT_CHAT);
442 
443  p->Send_uint8 (action);
444  p->Send_uint8 (type);
445  p->Send_uint32(dest);
446  p->Send_string(msg);
447  p->Send_uint64(data);
448 
449  my_client->SendPacket(p);
451 }
452 
455 {
457 
458  p->Send_uint8(errorno);
459  my_client->SendPacket(p);
461 }
462 
468 {
470 
471  p->Send_string(GenerateCompanyPasswordHash(password, _password_server_id, _password_game_seed));
472  my_client->SendPacket(p);
474 }
475 
481 {
483 
484  p->Send_string(name);
485  my_client->SendPacket(p);
487 }
488 
493 {
494  Packet *p = new Packet(PACKET_CLIENT_QUIT);
495 
496  my_client->SendPacket(p);
498 }
499 
505 NetworkRecvStatus ClientNetworkGameSocketHandler::SendRCon(const char *pass, const char *command)
506 {
507  Packet *p = new Packet(PACKET_CLIENT_RCON);
508  p->Send_string(pass);
509  p->Send_string(command);
510  my_client->SendPacket(p);
512 }
513 
520 {
521  Packet *p = new Packet(PACKET_CLIENT_MOVE);
522  p->Send_uint8(company);
523  p->Send_string(GenerateCompanyPasswordHash(password, _password_server_id, _password_game_seed));
524  my_client->SendPacket(p);
526 }
527 
533 {
534  return my_client != nullptr && my_client->status == STATUS_ACTIVE;
535 }
536 
537 
538 /***********
539  * Receiving functions
540  * DEF_CLIENT_RECEIVE_COMMAND has parameter: Packet *p
541  ************/
542 
543 extern bool SafeLoad(const char *filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = nullptr);
544 
546 {
547  /* We try to join a server which is full */
548  ShowErrorMessage(STR_NETWORK_ERROR_SERVER_FULL, INVALID_STRING_ID, WL_CRITICAL);
550 
552 }
553 
555 {
556  /* We try to join a server where we are banned */
557  ShowErrorMessage(STR_NETWORK_ERROR_SERVER_BANNED, INVALID_STRING_ID, WL_CRITICAL);
559 
561 }
562 
564 {
566 
567  byte company_info_version = p->Recv_uint8();
568 
569  if (!this->HasClientQuit() && company_info_version == NETWORK_COMPANY_INFO_VERSION) {
570  /* We have received all data... (there are no more packets coming) */
571  if (!p->Recv_bool()) return NETWORK_RECV_STATUS_CLOSE_QUERY;
572 
573  CompanyID current = (Owner)p->Recv_uint8();
574  if (current >= MAX_COMPANIES) return NETWORK_RECV_STATUS_CLOSE_QUERY;
575 
576  NetworkCompanyInfo *company_info = GetLobbyCompanyInfo(current);
577  if (company_info == nullptr) return NETWORK_RECV_STATUS_CLOSE_QUERY;
578 
579  p->Recv_string(company_info->company_name, sizeof(company_info->company_name));
580  company_info->inaugurated_year = p->Recv_uint32();
581  company_info->company_value = p->Recv_uint64();
582  company_info->money = p->Recv_uint64();
583  company_info->income = p->Recv_uint64();
584  company_info->performance = p->Recv_uint16();
585  company_info->use_password = p->Recv_bool();
586  for (uint i = 0; i < NETWORK_VEH_END; i++) {
587  company_info->num_vehicle[i] = p->Recv_uint16();
588  }
589  for (uint i = 0; i < NETWORK_VEH_END; i++) {
590  company_info->num_station[i] = p->Recv_uint16();
591  }
592  company_info->ai = p->Recv_bool();
593 
594  p->Recv_string(company_info->clients, sizeof(company_info->clients));
595 
597 
599  }
600 
602 }
603 
604 /* This packet contains info about the client (playas and name)
605  * as client we save this in NetworkClientInfo, linked via 'client_id'
606  * which is always an unique number on a server. */
608 {
609  NetworkClientInfo *ci;
611  CompanyID playas = (CompanyID)p->Recv_uint8();
612  char name[NETWORK_NAME_LENGTH];
613 
614  p->Recv_string(name, sizeof(name));
615 
617  if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
618 
619  ci = NetworkClientInfo::GetByClientID(client_id);
620  if (ci != nullptr) {
621  if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) {
622  /* Client name changed, display the change */
623  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, name);
624  } else if (playas != ci->client_playas) {
625  /* The client changed from client-player..
626  * Do not display that for now */
627  }
628 
629  /* Make sure we're in the company the server tells us to be in,
630  * for the rare case that we get moved while joining. */
631  if (client_id == _network_own_client_id) SetLocalCompany(!Company::IsValidID(playas) ? COMPANY_SPECTATOR : playas);
632 
633  ci->client_playas = playas;
634  strecpy(ci->client_name, name, lastof(ci->client_name));
635 
637 
639  }
640 
641  /* There are at most as many ClientInfo as ClientSocket objects in a
642  * server. Having more info than a server can have means something
643  * has gone wrong somewhere, i.e. the server has more info than it
644  * has actual clients. That means the server is feeding us an invalid
645  * state. So, bail out! This server is broken. */
647 
648  /* We don't have this client_id yet, find an empty client_id, and put the data there */
649  ci = new NetworkClientInfo(client_id);
650  ci->client_playas = playas;
651  if (client_id == _network_own_client_id) this->SetInfo(ci);
652 
653  strecpy(ci->client_name, name, lastof(ci->client_name));
654 
656 
658 }
659 
661 {
662  static const StringID network_error_strings[] = {
663  STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_GENERAL
664  STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_DESYNC
665  STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_SAVEGAME_FAILED
666  STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_CONNECTION_LOST
667  STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_ILLEGAL_PACKET
668  STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_NEWGRF_MISMATCH
669  STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_NOT_AUTHORIZED
670  STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_NOT_EXPECTED
671  STR_NETWORK_ERROR_WRONG_REVISION, // NETWORK_ERROR_WRONG_REVISION
672  STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_NAME_IN_USE
673  STR_NETWORK_ERROR_WRONG_PASSWORD, // NETWORK_ERROR_WRONG_PASSWORD
674  STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_COMPANY_MISMATCH
675  STR_NETWORK_ERROR_KICKED, // NETWORK_ERROR_KICKED
676  STR_NETWORK_ERROR_CHEATER, // NETWORK_ERROR_CHEATER
677  STR_NETWORK_ERROR_SERVER_FULL, // NETWORK_ERROR_FULL
678  STR_NETWORK_ERROR_TOO_MANY_COMMANDS, // NETWORK_ERROR_TOO_MANY_COMMANDS
679  STR_NETWORK_ERROR_TIMEOUT_PASSWORD, // NETWORK_ERROR_TIMEOUT_PASSWORD
680  STR_NETWORK_ERROR_TIMEOUT_COMPUTER, // NETWORK_ERROR_TIMEOUT_COMPUTER
681  STR_NETWORK_ERROR_TIMEOUT_MAP, // NETWORK_ERROR_TIMEOUT_MAP
682  STR_NETWORK_ERROR_TIMEOUT_JOIN, // NETWORK_ERROR_TIMEOUT_JOIN
683  };
684  assert_compile(lengthof(network_error_strings) == NETWORK_ERROR_END);
685 
687 
688  StringID err = STR_NETWORK_ERROR_LOSTCONNECTION;
689  if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error];
690  /* In case of kicking a client, we assume there is a kick message in the packet if we can read one byte */
691  if (error == NETWORK_ERROR_KICKED && p->CanReadFromPacket(1)) {
692  char kick_msg[255];
693  p->Recv_string(kick_msg, sizeof(kick_msg));
694  SetDParamStr(0, kick_msg);
695  ShowErrorMessage(err, STR_NETWORK_ERROR_KICK_MESSAGE, WL_CRITICAL);
696  } else {
698  }
699 
700  /* Perform an emergency save if we had already entered the game */
702 
704 
706 }
707 
709 {
711 
712  uint grf_count = p->Recv_uint8();
714 
715  /* Check all GRFs */
716  for (; grf_count > 0; grf_count--) {
717  GRFIdentifier c;
718  this->ReceiveGRFIdentifier(p, &c);
719 
720  /* Check whether we know this GRF */
721  const GRFConfig *f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum);
722  if (f == nullptr) {
723  /* We do not know this GRF, bail out of initialization */
724  char buf[sizeof(c.md5sum) * 2 + 1];
725  md5sumToString(buf, lastof(buf), c.md5sum);
726  DEBUG(grf, 0, "NewGRF %08X not found; checksum %s", BSWAP32(c.grfid), buf);
728  }
729  }
730 
731  if (ret == NETWORK_RECV_STATUS_OKAY) {
732  /* Start receiving the map */
733  return SendNewGRFsOk();
734  }
735 
736  /* NewGRF mismatch, bail out */
737  ShowErrorMessage(STR_NETWORK_ERROR_NEWGRF_MISMATCH, INVALID_STRING_ID, WL_CRITICAL);
738  return ret;
739 }
740 
742 {
743  if (this->status < STATUS_JOIN || this->status >= STATUS_AUTH_GAME) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
744  this->status = STATUS_AUTH_GAME;
745 
746  const char *password = _network_join_server_password;
747  if (!StrEmpty(password)) {
748  return SendGamePassword(password);
749  }
750 
751  ShowNetworkNeedPassword(NETWORK_GAME_PASSWORD);
752 
754 }
755 
757 {
758  if (this->status < STATUS_JOIN || this->status >= STATUS_AUTH_COMPANY) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
759  this->status = STATUS_AUTH_COMPANY;
760 
761  _password_game_seed = p->Recv_uint32();
762  p->Recv_string(_password_server_id, sizeof(_password_server_id));
764 
765  const char *password = _network_join_company_password;
766  if (!StrEmpty(password)) {
767  return SendCompanyPassword(password);
768  }
769 
770  ShowNetworkNeedPassword(NETWORK_COMPANY_PASSWORD);
771 
773 }
774 
776 {
777  if (this->status < STATUS_JOIN || this->status >= STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
778  this->status = STATUS_AUTHORIZED;
779 
781 
782  /* Initialize the password hash salting variables, even if they were previously. */
783  _password_game_seed = p->Recv_uint32();
784  p->Recv_string(_password_server_id, sizeof(_password_server_id));
785 
786  /* Start receiving the map */
787  return SendGetMap();
788 }
789 
791 {
792  /* We set the internal wait state when requesting the map. */
794 
795  /* But... only now we set the join status to waiting, instead of requesting. */
796  _network_join_status = NETWORK_JOIN_STATUS_WAITING;
799 
801 }
802 
804 {
805  if (this->status < STATUS_AUTHORIZED || this->status >= STATUS_MAP) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
806  this->status = STATUS_MAP;
807 
808  if (this->savegame != nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
809 
810  this->savegame = new PacketReader();
811 
813 
816 
817  _network_join_status = NETWORK_JOIN_STATUS_DOWNLOADING;
819 
821 }
822 
824 {
826  if (this->savegame == nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
827 
830 
832 }
833 
835 {
837  if (this->savegame == nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
838 
839  /* We are still receiving data, put it to the file */
840  this->savegame->AddPacket(p);
841 
842  _network_join_bytes = (uint32)this->savegame->written_bytes;
844 
846 }
847 
849 {
851  if (this->savegame == nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
852 
853  _network_join_status = NETWORK_JOIN_STATUS_PROCESSING;
855 
856  /*
857  * Make sure everything is set for reading.
858  *
859  * We need the local copy and reset this->savegame because when
860  * loading fails the network gets reset upon loading the intro
861  * game, which would cause us to free this->savegame twice.
862  */
863  LoadFilter *lf = this->savegame;
864  this->savegame = nullptr;
865  lf->Reset();
866 
867  /* The map is done downloading, load it */
869  bool load_success = SafeLoad(nullptr, SLO_LOAD, DFT_GAME_FILE, GM_NORMAL, NO_DIRECTORY, lf);
870 
871  /* Long savegame loads shouldn't affect the lag calculation! */
872  this->last_packet = _realtime_tick;
873 
874  if (!load_success) {
876  ShowErrorMessage(STR_NETWORK_ERROR_SAVEGAMEERROR, INVALID_STRING_ID, WL_CRITICAL);
878  }
879  /* If the savegame has successfully loaded, ALL windows have been removed,
880  * only toolbar/statusbar and gamefield are visible */
881 
882  /* Say we received the map and loaded it correctly! */
883  SendMapOk();
884 
885  /* New company/spectator (invalid company) or company we want to join is not active
886  * Switch local company to spectator and await the server's judgement */
887  if (_network_join_as == COMPANY_NEW_COMPANY || !Company::IsValidID(_network_join_as)) {
889 
890  if (_network_join_as != COMPANY_SPECTATOR) {
891  /* We have arrived and ready to start playing; send a command to make a new company;
892  * the server will give us a client-id and let us in */
893  _network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
894  ShowJoinStatusWindow();
895  NetworkSendCommand(0, CCA_NEW, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company);
896  }
897  } else {
898  /* take control over an existing company */
899  SetLocalCompany(_network_join_as);
900  }
901 
903 }
904 
906 {
908 
911 #ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
912  /* Test if the server supports this option
913  * and if we are at the frame the server is */
914  if (p->pos + 1 < p->size) {
916  _sync_seed_1 = p->Recv_uint32();
917 #ifdef NETWORK_SEND_DOUBLE_SEED
918  _sync_seed_2 = p->Recv_uint32();
919 #endif
920  }
921 #endif
922  /* Receive the token. */
923  if (p->pos != p->size) this->token = p->Recv_uint8();
924 
925  DEBUG(net, 5, "Received FRAME %d", _frame_counter_server);
926 
927  /* Let the server know that we received this frame correctly
928  * We do this only once per day, to save some bandwidth ;) */
929  if (!_network_first_time && last_ack_frame < _frame_counter) {
930  last_ack_frame = _frame_counter + DAY_TICKS;
931  DEBUG(net, 4, "Sent ACK at %d", _frame_counter);
932  SendAck();
933  }
934 
936 }
937 
939 {
941 
942  _sync_frame = p->Recv_uint32();
943  _sync_seed_1 = p->Recv_uint32();
944 #ifdef NETWORK_SEND_DOUBLE_SEED
945  _sync_seed_2 = p->Recv_uint32();
946 #endif
947 
949 }
950 
952 {
954 
955  CommandPacket cp;
956  const char *err = this->ReceiveCommand(p, &cp);
957  cp.frame = p->Recv_uint32();
958  cp.my_cmd = p->Recv_bool();
959 
960  if (err != nullptr) {
961  IConsolePrintF(CC_ERROR, "WARNING: %s from server, dropping...", err);
963  }
964 
965  this->incoming_queue.Append(&cp);
966 
968 }
969 
971 {
973 
974  char name[NETWORK_NAME_LENGTH], msg[NETWORK_CHAT_LENGTH];
975  const NetworkClientInfo *ci = nullptr, *ci_to;
976 
977  NetworkAction action = (NetworkAction)p->Recv_uint8();
979  bool self_send = p->Recv_bool();
981  int64 data = p->Recv_uint64();
982 
983  ci_to = NetworkClientInfo::GetByClientID(client_id);
984  if (ci_to == nullptr) return NETWORK_RECV_STATUS_OKAY;
985 
986  /* Did we initiate the action locally? */
987  if (self_send) {
988  switch (action) {
989  case NETWORK_ACTION_CHAT_CLIENT:
990  /* For speaking to client we need the client-name */
991  seprintf(name, lastof(name), "%s", ci_to->client_name);
993  break;
994 
995  /* For speaking to company or giving money, we need the company-name */
996  case NETWORK_ACTION_GIVE_MONEY:
997  if (!Company::IsValidID(ci_to->client_playas)) return NETWORK_RECV_STATUS_OKAY;
998  FALLTHROUGH;
999 
1000  case NETWORK_ACTION_CHAT_COMPANY: {
1001  StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
1002  SetDParam(0, ci_to->client_playas);
1003 
1004  GetString(name, str, lastof(name));
1006  break;
1007  }
1008 
1009  default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
1010  }
1011  } else {
1012  /* Display message from somebody else */
1013  seprintf(name, lastof(name), "%s", ci_to->client_name);
1014  ci = ci_to;
1015  }
1016 
1017  if (ci != nullptr) {
1018  NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), self_send, name, msg, data);
1019  }
1020  return NETWORK_RECV_STATUS_OKAY;
1021 }
1022 
1024 {
1026 
1028 
1030  if (ci != nullptr) {
1031  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, nullptr, GetNetworkErrorMsg((NetworkErrorCode)p->Recv_uint8()));
1032  delete ci;
1033  }
1034 
1036 
1037  return NETWORK_RECV_STATUS_OKAY;
1038 }
1039 
1041 {
1043 
1045 
1047  if (ci != nullptr) {
1048  NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, nullptr, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
1049  delete ci;
1050  } else {
1051  DEBUG(net, 0, "Unknown client (%d) is leaving the game", client_id);
1052  }
1053 
1055 
1056  /* If we come here it means we could not locate the client.. strange :s */
1057  return NETWORK_RECV_STATUS_OKAY;
1058 }
1059 
1061 {
1063 
1065 
1067  if (ci != nullptr) {
1068  NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, ci->client_name);
1069  }
1070 
1072 
1073  return NETWORK_RECV_STATUS_OKAY;
1074 }
1075 
1077 {
1078  /* Only when we're trying to join we really
1079  * care about the server shutting down. */
1080  if (this->status >= STATUS_JOIN) {
1081  ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_SHUTDOWN, INVALID_STRING_ID, WL_CRITICAL);
1082  }
1083 
1085 
1087 }
1088 
1090 {
1091  /* Only when we're trying to join we really
1092  * care about the server shutting down. */
1093  if (this->status >= STATUS_JOIN) {
1094  /* To throttle the reconnects a bit, every clients waits its
1095  * Client ID modulo 16. This way reconnects should be spread
1096  * out a bit. */
1098  ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_REBOOT, INVALID_STRING_ID, WL_CRITICAL);
1099  }
1100 
1102 
1104 }
1105 
1107 {
1109 
1110  TextColour colour_code = (TextColour)p->Recv_uint16();
1112 
1113  char rcon_out[NETWORK_RCONCOMMAND_LENGTH];
1114  p->Recv_string(rcon_out, sizeof(rcon_out));
1115 
1116  IConsolePrint(colour_code, rcon_out);
1117 
1118  return NETWORK_RECV_STATUS_OKAY;
1119 }
1120 
1122 {
1124 
1125  /* Nothing more in this packet... */
1127  CompanyID company_id = (CompanyID)p->Recv_uint8();
1128 
1129  if (client_id == 0) {
1130  /* definitely an invalid client id, debug message and do nothing. */
1131  DEBUG(net, 0, "[move] received invalid client index = 0");
1133  }
1134 
1135  const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
1136  /* Just make sure we do not try to use a client_index that does not exist */
1137  if (ci == nullptr) return NETWORK_RECV_STATUS_OKAY;
1138 
1139  /* if not valid player, force spectator, else check player exists */
1140  if (!Company::IsValidID(company_id)) company_id = COMPANY_SPECTATOR;
1141 
1142  if (client_id == _network_own_client_id) {
1143  SetLocalCompany(company_id);
1144  }
1145 
1146  return NETWORK_RECV_STATUS_OKAY;
1147 }
1148 
1150 {
1152 
1153  _network_server_max_companies = p->Recv_uint8();
1154  _network_server_max_spectators = p->Recv_uint8();
1155 
1156  return NETWORK_RECV_STATUS_OKAY;
1157 }
1158 
1160 {
1162 
1165 
1166  return NETWORK_RECV_STATUS_OKAY;
1167 }
1168 
1173 {
1174  /* Only once we're authorized we can expect a steady stream of packets. */
1175  if (this->status < STATUS_AUTHORIZED) return;
1176 
1177  /* It might... sometimes occur that the realtime ticker overflows. */
1178  if (_realtime_tick < this->last_packet) this->last_packet = _realtime_tick;
1179 
1180  /* Lag is in milliseconds; 5 seconds are roughly twice the
1181  * server's "you're slow" threshold (1 game day). */
1182  uint lag = (_realtime_tick - this->last_packet) / 1000;
1183  if (lag < 5) return;
1184 
1185  /* 20 seconds are (way) more than 4 game days after which
1186  * the server will forcefully disconnect you. */
1187  if (lag > 20) {
1189  return;
1190  }
1191 
1192  /* Prevent showing the lag message every tick; just update it when needed. */
1193  static uint last_lag = 0;
1194  if (last_lag == lag) return;
1195 
1196  last_lag = lag;
1197  SetDParam(0, lag);
1198  ShowErrorMessage(STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION, STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION, WL_INFO);
1199 }
1200 
1201 
1204 {
1205  /* Set the frame-counter to 0 so nothing happens till we are ready */
1206  _frame_counter = 0;
1208  last_ack_frame = 0;
1209  /* Request the game-info */
1211 }
1212 
1218 void NetworkClientSendRcon(const char *password, const char *command)
1219 {
1220  MyClient::SendRCon(password, command);
1221 }
1222 
1229 void NetworkClientRequestMove(CompanyID company_id, const char *pass)
1230 {
1231  MyClient::SendMove(company_id, pass);
1232 }
1233 
1239 {
1240  Backup<CompanyID> cur_company(_current_company, FILE_LINE);
1241  /* If our company is changing owner, go to spectators */
1243 
1245  if (ci->client_playas != cid) continue;
1246  NetworkTextMessage(NETWORK_ACTION_COMPANY_SPECTATOR, CC_DEFAULT, false, ci->client_name);
1247  ci->client_playas = COMPANY_SPECTATOR;
1248  }
1249 
1250  cur_company.Restore();
1251 }
1252 
1257 {
1259 
1260  if (ci == nullptr) return;
1261 
1262  /* Don't change the name if it is the same as the old name */
1263  if (strcmp(ci->client_name, _settings_client.network.client_name) != 0) {
1264  if (!_network_server) {
1266  } else {
1268  NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, _settings_client.network.client_name);
1271  }
1272  }
1273  }
1274 }
1275 
1284 void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data)
1285 {
1286  MyClient::SendChat(action, type, dest, msg, data);
1287 }
1288 
1293 void NetworkClientSetCompanyPassword(const char *password)
1294 {
1295  MyClient::SendSetPassword(password);
1296 }
1297 
1304 {
1305  /* Only companies actually playing can speak to team. Eg spectators cannot */
1307 
1308  for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
1309  if (ci->client_playas == cio->client_playas && ci != cio) return true;
1310  }
1311 
1312  return false;
1313 }
1314 
1320 {
1322 }
1323 
1329 {
1331 }
Everything is okay.
Definition: core.h:23
Client acknowledges that it has all required NewGRFs.
Definition: tcp_game.h:56
Owner
Enum for all companies/owners.
Definition: company_type.h:18
We are trying to get company information.
NetworkRecvStatus Receive_SERVER_COMPANY_INFO(Packet *p) override
Sends information about the companies (one packet per company): uint8 Version of the structure of thi...
NetworkRecvStatus CloseConnection(bool error=true) override
Functions to help ReceivePacket/SendPacket a bit A socket can make errors.
Definition: tcp_game.cpp:40
used in multiplayer to create a new companies etc.
Definition: command_type.h:280
bool _networking
are we in networking mode?
Definition: network.cpp:52
NetworkRecvStatus Receive_SERVER_FULL(Packet *p) override
Notification that the server is full.
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.
char clients[NETWORK_CLIENTS_LENGTH]
The clients that control this company (Name1, name2, ..)
Definition: network_gui.h:36
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition: core.h:67
Container for all information known about a client.
Definition: network_base.h:23
SOCKET sock
The socket currently connected to.
Definition: tcp.h:32
uint32 _sync_seed_1
Seed to compare during sync checks.
Definition: network.cpp:71
struct PacketReader * savegame
Packet reader for reading the savegame.
uint32 _realtime_tick
The real time in the game.
Definition: debug.cpp:48
Internal entity of a packet.
Definition: packet.h:40
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3218
TextColour GetDrawStringCompanyColour(CompanyID company)
Get the colour for DrawString-subroutines which matches the colour of the company.
A client changes its name.
Definition: tcp_game.h:108
static NetworkRecvStatus SendJoin()
Tell the server we would like to join.
size_t written_bytes
The total number of bytes we&#39;ve written.
static bool Receive()
Check whether we received/can send some data from/to the server and when that&#39;s the case handle it ap...
Subdirectory
The different kinds of subdirectories OpenTTD uses.
Definition: fileio_type.h:108
uint32 Recv_uint32()
Read a 32 bits integer from the packet.
Definition: packet.cpp:246
The client is authorized at the server.
NetworkRecvStatus Receive_SERVER_JOIN(Packet *p) override
A client joined (PACKET_CLIENT_MAP_OK), what usually directly follows is a PACKET_SERVER_CLIENT_INFO:...
NetworkRecvStatus ReceivePackets()
Do the actual receiving of packets.
Definition: tcp_game.cpp:132
Client list; Window numbers:
Definition: window_type.h:472
PacketSize pos
The current read/write position in the packet.
Definition: packet.h:50
NetworkRecvStatus Receive_SERVER_NEWGAME(Packet *p) override
Let the clients know that the server is loading a new map.
const char * _network_join_server_password
Login password from -p argument.
static NetworkRecvStatus SendGamePassword(const char *password)
Set the game password as requested.
Switch to game intro menu.
Definition: openttd.h:30
const char * _network_join_company_password
Company password from -P argument.
bool SafeLoad(const char *filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf=nullptr)
Load the specified savegame but on error do different things.
Definition: openttd.cpp:1001
bool ai
Is this company an AI.
Definition: network_type.h:60
static uint8 _network_server_max_spectators
Maximum number of spectators of the currently joined server.
GUIs related to networking.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
Definition: string.cpp:407
void Send_string(const char *data)
Sends a string over the network.
Definition: packet.cpp:148
void ClientError(NetworkRecvStatus res)
Handle an error coming from the client side.
static NetworkRecvStatus SendMapOk()
Tell the server we received the complete map.
Something went wrong (down)loading the savegame.
Definition: core.h:26
byte ** block
The block we&#39;re reading from/writing to.
void ClientNetworkEmergencySave()
Create an emergency savegame when the network connection is lost.
NetworkErrorCode
The error codes we send around in the protocols.
Definition: network_type.h:101
NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override
Close the network connection due to the given status.
char company_name[NETWORK_COMPANY_NAME_LENGTH]
Company name.
Definition: network_gui.h:29
Clients sends the (hashed) game password.
Definition: tcp_game.h:60
NetworkJoinStatus _network_join_status
The status of joining.
NetworkRecvStatus Receive_SERVER_COMMAND(Packet *p) override
Sends a DoCommand to the client: uint8 ID of the company (0..MAX_COMPANIES-1).
The client wants a new company.
Definition: company_type.h:34
void Send_uint8(uint8 data)
Package a 8 bits integer in the packet.
Definition: packet.cpp:96
char * md5sumToString(char *buf, const char *last, const uint8 md5sum[16])
Convert the md5sum to a hexadecimal string representation.
Definition: string.cpp:425
Client part of the network protocol.
void NetworkUpdateClientInfo(ClientID client_id)
Send updated client info of a particular client.
static uint8 _network_server_max_companies
Maximum number of companies of the currently joined server.
NetworkRecvStatus Receive_SERVER_CONFIG_UPDATE(Packet *p) override
Update the clients knowledge of the max settings: uint8 Maximum number of companies allowed...
void NetworkClientRequestMove(CompanyID company_id, const char *pass)
Notify the server of this client wanting to be moved to another company.
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=nullptr, uint textref_stack_size=0, const uint32 *textref_stack=nullptr)
Display an error message in a window.
Definition: error_gui.cpp:380
NetworkRecvStatus Receive_SERVER_SHUTDOWN(Packet *p) override
Let the clients know that the server is closing.
static NetworkRecvStatus SendNewGRFsOk()
Tell the server we got all the NewGRFs.
static const int DAY_TICKS
1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885.
Definition: date_type.h:28
void CSleep(int milliseconds)
Sleep on the current thread for a defined time.
Definition: thread.h:25
void Send_uint32(uint32 data)
Package a 32 bits integer in the packet.
Definition: packet.cpp:117
void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data)
Send a chat message.
NetworkRecvStatus Receive_SERVER_WELCOME(Packet *p) override
The client is joined and ready to receive his map: uint32 Own client ID.
bool CanReadFromPacket(uint bytes_to_read)
Is it safe to read from the packet, i.e.
Definition: packet.cpp:169
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:48
NetworkRecvStatus Receive_SERVER_COMPANY_UPDATE(Packet *p) override
Update the clients knowledge of which company is password protected: uint16 Bitwise representation of...
static const TextColour CC_DEFAULT
Default colour of the console.
Definition: console_type.h:23
Money company_value
The company value.
Definition: network_gui.h:31
bool IsValidConsoleColour(TextColour c)
Check whether the given TextColour is valid for console usage.
Base core network types and some helper functions to access them.
bool NetworkMaxSpectatorsReached()
Check if max_spectatos has been reached on the server (local check only).
ClientNetworkGameSocketHandler(SOCKET s)
Create a new socket for the client side of the game connection.
static NetworkRecvStatus SendSetPassword(const char *password)
Tell the server that we like to change the password of the company.
NetworkRecvStatus Receive_SERVER_SYNC(Packet *p) override
Sends a sync-check to the client: uint32 Frame counter.
const char * GetNetworkRevisionString()
Get the network version string used by this build.
Definition: network.cpp:1094
void Append(CommandPacket *p)
Append a CommandPacket at the end of the queue.
const GRFConfig * FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8 *md5sum, uint32 desired_version)
Find a NewGRF in the scanned list.
void AddPacket(const Packet *p)
Add a packet to this buffer.
Class for handling the client side of the game connection.
ClientID
&#39;Unique&#39; identifier to be given to clients
Definition: network_type.h:39
uint32 _sync_frame
The frame to perform the sync check.
Definition: network.cpp:75
The server told us we made an error.
Definition: core.h:29
The client tells the server which frame it has executed.
Definition: tcp_game.h:87
Basic data to distinguish a GRF.
Definition: newgrf_config.h:82
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
Definition: tcp.cpp:95
File is being saved.
Definition: fileio_type.h:50
StringID GetNetworkErrorMsg(NetworkErrorCode err)
Retrieve the string id of an internal error number.
Definition: network.cpp:299
Client asks the server to execute some command.
Definition: tcp_game.h:99
Network lobby window.
Definition: window_type.h:28
The password of the company.
Definition: network_type.h:74
CommandQueue incoming_queue
The command-queue awaiting handling.
Definition: tcp_game.h:520
Class to backup a specific variable and restore it later.
Definition: backup_type.hpp:21
size_t Read(byte *rbuf, size_t size) override
Read a given number of bytes from the savegame.
static const size_t CHUNK
32 KiB chunks of memory.
uint16 num_vehicle[NETWORK_VEH_END]
How many vehicles are there of this type?
Definition: network_type.h:58
Save game or scenario file.
Definition: fileio_type.h:31
Done querying the server.
Definition: core.h:32
Interface for filtering a savegame till it is loaded.
A desync did occur.
Definition: core.h:24
Year inaugurated_year
What year the company started in.
Definition: network_gui.h:30
~ClientNetworkGameSocketHandler()
Clear whatever we assigned.
Critical errors, the MessageBox is shown in all cases.
Definition: error.h:24
void SetDParamStr(uint n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:279
void StateGameLoop()
State controlling game loop.
Definition: openttd.cpp:1328
static bool IsConnected()
Check whether the client is actually connected (and in the game).
NetworkRecvStatus Receive_SERVER_MAP_DATA(Packet *p) override
Sends the data of the map to the client: Contains a part of the map (until max size of packet)...
bool prefer_teamchat
choose the chat message target with <ENTER>, true=all clients, false=your team
static NetworkRecvStatus SendAck()
Send an acknowledgement from the server&#39;s ticks.
NetworkSettings network
settings related to the network
CompanyID client_playas
As which company is this client playing (CompanyID)
Definition: network_base.h:27
static const uint NETWORK_RCONCOMMAND_LENGTH
The maximum length of a rconsole command, in bytes including &#39;\0&#39;.
Definition: config.h:48
void Send_uint64(uint64 data)
Package a 64 bits integer in the packet.
Definition: packet.cpp:130
A client would like to be moved to another company.
Definition: tcp_game.h:103
static NetworkRecvStatus SendCompanyPassword(const char *password)
Set the company password as requested.
DateFract _date_fract
Fractional part of the day.
Definition: date.cpp:28
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
Definition: packet.h:52
The client is spectating.
Definition: company_type.h:35
Information about GRF, used in the game and (part of it) in savegames.
friend void NetworkExecuteLocalCommandQueue()
Execute all commands on the local command queue that ought to be executed this frame.
char client_name[NETWORK_CLIENT_NAME_LENGTH]
Name of the client.
Definition: network_base.h:25
GameMode
Mode which defines the state of the game.
Definition: openttd.h:16
Client sends the (hashed) company password.
Definition: tcp_game.h:62
uint8 max_spectators
maximum amount of spectators
Company information stored at the client side.
Definition: network_gui.h:28
void IConsolePrint(TextColour colour_code, const char *string)
Handle the printing of text entered into the console or redirected there by any other means...
Definition: console.cpp:85
Read some packets, and when do use that data as initial load filter.
size_t read_bytes
The total number of read bytes.
void CheckConnection()
Check the connection&#39;s state, i.e.
ClientID _network_own_client_id
Our client identifier.
Definition: network.cpp:59
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:79
static NetworkRecvStatus SendError(NetworkErrorCode errorno)
Send an error-packet over the network.
void CDECL IConsolePrintF(TextColour colour_code, const char *format,...)
Handle the printing of text entered into the console or redirected there by any other means...
Definition: console.cpp:125
A path without any base directory.
Definition: fileio_type.h:125
The client is waiting as someone else is downloading the map.
void NetworkClientsToSpectators(CompanyID cid)
Move the clients of a company to the spectators.
NetworkRecvStatus Receive_SERVER_FRAME(Packet *p) override
Sends the current frame counter to the client: uint32 Frame counter uint32 Frame counter max (how far...
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...
NetworkRecvStatus Receive_SERVER_CHAT(Packet *p) override
Sends a chat-packet to the client: uint8 ID of the action (see NetworkAction).
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition: gfx_type.h:245
virtual void Reset()
Reset this filter to read from the beginning of the file.
void NetworkUpdateClientName()
Send the server our name.
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
Definition: gfx_type.h:305
uint8 _network_reconnect
Reconnect timeout.
Definition: network.cpp:62
static ClientNetworkGameSocketHandler * my_client
This is us!
Subdirectory of save for autosaves.
Definition: fileio_type.h:111
NetworkRecvStatus Receive_SERVER_NEED_GAME_PASSWORD(Packet *p) override
Indication to the client that the server needs a game password.
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
Definition: core.h:22
A client (re)sets its company&#39;s password.
Definition: tcp_game.h:107
void Reset() override
Reset this filter to read from the beginning of the file.
assert_compile(NETWORK_SERVER_ID_LENGTH==16 *2+1)
Make sure the server ID length is the same as a md5 hash.
NetworkRecvStatus Receive_SERVER_MAP_DONE(Packet *p) override
Sends that all data of the map are sent to the client:
byte * buf
Buffer we&#39;re going to write to/read from.
std::vector< byte * > blocks
Buffer with blocks of allocated memory.
static const uint NETWORK_CHAT_LENGTH
The maximum length of a chat message, in bytes including &#39;\0&#39;.
Definition: config.h:50
We did not have the required NewGRFs.
Definition: core.h:25
Basic functions/variables used all over the place.
PacketSize size
The size of the whole packet for received packets.
Definition: packet.h:48
SaveOrLoadResult SaveOrLoad(const char *filename, SaveLoadOperation fop, DetailedFileType dft, Subdirectory sb, bool threaded)
Main Save or Load function where the high-level saveload functions are handled.
Definition: saveload.cpp:2729
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:40
uint last_packet
Time we received the last frame.
Definition: tcp_game.h:521
File is being loaded.
Definition: fileio_type.h:49
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:40
NetworkClientInfo * GetInfo() const
Gets the client info of this socket handler.
Definition: tcp_game.h:546
uint32 frame
the frame in which this packet is executed
ServerStatus status
Status of the connection with the server.
static NetworkRecvStatus SendRCon(const char *password, const char *command)
Send a console command.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
static NetworkRecvStatus SendMove(CompanyID company, const char *password)
Ask the server to move us.
A client reports an error to the server.
Definition: tcp_game.h:119
bool Recv_bool()
Read a boolean from the packet.
Definition: packet.cpp:208
uint32 _network_join_bytes
The number of bytes we already downloaded.
SaveLoadOperation
Operation performed on the file.
Definition: fileio_type.h:47
void NetworkClient_Connected()
Is called after a client is connected to the server.
uint16 performance
What was his performance last month?
Definition: network_gui.h:34
uint8 max_companies
maximum amount of companies
bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio)
Tell whether the client has team members where he/she can chat to.
The connection is &#39;just&#39; lost.
Definition: core.h:27
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
Network status window; Window numbers:
Definition: window_type.h:485
ClientID client_id
Client identifier.
Definition: tcp_game.h:517
NetworkRecvStatus Receive_SERVER_CLIENT_INFO(Packet *p) override
Send information about a client: uint32 ID of the client (always unique on a server.
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1165
The server is full.
Definition: core.h:30
static NetworkRecvStatus SendCompanyInformationQuery()
Query the server for company information.
The password of the game.
Definition: network_type.h:73
NetworkRecvStatus Receive_SERVER_RCON(Packet *p) override
Send the result of an issues RCon command back to the client: uint16 Colour code. ...
Network join status.
Definition: window_type.h:32
bool NetworkFindName(char *new_name, const char *last)
Check whether a name is unique, and otherwise try to make it unique.
uint8 Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:217
bool use_password
Is there a password.
Definition: network_gui.h:35
char client_name[NETWORK_CLIENT_NAME_LENGTH]
name of the player (as client)
GUISettings gui
settings related to the GUI
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:378
Client requests the actual map.
Definition: tcp_game.h:69
void SetInfo(NetworkClientInfo *info)
Sets the client info for this socket handler.
Definition: tcp_game.h:536
uint32 _frame_counter
The current frame.
Definition: network.cpp:68
The server has banned us.
Definition: core.h:31
uint64 Recv_uint64()
Read a 64 bits integer from the packet.
Definition: packet.cpp:263
void ClearErrorMessages()
Clear all errors from the queue.
Definition: error_gui.cpp:338
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:57
Randomizer _random
Random used in the game state calculations.
Definition: random_func.cpp:25
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:359
PacketReader()
Initialise everything.
CompanyID _network_join_as
Who would we like to join as.
CompanyMask _network_company_passworded
Bitmask of the password status of all companies.
Definition: network.cpp:80
void NetworkClientSetCompanyPassword(const char *password)
Set/Reset company password on the client side.
NetworkRecvStatus Receive_SERVER_CHECK_NEWGRFS(Packet *p) override
Sends information about all used GRFs to the client: uint8 Amount of GRFs (the following data is repe...
NetworkRecvStatus Receive_SERVER_NEED_COMPANY_PASSWORD(Packet *p) override
Indication to the client that the server needs a company password: uint32 Generation seed...
Client executed a command and sends it to the server.
Definition: tcp_game.h:91
virtual NetworkRecvStatus CloseConnection(bool error=true)
Close the current connection; for TCP this will be mostly equivalent to Close(), but for UDP it just ...
Definition: core.h:59
void NetworkClientSendRcon(const char *password, const char *command)
Send a remote console command.
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
Definition: openttd.cpp:112
The client telling the server it wants to join.
Definition: tcp_game.h:37
NetworkRecvStatus Receive_SERVER_ERROR_QUIT(Packet *p) override
Inform all clients that one client made an error and thus has quit/been disconnected: uint32 ID of th...
uint32 _frame_counter_server
The frame_counter of the server, if in network-mode.
Definition: network.cpp:66
uint16 num_station[NETWORK_VEH_END]
How many stations are there of this type?
Definition: network_type.h:59
static const uint NETWORK_SERVER_ID_LENGTH
The maximum length of the network id of the servers, in bytes including &#39;\0&#39;.
Definition: config.h:43
Network window; Window numbers:
Definition: window_type.h:466
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: depend.cpp:66
Maximum number of companies.
Definition: company_type.h:23
The client is active within in the game.
byte * bufe
End of the buffer we write to/read from.
SwitchMode _switch_mode
The next mainloop command.
Definition: gfx.cpp:46
const char * GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed)
Hash the given password using server ID and game seed.
Definition: network.cpp:182
const char * ReceiveCommand(Packet *p, CommandPacket *cp)
Receives a command from the network.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:299
static uint32 _password_game_seed
One bit of &#39;entropy&#39; used to generate a salt for the company passwords.
A client tells the server it is going to quit.
Definition: tcp_game.h:117
bool NetworkMaxCompaniesReached()
Check if max_companies has been reached on the server (local check only).
NetworkRecvStatus Receive_SERVER_BANNED(Packet *p) override
Notification that the client trying to join is banned.
bool _network_server
network-server is active
Definition: network.cpp:53
static NetworkRecvStatus SendQuit()
Tell the server we would like to quit.
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:45
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:318
static const TextColour CC_ERROR
Colour for error lines.
Definition: console_type.h:24
We are trying to join a server.
Everything we need to know about a command to be able to execute it.
static void Send()
Send the packets of this socket handler.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
static NetworkRecvStatus SendSetName(const char *name)
Tell the server that we like to change the name of the client.
uint32 grfid
GRF ID (defined by Action 0x08)
Definition: newgrf_config.h:83
We apparently send a malformed packet.
Definition: core.h:28
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:129
uint32 _network_join_bytes_total
The total number of bytes to download.
NetworkRecvStatus Receive_SERVER_QUIT(Packet *p) override
Notification that a client left the game: uint32 ID of the client.
The client is downloading the map.
Client said something that should be distributed.
Definition: tcp_game.h:95
static const uint NETWORK_NAME_LENGTH
The maximum length of the server name and map name, in bytes including &#39;\0&#39;.
Definition: config.h:40
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition: error.h:21
virtual void SendPacket(Packet *packet)
This function puts the packet in the send-queue and it is send as soon as possible.
Definition: tcp.cpp:61
static NetworkRecvStatus SendGetMap()
Request the map from the server.
Create a new company.
Definition: company_type.h:65
void Restore()
Restore the variable.
static NetworkRecvStatus SendCommand(const CommandPacket *cp)
Send a command to the server.
Servers always have this ID.
Definition: network_type.h:41
Money money
The amount of money the company has.
Definition: network_gui.h:32
void ReceiveGRFIdentifier(Packet *p, GRFIdentifier *grf)
Deserializes the GRFIdentifier (GRF ID and MD5 checksum) from the packet.
Definition: core.cpp:71
Last action was requesting game (server) password.
uint16 Recv_uint16()
Read a 16 bits integer from the packet.
Definition: packet.cpp:231
bool CanSendReceive()
Check whether this socket can send or receive something.
Definition: tcp.cpp:225
Base socket handler for all TCP sockets.
Definition: tcp_game.h:148
static uint32 BSWAP32(uint32 x)
Perform a 32 bits endianness bitswap on x.
Last action was requesting company password.
uint8 md5sum[16]
MD5 checksum of file to distinguish files with the same GRF ID (eg. newer version of GRF) ...
Definition: newgrf_config.h:84
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it&#39;s client-identifier.
Definition: network.cpp:119
static uint32 last_ack_frame
Last frame we performed an ack.
Only find Grfs matching md5sum.
uint32 state[2]
The state of the randomizer.
Definition: random_func.hpp:23
static const byte NETWORK_COMPANY_INFO_VERSION
What version of company info is this?
Definition: config.h:37
uint8 _network_join_waiting
The number of clients waiting in front of us.
static NetworkRecvStatus SendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data)
Send a chat-packet over the network.
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3246
bool my_cmd
did the command originate from "me"
NetworkRecvStatus Receive_SERVER_MAP_BEGIN(Packet *p) override
Sends that the server will begin with sending the map to the client: uint32 Current frame...
Date _date
Current date in days (day counter)
Definition: date.cpp:27
NetworkRecvStatus Receive_SERVER_MOVE(Packet *p) override
Move a client from one company into another: uint32 ID of the client.
Company view; Window numbers:
Definition: window_type.h:362
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:44
DetailedFileType
Kinds of files in each AbstractFileType.
Definition: fileio_type.h:28
uint32 _frame_counter_max
To where we may go with our clients.
Definition: network.cpp:67
NetworkRecvStatus Receive_SERVER_ERROR(Packet *p) override
The client made an error: uint8 Error code caused (see NetworkErrorCode).
static bool GameLoop()
Actual game loop for the client.
bool _network_first_time
Whether we have finished joining or not.
Definition: network.cpp:76
byte token
The token we need to send back to the server to prove we&#39;re the right client.
DestType
Destination of our chat messages.
Definition: network_type.h:78
Money income
How much did the company earned last year.
Definition: network_gui.h:33
static char _password_server_id[NETWORK_SERVER_ID_LENGTH]
The other bit of &#39;entropy&#39; used to generate a salt for the company passwords.
NetworkAction
Actions that can be used for NetworkTextMessage.
Definition: network_type.h:85
NetworkRecvStatus Receive_SERVER_MAP_SIZE(Packet *p) override
Sends the size of the map to the client.
NetworkRecvStatus Receive_SERVER_WAIT(Packet *p) override
Notification that another client is currently receiving the map: uint8 Number of clients waiting in f...
void Recv_string(char *buffer, size_t size, StringValidationSettings settings=SVS_REPLACE_WITH_QUESTION_MARK)
Reads a string till it finds a &#39;\0&#39; in the stream.
Definition: packet.cpp:286
Request information about all companies.
Definition: tcp_game.h:41
bool autosave_on_network_disconnect
save an autosave when you get disconnected from a network game with an error?
NetworkCompanyInfo * GetLobbyCompanyInfo(CompanyID company)
Get the company information of a given company to fill for the lobby.
Client tells the server that it received the whole map.
Definition: tcp_game.h:75
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:199