# network_admin.cpp

Go to the documentation of this file.

    00001 /* $Id: network_admin.cpp 23255 2011-11-18 21:04:08Z 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
    00027
    00028 /* This file handles all the admin network commands. */
    00029
    00031 AdminIndex _redirect_console_to_admin = INVALID_ADMIN_ID;
    00032
    00034 byte _network_admins_connected = 0;
    00035
    00036 NetworkAdminSocketPool _networkadminsocket_pool("NetworkAdminSocket");
    00037 INSTANTIATE_POOL_METHODS(NetworkAdminSocket)
    00038
    00039
    00040 static const int ADMIN_AUTHORISATION_TIMEOUT = 10000;
    00041
    00042
    00044 static const AdminUpdateFrequency _admin_update_type_frequencies[] = {
    00045   ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_DAILY | ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY,
    00046   ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_AUTOMATIC,
    00047   ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_AUTOMATIC,
    00048   ADMIN_FREQUENCY_POLL |                         ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY,
    00049   ADMIN_FREQUENCY_POLL |                         ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY,
    00050                          ADMIN_FREQUENCY_AUTOMATIC,
    00051                          ADMIN_FREQUENCY_AUTOMATIC,
    00052   ADMIN_FREQUENCY_POLL,
    00053                          ADMIN_FREQUENCY_AUTOMATIC,
    00054 };
    00055 assert_compile(lengthof(_admin_update_type_frequencies) == ADMIN_UPDATE_END);
    00056
    00061 ServerNetworkAdminSocketHandler::ServerNetworkAdminSocketHandler(SOCKET s) : NetworkAdminSocketHandler(s)
    00062 {
    00063   _network_admins_connected++;
    00064   this->status = ADMIN_STATUS_INACTIVE;
    00065   this->realtime_connect = _realtime_tick;
    00066 }
    00067
    00071 ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler()
    00072 {
    00073   _network_admins_connected--;
    00074   DEBUG(net, 1, "[admin] '%s' (%s) has disconnected", this->admin_name, this->admin_version);
    00075   if (_redirect_console_to_admin == this->index) _redirect_console_to_admin = INVALID_ADMIN_ID;
    00076 }
    00077
    00082 /* static */ bool ServerNetworkAdminSocketHandler::AllowConnection()
    00083 {
    00084   return !StrEmpty(_settings_client.network.admin_password) && _network_admins_connected < MAX_ADMINS;
    00085 }
    00086
    00088 /* static */ void ServerNetworkAdminSocketHandler::Send()
    00089 {
    00090   ServerNetworkAdminSocketHandler *as;
    00091   FOR_ALL_ADMIN_SOCKETS(as) {
    00092     if (as->status == ADMIN_STATUS_INACTIVE && as->realtime_connect + ADMIN_AUTHORISATION_TIMEOUT < _realtime_tick) {
    00093       DEBUG(net, 1, "[admin] Admin did not send its authorisation within %d seconds", ADMIN_AUTHORISATION_TIMEOUT / 1000);
    00094       as->CloseConnection(true);
    00095       continue;
    00096     }
    00097     if (as->writable) {
    00098       as->SendPackets();
    00099     }
    00100   }
    00101 }
    00102
    00103 /* static */ void ServerNetworkAdminSocketHandler::AcceptConnection(SOCKET s, const NetworkAddress &address)
    00104 {
    00105   ServerNetworkAdminSocketHandler *as = new ServerNetworkAdminSocketHandler(s);
    00106   as->address = address; // Save the IP of the client
    00107 }
    00108
    00109 /***********
    00110  * Sending functions for admin network
    00111  ************/
    00112
    00113 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode error)
    00114 {
    00115   Packet *p = new Packet(ADMIN_PACKET_SERVER_ERROR);
    00116
    00117   p->Send_uint8(error);
    00118   this->SendPacket(p);
    00119
    00120   char str[100];
    00121   StringID strid = GetNetworkErrorMsg(error);
    00122   GetString(str, strid, lastof(str));
    00123
    00124   DEBUG(net, 1, "[admin] the admin '%s' (%s) made an error and has been disconnected. Reason: '%s'", this->admin_name, this->admin_version, str);
    00125
    00126   return this->CloseConnection(true);
    00127 }
    00128
    00129 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendProtocol()
    00130 {
    00131   Packet *p = new Packet(ADMIN_PACKET_SERVER_PROTOCOL);
    00132
    00133   /* announce the protocol version */
    00134   p->Send_uint8(NETWORK_GAME_ADMIN_VERSION);
    00135
    00136   for (int i = 0; i < ADMIN_UPDATE_END; i++) {
    00137     p->Send_bool  (true);
    00138     p->Send_uint16(i);
    00139     p->Send_uint16(_admin_update_type_frequencies[i]);
    00140   }
    00141
    00142   p->Send_bool(false);
    00143   this->SendPacket(p);
    00144
    00145   return this->SendWelcome();
    00146 }
    00147
    00148 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendWelcome()
    00149 {
    00150   Packet *p = new Packet(ADMIN_PACKET_SERVER_WELCOME);
    00151
    00152   p->Send_string(_settings_client.network.server_name);
    00153   p->Send_string(_openttd_revision);
    00154   p->Send_bool  (_network_dedicated);
    00155
    00156   p->Send_string(_network_game_info.map_name);
    00157   p->Send_uint32(_settings_game.game_creation.generation_seed);
    00158   p->Send_uint8 (_settings_game.game_creation.landscape);
    00159   p->Send_uint32(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
    00160   p->Send_uint16(MapSizeX());
    00161   p->Send_uint16(MapSizeY());
    00162
    00163   this->SendPacket(p);
    00164
    00165   return NETWORK_RECV_STATUS_OKAY;
    00166 }
    00167
    00168 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendNewGame()
    00169 {
    00170   Packet *p = new Packet(ADMIN_PACKET_SERVER_NEWGAME);
    00171   this->SendPacket(p);
    00172   return NETWORK_RECV_STATUS_OKAY;
    00173 }
    00174
    00175 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendShutdown()
    00176 {
    00177   Packet *p = new Packet(ADMIN_PACKET_SERVER_SHUTDOWN);
    00178   this->SendPacket(p);
    00179   return NETWORK_RECV_STATUS_OKAY;
    00180 }
    00181
    00182 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendDate()
    00183 {
    00184   Packet *p = new Packet(ADMIN_PACKET_SERVER_DATE);
    00185
    00186   p->Send_uint32(_date);
    00187   this->SendPacket(p);
    00188
    00189   return NETWORK_RECV_STATUS_OKAY;
    00190 }
    00191
    00192 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientJoin(ClientID client_id)
    00193 {
    00194   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_JOIN);
    00195
    00196   p->Send_uint32(client_id);
    00197   this->SendPacket(p);
    00198
    00199   return NETWORK_RECV_STATUS_OKAY;
    00200 }
    00201
    00207 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientInfo(const NetworkClientSocket *cs, const NetworkClientInfo *ci)
    00208 {
    00209   /* Only send data when we're a proper client, not just someone trying to query the server. */
    00210   if (ci == NULL) return NETWORK_RECV_STATUS_OKAY;
    00211
    00212   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_INFO);
    00213
    00214   p->Send_uint32(ci->client_id);
    00215   p->Send_string(cs == NULL ? "" : const_cast<NetworkAddress &>(cs->client_address).GetHostname());
    00216   p->Send_string(ci->client_name);
    00217   p->Send_uint8 (ci->client_lang);
    00218   p->Send_uint32(ci->join_date);
    00219   p->Send_uint8 (ci->client_playas);
    00220
    00221   this->SendPacket(p);
    00222
    00223   return NETWORK_RECV_STATUS_OKAY;
    00224 }
    00225
    00226 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientUpdate(const NetworkClientInfo *ci)
    00227 {
    00228   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_UPDATE);
    00229
    00230   p->Send_uint32(ci->client_id);
    00231   p->Send_string(ci->client_name);
    00232   p->Send_uint8 (ci->client_playas);
    00233
    00234   this->SendPacket(p);
    00235
    00236   return NETWORK_RECV_STATUS_OKAY;
    00237 }
    00238
    00239 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientQuit(ClientID client_id)
    00240 {
    00241   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_QUIT);
    00242
    00243   p->Send_uint32(client_id);
    00244   this->SendPacket(p);
    00245
    00246   return NETWORK_RECV_STATUS_OKAY;
    00247 }
    00248
    00249 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientError(ClientID client_id, NetworkErrorCode error)
    00250 {
    00251   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_ERROR);
    00252
    00253   p->Send_uint32(client_id);
    00254   p->Send_uint8 (error);
    00255   this->SendPacket(p);
    00256
    00257   return NETWORK_RECV_STATUS_OKAY;
    00258 }
    00259
    00260 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyNew(CompanyID company_id)
    00261 {
    00262   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_NEW);
    00263   p->Send_uint8(company_id);
    00264
    00265   this->SendPacket(p);
    00266
    00267   return NETWORK_RECV_STATUS_OKAY;
    00268 }
    00269
    00270 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company *c)
    00271 {
    00272   char company_name[NETWORK_COMPANY_NAME_LENGTH];
    00273   char manager_name[NETWORK_COMPANY_NAME_LENGTH];
    00274
    00275   SetDParam(0, c->index);
    00276   GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
    00277
    00278   SetDParam(0, c->index);
    00279   GetString(manager_name, STR_PRESIDENT_NAME, lastof(manager_name));
    00280
    00281   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_INFO);
    00282
    00283   p->Send_uint8 (c->index);
    00284   p->Send_string(company_name);
    00285   p->Send_string(manager_name);
    00286   p->Send_uint8 (c->colour);
    00287   p->Send_bool  (NetworkCompanyIsPassworded(c->index));
    00288   p->Send_uint32(c->inaugurated_year);
    00289   p->Send_bool  (c->is_ai);
    00290
    00291   this->SendPacket(p);
    00292
    00293   return NETWORK_RECV_STATUS_OKAY;
    00294 }
    00295
    00296 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyUpdate(const Company *c)
    00297 {
    00298   char company_name[NETWORK_COMPANY_NAME_LENGTH];
    00299   char manager_name[NETWORK_COMPANY_NAME_LENGTH];
    00300
    00301   SetDParam(0, c->index);
    00302   GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
    00303
    00304   SetDParam(0, c->index);
    00305   GetString(manager_name, STR_PRESIDENT_NAME, lastof(manager_name));
    00306
    00307   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_UPDATE);
    00308
    00309   p->Send_uint8 (c->index);
    00310   p->Send_string(company_name);
    00311   p->Send_string(manager_name);
    00312   p->Send_uint8 (c->colour);
    00313   p->Send_bool  (NetworkCompanyIsPassworded(c->index));
    00314   p->Send_uint8 (c->quarters_of_bankruptcy);
    00315
    00316   for (size_t i = 0; i < lengthof(c->share_owners); i++) {
    00317     p->Send_uint8(c->share_owners[i]);
    00318   }
    00319
    00320   this->SendPacket(p);
    00321
    00322   return NETWORK_RECV_STATUS_OKAY;
    00323 }
    00324
    00325 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason acrr)
    00326 {
    00327   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_REMOVE);
    00328
    00329   p->Send_uint8(company_id);
    00330   p->Send_uint8(acrr);
    00331
    00332   this->SendPacket(p);
    00333
    00334   return NETWORK_RECV_STATUS_OKAY;
    00335 }
    00336
    00337 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyEconomy()
    00338 {
    00339   const Company *company;
    00340   FOR_ALL_COMPANIES(company) {
    00341     /* Get the income. */
    00342     Money income = 0;
    00343     for (uint i = 0; i < lengthof(company->yearly_expenses[0]); i++) {
    00344       income -= company->yearly_expenses[0][i];
    00345     }
    00346
    00347     Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_ECONOMY);
    00348
    00349     p->Send_uint8(company->index);
    00350
    00351     /* Current information. */
    00352     p->Send_uint64(company->money);
    00353     p->Send_uint64(company->current_loan);
    00354     p->Send_uint64(income);
    00355     p->Send_uint16(company->cur_economy.delivered_cargo);
    00356
    00357     /* Send stats for the last 2 quarters. */
    00358     for (uint i = 0; i < 2; i++) {
    00359       p->Send_uint64(company->old_economy[i].company_value);
    00360       p->Send_uint16(company->old_economy[i].performance_history);
    00361       p->Send_uint16(company->old_economy[i].delivered_cargo);
    00362     }
    00363
    00364     this->SendPacket(p);
    00365   }
    00366
    00367
    00368   return NETWORK_RECV_STATUS_OKAY;
    00369 }
    00370
    00371 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyStats()
    00372 {
    00373   /* Fetch the latest version of the stats. */
    00374   NetworkCompanyStats company_stats[MAX_COMPANIES];
    00375   NetworkPopulateCompanyStats(company_stats);
    00376
    00377   const Company *company;
    00378
    00379   /* Go through all the companies. */
    00380   FOR_ALL_COMPANIES(company) {
    00381     Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_STATS);
    00382
    00383     /* Send the information. */
    00384     p->Send_uint8(company->index);
    00385
    00386     for (uint i = 0; i < NETWORK_VEH_END; i++) {
    00387       p->Send_uint16(company_stats[company->index].num_vehicle[i]);
    00388     }
    00389
    00390     for (uint i = 0; i < NETWORK_VEH_END; i++) {
    00391       p->Send_uint16(company_stats[company->index].num_station[i]);
    00392     }
    00393
    00394     this->SendPacket(p);
    00395   }
    00396
    00397   return NETWORK_RECV_STATUS_OKAY;
    00398 }
    00399
    00400 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data)
    00401 {
    00402   Packet *p = new Packet(ADMIN_PACKET_SERVER_CHAT);
    00403
    00404   p->Send_uint8 (action);
    00405   p->Send_uint8 (desttype);
    00406   p->Send_uint32(client_id);
    00407   p->Send_string(msg);
    00408   p->Send_uint64(data);
    00409
    00410   this->SendPacket(p);
    00411   return NETWORK_RECV_STATUS_OKAY;
    00412 }
    00413
    00414 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRcon(uint16 colour, const char *result)
    00415 {
    00416   Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON);
    00417
    00418   p->Send_uint16(colour);
    00419   p->Send_string(result);
    00420   this->SendPacket(p);
    00421
    00422   return NETWORK_RECV_STATUS_OKAY;
    00423 }
    00424
    00425 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_RCON)
    00426 {
    00427   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00428
    00429   char command[NETWORK_RCONCOMMAND_LENGTH];
    00430
    00431   p->Recv_string(command, sizeof(command));
    00432
    00433   DEBUG(net, 2, "[admin] Rcon command from '%s' (%s): '%s'", this->admin_name, this->admin_version, command);
    00434
    00435   _redirect_console_to_admin = this->index;
    00436   IConsoleCmdExec(command);
    00437   _redirect_console_to_admin = INVALID_ADMIN_ID;
    00438   return NETWORK_RECV_STATUS_OKAY;
    00439 }
    00440
    00441 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const char *origin, const char *string)
    00442 {
    00443   /* If the length of both strings, plus the 2 '\0' terminations and 3 bytes of the packet
    00444    * are bigger than the MTU, just ignore the message. Better safe than sorry. It should
    00445    * never occur though as the longest strings are chat messages, which are still 30%
    00446    * smaller than SEND_MTU. */
    00447   if (strlen(origin) + strlen(string) + 2 + 3 >= SEND_MTU) return NETWORK_RECV_STATUS_OKAY;
    00448
    00449   Packet *p = new Packet(ADMIN_PACKET_SERVER_CONSOLE);
    00450
    00451   p->Send_string(origin);
    00452   p->Send_string(string);
    00453   this->SendPacket(p);
    00454
    00455   return NETWORK_RECV_STATUS_OKAY;
    00456 }
    00457
    00458 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdNames()
    00459 {
    00460   Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
    00461
    00462   for (uint i = 0; i < CMD_END; i++) {
    00463     const char *cmdname = GetCommandName(i);
    00464
    00465     /* Should SEND_MTU be exceeded, start a new packet
    00466      * (magic 5: 1 bool "more data" and one uint16 "command id", one
    00467      * byte for string '\0' termination and 1 bool "no more data" */
    00468     if (p->size + strlen(cmdname) + 5 >= SEND_MTU) {
    00469       p->Send_bool(false);
    00470       this->SendPacket(p);
    00471
    00472       p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
    00473     }
    00474
    00475     p->Send_bool(true);
    00476     p->Send_uint16(i);
    00477     p->Send_string(cmdname);
    00478   }
    00479
    00480   /* Marker to notify the end of the packet has been reached. */
    00481   p->Send_bool(false);
    00482   this->SendPacket(p);
    00483
    00484   return NETWORK_RECV_STATUS_OKAY;
    00485 }
    00486
    00487 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdLogging(ClientID client_id, const CommandPacket *cp)
    00488 {
    00489   Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_LOGGING);
    00490
    00491   p->Send_uint32(client_id);
    00492   p->Send_uint8 (cp->company);
    00493   p->Send_uint16(cp->cmd & CMD_ID_MASK);
    00494   p->Send_uint32(cp->p1);
    00495   p->Send_uint32(cp->p2);
    00496   p->Send_uint32(cp->tile);
    00497   p->Send_string(cp->text);
    00498   p->Send_uint32(cp->frame);
    00499
    00500   this->SendPacket(p);
    00501
    00502   return NETWORK_RECV_STATUS_OKAY;
    00503 }
    00504
    00505 /***********
    00506  * Receiving functions
    00507  ************/
    00508
    00509 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_JOIN)
    00510 {
    00511   if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00512
    00513   char password[NETWORK_PASSWORD_LENGTH];
    00514   p->Recv_string(password, sizeof(password));
    00515
    00516   if (StrEmpty(_settings_client.network.admin_password) ||
    00517       strcmp(password, _settings_client.network.admin_password) != 0) {
    00518     /* Password is invalid */
    00519     return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
    00520   }
    00521
    00522   p->Recv_string(this->admin_name, sizeof(this->admin_name));
    00523   p->Recv_string(this->admin_version, sizeof(this->admin_version));
    00524
    00525   if (StrEmpty(this->admin_name) || StrEmpty(this->admin_version)) {
    00526     /* no name or version supplied */
    00527     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00528   }
    00529
    00530   this->status = ADMIN_STATUS_ACTIVE;
    00531
    00532   DEBUG(net, 1, "[admin] '%s' (%s) has connected", this->admin_name, this->admin_version);
    00533
    00534   return this->SendProtocol();
    00535 }
    00536
    00537 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_QUIT)
    00538 {
    00539   /* The admin is leaving nothing else to do */
    00540   return this->CloseConnection();
    00541 }
    00542
    00543 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY)
    00544 {
    00545   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00546
    00547   AdminUpdateType type = (AdminUpdateType)p->Recv_uint16();
    00548   AdminUpdateFrequency freq = (AdminUpdateFrequency)p->Recv_uint16();
    00549
    00550   if (type >= ADMIN_UPDATE_END || (_admin_update_type_frequencies[type] & freq) != freq) {
    00551     /* The server does not know of this UpdateType. */
    00552     DEBUG(net, 3, "[admin] Not supported update frequency %d (%d) from '%s' (%s).", type, freq, this->admin_name, this->admin_version);
    00553     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00554   }
    00555
    00556   this->update_frequency[type] = freq;
    00557
    00558   return NETWORK_RECV_STATUS_OKAY;
    00559 }
    00560
    00561 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_POLL)
    00562 {
    00563   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00564
    00565   AdminUpdateType type = (AdminUpdateType)p->Recv_uint8();
    00566   uint32 d1 = p->Recv_uint32();
    00567
    00568   switch (type) {
    00569     case ADMIN_UPDATE_DATE:
    00570       /* The admin is requesting the current date. */
    00571       this->SendDate();
    00572       break;
    00573
    00574     case ADMIN_UPDATE_CLIENT_INFO:
    00575       /* The admin is requesting client info. */
    00576       const NetworkClientSocket *cs;
    00577       if (d1 == UINT32_MAX) {
    00578         this->SendClientInfo(NULL, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
    00579         FOR_ALL_CLIENT_SOCKETS(cs) {
    00580           this->SendClientInfo(cs, cs->GetInfo());
    00581         }
    00582       } else {
    00583         if (d1 == CLIENT_ID_SERVER) {
    00584           this->SendClientInfo(NULL, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
    00585         } else {
    00586           cs = NetworkClientSocket::GetByClientID((ClientID)d1);
    00587           if (cs != NULL) this->SendClientInfo(cs, cs->GetInfo());
    00588         }
    00589       }
    00590       break;
    00591
    00592     case ADMIN_UPDATE_COMPANY_INFO:
    00593       /* The admin is asking for company info. */
    00594       const Company *company;
    00595       if (d1 == UINT32_MAX) {
    00596         FOR_ALL_COMPANIES(company) {
    00597           this->SendCompanyInfo(company);
    00598         }
    00599       } else {
    00600         company = Company::GetIfValid(d1);
    00601         if (company != NULL) this->SendCompanyInfo(company);
    00602       }
    00603       break;
    00604
    00605     case ADMIN_UPDATE_COMPANY_ECONOMY:
    00606       /* The admin is requesting economy info. */
    00607       this->SendCompanyEconomy();
    00608       break;
    00609
    00610     case ADMIN_UPDATE_COMPANY_STATS:
    00611       /* the admin is requesting company stats. */
    00612       this->SendCompanyStats();
    00613       break;
    00614
    00615     case ADMIN_UPDATE_CMD_NAMES:
    00616       /* The admin is requesting the names of DoCommands. */
    00617       this->SendCmdNames();
    00618       break;
    00619
    00620     default:
    00621       /* An unsupported "poll" update type. */
    00622       DEBUG(net, 3, "[admin] Not supported poll %d (%d) from '%s' (%s).", type, d1, this->admin_name, this->admin_version);
    00623       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00624   }
    00625
    00626   return NETWORK_RECV_STATUS_OKAY;
    00627 }
    00628
    00629 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_CHAT)
    00630 {
    00631   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00632
    00633   NetworkAction action = (NetworkAction)p->Recv_uint8();
    00634   DestType desttype = (DestType)p->Recv_uint8();
    00635   int dest = p->Recv_uint32();
    00636
    00637   char msg[NETWORK_CHAT_LENGTH];
    00638   p->Recv_string(msg, NETWORK_CHAT_LENGTH);
    00639
    00640   switch (action) {
    00641     case NETWORK_ACTION_CHAT:
    00642     case NETWORK_ACTION_CHAT_CLIENT:
    00643     case NETWORK_ACTION_CHAT_COMPANY:
    00644     case NETWORK_ACTION_SERVER_MESSAGE:
    00645       NetworkServerSendChat(action, desttype, dest, msg, _network_own_client_id, 0, true);
    00646       break;
    00647
    00648     default:
    00649       DEBUG(net, 3, "[admin] Invalid chat action %d from admin '%s' (%s).", action, this->admin_name, this->admin_version);
    00650       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00651   }
    00652
    00653   return NETWORK_RECV_STATUS_OKAY;
    00654 }
    00655
    00656 /*
    00657  * Useful wrapper functions
    00658  */
    00659
    00665 void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client)
    00666 {
    00667   ServerNetworkAdminSocketHandler *as;
    00668   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00669     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00670       as->SendClientInfo(cs, cs->GetInfo());
    00671       if (new_client) {
    00672         as->SendClientJoin(cs->client_id);
    00673       }
    00674     }
    00675   }
    00676 }
    00677
    00682 void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
    00683 {
    00684   ServerNetworkAdminSocketHandler *as;
    00685   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00686     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00687       as->SendClientUpdate(ci);
    00688     }
    00689   }
    00690 }
    00691
    00696 void NetworkAdminClientQuit(ClientID client_id)
    00697 {
    00698   ServerNetworkAdminSocketHandler *as;
    00699   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00700     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00701       as->SendClientQuit(client_id);
    00702     }
    00703   }
    00704 }
    00705
    00711 void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code)
    00712 {
    00713   ServerNetworkAdminSocketHandler *as;
    00714   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00715     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00716       as->SendClientError(client_id, error_code);
    00717     }
    00718   }
    00719 }
    00720
    00726 void NetworkAdminCompanyInfo(const Company *company, bool new_company)
    00727 {
    00728   if (company == NULL) {
    00729     DEBUG(net, 1, "[admin] Empty company given for update");
    00730     return;
    00731   }
    00732
    00733   ServerNetworkAdminSocketHandler *as;
    00734   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00735     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
    00736
    00737     as->SendCompanyInfo(company);
    00738     if (new_company) {
    00739       as->SendCompanyNew(company->index);
    00740     }
    00741   }
    00742 }
    00743
    00748 void NetworkAdminCompanyUpdate(const Company *company)
    00749 {
    00750   if (company == NULL) return;
    00751
    00752   ServerNetworkAdminSocketHandler *as;
    00753   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00754     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
    00755
    00756     as->SendCompanyUpdate(company);
    00757   }
    00758 }
    00759
    00765 void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bcrr)
    00766 {
    00767   ServerNetworkAdminSocketHandler *as;
    00768   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00769     as->SendCompanyRemove(company_id, bcrr);
    00770   }
    00771 }
    00772
    00773
    00777 void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data, bool from_admin)
    00778 {
    00779   if (from_admin) return;
    00780
    00781   ServerNetworkAdminSocketHandler *as;
    00782   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00783     if (as->update_frequency[ADMIN_UPDATE_CHAT] & ADMIN_FREQUENCY_AUTOMATIC) {
    00784       as->SendChat(action, desttype, client_id, msg, data);
    00785     }
    00786   }
    00787 }
    00788
    00795 void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, const char *string)
    00796 {
    00797   ServerNetworkAdminSocketHandler::Get(admin_index)->SendRcon(colour_code, string);
    00798 }
    00799
    00805 void NetworkAdminConsole(const char *origin, const char *string)
    00806 {
    00807   ServerNetworkAdminSocketHandler *as;
    00808   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00809     if (as->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) {
    00810       as->SendConsole(origin, string);
    00811     }
    00812   }
    00813 }
    00814
    00820 void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket *cp)
    00821 {
    00822   ClientID client_id = owner == NULL ? _network_own_client_id : owner->client_id;
    00823
    00824   ServerNetworkAdminSocketHandler *as;
    00825   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00826     if (as->update_frequency[ADMIN_UPDATE_CMD_LOGGING] & ADMIN_FREQUENCY_AUTOMATIC) {
    00827       as->SendCmdLogging(client_id, cp);
    00828     }
    00829   }
    00830 }
    00831
    00835 void ServerNetworkAdminSocketHandler::WelcomeAll()
    00836 {
    00837   ServerNetworkAdminSocketHandler *as;
    00838   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00839     as->SendWelcome();
    00840   }
    00841 }
    00842
    00847 void NetworkAdminUpdate(AdminUpdateFrequency freq)
    00848 {
    00849   ServerNetworkAdminSocketHandler *as;
    00850   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
    00851     for (int i = 0; i < ADMIN_UPDATE_END; i++) {
    00852       if (as->update_frequency[i] & freq) {
    00853         /* Update the admin for the required details */
    00854         switch (i) {
    00855           case ADMIN_UPDATE_DATE:
    00856             as->SendDate();
    00857             break;
    00858
    00859           case ADMIN_UPDATE_COMPANY_ECONOMY:
    00860             as->SendCompanyEconomy();
    00861             break;
    00862
    00863           case ADMIN_UPDATE_COMPANY_STATS:
    00864             as->SendCompanyStats();
    00865             break;
    00866
    00867           default: NOT_REACHED();
    00868         }
    00869       }
    00870     }
    00871   }
    00872 }
    00873
    00874 #endif /* ENABLE_NETWORK */