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 "../window_func.h"
00031 #include "../roadveh.h"
00032 #include "../order_backup.h"
00033 #include "../core/pool_func.hpp"
00034 #include "../core/random_func.hpp"
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 
00455   Packet *p = new Packet(PACKET_SERVER_NEED_GAME_PASSWORD);
00456   this->SendPacket(p);
00457   return NETWORK_RECV_STATUS_OKAY;
00458 }
00459 
00461 NetworkRecvStatus ServerNetworkGameSocketHandler::SendNeedCompanyPassword()
00462 {
00463   /* Invalid packet when status is STATUS_AUTH_COMPANY or higher */
00464   if (this->status >= STATUS_AUTH_COMPANY) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
00465 
00466   this->status = STATUS_AUTH_COMPANY;
00467 
00468   Packet *p = new Packet(PACKET_SERVER_NEED_COMPANY_PASSWORD);
00469   p->Send_uint32(_settings_game.game_creation.generation_seed);
00470   p->Send_string(_settings_client.network.network_id);
00471   this->SendPacket(p);
00472   return NETWORK_RECV_STATUS_OKAY;
00473 }
00474 
00476 NetworkRecvStatus ServerNetworkGameSocketHandler::SendWelcome()
00477 {
00478   Packet *p;
00479   NetworkClientSocket *new_cs;
00480 
00481   /* Invalid packet when status is AUTH or higher */
00482   if (this->status >= STATUS_AUTHORIZED) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
00483 
00484   this->status = STATUS_AUTHORIZED;
00485   _network_game_info.clients_on++;
00486 
00487   p = new Packet(PACKET_SERVER_WELCOME);
00488   p->Send_uint32(this->client_id);
00489   p->Send_uint32(_settings_game.game_creation.generation_seed);
00490   p->Send_string(_settings_client.network.network_id);
00491   this->SendPacket(p);
00492 
00493   /* Transmit info about all the active clients */
00494   FOR_ALL_CLIENT_SOCKETS(new_cs) {
00495     if (new_cs != this && new_cs->status > STATUS_AUTHORIZED) {
00496       this->SendClientInfo(new_cs->GetInfo());
00497     }
00498   }
00499   /* Also send the info of the server */
00500   return this->SendClientInfo(NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
00501 }
00502 
00504 NetworkRecvStatus ServerNetworkGameSocketHandler::SendWait()
00505 {
00506   int waiting = 0;
00507   NetworkClientSocket *new_cs;
00508   Packet *p;
00509 
00510   /* Count how many clients are waiting in the queue, in front of you! */
00511   FOR_ALL_CLIENT_SOCKETS(new_cs) {
00512     if (new_cs->status != STATUS_MAP_WAIT) continue;
00513     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++;
00514   }
00515 
00516   p = new Packet(PACKET_SERVER_WAIT);
00517   p->Send_uint8(waiting);
00518   this->SendPacket(p);
00519   return NETWORK_RECV_STATUS_OKAY;
00520 }
00521 
00523 NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap()
00524 {
00525   static uint sent_packets; // How many packets we did send succecfully last time
00526 
00527   if (this->status < STATUS_AUTHORIZED) {
00528     /* Illegal call, return error and ignore the packet */
00529     return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
00530   }
00531 
00532   if (this->status == STATUS_AUTHORIZED) {
00533     this->savegame = new PacketWriter(this);
00534 
00535     /* Now send the _frame_counter and how many packets are coming */
00536     Packet *p = new Packet(PACKET_SERVER_MAP_BEGIN);
00537     p->Send_uint32(_frame_counter);
00538     this->SendPacket(p);
00539 
00540     NetworkSyncCommandQueue(this);
00541     this->status = STATUS_MAP;
00542     /* Mark the start of download */
00543     this->last_frame = _frame_counter;
00544     this->last_frame_server = _frame_counter;
00545 
00546     sent_packets = 4; // We start with trying 4 packets
00547 
00548     /* Make a dump of the current game */
00549     if (SaveWithFilter(this->savegame, true) != SL_OK) usererror("network savedump failed");
00550   }
00551 
00552   if (this->status == STATUS_MAP) {
00553     if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical();
00554 
00555     bool last_packet = false;
00556 
00557     for (uint i = 0; i < sent_packets && this->savegame_packets != NULL; i++) {
00558       Packet *p = this->savegame_packets;
00559       last_packet = p->buffer[2] == PACKET_SERVER_MAP_DONE;
00560 
00561       /* Remove the packet from the savegame queue and put it in the real queue. */
00562       this->savegame_packets = p->next;
00563       p->next = NULL;
00564       this->NetworkTCPSocketHandler::SendPacket(p);
00565 
00566       if (last_packet) {
00567         /* There is no more data, so break the for */
00568         break;
00569       }
00570     }
00571 
00572     if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical();
00573 
00574     if (last_packet) {
00575       /* Done reading, make sure saving is done as well */
00576       WaitTillSaved();
00577 
00578       /* Set the status to DONE_MAP, no we will wait for the client
00579        *  to send it is ready (maybe that happens like never ;)) */
00580       this->status = STATUS_DONE_MAP;
00581 
00582       /* Find the best candidate for joining, i.e. the first joiner. */
00583       NetworkClientSocket *new_cs;
00584       NetworkClientSocket *best = NULL;
00585       FOR_ALL_CLIENT_SOCKETS(new_cs) {
00586         if (new_cs->status == STATUS_MAP_WAIT) {
00587           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)) {
00588             best = new_cs;
00589           }
00590         }
00591       }
00592 
00593       /* Is there someone else to join? */
00594       if (best != NULL) {
00595         /* Let the first start joining. */
00596         best->status = STATUS_AUTHORIZED;
00597         best->SendMap();
00598 
00599         /* And update the rest. */
00600         FOR_ALL_CLIENT_SOCKETS(new_cs) {
00601           if (new_cs->status == STATUS_MAP_WAIT) new_cs->SendWait();
00602         }
00603       }
00604     }
00605 
00606     switch (this->SendPackets()) {
00607       case SPS_CLOSED:
00608         return NETWORK_RECV_STATUS_CONN_LOST;
00609 
00610       case SPS_ALL_SENT:
00611         /* All are sent, increase the sent_packets */
00612         if (this->savegame_packets != NULL) sent_packets *= 2;
00613         break;
00614 
00615       case SPS_PARTLY_SENT:
00616         /* Only a part is sent; leave the transmission state. */
00617         break;
00618 
00619       case SPS_NONE_SENT:
00620         /* Not everything is sent, decrease the sent_packets */
00621         if (sent_packets > 1) sent_packets /= 2;
00622         break;
00623     }
00624   }
00625   return NETWORK_RECV_STATUS_OKAY;
00626 }
00627 
00632 NetworkRecvStatus ServerNetworkGameSocketHandler::SendJoin(ClientID client_id)
00633 {
00634   Packet *p = new Packet(PACKET_SERVER_JOIN);
00635 
00636   p->Send_uint32(client_id);
00637 
00638   this->SendPacket(p);
00639   return NETWORK_RECV_STATUS_OKAY;
00640 }
00641 
00643 NetworkRecvStatus ServerNetworkGameSocketHandler::SendFrame()
00644 {
00645   Packet *p = new Packet(PACKET_SERVER_FRAME);
00646   p->Send_uint32(_frame_counter);
00647   p->Send_uint32(_frame_counter_max);
00648 #ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
00649   p->Send_uint32(_sync_seed_1);
00650 #ifdef NETWORK_SEND_DOUBLE_SEED
00651   p->Send_uint32(_sync_seed_2);
00652 #endif
00653 #endif
00654 
00655   /* If token equals 0, we need to make a new token and send that. */
00656   if (this->last_token == 0) {
00657     this->last_token = InteractiveRandomRange(UINT8_MAX - 1) + 1;
00658     p->Send_uint8(this->last_token);
00659   }
00660 
00661   this->SendPacket(p);
00662   return NETWORK_RECV_STATUS_OKAY;
00663 }
00664 
00666 NetworkRecvStatus ServerNetworkGameSocketHandler::SendSync()
00667 {
00668   Packet *p = new Packet(PACKET_SERVER_SYNC);
00669   p->Send_uint32(_frame_counter);
00670   p->Send_uint32(_sync_seed_1);
00671 
00672 #ifdef NETWORK_SEND_DOUBLE_SEED
00673   p->Send_uint32(_sync_seed_2);
00674 #endif
00675   this->SendPacket(p);
00676   return NETWORK_RECV_STATUS_OKAY;
00677 }
00678 
00683 NetworkRecvStatus ServerNetworkGameSocketHandler::SendCommand(const CommandPacket *cp)
00684 {
00685   Packet *p = new Packet(PACKET_SERVER_COMMAND);
00686 
00687   this->NetworkGameSocketHandler::SendCommand(p, cp);
00688   p->Send_uint32(cp->frame);
00689   p->Send_bool  (cp->my_cmd);
00690 
00691   this->SendPacket(p);
00692   return NETWORK_RECV_STATUS_OKAY;
00693 }
00694 
00703 NetworkRecvStatus ServerNetworkGameSocketHandler::SendChat(NetworkAction action, ClientID client_id, bool self_send, const char *msg, int64 data)
00704 {
00705   if (this->status != STATUS_ACTIVE) return NETWORK_RECV_STATUS_OKAY;
00706 
00707   Packet *p = new Packet(PACKET_SERVER_CHAT);
00708 
00709   p->Send_uint8 (action);
00710   p->Send_uint32(client_id);
00711   p->Send_bool  (self_send);
00712   p->Send_string(msg);
00713   p->Send_uint64(data);
00714 
00715   this->SendPacket(p);
00716   return NETWORK_RECV_STATUS_OKAY;
00717 }
00718 
00724 NetworkRecvStatus ServerNetworkGameSocketHandler::SendErrorQuit(ClientID client_id, NetworkErrorCode errorno)
00725 {
00726   Packet *p = new Packet(PACKET_SERVER_ERROR_QUIT);
00727 
00728   p->Send_uint32(client_id);
00729   p->Send_uint8 (errorno);
00730 
00731   this->SendPacket(p);
00732   return NETWORK_RECV_STATUS_OKAY;
00733 }
00734 
00739 NetworkRecvStatus ServerNetworkGameSocketHandler::SendQuit(ClientID client_id)
00740 {
00741   Packet *p = new Packet(PACKET_SERVER_QUIT);
00742 
00743   p->Send_uint32(client_id);
00744 
00745   this->SendPacket(p);
00746   return NETWORK_RECV_STATUS_OKAY;
00747 }
00748 
00750 NetworkRecvStatus ServerNetworkGameSocketHandler::SendShutdown()
00751 {
00752   Packet *p = new Packet(PACKET_SERVER_SHUTDOWN);
00753   this->SendPacket(p);
00754   return NETWORK_RECV_STATUS_OKAY;
00755 }
00756 
00758 NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGame()
00759 {
00760   Packet *p = new Packet(PACKET_SERVER_NEWGAME);
00761   this->SendPacket(p);
00762   return NETWORK_RECV_STATUS_OKAY;
00763 }
00764 
00770 NetworkRecvStatus ServerNetworkGameSocketHandler::SendRConResult(uint16 colour, const char *command)
00771 {
00772   Packet *p = new Packet(PACKET_SERVER_RCON);
00773 
00774   p->Send_uint16(colour);
00775   p->Send_string(command);
00776   this->SendPacket(p);
00777   return NETWORK_RECV_STATUS_OKAY;
00778 }
00779 
00785 NetworkRecvStatus ServerNetworkGameSocketHandler::SendMove(ClientID client_id, CompanyID company_id)
00786 {
00787   Packet *p = new Packet(PACKET_SERVER_MOVE);
00788 
00789   p->Send_uint32(client_id);
00790   p->Send_uint8(company_id);
00791   this->SendPacket(p);
00792   return NETWORK_RECV_STATUS_OKAY;
00793 }
00794 
00796 NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyUpdate()
00797 {
00798   Packet *p = new Packet(PACKET_SERVER_COMPANY_UPDATE);
00799 
00800   p->Send_uint16(_network_company_passworded);
00801   this->SendPacket(p);
00802   return NETWORK_RECV_STATUS_OKAY;
00803 }
00804 
00806 NetworkRecvStatus ServerNetworkGameSocketHandler::SendConfigUpdate()
00807 {
00808   Packet *p = new Packet(PACKET_SERVER_CONFIG_UPDATE);
00809 
00810   p->Send_uint8(_settings_client.network.max_companies);
00811   p->Send_uint8(_settings_client.network.max_spectators);
00812   this->SendPacket(p);
00813   return NETWORK_RECV_STATUS_OKAY;
00814 }
00815 
00816 /***********
00817  * Receiving functions
00818  *   DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientSocket *cs, Packet *p
00819  ************/
00820 
00821 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_INFO(Packet *p)
00822 {
00823   return this->SendCompanyInfo();
00824 }
00825 
00826 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_NEWGRFS_CHECKED(Packet *p)
00827 {
00828   if (this->status != STATUS_NEWGRFS_CHECK) {
00829     /* Illegal call, return error and ignore the packet */
00830     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00831   }
00832 
00833   NetworkClientInfo *ci = this->GetInfo();
00834 
00835   /* We now want a password from the client else we do not allow him in! */
00836   if (!StrEmpty(_settings_client.network.server_password)) {
00837     return this->SendNeedGamePassword();
00838   }
00839 
00840   if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) {
00841     return this->SendNeedCompanyPassword();
00842   }
00843 
00844   return this->SendWelcome();
00845 }
00846 
00847 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p)
00848 {
00849   if (this->status != STATUS_INACTIVE) {
00850     /* Illegal call, return error and ignore the packet */
00851     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00852   }
00853 
00854   char name[NETWORK_CLIENT_NAME_LENGTH];
00855   CompanyID playas;
00856   NetworkLanguage client_lang;
00857   char client_revision[NETWORK_REVISION_LENGTH];
00858 
00859   p->Recv_string(client_revision, sizeof(client_revision));
00860 
00861   /* Check if the client has revision control enabled */
00862   if (!IsNetworkCompatibleVersion(client_revision)) {
00863     /* Different revisions!! */
00864     return this->SendError(NETWORK_ERROR_WRONG_REVISION);
00865   }
00866 
00867   p->Recv_string(name, sizeof(name));
00868   playas = (Owner)p->Recv_uint8();
00869   client_lang = (NetworkLanguage)p->Recv_uint8();
00870 
00871   if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
00872 
00873   /* join another company does not affect these values */
00874   switch (playas) {
00875     case COMPANY_NEW_COMPANY: // New company
00876       if (Company::GetNumItems() >= _settings_client.network.max_companies) {
00877         return this->SendError(NETWORK_ERROR_FULL);
00878       }
00879       break;
00880     case COMPANY_SPECTATOR: // Spectator
00881       if (NetworkSpectatorCount() >= _settings_client.network.max_spectators) {
00882         return this->SendError(NETWORK_ERROR_FULL);
00883       }
00884       break;
00885     default: // Join another company (companies 1-8 (index 0-7))
00886       if (!Company::IsValidHumanID(playas)) {
00887         return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
00888       }
00889       break;
00890   }
00891 
00892   /* We need a valid name.. make it Player */
00893   if (StrEmpty(name)) strecpy(name, "Player", lastof(name));
00894 
00895   if (!NetworkFindName(name)) { // Change name if duplicate
00896     /* We could not create a name for this client */
00897     return this->SendError(NETWORK_ERROR_NAME_IN_USE);
00898   }
00899 
00900   assert(NetworkClientInfo::CanAllocateItem());
00901   NetworkClientInfo *ci = new NetworkClientInfo(this->client_id);
00902   this->SetInfo(ci);
00903   ci->join_date = _date;
00904   strecpy(ci->client_name, name, lastof(ci->client_name));
00905   ci->client_playas = playas;
00906   ci->client_lang = client_lang;
00907   DEBUG(desync, 1, "client: %08x; %02x; %02x; %04x", _date, _date_fract, (int)ci->client_playas, ci->index);
00908 
00909   /* Make sure companies to which people try to join are not autocleaned */
00910   if (Company::IsValidID(playas)) _network_company_states[playas].months_empty = 0;
00911 
00912   this->status = STATUS_NEWGRFS_CHECK;
00913 
00914   if (_grfconfig == NULL) {
00915     /* Behave as if we received PACKET_CLIENT_NEWGRFS_CHECKED */
00916     return this->Receive_CLIENT_NEWGRFS_CHECKED(NULL);
00917   }
00918 
00919   return this->SendNewGRFCheck();
00920 }
00921 
00922 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GAME_PASSWORD(Packet *p)
00923 {
00924   if (this->status != STATUS_AUTH_GAME) {
00925     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00926   }
00927 
00928   char password[NETWORK_PASSWORD_LENGTH];
00929   p->Recv_string(password, sizeof(password));
00930 
00931   /* Check game password. Allow joining if we cleared the password meanwhile */
00932   if (!StrEmpty(_settings_client.network.server_password) &&
00933       strcmp(password, _settings_client.network.server_password) != 0) {
00934     /* Password is invalid */
00935     return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
00936   }
00937 
00938   const NetworkClientInfo *ci = this->GetInfo();
00939   if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) {
00940     return this->SendNeedCompanyPassword();
00941   }
00942 
00943   /* Valid password, allow user */
00944   return this->SendWelcome();
00945 }
00946 
00947 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWORD(Packet *p)
00948 {
00949   if (this->status != STATUS_AUTH_COMPANY) {
00950     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00951   }
00952 
00953   char password[NETWORK_PASSWORD_LENGTH];
00954   p->Recv_string(password, sizeof(password));
00955 
00956   /* Check company password. Allow joining if we cleared the password meanwhile.
00957    * Also, check the company is still valid - client could be moved to spectators
00958    * in the middle of the authorization process */
00959   CompanyID playas = this->GetInfo()->client_playas;
00960   if (Company::IsValidID(playas) && !StrEmpty(_network_company_states[playas].password) &&
00961       strcmp(password, _network_company_states[playas].password) != 0) {
00962     /* Password is invalid */
00963     return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
00964   }
00965 
00966   return this->SendWelcome();
00967 }
00968 
00969 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GETMAP(Packet *p)
00970 {
00971   NetworkClientSocket *new_cs;
00972 
00973   /* Do an extra version match. We told the client our version already,
00974    * lets confirm that the client isn't lieing to us.
00975    * But only do it for stable releases because of those we are sure
00976    * that everybody has the same NewGRF version. For trunk and the
00977    * branches we make tarballs of the OpenTTDs compiled from tarball
00978    * will have the lower bits set to 0. As such they would become
00979    * incompatible, which we would like to prevent by this. */
00980   if (IsReleasedVersion()) {
00981     if (_openttd_newgrf_version != p->Recv_uint32()) {
00982       /* The version we get from the client differs, it must have the
00983        * wrong version. The client must be wrong. */
00984       return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00985     }
00986   } else if (p->size != 3) {
00987     /* We received a packet from a version that claims to be stable.
00988      * That shouldn't happen. The client must be wrong. */
00989     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00990   }
00991 
00992   /* The client was never joined.. so this is impossible, right?
00993    *  Ignore the packet, give the client a warning, and close his connection */
00994   if (this->status < STATUS_AUTHORIZED || this->HasClientQuit()) {
00995     return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
00996   }
00997 
00998   /* Check if someone else is receiving the map */
00999   FOR_ALL_CLIENT_SOCKETS(new_cs) {
01000     if (new_cs->status == STATUS_MAP) {
01001       /* Tell the new client to wait */
01002       this->status = STATUS_MAP_WAIT;
01003       return this->SendWait();
01004     }
01005   }
01006 
01007   /* We receive a request to upload the map.. give it to the client! */
01008   return this->SendMap();
01009 }
01010 
01011 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MAP_OK(Packet *p)
01012 {
01013   /* Client has the map, now start syncing */
01014   if (this->status == STATUS_DONE_MAP && !this->HasClientQuit()) {
01015     char client_name[NETWORK_CLIENT_NAME_LENGTH];
01016     NetworkClientSocket *new_cs;
01017 
01018     this->GetClientName(client_name, sizeof(client_name));
01019 
01020     NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, NULL, this->client_id);
01021 
01022     /* Mark the client as pre-active, and wait for an ACK
01023      *  so we know he is done loading and in sync with us */
01024     this->status = STATUS_PRE_ACTIVE;
01025     NetworkHandleCommandQueue(this);
01026     this->SendFrame();
01027     this->SendSync();
01028 
01029     /* This is the frame the client receives
01030      *  we need it later on to make sure the client is not too slow */
01031     this->last_frame = _frame_counter;
01032     this->last_frame_server = _frame_counter;
01033 
01034     FOR_ALL_CLIENT_SOCKETS(new_cs) {
01035       if (new_cs->status > STATUS_AUTHORIZED) {
01036         new_cs->SendClientInfo(this->GetInfo());
01037         new_cs->SendJoin(this->client_id);
01038       }
01039     }
01040 
01041     NetworkAdminClientInfo(this, true);
01042 
01043     /* also update the new client with our max values */
01044     this->SendConfigUpdate();
01045 
01046     /* quickly update the syncing client with company details */
01047     return this->SendCompanyUpdate();
01048   }
01049 
01050   /* Wrong status for this packet, give a warning to client, and close connection */
01051   return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01052 }
01053 
01058 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMMAND(Packet *p)
01059 {
01060   /* The client was never joined.. so this is impossible, right?
01061    *  Ignore the packet, give the client a warning, and close his connection */
01062   if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
01063     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01064   }
01065 
01066   if (this->incoming_queue.Count() >= _settings_client.network.max_commands_in_queue) {
01067     return this->SendError(NETWORK_ERROR_TOO_MANY_COMMANDS);
01068   }
01069 
01070   CommandPacket cp;
01071   const char *err = this->ReceiveCommand(p, &cp);
01072 
01073   if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
01074 
01075   NetworkClientInfo *ci = this->GetInfo();
01076 
01077   if (err != NULL) {
01078     IConsolePrintF(CC_ERROR, "WARNING: %s from client %d (IP: %s).", err, ci->client_id, this->GetClientIP());
01079     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01080   }
01081 
01082 
01083   if ((GetCommandFlags(cp.cmd) & CMD_SERVER) && ci->client_id != CLIENT_ID_SERVER) {
01084     IConsolePrintF(CC_ERROR, "WARNING: server only command from: client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
01085     return this->SendError(NETWORK_ERROR_KICKED);
01086   }
01087 
01088   if ((GetCommandFlags(cp.cmd) & CMD_SPECTATOR) == 0 && !Company::IsValidID(cp.company) && ci->client_id != CLIENT_ID_SERVER) {
01089     IConsolePrintF(CC_ERROR, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
01090     return this->SendError(NETWORK_ERROR_KICKED);
01091   }
01092 
01098   if (!(cp.cmd == CMD_COMPANY_CTRL && cp.p1 == 0 && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) {
01099     IConsolePrintF(CC_ERROR, "WARNING: client %d (IP: %s) tried to execute a command as company %d, kicking...",
01100                    ci->client_playas + 1, this->GetClientIP(), cp.company + 1);
01101     return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
01102   }
01103 
01104   if (cp.cmd == CMD_COMPANY_CTRL) {
01105     if (cp.p1 != 0 || cp.company != COMPANY_SPECTATOR) {
01106       return this->SendError(NETWORK_ERROR_CHEATER);
01107     }
01108 
01109     /* 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! */
01110     if (Company::GetNumItems() >= _settings_client.network.max_companies) {
01111       NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_CLIENT, ci->client_id, "cannot create new company, server full", CLIENT_ID_SERVER);
01112       return NETWORK_RECV_STATUS_OKAY;
01113     }
01114   }
01115 
01116   if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) cp.p2 = this->client_id;
01117 
01118   this->incoming_queue.Append(&cp);
01119   return NETWORK_RECV_STATUS_OKAY;
01120 }
01121 
01122 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet *p)
01123 {
01124   /* This packets means a client noticed an error and is reporting this
01125    *  to us. Display the error and report it to the other clients */
01126   NetworkClientSocket *new_cs;
01127   char str[100];
01128   char client_name[NETWORK_CLIENT_NAME_LENGTH];
01129   NetworkErrorCode errorno = (NetworkErrorCode)p->Recv_uint8();
01130 
01131   /* The client was never joined.. thank the client for the packet, but ignore it */
01132   if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
01133     return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
01134   }
01135 
01136   this->GetClientName(client_name, sizeof(client_name));
01137 
01138   StringID strid = GetNetworkErrorMsg(errorno);
01139   GetString(str, strid, lastof(str));
01140 
01141   DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
01142 
01143   NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, strid);
01144 
01145   FOR_ALL_CLIENT_SOCKETS(new_cs) {
01146     if (new_cs->status > STATUS_AUTHORIZED) {
01147       new_cs->SendErrorQuit(this->client_id, errorno);
01148     }
01149   }
01150 
01151   NetworkAdminClientError(this->client_id, errorno);
01152 
01153   return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
01154 }
01155 
01156 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_QUIT(Packet *p)
01157 {
01158   /* The client wants to leave. Display this and report it to the other
01159    *  clients. */
01160   NetworkClientSocket *new_cs;
01161   char client_name[NETWORK_CLIENT_NAME_LENGTH];
01162 
01163   /* The client was never joined.. thank the client for the packet, but ignore it */
01164   if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
01165     return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
01166   }
01167 
01168   this->GetClientName(client_name, sizeof(client_name));
01169 
01170   NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
01171 
01172   FOR_ALL_CLIENT_SOCKETS(new_cs) {
01173     if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
01174       new_cs->SendQuit(this->client_id);
01175     }
01176   }
01177 
01178   NetworkAdminClientQuit(this->client_id);
01179 
01180   return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
01181 }
01182 
01183 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ACK(Packet *p)
01184 {
01185   if (this->status < STATUS_AUTHORIZED) {
01186     /* Illegal call, return error and ignore the packet */
01187     return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
01188   }
01189 
01190   uint32 frame = p->Recv_uint32();
01191 
01192   /* The client is trying to catch up with the server */
01193   if (this->status == STATUS_PRE_ACTIVE) {
01194     /* The client is not yet catched up? */
01195     if (frame + DAY_TICKS < _frame_counter) return NETWORK_RECV_STATUS_OKAY;
01196 
01197     /* Now he is! Unpause the game */
01198     this->status = STATUS_ACTIVE;
01199     this->last_token_frame = _frame_counter;
01200 
01201     /* Execute script for, e.g. MOTD */
01202     IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
01203   }
01204 
01205   /* Get, and validate the token. */
01206   uint8 token = p->Recv_uint8();
01207   if (token == this->last_token) {
01208     /* We differentiate between last_token_frame and last_frame so the lag
01209      * test uses the actual lag of the client instead of the lag for getting
01210      * the token back and forth; after all, the token is only sent every
01211      * time we receive a PACKET_CLIENT_ACK, after which we will send a new
01212      * token to the client. If the lag would be one day, then we would not
01213      * be sending the new token soon enough for the new daily scheduled
01214      * PACKET_CLIENT_ACK. This would then register the lag of the client as
01215      * two days, even when it's only a single day. */
01216     this->last_token_frame = _frame_counter;
01217     /* Request a new token. */
01218     this->last_token = 0;
01219   }
01220 
01221   /* The client received the frame, make note of it */
01222   this->last_frame = frame;
01223   /* With those 2 values we can calculate the lag realtime */
01224   this->last_frame_server = _frame_counter;
01225   return NETWORK_RECV_STATUS_OKAY;
01226 }
01227 
01228 
01239 void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, ClientID from_id, int64 data, bool from_admin)
01240 {
01241   NetworkClientSocket *cs;
01242   const NetworkClientInfo *ci, *ci_own, *ci_to;
01243 
01244   switch (desttype) {
01245     case DESTTYPE_CLIENT:
01246       /* Are we sending to the server? */
01247       if ((ClientID)dest == CLIENT_ID_SERVER) {
01248         ci = NetworkClientInfo::GetByClientID(from_id);
01249         /* Display the text locally, and that is it */
01250         if (ci != NULL) {
01251           NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
01252 
01253           if (_settings_client.network.server_admin_chat) {
01254             NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
01255           }
01256         }
01257       } else {
01258         /* Else find the client to send the message to */
01259         FOR_ALL_CLIENT_SOCKETS(cs) {
01260           if (cs->client_id == (ClientID)dest) {
01261             cs->SendChat(action, from_id, false, msg, data);
01262             break;
01263           }
01264         }
01265       }
01266 
01267       /* Display the message locally (so you know you have sent it) */
01268       if (from_id != (ClientID)dest) {
01269         if (from_id == CLIENT_ID_SERVER) {
01270           ci = NetworkClientInfo::GetByClientID(from_id);
01271           ci_to = NetworkClientInfo::GetByClientID((ClientID)dest);
01272           if (ci != NULL && ci_to != NULL) {
01273             NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), true, ci_to->client_name, msg, data);
01274           }
01275         } else {
01276           FOR_ALL_CLIENT_SOCKETS(cs) {
01277             if (cs->client_id == from_id) {
01278               cs->SendChat(action, (ClientID)dest, true, msg, data);
01279               break;
01280             }
01281           }
01282         }
01283       }
01284       break;
01285     case DESTTYPE_TEAM: {
01286       /* If this is false, the message is already displayed on the client who sent it. */
01287       bool show_local = true;
01288       /* Find all clients that belong to this company */
01289       ci_to = NULL;
01290       FOR_ALL_CLIENT_SOCKETS(cs) {
01291         ci = cs->GetInfo();
01292         if (ci != NULL && ci->client_playas == (CompanyID)dest) {
01293           cs->SendChat(action, from_id, false, msg, data);
01294           if (cs->client_id == from_id) show_local = false;
01295           ci_to = ci; // Remember a client that is in the company for company-name
01296         }
01297       }
01298 
01299       /* if the server can read it, let the admin network read it, too. */
01300       if (_local_company == (CompanyID)dest && _settings_client.network.server_admin_chat) {
01301         NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
01302       }
01303 
01304       ci = NetworkClientInfo::GetByClientID(from_id);
01305       ci_own = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
01306       if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
01307         NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
01308         if (from_id == CLIENT_ID_SERVER) show_local = false;
01309         ci_to = ci_own;
01310       }
01311 
01312       /* There is no such client */
01313       if (ci_to == NULL) break;
01314 
01315       /* Display the message locally (so you know you have sent it) */
01316       if (ci != NULL && show_local) {
01317         if (from_id == CLIENT_ID_SERVER) {
01318           char name[NETWORK_NAME_LENGTH];
01319           StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
01320           SetDParam(0, ci_to->client_playas);
01321           GetString(name, str, lastof(name));
01322           NetworkTextMessage(action, GetDrawStringCompanyColour(ci_own->client_playas), true, name, msg, data);
01323         } else {
01324           FOR_ALL_CLIENT_SOCKETS(cs) {
01325             if (cs->client_id == from_id) {
01326               cs->SendChat(action, ci_to->client_id, true, msg, data);
01327             }
01328           }
01329         }
01330       }
01331       break;
01332     }
01333     default:
01334       DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
01335       /* FALL THROUGH */
01336     case DESTTYPE_BROADCAST:
01337       FOR_ALL_CLIENT_SOCKETS(cs) {
01338         cs->SendChat(action, from_id, false, msg, data);
01339       }
01340 
01341       NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
01342 
01343       ci = NetworkClientInfo::GetByClientID(from_id);
01344       if (ci != NULL) {
01345         NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
01346       }
01347       break;
01348   }
01349 }
01350 
01351 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_CHAT(Packet *p)
01352 {
01353   if (this->status < STATUS_AUTHORIZED) {
01354     /* Illegal call, return error and ignore the packet */
01355     return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
01356   }
01357 
01358   NetworkAction action = (NetworkAction)p->Recv_uint8();
01359   DestType desttype = (DestType)p->Recv_uint8();
01360   int dest = p->Recv_uint32();
01361   char msg[NETWORK_CHAT_LENGTH];
01362 
01363   p->Recv_string(msg, NETWORK_CHAT_LENGTH);
01364   int64 data = p->Recv_uint64();
01365 
01366   NetworkClientInfo *ci = this->GetInfo();
01367   switch (action) {
01368     case NETWORK_ACTION_GIVE_MONEY:
01369       if (!Company::IsValidID(ci->client_playas)) break;
01370       /* FALL THROUGH */
01371     case NETWORK_ACTION_CHAT:
01372     case NETWORK_ACTION_CHAT_CLIENT:
01373     case NETWORK_ACTION_CHAT_COMPANY:
01374       NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data);
01375       break;
01376     default:
01377       IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, this->GetClientIP());
01378       return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01379   }
01380   return NETWORK_RECV_STATUS_OKAY;
01381 }
01382 
01383 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_PASSWORD(Packet *p)
01384 {
01385   if (this->status != STATUS_ACTIVE) {
01386     /* Illegal call, return error and ignore the packet */
01387     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01388   }
01389 
01390   char password[NETWORK_PASSWORD_LENGTH];
01391   const NetworkClientInfo *ci;
01392 
01393   p->Recv_string(password, sizeof(password));
01394   ci = this->GetInfo();
01395 
01396   NetworkServerSetCompanyPassword(ci->client_playas, password);
01397   return NETWORK_RECV_STATUS_OKAY;
01398 }
01399 
01400 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_NAME(Packet *p)
01401 {
01402   if (this->status != STATUS_ACTIVE) {
01403     /* Illegal call, return error and ignore the packet */
01404     return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01405   }
01406 
01407   char client_name[NETWORK_CLIENT_NAME_LENGTH];
01408   NetworkClientInfo *ci;
01409 
01410   p->Recv_string(client_name, sizeof(client_name));
01411   ci = this->GetInfo();
01412 
01413   if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
01414 
01415   if (ci != NULL) {
01416     /* Display change */
01417     if (NetworkFindName(client_name)) {
01418       NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name);
01419       strecpy(ci->client_name, client_name, lastof(ci->client_name));
01420       NetworkUpdateClientInfo(ci->client_id);
01421     }
01422   }
01423   return NETWORK_RECV_STATUS_OKAY;
01424 }
01425 
01426 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet *p)
01427 {
01428   if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01429 
01430   char pass[NETWORK_PASSWORD_LENGTH];
01431   char command[NETWORK_RCONCOMMAND_LENGTH];
01432 
01433   if (StrEmpty(_settings_client.network.rcon_password)) return NETWORK_RECV_STATUS_OKAY;
01434 
01435   p->Recv_string(pass, sizeof(pass));
01436   p->Recv_string(command, sizeof(command));
01437 
01438   if (strcmp(pass, _settings_client.network.rcon_password) != 0) {
01439     DEBUG(net, 0, "[rcon] wrong password from client-id %d", this->client_id);
01440     return NETWORK_RECV_STATUS_OKAY;
01441   }
01442 
01443   DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", this->client_id, command);
01444 
01445   _redirect_console_to_client = this->client_id;
01446   IConsoleCmdExec(command);
01447   _redirect_console_to_client = INVALID_CLIENT_ID;
01448   return NETWORK_RECV_STATUS_OKAY;
01449 }
01450 
01451 NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MOVE(Packet *p)
01452 {
01453   if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01454 
01455   CompanyID company_id = (Owner)p->Recv_uint8();
01456 
01457   /* Check if the company is valid, we don't allow moving to AI companies */
01458   if (company_id != COMPANY_SPECTATOR && !Company::IsValidHumanID(company_id)) return NETWORK_RECV_STATUS_OKAY;
01459 
01460   /* Check if we require a password for this company */
01461   if (company_id != COMPANY_SPECTATOR && !StrEmpty(_network_company_states[company_id].password)) {
01462     /* we need a password from the client - should be in this packet */
01463     char password[NETWORK_PASSWORD_LENGTH];
01464     p->Recv_string(password, sizeof(password));
01465 
01466     /* Incorrect password sent, return! */
01467     if (strcmp(password, _network_company_states[company_id].password) != 0) {
01468       DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", this->client_id, company_id + 1);
01469       return NETWORK_RECV_STATUS_OKAY;
01470     }
01471   }
01472 
01473   /* if we get here we can move the client */
01474   NetworkServerDoMove(this->client_id, company_id);
01475   return NETWORK_RECV_STATUS_OKAY;
01476 }
01477 
01485 void NetworkSocketHandler::SendCompanyInformation(Packet *p, const Company *c, const NetworkCompanyStats *stats, uint max_len)
01486 {
01487   /* Grab the company name */
01488   char company_name[NETWORK_COMPANY_NAME_LENGTH];
01489   SetDParam(0, c->index);
01490 
01491   assert(max_len <= lengthof(company_name));
01492   GetString(company_name, STR_COMPANY_NAME, company_name + max_len - 1);
01493 
01494   /* Get the income */
01495   Money income = 0;
01496   if (_cur_year - 1 == c->inaugurated_year) {
01497     /* The company is here just 1 year, so display [2], else display[1] */
01498     for (uint i = 0; i < lengthof(c->yearly_expenses[2]); i++) {
01499       income -= c->yearly_expenses[2][i];
01500     }
01501   } else {
01502     for (uint i = 0; i < lengthof(c->yearly_expenses[1]); i++) {
01503       income -= c->yearly_expenses[1][i];
01504     }
01505   }
01506 
01507   /* Send the information */
01508   p->Send_uint8 (c->index);
01509   p->Send_string(company_name);
01510   p->Send_uint32(c->inaugurated_year);
01511   p->Send_uint64(c->old_economy[0].company_value);
01512   p->Send_uint64(c->money);
01513   p->Send_uint64(income);
01514   p->Send_uint16(c->old_economy[0].performance_history);
01515 
01516   /* Send 1 if there is a passord for the company else send 0 */
01517   p->Send_bool  (!StrEmpty(_network_company_states[c->index].password));
01518 
01519   for (uint i = 0; i < NETWORK_VEH_END; i++) {
01520     p->Send_uint16(stats->num_vehicle[i]);
01521   }
01522 
01523   for (uint i = 0; i < NETWORK_VEH_END; i++) {
01524     p->Send_uint16(stats->num_station[i]);
01525   }
01526 
01527   p->Send_bool(c->is_ai);
01528 }
01529 
01534 void NetworkPopulateCompanyStats(NetworkCompanyStats *stats)
01535 {
01536   const Vehicle *v;
01537   const Station *s;
01538 
01539   memset(stats, 0, sizeof(*stats) * MAX_COMPANIES);
01540 
01541   /* Go through all vehicles and count the type of vehicles */
01542   FOR_ALL_VEHICLES(v) {
01543     if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
01544     byte type = 0;
01545     switch (v->type) {
01546       case VEH_TRAIN: type = NETWORK_VEH_TRAIN; break;
01547       case VEH_ROAD: type = RoadVehicle::From(v)->IsBus() ? NETWORK_VEH_BUS : NETWORK_VEH_LORRY; break;
01548       case VEH_AIRCRAFT: type = NETWORK_VEH_PLANE; break;
01549       case VEH_SHIP: type = NETWORK_VEH_SHIP; break;
01550       default: continue;
01551     }
01552     stats[v->owner].num_vehicle[type]++;
01553   }
01554 
01555   /* Go through all stations and count the types of stations */
01556   FOR_ALL_STATIONS(s) {
01557     if (Company::IsValidID(s->owner)) {
01558       NetworkCompanyStats *npi = &stats[s->owner];
01559 
01560       if (s->facilities & FACIL_TRAIN)      npi->num_station[NETWORK_VEH_TRAIN]++;
01561       if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[NETWORK_VEH_LORRY]++;
01562       if (s->facilities & FACIL_BUS_STOP)   npi->num_station[NETWORK_VEH_BUS]++;
01563       if (s->facilities & FACIL_AIRPORT)    npi->num_station[NETWORK_VEH_PLANE]++;
01564       if (s->facilities & FACIL_DOCK)       npi->num_station[NETWORK_VEH_SHIP]++;
01565     }
01566   }
01567 }
01568 
01573 void NetworkUpdateClientInfo(ClientID client_id)
01574 {
01575   NetworkClientSocket *cs;
01576   NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
01577 
01578   if (ci == NULL) return;
01579 
01580   DEBUG(desync, 1, "client: %08x; %02x; %02x; %04x", _date, _date_fract, (int)ci->client_playas, client_id);
01581 
01582   FOR_ALL_CLIENT_SOCKETS(cs) {
01583     cs->SendClientInfo(ci);
01584   }
01585 
01586   NetworkAdminClientUpdate(ci);
01587 }
01588 
01590 static void NetworkCheckRestartMap()
01591 {
01592   if (_settings_client.network.restart_game_year != 0 && _cur_year >= _settings_client.network.restart_game_year) {
01593     DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
01594 
01595     StartNewGameWithoutGUI(GENERATE_NEW_SEED);
01596   }
01597 }
01598 
01605 static void NetworkAutoCleanCompanies()
01606 {
01607   const NetworkClientInfo *ci;
01608   const Company *c;
01609   bool clients_in_company[MAX_COMPANIES];
01610   int vehicles_in_company[MAX_COMPANIES];
01611 
01612   if (!_settings_client.network.autoclean_companies) return;
01613 
01614   memset(clients_in_company, 0, sizeof(clients_in_company));
01615 
01616   /* Detect the active companies */
01617   FOR_ALL_CLIENT_INFOS(ci) {
01618     if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
01619   }
01620 
01621   if (!_network_dedicated) {
01622     ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
01623     if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
01624   }
01625 
01626   if (_settings_client.network.autoclean_novehicles != 0) {
01627     memset(vehicles_in_company, 0, sizeof(vehicles_in_company));
01628 
01629     const Vehicle *v;
01630     FOR_ALL_VEHICLES(v) {
01631       if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
01632       vehicles_in_company[v->owner]++;
01633     }
01634   }
01635 
01636   /* Go through all the comapnies */
01637   FOR_ALL_COMPANIES(c) {
01638     /* Skip the non-active once */
01639     if (c->is_ai) continue;
01640 
01641     if (!clients_in_company[c->index]) {
01642       /* The company is empty for one month more */
01643       _network_company_states[c->index].months_empty++;
01644 
01645       /* Is the company empty for autoclean_unprotected-months, and is there no protection? */
01646       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)) {
01647         /* Shut the company down */
01648         DoCommandP(0, 2 | c->index << 16, CRR_AUTOCLEAN, CMD_COMPANY_CTRL);
01649         IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no password", c->index + 1);
01650       }
01651       /* Is the company empty for autoclean_protected-months, and there is a protection? */
01652       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)) {
01653         /* Unprotect the company */
01654         _network_company_states[c->index].password[0] = '\0';
01655         IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", c->index + 1);
01656         _network_company_states[c->index].months_empty = 0;
01657         NetworkServerUpdateCompanyPassworded(c->index, false);
01658       }
01659       /* Is the company empty for autoclean_novehicles-months, and has no vehicles? */
01660       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) {
01661         /* Shut the company down */
01662         DoCommandP(0, 2 | c->index << 16, CRR_AUTOCLEAN, CMD_COMPANY_CTRL);
01663         IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no vehicles", c->index + 1);
01664       }
01665     } else {
01666       /* It is not empty, reset the date */
01667       _network_company_states[c->index].months_empty = 0;
01668     }
01669   }
01670 }
01671 
01677 bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH])
01678 {
01679   bool found_name = false;
01680   uint number = 0;
01681   char original_name[NETWORK_CLIENT_NAME_LENGTH];
01682 
01683   /* We use NETWORK_CLIENT_NAME_LENGTH in here, because new_name is really a pointer */
01684   ttd_strlcpy(original_name, new_name, NETWORK_CLIENT_NAME_LENGTH);
01685 
01686   while (!found_name) {
01687     const NetworkClientInfo *ci;
01688 
01689     found_name = true;
01690     FOR_ALL_CLIENT_INFOS(ci) {
01691       if (strcmp(ci->client_name, new_name) == 0) {
01692         /* Name already in use */
01693         found_name = false;
01694         break;
01695       }
01696     }
01697     /* Check if it is the same as the server-name */
01698     ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
01699     if (ci != NULL) {
01700       if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
01701     }
01702 
01703     if (!found_name) {
01704       /* Try a new name (<name> #1, <name> #2, and so on) */
01705 
01706       /* Something's really wrong when there're more names than clients */
01707       if (number++ > MAX_CLIENTS) break;
01708       snprintf(new_name, NETWORK_CLIENT_NAME_LENGTH, "%s #%d", original_name, number);
01709     }
01710   }
01711 
01712   return found_name;
01713 }
01714 
01721 bool NetworkServerChangeClientName(ClientID client_id, const char *new_name)
01722 {
01723   NetworkClientInfo *ci;
01724   /* Check if the name's already in use */
01725   FOR_ALL_CLIENT_INFOS(ci) {
01726     if (strcmp(ci->client_name, new_name) == 0) return false;
01727   }
01728 
01729   ci = NetworkClientInfo::GetByClientID(client_id);
01730   if (ci == NULL) return false;
01731 
01732   NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, true, ci->client_name, new_name);
01733 
01734   strecpy(ci->client_name, new_name, lastof(ci->client_name));
01735 
01736   NetworkUpdateClientInfo(client_id);
01737   return true;
01738 }
01739 
01746 void NetworkServerSetCompanyPassword(CompanyID company_id, const char *password, bool already_hashed)
01747 {
01748   if (!Company::IsValidHumanID(company_id)) return;
01749 
01750   if (!already_hashed) {
01751     password = GenerateCompanyPasswordHash(password, _settings_client.network.network_id, _settings_game.game_creation.generation_seed);
01752   }
01753 
01754   strecpy(_network_company_states[company_id].password, password, lastof(_network_company_states[company_id].password));
01755   NetworkServerUpdateCompanyPassworded(company_id, !StrEmpty(_network_company_states[company_id].password));
01756 }
01757 
01762 static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
01763 {
01764   CommandPacket *cp;
01765   while ((cp = cs->outgoing_queue.Pop()) != NULL) {
01766     cs->SendCommand(cp);
01767     free(cp);
01768   }
01769 }
01770 
01775 void NetworkServer_Tick(bool send_frame)
01776 {
01777   NetworkClientSocket *cs;
01778 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01779   bool send_sync = false;
01780 #endif
01781 
01782 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01783   if (_frame_counter >= _last_sync_frame + _settings_client.network.sync_freq) {
01784     _last_sync_frame = _frame_counter;
01785     send_sync = true;
01786   }
01787 #endif
01788 
01789   /* Now we are done with the frame, inform the clients that they can
01790    *  do their frame! */
01791   FOR_ALL_CLIENT_SOCKETS(cs) {
01792     /* We allow a number of bytes per frame, but only to the burst amount
01793      * to be available for packet receiving at any particular time. */
01794     cs->receive_limit = min(cs->receive_limit + _settings_client.network.bytes_per_frame,
01795         _settings_client.network.bytes_per_frame_burst);
01796 
01797     /* Check if the speed of the client is what we can expect from a client */
01798     if (cs->status == NetworkClientSocket::STATUS_ACTIVE) {
01799       /* 1 lag-point per day */
01800       uint lag = NetworkCalculateLag(cs) / DAY_TICKS;
01801       if (lag > 0) {
01802         if (lag > 3) {
01803           /* Client did still not report in after 4 game-day, drop him
01804            *  (that is, the 3 of above, + 1 before any lag is counted) */
01805           IConsolePrintF(CC_ERROR, cs->last_packet + 3 * DAY_TICKS * MILLISECONDS_PER_TICK > _realtime_tick ?
01806               /* A packet was received in the last three game days, so the client is likely lagging behind. */
01807                 "Client #%d is dropped because the client's game state is more than 4 game-days behind" :
01808               /* No packet was received in the last three game days; sounds like a lost connection. */
01809                 "Client #%d is dropped because the client did not respond for more than 4 game-days",
01810               cs->client_id);
01811           cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR);
01812           continue;
01813         }
01814 
01815         /* Report once per time we detect the lag, and only when we
01816          * received a packet in the last 2000 milliseconds. If we
01817          * did not receive a packet, then the client is not just
01818          * slow, but the connection is likely severed. Mentioning
01819          * frame_freq is not useful in this case. */
01820         if (cs->lag_test == 0 && cs->last_packet + DAY_TICKS * MILLISECONDS_PER_TICK > _realtime_tick) {
01821           IConsolePrintF(CC_WARNING,"[%d] Client #%d is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id);
01822           cs->lag_test = 1;
01823         }
01824       } else {
01825         cs->lag_test = 0;
01826       }
01827       if (cs->last_frame_server - cs->last_token_frame >= 5 * DAY_TICKS) {
01828         /* This is a bad client! It didn't send the right token back. */
01829         IConsolePrintF(CC_ERROR, "Client #%d is dropped because it fails to send valid acks", cs->client_id);
01830         cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR);
01831         continue;
01832       }
01833     } else if (cs->status == NetworkClientSocket::STATUS_PRE_ACTIVE) {
01834       uint lag = NetworkCalculateLag(cs);
01835       if (lag > _settings_client.network.max_join_time) {
01836         IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->client_id, _settings_client.network.max_join_time);
01837         cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR);
01838         continue;
01839       }
01840     } else if (cs->status == NetworkClientSocket::STATUS_INACTIVE) {
01841       uint lag = NetworkCalculateLag(cs);
01842       if (lag > 4 * DAY_TICKS) {
01843         IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->client_id, 4 * DAY_TICKS);
01844         cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR);
01845         continue;
01846       }
01847     }
01848 
01849     if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) {
01850       /* Check if we can send command, and if we have anything in the queue */
01851       NetworkHandleCommandQueue(cs);
01852 
01853       /* Send an updated _frame_counter_max to the client */
01854       if (send_frame) cs->SendFrame();
01855 
01856 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01857       /* Send a sync-check packet */
01858       if (send_sync) cs->SendSync();
01859 #endif
01860     }
01861   }
01862 
01863   /* See if we need to advertise */
01864   NetworkUDPAdvertise();
01865 }
01866 
01868 void NetworkServerYearlyLoop()
01869 {
01870   NetworkCheckRestartMap();
01871   NetworkAdminUpdate(ADMIN_FREQUENCY_ANUALLY);
01872 }
01873 
01875 void NetworkServerMonthlyLoop()
01876 {
01877   NetworkAutoCleanCompanies();
01878   NetworkAdminUpdate(ADMIN_FREQUENCY_MONTHLY);
01879   if ((_cur_month % 3) == 0) NetworkAdminUpdate(ADMIN_FREQUENCY_QUARTERLY);
01880 }
01881 
01883 void NetworkServerDailyLoop()
01884 {
01885   NetworkAdminUpdate(ADMIN_FREQUENCY_DAILY);
01886   if ((_date % 7) == 3) NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY);
01887 }
01888 
01893 const char *ServerNetworkGameSocketHandler::GetClientIP()
01894 {
01895   return this->client_address.GetHostname();
01896 }
01897 
01899 void NetworkServerShowStatusToConsole()
01900 {
01901   static const char * const stat_str[] = {
01902     "inactive",
01903     "checking NewGRFs",
01904     "authorizing (server password)",
01905     "authorizing (company password)",
01906     "authorized",
01907     "waiting",
01908     "loading map",
01909     "map done",
01910     "ready",
01911     "active"
01912   };
01913   assert_compile(lengthof(stat_str) == NetworkClientSocket::STATUS_END);
01914 
01915   NetworkClientSocket *cs;
01916   FOR_ALL_CLIENT_SOCKETS(cs) {
01917     NetworkClientInfo *ci = cs->GetInfo();
01918     if (ci == NULL) continue;
01919     uint lag = NetworkCalculateLag(cs);
01920     const char *status;
01921 
01922     status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
01923     IConsolePrintF(CC_INFO, "Client #%1d  name: '%s'  status: '%s'  frame-lag: %3d  company: %1d  IP: %s",
01924       cs->client_id, ci->client_name, status, lag,
01925       ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
01926       cs->GetClientIP());
01927   }
01928 }
01929 
01933 void NetworkServerSendConfigUpdate()
01934 {
01935   NetworkClientSocket *cs;
01936 
01937   FOR_ALL_CLIENT_SOCKETS(cs) {
01938     if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendConfigUpdate();
01939   }
01940 }
01941 
01947 void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded)
01948 {
01949   if (NetworkCompanyIsPassworded(company_id) == passworded) return;
01950 
01951   SB(_network_company_passworded, company_id, 1, !!passworded);
01952   SetWindowClassesDirty(WC_COMPANY);
01953 
01954   NetworkClientSocket *cs;
01955   FOR_ALL_CLIENT_SOCKETS(cs) {
01956     if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendCompanyUpdate();
01957   }
01958 
01959   NetworkAdminCompanyUpdate(Company::GetIfValid(company_id));
01960 }
01961 
01968 void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
01969 {
01970   /* Only allow non-dedicated servers and normal clients to be moved */
01971   if (client_id == CLIENT_ID_SERVER && _network_dedicated) return;
01972 
01973   NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
01974 
01975   /* No need to waste network resources if the client is in the company already! */
01976   if (ci->client_playas == company_id) return;
01977 
01978   ci->client_playas = company_id;
01979 
01980   if (client_id == CLIENT_ID_SERVER) {
01981     SetLocalCompany(company_id);
01982   } else {
01983     NetworkClientSocket *cs = NetworkClientSocket::GetByClientID(client_id);
01984     /* When the company isn't authorized we can't move them yet. */
01985     if (cs->status < NetworkClientSocket::STATUS_AUTHORIZED) return;
01986     cs->SendMove(client_id, company_id);
01987   }
01988 
01989   /* announce the client's move */
01990   NetworkUpdateClientInfo(client_id);
01991 
01992   NetworkAction action = (company_id == COMPANY_SPECTATOR) ? NETWORK_ACTION_COMPANY_SPECTATOR : NETWORK_ACTION_COMPANY_JOIN;
01993   NetworkServerSendChat(action, DESTTYPE_BROADCAST, 0, "", client_id, company_id + 1);
01994 }
01995 
02002 void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string)
02003 {
02004   NetworkClientSocket::GetByClientID(client_id)->SendRConResult(colour_code, string);
02005 }
02006 
02011 void NetworkServerKickClient(ClientID client_id)
02012 {
02013   if (client_id == CLIENT_ID_SERVER) return;
02014   NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED);
02015 }
02016 
02022 uint NetworkServerKickOrBanIP(ClientID client_id, bool ban)
02023 {
02024   return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban);
02025 }
02026 
02032 uint NetworkServerKickOrBanIP(const char *ip, bool ban)
02033 {
02034   /* Add address to ban-list */
02035   if (ban) *_network_ban_list.Append() = strdup(ip);
02036 
02037   uint n = 0;
02038 
02039   /* There can be multiple clients with the same IP, kick them all */
02040   NetworkClientSocket *cs;
02041   FOR_ALL_CLIENT_SOCKETS(cs) {
02042     if (cs->client_id == CLIENT_ID_SERVER) continue;
02043     if (cs->client_address.IsInNetmask(const_cast<char *>(ip))) {
02044       NetworkServerKickClient(cs->client_id);
02045       n++;
02046     }
02047   }
02048 
02049   return n;
02050 }
02051 
02057 bool NetworkCompanyHasClients(CompanyID company)
02058 {
02059   const NetworkClientInfo *ci;
02060   FOR_ALL_CLIENT_INFOS(ci) {
02061     if (ci->client_playas == company) return true;
02062   }
02063   return false;
02064 }
02065 
02066 
02072 void ServerNetworkGameSocketHandler::GetClientName(char *client_name, size_t size) const
02073 {
02074   const NetworkClientInfo *ci = this->GetInfo();
02075 
02076   if (ci == NULL || StrEmpty(ci->client_name)) {
02077     snprintf(client_name, size, "Client #%4d", this->client_id);
02078   } else {
02079     ttd_strlcpy(client_name, ci->client_name, size);
02080   }
02081 }
02082 
02086 void NetworkPrintClients()
02087 {
02088   NetworkClientInfo *ci;
02089   FOR_ALL_CLIENT_INFOS(ci) {
02090     IConsolePrintF(CC_INFO, _network_server ? "Client #%1d  name: '%s'  company: %1d  IP: %s" : "Client #%1d  name: '%s'  company: %1d",
02091         ci->client_id,
02092         ci->client_name,
02093         ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
02094         _network_server ? (ci->client_id == CLIENT_ID_SERVER ? "server" : NetworkClientSocket::GetByClientID(ci->client_id)->GetClientIP()) : "");
02095   }
02096 }
02097 
02098 #endif /* ENABLE_NETWORK */