# network_admin.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    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 (c->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
    00488 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRcon(uint16 colour, const char *result)
    00489 {
    00490   Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON);
    00491
    00492   p->Send_uint16(colour);
    00493   p->Send_string(result);
    00494   this->SendPacket(p);
    00495
    00496   return NETWORK_RECV_STATUS_OKAY;
    00497 }
    00498
    00499 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet *p)
    00500 {
    00501   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00502
    00503   char command[NETWORK_RCONCOMMAND_LENGTH];
    00504
    00505   p->Recv_string(command, sizeof(command));
    00506
    00507   DEBUG(net, 2, "[admin] Rcon command from '%s' (%s): '%s'", this->admin_name, this->admin_version, command);
    00508
    00509   _redirect_console_to_admin = this->index;
    00510   IConsoleCmdExec(command);
    00511   _redirect_console_to_admin = INVALID_ADMIN_ID;
    00512   return NETWORK_RECV_STATUS_OKAY;
    00513 }
    00514
    00515 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet *p)
    00516 {
    00517   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00518
    00519   char json[NETWORK_GAMESCRIPT_JSON_LENGTH];
    00520
    00521   p->Recv_string(json, sizeof(json));
    00522
    00523   DEBUG(net, 2, "[admin] GameScript JSON from '%s' (%s): '%s'", this->admin_name, this->admin_version, json);
    00524
    00525   Game::NewEvent(new ScriptEventAdminPort(json));
    00526   return NETWORK_RECV_STATUS_OKAY;
    00527 }
    00528
    00534 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const char *origin, const char *string)
    00535 {
    00536   /* If the length of both strings, plus the 2 '\0' terminations and 3 bytes of the packet
    00537    * are bigger than the MTU, just ignore the message. Better safe than sorry. It should
    00538    * never occur though as the longest strings are chat messages, which are still 30%
    00539    * smaller than SEND_MTU. */
    00540   if (strlen(origin) + strlen(string) + 2 + 3 >= SEND_MTU) return NETWORK_RECV_STATUS_OKAY;
    00541
    00542   Packet *p = new Packet(ADMIN_PACKET_SERVER_CONSOLE);
    00543
    00544   p->Send_string(origin);
    00545   p->Send_string(string);
    00546   this->SendPacket(p);
    00547
    00548   return NETWORK_RECV_STATUS_OKAY;
    00549 }
    00550
    00555 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendGameScript(const char *json)
    00556 {
    00557   /* At the moment we cannot transmit anything larger than MTU. So the string
    00558    *  has to be no longer than the length of the json + '\0' + 3 bytes of the
    00559    *  packet header. */
    00560   if (strlen(json) + 1 + 3 >= SEND_MTU) return NETWORK_RECV_STATUS_OKAY;
    00561
    00562   Packet *p = new Packet(ADMIN_PACKET_SERVER_GAMESCRIPT);
    00563
    00564   p->Send_string(json);
    00565   this->SendPacket(p);
    00566
    00567   return NETWORK_RECV_STATUS_OKAY;
    00568 }
    00569
    00571 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdNames()
    00572 {
    00573   Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
    00574
    00575   for (uint i = 0; i < CMD_END; i++) {
    00576     const char *cmdname = GetCommandName(i);
    00577
    00578     /* Should SEND_MTU be exceeded, start a new packet
    00579      * (magic 5: 1 bool "more data" and one uint16 "command id", one
    00580      * byte for string '\0' termination and 1 bool "no more data" */
    00581     if (p->size + strlen(cmdname) + 5 >= SEND_MTU) {
    00582       p->Send_bool(false);
    00583       this->SendPacket(p);
    00584
    00585       p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
    00586     }
    00587
    00588     p->Send_bool(true);
    00589     p->Send_uint16(i);
    00590     p->Send_string(cmdname);
    00591   }
    00592
    00593   /* Marker to notify the end of the packet has been reached. */
    00594   p->Send_bool(false);
    00595   this->SendPacket(p);
    00596
    00597   return NETWORK_RECV_STATUS_OKAY;
    00598 }
    00599
    00605 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdLogging(ClientID client_id, const CommandPacket *cp)
    00606 {
    00607   Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_LOGGING);
    00608
    00609   p->Send_uint32(client_id);
    00610   p->Send_uint8 (cp->company);
    00611   p->Send_uint16(cp->cmd & CMD_ID_MASK);
    00612   p->Send_uint32(cp->p1);
    00613   p->Send_uint32(cp->p2);
    00614   p->Send_uint32(cp->tile);
    00615   p->Send_string(cp->text);
    00616   p->Send_uint32(cp->frame);
    00617
    00618   this->SendPacket(p);
    00619
    00620   return NETWORK_RECV_STATUS_OKAY;
    00621 }
    00622
    00623 /***********
    00624  * Receiving functions
    00625  ************/
    00626
    00627 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet *p)
    00628 {
    00629   if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00630
    00631   char password[NETWORK_PASSWORD_LENGTH];
    00632   p->Recv_string(password, sizeof(password));
    00633
    00634   if (StrEmpty(_settings_client.network.admin_password) ||
    00635       strcmp(password, _settings_client.network.admin_password) != 0) {
    00636     /* Password is invalid */
    00637     return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
    00638   }
    00639
    00640   p->Recv_string(this->admin_name, sizeof(this->admin_name));
    00641   p->Recv_string(this->admin_version, sizeof(this->admin_version));
    00642
    00643   if (StrEmpty(this->admin_name) || StrEmpty(this->admin_version)) {
    00644     /* no name or version supplied */
    00645     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00646   }
    00647
    00648   this->status = ADMIN_STATUS_ACTIVE;
    00649
    00650   DEBUG(net, 1, "[admin] '%s' (%s) has connected", this->admin_name, this->admin_version);
    00651
    00652   return this->SendProtocol();
    00653 }
    00654
    00655 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_QUIT(Packet *p)
    00656 {
    00657   /* The admin is leaving nothing else to do */
    00658   return this->CloseConnection();
    00659 }
    00660
    00661 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENCY(Packet *p)
    00662 {
    00663   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00664
    00665   AdminUpdateType type = (AdminUpdateType)p->Recv_uint16();
    00666   AdminUpdateFrequency freq = (AdminUpdateFrequency)p->Recv_uint16();
    00667
    00668   if (type >= ADMIN_UPDATE_END || (_admin_update_type_frequencies[type] & freq) != freq) {
    00669     /* The server does not know of this UpdateType. */
    00670     DEBUG(net, 3, "[admin] Not supported update frequency %d (%d) from '%s' (%s).", type, freq, this->admin_name, this->admin_version);
    00671     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00672   }
    00673
    00674   this->update_frequency[type] = freq;
    00675
    00676   return NETWORK_RECV_STATUS_OKAY;
    00677 }
    00678
    00679 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet *p)
    00680 {
    00681   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00682
    00683   AdminUpdateType type = (AdminUpdateType)p->Recv_uint8();
    00684   uint32 d1 = p->Recv_uint32();
    00685
    00686   switch (type) {
    00687     case ADMIN_UPDATE_DATE:
    00688       /* The admin is requesting the current date. */
    00689       this->SendDate();
    00690       break;
    00691
    00692     case ADMIN_UPDATE_CLIENT_INFO:
    00693       /* The admin is requesting client info. */
    00694       const NetworkClientSocket *cs;
    00695       if (d1 == UINT32_MAX) {
    00696         this->SendClientInfo(NULL, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
    00697         FOR_ALL_CLIENT_SOCKETS(cs) {
    00698           this->SendClientInfo(cs, cs->GetInfo());
    00699         }
    00700       } else {
    00701         if (d1 == CLIENT_ID_SERVER) {
    00702           this->SendClientInfo(NULL, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
    00703         } else {
    00704           cs = NetworkClientSocket::GetByClientID((ClientID)d1);
    00705           if (cs != NULL) this->SendClientInfo(cs, cs->GetInfo());
    00706         }
    00707       }
    00708       break;
    00709
    00710     case ADMIN_UPDATE_COMPANY_INFO:
    00711       /* The admin is asking for company info. */
    00712       const Company *company;
    00713       if (d1 == UINT32_MAX) {
    00714         FOR_ALL_COMPANIES(company) {
    00715           this->SendCompanyInfo(company);
    00716         }
    00717       } else {
    00718         company = Company::GetIfValid(d1);
    00719         if (company != NULL) this->SendCompanyInfo(company);
    00720       }
    00721       break;
    00722
    00723     case ADMIN_UPDATE_COMPANY_ECONOMY:
    00724       /* The admin is requesting economy info. */
    00725       this->SendCompanyEconomy();
    00726       break;
    00727
    00728     case ADMIN_UPDATE_COMPANY_STATS:
    00729       /* the admin is requesting company stats. */
    00730       this->SendCompanyStats();
    00731       break;
    00732
    00733     case ADMIN_UPDATE_CMD_NAMES:
    00734       /* The admin is requesting the names of DoCommands. */
    00735       this->SendCmdNames();
    00736       break;
    00737
    00738     default:
    00739       /* An unsupported "poll" update type. */
    00740       DEBUG(net, 3, "[admin] Not supported poll %d (%d) from '%s' (%s).", type, d1, this->admin_name, this->admin_version);
    00741       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00742   }
    00743
    00744   return NETWORK_RECV_STATUS_OKAY;
    00745 }
    00746
    00747 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet *p)
    00748 {
    00749   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00750
    00751   NetworkAction action = (NetworkAction)p->Recv_uint8();
    00752   DestType desttype = (DestType)p->Recv_uint8();
    00753   int dest = p->Recv_uint32();
    00754
    00755   char msg[NETWORK_CHAT_LENGTH];
    00756   p->Recv_string(msg, NETWORK_CHAT_LENGTH);
    00757
    00758   switch (action) {
    00759     case NETWORK_ACTION_CHAT:
    00760     case NETWORK_ACTION_CHAT_CLIENT:
    00761     case NETWORK_ACTION_CHAT_COMPANY:
    00762     case NETWORK_ACTION_SERVER_MESSAGE:
    00763       NetworkServerSendChat(action, desttype, dest, msg, _network_own_client_id, 0, true);
    00764       break;
    00765
    00766     default:
    00767       DEBUG(net, 3, "[admin] Invalid chat action %d from admin '%s' (%s).", action, this->admin_name, this->admin_version);
    00768       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00769   }
    00770
    00771   return NETWORK_RECV_STATUS_OKAY;
    00772 }
    00773
    00774 /*
    00775  * Useful wrapper functions
    00776  */
    00777
    00783 void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client)
    00784 {
    00785   ServerNetworkAdminSocketHandler *as;
    00786   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00787     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00788       as->SendClientInfo(cs, cs->GetInfo());
    00789       if (new_client) {
    00790         as->SendClientJoin(cs->client_id);
    00791       }
    00792     }
    00793   }
    00794 }
    00795
    00800 void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
    00801 {
    00802   ServerNetworkAdminSocketHandler *as;
    00803   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00804     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00805       as->SendClientUpdate(ci);
    00806     }
    00807   }
    00808 }
    00809
    00814 void NetworkAdminClientQuit(ClientID client_id)
    00815 {
    00816   ServerNetworkAdminSocketHandler *as;
    00817   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00818     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00819       as->SendClientQuit(client_id);
    00820     }
    00821   }
    00822 }
    00823
    00829 void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code)
    00830 {
    00831   ServerNetworkAdminSocketHandler *as;
    00832   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00833     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00834       as->SendClientError(client_id, error_code);
    00835     }
    00836   }
    00837 }
    00838
    00844 void NetworkAdminCompanyInfo(const Company *company, bool new_company)
    00845 {
    00846   if (company == NULL) {
    00847     DEBUG(net, 1, "[admin] Empty company given for update");
    00848     return;
    00849   }
    00850
    00851   ServerNetworkAdminSocketHandler *as;
    00852   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00853     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
    00854
    00855     as->SendCompanyInfo(company);
    00856     if (new_company) {
    00857       as->SendCompanyNew(company->index);
    00858     }
    00859   }
    00860 }
    00861
    00866 void NetworkAdminCompanyUpdate(const Company *company)
    00867 {
    00868   if (company == NULL) return;
    00869
    00870   ServerNetworkAdminSocketHandler *as;
    00871   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00872     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
    00873
    00874     as->SendCompanyUpdate(company);
    00875   }
    00876 }
    00877
    00883 void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bcrr)
    00884 {
    00885   ServerNetworkAdminSocketHandler *as;
    00886   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00887     as->SendCompanyRemove(company_id, bcrr);
    00888   }
    00889 }
    00890
    00891
    00895 void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data, bool from_admin)
    00896 {
    00897   if (from_admin) return;
    00898
    00899   ServerNetworkAdminSocketHandler *as;
    00900   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00901     if (as->update_frequency[ADMIN_UPDATE_CHAT] & ADMIN_FREQUENCY_AUTOMATIC) {
    00902       as->SendChat(action, desttype, client_id, msg, data);
    00903     }
    00904   }
    00905 }
    00906
    00913 void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, const char *string)
    00914 {
    00915   ServerNetworkAdminSocketHandler::Get(admin_index)->SendRcon(colour_code, string);
    00916 }
    00917
    00923 void NetworkAdminConsole(const char *origin, const char *string)
    00924 {
    00925   ServerNetworkAdminSocketHandler *as;
    00926   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00927     if (as->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) {
    00928       as->SendConsole(origin, string);
    00929     }
    00930   }
    00931 }
    00932
    00937 void NetworkAdminGameScript(const char *json)
    00938 {
    00939   ServerNetworkAdminSocketHandler *as;
    00940   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00941     if (as->update_frequency[ADMIN_UPDATE_GAMESCRIPT] & ADMIN_FREQUENCY_AUTOMATIC) {
    00942       as->SendGameScript(json);
    00943     }
    00944   }
    00945 }
    00946
    00952 void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket *cp)
    00953 {
    00954   ClientID client_id = owner == NULL ? _network_own_client_id : owner->client_id;
    00955
    00956   ServerNetworkAdminSocketHandler *as;
    00957   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00958     if (as->update_frequency[ADMIN_UPDATE_CMD_LOGGING] & ADMIN_FREQUENCY_AUTOMATIC) {
    00959       as->SendCmdLogging(client_id, cp);
    00960     }
    00961   }
    00962 }
    00963
    00967 void ServerNetworkAdminSocketHandler::WelcomeAll()
    00968 {
    00969   ServerNetworkAdminSocketHandler *as;
    00970   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00971     as->SendWelcome();
    00972   }
    00973 }
    00974
    00979 void NetworkAdminUpdate(AdminUpdateFrequency freq)
    00980 {
    00981   ServerNetworkAdminSocketHandler *as;
    00982   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00983     for (int i = 0; i < ADMIN_UPDATE_END; i++) {
    00984       if (as->update_frequency[i] & freq) {
    00985         /* Update the admin for the required details */
    00986         switch (i) {
    00987           case ADMIN_UPDATE_DATE:
    00988             as->SendDate();
    00989             break;
    00990
    00991           case ADMIN_UPDATE_COMPANY_ECONOMY:
    00992             as->SendCompanyEconomy();
    00993             break;
    00994
    00995           case ADMIN_UPDATE_COMPANY_STATS:
    00996             as->SendCompanyStats();
    00997             break;
    00998
    00999           default: NOT_REACHED();
    01000         }
    01001       }
    01002     }
    01003   }
    01004 }
    01005
    01006 #endif /* ENABLE_NETWORK */