network_admin.cpp

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