network_server.cpp

00001 /* $Id: network_server.cpp 13827 2008-07-25 19:54:14Z rubidium $ */
00002 
00003 #ifdef ENABLE_NETWORK
00004 
00005 #include "../stdafx.h"
00006 #include "../openttd.h" // XXX StringID
00007 #include "../debug.h"
00008 #include "../strings_func.h"
00009 #include "network_data.h"
00010 #include "core/tcp.h"
00011 #include "../vehicle_base.h"
00012 #include "../vehicle_func.h"
00013 #include "../date_func.h"
00014 #include "network_server.h"
00015 #include "network_udp.h"
00016 #include "../console.h"
00017 #include "../command_func.h"
00018 #include "../saveload.h"
00019 #include "../station.h"
00020 #include "../variables.h"
00021 #include "../genworld.h"
00022 #include "../core/alloc_func.hpp"
00023 #include "../fileio.h"
00024 #include "../string_func.h"
00025 #include "../player_base.h"
00026 #include "../player_func.h"
00027 #include "../player_gui.h"
00028 #include "../settings_type.h"
00029 
00030 #include "table/strings.h"
00031 
00032 // This file handles all the server-commands
00033 
00034 static void NetworkHandleCommandQueue(NetworkTCPSocketHandler* cs);
00035 
00036 // **********
00037 // Sending functions
00038 //   DEF_SERVER_SEND_COMMAND has parameter: NetworkTCPSocketHandler *cs
00039 // **********
00040 
00041 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CLIENT_INFO)(NetworkTCPSocketHandler *cs, NetworkClientInfo *ci)
00042 {
00043   //
00044   // Packet: SERVER_CLIENT_INFO
00045   // Function: Sends info about a client
00046   // Data:
00047   //    uint16:  The index of the client (always unique on a server. 1 = server)
00048   //    uint8:  As which player the client is playing
00049   //    String: The name of the client
00050   //
00051 
00052   if (ci->client_index != NETWORK_EMPTY_INDEX) {
00053     Packet *p = NetworkSend_Init(PACKET_SERVER_CLIENT_INFO);
00054     p->Send_uint16(ci->client_index);
00055     p->Send_uint8 (ci->client_playas);
00056     p->Send_string(ci->client_name);
00057 
00058     cs->Send_Packet(p);
00059   }
00060 }
00061 
00062 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)
00063 {
00064 //
00065   // Packet: SERVER_COMPANY_INFO
00066   // Function: Sends info about the companies
00067   // Data:
00068   //
00069 
00070   int i;
00071 
00072   Player *player;
00073   Packet *p;
00074 
00075   byte active = ActivePlayerCount();
00076 
00077   if (active == 0) {
00078     p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
00079 
00080     p->Send_uint8 (NETWORK_COMPANY_INFO_VERSION);
00081     p->Send_uint8 (active);
00082 
00083     cs->Send_Packet(p);
00084     return;
00085   }
00086 
00087   NetworkPopulateCompanyInfo();
00088 
00089   FOR_ALL_PLAYERS(player) {
00090     if (!player->is_active) continue;
00091 
00092     p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
00093 
00094     p->Send_uint8 (NETWORK_COMPANY_INFO_VERSION);
00095     p->Send_uint8 (active);
00096     p->Send_uint8 (player->index);
00097 
00098     p->Send_string(_network_player_info[player->index].company_name);
00099     p->Send_uint32(_network_player_info[player->index].inaugurated_year);
00100     p->Send_uint64(_network_player_info[player->index].company_value);
00101     p->Send_uint64(_network_player_info[player->index].money);
00102     p->Send_uint64(_network_player_info[player->index].income);
00103     p->Send_uint16(_network_player_info[player->index].performance);
00104 
00105     /* Send 1 if there is a passord for the company else send 0 */
00106     p->Send_bool(!StrEmpty(_network_player_info[player->index].password));
00107 
00108     for (i = 0; i < NETWORK_VEHICLE_TYPES; i++) {
00109       p->Send_uint16(_network_player_info[player->index].num_vehicle[i]);
00110     }
00111 
00112     for (i = 0; i < NETWORK_STATION_TYPES; i++) {
00113       p->Send_uint16(_network_player_info[player->index].num_station[i]);
00114     }
00115 
00116     if (_network_player_info[player->index].players[0] == '\0') {
00117       p->Send_string("<none>");
00118     } else {
00119       p->Send_string(_network_player_info[player->index].players);
00120     }
00121 
00122     cs->Send_Packet(p);
00123   }
00124 
00125   p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
00126 
00127   p->Send_uint8 (NETWORK_COMPANY_INFO_VERSION);
00128   p->Send_uint8 (0);
00129 
00130   cs->Send_Packet(p);
00131 }
00132 
00133 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkTCPSocketHandler *cs, NetworkErrorCode error)
00134 {
00135   //
00136   // Packet: SERVER_ERROR
00137   // Function: The client made an error
00138   // Data:
00139   //    uint8:  ErrorID (see network_data.h, NetworkErrorCode)
00140   //
00141 
00142   char str[100];
00143   Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR);
00144 
00145   p->Send_uint8(error);
00146   cs->Send_Packet(p);
00147 
00148   GetNetworkErrorMsg(str, error, lastof(str));
00149 
00150   // Only send when the current client was in game
00151   if (cs->status > STATUS_AUTH) {
00152     NetworkTCPSocketHandler *new_cs;
00153     char client_name[NETWORK_CLIENT_NAME_LENGTH];
00154 
00155     NetworkGetClientName(client_name, sizeof(client_name), cs);
00156 
00157     DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
00158 
00159     NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
00160 
00161     FOR_ALL_CLIENTS(new_cs) {
00162       if (new_cs->status > STATUS_AUTH && new_cs != cs) {
00163         // Some errors we filter to a more general error. Clients don't have to know the real
00164         //  reason a joining failed.
00165         if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION)
00166           error = NETWORK_ERROR_ILLEGAL_PACKET;
00167 
00168         SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, error);
00169       }
00170     }
00171   } else {
00172     DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", cs->index, str);
00173   }
00174 
00175   cs->has_quit = true;
00176 
00177   // Make sure the data get's there before we close the connection
00178   cs->Send_Packets();
00179 
00180   // The client made a mistake, so drop his connection now!
00181   NetworkCloseClient(cs);
00182 }
00183 
00184 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHECK_NEWGRFS)(NetworkTCPSocketHandler *cs)
00185 {
00186   //
00187   // Packet: PACKET_SERVER_CHECK_NEWGRFS
00188   // Function: Sends info about the used GRFs to the client
00189   // Data:
00190   //      uint8:  Amount of GRFs
00191   //    And then for each GRF:
00192   //      uint32: GRF ID
00193   // 16 * uint8:  MD5 checksum of the GRF
00194   //
00195 
00196   Packet *p = NetworkSend_Init(PACKET_SERVER_CHECK_NEWGRFS);
00197   const GRFConfig *c;
00198   uint grf_count = 0;
00199 
00200   for (c = _grfconfig; c != NULL; c = c->next) {
00201     if (!HasBit(c->flags, GCF_STATIC)) grf_count++;
00202   }
00203 
00204   p->Send_uint8 (grf_count);
00205   for (c = _grfconfig; c != NULL; c = c->next) {
00206     if (!HasBit(c->flags, GCF_STATIC)) cs->Send_GRFIdentifier(p, c);
00207   }
00208 
00209   cs->Send_Packet(p);
00210 }
00211 
00212 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_PASSWORD)(NetworkTCPSocketHandler *cs, NetworkPasswordType type)
00213 {
00214   //
00215   // Packet: SERVER_NEED_PASSWORD
00216   // Function: Indication to the client that the server needs a password
00217   // Data:
00218   //    uint8:  Type of password
00219   //
00220 
00221   /* Invalid packet when status is AUTH or higher */
00222   if (cs->status >= STATUS_AUTH) return;
00223 
00224   cs->status = STATUS_AUTHORIZING;
00225 
00226   Packet *p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD);
00227   p->Send_uint8(type);
00228   p->Send_uint32(_patches.generation_seed);
00229   p->Send_string(_network_unique_id);
00230   cs->Send_Packet(p);
00231 }
00232 
00233 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WELCOME)
00234 {
00235   //
00236   // Packet: SERVER_WELCOME
00237   // Function: The client is joined and ready to receive his map
00238   // Data:
00239   //    uint16:  Own ClientID
00240   //
00241 
00242   Packet *p;
00243   NetworkTCPSocketHandler *new_cs;
00244 
00245   // Invalid packet when status is AUTH or higher
00246   if (cs->status >= STATUS_AUTH) return;
00247 
00248   cs->status = STATUS_AUTH;
00249   _network_game_info.clients_on++;
00250 
00251   p = NetworkSend_Init(PACKET_SERVER_WELCOME);
00252   p->Send_uint16(cs->index);
00253   p->Send_uint32(_patches.generation_seed);
00254   p->Send_string(_network_unique_id);
00255   cs->Send_Packet(p);
00256 
00257     // Transmit info about all the active clients
00258   FOR_ALL_CLIENTS(new_cs) {
00259     if (new_cs != cs && new_cs->status > STATUS_AUTH)
00260       SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, DEREF_CLIENT_INFO(new_cs));
00261   }
00262   // Also send the info of the server
00263   SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX));
00264 }
00265 
00266 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WAIT)
00267 {
00268   //
00269   // Packet: PACKET_SERVER_WAIT
00270   // Function: The client can not receive the map at the moment because
00271   //             someone else is already receiving the map
00272   // Data:
00273   //    uint8:  Clients awaiting map
00274   //
00275   int waiting = 0;
00276   NetworkTCPSocketHandler *new_cs;
00277   Packet *p;
00278 
00279   // Count how many players are waiting in the queue
00280   FOR_ALL_CLIENTS(new_cs) {
00281     if (new_cs->status == STATUS_MAP_WAIT) waiting++;
00282   }
00283 
00284   p = NetworkSend_Init(PACKET_SERVER_WAIT);
00285   p->Send_uint8(waiting);
00286   cs->Send_Packet(p);
00287 }
00288 
00289 // This sends the map to the client
00290 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP)
00291 {
00292   //
00293   // Packet: SERVER_MAP
00294   // Function: Sends the map to the client, or a part of it (it is splitted in
00295   //   a lot of multiple packets)
00296   // Data:
00297   //    uint8:  packet-type (MAP_PACKET_START, MAP_PACKET_NORMAL and MAP_PACKET_END)
00298   //  if MAP_PACKET_START:
00299   //    uint32: The current FrameCounter
00300   //  if MAP_PACKET_NORMAL:
00301   //    piece of the map (till max-size of packet)
00302   //  if MAP_PACKET_END:
00303   //    uint32: seed0 of player
00304   //    uint32: seed1 of player
00305   //      last 2 are repeated MAX_PLAYERS time
00306   //
00307 
00308   static FILE *file_pointer;
00309   static uint sent_packets; // How many packets we did send succecfully last time
00310 
00311   if (cs->status < STATUS_AUTH) {
00312     // Illegal call, return error and ignore the packet
00313     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
00314     return;
00315   }
00316 
00317   if (cs->status == STATUS_AUTH) {
00318     const char *filename = "network_server.tmp";
00319     Packet *p;
00320 
00321     // Make a dump of the current game
00322     if (SaveOrLoad(filename, SL_SAVE, AUTOSAVE_DIR) != SL_OK) error("network savedump failed");
00323 
00324     file_pointer = FioFOpenFile(filename, "rb", AUTOSAVE_DIR);
00325     fseek(file_pointer, 0, SEEK_END);
00326 
00327     if (ftell(file_pointer) == 0) error("network savedump failed - zero sized savegame?");
00328 
00329     // Now send the _frame_counter and how many packets are coming
00330     p = NetworkSend_Init(PACKET_SERVER_MAP);
00331     p->Send_uint8 (MAP_PACKET_START);
00332     p->Send_uint32(_frame_counter);
00333     p->Send_uint32(ftell(file_pointer));
00334     cs->Send_Packet(p);
00335 
00336     fseek(file_pointer, 0, SEEK_SET);
00337 
00338     sent_packets = 4; // We start with trying 4 packets
00339 
00340     cs->status = STATUS_MAP;
00341     /* Mark the start of download */
00342     cs->last_frame = _frame_counter;
00343     cs->last_frame_server = _frame_counter;
00344   }
00345 
00346   if (cs->status == STATUS_MAP) {
00347     uint i;
00348     int res;
00349     for (i = 0; i < sent_packets; i++) {
00350       Packet *p = NetworkSend_Init(PACKET_SERVER_MAP);
00351       p->Send_uint8(MAP_PACKET_NORMAL);
00352       res = (int)fread(p->buffer + p->size, 1, SEND_MTU - p->size, file_pointer);
00353 
00354       if (ferror(file_pointer)) error("Error reading temporary network savegame!");
00355 
00356       p->size += res;
00357       cs->Send_Packet(p);
00358       if (feof(file_pointer)) {
00359         // Done reading!
00360         Packet *p = NetworkSend_Init(PACKET_SERVER_MAP);
00361         p->Send_uint8(MAP_PACKET_END);
00362         cs->Send_Packet(p);
00363 
00364         // Set the status to DONE_MAP, no we will wait for the client
00365         //  to send it is ready (maybe that happens like never ;))
00366         cs->status = STATUS_DONE_MAP;
00367         fclose(file_pointer);
00368 
00369         {
00370           NetworkTCPSocketHandler *new_cs;
00371           bool new_map_client = false;
00372           // Check if there is a client waiting for receiving the map
00373           //  and start sending him the map
00374           FOR_ALL_CLIENTS(new_cs) {
00375             if (new_cs->status == STATUS_MAP_WAIT) {
00376               // Check if we already have a new client to send the map to
00377               if (!new_map_client) {
00378                 // If not, this client will get the map
00379                 new_cs->status = STATUS_AUTH;
00380                 new_map_client = true;
00381                 SEND_COMMAND(PACKET_SERVER_MAP)(new_cs);
00382               } else {
00383                 // Else, send the other clients how many clients are in front of them
00384                 SEND_COMMAND(PACKET_SERVER_WAIT)(new_cs);
00385               }
00386             }
00387           }
00388         }
00389 
00390         // There is no more data, so break the for
00391         break;
00392       }
00393     }
00394 
00395     // Send all packets (forced) and check if we have send it all
00396     cs->Send_Packets();
00397     if (cs->IsPacketQueueEmpty()) {
00398       // All are sent, increase the sent_packets
00399       sent_packets *= 2;
00400     } else {
00401       // Not everything is sent, decrease the sent_packets
00402       if (sent_packets > 1) sent_packets /= 2;
00403     }
00404   }
00405 }
00406 
00407 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_JOIN)(NetworkTCPSocketHandler *cs, uint16 client_index)
00408 {
00409   //
00410   // Packet: SERVER_JOIN
00411   // Function: A client is joined (all active clients receive this after a
00412   //     PACKET_CLIENT_MAP_OK) Mostly what directly follows is a
00413   //     PACKET_SERVER_CLIENT_INFO
00414   // Data:
00415   //    uint16:  Client-Index
00416   //
00417 
00418   Packet *p = NetworkSend_Init(PACKET_SERVER_JOIN);
00419 
00420   p->Send_uint16(client_index);
00421 
00422   cs->Send_Packet(p);
00423 }
00424 
00425 
00426 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_FRAME)
00427 {
00428   //
00429   // Packet: SERVER_FRAME
00430   // Function: Sends the current frame-counter to the client
00431   // Data:
00432   //    uint32: Frame Counter
00433   //    uint32: Frame Counter Max (how far may the client walk before the server?)
00434   //    [uint32: general-seed-1]
00435   //    [uint32: general-seed-2]
00436   //      (last two depends on compile-settings, and are not default settings)
00437   //
00438 
00439   Packet *p = NetworkSend_Init(PACKET_SERVER_FRAME);
00440   p->Send_uint32(_frame_counter);
00441   p->Send_uint32(_frame_counter_max);
00442 #ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
00443   p->Send_uint32(_sync_seed_1);
00444 #ifdef NETWORK_SEND_DOUBLE_SEED
00445   p->Send_uint32(_sync_seed_2);
00446 #endif
00447 #endif
00448   cs->Send_Packet(p);
00449 }
00450 
00451 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SYNC)
00452 {
00453   //
00454   // Packet: SERVER_SYNC
00455   // Function: Sends a sync-check to the client
00456   // Data:
00457   //    uint32: Frame Counter
00458   //    uint32: General-seed-1
00459   //    [uint32: general-seed-2]
00460   //      (last one depends on compile-settings, and are not default settings)
00461   //
00462 
00463   Packet *p = NetworkSend_Init(PACKET_SERVER_SYNC);
00464   p->Send_uint32(_frame_counter);
00465   p->Send_uint32(_sync_seed_1);
00466 
00467 #ifdef NETWORK_SEND_DOUBLE_SEED
00468   p->Send_uint32(_sync_seed_2);
00469 #endif
00470   cs->Send_Packet(p);
00471 }
00472 
00473 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_COMMAND)(NetworkTCPSocketHandler *cs, CommandPacket *cp)
00474 {
00475   //
00476   // Packet: SERVER_COMMAND
00477   // Function: Sends a DoCommand to the client
00478   // Data:
00479   //    uint8:  PlayerID (0..MAX_PLAYERS-1)
00480   //    uint32: CommandID (see command.h)
00481   //    uint32: P1 (free variables used in DoCommand)
00482   //    uint32: P2
00483   //    uint32: Tile
00484   //    string: text
00485   //    uint8:  CallBackID (see callback_table.c)
00486   //    uint32: Frame of execution
00487   //
00488 
00489   Packet *p = NetworkSend_Init(PACKET_SERVER_COMMAND);
00490 
00491   p->Send_uint8 (cp->player);
00492   p->Send_uint32(cp->cmd);
00493   p->Send_uint32(cp->p1);
00494   p->Send_uint32(cp->p2);
00495   p->Send_uint32(cp->tile);
00496   p->Send_string(cp->text);
00497   p->Send_uint8 (cp->callback);
00498   p->Send_uint32(cp->frame);
00499   p->Send_bool  (cp->my_cmd);
00500 
00501   cs->Send_Packet(p);
00502 }
00503 
00504 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHAT)(NetworkTCPSocketHandler *cs, NetworkAction action, uint16 client_index, bool self_send, const char *msg)
00505 {
00506   //
00507   // Packet: SERVER_CHAT
00508   // Function: Sends a chat-packet to the client
00509   // Data:
00510   //    uint8:  ActionID (see network_data.h, NetworkAction)
00511   //    uint16:  Client-index
00512   //    String: Message (max MAX_TEXT_MSG_LEN)
00513   //
00514 
00515   Packet *p = NetworkSend_Init(PACKET_SERVER_CHAT);
00516 
00517   p->Send_uint8 (action);
00518   p->Send_uint16(client_index);
00519   p->Send_bool  (self_send);
00520   p->Send_string(msg);
00521 
00522   cs->Send_Packet(p);
00523 }
00524 
00525 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkTCPSocketHandler *cs, uint16 client_index, NetworkErrorCode errorno)
00526 {
00527   //
00528   // Packet: SERVER_ERROR_QUIT
00529   // Function: One of the clients made an error and is quiting the game
00530   //      This packet informs the other clients of that.
00531   // Data:
00532   //    uint16:  Client-index
00533   //    uint8:  ErrorID (see network_data.h, NetworkErrorCode)
00534   //
00535 
00536   Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR_QUIT);
00537 
00538   p->Send_uint16(client_index);
00539   p->Send_uint8 (errorno);
00540 
00541   cs->Send_Packet(p);
00542 }
00543 
00544 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_QUIT)(NetworkTCPSocketHandler *cs, uint16 client_index, const char *leavemsg)
00545 {
00546   //
00547   // Packet: SERVER_ERROR_QUIT
00548   // Function: A client left the game, and this packets informs the other clients
00549   //      of that.
00550   // Data:
00551   //    uint16:  Client-index
00552   //    String: leave-message
00553   //
00554 
00555   Packet *p = NetworkSend_Init(PACKET_SERVER_QUIT);
00556 
00557   p->Send_uint16(client_index);
00558   p->Send_string(leavemsg);
00559 
00560   cs->Send_Packet(p);
00561 }
00562 
00563 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN)
00564 {
00565   //
00566   // Packet: SERVER_SHUTDOWN
00567   // Function: Let the clients know that the server is closing
00568   // Data:
00569   //     <none>
00570   //
00571 
00572   Packet *p = NetworkSend_Init(PACKET_SERVER_SHUTDOWN);
00573   cs->Send_Packet(p);
00574 }
00575 
00576 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME)
00577 {
00578   //
00579   // Packet: PACKET_SERVER_NEWGAME
00580   // Function: Let the clients know that the server is loading a new map
00581   // Data:
00582   //     <none>
00583   //
00584 
00585   Packet *p = NetworkSend_Init(PACKET_SERVER_NEWGAME);
00586   cs->Send_Packet(p);
00587 }
00588 
00589 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkTCPSocketHandler *cs, uint16 color, const char *command)
00590 {
00591   Packet *p = NetworkSend_Init(PACKET_SERVER_RCON);
00592 
00593   p->Send_uint16(color);
00594   p->Send_string(command);
00595   cs->Send_Packet(p);
00596 }
00597 
00598 // **********
00599 // Receiving functions
00600 //   DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkTCPSocketHandler *cs, Packet *p
00601 // **********
00602 
00603 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO)
00604 {
00605   SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)(cs);
00606 }
00607 
00608 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)
00609 {
00610   if (cs->status != STATUS_INACTIVE) {
00611     /* Illegal call, return error and ignore the packet */
00612     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
00613     return;
00614   }
00615 
00616   NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
00617 
00618   /* We now want a password from the client else we do not allow him in! */
00619   if (_network_game_info.use_password) {
00620     SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_GAME_PASSWORD);
00621   } else {
00622     if (IsValidPlayer(ci->client_playas) && _network_player_info[ci->client_playas].password[0] != '\0') {
00623       SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
00624     } else {
00625       SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
00626     }
00627   }
00628 }
00629 
00630 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN)
00631 {
00632   if (cs->status != STATUS_INACTIVE) {
00633     /* Illegal call, return error and ignore the packet */
00634     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
00635     return;
00636   }
00637 
00638   char name[NETWORK_CLIENT_NAME_LENGTH];
00639   char unique_id[NETWORK_UNIQUE_ID_LENGTH];
00640   NetworkClientInfo *ci;
00641   PlayerID playas;
00642   NetworkLanguage client_lang;
00643   char client_revision[NETWORK_REVISION_LENGTH];
00644 
00645   p->Recv_string(client_revision, sizeof(client_revision));
00646 
00647   // Check if the client has revision control enabled
00648   if (!IsNetworkCompatibleVersion(client_revision)) {
00649     // Different revisions!!
00650     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_REVISION);
00651     return;
00652   }
00653 
00654   p->Recv_string(name, sizeof(name));
00655   playas = (Owner)p->Recv_uint8();
00656   client_lang = (NetworkLanguage)p->Recv_uint8();
00657   p->Recv_string(unique_id, sizeof(unique_id));
00658 
00659   if (cs->has_quit) return;
00660 
00661   // join another company does not affect these values
00662   switch (playas) {
00663     case PLAYER_NEW_COMPANY: /* New company */
00664       if (ActivePlayerCount() >= _network_game_info.companies_max) {
00665         SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
00666         return;
00667       }
00668       break;
00669     case PLAYER_SPECTATOR: /* Spectator */
00670       if (NetworkSpectatorCount() >= _network_game_info.spectators_max) {
00671         SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
00672         return;
00673       }
00674       break;
00675     default: /* Join another company (companies 1-8 (index 0-7)) */
00676       if (!IsValidPlayer(playas)) {
00677         SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH);
00678         return;
00679       }
00680       break;
00681   }
00682 
00683   // We need a valid name.. make it Player
00684   if (*name == '\0') ttd_strlcpy(name, "Player", sizeof(name));
00685 
00686   if (!NetworkFindName(name)) { // Change name if duplicate
00687     // We could not create a name for this player
00688     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NAME_IN_USE);
00689     return;
00690   }
00691 
00692   ci = DEREF_CLIENT_INFO(cs);
00693 
00694   ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name));
00695   ttd_strlcpy(ci->unique_id, unique_id, sizeof(ci->unique_id));
00696   ci->client_playas = playas;
00697   ci->client_lang = client_lang;
00698 
00699   /* Make sure companies to which people try to join are not autocleaned */
00700   if (IsValidPlayer(playas)) _network_player_info[playas].months_empty = 0;
00701 
00702   if (_grfconfig == NULL) {
00703     RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)(cs, NULL);
00704   } else {
00705     SEND_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)(cs);
00706   }
00707 }
00708 
00709 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD)
00710 {
00711   NetworkPasswordType type;
00712   char password[NETWORK_PASSWORD_LENGTH];
00713   const NetworkClientInfo *ci;
00714 
00715   type = (NetworkPasswordType)p->Recv_uint8();
00716   p->Recv_string(password, sizeof(password));
00717 
00718   if (cs->status == STATUS_AUTHORIZING && type == NETWORK_GAME_PASSWORD) {
00719     // Check game-password
00720     if (strcmp(password, _network_game_info.server_password) != 0) {
00721       // Password is invalid
00722       SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
00723       return;
00724     }
00725 
00726     ci = DEREF_CLIENT_INFO(cs);
00727 
00728     if (IsValidPlayer(ci->client_playas) && _network_player_info[ci->client_playas].password[0] != '\0') {
00729       SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
00730       return;
00731     }
00732 
00733     // Valid password, allow user
00734     SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
00735     return;
00736   } else if (cs->status == STATUS_AUTHORIZING && type == NETWORK_COMPANY_PASSWORD) {
00737     ci = DEREF_CLIENT_INFO(cs);
00738 
00739     if (strcmp(password, _network_player_info[ci->client_playas].password) != 0) {
00740       // Password is invalid
00741       SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
00742       return;
00743     }
00744 
00745     SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
00746     return;
00747   }
00748 
00749 
00750   SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
00751   return;
00752 }
00753 
00754 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP)
00755 {
00756   NetworkTCPSocketHandler *new_cs;
00757 
00758   // The client was never joined.. so this is impossible, right?
00759   //  Ignore the packet, give the client a warning, and close his connection
00760   if (cs->status < STATUS_AUTH || cs->has_quit) {
00761     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
00762     return;
00763   }
00764 
00765   // Check if someone else is receiving the map
00766   FOR_ALL_CLIENTS(new_cs) {
00767     if (new_cs->status == STATUS_MAP) {
00768       // Tell the new client to wait
00769       cs->status = STATUS_MAP_WAIT;
00770       SEND_COMMAND(PACKET_SERVER_WAIT)(cs);
00771       return;
00772     }
00773   }
00774 
00775   // We receive a request to upload the map.. give it to the client!
00776   SEND_COMMAND(PACKET_SERVER_MAP)(cs);
00777 }
00778 
00779 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK)
00780 {
00781   // Client has the map, now start syncing
00782   if (cs->status == STATUS_DONE_MAP && !cs->has_quit) {
00783     char client_name[NETWORK_CLIENT_NAME_LENGTH];
00784     NetworkTCPSocketHandler *new_cs;
00785 
00786     NetworkGetClientName(client_name, sizeof(client_name), cs);
00787 
00788     NetworkTextMessage(NETWORK_ACTION_JOIN, 1, false, client_name, "");
00789 
00790     // Mark the client as pre-active, and wait for an ACK
00791     //  so we know he is done loading and in sync with us
00792     cs->status = STATUS_PRE_ACTIVE;
00793     NetworkHandleCommandQueue(cs);
00794     SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
00795     SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
00796 
00797     // This is the frame the client receives
00798     //  we need it later on to make sure the client is not too slow
00799     cs->last_frame = _frame_counter;
00800     cs->last_frame_server = _frame_counter;
00801 
00802     FOR_ALL_CLIENTS(new_cs) {
00803       if (new_cs->status > STATUS_AUTH) {
00804         SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(new_cs, DEREF_CLIENT_INFO(cs));
00805         SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, cs->index);
00806       }
00807     }
00808 
00809     if (_network_pause_on_join) {
00810       /* Now pause the game till the client is in sync */
00811       DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
00812 
00813       NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (incoming client)", NETWORK_SERVER_INDEX);
00814     }
00815   } else {
00816     // Wrong status for this packet, give a warning to client, and close connection
00817     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
00818   }
00819 }
00820 
00826 static bool CheckCommandFlags(const CommandPacket *cp, const NetworkClientInfo *ci)
00827 {
00828   byte flags = GetCommandFlags(cp->cmd);
00829 
00830   if (flags & CMD_SERVER && ci->client_index != NETWORK_SERVER_INDEX) {
00831     IConsolePrintF(_icolour_err, "WARNING: server only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
00832     return false;
00833   }
00834 
00835   if (flags & CMD_OFFLINE) {
00836     IConsolePrintF(_icolour_err, "WARNING: offline only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
00837     return false;
00838   }
00839 
00840   if (cp->cmd != CMD_PLAYER_CTRL && !IsValidPlayer(cp->player) && ci->client_index != NETWORK_SERVER_INDEX) {
00841     IConsolePrintF(_icolour_err, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
00842     return false;
00843   }
00844 
00845   return true;
00846 }
00847 
00852 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
00853 {
00854   NetworkTCPSocketHandler *new_cs;
00855   const NetworkClientInfo *ci;
00856   byte callback;
00857 
00858   // The client was never joined.. so this is impossible, right?
00859   //  Ignore the packet, give the client a warning, and close his connection
00860   if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
00861     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
00862     return;
00863   }
00864 
00865   CommandPacket *cp = MallocT<CommandPacket>(1);
00866   cp->player = (Owner)p->Recv_uint8();
00867   cp->cmd    = p->Recv_uint32();
00868   cp->p1     = p->Recv_uint32();
00869   cp->p2     = p->Recv_uint32();
00870   cp->tile   = p->Recv_uint32();
00871   p->Recv_string(cp->text, lengthof(cp->text));
00872 
00873   callback = p->Recv_uint8();
00874 
00875   if (cs->has_quit) {
00876     free(cp);
00877     return;
00878   }
00879 
00880   ci = DEREF_CLIENT_INFO(cs);
00881 
00882   /* Check if cp->cmd is valid */
00883   if (!IsValidCommand(cp->cmd)) {
00884     IConsolePrintF(_icolour_err, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci));
00885     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
00886     free(cp);
00887     return;
00888   }
00889 
00890   if (!CheckCommandFlags(cp, ci)) {
00891     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED);
00892     free(cp);
00893     return;
00894   }
00895 
00900   if (!(cp->cmd == CMD_PLAYER_CTRL && cp->p1 == 0 && ci->client_playas == PLAYER_NEW_COMPANY) && ci->client_playas != cp->player) {
00901     IConsolePrintF(_icolour_err, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...",
00902                    ci->client_playas + 1, GetPlayerIP(ci), cp->player + 1);
00903     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH);
00904     free(cp);
00905     return;
00906   }
00907 
00913   if (cp->cmd == CMD_PLAYER_CTRL) {
00914     if (cp->p1 != 0) {
00915       SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER);
00916       free(cp);
00917       return;
00918     }
00919 
00920     /* XXX - Execute the command as a valid player. Normally this would be done by a
00921      * spectator, but that is not allowed any commands. So do an impersonation. The drawback
00922      * of this is that the first company's last_built_tile is also updated... */
00923     cp->player = OWNER_BEGIN;
00924     cp->p2 = cs - _clients; // XXX - UGLY! p2 is mis-used to get the client-id in CmdPlayerCtrl
00925   }
00926 
00927   // The frame can be executed in the same frame as the next frame-packet
00928   //  That frame just before that frame is saved in _frame_counter_max
00929   cp->frame = _frame_counter_max + 1;
00930   cp->next  = NULL;
00931 
00932   // Queue the command for the clients (are send at the end of the frame
00933   //   if they can handle it ;))
00934   FOR_ALL_CLIENTS(new_cs) {
00935     if (new_cs->status >= STATUS_MAP) {
00936       // Callbacks are only send back to the client who sent them in the
00937       //  first place. This filters that out.
00938       cp->callback = (new_cs != cs) ? 0 : callback;
00939       cp->my_cmd = (new_cs == cs);
00940       NetworkAddCommandQueue(new_cs, cp);
00941     }
00942   }
00943 
00944   cp->callback = 0;
00945   cp->my_cmd = false;
00946   // Queue the command on the server
00947   if (_local_command_queue == NULL) {
00948     _local_command_queue = cp;
00949   } else {
00950     // Find last packet
00951     CommandPacket *c = _local_command_queue;
00952     while (c->next != NULL) c = c->next;
00953     c->next = cp;
00954   }
00955 }
00956 
00957 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ERROR)
00958 {
00959   // This packets means a client noticed an error and is reporting this
00960   //  to us. Display the error and report it to the other clients
00961   NetworkTCPSocketHandler *new_cs;
00962   char str[100];
00963   char client_name[NETWORK_CLIENT_NAME_LENGTH];
00964   NetworkErrorCode errorno = (NetworkErrorCode)p->Recv_uint8();
00965 
00966   // The client was never joined.. thank the client for the packet, but ignore it
00967   if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
00968     cs->has_quit = true;
00969     return;
00970   }
00971 
00972   NetworkGetClientName(client_name, sizeof(client_name), cs);
00973 
00974   GetNetworkErrorMsg(str, errorno, lastof(str));
00975 
00976   DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
00977 
00978   NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
00979 
00980   FOR_ALL_CLIENTS(new_cs) {
00981     if (new_cs->status > STATUS_AUTH) {
00982       SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, errorno);
00983     }
00984   }
00985 
00986   cs->has_quit = true;
00987 }
00988 
00989 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
00990 {
00991   // The client wants to leave. Display this and report it to the other
00992   //  clients.
00993   NetworkTCPSocketHandler *new_cs;
00994   char str[100];
00995   char client_name[NETWORK_CLIENT_NAME_LENGTH];
00996 
00997   // The client was never joined.. thank the client for the packet, but ignore it
00998   if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
00999     cs->has_quit = true;
01000     return;
01001   }
01002 
01003   p->Recv_string(str, lengthof(str));
01004 
01005   NetworkGetClientName(client_name, sizeof(client_name), cs);
01006 
01007   NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
01008 
01009   FOR_ALL_CLIENTS(new_cs) {
01010     if (new_cs->status > STATUS_AUTH) {
01011       SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, cs->index, str);
01012     }
01013   }
01014 
01015   cs->has_quit = true;
01016 }
01017 
01018 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK)
01019 {
01020   if (cs->status < STATUS_AUTH) {
01021     /* Illegal call, return error and ignore the packet */
01022     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
01023     return;
01024   }
01025 
01026   uint32 frame = p->Recv_uint32();
01027 
01028   /* The client is trying to catch up with the server */
01029   if (cs->status == STATUS_PRE_ACTIVE) {
01030     /* The client is not yet catched up? */
01031     if (frame + DAY_TICKS < _frame_counter) return;
01032 
01033     /* Now he is! Unpause the game */
01034     cs->status = STATUS_ACTIVE;
01035 
01036     if (_network_pause_on_join) {
01037       DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
01038       NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (client connected)", NETWORK_SERVER_INDEX);
01039     }
01040 
01041     CheckMinPlayers();
01042 
01043     /* Execute script for, e.g. MOTD */
01044     IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
01045   }
01046 
01047   // The client received the frame, make note of it
01048   cs->last_frame = frame;
01049   // With those 2 values we can calculate the lag realtime
01050   cs->last_frame_server = _frame_counter;
01051 }
01052 
01053 
01054 
01055 void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest, const char *msg, uint16 from_index)
01056 {
01057   NetworkTCPSocketHandler *cs;
01058   const NetworkClientInfo *ci, *ci_own, *ci_to;
01059 
01060   switch (desttype) {
01061   case DESTTYPE_CLIENT:
01062     /* Are we sending to the server? */
01063     if (dest == NETWORK_SERVER_INDEX) {
01064       ci = NetworkFindClientInfoFromIndex(from_index);
01065       /* Display the text locally, and that is it */
01066       if (ci != NULL)
01067         NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
01068     } else {
01069       /* Else find the client to send the message to */
01070       FOR_ALL_CLIENTS(cs) {
01071         if (cs->index == dest) {
01072           SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
01073           break;
01074         }
01075       }
01076     }
01077 
01078     // Display the message locally (so you know you have sent it)
01079     if (from_index != dest) {
01080       if (from_index == NETWORK_SERVER_INDEX) {
01081         ci = NetworkFindClientInfoFromIndex(from_index);
01082         ci_to = NetworkFindClientInfoFromIndex(dest);
01083         if (ci != NULL && ci_to != NULL)
01084           NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), true, ci_to->client_name, "%s", msg);
01085       } else {
01086         FOR_ALL_CLIENTS(cs) {
01087           if (cs->index == from_index) {
01088             SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, dest, true, msg);
01089             break;
01090           }
01091         }
01092       }
01093     }
01094     break;
01095   case DESTTYPE_TEAM: {
01096     bool show_local = true; // If this is false, the message is already displayed
01097                             // on the client who did sent it.
01098     /* Find all clients that belong to this player */
01099     ci_to = NULL;
01100     FOR_ALL_CLIENTS(cs) {
01101       ci = DEREF_CLIENT_INFO(cs);
01102       if (ci->client_playas == dest) {
01103         SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
01104         if (cs->index == from_index) show_local = false;
01105         ci_to = ci; // Remember a client that is in the company for company-name
01106       }
01107     }
01108 
01109     ci = NetworkFindClientInfoFromIndex(from_index);
01110     ci_own = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
01111     if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
01112       NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
01113       if (from_index == NETWORK_SERVER_INDEX) show_local = false;
01114       ci_to = ci_own;
01115     }
01116 
01117     /* There is no such player */
01118     if (ci_to == NULL) break;
01119 
01120     // Display the message locally (so you know you have sent it)
01121     if (ci != NULL && show_local) {
01122       if (from_index == NETWORK_SERVER_INDEX) {
01123         char name[NETWORK_NAME_LENGTH];
01124         StringID str = IsValidPlayer(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
01125         SetDParam(0, ci_to->client_playas);
01126         GetString(name, str, lastof(name));
01127         NetworkTextMessage(action, GetDrawStringPlayerColor(ci_own->client_playas), true, name, "%s", msg);
01128       } else {
01129         FOR_ALL_CLIENTS(cs) {
01130           if (cs->index == from_index) {
01131             SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, ci_to->client_index, true, msg);
01132           }
01133         }
01134       }
01135     }
01136     }
01137     break;
01138   default:
01139     DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
01140     /* fall-through to next case */
01141   case DESTTYPE_BROADCAST:
01142     FOR_ALL_CLIENTS(cs) {
01143       SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
01144     }
01145     ci = NetworkFindClientInfoFromIndex(from_index);
01146     if (ci != NULL)
01147       NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
01148     break;
01149   }
01150 }
01151 
01152 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_CHAT)
01153 {
01154   if (cs->status < STATUS_AUTH) {
01155     /* Illegal call, return error and ignore the packet */
01156     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
01157     return;
01158   }
01159 
01160   NetworkAction action = (NetworkAction)p->Recv_uint8();
01161   DestType desttype = (DestType)p->Recv_uint8();
01162   int dest = p->Recv_uint16();
01163   char msg[MAX_TEXT_MSG_LEN];
01164 
01165   p->Recv_string(msg, MAX_TEXT_MSG_LEN);
01166 
01167   const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
01168   switch (action) {
01169     case NETWORK_ACTION_GIVE_MONEY:
01170       if (!IsValidPlayer(ci->client_playas)) break;
01171       /* Fall-through */
01172     case NETWORK_ACTION_CHAT:
01173     case NETWORK_ACTION_CHAT_CLIENT:
01174     case NETWORK_ACTION_CHAT_COMPANY:
01175       NetworkServer_HandleChat(action, desttype, dest, msg, cs->index);
01176       break;
01177     default:
01178       IConsolePrintF(_icolour_err, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci));
01179       SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
01180       break;
01181   }
01182 }
01183 
01184 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD)
01185 {
01186   if (cs->status != STATUS_ACTIVE) {
01187     /* Illegal call, return error and ignore the packet */
01188     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
01189     return;
01190   }
01191 
01192   char password[NETWORK_PASSWORD_LENGTH];
01193   const NetworkClientInfo *ci;
01194 
01195   p->Recv_string(password, sizeof(password));
01196   ci = DEREF_CLIENT_INFO(cs);
01197 
01198   if (IsValidPlayer(ci->client_playas)) {
01199     ttd_strlcpy(_network_player_info[ci->client_playas].password, password, sizeof(_network_player_info[0].password));
01200   }
01201 }
01202 
01203 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME)
01204 {
01205   if (cs->status != STATUS_ACTIVE) {
01206     /* Illegal call, return error and ignore the packet */
01207     SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
01208     return;
01209   }
01210 
01211   char client_name[NETWORK_CLIENT_NAME_LENGTH];
01212   NetworkClientInfo *ci;
01213 
01214   p->Recv_string(client_name, sizeof(client_name));
01215   ci = DEREF_CLIENT_INFO(cs);
01216 
01217   if (cs->has_quit) return;
01218 
01219   if (ci != NULL) {
01220     // Display change
01221     if (NetworkFindName(client_name)) {
01222       NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", client_name);
01223       ttd_strlcpy(ci->client_name, client_name, sizeof(ci->client_name));
01224       NetworkUpdateClientInfo(ci->client_index);
01225     }
01226   }
01227 }
01228 
01229 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_RCON)
01230 {
01231   char pass[NETWORK_PASSWORD_LENGTH];
01232   char command[NETWORK_RCONCOMMAND_LENGTH];
01233 
01234   if (_network_game_info.rcon_password[0] == '\0') return;
01235 
01236   p->Recv_string(pass, sizeof(pass));
01237   p->Recv_string(command, sizeof(command));
01238 
01239   if (strcmp(pass, _network_game_info.rcon_password) != 0) {
01240     DEBUG(net, 0, "[rcon] wrong password from client-id %d", cs->index);
01241     return;
01242   }
01243 
01244   DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", cs->index, command);
01245 
01246   _redirect_console_to_client = cs->index;
01247   IConsoleCmdExec(command);
01248   _redirect_console_to_client = 0;
01249   return;
01250 }
01251 
01252 // The layout for the receive-functions by the server
01253 typedef void NetworkServerPacket(NetworkTCPSocketHandler *cs, Packet *p);
01254 
01255 
01256 // This array matches PacketType. At an incoming
01257 //  packet it is matches against this array
01258 //  and that way the right function to handle that
01259 //  packet is found.
01260 static NetworkServerPacket* const _network_server_packet[] = {
01261   NULL, /*PACKET_SERVER_FULL,*/
01262   NULL, /*PACKET_SERVER_BANNED,*/
01263   RECEIVE_COMMAND(PACKET_CLIENT_JOIN),
01264   NULL, /*PACKET_SERVER_ERROR,*/
01265   RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO),
01266   NULL, /*PACKET_SERVER_COMPANY_INFO,*/
01267   NULL, /*PACKET_SERVER_CLIENT_INFO,*/
01268   NULL, /*PACKET_SERVER_NEED_PASSWORD,*/
01269   RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD),
01270   NULL, /*PACKET_SERVER_WELCOME,*/
01271   RECEIVE_COMMAND(PACKET_CLIENT_GETMAP),
01272   NULL, /*PACKET_SERVER_WAIT,*/
01273   NULL, /*PACKET_SERVER_MAP,*/
01274   RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK),
01275   NULL, /*PACKET_SERVER_JOIN,*/
01276   NULL, /*PACKET_SERVER_FRAME,*/
01277   NULL, /*PACKET_SERVER_SYNC,*/
01278   RECEIVE_COMMAND(PACKET_CLIENT_ACK),
01279   RECEIVE_COMMAND(PACKET_CLIENT_COMMAND),
01280   NULL, /*PACKET_SERVER_COMMAND,*/
01281   RECEIVE_COMMAND(PACKET_CLIENT_CHAT),
01282   NULL, /*PACKET_SERVER_CHAT,*/
01283   RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD),
01284   RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME),
01285   RECEIVE_COMMAND(PACKET_CLIENT_QUIT),
01286   RECEIVE_COMMAND(PACKET_CLIENT_ERROR),
01287   NULL, /*PACKET_SERVER_QUIT,*/
01288   NULL, /*PACKET_SERVER_ERROR_QUIT,*/
01289   NULL, /*PACKET_SERVER_SHUTDOWN,*/
01290   NULL, /*PACKET_SERVER_NEWGAME,*/
01291   NULL, /*PACKET_SERVER_RCON,*/
01292   RECEIVE_COMMAND(PACKET_CLIENT_RCON),
01293   NULL, /*PACKET_CLIENT_CHECK_NEWGRFS,*/
01294   RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED),
01295 };
01296 
01297 // If this fails, check the array above with network_data.h
01298 assert_compile(lengthof(_network_server_packet) == PACKET_END);
01299 
01300 // This update the company_info-stuff
01301 void NetworkPopulateCompanyInfo()
01302 {
01303   char password[NETWORK_PASSWORD_LENGTH];
01304   const Player *p;
01305   const Vehicle *v;
01306   const Station *s;
01307   NetworkTCPSocketHandler *cs;
01308   const NetworkClientInfo *ci;
01309   uint i;
01310   uint16 months_empty;
01311 
01312   FOR_ALL_PLAYERS(p) {
01313     if (!p->is_active) {
01314       memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo));
01315       continue;
01316     }
01317 
01318     // Clean the info but not the password
01319     ttd_strlcpy(password, _network_player_info[p->index].password, sizeof(password));
01320     months_empty = _network_player_info[p->index].months_empty;
01321     memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo));
01322     _network_player_info[p->index].months_empty = months_empty;
01323     ttd_strlcpy(_network_player_info[p->index].password, password, sizeof(_network_player_info[p->index].password));
01324 
01325     // Grap the company name
01326     SetDParam(0, p->index);
01327     GetString(_network_player_info[p->index].company_name, STR_COMPANY_NAME, lastof(_network_player_info[p->index].company_name));
01328 
01329     // Check the income
01330     if (_cur_year - 1 == p->inaugurated_year) {
01331       // The player is here just 1 year, so display [2], else display[1]
01332       for (i = 0; i < lengthof(p->yearly_expenses[2]); i++) {
01333         _network_player_info[p->index].income -= p->yearly_expenses[2][i];
01334       }
01335     } else {
01336       for (i = 0; i < lengthof(p->yearly_expenses[1]); i++) {
01337         _network_player_info[p->index].income -= p->yearly_expenses[1][i];
01338       }
01339     }
01340 
01341     // Set some general stuff
01342     _network_player_info[p->index].inaugurated_year = p->inaugurated_year;
01343     _network_player_info[p->index].company_value = p->old_economy[0].company_value;
01344     _network_player_info[p->index].money = p->player_money;
01345     _network_player_info[p->index].performance = p->old_economy[0].performance_history;
01346   }
01347 
01348   // Go through all vehicles and count the type of vehicles
01349   FOR_ALL_VEHICLES(v) {
01350     if (!IsValidPlayer(v->owner) || !v->IsPrimaryVehicle()) continue;
01351     byte type = 0;
01352     switch (v->type) {
01353       case VEH_TRAIN: type = 0; break;
01354       case VEH_ROAD: type = (v->cargo_type != CT_PASSENGERS) ? 1 : 2; break;
01355       case VEH_AIRCRAFT: type = 3; break;
01356       case VEH_SHIP: type = 4; break;
01357       default: continue;
01358     }
01359     _network_player_info[v->owner].num_vehicle[type]++;
01360   }
01361 
01362   // Go through all stations and count the types of stations
01363   FOR_ALL_STATIONS(s) {
01364     if (IsValidPlayer(s->owner)) {
01365       NetworkPlayerInfo *npi = &_network_player_info[s->owner];
01366 
01367       if (s->facilities & FACIL_TRAIN)      npi->num_station[0]++;
01368       if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[1]++;
01369       if (s->facilities & FACIL_BUS_STOP)   npi->num_station[2]++;
01370       if (s->facilities & FACIL_AIRPORT)    npi->num_station[3]++;
01371       if (s->facilities & FACIL_DOCK)       npi->num_station[4]++;
01372     }
01373   }
01374 
01375   ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
01376   // Register local player (if not dedicated)
01377   if (ci != NULL && IsValidPlayer(ci->client_playas))
01378     ttd_strlcpy(_network_player_info[ci->client_playas].players, ci->client_name, sizeof(_network_player_info[0].players));
01379 
01380   FOR_ALL_CLIENTS(cs) {
01381     char client_name[NETWORK_CLIENT_NAME_LENGTH];
01382 
01383     NetworkGetClientName(client_name, sizeof(client_name), cs);
01384 
01385     ci = DEREF_CLIENT_INFO(cs);
01386     if (ci != NULL && IsValidPlayer(ci->client_playas)) {
01387       if (!StrEmpty(_network_player_info[ci->client_playas].players)) {
01388         ttd_strlcat(_network_player_info[ci->client_playas].players, ", ", lengthof(_network_player_info[0].players));
01389       }
01390 
01391       ttd_strlcat(_network_player_info[ci->client_playas].players, client_name, lengthof(_network_player_info[0].players));
01392     }
01393   }
01394 }
01395 
01396 // Send a packet to all clients with updated info about this client_index
01397 void NetworkUpdateClientInfo(uint16 client_index)
01398 {
01399   NetworkTCPSocketHandler *cs;
01400   NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(client_index);
01401 
01402   if (ci == NULL) return;
01403 
01404   FOR_ALL_CLIENTS(cs) {
01405     SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, ci);
01406   }
01407 }
01408 
01409 /* Check if we want to restart the map */
01410 static void NetworkCheckRestartMap()
01411 {
01412   if (_network_restart_game_year != 0 && _cur_year >= _network_restart_game_year) {
01413     DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
01414 
01415     StartNewGameWithoutGUI(GENERATE_NEW_SEED);
01416   }
01417 }
01418 
01419 /* Check if the server has autoclean_companies activated
01420     Two things happen:
01421       1) If a company is not protected, it is closed after 1 year (for example)
01422       2) If a company is protected, protection is disabled after 3 years (for example)
01423            (and item 1. happens a year later) */
01424 static void NetworkAutoCleanCompanies()
01425 {
01426   NetworkTCPSocketHandler *cs;
01427   const NetworkClientInfo *ci;
01428   const Player *p;
01429   bool clients_in_company[MAX_PLAYERS];
01430 
01431   if (!_network_autoclean_companies) return;
01432 
01433   memset(clients_in_company, 0, sizeof(clients_in_company));
01434 
01435   /* Detect the active companies */
01436   FOR_ALL_CLIENTS(cs) {
01437     ci = DEREF_CLIENT_INFO(cs);
01438     if (IsValidPlayer(ci->client_playas)) clients_in_company[ci->client_playas] = true;
01439   }
01440 
01441   if (!_network_dedicated) {
01442     ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
01443     if (IsValidPlayer(ci->client_playas)) clients_in_company[ci->client_playas] = true;
01444   }
01445 
01446   /* Go through all the comapnies */
01447   FOR_ALL_PLAYERS(p) {
01448     /* Skip the non-active once */
01449     if (!p->is_active || p->is_ai) continue;
01450 
01451     if (!clients_in_company[p->index]) {
01452       /* The company is empty for one month more */
01453       _network_player_info[p->index].months_empty++;
01454 
01455       /* Is the company empty for autoclean_unprotected-months, and is there no protection? */
01456       if (_network_player_info[p->index].months_empty > _network_autoclean_unprotected && _network_player_info[p->index].password[0] == '\0') {
01457         /* Shut the company down */
01458         DoCommandP(0, 2, p->index, NULL, CMD_PLAYER_CTRL);
01459         IConsolePrintF(_icolour_def, "Auto-cleaned company #%d", p->index + 1);
01460       }
01461       /* Is the compnay empty for autoclean_protected-months, and there is a protection? */
01462       if (_network_player_info[p->index].months_empty > _network_autoclean_protected && _network_player_info[p->index].password[0] != '\0') {
01463         /* Unprotect the company */
01464         _network_player_info[p->index].password[0] = '\0';
01465         IConsolePrintF(_icolour_def, "Auto-removed protection from company #%d", p->index+1);
01466         _network_player_info[p->index].months_empty = 0;
01467       }
01468     } else {
01469       /* It is not empty, reset the date */
01470       _network_player_info[p->index].months_empty = 0;
01471     }
01472   }
01473 }
01474 
01475 // This function changes new_name to a name that is unique (by adding #1 ...)
01476 //  and it returns true if that succeeded.
01477 bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH])
01478 {
01479   NetworkTCPSocketHandler *new_cs;
01480   bool found_name = false;
01481   byte number = 0;
01482   char original_name[NETWORK_CLIENT_NAME_LENGTH];
01483 
01484   // We use NETWORK_CLIENT_NAME_LENGTH in here, because new_name is really a pointer
01485   ttd_strlcpy(original_name, new_name, NETWORK_CLIENT_NAME_LENGTH);
01486 
01487   while (!found_name) {
01488     const NetworkClientInfo *ci;
01489 
01490     found_name = true;
01491     FOR_ALL_CLIENTS(new_cs) {
01492       ci = DEREF_CLIENT_INFO(new_cs);
01493       if (strcmp(ci->client_name, new_name) == 0) {
01494         // Name already in use
01495         found_name = false;
01496         break;
01497       }
01498     }
01499     // Check if it is the same as the server-name
01500     ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
01501     if (ci != NULL) {
01502       if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
01503     }
01504 
01505     if (!found_name) {
01506       // Try a new name (<name> #1, <name> #2, and so on)
01507 
01508       // Stop if we tried for more than 50 times..
01509       if (number++ > 50) break;
01510       snprintf(new_name, NETWORK_CLIENT_NAME_LENGTH, "%s #%d", original_name, number);
01511     }
01512   }
01513 
01514   return found_name;
01515 }
01516 
01517 // Reads a packet from the stream
01518 bool NetworkServer_ReadPackets(NetworkTCPSocketHandler *cs)
01519 {
01520   Packet *p;
01521   NetworkRecvStatus res;
01522   while ((p = cs->Recv_Packet(&res)) != NULL) {
01523     byte type = p->Recv_uint8();
01524     if (type < PACKET_END && _network_server_packet[type] != NULL && !cs->has_quit) {
01525       _network_server_packet[type](cs, p);
01526     } else {
01527       DEBUG(net, 0, "[server] received invalid packet type %d", type);
01528     }
01529     delete p;
01530   }
01531 
01532   return true;
01533 }
01534 
01535 // Handle the local command-queue
01536 static void NetworkHandleCommandQueue(NetworkTCPSocketHandler* cs)
01537 {
01538   CommandPacket *cp;
01539 
01540   while ( (cp = cs->command_queue) != NULL) {
01541     SEND_COMMAND(PACKET_SERVER_COMMAND)(cs, cp);
01542 
01543     cs->command_queue = cp->next;
01544     free(cp);
01545   }
01546 }
01547 
01548 // This is called every tick if this is a _network_server
01549 void NetworkServer_Tick(bool send_frame)
01550 {
01551   NetworkTCPSocketHandler *cs;
01552 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01553   bool send_sync = false;
01554 #endif
01555 
01556 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01557   if (_frame_counter >= _last_sync_frame + _network_sync_freq) {
01558     _last_sync_frame = _frame_counter;
01559     send_sync = true;
01560   }
01561 #endif
01562 
01563   // Now we are done with the frame, inform the clients that they can
01564   //  do their frame!
01565   FOR_ALL_CLIENTS(cs) {
01566     // Check if the speed of the client is what we can expect from a client
01567     if (cs->status == STATUS_ACTIVE) {
01568       // 1 lag-point per day
01569       int lag = NetworkCalculateLag(cs) / DAY_TICKS;
01570       if (lag > 0) {
01571         if (lag > 3) {
01572           // Client did still not report in after 4 game-day, drop him
01573           //  (that is, the 3 of above, + 1 before any lag is counted)
01574           IConsolePrintF(_icolour_err,"Client #%d is dropped because the client did not respond for more than 4 game-days", cs->index);
01575           NetworkCloseClient(cs);
01576           continue;
01577         }
01578 
01579         // Report once per time we detect the lag
01580         if (cs->lag_test == 0) {
01581           IConsolePrintF(_icolour_warn,"[%d] Client #%d is slow, try increasing *net_frame_freq to a higher value!", _frame_counter, cs->index);
01582           cs->lag_test = 1;
01583         }
01584       } else {
01585         cs->lag_test = 0;
01586       }
01587     } else if (cs->status == STATUS_PRE_ACTIVE) {
01588       int lag = NetworkCalculateLag(cs);
01589       if (lag > _network_max_join_time) {
01590         IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time);
01591         NetworkCloseClient(cs);
01592       }
01593     } else if (cs->status == STATUS_INACTIVE) {
01594       int lag = NetworkCalculateLag(cs);
01595       if (lag > 4 * DAY_TICKS) {
01596         IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->index, 4 * DAY_TICKS);
01597         NetworkCloseClient(cs);
01598       }
01599     }
01600 
01601     if (cs->status >= STATUS_PRE_ACTIVE) {
01602       // Check if we can send command, and if we have anything in the queue
01603       NetworkHandleCommandQueue(cs);
01604 
01605       // Send an updated _frame_counter_max to the client
01606       if (send_frame) SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
01607 
01608 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01609       // Send a sync-check packet
01610       if (send_sync) SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
01611 #endif
01612     }
01613   }
01614 
01615   /* See if we need to advertise */
01616   NetworkUDPAdvertise();
01617 }
01618 
01619 void NetworkServerYearlyLoop()
01620 {
01621   NetworkCheckRestartMap();
01622 }
01623 
01624 void NetworkServerMonthlyLoop()
01625 {
01626   NetworkAutoCleanCompanies();
01627 }
01628 
01629 #endif /* ENABLE_NETWORK */

Generated on Mon Sep 22 20:34:16 2008 for openttd by  doxygen 1.5.6