network_admin.cpp

Go to the documentation of this file.
00001 /* $Id: network_admin.cpp 25845 2013-10-12 17:03:15Z planetmaker $ */
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 #include "../game/game.hpp"
00027 
00028 
00029 /* This file handles all the admin network commands. */
00030 
00032 AdminIndex _redirect_console_to_admin = INVALID_ADMIN_ID;
00033 
00035 byte _network_admins_connected = 0;
00036 
00038 NetworkAdminSocketPool _networkadminsocket_pool("NetworkAdminSocket");
00039 INSTANTIATE_POOL_METHODS(NetworkAdminSocket)
00040 
00041 
00042 static const int ADMIN_AUTHORISATION_TIMEOUT = 10000;
00043 
00044 
00046 static const AdminUpdateFrequency _admin_update_type_frequencies[] = {
00047   ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_DAILY | ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, 
00048   ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      
00049   ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      
00050   ADMIN_FREQUENCY_POLL |                         ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, 
00051   ADMIN_FREQUENCY_POLL |                         ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, 
00052                          ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      
00053                          ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      
00054   ADMIN_FREQUENCY_POLL,                                                                                                                                  
00055                          ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      
00056                          ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      
00057 };
00059 assert_compile(lengthof(_admin_update_type_frequencies) == ADMIN_UPDATE_END);
00060 
00065 ServerNetworkAdminSocketHandler::ServerNetworkAdminSocketHandler(SOCKET s) : NetworkAdminSocketHandler(s)
00066 {
00067   _network_admins_connected++;
00068   this->status = ADMIN_STATUS_INACTIVE;
00069   this->realtime_connect = _realtime_tick;
00070 }
00071 
00075 ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler()
00076 {
00077   _network_admins_connected--;
00078   DEBUG(net, 1, "[admin] '%s' (%s) has disconnected", this->admin_name, this->admin_version);
00079   if (_redirect_console_to_admin == this->index) _redirect_console_to_admin = INVALID_ADMIN_ID;
00080 }
00081 
00086 /* static */ bool ServerNetworkAdminSocketHandler::AllowConnection()
00087 {
00088   bool accept = !StrEmpty(_settings_client.network.admin_password) && _network_admins_connected < MAX_ADMINS;
00089   /* We can't go over the MAX_ADMINS limit here. However, if we accept
00090    * the connection, there has to be space in the pool. */
00091   assert_compile(NetworkAdminSocketPool::MAX_SIZE == MAX_ADMINS);
00092   assert(!accept || ServerNetworkAdminSocketHandler::CanAllocateItem());
00093   return accept;
00094 }
00095 
00097 /* static */ void ServerNetworkAdminSocketHandler::Send()
00098 {
00099   ServerNetworkAdminSocketHandler *as;
00100   FOR_ALL_ADMIN_SOCKETS(as) {
00101     if (as->status == ADMIN_STATUS_INACTIVE && as->realtime_connect + ADMIN_AUTHORISATION_TIMEOUT < _realtime_tick) {
00102       DEBUG(net, 1, "[admin] Admin did not send its authorisation within %d seconds", ADMIN_AUTHORISATION_TIMEOUT / 1000);
00103       as->CloseConnection(true);
00104       continue;
00105     }
00106     if (as->writable) {
00107       as->SendPackets();
00108     }
00109   }
00110 }
00111 
00117 /* static */ void ServerNetworkAdminSocketHandler::AcceptConnection(SOCKET s, const NetworkAddress &address)
00118 {
00119   ServerNetworkAdminSocketHandler *as = new ServerNetworkAdminSocketHandler(s);
00120   as->address = address; // Save the IP of the client
00121 }
00122 
00123 /***********
00124  * Sending functions for admin network
00125  ************/
00126 
00131 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode error)
00132 {
00133   Packet *p = new Packet(ADMIN_PACKET_SERVER_ERROR);
00134 
00135   p->Send_uint8(error);
00136   this->SendPacket(p);
00137 
00138   char str[100];
00139   StringID strid = GetNetworkErrorMsg(error);
00140   GetString(str, strid, lastof(str));
00141 
00142   DEBUG(net, 1, "[admin] the admin '%s' (%s) made an error and has been disconnected. Reason: '%s'", this->admin_name, this->admin_version, str);
00143 
00144   return this->CloseConnection(true);
00145 }
00146 
00148 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendProtocol()
00149 {
00150   Packet *p = new Packet(ADMIN_PACKET_SERVER_PROTOCOL);
00151 
00152   /* announce the protocol version */
00153   p->Send_uint8(NETWORK_GAME_ADMIN_VERSION);
00154 
00155   for (int i = 0; i < ADMIN_UPDATE_END; i++) {
00156     p->Send_bool  (true);
00157     p->Send_uint16(i);
00158     p->Send_uint16(_admin_update_type_frequencies[i]);
00159   }
00160 
00161   p->Send_bool(false);
00162   this->SendPacket(p);
00163 
00164   return this->SendWelcome();
00165 }
00166 
00168 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendWelcome()
00169 {
00170   Packet *p = new Packet(ADMIN_PACKET_SERVER_WELCOME);
00171 
00172   p->Send_string(_settings_client.network.server_name);
00173   p->Send_string(_openttd_revision);
00174   p->Send_bool  (_network_dedicated);
00175 
00176   p->Send_string(_network_game_info.map_name);
00177   p->Send_uint32(_settings_game.game_creation.generation_seed);
00178   p->Send_uint8 (_settings_game.game_creation.landscape);
00179   p->Send_uint32(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
00180   p->Send_uint16(MapSizeX());
00181   p->Send_uint16(MapSizeY());
00182 
00183   this->SendPacket(p);
00184 
00185   return NETWORK_RECV_STATUS_OKAY;
00186 }
00187 
00189 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendNewGame()
00190 {
00191   Packet *p = new Packet(ADMIN_PACKET_SERVER_NEWGAME);
00192   this->SendPacket(p);
00193   return NETWORK_RECV_STATUS_OKAY;
00194 }
00195 
00197 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendShutdown()
00198 {
00199   Packet *p = new Packet(ADMIN_PACKET_SERVER_SHUTDOWN);
00200   this->SendPacket(p);
00201   return NETWORK_RECV_STATUS_OKAY;
00202 }
00203 
00205 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendDate()
00206 {
00207   Packet *p = new Packet(ADMIN_PACKET_SERVER_DATE);
00208 
00209   p->Send_uint32(_date);
00210   this->SendPacket(p);
00211 
00212   return NETWORK_RECV_STATUS_OKAY;
00213 }
00214 
00219 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientJoin(ClientID client_id)
00220 {
00221   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_JOIN);
00222 
00223   p->Send_uint32(client_id);
00224   this->SendPacket(p);
00225 
00226   return NETWORK_RECV_STATUS_OKAY;
00227 }
00228 
00234 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientInfo(const NetworkClientSocket *cs, const NetworkClientInfo *ci)
00235 {
00236   /* Only send data when we're a proper client, not just someone trying to query the server. */
00237   if (ci == NULL) return NETWORK_RECV_STATUS_OKAY;
00238 
00239   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_INFO);
00240 
00241   p->Send_uint32(ci->client_id);
00242   p->Send_string(cs == NULL ? "" : const_cast<NetworkAddress &>(cs->client_address).GetHostname());
00243   p->Send_string(ci->client_name);
00244   p->Send_uint8 (ci->client_lang);
00245   p->Send_uint32(ci->join_date);
00246   p->Send_uint8 (ci->client_playas);
00247 
00248   this->SendPacket(p);
00249 
00250   return NETWORK_RECV_STATUS_OKAY;
00251 }
00252 
00253 
00258 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientUpdate(const NetworkClientInfo *ci)
00259 {
00260   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_UPDATE);
00261 
00262   p->Send_uint32(ci->client_id);
00263   p->Send_string(ci->client_name);
00264   p->Send_uint8 (ci->client_playas);
00265 
00266   this->SendPacket(p);
00267 
00268   return NETWORK_RECV_STATUS_OKAY;
00269 }
00270 
00275 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientQuit(ClientID client_id)
00276 {
00277   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_QUIT);
00278 
00279   p->Send_uint32(client_id);
00280   this->SendPacket(p);
00281 
00282   return NETWORK_RECV_STATUS_OKAY;
00283 }
00284 
00290 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientError(ClientID client_id, NetworkErrorCode error)
00291 {
00292   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_ERROR);
00293 
00294   p->Send_uint32(client_id);
00295   p->Send_uint8 (error);
00296   this->SendPacket(p);
00297 
00298   return NETWORK_RECV_STATUS_OKAY;
00299 }
00300 
00305 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyNew(CompanyID company_id)
00306 {
00307   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_NEW);
00308   p->Send_uint8(company_id);
00309 
00310   this->SendPacket(p);
00311 
00312   return NETWORK_RECV_STATUS_OKAY;
00313 }
00314 
00319 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company *c)
00320 {
00321   char company_name[NETWORK_COMPANY_NAME_LENGTH];
00322   char manager_name[NETWORK_COMPANY_NAME_LENGTH];
00323 
00324   SetDParam(0, c->index);
00325   GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
00326 
00327   SetDParam(0, c->index);
00328   GetString(manager_name, STR_PRESIDENT_NAME, lastof(manager_name));
00329 
00330   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_INFO);
00331 
00332   p->Send_uint8 (c->index);
00333   p->Send_string(company_name);
00334   p->Send_string(manager_name);
00335   p->Send_uint8 (c->colour);
00336   p->Send_bool  (NetworkCompanyIsPassworded(c->index));
00337   p->Send_uint32(c->inaugurated_year);
00338   p->Send_bool  (c->is_ai);
00339   p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy
00340 
00341   for (size_t i = 0; i < lengthof(c->share_owners); i++) {
00342     p->Send_uint8(c->share_owners[i]);
00343   }
00344 
00345   this->SendPacket(p);
00346 
00347   return NETWORK_RECV_STATUS_OKAY;
00348 }
00349 
00350 
00355 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyUpdate(const Company *c)
00356 {
00357   char company_name[NETWORK_COMPANY_NAME_LENGTH];
00358   char manager_name[NETWORK_COMPANY_NAME_LENGTH];
00359 
00360   SetDParam(0, c->index);
00361   GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
00362 
00363   SetDParam(0, c->index);
00364   GetString(manager_name, STR_PRESIDENT_NAME, lastof(manager_name));
00365 
00366   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_UPDATE);
00367 
00368   p->Send_uint8 (c->index);
00369   p->Send_string(company_name);
00370   p->Send_string(manager_name);
00371   p->Send_uint8 (c->colour);
00372   p->Send_bool  (NetworkCompanyIsPassworded(c->index));
00373   p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy
00374 
00375   for (size_t i = 0; i < lengthof(c->share_owners); i++) {
00376     p->Send_uint8(c->share_owners[i]);
00377   }
00378 
00379   this->SendPacket(p);
00380 
00381   return NETWORK_RECV_STATUS_OKAY;
00382 }
00383 
00389 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason acrr)
00390 {
00391   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_REMOVE);
00392 
00393   p->Send_uint8(company_id);
00394   p->Send_uint8(acrr);
00395 
00396   this->SendPacket(p);
00397 
00398   return NETWORK_RECV_STATUS_OKAY;
00399 }
00400 
00402 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyEconomy()
00403 {
00404   const Company *company;
00405   FOR_ALL_COMPANIES(company) {
00406     /* Get the income. */
00407     Money income = 0;
00408     for (uint i = 0; i < lengthof(company->yearly_expenses[0]); i++) {
00409       income -= company->yearly_expenses[0][i];
00410     }
00411 
00412     Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_ECONOMY);
00413 
00414     p->Send_uint8(company->index);
00415 
00416     /* Current information. */
00417     p->Send_uint64(company->money);
00418     p->Send_uint64(company->current_loan);
00419     p->Send_uint64(income);
00420     p->Send_uint16(min(UINT16_MAX, company->cur_economy.delivered_cargo.GetSum<OverflowSafeInt64>()));
00421 
00422     /* Send stats for the last 2 quarters. */
00423     for (uint i = 0; i < 2; i++) {
00424       p->Send_uint64(company->old_economy[i].company_value);
00425       p->Send_uint16(company->old_economy[i].performance_history);
00426       p->Send_uint16(min(UINT16_MAX, company->old_economy[i].delivered_cargo.GetSum<OverflowSafeInt64>()));
00427     }
00428 
00429     this->SendPacket(p);
00430   }
00431 
00432 
00433   return NETWORK_RECV_STATUS_OKAY;
00434 }
00435 
00437 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyStats()
00438 {
00439   /* Fetch the latest version of the stats. */
00440   NetworkCompanyStats company_stats[MAX_COMPANIES];
00441   NetworkPopulateCompanyStats(company_stats);
00442 
00443   const Company *company;
00444 
00445   /* Go through all the companies. */
00446   FOR_ALL_COMPANIES(company) {
00447     Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_STATS);
00448 
00449     /* Send the information. */
00450     p->Send_uint8(company->index);
00451 
00452     for (uint i = 0; i < NETWORK_VEH_END; i++) {
00453       p->Send_uint16(company_stats[company->index].num_vehicle[i]);
00454     }
00455 
00456     for (uint i = 0; i < NETWORK_VEH_END; i++) {
00457       p->Send_uint16(company_stats[company->index].num_station[i]);
00458     }
00459 
00460     this->SendPacket(p);
00461   }
00462 
00463   return NETWORK_RECV_STATUS_OKAY;
00464 }
00465 
00474 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data)
00475 {
00476   Packet *p = new Packet(ADMIN_PACKET_SERVER_CHAT);
00477 
00478   p->Send_uint8 (action);
00479   p->Send_uint8 (desttype);
00480   p->Send_uint32(client_id);
00481   p->Send_string(msg);
00482   p->Send_uint64(data);
00483 
00484   this->SendPacket(p);
00485   return NETWORK_RECV_STATUS_OKAY;
00486 }
00487 
00492 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRconEnd(const char *command)
00493 {
00494   Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON_END);
00495 
00496   p->Send_string(command);
00497   this->SendPacket(p);
00498 
00499   return NETWORK_RECV_STATUS_OKAY;
00500 }
00501 
00507 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRcon(uint16 colour, const char *result)
00508 {
00509   Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON);
00510 
00511   p->Send_uint16(colour);
00512   p->Send_string(result);
00513   this->SendPacket(p);
00514 
00515   return NETWORK_RECV_STATUS_OKAY;
00516 }
00517 
00518 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet *p)
00519 {
00520   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00521 
00522   char command[NETWORK_RCONCOMMAND_LENGTH];
00523 
00524   p->Recv_string(command, sizeof(command));
00525 
00526   DEBUG(net, 2, "[admin] Rcon command from '%s' (%s): '%s'", this->admin_name, this->admin_version, command);
00527 
00528   _redirect_console_to_admin = this->index;
00529   IConsoleCmdExec(command);
00530   _redirect_console_to_admin = INVALID_ADMIN_ID;
00531   return this->SendRconEnd(command);
00532 }
00533 
00534 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet *p)
00535 {
00536   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00537 
00538   char json[NETWORK_GAMESCRIPT_JSON_LENGTH];
00539 
00540   p->Recv_string(json, sizeof(json));
00541 
00542   DEBUG(net, 2, "[admin] GameScript JSON from '%s' (%s): '%s'", this->admin_name, this->admin_version, json);
00543 
00544   Game::NewEvent(new ScriptEventAdminPort(json));
00545   return NETWORK_RECV_STATUS_OKAY;
00546 }
00547 
00548 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_PING(Packet *p)
00549 {
00550   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00551 
00552   uint32 d1 = p->Recv_uint32();
00553 
00554   DEBUG(net, 2, "[admin] Ping from '%s' (%s): '%d'", this->admin_name, this->admin_version, d1);
00555 
00556   return this->SendPong(d1);
00557 }
00558 
00564 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const char *origin, const char *string)
00565 {
00566   /* If the length of both strings, plus the 2 '\0' terminations and 3 bytes of the packet
00567    * are bigger than the MTU, just ignore the message. Better safe than sorry. It should
00568    * never occur though as the longest strings are chat messages, which are still 30%
00569    * smaller than SEND_MTU. */
00570   if (strlen(origin) + strlen(string) + 2 + 3 >= SEND_MTU) return NETWORK_RECV_STATUS_OKAY;
00571 
00572   Packet *p = new Packet(ADMIN_PACKET_SERVER_CONSOLE);
00573 
00574   p->Send_string(origin);
00575   p->Send_string(string);
00576   this->SendPacket(p);
00577 
00578   return NETWORK_RECV_STATUS_OKAY;
00579 }
00580 
00585 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendGameScript(const char *json)
00586 {
00587   /* At the moment we cannot transmit anything larger than MTU. So we limit
00588    *  the maximum amount of json data that can be sent. Account also for
00589    *  the trailing \0 of the string */
00590   if (strlen(json) + 1 >= NETWORK_GAMESCRIPT_JSON_LENGTH) return NETWORK_RECV_STATUS_OKAY;
00591 
00592   Packet *p = new Packet(ADMIN_PACKET_SERVER_GAMESCRIPT);
00593 
00594   p->Send_string(json);
00595   this->SendPacket(p);
00596 
00597   return NETWORK_RECV_STATUS_OKAY;
00598 }
00599 
00601 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendPong(uint32 d1)
00602 {
00603   Packet *p = new Packet(ADMIN_PACKET_SERVER_PONG);
00604 
00605   p->Send_uint32(d1);
00606   this->SendPacket(p);
00607 
00608   return NETWORK_RECV_STATUS_OKAY;
00609 }
00610 
00612 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdNames()
00613 {
00614   Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
00615 
00616   for (uint i = 0; i < CMD_END; i++) {
00617     const char *cmdname = GetCommandName(i);
00618 
00619     /* Should SEND_MTU be exceeded, start a new packet
00620      * (magic 5: 1 bool "more data" and one uint16 "command id", one
00621      * byte for string '\0' termination and 1 bool "no more data" */
00622     if (p->size + strlen(cmdname) + 5 >= SEND_MTU) {
00623       p->Send_bool(false);
00624       this->SendPacket(p);
00625 
00626       p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
00627     }
00628 
00629     p->Send_bool(true);
00630     p->Send_uint16(i);
00631     p->Send_string(cmdname);
00632   }
00633 
00634   /* Marker to notify the end of the packet has been reached. */
00635   p->Send_bool(false);
00636   this->SendPacket(p);
00637 
00638   return NETWORK_RECV_STATUS_OKAY;
00639 }
00640 
00646 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdLogging(ClientID client_id, const CommandPacket *cp)
00647 {
00648   Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_LOGGING);
00649 
00650   p->Send_uint32(client_id);
00651   p->Send_uint8 (cp->company);
00652   p->Send_uint16(cp->cmd & CMD_ID_MASK);
00653   p->Send_uint32(cp->p1);
00654   p->Send_uint32(cp->p2);
00655   p->Send_uint32(cp->tile);
00656   p->Send_string(cp->text);
00657   p->Send_uint32(cp->frame);
00658 
00659   this->SendPacket(p);
00660 
00661   return NETWORK_RECV_STATUS_OKAY;
00662 }
00663 
00664 /***********
00665  * Receiving functions
00666  ************/
00667 
00668 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet *p)
00669 {
00670   if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00671 
00672   char password[NETWORK_PASSWORD_LENGTH];
00673   p->Recv_string(password, sizeof(password));
00674 
00675   if (StrEmpty(_settings_client.network.admin_password) ||
00676       strcmp(password, _settings_client.network.admin_password) != 0) {
00677     /* Password is invalid */
00678     return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
00679   }
00680 
00681   p->Recv_string(this->admin_name, sizeof(this->admin_name));
00682   p->Recv_string(this->admin_version, sizeof(this->admin_version));
00683 
00684   if (StrEmpty(this->admin_name) || StrEmpty(this->admin_version)) {
00685     /* no name or version supplied */
00686     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
00687   }
00688 
00689   this->status = ADMIN_STATUS_ACTIVE;
00690 
00691   DEBUG(net, 1, "[admin] '%s' (%s) has connected", this->admin_name, this->admin_version);
00692 
00693   return this->SendProtocol();
00694 }
00695 
00696 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_QUIT(Packet *p)
00697 {
00698   /* The admin is leaving nothing else to do */
00699   return this->CloseConnection();
00700 }
00701 
00702 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENCY(Packet *p)
00703 {
00704   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00705 
00706   AdminUpdateType type = (AdminUpdateType)p->Recv_uint16();
00707   AdminUpdateFrequency freq = (AdminUpdateFrequency)p->Recv_uint16();
00708 
00709   if (type >= ADMIN_UPDATE_END || (_admin_update_type_frequencies[type] & freq) != freq) {
00710     /* The server does not know of this UpdateType. */
00711     DEBUG(net, 3, "[admin] Not supported update frequency %d (%d) from '%s' (%s).", type, freq, this->admin_name, this->admin_version);
00712     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
00713   }
00714 
00715   this->update_frequency[type] = freq;
00716 
00717   return NETWORK_RECV_STATUS_OKAY;
00718 }
00719 
00720 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet *p)
00721 {
00722   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00723 
00724   AdminUpdateType type = (AdminUpdateType)p->Recv_uint8();
00725   uint32 d1 = p->Recv_uint32();
00726 
00727   switch (type) {
00728     case ADMIN_UPDATE_DATE:
00729       /* The admin is requesting the current date. */
00730       this->SendDate();
00731       break;
00732 
00733     case ADMIN_UPDATE_CLIENT_INFO:
00734       /* The admin is requesting client info. */
00735       const NetworkClientSocket *cs;
00736       if (d1 == UINT32_MAX) {
00737         this->SendClientInfo(NULL, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
00738         FOR_ALL_CLIENT_SOCKETS(cs) {
00739           this->SendClientInfo(cs, cs->GetInfo());
00740         }
00741       } else {
00742         if (d1 == CLIENT_ID_SERVER) {
00743           this->SendClientInfo(NULL, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
00744         } else {
00745           cs = NetworkClientSocket::GetByClientID((ClientID)d1);
00746           if (cs != NULL) this->SendClientInfo(cs, cs->GetInfo());
00747         }
00748       }
00749       break;
00750 
00751     case ADMIN_UPDATE_COMPANY_INFO:
00752       /* The admin is asking for company info. */
00753       const Company *company;
00754       if (d1 == UINT32_MAX) {
00755         FOR_ALL_COMPANIES(company) {
00756           this->SendCompanyInfo(company);
00757         }
00758       } else {
00759         company = Company::GetIfValid(d1);
00760         if (company != NULL) this->SendCompanyInfo(company);
00761       }
00762       break;
00763 
00764     case ADMIN_UPDATE_COMPANY_ECONOMY:
00765       /* The admin is requesting economy info. */
00766       this->SendCompanyEconomy();
00767       break;
00768 
00769     case ADMIN_UPDATE_COMPANY_STATS:
00770       /* the admin is requesting company stats. */
00771       this->SendCompanyStats();
00772       break;
00773 
00774     case ADMIN_UPDATE_CMD_NAMES:
00775       /* The admin is requesting the names of DoCommands. */
00776       this->SendCmdNames();
00777       break;
00778 
00779     default:
00780       /* An unsupported "poll" update type. */
00781       DEBUG(net, 3, "[admin] Not supported poll %d (%d) from '%s' (%s).", type, d1, this->admin_name, this->admin_version);
00782       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
00783   }
00784 
00785   return NETWORK_RECV_STATUS_OKAY;
00786 }
00787 
00788 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet *p)
00789 {
00790   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00791 
00792   NetworkAction action = (NetworkAction)p->Recv_uint8();
00793   DestType desttype = (DestType)p->Recv_uint8();
00794   int dest = p->Recv_uint32();
00795 
00796   char msg[NETWORK_CHAT_LENGTH];
00797   p->Recv_string(msg, NETWORK_CHAT_LENGTH);
00798 
00799   switch (action) {
00800     case NETWORK_ACTION_CHAT:
00801     case NETWORK_ACTION_CHAT_CLIENT:
00802     case NETWORK_ACTION_CHAT_COMPANY:
00803     case NETWORK_ACTION_SERVER_MESSAGE:
00804       NetworkServerSendChat(action, desttype, dest, msg, _network_own_client_id, 0, true);
00805       break;
00806 
00807     default:
00808       DEBUG(net, 3, "[admin] Invalid chat action %d from admin '%s' (%s).", action, this->admin_name, this->admin_version);
00809       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
00810   }
00811 
00812   return NETWORK_RECV_STATUS_OKAY;
00813 }
00814 
00815 /*
00816  * Useful wrapper functions
00817  */
00818 
00824 void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client)
00825 {
00826   ServerNetworkAdminSocketHandler *as;
00827   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
00828     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
00829       as->SendClientInfo(cs, cs->GetInfo());
00830       if (new_client) {
00831         as->SendClientJoin(cs->client_id);
00832       }
00833     }
00834   }
00835 }
00836 
00841 void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
00842 {
00843   ServerNetworkAdminSocketHandler *as;
00844   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
00845     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
00846       as->SendClientUpdate(ci);
00847     }
00848   }
00849 }
00850 
00855 void NetworkAdminClientQuit(ClientID client_id)
00856 {
00857   ServerNetworkAdminSocketHandler *as;
00858   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
00859     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
00860       as->SendClientQuit(client_id);
00861     }
00862   }
00863 }
00864 
00870 void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code)
00871 {
00872   ServerNetworkAdminSocketHandler *as;
00873   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
00874     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
00875       as->SendClientError(client_id, error_code);
00876     }
00877   }
00878 }
00879 
00885 void NetworkAdminCompanyInfo(const Company *company, bool new_company)
00886 {
00887   if (company == NULL) {
00888     DEBUG(net, 1, "[admin] Empty company given for update");
00889     return;
00890   }
00891 
00892   ServerNetworkAdminSocketHandler *as;
00893   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
00894     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
00895 
00896     as->SendCompanyInfo(company);
00897     if (new_company) {
00898       as->SendCompanyNew(company->index);
00899     }
00900   }
00901 }
00902 
00907 void NetworkAdminCompanyUpdate(const Company *company)
00908 {
00909   if (company == NULL) return;
00910 
00911   ServerNetworkAdminSocketHandler *as;
00912   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
00913     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
00914 
00915     as->SendCompanyUpdate(company);
00916   }
00917 }
00918 
00924 void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bcrr)
00925 {
00926   ServerNetworkAdminSocketHandler *as;
00927   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
00928     as->SendCompanyRemove(company_id, bcrr);
00929   }
00930 }
00931 
00932 
00936 void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data, bool from_admin)
00937 {
00938   if (from_admin) return;
00939 
00940   ServerNetworkAdminSocketHandler *as;
00941   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
00942     if (as->update_frequency[ADMIN_UPDATE_CHAT] & ADMIN_FREQUENCY_AUTOMATIC) {
00943       as->SendChat(action, desttype, client_id, msg, data);
00944     }
00945   }
00946 }
00947 
00954 void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, const char *string)
00955 {
00956   ServerNetworkAdminSocketHandler::Get(admin_index)->SendRcon(colour_code, string);
00957 }
00958 
00964 void NetworkAdminConsole(const char *origin, const char *string)
00965 {
00966   ServerNetworkAdminSocketHandler *as;
00967   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
00968     if (as->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) {
00969       as->SendConsole(origin, string);
00970     }
00971   }
00972 }
00973 
00978 void NetworkAdminGameScript(const char *json)
00979 {
00980   ServerNetworkAdminSocketHandler *as;
00981   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
00982     if (as->update_frequency[ADMIN_UPDATE_GAMESCRIPT] & ADMIN_FREQUENCY_AUTOMATIC) {
00983       as->SendGameScript(json);
00984     }
00985   }
00986 }
00987 
00993 void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket *cp)
00994 {
00995   ClientID client_id = owner == NULL ? _network_own_client_id : owner->client_id;
00996 
00997   ServerNetworkAdminSocketHandler *as;
00998   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
00999     if (as->update_frequency[ADMIN_UPDATE_CMD_LOGGING] & ADMIN_FREQUENCY_AUTOMATIC) {
01000       as->SendCmdLogging(client_id, cp);
01001     }
01002   }
01003 }
01004 
01008 void ServerNetworkAdminSocketHandler::WelcomeAll()
01009 {
01010   ServerNetworkAdminSocketHandler *as;
01011   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
01012     as->SendWelcome();
01013   }
01014 }
01015 
01020 void NetworkAdminUpdate(AdminUpdateFrequency freq)
01021 {
01022   ServerNetworkAdminSocketHandler *as;
01023   FOR_ALL_ACTIVE_ADMIN_SOCKETS(as) {
01024     for (int i = 0; i < ADMIN_UPDATE_END; i++) {
01025       if (as->update_frequency[i] & freq) {
01026         /* Update the admin for the required details */
01027         switch (i) {
01028           case ADMIN_UPDATE_DATE:
01029             as->SendDate();
01030             break;
01031 
01032           case ADMIN_UPDATE_COMPANY_ECONOMY:
01033             as->SendCompanyEconomy();
01034             break;
01035 
01036           case ADMIN_UPDATE_COMPANY_STATS:
01037             as->SendCompanyStats();
01038             break;
01039 
01040           default: NOT_REACHED();
01041         }
01042       }
01043     }
01044   }
01045 }
01046 
01047 #endif /* ENABLE_NETWORK */