network_admin.cpp

Go to the documentation of this file.
00001 /* $Id: network_admin.cpp 21420 2010-12-06 14:55:47Z 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 "../debug.h"
00016 #include "../strings_func.h"
00017 #include "../date_func.h"
00018 #include "network_admin.h"
00019 #include "network.h"
00020 #include "network_base.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 #include "table/strings.h"
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 
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 };
00054 assert_compile(lengthof(_admin_update_type_frequencies) == ADMIN_UPDATE_END);
00055 
00060 ServerNetworkAdminSocketHandler::ServerNetworkAdminSocketHandler(SOCKET s) : NetworkAdminSocketHandler(s)
00061 {
00062   _network_admins_connected++;
00063   this->status = ADMIN_STATUS_INACTIVE;
00064   this->realtime_connect = _realtime_tick;
00065 }
00066 
00070 ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler()
00071 {
00072   _network_admins_connected--;
00073   DEBUG(net, 1, "[admin] '%s' (%s) has disconnected", this->admin_name, this->admin_version);
00074   if (_redirect_console_to_admin == this->index) _redirect_console_to_admin = INVALID_ADMIN_ID;
00075 }
00076 
00081 /* static */ bool ServerNetworkAdminSocketHandler::AllowConnection()
00082 {
00083   return !StrEmpty(_settings_client.network.admin_password) && _network_admins_connected < MAX_ADMINS;
00084 }
00085 
00087 /* static */ void ServerNetworkAdminSocketHandler::Send()
00088 {
00089   ServerNetworkAdminSocketHandler *as;
00090   FOR_ALL_ADMIN_SOCKETS(as) {
00091     if (as->status == ADMIN_STATUS_INACTIVE && as->realtime_connect + ADMIN_AUTHORISATION_TIMEOUT < _realtime_tick) {
00092       DEBUG(net, 1, "[admin] Admin did not send its authorisation within %d seconds", ADMIN_AUTHORISATION_TIMEOUT / 1000);
00093       as->CloseConnection(true);
00094       continue;
00095     }
00096     if (as->writable) {
00097       as->SendPackets();
00098     }
00099   }
00100 }
00101 
00102 /* static */ void ServerNetworkAdminSocketHandler::AcceptConnection(SOCKET s, const NetworkAddress &address)
00103 {
00104   ServerNetworkAdminSocketHandler *as = new ServerNetworkAdminSocketHandler(s);
00105   as->address = address; // Save the IP of the client
00106 }
00107 
00108 /***********
00109  * Sending functions for admin network
00110  ************/
00111 
00112 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode error)
00113 {
00114   Packet *p = new Packet(ADMIN_PACKET_SERVER_ERROR);
00115 
00116   p->Send_uint8(error);
00117   this->SendPacket(p);
00118 
00119   char str[100];
00120   StringID strid = GetNetworkErrorMsg(error);
00121   GetString(str, strid, lastof(str));
00122 
00123   DEBUG(net, 1, "[admin] the admin '%s' (%s) made an error and has been disconnected. Reason: '%s'", this->admin_name, this->admin_version, str);
00124 
00125   return this->CloseConnection(true);
00126 }
00127 
00128 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendProtocol()
00129 {
00130   Packet *p = new Packet(ADMIN_PACKET_SERVER_PROTOCOL);
00131 
00132   /* announce the protocol version */
00133   p->Send_uint8(NETWORK_GAME_ADMIN_VERSION);
00134 
00135   for (int i = 0; i < ADMIN_UPDATE_END; i++) {
00136     p->Send_bool  (true);
00137     p->Send_uint16(i);
00138     p->Send_uint16(_admin_update_type_frequencies[i]);
00139   }
00140 
00141   p->Send_bool(false);
00142   this->SendPacket(p);
00143 
00144   return this->SendWelcome();
00145 }
00146 
00147 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendWelcome()
00148 {
00149   this->status = ADMIN_STATUS_ACTIVE;
00150 
00151   Packet *p = new Packet(ADMIN_PACKET_SERVER_WELCOME);
00152 
00153   p->Send_string(_settings_client.network.server_name);
00154   p->Send_string(_openttd_revision);
00155   p->Send_bool  (_network_dedicated);
00156 
00157   p->Send_string(_network_game_info.map_name);
00158   p->Send_uint32(_settings_game.game_creation.generation_seed);
00159   p->Send_uint8 (_settings_game.game_creation.landscape);
00160   p->Send_uint32(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
00161   p->Send_uint16(MapSizeX());
00162   p->Send_uint16(MapSizeY());
00163 
00164   this->SendPacket(p);
00165 
00166   return NETWORK_RECV_STATUS_OKAY;
00167 }
00168 
00169 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendNewGame()
00170 {
00171   Packet *p = new Packet(ADMIN_PACKET_SERVER_NEWGAME);
00172   this->SendPacket(p);
00173   return NETWORK_RECV_STATUS_OKAY;
00174 }
00175 
00176 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendShutdown()
00177 {
00178   Packet *p = new Packet(ADMIN_PACKET_SERVER_SHUTDOWN);
00179   this->SendPacket(p);
00180   return NETWORK_RECV_STATUS_OKAY;
00181 }
00182 
00183 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendDate()
00184 {
00185   Packet *p = new Packet(ADMIN_PACKET_SERVER_DATE);
00186 
00187   p->Send_uint32(_date);
00188   this->SendPacket(p);
00189 
00190   return NETWORK_RECV_STATUS_OKAY;
00191 }
00192 
00193 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientJoin(ClientID client_id)
00194 {
00195   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_JOIN);
00196 
00197   p->Send_uint32(client_id);
00198   this->SendPacket(p);
00199 
00200   return NETWORK_RECV_STATUS_OKAY;
00201 }
00202 
00203 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientInfo(const NetworkClientInfo *ci)
00204 {
00205   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_INFO);
00206 
00207   p->Send_uint32(ci->client_id);
00208   p->Send_string(const_cast<NetworkAddress &>(ci->client_address).GetHostname());
00209   p->Send_string(ci->client_name);
00210   p->Send_uint8 (ci->client_lang);
00211   p->Send_uint32(ci->join_date);
00212   p->Send_uint8 (ci->client_playas);
00213 
00214   this->SendPacket(p);
00215 
00216   return NETWORK_RECV_STATUS_OKAY;
00217 }
00218 
00219 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientUpdate(const NetworkClientInfo *ci)
00220 {
00221   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_UPDATE);
00222 
00223   p->Send_uint32(ci->client_id);
00224   p->Send_string(ci->client_name);
00225   p->Send_uint8 (ci->client_playas);
00226 
00227   this->SendPacket(p);
00228 
00229   return NETWORK_RECV_STATUS_OKAY;
00230 }
00231 
00232 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientQuit(ClientID client_id)
00233 {
00234   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_QUIT);
00235 
00236   p->Send_uint32(client_id);
00237   this->SendPacket(p);
00238 
00239   return NETWORK_RECV_STATUS_OKAY;
00240 }
00241 
00242 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientError(ClientID client_id, NetworkErrorCode error)
00243 {
00244   Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_ERROR);
00245 
00246   p->Send_uint32(client_id);
00247   p->Send_uint8 (error);
00248   this->SendPacket(p);
00249 
00250   return NETWORK_RECV_STATUS_OKAY;
00251 }
00252 
00253 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyNew(CompanyID company_id)
00254 {
00255   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_NEW);
00256   p->Send_uint8(company_id);
00257 
00258   this->SendPacket(p);
00259 
00260   return NETWORK_RECV_STATUS_OKAY;
00261 }
00262 
00263 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company *c)
00264 {
00265   char company_name[NETWORK_COMPANY_NAME_LENGTH];
00266   char manager_name[NETWORK_COMPANY_NAME_LENGTH];
00267 
00268   SetDParam(0, c->index);
00269   GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
00270 
00271   SetDParam(0, c->index);
00272   GetString(manager_name, STR_PRESIDENT_NAME, lastof(manager_name));
00273 
00274   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_INFO);
00275 
00276   p->Send_uint8 (c->index);
00277   p->Send_string(company_name);
00278   p->Send_string(manager_name);
00279   p->Send_uint8 (c->colour);
00280   p->Send_bool  (NetworkCompanyIsPassworded(c->index));
00281   p->Send_uint32(c->inaugurated_year);
00282   p->Send_bool  (c->is_ai);
00283 
00284   this->SendPacket(p);
00285 
00286   return NETWORK_RECV_STATUS_OKAY;
00287 }
00288 
00289 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyUpdate(const Company *c)
00290 {
00291   char company_name[NETWORK_COMPANY_NAME_LENGTH];
00292   char manager_name[NETWORK_COMPANY_NAME_LENGTH];
00293 
00294   SetDParam(0, c->index);
00295   GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
00296 
00297   SetDParam(0, c->index);
00298   GetString(manager_name, STR_PRESIDENT_NAME, lastof(manager_name));
00299 
00300   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_UPDATE);
00301 
00302   p->Send_uint8 (c->index);
00303   p->Send_string(company_name);
00304   p->Send_string(manager_name);
00305   p->Send_uint8 (c->colour);
00306   p->Send_bool  (NetworkCompanyIsPassworded(c->index));
00307   p->Send_uint8 (c->quarters_of_bankruptcy);
00308 
00309   for (size_t i = 0; i < lengthof(c->share_owners); i++) {
00310     p->Send_uint8(c->share_owners[i]);
00311   }
00312 
00313   this->SendPacket(p);
00314 
00315   return NETWORK_RECV_STATUS_OKAY;
00316 }
00317 
00318 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason acrr)
00319 {
00320   Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_REMOVE);
00321 
00322   p->Send_uint8(company_id);
00323   p->Send_uint8(acrr);
00324 
00325   this->SendPacket(p);
00326 
00327   return NETWORK_RECV_STATUS_OKAY;
00328 }
00329 
00330 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyEconomy()
00331 {
00332   const Company *company;
00333   FOR_ALL_COMPANIES(company) {
00334     /* Get the income. */
00335     Money income = 0;
00336     for (uint i = 0; i < lengthof(company->yearly_expenses[0]); i++) {
00337       income -= company->yearly_expenses[0][i];
00338     }
00339 
00340     Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_ECONOMY);
00341 
00342     p->Send_uint8(company->index);
00343 
00344     /* Current information. */
00345     p->Send_uint64(company->money);
00346     p->Send_uint64(company->current_loan);
00347     p->Send_uint64(income);
00348     p->Send_uint16(company->cur_economy.delivered_cargo);
00349 
00350     /* Send stats for the last 2 quarters. */
00351     for (uint i = 0; i < 2; i++) {
00352       p->Send_uint64(company->old_economy[i].company_value);
00353       p->Send_uint16(company->old_economy[i].performance_history);
00354       p->Send_uint16(company->old_economy[i].delivered_cargo);
00355     }
00356 
00357     this->SendPacket(p);
00358   }
00359 
00360 
00361   return NETWORK_RECV_STATUS_OKAY;
00362 }
00363 
00364 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyStats()
00365 {
00366   /* Fetch the latest version of the stats. */
00367   NetworkCompanyStats company_stats[MAX_COMPANIES];
00368   NetworkPopulateCompanyStats(company_stats);
00369 
00370   const Company *company;
00371 
00372   /* Go through all the companies. */
00373   FOR_ALL_COMPANIES(company) {
00374     Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_STATS);
00375 
00376     /* Send the information. */
00377     p->Send_uint8(company->index);
00378 
00379     for (uint i = 0; i < NETWORK_VEH_END; i++) {
00380       p->Send_uint16(company_stats[company->index].num_vehicle[i]);
00381     }
00382 
00383     for (uint i = 0; i < NETWORK_VEH_END; i++) {
00384       p->Send_uint16(company_stats[company->index].num_station[i]);
00385     }
00386 
00387     this->SendPacket(p);
00388   }
00389 
00390   return NETWORK_RECV_STATUS_OKAY;
00391 }
00392 
00393 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data)
00394 {
00395   Packet *p = new Packet(ADMIN_PACKET_SERVER_CHAT);
00396 
00397   p->Send_uint8 (action);
00398   p->Send_uint8 (desttype);
00399   p->Send_uint32(client_id);
00400   p->Send_string(msg);
00401   p->Send_uint64(data);
00402 
00403   this->SendPacket(p);
00404   return NETWORK_RECV_STATUS_OKAY;
00405 }
00406 
00407 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRcon(uint16 colour, const char *result)
00408 {
00409   Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON);
00410 
00411   p->Send_uint16(colour);
00412   p->Send_string(result);
00413   this->SendPacket(p);
00414 
00415   return NETWORK_RECV_STATUS_OKAY;
00416 }
00417 
00418 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_RCON)
00419 {
00420   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00421 
00422   char command[NETWORK_RCONCOMMAND_LENGTH];
00423 
00424   p->Recv_string(command, sizeof(command));
00425 
00426   DEBUG(net, 2, "[admin] Rcon command from '%s' (%s): '%s'", this->admin_name, this->admin_version, command);
00427 
00428   _redirect_console_to_admin = this->index;
00429   IConsoleCmdExec(command);
00430   _redirect_console_to_admin = INVALID_ADMIN_ID;
00431   return NETWORK_RECV_STATUS_OKAY;
00432 }
00433 
00434 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const char *origin, const char *string)
00435 {
00436   /* If the length of both strings, plus the 2 '\0' terminations and 3 bytes of the packet
00437    * are bigger than the MTU, just ignore the message. Better safe than sorry. It should
00438    * never occur though as the longest strings are chat messages, which are still 30%
00439    * smaller than SEND_MTU. */
00440   if (strlen(origin) + strlen(string) + 2 + 3 >= SEND_MTU) return NETWORK_RECV_STATUS_OKAY;
00441 
00442   Packet *p = new Packet(ADMIN_PACKET_SERVER_CONSOLE);
00443 
00444   p->Send_string(origin);
00445   p->Send_string(string);
00446   this->SendPacket(p);
00447 
00448   return NETWORK_RECV_STATUS_OKAY;
00449 }
00450 
00451 /***********
00452  * Receiving functions
00453  ************/
00454 
00455 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_JOIN)
00456 {
00457   if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00458 
00459   char password[NETWORK_PASSWORD_LENGTH];
00460   p->Recv_string(password, sizeof(password));
00461 
00462   if (StrEmpty(_settings_client.network.admin_password) ||
00463       strcmp(password, _settings_client.network.admin_password) != 0) {
00464     /* Password is invalid */
00465     return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
00466   }
00467 
00468   p->Recv_string(this->admin_name, sizeof(this->admin_name));
00469   p->Recv_string(this->admin_version, sizeof(this->admin_version));
00470 
00471   if (StrEmpty(this->admin_name) || StrEmpty(this->admin_version)) {
00472     /* no name or version supplied */
00473     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
00474   }
00475 
00476   DEBUG(net, 1, "[admin] '%s' (%s) has connected", this->admin_name, this->admin_version);
00477 
00478   return this->SendProtocol();
00479 }
00480 
00481 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_QUIT)
00482 {
00483   /* The admin is leaving nothing else to do */
00484   return this->CloseConnection();
00485 }
00486 
00487 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY)
00488 {
00489   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00490 
00491   AdminUpdateType type = (AdminUpdateType)p->Recv_uint16();
00492   AdminUpdateFrequency freq = (AdminUpdateFrequency)p->Recv_uint16();
00493 
00494   if (type >= ADMIN_UPDATE_END || (_admin_update_type_frequencies[type] & freq) != freq) {
00495     /* The server does not know of this UpdateType. */
00496     DEBUG(net, 3, "[admin] Not supported update frequency %d (%d) from '%s' (%s).", type, freq, this->admin_name, this->admin_version);
00497     return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
00498   }
00499 
00500   this->update_frequency[type] = freq;
00501 
00502   return NETWORK_RECV_STATUS_OKAY;
00503 }
00504 
00505 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_POLL)
00506 {
00507   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00508 
00509   AdminUpdateType type = (AdminUpdateType)p->Recv_uint8();
00510   uint32 d1 = p->Recv_uint32();
00511 
00512   switch (type) {
00513     case ADMIN_UPDATE_DATE:
00514       /* The admin is requesting the current date. */
00515       this->SendDate();
00516       break;
00517 
00518     case ADMIN_UPDATE_CLIENT_INFO:
00519       /* The admin is requesting client info. */
00520       const NetworkClientInfo *ci;
00521       if (d1 == UINT32_MAX) {
00522         FOR_ALL_CLIENT_INFOS(ci) {
00523           this->SendClientInfo(ci);
00524         }
00525       } else {
00526         ci = NetworkFindClientInfoFromClientID((ClientID)d1);
00527         if (ci != NULL) this->SendClientInfo(ci);
00528       }
00529       break;
00530 
00531     case ADMIN_UPDATE_COMPANY_INFO:
00532       /* The admin is asking for company info. */
00533       const Company *company;
00534       if (d1 == UINT32_MAX) {
00535         FOR_ALL_COMPANIES(company) {
00536           this->SendCompanyInfo(company);
00537         }
00538       } else {
00539         company = Company::GetIfValid(d1);
00540         if (company != NULL) this->SendCompanyInfo(company);
00541       }
00542       break;
00543 
00544     case ADMIN_UPDATE_COMPANY_ECONOMY:
00545       /* The admin is requesting economy info. */
00546       this->SendCompanyEconomy();
00547       break;
00548 
00549     case ADMIN_UPDATE_COMPANY_STATS:
00550       /* the admin is requesting company stats. */
00551       this->SendCompanyStats();
00552       break;
00553 
00554     default:
00555       /* An unsupported "poll" update type. */
00556       DEBUG(net, 3, "[admin] Not supported poll %d (%d) from '%s' (%s).", type, d1, this->admin_name, this->admin_version);
00557       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
00558   }
00559 
00560   return NETWORK_RECV_STATUS_OKAY;
00561 }
00562 
00563 DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_CHAT)
00564 {
00565   if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00566 
00567   NetworkAction action = (NetworkAction)p->Recv_uint8();
00568   DestType desttype = (DestType)p->Recv_uint8();
00569   int dest = p->Recv_uint32();
00570 
00571   char msg[NETWORK_CHAT_LENGTH];
00572   p->Recv_string(msg, NETWORK_CHAT_LENGTH);
00573 
00574   switch (action) {
00575     case NETWORK_ACTION_CHAT:
00576     case NETWORK_ACTION_CHAT_CLIENT:
00577     case NETWORK_ACTION_CHAT_COMPANY:
00578     case NETWORK_ACTION_SERVER_MESSAGE:
00579       NetworkServerSendChat(action, desttype, dest, msg, _network_own_client_id, 0, true);
00580       break;
00581 
00582     default:
00583       DEBUG(net, 3, "[admin] Invalid chat action %d from admin '%s' (%s).", action, this->admin_name, this->admin_version);
00584       return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
00585   }
00586 
00587   return NETWORK_RECV_STATUS_OKAY;
00588 }
00589 
00590 /*
00591  * Useful wrapper functions
00592  */
00593 
00599 void NetworkAdminClientInfo(const NetworkClientInfo *ci, bool new_client)
00600 {
00601   ServerNetworkAdminSocketHandler *as;
00602   FOR_ALL_ADMIN_SOCKETS(as) {
00603     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
00604       as->SendClientInfo(ci);
00605       if (new_client) {
00606         as->SendClientJoin(ci->client_id);
00607       }
00608     }
00609   }
00610 }
00611 
00616 void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
00617 {
00618   ServerNetworkAdminSocketHandler *as;
00619   FOR_ALL_ADMIN_SOCKETS(as) {
00620     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
00621       as->SendClientUpdate(ci);
00622     }
00623   }
00624 }
00625 
00630 void NetworkAdminClientQuit(ClientID client_id)
00631 {
00632   ServerNetworkAdminSocketHandler *as;
00633   FOR_ALL_ADMIN_SOCKETS(as) {
00634     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
00635       as->SendClientQuit(client_id);
00636     }
00637   }
00638 }
00639 
00645 void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code)
00646 {
00647   ServerNetworkAdminSocketHandler *as;
00648   FOR_ALL_ADMIN_SOCKETS(as) {
00649     if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
00650       as->SendClientError(client_id, error_code);
00651     }
00652   }
00653 }
00654 
00660 void NetworkAdminCompanyInfo(const Company *company, bool new_company)
00661 {
00662   if (company == NULL) {
00663     DEBUG(net, 1, "[admin] Empty company given for update");
00664     return;
00665   }
00666 
00667   ServerNetworkAdminSocketHandler *as;
00668   FOR_ALL_ADMIN_SOCKETS(as) {
00669     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
00670 
00671     as->SendCompanyInfo(company);
00672     if (new_company) {
00673       as->SendCompanyNew(company->index);
00674     }
00675   }
00676 }
00677 
00682 void NetworkAdminCompanyUpdate(const Company *company)
00683 {
00684   if (company == NULL) return;
00685 
00686   ServerNetworkAdminSocketHandler *as;
00687   FOR_ALL_ADMIN_SOCKETS(as) {
00688     if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
00689 
00690     as->SendCompanyUpdate(company);
00691   }
00692 }
00693 
00699 void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bcrr)
00700 {
00701   ServerNetworkAdminSocketHandler *as;
00702   FOR_ALL_ADMIN_SOCKETS(as) {
00703     as->SendCompanyRemove(company_id, bcrr);
00704   }
00705 }
00706 
00707 
00711 void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data, bool from_admin)
00712 {
00713   if (from_admin) return;
00714 
00715   ServerNetworkAdminSocketHandler *as;
00716   FOR_ALL_ADMIN_SOCKETS(as) {
00717     if (as->update_frequency[ADMIN_UPDATE_CHAT] & ADMIN_FREQUENCY_AUTOMATIC) {
00718       as->SendChat(action, desttype, client_id, msg, data);
00719     }
00720   }
00721 }
00722 
00729 void NetworkServerSendAdminRcon(AdminIndex admin_index, ConsoleColour colour_code, const char *string)
00730 {
00731   ServerNetworkAdminSocketHandler::Get(admin_index)->SendRcon(colour_code, string);
00732 }
00733 
00739 void NetworkAdminConsole(const char *origin, const char *string)
00740 {
00741   ServerNetworkAdminSocketHandler *as;
00742   FOR_ALL_ADMIN_SOCKETS(as) {
00743     if (as->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) {
00744       as->SendConsole(origin, string);
00745     }
00746   }
00747 }
00748 
00752 void ServerNetworkAdminSocketHandler::WelcomeAll()
00753 {
00754   ServerNetworkAdminSocketHandler *as;
00755   FOR_ALL_ADMIN_SOCKETS(as) {
00756     as->SendWelcome();
00757   }
00758 }
00759 
00764 void NetworkAdminUpdate(AdminUpdateFrequency freq)
00765 {
00766   ServerNetworkAdminSocketHandler *as;
00767   FOR_ALL_ADMIN_SOCKETS(as) {
00768     for (int i = 0; i < ADMIN_UPDATE_END; i++) {
00769       if (as->update_frequency[i] & freq) {
00770         /* Update the admin for the required details */
00771         switch (i) {
00772           case ADMIN_UPDATE_DATE:
00773             as->SendDate();
00774             break;
00775 
00776           case ADMIN_UPDATE_COMPANY_ECONOMY:
00777             as->SendCompanyEconomy();
00778             break;
00779 
00780           case ADMIN_UPDATE_COMPANY_STATS:
00781             as->SendCompanyStats();
00782             break;
00783 
00784           default: NOT_REACHED();
00785         }
00786       }
00787     }
00788   }
00789 }
00790 
00791 #endif /* ENABLE_NETWORK */

Generated on Thu Dec 23 23:41:26 2010 for OpenTTD by  doxygen 1.6.1