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