# 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 */