# network_admin.cpp

Go to the documentation of this file.

    00001 /* $Id: network_admin.cpp 25845 2013-10-12 17:03:15Z planetmaker $ */
    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   p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy
    00340
    00341   for (size_t i = 0; i < lengthof(c->share_owners); i++) {
    00342     p->Send_uint8(c->share_owners[i]);
    00343   }
    00344
    00345   this->SendPacket(p);
    00346
    00347   return NETWORK_RECV_STATUS_OKAY;
    00348 }
    00349
    00350
    00355 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyUpdate(const Company *c)
    00356 {
    00357   char company_name[NETWORK_COMPANY_NAME_LENGTH];
    00358   char manager_name[NETWORK_COMPANY_NAME_LENGTH];
    00359
    00360   SetDParam(0, c->index);
    00361   GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
    00362
    00363   SetDParam(0, c->index);
    00364   GetString(manager_name, STR_PRESIDENT_NAME, lastof(manager_name));
    00365
    00366   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_UPDATE);
    00367
    00368   p->Send_uint8 (c->index);
    00369   p->Send_string(company_name);
    00370   p->Send_string(manager_name);
    00371   p->Send_uint8 (c->colour);
    00372   p->Send_bool  (NetworkCompanyIsPassworded(c->index));
    00373   p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy
    00374
    00375   for (size_t i = 0; i < lengthof(c->share_owners); i++) {
    00376     p->Send_uint8(c->share_owners[i]);
    00377   }
    00378
    00379   this->SendPacket(p);
    00380
    00381   return NETWORK_RECV_STATUS_OKAY;
    00382 }
    00383
    00389 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason acrr)
    00390 {
    00391   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_REMOVE);
    00392
    00393   p->Send_uint8(company_id);
    00394   p->Send_uint8(acrr);
    00395
    00396   this->SendPacket(p);
    00397
    00398   return NETWORK_RECV_STATUS_OKAY;
    00399 }
    00400
    00402 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyEconomy()
    00403 {
    00404   const Company *company;
    00405   FOR_ALL_COMPANIES(company) {
    00406     /* Get the income. */
    00407     Money income = 0;
    00408     for (uint i = 0; i < lengthof(company->yearly_expenses[0]); i++) {
    00409       income -= company->yearly_expenses[0][i];
    00410     }
    00411
    00412     Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_ECONOMY);
    00413
    00414     p->Send_uint8(company->index);
    00415
    00416     /* Current information. */
    00417     p->Send_uint64(company->money);
    00418     p->Send_uint64(company->current_loan);
    00419     p->Send_uint64(income);
    00420     p->Send_uint16(min(UINT16_MAX, company->cur_economy.delivered_cargo.GetSum<OverflowSafeInt64>()));
    00421
    00422     /* Send stats for the last 2 quarters. */
    00423     for (uint i = 0; i < 2; i++) {
    00424       p->Send_uint64(company->old_economy[i].company_value);
    00425       p->Send_uint16(company->old_economy[i].performance_history);
    00426       p->Send_uint16(min(UINT16_MAX, company->old_economy[i].delivered_cargo.GetSum<OverflowSafeInt64>()));
    00427     }
    00428
    00429     this->SendPacket(p);
    00430   }
    00431
    00432
    00433   return NETWORK_RECV_STATUS_OKAY;
    00434 }
    00435
    00437 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyStats()
    00438 {
    00439   /* Fetch the latest version of the stats. */
    00440   NetworkCompanyStats company_stats[MAX_COMPANIES];
    00441   NetworkPopulateCompanyStats(company_stats);
    00442
    00443   const Company *company;
    00444
    00445   /* Go through all the companies. */
    00446   FOR_ALL_COMPANIES(company) {
    00447     Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_STATS);
    00448
    00449     /* Send the information. */
    00450     p->Send_uint8(company->index);
    00451
    00452     for (uint i = 0; i < NETWORK_VEH_END; i++) {
    00453       p->Send_uint16(company_stats[company->index].num_vehicle[i]);
    00454     }
    00455
    00456     for (uint i = 0; i < NETWORK_VEH_END; i++) {
    00457       p->Send_uint16(company_stats[company->index].num_station[i]);
    00458     }
    00459
    00460     this->SendPacket(p);
    00461   }
    00462
    00463   return NETWORK_RECV_STATUS_OKAY;
    00464 }
    00465
    00474 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data)
    00475 {
    00476   Packet *p = new Packet(ADMIN_PACKET_SERVER_CHAT);
    00477
    00478   p->Send_uint8 (action);
    00479   p->Send_uint8 (desttype);
    00480   p->Send_uint32(client_id);
    00481   p->Send_string(msg);
    00482   p->Send_uint64(data);
    00483
    00484   this->SendPacket(p);
    00485   return NETWORK_RECV_STATUS_OKAY;
    00486 }
    00487
    00492 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRconEnd(const char *command)
    00493 {
    00494   Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON_END);
    00495
    00496   p->Send_string(command);
    00497   this->SendPacket(p);
    00498
    00499   return NETWORK_RECV_STATUS_OKAY;
    00500 }
    00501
    00507 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRcon(uint16 colour, const char *result)
    00508 {
    00509   Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON);
    00510
    00511   p->Send_uint16(colour);
    00512   p->Send_string(result);
    00513   this->SendPacket(p);
    00514
    00515   return NETWORK_RECV_STATUS_OKAY;
    00516 }
    00517
    00518 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet *p)
    00519 {
    00520   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00521
    00522   char command[NETWORK_RCONCOMMAND_LENGTH];
    00523
    00524   p->Recv_string(command, sizeof(command));
    00525
    00526   DEBUG(net, 2, "[admin] Rcon command from '%s' (%s): '%s'", this->admin_name, this->admin_version, command);
    00527
    00528   _redirect_console_to_admin = this->index;
    00529   IConsoleCmdExec(command);
    00530   _redirect_console_to_admin = INVALID_ADMIN_ID;
    00531   return this->SendRconEnd(command);
    00532 }
    00533
    00534 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet *p)
    00535 {
    00536   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00537
    00538   char json[NETWORK_GAMESCRIPT_JSON_LENGTH];
    00539
    00540   p->Recv_string(json, sizeof(json));
    00541
    00542   DEBUG(net, 2, "[admin] GameScript JSON from '%s' (%s): '%s'", this->admin_name, this->admin_version, json);
    00543
    00544   Game::NewEvent(new ScriptEventAdminPort(json));
    00545   return NETWORK_RECV_STATUS_OKAY;
    00546 }
    00547
    00548 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_PING(Packet *p)
    00549 {
    00550   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00551
    00552   uint32 d1 = p->Recv_uint32();
    00553
    00554   DEBUG(net, 2, "[admin] Ping from '%s' (%s): '%d'", this->admin_name, this->admin_version, d1);
    00555
    00556   return this->SendPong(d1);
    00557 }
    00558
    00564 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const char *origin, const char *string)
    00565 {
    00566   /* If the length of both strings, plus the 2 '\0' terminations and 3 bytes of the packet
    00567    * are bigger than the MTU, just ignore the message. Better safe than sorry. It should
    00568    * never occur though as the longest strings are chat messages, which are still 30%
    00569    * smaller than SEND_MTU. */
    00570   if (strlen(origin) + strlen(string) + 2 + 3 >= SEND_MTU) return NETWORK_RECV_STATUS_OKAY;
    00571
    00572   Packet *p = new Packet(ADMIN_PACKET_SERVER_CONSOLE);
    00573
    00574   p->Send_string(origin);
    00575   p->Send_string(string);
    00576   this->SendPacket(p);
    00577
    00578   return NETWORK_RECV_STATUS_OKAY;
    00579 }
    00580
    00585 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendGameScript(const char *json)
    00586 {
    00587   /* At the moment we cannot transmit anything larger than MTU. So we limit
    00588    *  the maximum amount of json data that can be sent. Account also for
    00589    *  the trailing \0 of the string */
    00590   if (strlen(json) + 1 >= NETWORK_GAMESCRIPT_JSON_LENGTH) return NETWORK_RECV_STATUS_OKAY;
    00591
    00592   Packet *p = new Packet(ADMIN_PACKET_SERVER_GAMESCRIPT);
    00593
    00594   p->Send_string(json);
    00595   this->SendPacket(p);
    00596
    00597   return NETWORK_RECV_STATUS_OKAY;
    00598 }
    00599
    00601 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendPong(uint32 d1)
    00602 {
    00603   Packet *p = new Packet(ADMIN_PACKET_SERVER_PONG);
    00604
    00605   p->Send_uint32(d1);
    00606   this->SendPacket(p);
    00607
    00608   return NETWORK_RECV_STATUS_OKAY;
    00609 }
    00610
    00612 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdNames()
    00613 {
    00614   Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
    00615
    00616   for (uint i = 0; i < CMD_END; i++) {
    00617     const char *cmdname = GetCommandName(i);
    00618
    00619     /* Should SEND_MTU be exceeded, start a new packet
    00620      * (magic 5: 1 bool "more data" and one uint16 "command id", one
    00621      * byte for string '\0' termination and 1 bool "no more data" */
    00622     if (p->size + strlen(cmdname) + 5 >= SEND_MTU) {
    00623       p->Send_bool(false);
    00624       this->SendPacket(p);
    00625
    00626       p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
    00627     }
    00628
    00629     p->Send_bool(true);
    00630     p->Send_uint16(i);
    00631     p->Send_string(cmdname);
    00632   }
    00633
    00634   /* Marker to notify the end of the packet has been reached. */
    00635   p->Send_bool(false);
    00636   this->SendPacket(p);
    00637
    00638   return NETWORK_RECV_STATUS_OKAY;
    00639 }
    00640
    00646 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdLogging(ClientID client_id, const CommandPacket *cp)
    00647 {
    00648   Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_LOGGING);
    00649
    00650   p->Send_uint32(client_id);
    00651   p->Send_uint8 (cp->company);
    00652   p->Send_uint16(cp->cmd & CMD_ID_MASK);
    00653   p->Send_uint32(cp->p1);
    00654   p->Send_uint32(cp->p2);
    00655   p->Send_uint32(cp->tile);
    00656   p->Send_string(cp->text);
    00657   p->Send_uint32(cp->frame);
    00658
    00659   this->SendPacket(p);
    00660
    00661   return NETWORK_RECV_STATUS_OKAY;
    00662 }
    00663
    00664 /***********
    00665  * Receiving functions
    00666  ************/
    00667
    00668 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet *p)
    00669 {
    00670   if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00671
    00672   char password[NETWORK_PASSWORD_LENGTH];
    00673   p->Recv_string(password, sizeof(password));
    00674
    00675   if (StrEmpty(_settings_client.network.admin_password) ||
    00676       strcmp(password, _settings_client.network.admin_password) != 0) {
    00677     /* Password is invalid */
    00678     return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
    00679   }
    00680
    00681   p->Recv_string(this->admin_name, sizeof(this->admin_name));
    00682   p->Recv_string(this->admin_version, sizeof(this->admin_version));
    00683
    00684   if (StrEmpty(this->admin_name) || StrEmpty(this->admin_version)) {
    00685     /* no name or version supplied */
    00686     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00687   }
    00688
    00689   this->status = ADMIN_STATUS_ACTIVE;
    00690
    00691   DEBUG(net, 1, "[admin] '%s' (%s) has connected", this->admin_name, this->admin_version);
    00692
    00693   return this->SendProtocol();
    00694 }
    00695
    00696 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_QUIT(Packet *p)
    00697 {
    00698   /* The admin is leaving nothing else to do */
    00699   return this->CloseConnection();
    00700 }
    00701
    00702 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENCY(Packet *p)
    00703 {
    00704   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00705
    00706   AdminUpdateType type = (AdminUpdateType)p->Recv_uint16();
    00707   AdminUpdateFrequency freq = (AdminUpdateFrequency)p->Recv_uint16();
    00708
    00709   if (type >= ADMIN_UPDATE_END || (_admin_update_type_frequencies[type] & freq) != freq) {
    00710     /* The server does not know of this UpdateType. */
    00711     DEBUG(net, 3, "[admin] Not supported update frequency %d (%d) from '%s' (%s).", type, freq, this->admin_name, this->admin_version);
    00712     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00713   }
    00714
    00715   this->update_frequency[type] = freq;
    00716
    00717   return NETWORK_RECV_STATUS_OKAY;
    00718 }
    00719
    00720 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet *p)
    00721 {
    00722   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00723
    00724   AdminUpdateType type = (AdminUpdateType)p->Recv_uint8();
    00725   uint32 d1 = p->Recv_uint32();
    00726
    00727   switch (type) {
    00728     case ADMIN_UPDATE_DATE:
    00729       /* The admin is requesting the current date. */
    00730       this->SendDate();
    00731       break;
    00732
    00733     case ADMIN_UPDATE_CLIENT_INFO:
    00734       /* The admin is requesting client info. */
    00735       const NetworkClientSocket *cs;
    00736       if (d1 == UINT32_MAX) {
    00737         this->SendClientInfo(NULL, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
    00738         FOR_ALL_CLIENT_SOCKETS(cs) {
    00739           this->SendClientInfo(cs, cs->GetInfo());
    00740         }
    00741       } else {
    00742         if (d1 == CLIENT_ID_SERVER) {
    00743           this->SendClientInfo(NULL, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
    00744         } else {
    00745           cs = NetworkClientSocket::GetByClientID((ClientID)d1);
    00746           if (cs != NULL) this->SendClientInfo(cs, cs->GetInfo());
    00747         }
    00748       }
    00749       break;
    00750
    00751     case ADMIN_UPDATE_COMPANY_INFO:
    00752       /* The admin is asking for company info. */
    00753       const Company *company;
    00754       if (d1 == UINT32_MAX) {
    00755         FOR_ALL_COMPANIES(company) {
    00756           this->SendCompanyInfo(company);
    00757         }
    00758       } else {
    00759         company = Company::GetIfValid(d1);
    00760         if (company != NULL) this->SendCompanyInfo(company);
    00761       }
    00762       break;
    00763
    00764     case ADMIN_UPDATE_COMPANY_ECONOMY:
    00765       /* The admin is requesting economy info. */
    00766       this->SendCompanyEconomy();
    00767       break;
    00768
    00769     case ADMIN_UPDATE_COMPANY_STATS:
    00770       /* the admin is requesting company stats. */
    00771       this->SendCompanyStats();
    00772       break;
    00773
    00774     case ADMIN_UPDATE_CMD_NAMES:
    00775       /* The admin is requesting the names of DoCommands. */
    00776       this->SendCmdNames();
    00777       break;
    00778
    00779     default:
    00780       /* An unsupported "poll" update type. */
    00781       DEBUG(net, 3, "[admin] Not supported poll %d (%d) from '%s' (%s).", type, d1, this->admin_name, this->admin_version);
    00782       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00783   }
    00784
    00785   return NETWORK_RECV_STATUS_OKAY;
    00786 }
    00787
    00788 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet *p)
    00789 {
    00790   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00791
    00792   NetworkAction action = (NetworkAction)p->Recv_uint8();
    00793   DestType desttype = (DestType)p->Recv_uint8();
    00794   int dest = p->Recv_uint32();
    00795
    00796   char msg[NETWORK_CHAT_LENGTH];
    00797   p->Recv_string(msg, NETWORK_CHAT_LENGTH);
    00798
    00799   switch (action) {
    00800     case NETWORK_ACTION_CHAT:
    00801     case NETWORK_ACTION_CHAT_CLIENT:
    00802     case NETWORK_ACTION_CHAT_COMPANY:
    00803     case NETWORK_ACTION_SERVER_MESSAGE:
    00804       NetworkServerSendChat(action, desttype, dest, msg, _network_own_client_id, 0, true);
    00805       break;
    00806
    00807     default:
    00808       DEBUG(net, 3, "[admin] Invalid chat action %d from admin '%s' (%s).", action, this->admin_name, this->admin_version);
    00809       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00810   }
    00811
    00812   return NETWORK_RECV_STATUS_OKAY;
    00813 }
    00814
    00815 /*
    00816  * Useful wrapper functions
    00817  */
    00818
    00824 void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client)
    00825 {
    00826   ServerNetworkAdminSocketHandler *as;
    00827   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00828     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00829       as->SendClientInfo(cs, cs->GetInfo());
    00830       if (new_client) {
    00831         as->SendClientJoin(cs->client_id);
    00832       }
    00833     }
    00834   }
    00835 }
    00836
    00841 void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
    00842 {
    00843   ServerNetworkAdminSocketHandler *as;
    00844   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00845     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00846       as->SendClientUpdate(ci);
    00847     }
    00848   }
    00849 }
    00850
    00855 void NetworkAdminClientQuit(ClientID client_id)
    00856 {
    00857   ServerNetworkAdminSocketHandler *as;
    00858   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00859     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00860       as->SendClientQuit(client_id);
    00861     }
    00862   }
    00863 }
    00864
    00870 void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code)
    00871 {
    00872   ServerNetworkAdminSocketHandler *as;
    00873   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00874     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00875       as->SendClientError(client_id, error_code);
    00876     }
    00877   }
    00878 }
    00879
    00885 void NetworkAdminCompanyInfo(const Company *company, bool new_company)
    00886 {
    00887   if (company == NULL) {
    00888     DEBUG(net, 1, "[admin] Empty company given for update");
    00889     return;
    00890   }
    00891
    00892   ServerNetworkAdminSocketHandler *as;
    00893   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00894     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
    00895
    00896     as->SendCompanyInfo(company);
    00897     if (new_company) {
    00898       as->SendCompanyNew(company->index);
    00899     }
    00900   }
    00901 }
    00902
    00907 void NetworkAdminCompanyUpdate(const Company *company)
    00908 {
    00909   if (company == NULL) return;
    00910
    00911   ServerNetworkAdminSocketHandler *as;
    00912   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00913     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
    00914
    00915     as->SendCompanyUpdate(company);
    00916   }
    00917 }
    00918
    00924 void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bcrr)
    00925 {
    00926   ServerNetworkAdminSocketHandler *as;
    00927   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00928     as->SendCompanyRemove(company_id, bcrr);
    00929   }
    00930 }
    00931
    00932
    00936 void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data, bool from_admin)
    00937 {
    00938   if (from_admin) return;
    00939
    00940   ServerNetworkAdminSocketHandler *as;
    00941   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00942     if (as->update_frequency[ADMIN_UPDATE_CHAT] & ADMIN_FREQUENCY_AUTOMATIC) {
    00943       as->SendChat(action, desttype, client_id, msg, data);
    00944     }
    00945   }
    00946 }
    00947
    00954 void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, const char *string)
    00955 {
    00956   ServerNetworkAdminSocketHandler::Get(admin_index)->SendRcon(colour_code, string);
    00957 }
    00958
    00964 void NetworkAdminConsole(const char *origin, const char *string)
    00965 {
    00966   ServerNetworkAdminSocketHandler *as;
    00967   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00968     if (as->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) {
    00969       as->SendConsole(origin, string);
    00970     }
    00971   }
    00972 }
    00973
    00978 void NetworkAdminGameScript(const char *json)
    00979 {
    00980   ServerNetworkAdminSocketHandler *as;
    00981   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00982     if (as->update_frequency[ADMIN_UPDATE_GAMESCRIPT] & ADMIN_FREQUENCY_AUTOMATIC) {
    00983       as->SendGameScript(json);
    00984     }
    00985   }
    00986 }
    00987
    00993 void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket *cp)
    00994 {
    00995   ClientID client_id = owner == NULL ? _network_own_client_id : owner->client_id;
    00996
    00997   ServerNetworkAdminSocketHandler *as;
    00998   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00999     if (as->update_frequency[ADMIN_UPDATE_CMD_LOGGING] & ADMIN_FREQUENCY_AUTOMATIC) {
    01000       as->SendCmdLogging(client_id, cp);
    01001     }
    01002   }
    01003 }
    01004
    01008 void ServerNetworkAdminSocketHandler::WelcomeAll()
    01009 {
    01010   ServerNetworkAdminSocketHandler *as;
    01011   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    01012     as->SendWelcome();
    01013   }
    01014 }
    01015
    01020 void NetworkAdminUpdate(AdminUpdateFrequency freq)
    01021 {
    01022   ServerNetworkAdminSocketHandler *as;
    01023   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    01024     for (int i = 0; i < ADMIN_UPDATE_END; i++) {
    01025       if (as->update_frequency[i] & freq) {
    01026         /* Update the admin for the required details */
    01027         switch (i) {
    01028           case ADMIN_UPDATE_DATE:
    01029             as->SendDate();
    01030             break;
    01031
    01032           case ADMIN_UPDATE_COMPANY_ECONOMY:
    01033             as->SendCompanyEconomy();
    01034             break;
    01035
    01036           case ADMIN_UPDATE_COMPANY_STATS:
    01037             as->SendCompanyStats();
    01038             break;
    01039
    01040           default: NOT_REACHED();
    01041         }
    01042       }
    01043     }
    01044   }
    01045 }
    01046
    01047 #endif /* ENABLE_NETWORK */