# 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
    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   this->status = ADMIN_STATUS_ACTIVE;
    00151
    00152   Packet *p = new Packet(ADMIN_PACKET_SERVER_WELCOME);
    00153
    00154   p->Send_string(_settings_client.network.server_name);
    00155   p->Send_string(_openttd_revision);
    00156   p->Send_bool  (_network_dedicated);
    00157
    00158   p->Send_string(_network_game_info.map_name);
    00159   p->Send_uint32(_settings_game.game_creation.generation_seed);
    00160   p->Send_uint8 (_settings_game.game_creation.landscape);
    00161   p->Send_uint32(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
    00162   p->Send_uint16(MapSizeX());
    00163   p->Send_uint16(MapSizeY());
    00164
    00165   this->SendPacket(p);
    00166
    00167   return NETWORK_RECV_STATUS_OKAY;
    00168 }
    00169
    00170 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendNewGame()
    00171 {
    00172   Packet *p = new Packet(ADMIN_PACKET_SERVER_NEWGAME);
    00173   this->SendPacket(p);
    00174   return NETWORK_RECV_STATUS_OKAY;
    00175 }
    00176
    00177 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendShutdown()
    00178 {
    00179   Packet *p = new Packet(ADMIN_PACKET_SERVER_SHUTDOWN);
    00180   this->SendPacket(p);
    00181   return NETWORK_RECV_STATUS_OKAY;
    00182 }
    00183
    00184 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendDate()
    00185 {
    00186   Packet *p = new Packet(ADMIN_PACKET_SERVER_DATE);
    00187
    00188   p->Send_uint32(_date);
    00189   this->SendPacket(p);
    00190
    00191   return NETWORK_RECV_STATUS_OKAY;
    00192 }
    00193
    00194 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientJoin(ClientID client_id)
    00195 {
    00196   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_JOIN);
    00197
    00198   p->Send_uint32(client_id);
    00199   this->SendPacket(p);
    00200
    00201   return NETWORK_RECV_STATUS_OKAY;
    00202 }
    00203
    00204 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientInfo(const NetworkClientInfo *ci)
    00205 {
    00206   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_INFO);
    00207
    00208   p->Send_uint32(ci->client_id);
    00209   p->Send_string(const_cast<NetworkAddress &>(ci->client_address).GetHostname());
    00210   p->Send_string(ci->client_name);
    00211   p->Send_uint8 (ci->client_lang);
    00212   p->Send_uint32(ci->join_date);
    00213   p->Send_uint8 (ci->client_playas);
    00214
    00215   this->SendPacket(p);
    00216
    00217   return NETWORK_RECV_STATUS_OKAY;
    00218 }
    00219
    00220 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientUpdate(const NetworkClientInfo *ci)
    00221 {
    00222   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_UPDATE);
    00223
    00224   p->Send_uint32(ci->client_id);
    00225   p->Send_string(ci->client_name);
    00226   p->Send_uint8 (ci->client_playas);
    00227
    00228   this->SendPacket(p);
    00229
    00230   return NETWORK_RECV_STATUS_OKAY;
    00231 }
    00232
    00233 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientQuit(ClientID client_id)
    00234 {
    00235   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_QUIT);
    00236
    00237   p->Send_uint32(client_id);
    00238   this->SendPacket(p);
    00239
    00240   return NETWORK_RECV_STATUS_OKAY;
    00241 }
    00242
    00243 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientError(ClientID client_id, NetworkErrorCode error)
    00244 {
    00245   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_ERROR);
    00246
    00247   p->Send_uint32(client_id);
    00248   p->Send_uint8 (error);
    00249   this->SendPacket(p);
    00250
    00251   return NETWORK_RECV_STATUS_OKAY;
    00252 }
    00253
    00254 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyNew(CompanyID company_id)
    00255 {
    00256   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_NEW);
    00257   p->Send_uint8(company_id);
    00258
    00259   this->SendPacket(p);
    00260
    00261   return NETWORK_RECV_STATUS_OKAY;
    00262 }
    00263
    00264 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company *c)
    00265 {
    00266   char company_name[NETWORK_COMPANY_NAME_LENGTH];
    00267   char manager_name[NETWORK_COMPANY_NAME_LENGTH];
    00268
    00269   SetDParam(0, c->index);
    00270   GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
    00271
    00272   SetDParam(0, c->index);
    00273   GetString(manager_name, STR_PRESIDENT_NAME, lastof(manager_name));
    00274
    00275   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_INFO);
    00276
    00277   p->Send_uint8 (c->index);
    00278   p->Send_string(company_name);
    00279   p->Send_string(manager_name);
    00280   p->Send_uint8 (c->colour);
    00281   p->Send_bool  (NetworkCompanyIsPassworded(c->index));
    00282   p->Send_uint32(c->inaugurated_year);
    00283   p->Send_bool  (c->is_ai);
    00284
    00285   this->SendPacket(p);
    00286
    00287   return NETWORK_RECV_STATUS_OKAY;
    00288 }
    00289
    00290 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyUpdate(const Company *c)
    00291 {
    00292   char company_name[NETWORK_COMPANY_NAME_LENGTH];
    00293   char manager_name[NETWORK_COMPANY_NAME_LENGTH];
    00294
    00295   SetDParam(0, c->index);
    00296   GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
    00297
    00298   SetDParam(0, c->index);
    00299   GetString(manager_name, STR_PRESIDENT_NAME, lastof(manager_name));
    00300
    00301   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_UPDATE);
    00302
    00303   p->Send_uint8 (c->index);
    00304   p->Send_string(company_name);
    00305   p->Send_string(manager_name);
    00306   p->Send_uint8 (c->colour);
    00307   p->Send_bool  (NetworkCompanyIsPassworded(c->index));
    00308   p->Send_uint8 (c->quarters_of_bankruptcy);
    00309
    00310   for (size_t i = 0; i < lengthof(c->share_owners); i++) {
    00311     p->Send_uint8(c->share_owners[i]);
    00312   }
    00313
    00314   this->SendPacket(p);
    00315
    00316   return NETWORK_RECV_STATUS_OKAY;
    00317 }
    00318
    00319 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason acrr)
    00320 {
    00321   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_REMOVE);
    00322
    00323   p->Send_uint8(company_id);
    00324   p->Send_uint8(acrr);
    00325
    00326   this->SendPacket(p);
    00327
    00328   return NETWORK_RECV_STATUS_OKAY;
    00329 }
    00330
    00331 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyEconomy()
    00332 {
    00333   const Company *company;
    00334   FOR_ALL_COMPANIES(company) {
    00335     /* Get the income. */
    00336     Money income = 0;
    00337     for (uint i = 0; i < lengthof(company->yearly_expenses[0]); i++) {
    00338       income -= company->yearly_expenses[0][i];
    00339     }
    00340
    00341     Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_ECONOMY);
    00342
    00343     p->Send_uint8(company->index);
    00344
    00345     /* Current information. */
    00346     p->Send_uint64(company->money);
    00347     p->Send_uint64(company->current_loan);
    00348     p->Send_uint64(income);
    00349     p->Send_uint16(company->cur_economy.delivered_cargo);
    00350
    00351     /* Send stats for the last 2 quarters. */
    00352     for (uint i = 0; i < 2; i++) {
    00353       p->Send_uint64(company->old_economy[i].company_value);
    00354       p->Send_uint16(company->old_economy[i].performance_history);
    00355       p->Send_uint16(company->old_economy[i].delivered_cargo);
    00356     }
    00357
    00358     this->SendPacket(p);
    00359   }
    00360
    00361
    00362   return NETWORK_RECV_STATUS_OKAY;
    00363 }
    00364
    00365 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyStats()
    00366 {
    00367   /* Fetch the latest version of the stats. */
    00368   NetworkCompanyStats company_stats[MAX_COMPANIES];
    00369   NetworkPopulateCompanyStats(company_stats);
    00370
    00371   const Company *company;
    00372
    00373   /* Go through all the companies. */
    00374   FOR_ALL_COMPANIES(company) {
    00375     Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_STATS);
    00376
    00377     /* Send the information. */
    00378     p->Send_uint8(company->index);
    00379
    00380     for (uint i = 0; i < NETWORK_VEH_END; i++) {
    00381       p->Send_uint16(company_stats[company->index].num_vehicle[i]);
    00382     }
    00383
    00384     for (uint i = 0; i < NETWORK_VEH_END; i++) {
    00385       p->Send_uint16(company_stats[company->index].num_station[i]);
    00386     }
    00387
    00388     this->SendPacket(p);
    00389   }
    00390
    00391   return NETWORK_RECV_STATUS_OKAY;
    00392 }
    00393
    00394 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data)
    00395 {
    00396   Packet *p = new Packet(ADMIN_PACKET_SERVER_CHAT);
    00397
    00398   p->Send_uint8 (action);
    00399   p->Send_uint8 (desttype);
    00400   p->Send_uint32(client_id);
    00401   p->Send_string(msg);
    00402   p->Send_uint64(data);
    00403
    00404   this->SendPacket(p);
    00405   return NETWORK_RECV_STATUS_OKAY;
    00406 }
    00407
    00408 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRcon(uint16 colour, const char *result)
    00409 {
    00410   Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON);
    00411
    00412   p->Send_uint16(colour);
    00413   p->Send_string(result);
    00414   this->SendPacket(p);
    00415
    00416   return NETWORK_RECV_STATUS_OKAY;
    00417 }
    00418
    00419 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_RCON)
    00420 {
    00421   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00422
    00423   char command[NETWORK_RCONCOMMAND_LENGTH];
    00424
    00425   p->Recv_string(command, sizeof(command));
    00426
    00427   DEBUG(net, 2, "[admin] Rcon command from '%s' (%s): '%s'", this->admin_name, this->admin_version, command);
    00428
    00429   _redirect_console_to_admin = this->index;
    00430   IConsoleCmdExec(command);
    00431   _redirect_console_to_admin = INVALID_ADMIN_ID;
    00432   return NETWORK_RECV_STATUS_OKAY;
    00433 }
    00434
    00435 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const char *origin, const char *string)
    00436 {
    00437   /* If the length of both strings, plus the 2 '\0' terminations and 3 bytes of the packet
    00438    * are bigger than the MTU, just ignore the message. Better safe than sorry. It should
    00439    * never occur though as the longest strings are chat messages, which are still 30%
    00440    * smaller than SEND_MTU. */
    00441   if (strlen(origin) + strlen(string) + 2 + 3 >= SEND_MTU) return NETWORK_RECV_STATUS_OKAY;
    00442
    00443   Packet *p = new Packet(ADMIN_PACKET_SERVER_CONSOLE);
    00444
    00445   p->Send_string(origin);
    00446   p->Send_string(string);
    00447   this->SendPacket(p);
    00448
    00449   return NETWORK_RECV_STATUS_OKAY;
    00450 }
    00451
    00452 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdNames()
    00453 {
    00454   Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
    00455
    00456   for (uint i = 0; i < CMD_END; i++) {
    00457     const char *cmdname = GetCommandName(i);
    00458
    00459     /* Should SEND_MTU be exceeded, start a new packet
    00460      * (magic 5: 1 bool "more data" and one uint16 "command id", one
    00461      * byte for string '\0' termination and 1 bool "no more data" */
    00462     if (p->size + strlen(cmdname) + 5 >= SEND_MTU) {
    00463       p->Send_bool(false);
    00464       this->SendPacket(p);
    00465
    00466       p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
    00467     }
    00468
    00469     p->Send_bool(true);
    00470     p->Send_uint16(i);
    00471     p->Send_string(cmdname);
    00472   }
    00473
    00474   /* Marker to notify the end of the packet has been reached. */
    00475   p->Send_bool(false);
    00476   this->SendPacket(p);
    00477
    00478   return NETWORK_RECV_STATUS_OKAY;
    00479 }
    00480
    00481 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdLogging(ClientID client_id, const CommandPacket *cp)
    00482 {
    00483   Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_LOGGING);
    00484
    00485   p->Send_uint32(client_id);
    00486   p->Send_uint8 (cp->company);
    00487   p->Send_uint16(cp->cmd & CMD_ID_MASK);
    00488   p->Send_uint32(cp->p1);
    00489   p->Send_uint32(cp->p2);
    00490   p->Send_uint32(cp->tile);
    00491   p->Send_string(cp->text);
    00492   p->Send_uint32(cp->frame);
    00493
    00494   this->SendPacket(p);
    00495
    00496   return NETWORK_RECV_STATUS_OKAY;
    00497 }
    00498
    00499 /***********
    00500  * Receiving functions
    00501  ************/
    00502
    00503 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_JOIN)
    00504 {
    00505   if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00506
    00507   char password[NETWORK_PASSWORD_LENGTH];
    00508   p->Recv_string(password, sizeof(password));
    00509
    00510   if (StrEmpty(_settings_client.network.admin_password) ||
    00511       strcmp(password, _settings_client.network.admin_password) != 0) {
    00512     /* Password is invalid */
    00513     return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
    00514   }
    00515
    00516   p->Recv_string(this->admin_name, sizeof(this->admin_name));
    00517   p->Recv_string(this->admin_version, sizeof(this->admin_version));
    00518
    00519   if (StrEmpty(this->admin_name) || StrEmpty(this->admin_version)) {
    00520     /* no name or version supplied */
    00521     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00522   }
    00523
    00524   DEBUG(net, 1, "[admin] '%s' (%s) has connected", this->admin_name, this->admin_version);
    00525
    00526   return this->SendProtocol();
    00527 }
    00528
    00529 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_QUIT)
    00530 {
    00531   /* The admin is leaving nothing else to do */
    00532   return this->CloseConnection();
    00533 }
    00534
    00535 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY)
    00536 {
    00537   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00538
    00539   AdminUpdateType type = (AdminUpdateType)p->Recv_uint16();
    00540   AdminUpdateFrequency freq = (AdminUpdateFrequency)p->Recv_uint16();
    00541
    00542   if (type >= ADMIN_UPDATE_END || (_admin_update_type_frequencies[type] & freq) != freq) {
    00543     /* The server does not know of this UpdateType. */
    00544     DEBUG(net, 3, "[admin] Not supported update frequency %d (%d) from '%s' (%s).", type, freq, this->admin_name, this->admin_version);
    00545     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00546   }
    00547
    00548   this->update_frequency[type] = freq;
    00549
    00550   return NETWORK_RECV_STATUS_OKAY;
    00551 }
    00552
    00553 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_POLL)
    00554 {
    00555   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00556
    00557   AdminUpdateType type = (AdminUpdateType)p->Recv_uint8();
    00558   uint32 d1 = p->Recv_uint32();
    00559
    00560   switch (type) {
    00561     case ADMIN_UPDATE_DATE:
    00562       /* The admin is requesting the current date. */
    00563       this->SendDate();
    00564       break;
    00565
    00566     case ADMIN_UPDATE_CLIENT_INFO:
    00567       /* The admin is requesting client info. */
    00568       const NetworkClientInfo *ci;
    00569       if (d1 == UINT32_MAX) {
    00570         FOR_ALL_CLIENT_INFOS(ci) {
    00571           this->SendClientInfo(ci);
    00572         }
    00573       } else {
    00574         ci = NetworkFindClientInfoFromClientID((ClientID)d1);
    00575         if (ci != NULL) this->SendClientInfo(ci);
    00576       }
    00577       break;
    00578
    00579     case ADMIN_UPDATE_COMPANY_INFO:
    00580       /* The admin is asking for company info. */
    00581       const Company *company;
    00582       if (d1 == UINT32_MAX) {
    00583         FOR_ALL_COMPANIES(company) {
    00584           this->SendCompanyInfo(company);
    00585         }
    00586       } else {
    00587         company = Company::GetIfValid(d1);
    00588         if (company != NULL) this->SendCompanyInfo(company);
    00589       }
    00590       break;
    00591
    00592     case ADMIN_UPDATE_COMPANY_ECONOMY:
    00593       /* The admin is requesting economy info. */
    00594       this->SendCompanyEconomy();
    00595       break;
    00596
    00597     case ADMIN_UPDATE_COMPANY_STATS:
    00598       /* the admin is requesting company stats. */
    00599       this->SendCompanyStats();
    00600       break;
    00601
    00602     case ADMIN_UPDATE_CMD_NAMES:
    00603       /* The admin is requesting the names of DoCommands. */
    00604       this->SendCmdNames();
    00605       break;
    00606
    00607     default:
    00608       /* An unsupported "poll" update type. */
    00609       DEBUG(net, 3, "[admin] Not supported poll %d (%d) from '%s' (%s).", type, d1, this->admin_name, this->admin_version);
    00610       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00611   }
    00612
    00613   return NETWORK_RECV_STATUS_OKAY;
    00614 }
    00615
    00616 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_CHAT)
    00617 {
    00618   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
    00619
    00620   NetworkAction action = (NetworkAction)p->Recv_uint8();
    00621   DestType desttype = (DestType)p->Recv_uint8();
    00622   int dest = p->Recv_uint32();
    00623
    00624   char msg[NETWORK_CHAT_LENGTH];
    00625   p->Recv_string(msg, NETWORK_CHAT_LENGTH);
    00626
    00627   switch (action) {
    00628     case NETWORK_ACTION_CHAT:
    00629     case NETWORK_ACTION_CHAT_CLIENT:
    00630     case NETWORK_ACTION_CHAT_COMPANY:
    00631     case NETWORK_ACTION_SERVER_MESSAGE:
    00632       NetworkServerSendChat(action, desttype, dest, msg, _network_own_client_id, 0, true);
    00633       break;
    00634
    00635     default:
    00636       DEBUG(net, 3, "[admin] Invalid chat action %d from admin '%s' (%s).", action, this->admin_name, this->admin_version);
    00637       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
    00638   }
    00639
    00640   return NETWORK_RECV_STATUS_OKAY;
    00641 }
    00642
    00643 /*
    00644  * Useful wrapper functions
    00645  */
    00646
    00652 void NetworkAdminClientInfo(const NetworkClientInfo *ci, bool new_client)
    00653 {
    00654   ServerNetworkAdminSocketHandler *as;
    00655   FOR_ALL_ADMIN_SOCKETS(as) {
    00656     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00657       as->SendClientInfo(ci);
    00658       if (new_client) {
    00659         as->SendClientJoin(ci->client_id);
    00660       }
    00661     }
    00662   }
    00663 }
    00664
    00669 void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
    00670 {
    00671   ServerNetworkAdminSocketHandler *as;
    00672   FOR_ALL_ADMIN_SOCKETS(as) {
    00673     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00674       as->SendClientUpdate(ci);
    00675     }
    00676   }
    00677 }
    00678
    00683 void NetworkAdminClientQuit(ClientID client_id)
    00684 {
    00685   ServerNetworkAdminSocketHandler *as;
    00686   FOR_ALL_ADMIN_SOCKETS(as) {
    00687     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00688       as->SendClientQuit(client_id);
    00689     }
    00690   }
    00691 }
    00692
    00698 void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code)
    00699 {
    00700   ServerNetworkAdminSocketHandler *as;
    00701   FOR_ALL_ADMIN_SOCKETS(as) {
    00702     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
    00703       as->SendClientError(client_id, error_code);
    00704     }
    00705   }
    00706 }
    00707
    00713 void NetworkAdminCompanyInfo(const Company *company, bool new_company)
    00714 {
    00715   if (company == NULL) {
    00716     DEBUG(net, 1, "[admin] Empty company given for update");
    00717     return;
    00718   }
    00719
    00720   ServerNetworkAdminSocketHandler *as;
    00721   FOR_ALL_ADMIN_SOCKETS(as) {
    00722     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
    00723
    00724     as->SendCompanyInfo(company);
    00725     if (new_company) {
    00726       as->SendCompanyNew(company->index);
    00727     }
    00728   }
    00729 }
    00730
    00735 void NetworkAdminCompanyUpdate(const Company *company)
    00736 {
    00737   if (company == NULL) return;
    00738
    00739   ServerNetworkAdminSocketHandler *as;
    00740   FOR_ALL_ADMIN_SOCKETS(as) {
    00741     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
    00742
    00743     as->SendCompanyUpdate(company);
    00744   }
    00745 }
    00746
    00752 void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bcrr)
    00753 {
    00754   ServerNetworkAdminSocketHandler *as;
    00755   FOR_ALL_ADMIN_SOCKETS(as) {
    00756     as->SendCompanyRemove(company_id, bcrr);
    00757   }
    00758 }
    00759
    00760
    00764 void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data, bool from_admin)
    00765 {
    00766   if (from_admin) return;
    00767
    00768   ServerNetworkAdminSocketHandler *as;
    00769   FOR_ALL_ADMIN_SOCKETS(as) {
    00770     if (as->update_frequency[ADMIN_UPDATE_CHAT] & ADMIN_FREQUENCY_AUTOMATIC) {
    00771       as->SendChat(action, desttype, client_id, msg, data);
    00772     }
    00773   }
    00774 }
    00775
    00782 void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, const char *string)
    00783 {
    00784   ServerNetworkAdminSocketHandler::Get(admin_index)->SendRcon(colour_code, string);
    00785 }
    00786
    00792 void NetworkAdminConsole(const char *origin, const char *string)
    00793 {
    00794   ServerNetworkAdminSocketHandler *as;
    00795   FOR_ALL_ADMIN_SOCKETS(as) {
    00796     if (as->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) {
    00797       as->SendConsole(origin, string);
    00798     }
    00799   }
    00800 }
    00801
    00807 void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket *cp)
    00808 {
    00809   ClientID client_id = owner == NULL ? _network_own_client_id : owner->client_id;
    00810
    00811   ServerNetworkAdminSocketHandler *as;
    00812   FOR_ALL_ADMIN_SOCKETS(as) {
    00813     if (as->update_frequency[ADMIN_UPDATE_CMD_LOGGING] & ADMIN_FREQUENCY_AUTOMATIC) {
    00814       as->SendCmdLogging(client_id, cp);
    00815     }
    00816   }
    00817 }
    00818
    00822 void ServerNetworkAdminSocketHandler::WelcomeAll()
    00823 {
    00824   ServerNetworkAdminSocketHandler *as;
    00825   FOR_ALL_ADMIN_SOCKETS(as) {
    00826     as->SendWelcome();
    00827   }
    00828 }
    00829
    00834 void NetworkAdminUpdate(AdminUpdateFrequency freq)
    00835 {
    00836   ServerNetworkAdminSocketHandler *as;
    00837   FOR_ALL_ADMIN_SOCKETS(as) {
    00838     for (int i = 0; i < ADMIN_UPDATE_END; i++) {
    00839       if (as->update_frequency[i] & freq) {
    00840         /* Update the admin for the required details */
    00841         switch (i) {
    00842           case ADMIN_UPDATE_DATE:
    00843             as->SendDate();
    00844             break;
    00845
    00846           case ADMIN_UPDATE_COMPANY_ECONOMY:
    00847             as->SendCompanyEconomy();
    00848             break;
    00849
    00850           case ADMIN_UPDATE_COMPANY_STATS:
    00851             as->SendCompanyStats();
    00852             break;
    00853
    00854           default: NOT_REACHED();
    00855         }
    00856       }
    00857     }
    00858   }
    00859 }
    00860
    00861 #endif /* ENABLE_NETWORK */