network_server.cpp

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

Generated on Sun Jan 9 16:01:56 2011 for OpenTTD by  doxygen 1.6.1