network_server.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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/>.
00008  */
00009 
00012 #ifdef ENABLE_NETWORK
00013 
00014 #include "../stdafx.h"
00015 #include "../strings_func.h"
00016 #include "../date_func.h"
00017 #include "network_admin.h"
00018 #include "network_server.h"
00019 #include "network_udp.h"
00020 #include "network_base.h"
00021 #include "../console_func.h"
00022 #include "../company_base.h"
00023 #include "../command_func.h"
00024 #include "../saveload/saveload.h"
00025 #include "../saveload/saveload_filter.h"
00026 #include "../station_base.h"
00027 #include "../genworld.h"
00028 #include "../company_func.h"
00029 #include "../company_gui.h"
00030 #include "../roadveh.h"
00031 #include "../order_backup.h"
00032 #include "../core/pool_func.hpp"
00033 #include "../core/random_func.hpp"
00034 #include "../viewport_func.h"
00035 #include "../rev.h"
00036 
00037 
00038 /* This file handles all the server-commands */
00039 
00040 DECLARE_POSTFIX_INCREMENT(ClientID)
00042 static ClientID _network_client_id = CLIENT_ID_FIRST;
00043 
00045 assert_compile(MAX_CLIENT_SLOTS > MAX_CLIENTS);
00047 assert_compile(NetworkClientSocketPool::MAX_SIZE == MAX_CLIENT_SLOTS);
00048 
00050 NetworkClientSocketPool _networkclientsocket_pool("NetworkClientSocket");
00051 INSTANTIATE_POOL_METHODS(NetworkClientSocket)
00052 
00054 template SocketList TCPListenHandler<ServerNetworkGameSocketHandler, PACKET_SERVER_FULL, PACKET_SERVER_BANNED>::sockets;
00055 
00057 struct PacketWriter : SaveFilter {
00058   ServerNetworkGameSocketHandler *cs; 
00059   Packet *current;                    
00060   size_t total_size;                  
00061 
00066   PacketWriter(ServerNetworkGameSocketHandler *cs) : SaveFilter(NULL), cs(cs), current(NULL), total_size(0)
00067   {
00068     this->cs->savegame_mutex = ThreadMutex::New();
00069   }
00070 
00072   ~PacketWriter()
00073   {
00074     /* Prevent double frees. */
00075     if (this->cs != NULL) {
00076       if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->BeginCritical();
00077       this->cs->savegame = NULL;
00078       if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->EndCritical();
00079 
00080       delete this->cs->savegame_mutex;
00081       this->cs->savegame_mutex = NULL;
00082     }
00083 
00084     delete this->current;
00085   }
00086 
00088   void AppendQueue()
00089   {
00090     if (this->current == NULL) return;
00091 
00092     Packet **p = &this->cs->savegame_packets;
00093     while (*p != NULL) {
00094       p = &(*p)->next;
00095     }
00096     *p = this->current;
00097 
00098     this->current = NULL;
00099   }
00100 
00101   /* virtual */ void Write(byte *buf, size_t size)
00102   {
00103     /* We want to abort the saving when the socket is closed. */
00104     if (this->cs == NULL) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
00105 
00106     if (this->current == NULL) this->current = new Packet(PACKET_SERVER_MAP_DATA);
00107 
00108     if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->BeginCritical();
00109 
00110     byte *bufe = buf + size;
00111     while (buf != bufe) {
00112       size_t to_write = min(SEND_MTU - this->current->size, bufe - buf);
00113       memcpy(this->current->buffer + this->current->size, buf, to_write);
00114       this->current->size += (PacketSize)to_write;
00115       buf += to_write;
00116 
00117       if (this->current->size == SEND_MTU) {
00118         this->AppendQueue();
00119         if (buf != bufe) this->current = new Packet(PACKET_SERVER_MAP_DATA);
00120       }
00121     }
00122 
00123     if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->EndCritical();
00124 
00125     this->total_size += size;
00126   }
00127 
00128   /* virtual */ void Finish()
00129   {
00130     /* We want to abort the saving when the socket is closed. */
00131     if (this->cs == NULL) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
00132 
00133     if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->BeginCritical();
00134 
00135     /* Make sure the last packet is flushed. */
00136     this->AppendQueue();
00137 
00138     /* Add a packet stating that this is the end to the queue. */
00139     this->current = new Packet(PACKET_SERVER_MAP_DONE);
00140     this->AppendQueue();
00141 
00142     /* Fast-track the size to the client. */
00143     Packet *p = new Packet(PACKET_SERVER_MAP_SIZE);
00144     p->Send_uint32((uint32)this->total_size);
00145     this->cs->NetworkTCPSocketHandler::SendPacket(p);
00146 
00147     if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->EndCritical();
00148   }
00149 };
00150 
00151 
00156 ServerNetworkGameSocketHandler::ServerNetworkGameSocketHandler(SOCKET s) : NetworkGameSocketHandler(s)
00157 {
00158   this->status = STATUS_INACTIVE;
00159   this->client_id = _network_client_id++;
00160   this->receive_limit = _settings_client.network.bytes_per_frame_burst;
00161 
00162   /* The Socket and Info pools need to be the same in size. After all,
00163    * each Socket will be associated with at most one Info object. As
00164    * such if the Socket was allocated the Info object can as well. */
00165   assert_compile(NetworkClientSocketPool::MAX_SIZE == NetworkClientInfoPool::MAX_SIZE);
00166 }
00167 
00171 ServerNetworkGameSocketHandler::~ServerNetworkGameSocketHandler()
00172 {
00173   if (_redirect_console_to_client == this->client_id) _redirect_console_to_client = INVALID_CLIENT_ID;
00174   OrderBackup::ResetUser(this->client_id);
00175 
00176   if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical();
00177   if (this->savegame != NULL) this->savegame->cs = NULL;
00178   if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical();
00179 
00180   /* Make sure the saving is completely cancelled.
00181    * Yes, we need to handle the save finish as well
00182    * as the next connection in this "loop" might
00183    * just be requesting the map and such. */
00184   WaitTillSaved();
00185   ProcessAsyncSaveFinish();
00186 
00187   while (this->savegame_packets != NULL) {
00188     Packet *p = this->savegame_packets->next;
00189     delete this->savegame_packets;
00190     this->savegame_packets = p;
00191   }
00192 
00193   delete this->savegame_mutex;
00194 }
00195 
00196 Packet *ServerNetworkGameSocketHandler::ReceivePacket()
00197 {
00198   /* Only allow receiving when we have some buffer free; this value
00199    * can go negative, but eventually it will become positive again. */
00200   if (this->receive_limit <= 0) return NULL;
00201 
00202   /* We can receive a packet, so try that and if needed account for
00203    * the amount of received data. */
00204   Packet *p = this->NetworkTCPSocketHandler::ReceivePacket();
00205   if (p != NULL) this->receive_limit -= p->size;
00206   return p;
00207 }
00208 
00209 void ServerNetworkGameSocketHandler::SendPacket(Packet *packet)
00210 {
00211   if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical();
00212   this->NetworkTCPSocketHandler::SendPacket(packet);
00213   if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical();
00214 }
00215 
00216 NetworkRecvStatus ServerNetworkGameSocketHandler::CloseConnection(NetworkRecvStatus status)
00217 {
00218   assert(status != NETWORK_RECV_STATUS_OKAY);
00219   /*
00220    * Sending a message just before leaving the game calls cs->SendPackets.
00221    * This might invoke this function, which means that when we close the
00222    * connection after cs->SendPackets we will close an already closed
00223    * connection. This handles that case gracefully without having to make
00224    * that code any more complex or more aware of the validity of the socket.
00225    */
00226   if (this->sock == INVALID_SOCKET) return status;
00227 
00228   if (status != NETWORK_RECV_STATUS_CONN_LOST && !this->HasClientQuit() && this->status >= STATUS_AUTHORIZED) {
00229     /* We did not receive a leave message from this client... */
00230     char client_name[NETWORK_CLIENT_NAME_LENGTH];
00231     NetworkClientSocket *new_cs;
00232 
00233     this->GetClientName(client_name, sizeof(client_name));
00234 
00235     NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST);
00236 
00237     /* Inform other clients of this... strange leaving ;) */
00238     FOR_ALL_CLIENT_SOCKETS(new_cs) {
00239       if (new_cs->status > STATUS_AUTHORIZED && this != new_cs) {
00240         new_cs->SendErrorQuit(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
00241       }
00242     }
00243   }
00244 
00245   NetworkAdminClientError(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
00246   DEBUG(net, 1, "Closed client connection %d", this->client_id);
00247 
00248   /* We just lost one client :( */
00249   if (this->status >= STATUS_AUTHORIZED) _network_game_info.clients_on--;
00250   extern byte _network_clients_connected;
00251   _network_clients_connected--;
00252 
00253   DeleteWindowById(WC_CLIENT_LIST_POPUP, this->client_id);
00254   SetWindowDirty(WC_CLIENT_LIST, 0);
00255 
00256   this->SendPackets(true);
00257 
00258   delete this->GetInfo();
00259   delete this;
00260 
00261   return status;
00262 }
00263 
00268 /* static */ bool ServerNetworkGameSocketHandler::AllowConnection()
00269 {
00270   extern byte _network_clients_connected;
00271   bool accept = _network_clients_connected < MAX_CLIENTS && _network_game_info.clients_on < _settings_client.network.max_clients;
00272 
00273   /* We can't go over the MAX_CLIENTS limit here. However, the
00274    * pool must have place for all clients and ourself. */
00275   assert_compile(NetworkClientSocketPool::MAX_SIZE == MAX_CLIENTS + 1);
00276   assert(!accept || ServerNetworkGameSocketHandler::CanAllocateItem());
00277   return accept;
00278 }
00279 
00281 /* static */ void ServerNetworkGameSocketHandler::Send()
00282 {
00283   NetworkClientSocket *cs;
00284   FOR_ALL_CLIENT_SOCKETS(cs) {
00285     if (cs->writable) {
00286       if (cs->SendPackets() != SPS_CLOSED && cs->status == STATUS_MAP) {
00287         /* This client is in the middle of a map-send, call the function for that */
00288         cs->SendMap();
00289       }
00290     }
00291   }
00292 }
00293 
00294 static void NetworkHandleCommandQueue(NetworkClientSocket *cs);
00295 
00296 /***********
00297  * Sending functions
00298  *   DEF_SERVER_SEND_COMMAND has parameter: NetworkClientSocket *cs
00299  ************/
00300 
00305 NetworkRecvStatus ServerNetworkGameSocketHandler::SendClientInfo(NetworkClientInfo *ci)
00306 {
00307   if (ci->client_id != INVALID_CLIENT_ID) {
00308     Packet *p = new Packet(PACKET_SERVER_CLIENT_INFO);
00309     p->Send_uint32(ci->client_id);
00310     p->Send_uint8 (ci->client_playas);
00311     p->Send_string(ci->client_name);
00312 
00313     this->SendPacket(p);
00314   }
00315   return NETWORK_RECV_STATUS_OKAY;
00316 }
00317 
00319 NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo()
00320 {
00321   /* Fetch the latest version of the stats */
00322   NetworkCompanyStats company_stats[MAX_COMPANIES];
00323   NetworkPopulateCompanyStats(company_stats);
00324 
00325   /* Make a list of all clients per company */
00326   char clients[MAX_COMPANIES][NETWORK_CLIENTS_LENGTH];
00327   NetworkClientSocket *csi;
00328   memset(clients, 0, sizeof(clients));
00329 
00330   /* Add the local player (if not dedicated) */
00331   const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
00332   if (ci != NULL && Company::IsValidID(ci->client_playas)) {
00333     strecpy(clients[ci->client_playas], ci->client_name, lastof(clients[ci->client_playas]));
00334   }
00335 
00336   FOR_ALL_CLIENT_SOCKETS(csi) {
00337     char client_name[NETWORK_CLIENT_NAME_LENGTH];
00338 
00339     ((ServerNetworkGameSocketHandler*)csi)->GetClientName(client_name, sizeof(client_name));
00340 
00341     ci = csi->GetInfo();
00342     if (ci != NULL && Company::IsValidID(ci->client_playas)) {
00343       if (!StrEmpty(clients[ci->client_playas])) {
00344         strecat(clients[ci->client_playas], ", ", lastof(clients[ci->client_playas]));
00345       }
00346 
00347       strecat(clients[ci->client_playas], client_name, lastof(clients[ci->client_playas]));
00348     }
00349   }
00350 
00351   /* Now send the data */
00352 
00353   Company *company;
00354   Packet *p;
00355 
00356   FOR_ALL_COMPANIES(company) {
00357     p = new Packet(PACKET_SERVER_COMPANY_INFO);
00358 
00359     p->Send_uint8 (NETWORK_COMPANY_INFO_VERSION);
00360     p->Send_bool  (true);
00361     this->SendCompanyInformation(p, company, &company_stats[company->index]);
00362 
00363     if (StrEmpty(clients[company->index])) {
00364       p->Send_string("<none>");
00365     } else {
00366       p->Send_string(clients[company->index]);
00367     }
00368 
00369     this->SendPacket(p);
00370   }
00371 
00372   p = new Packet(PACKET_SERVER_COMPANY_INFO);
00373 
00374   p->Send_uint8 (NETWORK_COMPANY_INFO_VERSION);
00375   p->Send_bool  (false);
00376 
00377   this->SendPacket(p);
00378   return NETWORK_RECV_STATUS_OKAY;
00379 }
00380 
00385 NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode error)
00386 {
00387   char str[100];
00388   Packet *p = new Packet(PACKET_SERVER_ERROR);
00389 
00390   p->Send_uint8(error);
00391   this->SendPacket(p);
00392 
00393   StringID strid = GetNetworkErrorMsg(error);
00394   GetString(str, strid, lastof(str));
00395 
00396   /* Only send when the current client was in game */
00397   if (this->status > STATUS_AUTHORIZED) {
00398     NetworkClientSocket *new_cs;
00399     char client_name[NETWORK_CLIENT_NAME_LENGTH];
00400 
00401     this->GetClientName(client_name, sizeof(client_name));
00402 
00403     DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
00404 
00405     NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, strid);
00406 
00407     FOR_ALL_CLIENT_SOCKETS(new_cs) {
00408       if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
00409         /* Some errors we filter to a more general error. Clients don't have to know the real
00410          *  reason a joining failed. */
00411         if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION) {
00412           error = NETWORK_ERROR_ILLEGAL_PACKET;
00413         }
00414         new_cs->SendErrorQuit(this->client_id, error);
00415       }
00416     }
00417 
00418     NetworkAdminClientError(this->client_id, error);
00419   } else {
00420     DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", this->client_id, str);
00421   }
00422 
00423   /* The client made a mistake, so drop his connection now! */
00424   return this->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR);
00425 }
00426 
00428 NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGRFCheck()
00429 {
00430   Packet *p = new Packet(PACKET_SERVER_CHECK_NEWGRFS);
00431   const GRFConfig *c;
00432   uint grf_count = 0;
00433 
00434   for (c = _grfconfig; c != NULL; c = c->next) {
00435     if (!HasBit(c->flags, GCF_STATIC)) grf_count++;
00436   }
00437 
00438   p->Send_uint8 (grf_count);
00439   for (c = _grfconfig; c != NULL; c = c->next) {
00440     if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident);
00441   }
00442 
00443   this->SendPacket(p);
00444   return NETWORK_RECV_STATUS_OKAY;
00445 }
00446 
00448 NetworkRecvStatus ServerNetworkGameSocketHandler::SendNeedGamePassword()
00449 {
00450   /* Invalid packet when status is STATUS_AUTH_GAME or higher */
00451   if (this->status >= STATUS_AUTH_GAME) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
00452 
00453   this->status = STATUS_AUTH_GAME;
00454   /* Reset 'lag' counters */
00455   this->last_frame = this->last_frame_server = _frame_counter;
00456 
00457   Packet *p = new Packet(PACKET_SERVER_NEED_GAME_PASSWORD);
00458   this->SendPacket(p);
00459   return NETWORK_RECV_STATUS_OKAY;
00460 }
00461 
00463 NetworkRecvStatus ServerNetworkGameSocketHandler::SendNeedCompanyPassword()
00464 {
00465   /* Invalid packet when status is STATUS_AUTH_COMPANY or higher */
00466   if (this->status >= STATUS_AUTH_COMPANY) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
00467 
00468   this->status = STATUS_AUTH_COMPANY;
00469   /* Reset 'lag' counters */
00470   this->last_frame = this->last_frame_server = _frame_counter;
00471 
00472   Packet *p = new Packet(PACKET_SERVER_NEED_COMPANY_PASSWORD);
00473   p->Send_uint32(_settings_game.game_creation.generation_seed);
00474   p->Send_string(_settings_client.network.network_id);
00475   this->SendPacket(p);
00476   return NETWORK_RECV_STATUS_OKAY;
00477 }
00478 
00480 NetworkRecvStatus ServerNetworkGameSocketHandler::SendWelcome()
00481 {
00482   Packet *p;
00483   NetworkClientSocket *new_cs;
00484 
00485   /* Invalid packet when status is AUTH or higher */
00486   if (this->status >= STATUS_AUTHORIZED) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
00487 
00488   this->status = STATUS_AUTHORIZED;
00489   /* Reset 'lag' counters */
00490   this->last_frame = this->last_frame_server = _frame_counter;
00491 
00492   _network_game_info.clients_on++;
00493 
00494   p = new Packet(PACKET_SERVER_WELCOME);
00495   p->Send_uint32(this->client_id);
00496   p->Send_uint32(_settings_game.game_creation.generation_seed);
00497   p->Send_string(_settings_client.network.network_id);
00498   this->SendPacket(p);
00499 
00500   /* Transmit info about all the active clients */
00501   FOR_ALL_CLIENT_SOCKETS(new_cs) {
00502     if (new_cs != this && new_cs->status > STATUS_AUTHORIZED) {
00503       this->SendClientInfo(new_cs->GetInfo());
00504     }
00505   }
00506   /* Also send the info of the server */
00507   return this->SendClientInfo(NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
00508 }
00509 
00511 NetworkRecvStatus ServerNetworkGameSocketHandler::SendWait()
00512 {
00513   int waiting = 0;
00514   NetworkClientSocket *new_cs;
00515   Packet *p;
00516 
00517   /* Count how many clients are waiting in the queue, in front of you! */
00518   FOR_ALL_CLIENT_SOCKETS(new_cs) {
00519     if (new_cs->status != STATUS_MAP_WAIT) continue;
00520     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++;
00521   }
00522 
00523   p = new Packet(PACKET_SERVER_WAIT);
00524   p->Send_uint8(waiting);
00525   this->SendPacket(p);
00526   return NETWORK_RECV_STATUS_OKAY;
00527 }
00528 
00530 NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap()
00531 {
00532   static uint sent_packets; // How many packets we did send succecfully last time
00533 
00534   if (this->status < STATUS_AUTHORIZED) {
00535     /* Illegal call, return error and ignore the packet */
00536     return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
00537   }
00538 
00539   if (this->status == STATUS_AUTHORIZED) {
00540     this->savegame = new PacketWriter(this);
00541 
00542     /* Now send the _frame_counter and how many packets are coming */
00543     Packet *p = new Packet(PACKET_SERVER_MAP_BEGIN);
00544     p->Send_uint32(_frame_counter);
00545     this->SendPacket(p);
00546 
00547     NetworkSyncCommandQueue(this);
00548     this->status = STATUS_MAP;
00549     /* Mark the start of download */
00550     this->last_frame = _frame_counter;
00551     this->last_frame_server = _frame_counter;
00552 
00553     sent_packets = 4; // We start with trying 4 packets
00554 
00555     /* Make a dump of the current game */
00556     if (SaveWithFilter(this->savegame, true) != SL_OK) usererror("network savedump failed");
00557   }
00558 
00559   if (this->status == STATUS_MAP) {
00560     if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical();
00561 
00562     bool last_packet = false;
00563 
00564     for (uint i = 0; i < sent_packets && this->savegame_packets != NULL; i++) {
00565       Packet *p = this->savegame_packets;
00566       last_packet = p->buffer[2] == PACKET_SERVER_MAP_DONE;
00567 
00568       /* Remove the packet from the savegame queue and put it in the real queue. */
00569       this->savegame_packets = p->next;
00570       p->next = NULL;
00571       this->NetworkTCPSocketHandler::SendPacket(p);
00572 
00573       if (last_packet) {
00574         /* There is no more data, so break the for */
00575         break;
00576       }
00577     }
00578 
00579     if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical();
00580 
00581     if (last_packet) {
00582       /* Done reading, make sure saving is done as well */
00583       WaitTillSaved();
00584 
00585       /* Set the status to DONE_MAP, no we will wait for the client
00586        *  to send it is ready (maybe that happens like never ;)) */
00587       this->status = STATUS_DONE_MAP;
00588 
00589       /* Find the best candidate for joining, i.e. the first joiner. */
00590       NetworkClientSocket *new_cs;
00591       NetworkClientSocket *best = NULL;
00592       FOR_ALL_CLIENT_SOCKETS(new_cs) {
00593         if (new_cs->status == STATUS_MAP_WAIT) {
00594           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)) {
00595             best = new_cs;
00596           }
00597         }
00598       }
00599 
00600       /* Is there someone else to join? */
00601       if (best != NULL) {
00602         /* Let the first start joining. */
00603         best->status = STATUS_AUTHORIZED;
00604         best->SendMap();
00605 
00606         /* And update the rest. */
00607         FOR_ALL_CLIENT_SOCKETS(new_cs) {
00608           if (new_cs->status == STATUS_MAP_WAIT) new_cs->SendWait();
00609         }
00610       }
00611     }
00612 
00613     switch (this->SendPackets()) {
00614       case SPS_CLOSED:
00615         return NETWORK_RECV_STATUS_CONN_LOST;
00616 
00617       case SPS_ALL_SENT:
00618         /* All are sent, increase the sent_packets */
00619         if (this->savegame_packets != NULL) sent_packets *= 2;
00620         break;
00621 
00622       case SPS_PARTLY_SENT:
00623         /* Only a part is sent; leave the transmission state. */
00624         break;
00625 
00626       case SPS_NONE_SENT:
00627         /* Not everything is sent, decrease the sent_packets */
00628         if (sent_packets > 1) sent_packets /= 2;
00629         break;
00630     }
00631   }
00632   return NETWORK_RECV_STATUS_OKAY;
00633 }
00634 
00639 NetworkRecvStatus ServerNetworkGameSocketHandler::SendJoin(ClientID client_id)
00640 {
00641   Packet *p = new Packet(PACKET_SERVER_JOIN);
00642 
00643   p->Send_uint32(client_id);
00644 
00645   this->SendPacket(p);
00646   return NETWORK_RECV_STATUS_OKAY;
00647 }
00648 
00650 NetworkRecvStatus ServerNetworkGameSocketHandler::SendFrame()
00651 {
00652   Packet *p = new Packet(PACKET_SERVER_FRAME);
00653   p->Send_uint32(_frame_counter);
00654   p->Send_uint32(_frame_counter_max);
00655 #ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
00656   p->Send_uint32(_sync_seed_1);
00657 #ifdef NETWORK_SEND_DOUBLE_SEED
00658   p->Send_uint32(_sync_seed_2);
00659 #endif
00660 #endif
00661 
00662   /* If token equals 0, we need to make a new token and send that. */
00663   if (this->last_token == 0) {
00664     this->last_token = InteractiveRandomRange(UINT8_MAX - 1) + 1;
00665     p->Send_uint8(this->last_token);
00666   }
00667 
00668   this->SendPacket(p);
00669   return NETWORK_RECV_STATUS_OKAY;
00670 }
00671 
00673 NetworkRecvStatus ServerNetworkGameSocketHandler::SendSync()
00674 {
00675   Packet *p = new Packet(PACKET_SERVER_SYNC);
00676   p->Send_uint32(_frame_counter);
00677   p->Send_uint32(_sync_seed_1);
00678 
00679 #ifdef NETWORK_SEND_DOUBLE_SEED
00680   p->Send_uint32(_sync_seed_2);
00681 #endif
00682   this->SendPacket(p);
00683   return NETWORK_RECV_STATUS_OKAY;
00684 }
00685 
00690 NetworkRecvStatus ServerNetworkGameSocketHandler::SendCommand(const CommandPacket *cp)
00691 {
00692   Packet *p = new Packet(PACKET_SERVER_COMMAND);
00693 
00694   this->NetworkGameSocketHandler::SendCommand(p, cp);
00695   p->Send_uint32(cp->frame);
00696   p->Send_bool  (cp->my_cmd);
00697 
00698   this->SendPacket(p);
00699   return NETWORK_RECV_STATUS_OKAY;
00700 }
00701 
00710 NetworkRecvStatus ServerNetworkGameSocketHandler::SendChat(NetworkAction action, ClientID client_id, bool self_send, const char *msg, int64 data)
00711 {
00712   if (this->status < STATUS_PRE_ACTIVE) return NETWORK_RECV_STATUS_OKAY;
00713 
00714   Packet *p = new Packet(PACKET_SERVER_CHAT);
00715 
00716   p->Send_uint8 (action);
00717   p->Send_uint32(client_id);
00718   p->Send_bool  (self_send);
00719   p->Send_string(msg);
00720   p->Send_uint64(data);
00721 
00722   this->SendPacket(p);
00723   return NETWORK_RECV_STATUS_OKAY;
00724 }
00725 
00731 NetworkRecvStatus ServerNetworkGameSocketHandler::SendErrorQuit(ClientID client_id, NetworkErrorCode errorno)
00732 {
00733   Packet *p = new Packet(PACKET_SERVER_ERROR_QUIT);
00734 
00735   p->Send_uint32(client_id);
00736   p->Send_uint8 (errorno);
00737 
00738   this->SendPacket(p);
00739   return NETWORK_RECV_STATUS_OKAY;
00740 }
00741 
00746 NetworkRecvStatus ServerNetworkGameSocketHandler::SendQuit(ClientID client_id)
00747 {
00748   Packet *p = new Packet(PACKET_SERVER_QUIT);
00749 
00750   p->Send_uint32(client_id);
00751 
00752   this->SendPacket(p);
00753   return NETWORK_RECV_STATUS_OKAY;
00754 }
00755 
00757 NetworkRecvStatus ServerNetworkGameSocketHandler::SendShutdown()
00758 {
00759   Packet *p = new Packet(PACKET_SERVER_SHUTDOWN);
00760   this->SendPacket(p);
00761   return NETWORK_RECV_STATUS_OKAY;
00762 }
00763 
00765 NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGame()
00766 {
00767   Packet *p = new Packet(PACKET_SERVER_NEWGAME);
00768   this->SendPacket(p);
00769   return NETWORK_RECV_STATUS_OKAY;
00770 }
00771 
00777 NetworkRecvStatus ServerNetworkGameSocketHandler::SendRConResult(uint16 colour, const char *command)
00778 {
00779   Packet *p = new Packet(PACKET_SERVER_RCON);
00780 
00781   p->Send_uint16(colour);
00782   p->Send_string(command);
00783   this->SendPacket(p);
00784   return NETWORK_RECV_STATUS_OKAY;
00785 }
00786 
00792 NetworkRecvStatus ServerNetworkGameSocketHandler::SendMove(ClientID client_id, CompanyID company_id)
00793 {
00794   Packet *p = new Packet(PACKET_SERVER_MOVE);
00795 
00796   p->Send_uint32(client_id);
00797   p->Send_uint8(company_id);
00798   this->SendPacket(p);
00799   return NETWORK_RECV_STATUS_OKAY;
00800 }
00801 
00803 NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyUpdate()
00804 {
00805   Packet *p = new Packet(PACKET_SERVER_COMPANY_UPDATE);
00806 
00807   p->Send_uint16(_network_company_passworded);
00808   this->SendPacket(p);
00809   return NETWORK_RECV_STATUS_OKAY;
00810 }
00811 
00813 NetworkRecvStatus ServerNetworkGameSocketHandler::SendConfigUpdate()
00814 {
00815   Packet *p = new Packet(PACKET_SERVER_CONFIG_UPDATE);
00816 
00817   p->Send_uint8(_settings_client.network.max_companies);
00818   p->Send_uint8(_settings_client.network.max_spectators);
00819   this->SendPacket(p);
00820   return NETWORK_RECV_STATUS_OKAY;
00821 }
00822 
00823 /***********
00824  * Receiving functions
00825  *   DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientSocket *cs, Packet *p
00826  ************/
00827 
00828 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_INFO(Packet *p)
00829 {
00830   return this->SendCompanyInfo();
00831 }
00832 
00833 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_NEWGRFS_CHECKED(Packet *p)
00834 {
00835   if (this->status != STATUS_NEWGRFS_CHECK) {
00836     /* Illegal call, return error and ignore the packet */
00837     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00838   }
00839 
00840   NetworkClientInfo *ci = this->GetInfo();
00841 
00842   /* We now want a password from the client else we do not allow him in! */
00843   if (!StrEmpty(_settings_client.network.server_password)) {
00844     return this->SendNeedGamePassword();
00845   }
00846 
00847   if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) {
00848     return this->SendNeedCompanyPassword();
00849   }
00850 
00851   return this->SendWelcome();
00852 }
00853 
00854 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p)
00855 {
00856   if (this->status != STATUS_INACTIVE) {
00857     /* Illegal call, return error and ignore the packet */
00858     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00859   }
00860 
00861   char name[NETWORK_CLIENT_NAME_LENGTH];
00862   CompanyID playas;
00863   NetworkLanguage client_lang;
00864   char client_revision[NETWORK_REVISION_LENGTH];
00865 
00866   p->Recv_string(client_revision, sizeof(client_revision));
00867   uint32 newgrf_version = p->Recv_uint32();
00868 
00869   /* Check if the client has revision control enabled */
00870   if (!IsNetworkCompatibleVersion(client_revision) || _openttd_newgrf_version != newgrf_version) {
00871     /* Different revisions!! */
00872     return this->SendError(NETWORK_ERROR_WRONG_REVISION);
00873   }
00874 
00875   p->Recv_string(name, sizeof(name));
00876   playas = (Owner)p->Recv_uint8();
00877   client_lang = (NetworkLanguage)p->Recv_uint8();
00878 
00879   if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
00880 
00881   /* join another company does not affect these values */
00882   switch (playas) {
00883     case COMPANY_NEW_COMPANY: // New company
00884       if (Company::GetNumItems() >= _settings_client.network.max_companies) {
00885         return this->SendError(NETWORK_ERROR_FULL);
00886       }
00887       break;
00888     case COMPANY_SPECTATOR: // Spectator
00889       if (NetworkSpectatorCount() >= _settings_client.network.max_spectators) {
00890         return this->SendError(NETWORK_ERROR_FULL);
00891       }
00892       break;
00893     default: // Join another company (companies 1-8 (index 0-7))
00894       if (!Company::IsValidHumanID(playas)) {
00895         return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
00896       }
00897       break;
00898   }
00899 
00900   /* We need a valid name.. make it Player */
00901   if (StrEmpty(name)) strecpy(name, "Player", lastof(name));
00902 
00903   if (!NetworkFindName(name)) { // Change name if duplicate
00904     /* We could not create a name for this client */
00905     return this->SendError(NETWORK_ERROR_NAME_IN_USE);
00906   }
00907 
00908   assert(NetworkClientInfo::CanAllocateItem());
00909   NetworkClientInfo *ci = new NetworkClientInfo(this->client_id);
00910   this->SetInfo(ci);
00911   ci->join_date = _date;
00912   strecpy(ci->client_name, name, lastof(ci->client_name));
00913   ci->client_playas = playas;
00914   ci->client_lang = client_lang;
00915   DEBUG(desync, 1, "client: %08x; %02x; %02x; %04x", _date, _date_fract, (int)ci->client_playas, ci->index);
00916 
00917   /* Make sure companies to which people try to join are not autocleaned */
00918   if (Company::IsValidID(playas)) _network_company_states[playas].months_empty = 0;
00919 
00920   this->status = STATUS_NEWGRFS_CHECK;
00921 
00922   if (_grfconfig == NULL) {
00923     /* Behave as if we received PACKET_CLIENT_NEWGRFS_CHECKED */
00924     return this->Receive_CLIENT_NEWGRFS_CHECKED(NULL);
00925   }
00926 
00927   return this->SendNewGRFCheck();
00928 }
00929 
00930 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GAME_PASSWORD(Packet *p)
00931 {
00932   if (this->status != STATUS_AUTH_GAME) {
00933     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00934   }
00935 
00936   char password[NETWORK_PASSWORD_LENGTH];
00937   p->Recv_string(password, sizeof(password));
00938 
00939   /* Check game password. Allow joining if we cleared the password meanwhile */
00940   if (!StrEmpty(_settings_client.network.server_password) &&
00941       strcmp(password, _settings_client.network.server_password) != 0) {
00942     /* Password is invalid */
00943     return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
00944   }
00945 
00946   const NetworkClientInfo *ci = this->GetInfo();
00947   if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) {
00948     return this->SendNeedCompanyPassword();
00949   }
00950 
00951   /* Valid password, allow user */
00952   return this->SendWelcome();
00953 }
00954 
00955 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWORD(Packet *p)
00956 {
00957   if (this->status != STATUS_AUTH_COMPANY) {
00958     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00959   }
00960 
00961   char password[NETWORK_PASSWORD_LENGTH];
00962   p->Recv_string(password, sizeof(password));
00963 
00964   /* Check company password. Allow joining if we cleared the password meanwhile.
00965    * Also, check the company is still valid - client could be moved to spectators
00966    * in the middle of the authorization process */
00967   CompanyID playas = this->GetInfo()->client_playas;
00968   if (Company::IsValidID(playas) && !StrEmpty(_network_company_states[playas].password) &&
00969       strcmp(password, _network_company_states[playas].password) != 0) {
00970     /* Password is invalid */
00971     return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
00972   }
00973 
00974   return this->SendWelcome();
00975 }
00976 
00977 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GETMAP(Packet *p)
00978 {
00979   NetworkClientSocket *new_cs;
00980   /* The client was never joined.. so this is impossible, right?
00981    *  Ignore the packet, give the client a warning, and close his connection */
00982   if (this->status < STATUS_AUTHORIZED || this->HasClientQuit()) {
00983     return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
00984   }
00985 
00986   /* Check if someone else is receiving the map */
00987   FOR_ALL_CLIENT_SOCKETS(new_cs) {
00988     if (new_cs->status == STATUS_MAP) {
00989       /* Tell the new client to wait */
00990       this->status = STATUS_MAP_WAIT;
00991       return this->SendWait();
00992     }
00993   }
00994 
00995   /* We receive a request to upload the map.. give it to the client! */
00996   return this->SendMap();
00997 }
00998 
00999 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MAP_OK(Packet *p)
01000 {
01001   /* Client has the map, now start syncing */
01002   if (this->status == STATUS_DONE_MAP && !this->HasClientQuit()) {
01003     char client_name[NETWORK_CLIENT_NAME_LENGTH];
01004     NetworkClientSocket *new_cs;
01005 
01006     this->GetClientName(client_name, sizeof(client_name));
01007 
01008     NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, NULL, this->client_id);
01009 
01010     /* Mark the client as pre-active, and wait for an ACK
01011      *  so we know he is done loading and in sync with us */
01012     this->status = STATUS_PRE_ACTIVE;
01013     NetworkHandleCommandQueue(this);
01014     this->SendFrame();
01015     this->SendSync();
01016 
01017     /* This is the frame the client receives
01018      *  we need it later on to make sure the client is not too slow */
01019     this->last_frame = _frame_counter;
01020     this->last_frame_server = _frame_counter;
01021 
01022     FOR_ALL_CLIENT_SOCKETS(new_cs) {
01023       if (new_cs->status > STATUS_AUTHORIZED) {
01024         new_cs->SendClientInfo(this->GetInfo());
01025         new_cs->SendJoin(this->client_id);
01026       }
01027     }
01028 
01029     NetworkAdminClientInfo(this, true);
01030 
01031     /* also update the new client with our max values */
01032     this->SendConfigUpdate();
01033 
01034     /* quickly update the syncing client with company details */
01035     return this->SendCompanyUpdate();
01036   }
01037 
01038   /* Wrong status for this packet, give a warning to client, and close connection */
01039   return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01040 }
01041 
01046 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMMAND(Packet *p)
01047 {
01048   /* The client was never joined.. so this is impossible, right?
01049    *  Ignore the packet, give the client a warning, and close his connection */
01050   if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
01051     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01052   }
01053 
01054   if (this->incoming_queue.Count() >= _settings_client.network.max_commands_in_queue) {
01055     return this->SendError(NETWORK_ERROR_TOO_MANY_COMMANDS);
01056   }
01057 
01058   CommandPacket cp;
01059   const char *err = this->ReceiveCommand(p, &cp);
01060 
01061   if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
01062 
01063   NetworkClientInfo *ci = this->GetInfo();
01064 
01065   if (err != NULL) {
01066     IConsolePrintF(CC_ERROR, "WARNING: %s from client %d (IP: %s).", err, ci->client_id, this->GetClientIP());
01067     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01068   }
01069 
01070 
01071   if ((GetCommandFlags(cp.cmd) & CMD_SERVER) && ci->client_id != CLIENT_ID_SERVER) {
01072     IConsolePrintF(CC_ERROR, "WARNING: server only command from: client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
01073     return this->SendError(NETWORK_ERROR_KICKED);
01074   }
01075 
01076   if ((GetCommandFlags(cp.cmd) & CMD_SPECTATOR) == 0 && !Company::IsValidID(cp.company) && ci->client_id != CLIENT_ID_SERVER) {
01077     IConsolePrintF(CC_ERROR, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
01078     return this->SendError(NETWORK_ERROR_KICKED);
01079   }
01080 
01086   if (!(cp.cmd == CMD_COMPANY_CTRL && cp.p1 == 0 && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) {
01087     IConsolePrintF(CC_ERROR, "WARNING: client %d (IP: %s) tried to execute a command as company %d, kicking...",
01088                    ci->client_playas + 1, this->GetClientIP(), cp.company + 1);
01089     return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
01090   }
01091 
01092   if (cp.cmd == CMD_COMPANY_CTRL) {
01093     if (cp.p1 != 0 || cp.company != COMPANY_SPECTATOR) {
01094       return this->SendError(NETWORK_ERROR_CHEATER);
01095     }
01096 
01097     /* 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! */
01098     if (Company::GetNumItems() >= _settings_client.network.max_companies) {
01099       NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_CLIENT, ci->client_id, "cannot create new company, server full", CLIENT_ID_SERVER);
01100       return NETWORK_RECV_STATUS_OKAY;
01101     }
01102   }
01103 
01104   if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) cp.p2 = this->client_id;
01105 
01106   this->incoming_queue.Append(&cp);
01107   return NETWORK_RECV_STATUS_OKAY;
01108 }
01109 
01110 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet *p)
01111 {
01112   /* This packets means a client noticed an error and is reporting this
01113    *  to us. Display the error and report it to the other clients */
01114   NetworkClientSocket *new_cs;
01115   char str[100];
01116   char client_name[NETWORK_CLIENT_NAME_LENGTH];
01117   NetworkErrorCode errorno = (NetworkErrorCode)p->Recv_uint8();
01118 
01119   /* The client was never joined.. thank the client for the packet, but ignore it */
01120   if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
01121     return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
01122   }
01123 
01124   this->GetClientName(client_name, sizeof(client_name));
01125 
01126   StringID strid = GetNetworkErrorMsg(errorno);
01127   GetString(str, strid, lastof(str));
01128 
01129   DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
01130 
01131   NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, strid);
01132 
01133   FOR_ALL_CLIENT_SOCKETS(new_cs) {
01134     if (new_cs->status > STATUS_AUTHORIZED) {
01135       new_cs->SendErrorQuit(this->client_id, errorno);
01136     }
01137   }
01138 
01139   NetworkAdminClientError(this->client_id, errorno);
01140 
01141   return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
01142 }
01143 
01144 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_QUIT(Packet *p)
01145 {
01146   /* The client wants to leave. Display this and report it to the other
01147    *  clients. */
01148   NetworkClientSocket *new_cs;
01149   char client_name[NETWORK_CLIENT_NAME_LENGTH];
01150 
01151   /* The client was never joined.. thank the client for the packet, but ignore it */
01152   if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
01153     return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
01154   }
01155 
01156   this->GetClientName(client_name, sizeof(client_name));
01157 
01158   NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
01159 
01160   FOR_ALL_CLIENT_SOCKETS(new_cs) {
01161     if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
01162       new_cs->SendQuit(this->client_id);
01163     }
01164   }
01165 
01166   NetworkAdminClientQuit(this->client_id);
01167 
01168   return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
01169 }
01170 
01171 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ACK(Packet *p)
01172 {
01173   if (this->status < STATUS_AUTHORIZED) {
01174     /* Illegal call, return error and ignore the packet */
01175     return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
01176   }
01177 
01178   uint32 frame = p->Recv_uint32();
01179 
01180   /* The client is trying to catch up with the server */
01181   if (this->status == STATUS_PRE_ACTIVE) {
01182     /* The client is not yet catched up? */
01183     if (frame + DAY_TICKS < _frame_counter) return NETWORK_RECV_STATUS_OKAY;
01184 
01185     /* Now he is! Unpause the game */
01186     this->status = STATUS_ACTIVE;
01187     this->last_token_frame = _frame_counter;
01188 
01189     /* Execute script for, e.g. MOTD */
01190     IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
01191   }
01192 
01193   /* Get, and validate the token. */
01194   uint8 token = p->Recv_uint8();
01195   if (token == this->last_token) {
01196     /* We differentiate between last_token_frame and last_frame so the lag
01197      * test uses the actual lag of the client instead of the lag for getting
01198      * the token back and forth; after all, the token is only sent every
01199      * time we receive a PACKET_CLIENT_ACK, after which we will send a new
01200      * token to the client. If the lag would be one day, then we would not
01201      * be sending the new token soon enough for the new daily scheduled
01202      * PACKET_CLIENT_ACK. This would then register the lag of the client as
01203      * two days, even when it's only a single day. */
01204     this->last_token_frame = _frame_counter;
01205     /* Request a new token. */
01206     this->last_token = 0;
01207   }
01208 
01209   /* The client received the frame, make note of it */
01210   this->last_frame = frame;
01211   /* With those 2 values we can calculate the lag realtime */
01212   this->last_frame_server = _frame_counter;
01213   return NETWORK_RECV_STATUS_OKAY;
01214 }
01215 
01216 
01227 void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, ClientID from_id, int64 data, bool from_admin)
01228 {
01229   NetworkClientSocket *cs;
01230   const NetworkClientInfo *ci, *ci_own, *ci_to;
01231 
01232   switch (desttype) {
01233     case DESTTYPE_CLIENT:
01234       /* Are we sending to the server? */
01235       if ((ClientID)dest == CLIENT_ID_SERVER) {
01236         ci = NetworkClientInfo::GetByClientID(from_id);
01237         /* Display the text locally, and that is it */
01238         if (ci != NULL) {
01239           NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
01240 
01241           if (_settings_client.network.server_admin_chat) {
01242             NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
01243           }
01244         }
01245       } else {
01246         /* Else find the client to send the message to */
01247         FOR_ALL_CLIENT_SOCKETS(cs) {
01248           if (cs->client_id == (ClientID)dest) {
01249             cs->SendChat(action, from_id, false, msg, data);
01250             break;
01251           }
01252         }
01253       }
01254 
01255       /* Display the message locally (so you know you have sent it) */
01256       if (from_id != (ClientID)dest) {
01257         if (from_id == CLIENT_ID_SERVER) {
01258           ci = NetworkClientInfo::GetByClientID(from_id);
01259           ci_to = NetworkClientInfo::GetByClientID((ClientID)dest);
01260           if (ci != NULL && ci_to != NULL) {
01261             NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), true, ci_to->client_name, msg, data);
01262           }
01263         } else {
01264           FOR_ALL_CLIENT_SOCKETS(cs) {
01265             if (cs->client_id == from_id) {
01266               cs->SendChat(action, (ClientID)dest, true, msg, data);
01267               break;
01268             }
01269           }
01270         }
01271       }
01272       break;
01273     case DESTTYPE_TEAM: {
01274       /* If this is false, the message is already displayed on the client who sent it. */
01275       bool show_local = true;
01276       /* Find all clients that belong to this company */
01277       ci_to = NULL;
01278       FOR_ALL_CLIENT_SOCKETS(cs) {
01279         ci = cs->GetInfo();
01280         if (ci != NULL && ci->client_playas == (CompanyID)dest) {
01281           cs->SendChat(action, from_id, false, msg, data);
01282           if (cs->client_id == from_id) show_local = false;
01283           ci_to = ci; // Remember a client that is in the company for company-name
01284         }
01285       }
01286 
01287       /* if the server can read it, let the admin network read it, too. */
01288       if (_local_company == (CompanyID)dest && _settings_client.network.server_admin_chat) {
01289         NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
01290       }
01291 
01292       ci = NetworkClientInfo::GetByClientID(from_id);
01293       ci_own = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
01294       if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
01295         NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
01296         if (from_id == CLIENT_ID_SERVER) show_local = false;
01297         ci_to = ci_own;
01298       }
01299 
01300       /* There is no such client */
01301       if (ci_to == NULL) break;
01302 
01303       /* Display the message locally (so you know you have sent it) */
01304       if (ci != NULL && show_local) {
01305         if (from_id == CLIENT_ID_SERVER) {
01306           char name[NETWORK_NAME_LENGTH];
01307           StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
01308           SetDParam(0, ci_to->client_playas);
01309           GetString(name, str, lastof(name));
01310           NetworkTextMessage(action, GetDrawStringCompanyColour(ci_own->client_playas), true, name, msg, data);
01311         } else {
01312           FOR_ALL_CLIENT_SOCKETS(cs) {
01313             if (cs->client_id == from_id) {
01314               cs->SendChat(action, ci_to->client_id, true, msg, data);
01315             }
01316           }
01317         }
01318       }
01319       break;
01320     }
01321     default:
01322       DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
01323       /* FALL THROUGH */
01324     case DESTTYPE_BROADCAST:
01325       FOR_ALL_CLIENT_SOCKETS(cs) {
01326         cs->SendChat(action, from_id, false, msg, data);
01327       }
01328 
01329       NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
01330 
01331       ci = NetworkClientInfo::GetByClientID(from_id);
01332       if (ci != NULL) {
01333         NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
01334       }
01335       break;
01336   }
01337 }
01338 
01339 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_CHAT(Packet *p)
01340 {
01341   if (this->status < STATUS_PRE_ACTIVE) {
01342     /* Illegal call, return error and ignore the packet */
01343     return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
01344   }
01345 
01346   NetworkAction action = (NetworkAction)p->Recv_uint8();
01347   DestType desttype = (DestType)p->Recv_uint8();
01348   int dest = p->Recv_uint32();
01349   char msg[NETWORK_CHAT_LENGTH];
01350 
01351   p->Recv_string(msg, NETWORK_CHAT_LENGTH);
01352   int64 data = p->Recv_uint64();
01353 
01354   NetworkClientInfo *ci = this->GetInfo();
01355   switch (action) {
01356     case NETWORK_ACTION_GIVE_MONEY:
01357       if (!Company::IsValidID(ci->client_playas)) break;
01358       /* FALL THROUGH */
01359     case NETWORK_ACTION_CHAT:
01360     case NETWORK_ACTION_CHAT_CLIENT:
01361     case NETWORK_ACTION_CHAT_COMPANY:
01362       NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data);
01363       break;
01364     default:
01365       IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, this->GetClientIP());
01366       return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01367   }
01368   return NETWORK_RECV_STATUS_OKAY;
01369 }
01370 
01371 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_PASSWORD(Packet *p)
01372 {
01373   if (this->status != STATUS_ACTIVE) {
01374     /* Illegal call, return error and ignore the packet */
01375     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01376   }
01377 
01378   char password[NETWORK_PASSWORD_LENGTH];
01379   const NetworkClientInfo *ci;
01380 
01381   p->Recv_string(password, sizeof(password));
01382   ci = this->GetInfo();
01383 
01384   NetworkServerSetCompanyPassword(ci->client_playas, password);
01385   return NETWORK_RECV_STATUS_OKAY;
01386 }
01387 
01388 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_NAME(Packet *p)
01389 {
01390   if (this->status != STATUS_ACTIVE) {
01391     /* Illegal call, return error and ignore the packet */
01392     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01393   }
01394 
01395   char client_name[NETWORK_CLIENT_NAME_LENGTH];
01396   NetworkClientInfo *ci;
01397 
01398   p->Recv_string(client_name, sizeof(client_name));
01399   ci = this->GetInfo();
01400 
01401   if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
01402 
01403   if (ci != NULL) {
01404     /* Display change */
01405     if (NetworkFindName(client_name)) {
01406       NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name);
01407       strecpy(ci->client_name, client_name, lastof(ci->client_name));
01408       NetworkUpdateClientInfo(ci->client_id);
01409     }
01410   }
01411   return NETWORK_RECV_STATUS_OKAY;
01412 }
01413 
01414 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet *p)
01415 {
01416   if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01417 
01418   char pass[NETWORK_PASSWORD_LENGTH];
01419   char command[NETWORK_RCONCOMMAND_LENGTH];
01420 
01421   if (StrEmpty(_settings_client.network.rcon_password)) return NETWORK_RECV_STATUS_OKAY;
01422 
01423   p->Recv_string(pass, sizeof(pass));
01424   p->Recv_string(command, sizeof(command));
01425 
01426   if (strcmp(pass, _settings_client.network.rcon_password) != 0) {
01427     DEBUG(net, 0, "[rcon] wrong password from client-id %d", this->client_id);
01428     return NETWORK_RECV_STATUS_OKAY;
01429   }
01430 
01431   DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", this->client_id, command);
01432 
01433   _redirect_console_to_client = this->client_id;
01434   IConsoleCmdExec(command);
01435   _redirect_console_to_client = INVALID_CLIENT_ID;
01436   return NETWORK_RECV_STATUS_OKAY;
01437 }
01438 
01439 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MOVE(Packet *p)
01440 {
01441   if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01442 
01443   CompanyID company_id = (Owner)p->Recv_uint8();
01444 
01445   /* Check if the company is valid, we don't allow moving to AI companies */
01446   if (company_id != COMPANY_SPECTATOR && !Company::IsValidHumanID(company_id)) return NETWORK_RECV_STATUS_OKAY;
01447 
01448   /* Check if we require a password for this company */
01449   if (company_id != COMPANY_SPECTATOR && !StrEmpty(_network_company_states[company_id].password)) {
01450     /* we need a password from the client - should be in this packet */
01451     char password[NETWORK_PASSWORD_LENGTH];
01452     p->Recv_string(password, sizeof(password));
01453 
01454     /* Incorrect password sent, return! */
01455     if (strcmp(password, _network_company_states[company_id].password) != 0) {
01456       DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", this->client_id, company_id + 1);
01457       return NETWORK_RECV_STATUS_OKAY;
01458     }
01459   }
01460 
01461   /* if we get here we can move the client */
01462   NetworkServerDoMove(this->client_id, company_id);
01463   return NETWORK_RECV_STATUS_OKAY;
01464 }
01465 
01473 void NetworkSocketHandler::SendCompanyInformation(Packet *p, const Company *c, const NetworkCompanyStats *stats, uint max_len)
01474 {
01475   /* Grab the company name */
01476   char company_name[NETWORK_COMPANY_NAME_LENGTH];
01477   SetDParam(0, c->index);
01478 
01479   assert(max_len <= lengthof(company_name));
01480   GetString(company_name, STR_COMPANY_NAME, company_name + max_len - 1);
01481 
01482   /* Get the income */
01483   Money income = 0;
01484   if (_cur_year - 1 == c->inaugurated_year) {
01485     /* The company is here just 1 year, so display [2], else display[1] */
01486     for (uint i = 0; i < lengthof(c->yearly_expenses[2]); i++) {
01487       income -= c->yearly_expenses[2][i];
01488     }
01489   } else {
01490     for (uint i = 0; i < lengthof(c->yearly_expenses[1]); i++) {
01491       income -= c->yearly_expenses[1][i];
01492     }
01493   }
01494 
01495   /* Send the information */
01496   p->Send_uint8 (c->index);
01497   p->Send_string(company_name);
01498   p->Send_uint32(c->inaugurated_year);
01499   p->Send_uint64(c->old_economy[0].company_value);
01500   p->Send_uint64(c->money);
01501   p->Send_uint64(income);
01502   p->Send_uint16(c->old_economy[0].performance_history);
01503 
01504   /* Send 1 if there is a passord for the company else send 0 */
01505   p->Send_bool  (!StrEmpty(_network_company_states[c->index].password));
01506 
01507   for (uint i = 0; i < NETWORK_VEH_END; i++) {
01508     p->Send_uint16(stats->num_vehicle[i]);
01509   }
01510 
01511   for (uint i = 0; i < NETWORK_VEH_END; i++) {
01512     p->Send_uint16(stats->num_station[i]);
01513   }
01514 
01515   p->Send_bool(c->is_ai);
01516 }
01517 
01522 void NetworkPopulateCompanyStats(NetworkCompanyStats *stats)
01523 {
01524   const Vehicle *v;
01525   const Station *s;
01526 
01527   memset(stats, 0, sizeof(*stats) * MAX_COMPANIES);
01528 
01529   /* Go through all vehicles and count the type of vehicles */
01530   FOR_ALL_VEHICLES(v) {
01531     if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
01532     byte type = 0;
01533     switch (v->type) {
01534       case VEH_TRAIN: type = NETWORK_VEH_TRAIN; break;
01535       case VEH_ROAD: type = RoadVehicle::From(v)->IsBus() ? NETWORK_VEH_BUS : NETWORK_VEH_LORRY; break;
01536       case VEH_AIRCRAFT: type = NETWORK_VEH_PLANE; break;
01537       case VEH_SHIP: type = NETWORK_VEH_SHIP; break;
01538       default: continue;
01539     }
01540     stats[v->owner].num_vehicle[type]++;
01541   }
01542 
01543   /* Go through all stations and count the types of stations */
01544   FOR_ALL_STATIONS(s) {
01545     if (Company::IsValidID(s->owner)) {
01546       NetworkCompanyStats *npi = &stats[s->owner];
01547 
01548       if (s->facilities & FACIL_TRAIN)      npi->num_station[NETWORK_VEH_TRAIN]++;
01549       if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[NETWORK_VEH_LORRY]++;
01550       if (s->facilities & FACIL_BUS_STOP)   npi->num_station[NETWORK_VEH_BUS]++;
01551       if (s->facilities & FACIL_AIRPORT)    npi->num_station[NETWORK_VEH_PLANE]++;
01552       if (s->facilities & FACIL_DOCK)       npi->num_station[NETWORK_VEH_SHIP]++;
01553     }
01554   }
01555 }
01556 
01561 void NetworkUpdateClientInfo(ClientID client_id)
01562 {
01563   NetworkClientSocket *cs;
01564   NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
01565 
01566   if (ci == NULL) return;
01567 
01568   DEBUG(desync, 1, "client: %08x; %02x; %02x; %04x", _date, _date_fract, (int)ci->client_playas, client_id);
01569 
01570   FOR_ALL_CLIENT_SOCKETS(cs) {
01571     cs->SendClientInfo(ci);
01572   }
01573 
01574   NetworkAdminClientUpdate(ci);
01575 }
01576 
01578 static void NetworkCheckRestartMap()
01579 {
01580   if (_settings_client.network.restart_game_year != 0 && _cur_year >= _settings_client.network.restart_game_year) {
01581     DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
01582 
01583     StartNewGameWithoutGUI(GENERATE_NEW_SEED);
01584   }
01585 }
01586 
01593 static void NetworkAutoCleanCompanies()
01594 {
01595   const NetworkClientInfo *ci;
01596   const Company *c;
01597   bool clients_in_company[MAX_COMPANIES];
01598   int vehicles_in_company[MAX_COMPANIES];
01599 
01600   if (!_settings_client.network.autoclean_companies) return;
01601 
01602   memset(clients_in_company, 0, sizeof(clients_in_company));
01603 
01604   /* Detect the active companies */
01605   FOR_ALL_CLIENT_INFOS(ci) {
01606     if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
01607   }
01608 
01609   if (!_network_dedicated) {
01610     ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
01611     if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
01612   }
01613 
01614   if (_settings_client.network.autoclean_novehicles != 0) {
01615     memset(vehicles_in_company, 0, sizeof(vehicles_in_company));
01616 
01617     const Vehicle *v;
01618     FOR_ALL_VEHICLES(v) {
01619       if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
01620       vehicles_in_company[v->owner]++;
01621     }
01622   }
01623 
01624   /* Go through all the comapnies */
01625   FOR_ALL_COMPANIES(c) {
01626     /* Skip the non-active once */
01627     if (c->is_ai) continue;
01628 
01629     if (!clients_in_company[c->index]) {
01630       /* The company is empty for one month more */
01631       _network_company_states[c->index].months_empty++;
01632 
01633       /* Is the company empty for autoclean_unprotected-months, and is there no protection? */
01634       if (_settings_client.network.autoclean_unprotected != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_unprotected && StrEmpty(_network_company_states[c->index].password)) {
01635         /* Shut the company down */
01636         DoCommandP(0, 2 | c->index << 16, CRR_AUTOCLEAN, CMD_COMPANY_CTRL);
01637         IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no password", c->index + 1);
01638       }
01639       /* Is the company empty for autoclean_protected-months, and there is a protection? */
01640       if (_settings_client.network.autoclean_protected != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_protected && !StrEmpty(_network_company_states[c->index].password)) {
01641         /* Unprotect the company */
01642         _network_company_states[c->index].password[0] = '\0';
01643         IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", c->index + 1);
01644         _network_company_states[c->index].months_empty = 0;
01645         NetworkServerUpdateCompanyPassworded(c->index, false);
01646       }
01647       /* Is the company empty for autoclean_novehicles-months, and has no vehicles? */
01648       if (_settings_client.network.autoclean_novehicles != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_novehicles && vehicles_in_company[c->index] == 0) {
01649         /* Shut the company down */
01650         DoCommandP(0, 2 | c->index << 16, CRR_AUTOCLEAN, CMD_COMPANY_CTRL);
01651         IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no vehicles", c->index + 1);
01652       }
01653     } else {
01654       /* It is not empty, reset the date */
01655       _network_company_states[c->index].months_empty = 0;
01656     }
01657   }
01658 }
01659 
01665 bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH])
01666 {
01667   bool found_name = false;
01668   uint number = 0;
01669   char original_name[NETWORK_CLIENT_NAME_LENGTH];
01670 
01671   /* We use NETWORK_CLIENT_NAME_LENGTH in here, because new_name is really a pointer */
01672   ttd_strlcpy(original_name, new_name, NETWORK_CLIENT_NAME_LENGTH);
01673 
01674   while (!found_name) {
01675     const NetworkClientInfo *ci;
01676 
01677     found_name = true;
01678     FOR_ALL_CLIENT_INFOS(ci) {
01679       if (strcmp(ci->client_name, new_name) == 0) {
01680         /* Name already in use */
01681         found_name = false;
01682         break;
01683       }
01684     }
01685     /* Check if it is the same as the server-name */
01686     ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
01687     if (ci != NULL) {
01688       if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
01689     }
01690 
01691     if (!found_name) {
01692       /* Try a new name (<name> #1, <name> #2, and so on) */
01693 
01694       /* Something's really wrong when there're more names than clients */
01695       if (number++ > MAX_CLIENTS) break;
01696       snprintf(new_name, NETWORK_CLIENT_NAME_LENGTH, "%s #%d", original_name, number);
01697     }
01698   }
01699 
01700   return found_name;
01701 }
01702 
01709 bool NetworkServerChangeClientName(ClientID client_id, const char *new_name)
01710 {
01711   NetworkClientInfo *ci;
01712   /* Check if the name's already in use */
01713   FOR_ALL_CLIENT_INFOS(ci) {
01714     if (strcmp(ci->client_name, new_name) == 0) return false;
01715   }
01716 
01717   ci = NetworkClientInfo::GetByClientID(client_id);
01718   if (ci == NULL) return false;
01719 
01720   NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, true, ci->client_name, new_name);
01721 
01722   strecpy(ci->client_name, new_name, lastof(ci->client_name));
01723 
01724   NetworkUpdateClientInfo(client_id);
01725   return true;
01726 }
01727 
01734 void NetworkServerSetCompanyPassword(CompanyID company_id, const char *password, bool already_hashed)
01735 {
01736   if (!Company::IsValidHumanID(company_id)) return;
01737 
01738   if (!already_hashed) {
01739     password = GenerateCompanyPasswordHash(password, _settings_client.network.network_id, _settings_game.game_creation.generation_seed);
01740   }
01741 
01742   strecpy(_network_company_states[company_id].password, password, lastof(_network_company_states[company_id].password));
01743   NetworkServerUpdateCompanyPassworded(company_id, !StrEmpty(_network_company_states[company_id].password));
01744 }
01745 
01750 static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
01751 {
01752   CommandPacket *cp;
01753   while ((cp = cs->outgoing_queue.Pop()) != NULL) {
01754     cs->SendCommand(cp);
01755     free(cp);
01756   }
01757 }
01758 
01763 void NetworkServer_Tick(bool send_frame)
01764 {
01765   NetworkClientSocket *cs;
01766 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01767   bool send_sync = false;
01768 #endif
01769 
01770 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01771   if (_frame_counter >= _last_sync_frame + _settings_client.network.sync_freq) {
01772     _last_sync_frame = _frame_counter;
01773     send_sync = true;
01774   }
01775 #endif
01776 
01777   /* Now we are done with the frame, inform the clients that they can
01778    *  do their frame! */
01779   FOR_ALL_CLIENT_SOCKETS(cs) {
01780     /* We allow a number of bytes per frame, but only to the burst amount
01781      * to be available for packet receiving at any particular time. */
01782     cs->receive_limit = min(cs->receive_limit + _settings_client.network.bytes_per_frame,
01783         _settings_client.network.bytes_per_frame_burst);
01784 
01785     /* Check if the speed of the client is what we can expect from a client */
01786     uint lag = NetworkCalculateLag(cs);
01787     switch (cs->status) {
01788       case NetworkClientSocket::STATUS_ACTIVE:
01789         if (lag > _settings_client.network.max_lag_time) {
01790           /* Client did still not report in within the specififed limit. */
01791           IConsolePrintF(CC_ERROR, cs->last_packet + lag * MILLISECONDS_PER_TICK > _realtime_tick ?
01792               /* A packet was received in the last three game days, so the client is likely lagging behind. */
01793                 "Client #%d is dropped because the client's game state is more than %d ticks behind" :
01794               /* No packet was received in the last three game days; sounds like a lost connection. */
01795                 "Client #%d is dropped because the client did not respond for more than %d ticks",
01796               cs->client_id, lag);
01797           cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
01798           continue;
01799         }
01800 
01801         /* Report once per time we detect the lag, and only when we
01802          * received a packet in the last 2000 milliseconds. If we
01803          * did not receive a packet, then the client is not just
01804          * slow, but the connection is likely severed. Mentioning
01805          * frame_freq is not useful in this case. */
01806         if (lag > (uint)DAY_TICKS && cs->lag_test == 0 && cs->last_packet + 2000 > _realtime_tick) {
01807           IConsolePrintF(CC_WARNING, "[%d] Client #%d is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id);
01808           cs->lag_test = 1;
01809         }
01810 
01811         if (cs->last_frame_server - cs->last_token_frame >= _settings_client.network.max_lag_time) {
01812           /* This is a bad client! It didn't send the right token back within time. */
01813           IConsolePrintF(CC_ERROR, "Client #%d is dropped because it fails to send valid acks", cs->client_id);
01814           cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
01815           continue;
01816         }
01817         break;
01818 
01819       case NetworkClientSocket::STATUS_INACTIVE:
01820       case NetworkClientSocket::STATUS_NEWGRFS_CHECK:
01821       case NetworkClientSocket::STATUS_AUTHORIZED:
01822         /* NewGRF check and authorized states should be handled almost instantly.
01823          * So give them some lee-way, likewise for the query with inactive. */
01824         if (lag > _settings_client.network.max_init_time) {
01825           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);
01826           cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER);
01827           continue;
01828         }
01829         break;
01830 
01831       case NetworkClientSocket::STATUS_MAP:
01832         /* Downloading the map... this is the amount of time since starting the saving. */
01833         if (lag > _settings_client.network.max_download_time) {
01834           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);
01835           cs->SendError(NETWORK_ERROR_TIMEOUT_MAP);
01836           continue;
01837         }
01838         break;
01839 
01840       case NetworkClientSocket::STATUS_DONE_MAP:
01841       case NetworkClientSocket::STATUS_PRE_ACTIVE:
01842         /* The map has been sent, so this is for loading the map and syncing up. */
01843         if (lag > _settings_client.network.max_join_time) {
01844           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);
01845           cs->SendError(NETWORK_ERROR_TIMEOUT_JOIN);
01846           continue;
01847         }
01848         break;
01849 
01850       case NetworkClientSocket::STATUS_AUTH_GAME:
01851       case NetworkClientSocket::STATUS_AUTH_COMPANY:
01852         /* These don't block? */
01853         if (lag > _settings_client.network.max_password_time) {
01854           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);
01855           cs->SendError(NETWORK_ERROR_TIMEOUT_PASSWORD);
01856           continue;
01857         }
01858         break;
01859 
01860       case NetworkClientSocket::STATUS_MAP_WAIT:
01861         /* This is an internal state where we do not wait
01862          * on the client to move to a different state. */
01863         break;
01864 
01865       case NetworkClientSocket::STATUS_END:
01866         /* Bad server/code. */
01867         NOT_REACHED();
01868     }
01869 
01870     if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) {
01871       /* Check if we can send command, and if we have anything in the queue */
01872       NetworkHandleCommandQueue(cs);
01873 
01874       /* Send an updated _frame_counter_max to the client */
01875       if (send_frame) cs->SendFrame();
01876 
01877 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01878       /* Send a sync-check packet */
01879       if (send_sync) cs->SendSync();
01880 #endif
01881     }
01882   }
01883 
01884   /* See if we need to advertise */
01885   NetworkUDPAdvertise();
01886 }
01887 
01889 void NetworkServerYearlyLoop()
01890 {
01891   NetworkCheckRestartMap();
01892   NetworkAdminUpdate(ADMIN_FREQUENCY_ANUALLY);
01893 }
01894 
01896 void NetworkServerMonthlyLoop()
01897 {
01898   NetworkAutoCleanCompanies();
01899   NetworkAdminUpdate(ADMIN_FREQUENCY_MONTHLY);
01900   if ((_cur_month % 3) == 0) NetworkAdminUpdate(ADMIN_FREQUENCY_QUARTERLY);
01901 }
01902 
01904 void NetworkServerDailyLoop()
01905 {
01906   NetworkAdminUpdate(ADMIN_FREQUENCY_DAILY);
01907   if ((_date % 7) == 3) NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY);
01908 }
01909 
01914 const char *ServerNetworkGameSocketHandler::GetClientIP()
01915 {
01916   return this->client_address.GetHostname();
01917 }
01918 
01920 void NetworkServerShowStatusToConsole()
01921 {
01922   static const char * const stat_str[] = {
01923     "inactive",
01924     "checking NewGRFs",
01925     "authorizing (server password)",
01926     "authorizing (company password)",
01927     "authorized",
01928     "waiting",
01929     "loading map",
01930     "map done",
01931     "ready",
01932     "active"
01933   };
01934   assert_compile(lengthof(stat_str) == NetworkClientSocket::STATUS_END);
01935 
01936   NetworkClientSocket *cs;
01937   FOR_ALL_CLIENT_SOCKETS(cs) {
01938     NetworkClientInfo *ci = cs->GetInfo();
01939     if (ci == NULL) continue;
01940     uint lag = NetworkCalculateLag(cs);
01941     const char *status;
01942 
01943     status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
01944     IConsolePrintF(CC_INFO, "Client #%1d  name: '%s'  status: '%s'  frame-lag: %3d  company: %1d  IP: %s",
01945       cs->client_id, ci->client_name, status, lag,
01946       ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
01947       cs->GetClientIP());
01948   }
01949 }
01950 
01954 void NetworkServerSendConfigUpdate()
01955 {
01956   NetworkClientSocket *cs;
01957 
01958   FOR_ALL_CLIENT_SOCKETS(cs) {
01959     if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendConfigUpdate();
01960   }
01961 }
01962 
01968 void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded)
01969 {
01970   if (NetworkCompanyIsPassworded(company_id) == passworded) return;
01971 
01972   SB(_network_company_passworded, company_id, 1, !!passworded);
01973   SetWindowClassesDirty(WC_COMPANY);
01974 
01975   NetworkClientSocket *cs;
01976   FOR_ALL_CLIENT_SOCKETS(cs) {
01977     if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendCompanyUpdate();
01978   }
01979 
01980   NetworkAdminCompanyUpdate(Company::GetIfValid(company_id));
01981 }
01982 
01989 void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
01990 {
01991   /* Only allow non-dedicated servers and normal clients to be moved */
01992   if (client_id == CLIENT_ID_SERVER && _network_dedicated) return;
01993 
01994   NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
01995 
01996   /* No need to waste network resources if the client is in the company already! */
01997   if (ci->client_playas == company_id) return;
01998 
01999   ci->client_playas = company_id;
02000 
02001   if (client_id == CLIENT_ID_SERVER) {
02002     SetLocalCompany(company_id);
02003     if (company_id != COMPANY_SPECTATOR) {
02004       Company *c = Company::Get(company_id);
02005       if (c->location_of_HQ != INVALID_TILE) ScrollMainWindowToTile(c->location_of_HQ, true);
02006     }
02007   } else {
02008     NetworkClientSocket *cs = NetworkClientSocket::GetByClientID(client_id);
02009     /* When the company isn't authorized we can't move them yet. */
02010     if (cs->status < NetworkClientSocket::STATUS_AUTHORIZED) return;
02011     cs->SendMove(client_id, company_id);
02012   }
02013 
02014   /* announce the client's move */
02015   NetworkUpdateClientInfo(client_id);
02016 
02017   NetworkAction action = (company_id == COMPANY_SPECTATOR) ? NETWORK_ACTION_COMPANY_SPECTATOR : NETWORK_ACTION_COMPANY_JOIN;
02018   NetworkServerSendChat(action, DESTTYPE_BROADCAST, 0, "", client_id, company_id + 1);
02019 }
02020 
02027 void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string)
02028 {
02029   NetworkClientSocket::GetByClientID(client_id)->SendRConResult(colour_code, string);
02030 }
02031 
02036 void NetworkServerKickClient(ClientID client_id)
02037 {
02038   if (client_id == CLIENT_ID_SERVER) return;
02039   NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED);
02040 }
02041 
02047 uint NetworkServerKickOrBanIP(ClientID client_id, bool ban)
02048 {
02049   return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban);
02050 }
02051 
02057 uint NetworkServerKickOrBanIP(const char *ip, bool ban)
02058 {
02059   /* Add address to ban-list */
02060   if (ban) *_network_ban_list.Append() = strdup(ip);
02061 
02062   uint n = 0;
02063 
02064   /* There can be multiple clients with the same IP, kick them all */
02065   NetworkClientSocket *cs;
02066   FOR_ALL_CLIENT_SOCKETS(cs) {
02067     if (cs->client_id == CLIENT_ID_SERVER) continue;
02068     if (cs->client_address.IsInNetmask(const_cast<char *>(ip))) {
02069       NetworkServerKickClient(cs->client_id);
02070       n++;
02071     }
02072   }
02073 
02074   return n;
02075 }
02076 
02082 bool NetworkCompanyHasClients(CompanyID company)
02083 {
02084   const NetworkClientInfo *ci;
02085   FOR_ALL_CLIENT_INFOS(ci) {
02086     if (ci->client_playas == company) return true;
02087   }
02088   return false;
02089 }
02090 
02091 
02097 void ServerNetworkGameSocketHandler::GetClientName(char *client_name, size_t size) const
02098 {
02099   const NetworkClientInfo *ci = this->GetInfo();
02100 
02101   if (ci == NULL || StrEmpty(ci->client_name)) {
02102     snprintf(client_name, size, "Client #%4d", this->client_id);
02103   } else {
02104     ttd_strlcpy(client_name, ci->client_name, size);
02105   }
02106 }
02107 
02111 void NetworkPrintClients()
02112 {
02113   NetworkClientInfo *ci;
02114   FOR_ALL_CLIENT_INFOS(ci) {
02115     if (_network_server) {
02116       IConsolePrintF(CC_INFO, "Client #%1d  name: '%s'  company: %1d  IP: %s",
02117           ci->client_id,
02118           ci->client_name,
02119           ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
02120           ci->client_id == CLIENT_ID_SERVER ? "server" : NetworkClientSocket::GetByClientID(ci->client_id)->GetClientIP());
02121     } else {
02122       IConsolePrintF(CC_INFO, "Client #%1d  name: '%s'  company: %1d",
02123           ci->client_id,
02124           ci->client_name,
02125           ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0));
02126     }
02127   }
02128 }
02129 
02130 #endif /* ENABLE_NETWORK */