network_server.cpp

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