# network_admin.cpp

Go to the documentation of this file.

    00001 /* $Id: network_admin.cpp 25599 2013-07-13 10:13:55Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #ifdef ENABLE_NETWORK
    00013
    00014 #include "../stdafx.h"
    00015 #include "../strings_func.h"
    00016 #include "../date_func.h"
    00017 #include "network_admin.h"
    00018 #include "network_base.h"
    00019 #include "network_server.h"
    00020 #include "../command_func.h"
    00021 #include "../company_base.h"
    00022 #include "../console_func.h"
    00023 #include "../core/pool_func.hpp"
    00024 #include "../map_func.h"
    00025 #include "../rev.h"
    00026 #include "../game/game.hpp"
    00027
    00028
    00029 /* This file handles all the admin network commands. */
    00030
    00032 AdminIndex _redirect_console_to_admin = INVALID_ADMIN_ID;
    00033
    00035 byte _network_admins_connected = 0;
    00036
    00038 NetworkAdminSocketPool _networkadminsocket_pool("NetworkAdminSocket");
    00039 INSTANTIATE_POOL_METHODS(NetworkAdminSocket)
    00040
    00041
    00042 static const int ADMIN_AUTHORISATION_TIMEOUT = 10000;
    00043
    00044
    00046 static const AdminUpdateFrequency _admin_update_type_frequencies[] = {
    00047   ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_DAILY | ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY,
    00048   ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_AUTOMATIC,
    00049   ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_AUTOMATIC,
    00050   ADMIN_FREQUENCY_POLL |                         ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY,
    00051   ADMIN_FREQUENCY_POLL |                         ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY,
    00052                          ADMIN_FREQUENCY_AUTOMATIC,
    00053                          ADMIN_FREQUENCY_AUTOMATIC,
    00054   ADMIN_FREQUENCY_POLL,
    00055                          ADMIN_FREQUENCY_AUTOMATIC,
    00056                          ADMIN_FREQUENCY_AUTOMATIC,
    00057 };
    00059 assert_compile(lengthof(_admin_update_type_frequencies) == ADMIN_UPDATE_END);
    00060
    00065 ServerNetworkAdminSocketHandler::ServerNetworkAdminSocketHandler(SOCKET s) : NetworkAdminSocketHandler(s)
    00066 {
    00067   _network_admins_connected++;
    00068   this->status = ADMIN_STATUS_INACTIVE;
    00069   this->realtime_connect = _realtime_tick;
    00070 }
    00071
    00075 ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler()
    00076 {
    00077   _network_admins_connected--;
    00078   DEBUG(net, 1, "[admin] '%s' (%s) has disconnected", this->admin_name, this->admin_version);
    00079   if (_redirect_console_to_admin == this->index) _redirect_console_to_admin = INVALID_ADMIN_ID;
    00080 }
    00081
    00086 /* static */ bool ServerNetworkAdminSocketHandler::AllowConnection()
    00087 {
    00088   bool accept = !StrEmpty(_settings_client.network.admin_password) && _network_admins_connected < MAX_ADMINS;
    00089   /* We can't go over the MAX_ADMINS limit here. However, if we accept
    00090    * the connection, there has to be space in the pool. */
    00091   assert_compile(NetworkAdminSocketPool::MAX_SIZE == MAX_ADMINS);
    00092   assert(!accept || ServerNetworkAdminSocketHandler::CanAllocateItem());
    00093   return accept;
    00094 }
    00095
    00097 /* static */ void ServerNetworkAdminSocketHandler::Send()
    00098 {
    00099   ServerNetworkAdminSocketHandler *as;
    00100   FOR_ALL_ADMIN_SOCKETS(as) {
    00101     if (as->status == ADMIN_STATUS_INACTIVE && as->realtime_connect + ADMIN_AUTHORISATION_TIMEOUT < _realtime_tick) {
    00102       DEBUG(net, 1, "[admin] Admin did not send its authorisation within %d seconds", ADMIN_AUTHORISATION_TIMEOUT / 1000);
    00103       as->CloseConnection(true);
    00104       continue;
    00105     }
    00106     if (as->writable) {
    00107       as->SendPackets();
    00108     }
    00109   }
    00110 }
    00111
    00117 /* static */ void ServerNetworkAdminSocketHandler::AcceptConnection(SOCKET s, const NetworkAddress &address)
    00118 {
    00119   ServerNetworkAdminSocketHandler *as = new ServerNetworkAdminSocketHandler(s);
    00120   as->address = address; // Save the IP of the client
    00121 }
    00122
    00123 /***********
    00124  * Sending functions for admin network
    00125  ************/
    00126
    00131 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode error)
    00132 {
    00133   Packet *p = new Packet(ADMIN_PACKET_SERVER_ERROR);
    00134
    00135   p->Send_uint8(error);
    00136   this->SendPacket(p);
    00137
    00138   char str[100];
    00139   StringID strid = GetNetworkErrorMsg(error);
    00140   GetString(str, strid, lastof(str));
    00141
    00142   DEBUG(net, 1, "[admin] the admin '%s' (%s) made an error and has been disconnected. Reason: '%s'", this->admin_name, this->admin_version, str);
    00143
    00144   return this->CloseConnection(true);
    00145 }
    00146
    00148 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendProtocol()
    00149 {
    00150   Packet *p = new Packet(ADMIN_PACKET_SERVER_PROTOCOL);
    00151
    00152   /* announce the protocol version */
    00153   p->Send_uint8(NETWORK_GAME_ADMIN_VERSION);
    00154
    00155   for (int i = 0; i < ADMIN_UPDATE_END; i++) {
    00156     p->Send_bool  (true);
    00157     p->Send_uint16(i);
    00158     p->Send_uint16(_admin_update_type_frequencies[i]);
    00159   }
    00160
    00161   p->Send_bool(false);
    00162   this->SendPacket(p);
    00163
    00164   return this->SendWelcome();
    00165 }
    00166
    00168 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendWelcome()
    00169 {
    00170   Packet *p = new Packet(ADMIN_PACKET_SERVER_WELCOME);
    00171
    00172   p->Send_string(_settings_client.network.server_name);
    00173   p->Send_string(_openttd_revision);
    00174   p->Send_bool  (_network_dedicated);
    00175
    00176   p->Send_string(_network_game_info.map_name);
    00177   p->Send_uint32(_settings_game.game_creation.generation_seed);
    00178   p->Send_uint8 (_settings_game.game_creation.landscape);
    00179   p->Send_uint32(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
    00180   p->Send_uint16(MapSizeX());
    00181   p->Send_uint16(MapSizeY());
    00182
    00183   this->SendPacket(p);
    00184
    00185   return NETWORK_RECV_STATUS_OKAY;
    00186 }
    00187
    00189 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendNewGame()
    00190 {
    00191   Packet *p = new Packet(ADMIN_PACKET_SERVER_NEWGAME);
    00192   this->SendPacket(p);
    00193   return NETWORK_RECV_STATUS_OKAY;
    00194 }
    00195
    00197 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendShutdown()
    00198 {
    00199   Packet *p = new Packet(ADMIN_PACKET_SERVER_SHUTDOWN);
    00200   this->SendPacket(p);
    00201   return NETWORK_RECV_STATUS_OKAY;
    00202 }
    00203
    00205 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendDate()
    00206 {
    00207   Packet *p = new Packet(ADMIN_PACKET_SERVER_DATE);
    00208
    00209   p->Send_uint32(_date);
    00210   this->SendPacket(p);
    00211
    00212   return NETWORK_RECV_STATUS_OKAY;
    00213 }
    00214
    00219 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientJoin(ClientID client_id)
    00220 {
    00221   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_JOIN);
    00222
    00223   p->Send_uint32(client_id);
    00224   this->SendPacket(p);
    00225
    00226   return NETWORK_RECV_STATUS_OKAY;
    00227 }
    00228
    00234 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientInfo(const NetworkClientSocket *cs, const NetworkClientInfo *ci)
    00235 {
    00236   /* Only send data when we're a proper client, not just someone trying to query the server. */
    00237   if (ci == NULL) return NETWORK_RECV_STATUS_OKAY;
    00238
    00239   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_INFO);
    00240
    00241   p->Send_uint32(ci->client_id);
    00242   p->Send_string(cs == NULL ? "" : const_cast<NetworkAddress &>(cs->client_address).GetHostname());
    00243   p->Send_string(ci->client_name);
    00244   p->Send_uint8 (ci->client_lang);
    00245   p->Send_uint32(ci->join_date);
    00246   p->Send_uint8 (ci->client_playas);
    00247
    00248   this->SendPacket(p);
    00249
    00250   return NETWORK_RECV_STATUS_OKAY;
    00251 }
    00252
    00253
    00258 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientUpdate(const NetworkClientInfo *ci)
    00259 {
    00260   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_UPDATE);
    00261
    00262   p->Send_uint32(ci->client_id);
    00263   p->Send_string(ci->client_name);
    00264   p->Send_uint8 (ci->client_playas);
    00265
    00266   this->SendPacket(p);
    00267
    00268   return NETWORK_RECV_STATUS_OKAY;
    00269 }
    00270
    00275 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientQuit(ClientID client_id)
    00276 {
    00277   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_QUIT);
    00278
    00279   p->Send_uint32(client_id);
    00280   this->SendPacket(p);
    00281
    00282   return NETWORK_RECV_STATUS_OKAY;
    00283 }
    00284
    00290 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientError(ClientID client_id, NetworkErrorCode error)
    00291 {
    00292   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_ERROR);
    00293
    00294   p->Send_uint32(client_id);
    00295   p->Send_uint8 (error);
    00296   this->SendPacket(p);
    00297
    00298   return NETWORK_RECV_STATUS_OKAY;
    00299 }
    00300
    00305 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyNew(CompanyID company_id)
    00306 {
    00307   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_NEW);
    00308   p->Send_uint8(company_id);
    00309
    00310   this->SendPacket(p);
    00311
    00312   return NETWORK_RECV_STATUS_OKAY;
    00313 }
    00314
    00319 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company *c)
    00320 {
    00321   char company_name[NETWORK_COMPANY_NAME_LENGTH];
    00322   char manager_name[NETWORK_COMPANY_NAME_LENGTH];
    00323
    00324   SetDParam(0, c->index);
    00325   GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
    00326
    00327   SetDParam(0, c->index);
    00328   GetString(manager_name, STR_PRESIDENT_NAME, lastof(manager_name));
    00329
    00330   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_INFO);
    00331
    00332   p->Send_uint8 (c->index);
    00333   p->Send_string(company_name);
    00334   p->Send_string(manager_name);
    00335   p->Send_uint8 (c->colour);
    00336   p->Send_bool  (NetworkCompanyIsPassworded(c->index));
    00337   p->Send_uint32(c->inaugurated_year);
    00338   p->Send_bool  (c->is_ai);
    00339
    00340   this->SendPacket(p);
    00341
    00342   return NETWORK_RECV_STATUS_OKAY;
    00343 }
    00344
    00345
    00350 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyUpdate(const Company *c)
    00351 {
    00352   char company_name[NETWORK_COMPANY_NAME_LENGTH];
    00353   char manager_name[NETWORK_COMPANY_NAME_LENGTH];
    00354
    00355   SetDParam(0, c->index);
    00356   GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
    00357
    00358   SetDParam(0, c->index);
    00359   GetString(manager_name, STR_PRESIDENT_NAME, lastof(manager_name));
    00360
    00361   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_UPDATE);
    00362
    00363   p->Send_uint8 (c->index);
    00364   p->Send_string(company_name);
    00365   p->Send_string(manager_name);
    00366   p->Send_uint8 (c->colour);
    00367   p->Send_bool  (NetworkCompanyIsPassworded(c->index));
    00368   p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy
    00369
    00370   for (size_t i = 0; i < lengthof(c->share_owners); i++) {
    00371     p->Send_uint8(c->share_owners[i]);
    00372   }
    00373
    00374   this->SendPacket(p);
    00375
    00376   return NETWORK_RECV_STATUS_OKAY;
    00377 }
    00378
    00384 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason acrr)
    00385 {
    00386   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_REMOVE);
    00387
    00388   p->Send_uint8(company_id);
    00389   p->Send_uint8(acrr);
    00390
    00391   this->SendPacket(p);
    00392
    00393   return NETWORK_RECV_STATUS_OKAY;
    00394 }
    00395
    00397 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyEconomy()
    00398 {
    00399   const Company *company;
    00400   FOR_ALL_COMPANIES(company) {
    00401     /* Get the income. */
    00402     Money income = 0;
    00403     for (uint i = 0; i < lengthof(company->yearly_expenses[0]); i++) {
    00404       income -= company->yearly_expenses[0][i];
    00405     }
    00406
    00407     Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_ECONOMY);
    00408
    00409     p->Send_uint8(company->index);
    00410
    00411     /* Current information. */
    00412     p->Send_uint64(company->money);
    00413     p->Send_uint64(company->current_loan);
    00414     p->Send_uint64(income);
    00415     p->Send_uint16(min(UINT16_MAX, company->cur_economy.delivered_cargo.GetSum<OverflowSafeInt64>()));
    00416
    00417     /* Send stats for the last 2 quarters. */
    00418     for (uint i = 0; i < 2; i++) {
    00419       p->Send_uint64(company->old_economy[i].company_value);
    00420       p->Send_uint16(company->old_economy[i].performance_history);
    00421       p->Send_uint16(min(UINT16_MAX, company->old_economy[i].delivered_cargo.GetSum<OverflowSafeInt64>()));
    00422     }
    00423
    00424     this->SendPacket(p);
    00425   }
    00426
    00427
    00428   return NETWORK_RECV_STATUS_OKAY;
    00429 }
    00430
    00432 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyStats()
    00433 {
    00434   /* Fetch the latest version of the stats. */
    00435   NetworkCompanyStats company_stats[MAX_COMPANIES];
    00436   NetworkPopulateCompanyStats(company_stats);
    00437
    00438   const Company *company;
    00439
    00440   /* Go through all the companies. */
    00441   FOR_ALL_COMPANIES(company) {
    00442     Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_STATS);
    00443
    00444     /* Send the information. */
    00445     p->Send_uint8(company->index);
    00446
    00447     for (uint i = 0; i < NETWORK_VEH_END; i++) {
    00448       p->Send_uint16(company_stats[company->index].num_vehicle[i]);
    00449     }
    00450
    00451     for (uint i = 0; i < NETWORK_VEH_END; i++) {
    00452       p->Send_uint16(company_stats[company->index].num_station[i]);
    00453     }
    00454
    00455     this->SendPacket(p);
    00456   }
    00457
    00458   return NETWORK_RECV_STATUS_OKAY;
    00459 }
    00460
    00469 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data)
    00470 {
    00471   Packet *p = new Packet(ADMIN_PACKET_SERVER_CHAT);
    00472
    00473   p->Send_uint8 (action);
    00474   p->Send_uint8 (desttype);
    00475   p->Send_uint32(client_id);
    00476   p->Send_string(msg);
    00477   p->Send_uint64(data);
    00478
    00479   this->SendPacket(p);
    00480   return NETWORK_RECV_STATUS_OKAY;
    00481 }
    00482
    00487 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRconEnd(const char *command)
    00488 {
    00489   Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON_END);
    00490
    00491   p->Send_string(command);
    00492   this->SendPacket(p);
    00493
    00494   return NETWORK_RECV_STATUS_OKAY;
    00495 }
    00496
    00502 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRcon(uint16 colour, const char *result)
    00503 {
    00504   Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON);
    00505
    00506   p->Send_uint16(colour);
    00507   p->Send_string(result);
    00508   this->SendPacket(p);
    00509
    00510   return NETWORK_RECV_STATUS_OKAY;
    00511 }
    00512
    00513 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet *p)
    00514 {
    00515   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00516
    00517   char command[NETWORK_RCONCOMMAND_LENGTH];
    00518
    00519   p->Recv_string(command, sizeof(command));
    00520
    00521   DEBUG(net, 2, "[admin] Rcon command from '%s' (%s): '%s'", this->admin_name, this->admin_version, command);
    00522
    00523   _redirect_console_to_admin = this->index;
    00524   IConsoleCmdExec(command);
    00525   _redirect_console_to_admin = INVALID_ADMIN_ID;
    00526   return this->SendRconEnd(command);
    00527 }
    00528
    00529 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet *p)
    00530 {
    00531   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00532
    00533   char json[NETWORK_GAMESCRIPT_JSON_LENGTH];
    00534
    00535   p->Recv_string(json, sizeof(json));
    00536
    00537   DEBUG(net, 2, "[admin] GameScript JSON from '%s' (%s): '%s'", this->admin_name, this->admin_version, json);
    00538
    00539   Game::NewEvent(new ScriptEventAdminPort(json));
    00540   return NETWORK_RECV_STATUS_OKAY;
    00541 }
    00542
    00543 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_PING(Packet *p)
    00544 {
    00545   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00546
    00547   uint32 d1 = p->Recv_uint32();
    00548
    00549   DEBUG(net, 2, "[admin] Ping from '%s' (%s): '%d'", this->admin_name, this->admin_version, d1);
    00550
    00551   return this->SendPong(d1);
    00552 }
    00553
    00559 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const char *origin, const char *string)
    00560 {
    00561   /* If the length of both strings, plus the 2 '\0' terminations and 3 bytes of the packet
    00562    * are bigger than the MTU, just ignore the message. Better safe than sorry. It should
    00563    * never occur though as the longest strings are chat messages, which are still 30%
    00564    * smaller than SEND_MTU. */
    00565   if (strlen(origin) + strlen(string) + 2 + 3 >= SEND_MTU) return NETWORK_RECV_STATUS_OKAY;
    00566
    00567   Packet *p = new Packet(ADMIN_PACKET_SERVER_CONSOLE);
    00568
    00569   p->Send_string(origin);
    00570   p->Send_string(string);
    00571   this->SendPacket(p);
    00572
    00573   return NETWORK_RECV_STATUS_OKAY;
    00574 }
    00575
    00580 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendGameScript(const char *json)
    00581 {
    00582   /* At the moment we cannot transmit anything larger than MTU. So we limit
    00583    *  the maximum amount of json data that can be sent. Account also for
    00584    *  the trailing \0 of the string */
    00585   if (strlen(json) + 1 >= NETWORK_GAMESCRIPT_JSON_LENGTH) return NETWORK_RECV_STATUS_OKAY;
    00586
    00587   Packet *p = new Packet(ADMIN_PACKET_SERVER_GAMESCRIPT);
    00588
    00589   p->Send_string(json);
    00590   this->SendPacket(p);
    00591
    00592   return NETWORK_RECV_STATUS_OKAY;
    00593 }
    00594
    00596 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendPong(uint32 d1)
    00597 {
    00598   Packet *p = new Packet(ADMIN_PACKET_SERVER_PONG);
    00599
    00600   p->Send_uint32(d1);
    00601   this->SendPacket(p);
    00602
    00603   return NETWORK_RECV_STATUS_OKAY;
    00604 }
    00605
    00607 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdNames()
    00608 {
    00609   Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
    00610
    00611   for (uint i = 0; i < CMD_END; i++) {
    00612     const char *cmdname = GetCommandName(i);
    00613
    00614     /* Should SEND_MTU be exceeded, start a new packet
    00615      * (magic 5: 1 bool "more data" and one uint16 "command id", one
    00616      * byte for string '\0' termination and 1 bool "no more data" */
    00617     if (p->size + strlen(cmdname) + 5 >= SEND_MTU) {
    00618       p->Send_bool(false);
    00619       this->SendPacket(p);
    00620
    00621       p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
    00622     }
    00623
    00624     p->Send_bool(true);
    00625     p->Send_uint16(i);
    00626     p->Send_string(cmdname);
    00627   }
    00628
    00629   /* Marker to notify the end of the packet has been reached. */
    00630   p->Send_bool(false);
    00631   this->SendPacket(p);
    00632
    00633   return NETWORK_RECV_STATUS_OKAY;
    00634 }
    00635
    00641 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdLogging(ClientID client_id, const CommandPacket *cp)
    00642 {
    00643   Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_LOGGING);
    00644
    00645   p->Send_uint32(client_id);
    00646   p->Send_uint8 (cp->company);
    00647   p->Send_uint16(cp->cmd & CMD_ID_MASK);
    00648   p->Send_uint32(cp->p1);
    00649   p->Send_uint32(cp->p2);
    00650   p->Send_uint32(cp->tile);
    00651   p->Send_string(cp->text);
    00652   p->Send_uint32(cp->frame);
    00653
    00654   this->SendPacket(p);
    00655
    00656   return NETWORK_RECV_STATUS_OKAY;
    00657 }
    00658
    00659 /***********
    00660  * Receiving functions
    00661  ************/
    00662
    00663 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet *p)
    00664 {
    00665   if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00666
    00667   char password[NETWORK_PASSWORD_LENGTH];
    00668   p->Recv_string(password, sizeof(password));
    00669
    00670   if (StrEmpty(_settings_client.network.admin_password) ||
    00671       strcmp(password, _settings_client.network.admin_password) != 0) {
    00672     /* Password is invalid */
    00673     return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
    00674   }
    00675
    00676   p->Recv_string(this->admin_name, sizeof(this->admin_name));
    00677   p->Recv_string(this->admin_version, sizeof(this->admin_version));
    00678
    00679   if (StrEmpty(this->admin_name) || StrEmpty(this->admin_version)) {
    00680     /* no name or version supplied */
    00681     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00682   }
    00683
    00684   this->status = ADMIN_STATUS_ACTIVE;
    00685
    00686   DEBUG(net, 1, "[admin] '%s' (%s) has connected", this->admin_name, this->admin_version);
    00687
    00688   return this->SendProtocol();
    00689 }
    00690
    00691 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_QUIT(Packet *p)
    00692 {
    00693   /* The admin is leaving nothing else to do */
    00694   return this->CloseConnection();
    00695 }
    00696
    00697 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENCY(Packet *p)
    00698 {
    00699   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00700
    00701   AdminUpdateType type = (AdminUpdateType)p->Recv_uint16();
    00702   AdminUpdateFrequency freq = (AdminUpdateFrequency)p->Recv_uint16();
    00703
    00704   if (type >= ADMIN_UPDATE_END || (_admin_update_type_frequencies[type] & freq) != freq) {
    00705     /* The server does not know of this UpdateType. */
    00706     DEBUG(net, 3, "[admin] Not supported update frequency %d (%d) from '%s' (%s).", type, freq, this->admin_name, this->admin_version);
    00707     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00708   }
    00709
    00710   this->update_frequency[type] = freq;
    00711
    00712   return NETWORK_RECV_STATUS_OKAY;
    00713 }
    00714
    00715 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet *p)
    00716 {
    00717   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00718
    00719   AdminUpdateType type = (AdminUpdateType)p->Recv_uint8();
    00720   uint32 d1 = p->Recv_uint32();
    00721
    00722   switch (type) {
    00723     case ADMIN_UPDATE_DATE:
    00724       /* The admin is requesting the current date. */
    00725       this->SendDate();
    00726       break;
    00727
    00728     case ADMIN_UPDATE_CLIENT_INFO:
    00729       /* The admin is requesting client info. */
    00730       const NetworkClientSocket *cs;
    00731       if (d1 == UINT32_MAX) {
    00732         this->SendClientInfo(NULL, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
    00733         FOR_ALL_CLIENT_SOCKETS(cs) {
    00734           this->SendClientInfo(cs, cs->GetInfo());
    00735         }
    00736       } else {
    00737         if (d1 == CLIENT_ID_SERVER) {
    00738           this->SendClientInfo(NULL, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
    00739         } else {
    00740           cs = NetworkClientSocket::GetByClientID((ClientID)d1);
    00741           if (cs != NULL) this->SendClientInfo(cs, cs->GetInfo());
    00742         }
    00743       }
    00744       break;
    00745
    00746     case ADMIN_UPDATE_COMPANY_INFO:
    00747       /* The admin is asking for company info. */
    00748       const Company *company;
    00749       if (d1 == UINT32_MAX) {
    00750         FOR_ALL_COMPANIES(company) {
    00751           this->SendCompanyInfo(company);
    00752         }
    00753       } else {
    00754         company = Company::GetIfValid(d1);
    00755         if (company != NULL) this->SendCompanyInfo(company);
    00756       }
    00757       break;
    00758
    00759     case ADMIN_UPDATE_COMPANY_ECONOMY:
    00760       /* The admin is requesting economy info. */
    00761       this->SendCompanyEconomy();
    00762       break;
    00763
    00764     case ADMIN_UPDATE_COMPANY_STATS:
    00765       /* the admin is requesting company stats. */
    00766       this->SendCompanyStats();
    00767       break;
    00768
    00769     case ADMIN_UPDATE_CMD_NAMES:
    00770       /* The admin is requesting the names of DoCommands. */
    00771       this->SendCmdNames();
    00772       break;
    00773
    00774     default:
    00775       /* An unsupported "poll" update type. */
    00776       DEBUG(net, 3, "[admin] Not supported poll %d (%d) from '%s' (%s).", type, d1, this->admin_name, this->admin_version);
    00777       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00778   }
    00779
    00780   return NETWORK_RECV_STATUS_OKAY;
    00781 }
    00782
    00783 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet *p)
    00784 {
    00785   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00786
    00787   NetworkAction action = (NetworkAction)p->Recv_uint8();
    00788   DestType desttype = (DestType)p->Recv_uint8();
    00789   int dest = p->Recv_uint32();
    00790
    00791   char msg[NETWORK_CHAT_LENGTH];
    00792   p->Recv_string(msg, NETWORK_CHAT_LENGTH);
    00793
    00794   switch (action) {
    00795     case NETWORK_ACTION_CHAT:
    00796     case NETWORK_ACTION_CHAT_CLIENT:
    00797     case NETWORK_ACTION_CHAT_COMPANY:
    00798     case NETWORK_ACTION_SERVER_MESSAGE:
    00799       NetworkServerSendChat(action, desttype, dest, msg, _network_own_client_id, 0, true);
    00800       break;
    00801
    00802     default:
    00803       DEBUG(net, 3, "[admin] Invalid chat action %d from admin '%s' (%s).", action, this->admin_name, this->admin_version);
    00804       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00805   }
    00806
    00807   return NETWORK_RECV_STATUS_OKAY;
    00808 }
    00809
    00810 /*
    00811  * Useful wrapper functions
    00812  */
    00813
    00819 void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client)
    00820 {
    00821   ServerNetworkAdminSocketHandler *as;
    00822   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00823     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00824       as->SendClientInfo(cs, cs->GetInfo());
    00825       if (new_client) {
    00826         as->SendClientJoin(cs->client_id);
    00827       }
    00828     }
    00829   }
    00830 }
    00831
    00836 void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
    00837 {
    00838   ServerNetworkAdminSocketHandler *as;
    00839   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00840     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00841       as->SendClientUpdate(ci);
    00842     }
    00843   }
    00844 }
    00845
    00850 void NetworkAdminClientQuit(ClientID client_id)
    00851 {
    00852   ServerNetworkAdminSocketHandler *as;
    00853   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00854     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00855       as->SendClientQuit(client_id);
    00856     }
    00857   }
    00858 }
    00859
    00865 void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code)
    00866 {
    00867   ServerNetworkAdminSocketHandler *as;
    00868   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00869     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00870       as->SendClientError(client_id, error_code);
    00871     }
    00872   }
    00873 }
    00874
    00880 void NetworkAdminCompanyInfo(const Company *company, bool new_company)
    00881 {
    00882   if (company == NULL) {
    00883     DEBUG(net, 1, "[admin] Empty company given for update");
    00884     return;
    00885   }
    00886
    00887   ServerNetworkAdminSocketHandler *as;
    00888   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00889     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
    00890
    00891     as->SendCompanyInfo(company);
    00892     if (new_company) {
    00893       as->SendCompanyNew(company->index);
    00894     }
    00895   }
    00896 }
    00897
    00902 void NetworkAdminCompanyUpdate(const Company *company)
    00903 {
    00904   if (company == NULL) return;
    00905
    00906   ServerNetworkAdminSocketHandler *as;
    00907   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00908     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
    00909
    00910     as->SendCompanyUpdate(company);
    00911   }
    00912 }
    00913
    00919 void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bcrr)
    00920 {
    00921   ServerNetworkAdminSocketHandler *as;
    00922   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00923     as->SendCompanyRemove(company_id, bcrr);
    00924   }
    00925 }
    00926
    00927
    00931 void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data, bool from_admin)
    00932 {
    00933   if (from_admin) return;
    00934
    00935   ServerNetworkAdminSocketHandler *as;
    00936   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00937     if (as->update_frequency[ADMIN_UPDATE_CHAT] & ADMIN_FREQUENCY_AUTOMATIC) {
    00938       as->SendChat(action, desttype, client_id, msg, data);
    00939     }
    00940   }
    00941 }
    00942
    00949 void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, const char *string)
    00950 {
    00951   ServerNetworkAdminSocketHandler::Get(admin_index)->SendRcon(colour_code, string);
    00952 }
    00953
    00959 void NetworkAdminConsole(const char *origin, const char *string)
    00960 {
    00961   ServerNetworkAdminSocketHandler *as;
    00962   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00963     if (as->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) {
    00964       as->SendConsole(origin, string);
    00965     }
    00966   }
    00967 }
    00968
    00973 void NetworkAdminGameScript(const char *json)
    00974 {
    00975   ServerNetworkAdminSocketHandler *as;
    00976   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00977     if (as->update_frequency[ADMIN_UPDATE_GAMESCRIPT] & ADMIN_FREQUENCY_AUTOMATIC) {
    00978       as->SendGameScript(json);
    00979     }
    00980   }
    00981 }
    00982
    00988 void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket *cp)
    00989 {
    00990   ClientID client_id = owner == NULL ? _network_own_client_id : owner->client_id;
    00991
    00992   ServerNetworkAdminSocketHandler *as;
    00993   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00994     if (as->update_frequency[ADMIN_UPDATE_CMD_LOGGING] & ADMIN_FREQUENCY_AUTOMATIC) {
    00995       as->SendCmdLogging(client_id, cp);
    00996     }
    00997   }
    00998 }
    00999
    01003 void ServerNetworkAdminSocketHandler::WelcomeAll()
    01004 {
    01005   ServerNetworkAdminSocketHandler *as;
    01006   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    01007     as->SendWelcome();
    01008   }
    01009 }
    01010
    01015 void NetworkAdminUpdate(AdminUpdateFrequency freq)
    01016 {
    01017   ServerNetworkAdminSocketHandler *as;
    01018   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    01019     for (int i = 0; i < ADMIN_UPDATE_END; i++) {
    01020       if (as->update_frequency[i] & freq) {
    01021         /* Update the admin for the required details */
    01022         switch (i) {
    01023           case ADMIN_UPDATE_DATE:
    01024             as->SendDate();
    01025             break;
    01026
    01027           case ADMIN_UPDATE_COMPANY_ECONOMY:
    01028             as->SendCompanyEconomy();
    01029             break;
    01030
    01031           case ADMIN_UPDATE_COMPANY_STATS:
    01032             as->SendCompanyStats();
    01033             break;
    01034
    01035           default: NOT_REACHED();
    01036         }
    01037       }
    01038     }
    01039   }
    01040 }
    01041
    01042 #endif /* ENABLE_NETWORK */