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 */