network_server.cpp

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

Generated on Fri Feb 4 20:53:42 2011 for OpenTTD by  doxygen 1.6.1