Codechange: Use EnumBitSet for EndSegmentReasons. (#13490)
[openttd-github.git] / src / network / network_admin.cpp
blob611a3980ad8bfbff995e763f86298cf04d1c7d19
1 /*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
6 */
8 /** @file network_admin.cpp Server part of the admin network protocol. */
10 #include "../stdafx.h"
11 #include "../strings_func.h"
12 #include "../timer/timer_game_calendar.h"
13 #include "../timer/timer_game_calendar.h"
14 #include "core/network_game_info.h"
15 #include "network_admin.h"
16 #include "network_base.h"
17 #include "network_server.h"
18 #include "../command_func.h"
19 #include "../company_base.h"
20 #include "../console_func.h"
21 #include "../core/pool_func.hpp"
22 #include "../map_func.h"
23 #include "../rev.h"
24 #include "../game/game.hpp"
26 #include "../safeguards.h"
29 /* This file handles all the admin network commands. */
31 /** Redirection of the (remote) console to the admin. */
32 AdminID _redirect_console_to_admin = INVALID_ADMIN_ID;
34 /** The pool with sockets/clients. */
35 NetworkAdminSocketPool _networkadminsocket_pool("NetworkAdminSocket");
36 INSTANTIATE_POOL_METHODS(NetworkAdminSocket)
38 static NetworkAuthenticationDefaultPasswordProvider _admin_password_provider(_settings_client.network.admin_password); ///< Provides the password validation for the game's password.
39 static NetworkAuthenticationDefaultAuthorizedKeyHandler _admin_authorized_key_handler(_settings_client.network.admin_authorized_keys); ///< Provides the authorized key handling for the game authentication.
41 /** The timeout for authorisation of the client. */
42 static const std::chrono::seconds ADMIN_AUTHORISATION_TIMEOUT(10);
45 /** Frequencies, which may be registered for a certain update type. */
46 static const AdminUpdateFrequency _admin_update_type_frequencies[] = {
47 ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_DAILY | ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, ///< ADMIN_UPDATE_DATE
48 ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_CLIENT_INFO
49 ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_COMPANY_INFO
50 ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, ///< ADMIN_UPDATE_COMPANY_ECONOMY
51 ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, ///< ADMIN_UPDATE_COMPANY_STATS
52 ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_CHAT
53 ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_CONSOLE
54 ADMIN_FREQUENCY_POLL, ///< ADMIN_UPDATE_CMD_NAMES
55 ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_CMD_LOGGING
56 ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_GAMESCRIPT
58 /** Sanity check. */
59 static_assert(lengthof(_admin_update_type_frequencies) == ADMIN_UPDATE_END);
61 /**
62 * Create a new socket for the server side of the admin network.
63 * @param s The socket to connect with.
65 ServerNetworkAdminSocketHandler::ServerNetworkAdminSocketHandler(SOCKET s) : NetworkAdminSocketHandler(s)
67 this->status = ADMIN_STATUS_INACTIVE;
68 this->connect_time = std::chrono::steady_clock::now();
71 /**
72 * Clear everything related to this admin.
74 ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler()
76 Debug(net, 3, "[admin] '{}' ({}) has disconnected", this->admin_name, this->admin_version);
77 if (_redirect_console_to_admin == this->index) _redirect_console_to_admin = INVALID_ADMIN_ID;
79 if (this->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) {
80 this->update_frequency[ADMIN_UPDATE_CONSOLE] = (AdminUpdateFrequency)0;
81 DebugReconsiderSendRemoteMessages();
85 /**
86 * Whether a connection is allowed or not at this moment.
87 * @return Whether the connection is allowed.
89 /* static */ bool ServerNetworkAdminSocketHandler::AllowConnection()
91 return _settings_client.network.AdminAuthenticationConfigured() && ServerNetworkAdminSocketHandler::CanAllocateItem();
94 /** Send the packets for the server sockets. */
95 /* static */ void ServerNetworkAdminSocketHandler::Send()
97 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::Iterate()) {
98 if (as->status <= ADMIN_STATUS_AUTHENTICATE && std::chrono::steady_clock::now() > as->connect_time + ADMIN_AUTHORISATION_TIMEOUT) {
99 Debug(net, 2, "[admin] Admin did not send its authorisation within {} seconds", std::chrono::duration_cast<std::chrono::seconds>(ADMIN_AUTHORISATION_TIMEOUT).count());
100 as->CloseConnection(true);
101 continue;
103 if (as->writable) {
104 as->SendPackets();
110 * Handle the acception of a connection.
111 * @param s The socket of the new connection.
112 * @param address The address of the peer.
114 /* static */ void ServerNetworkAdminSocketHandler::AcceptConnection(SOCKET s, const NetworkAddress &address)
116 ServerNetworkAdminSocketHandler *as = new ServerNetworkAdminSocketHandler(s);
117 as->address = address; // Save the IP of the client
120 /***********
121 * Sending functions for admin network
122 ************/
125 * Send an error to the admin.
126 * @param error The error to send.
128 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode error)
130 /* Whatever the error might be, authentication (keys) must be released as soon as possible. */
131 this->authentication_handler = nullptr;
133 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_ERROR);
135 p->Send_uint8(error);
136 this->SendPacket(std::move(p));
138 std::string error_message = GetString(GetNetworkErrorMsg(error));
140 Debug(net, 1, "[admin] The admin '{}' ({}) made an error and has been disconnected: '{}'", this->admin_name, this->admin_version, error_message);
142 return this->CloseConnection(true);
145 /** Send the protocol version to the admin. */
146 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendProtocol()
148 this->status = ADMIN_STATUS_ACTIVE;
150 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_PROTOCOL);
152 /* announce the protocol version */
153 p->Send_uint8(NETWORK_GAME_ADMIN_VERSION);
155 for (int i = 0; i < ADMIN_UPDATE_END; i++) {
156 p->Send_bool (true);
157 p->Send_uint16(i);
158 p->Send_uint16(_admin_update_type_frequencies[i]);
161 p->Send_bool(false);
162 this->SendPacket(std::move(p));
164 return this->SendWelcome();
167 /** Send a welcome message to the admin. */
168 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendWelcome()
170 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_WELCOME);
172 p->Send_string(_settings_client.network.server_name);
173 p->Send_string(GetNetworkRevisionString());
174 p->Send_bool (_network_dedicated);
176 p->Send_string(""); // Used to be map-name.
177 p->Send_uint32(_settings_game.game_creation.generation_seed);
178 p->Send_uint8 (to_underlying(_settings_game.game_creation.landscape));
179 p->Send_uint32(TimerGameCalendar::ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1).base());
180 p->Send_uint16(Map::SizeX());
181 p->Send_uint16(Map::SizeY());
183 this->SendPacket(std::move(p));
185 return NETWORK_RECV_STATUS_OKAY;
188 /** Tell the admin we started a new game. */
189 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendNewGame()
191 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_NEWGAME);
192 this->SendPacket(std::move(p));
193 return NETWORK_RECV_STATUS_OKAY;
196 /** Tell the admin we're shutting down. */
197 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendShutdown()
199 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_SHUTDOWN);
200 this->SendPacket(std::move(p));
201 return NETWORK_RECV_STATUS_OKAY;
204 /** Tell the admin the date. */
205 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendDate()
207 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_DATE);
209 p->Send_uint32(TimerGameCalendar::date.base());
210 this->SendPacket(std::move(p));
212 return NETWORK_RECV_STATUS_OKAY;
216 * Tell the admin that a client joined.
217 * @param client_id The client that joined.
219 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientJoin(ClientID client_id)
221 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_CLIENT_JOIN);
223 p->Send_uint32(client_id);
224 this->SendPacket(std::move(p));
226 return NETWORK_RECV_STATUS_OKAY;
230 * Send an initial set of data from some client's information.
231 * @param cs The socket of the client.
232 * @param ci The information about the client.
234 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientInfo(const NetworkClientSocket *cs, const NetworkClientInfo *ci)
236 /* Only send data when we're a proper client, not just someone trying to query the server. */
237 if (ci == nullptr) return NETWORK_RECV_STATUS_OKAY;
239 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_CLIENT_INFO);
241 p->Send_uint32(ci->client_id);
242 p->Send_string(cs == nullptr ? "" : const_cast<NetworkAddress &>(cs->client_address).GetHostname());
243 p->Send_string(ci->client_name);
244 p->Send_uint8 (0); // Used to be language
245 p->Send_uint32(ci->join_date.base());
246 p->Send_uint8 (ci->client_playas);
248 this->SendPacket(std::move(p));
250 return NETWORK_RECV_STATUS_OKAY;
255 * Send an update for some client's information.
256 * @param ci The information about a client.
258 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientUpdate(const NetworkClientInfo *ci)
260 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_CLIENT_UPDATE);
262 p->Send_uint32(ci->client_id);
263 p->Send_string(ci->client_name);
264 p->Send_uint8 (ci->client_playas);
266 this->SendPacket(std::move(p));
268 return NETWORK_RECV_STATUS_OKAY;
272 * Tell the admin that a client quit.
273 * @param client_id The client that quit.
275 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientQuit(ClientID client_id)
277 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_CLIENT_QUIT);
279 p->Send_uint32(client_id);
280 this->SendPacket(std::move(p));
282 return NETWORK_RECV_STATUS_OKAY;
286 * Tell the admin that a client made an error.
287 * @param client_id The client that made the error.
288 * @param error The error that was made.
290 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientError(ClientID client_id, NetworkErrorCode error)
292 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_CLIENT_ERROR);
294 p->Send_uint32(client_id);
295 p->Send_uint8 (error);
296 this->SendPacket(std::move(p));
298 return NETWORK_RECV_STATUS_OKAY;
302 * Tell the admin that a new company was founded.
303 * @param company_id The company that was founded.
305 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyNew(CompanyID company_id)
307 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_COMPANY_NEW);
308 p->Send_uint8(company_id);
310 this->SendPacket(std::move(p));
312 return NETWORK_RECV_STATUS_OKAY;
316 * Send the admin some information about a company.
317 * @param c The company to send the information about.
319 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company *c)
321 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_COMPANY_INFO);
323 p->Send_uint8 (c->index);
324 SetDParam(0, c->index);
325 p->Send_string(GetString(STR_COMPANY_NAME));
326 SetDParam(0, c->index);
327 p->Send_string(GetString(STR_PRESIDENT_NAME));
328 p->Send_uint8 (c->colour);
329 p->Send_bool (true);
330 p->Send_uint32(c->inaugurated_year.base());
331 p->Send_bool (c->is_ai);
332 p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy
334 this->SendPacket(std::move(p));
336 return NETWORK_RECV_STATUS_OKAY;
341 * Send an update about a company.
342 * @param c The company to send the update of.
344 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyUpdate(const Company *c)
346 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_COMPANY_UPDATE);
348 p->Send_uint8 (c->index);
349 SetDParam(0, c->index);
350 p->Send_string(GetString(STR_COMPANY_NAME));
351 SetDParam(0, c->index);
352 p->Send_string(GetString(STR_PRESIDENT_NAME));
353 p->Send_uint8 (c->colour);
354 p->Send_bool (true);
355 p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy
357 this->SendPacket(std::move(p));
359 return NETWORK_RECV_STATUS_OKAY;
363 * Tell the admin that a company got removed.
364 * @param company_id The company that got removed.
365 * @param acrr The reason for removal, e.g. bankruptcy or merger.
367 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason acrr)
369 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_COMPANY_REMOVE);
371 p->Send_uint8(company_id);
372 p->Send_uint8(acrr);
374 this->SendPacket(std::move(p));
376 return NETWORK_RECV_STATUS_OKAY;
379 /** Send economic information of all companies. */
380 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyEconomy()
382 for (const Company *company : Company::Iterate()) {
383 /* Get the income. */
384 Money income = -std::reduce(std::begin(company->yearly_expenses[0]), std::end(company->yearly_expenses[0]));
386 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_COMPANY_ECONOMY);
388 p->Send_uint8(company->index);
390 /* Current information. */
391 p->Send_uint64(company->money);
392 p->Send_uint64(company->current_loan);
393 p->Send_uint64(income);
394 p->Send_uint16(static_cast<uint16_t>(std::min<uint64_t>(UINT16_MAX, company->cur_economy.delivered_cargo.GetSum<OverflowSafeInt64>())));
396 /* Send stats for the last 2 quarters. */
397 for (uint i = 0; i < 2; i++) {
398 p->Send_uint64(company->old_economy[i].company_value);
399 p->Send_uint16(company->old_economy[i].performance_history);
400 p->Send_uint16(static_cast<uint16_t>(std::min<uint64_t>(UINT16_MAX, company->old_economy[i].delivered_cargo.GetSum<OverflowSafeInt64>())));
403 this->SendPacket(std::move(p));
407 return NETWORK_RECV_STATUS_OKAY;
410 /** Send statistics about the companies. */
411 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyStats()
413 /* Fetch the latest version of the stats. */
414 NetworkCompanyStats company_stats[MAX_COMPANIES];
415 NetworkPopulateCompanyStats(company_stats);
417 /* Go through all the companies. */
418 for (const Company *company : Company::Iterate()) {
419 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_COMPANY_STATS);
421 /* Send the information. */
422 p->Send_uint8(company->index);
424 for (uint i = 0; i < NETWORK_VEH_END; i++) {
425 p->Send_uint16(company_stats[company->index].num_vehicle[i]);
428 for (uint i = 0; i < NETWORK_VEH_END; i++) {
429 p->Send_uint16(company_stats[company->index].num_station[i]);
432 this->SendPacket(std::move(p));
435 return NETWORK_RECV_STATUS_OKAY;
439 * Send a chat message.
440 * @param action The action associated with the message.
441 * @param desttype The destination type.
442 * @param client_id The origin of the chat message.
443 * @param msg The actual message.
444 * @param data Arbitrary extra data.
446 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendChat(NetworkAction action, DestType desttype, ClientID client_id, const std::string &msg, int64_t data)
448 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_CHAT);
450 p->Send_uint8 (action);
451 p->Send_uint8 (desttype);
452 p->Send_uint32(client_id);
453 p->Send_string(msg);
454 p->Send_uint64(data);
456 this->SendPacket(std::move(p));
457 return NETWORK_RECV_STATUS_OKAY;
461 * Send a notification indicating the rcon command has completed.
462 * @param command The original command sent.
464 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRconEnd(const std::string_view command)
466 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_RCON_END);
468 p->Send_string(command);
469 this->SendPacket(std::move(p));
471 return NETWORK_RECV_STATUS_OKAY;
475 * Send the reply of an rcon command.
476 * @param colour The colour of the text.
477 * @param result The result of the command.
479 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRcon(uint16_t colour, const std::string_view result)
481 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_RCON);
483 p->Send_uint16(colour);
484 p->Send_string(result);
485 this->SendPacket(std::move(p));
487 return NETWORK_RECV_STATUS_OKAY;
490 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet &p)
492 if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
494 std::string command = p.Recv_string(NETWORK_RCONCOMMAND_LENGTH);
496 Debug(net, 3, "[admin] Rcon command from '{}' ({}): {}", this->admin_name, this->admin_version, command);
498 _redirect_console_to_admin = this->index;
499 IConsoleCmdExec(command);
500 _redirect_console_to_admin = INVALID_ADMIN_ID;
501 return this->SendRconEnd(command);
504 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet &p)
506 if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
508 std::string json = p.Recv_string(NETWORK_GAMESCRIPT_JSON_LENGTH);
510 Debug(net, 6, "[admin] GameScript JSON from '{}' ({}): {}", this->admin_name, this->admin_version, json);
512 Game::NewEvent(new ScriptEventAdminPort(json));
513 return NETWORK_RECV_STATUS_OKAY;
516 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_PING(Packet &p)
518 if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
520 uint32_t d1 = p.Recv_uint32();
522 Debug(net, 6, "[admin] Ping from '{}' ({}): {}", this->admin_name, this->admin_version, d1);
524 return this->SendPong(d1);
528 * Send console output of other clients.
529 * @param origin The origin of the string.
530 * @param string The string that's put on the console.
532 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const std::string_view origin, const std::string_view string)
534 /* If the length of both strings, plus the 2 '\0' terminations and 3 bytes of the packet
535 * are bigger than the MTU, just ignore the message. Better safe than sorry. It should
536 * never occur though as the longest strings are chat messages, which are still 30%
537 * smaller than COMPAT_MTU. */
538 if (origin.size() + string.size() + 2 + 3 >= COMPAT_MTU) return NETWORK_RECV_STATUS_OKAY;
540 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_CONSOLE);
542 p->Send_string(origin);
543 p->Send_string(string);
544 this->SendPacket(std::move(p));
546 return NETWORK_RECV_STATUS_OKAY;
550 * Send GameScript JSON output.
551 * @param json The JSON string.
553 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendGameScript(const std::string_view json)
555 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_GAMESCRIPT);
557 p->Send_string(json);
558 this->SendPacket(std::move(p));
560 return NETWORK_RECV_STATUS_OKAY;
563 /** Send ping-reply (pong) to admin **/
564 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendPong(uint32_t d1)
566 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_PONG);
568 p->Send_uint32(d1);
569 this->SendPacket(std::move(p));
571 return NETWORK_RECV_STATUS_OKAY;
574 /** Send the names of the commands. */
575 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdNames()
577 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_CMD_NAMES);
579 for (uint16_t i = 0; i < CMD_END; i++) {
580 const char *cmdname = GetCommandName(static_cast<Commands>(i));
582 /* Should COMPAT_MTU be exceeded, start a new packet
583 * (magic 5: 1 bool "more data" and one uint16_t "command id", one
584 * byte for string '\0' termination and 1 bool "no more data" */
585 if (!p->CanWriteToPacket(strlen(cmdname) + 5)) {
586 p->Send_bool(false);
587 this->SendPacket(std::move(p));
589 p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_CMD_NAMES);
592 p->Send_bool(true);
593 p->Send_uint16(i);
594 p->Send_string(cmdname);
597 /* Marker to notify the end of the packet has been reached. */
598 p->Send_bool(false);
599 this->SendPacket(std::move(p));
601 return NETWORK_RECV_STATUS_OKAY;
605 * Send a command for logging purposes.
606 * @param client_id The client executing the command.
607 * @param cp The command that would be executed.
609 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdLogging(ClientID client_id, const CommandPacket &cp)
611 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_CMD_LOGGING);
613 p->Send_uint32(client_id);
614 p->Send_uint8 (cp.company);
615 p->Send_uint16(cp.cmd);
616 p->Send_buffer(cp.data);
617 p->Send_uint32(cp.frame);
619 this->SendPacket(std::move(p));
621 return NETWORK_RECV_STATUS_OKAY;
624 /***********
625 * Receiving functions
626 ************/
628 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet &p)
630 if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
632 if (!_settings_client.network.allow_insecure_admin_login) {
633 /* You're not authorized to login using this method. */
634 return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
637 std::string password = p.Recv_string(NETWORK_PASSWORD_LENGTH);
639 if (_settings_client.network.admin_password.empty() ||
640 _settings_client.network.admin_password.compare(password) != 0) {
641 /* Password is invalid */
642 return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
645 this->admin_name = p.Recv_string(NETWORK_CLIENT_NAME_LENGTH);
646 this->admin_version = p.Recv_string(NETWORK_REVISION_LENGTH);
648 if (this->admin_name.empty() || this->admin_version.empty()) {
649 /* no name or version supplied */
650 return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
653 Debug(net, 3, "[admin] '{}' ({}) has connected", this->admin_name, this->admin_version);
655 return this->SendProtocol();
658 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_QUIT(Packet &)
660 /* The admin is leaving nothing else to do */
661 return this->CloseConnection();
664 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENCY(Packet &p)
666 if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
668 AdminUpdateType type = (AdminUpdateType)p.Recv_uint16();
669 AdminUpdateFrequency freq = (AdminUpdateFrequency)p.Recv_uint16();
671 if (type >= ADMIN_UPDATE_END || (_admin_update_type_frequencies[type] & freq) != freq) {
672 /* The server does not know of this UpdateType. */
673 Debug(net, 1, "[admin] Not supported update frequency {} ({}) from '{}' ({})", type, freq, this->admin_name, this->admin_version);
674 return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
677 this->update_frequency[type] = freq;
679 if (type == ADMIN_UPDATE_CONSOLE) DebugReconsiderSendRemoteMessages();
681 return NETWORK_RECV_STATUS_OKAY;
684 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet &p)
686 if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
688 AdminUpdateType type = (AdminUpdateType)p.Recv_uint8();
689 uint32_t d1 = p.Recv_uint32();
691 switch (type) {
692 case ADMIN_UPDATE_DATE:
693 /* The admin is requesting the current date. */
694 this->SendDate();
695 break;
697 case ADMIN_UPDATE_CLIENT_INFO:
698 /* The admin is requesting client info. */
699 if (d1 == UINT32_MAX) {
700 this->SendClientInfo(nullptr, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
701 for (const NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
702 this->SendClientInfo(cs, cs->GetInfo());
704 } else {
705 if (d1 == CLIENT_ID_SERVER) {
706 this->SendClientInfo(nullptr, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
707 } else {
708 const NetworkClientSocket *cs = NetworkClientSocket::GetByClientID((ClientID)d1);
709 if (cs != nullptr) this->SendClientInfo(cs, cs->GetInfo());
712 break;
714 case ADMIN_UPDATE_COMPANY_INFO:
715 /* The admin is asking for company info. */
716 if (d1 == UINT32_MAX) {
717 for (const Company *company : Company::Iterate()) {
718 this->SendCompanyInfo(company);
720 } else {
721 const Company *company = Company::GetIfValid(d1);
722 if (company != nullptr) this->SendCompanyInfo(company);
724 break;
726 case ADMIN_UPDATE_COMPANY_ECONOMY:
727 /* The admin is requesting economy info. */
728 this->SendCompanyEconomy();
729 break;
731 case ADMIN_UPDATE_COMPANY_STATS:
732 /* the admin is requesting company stats. */
733 this->SendCompanyStats();
734 break;
736 case ADMIN_UPDATE_CMD_NAMES:
737 /* The admin is requesting the names of DoCommands. */
738 this->SendCmdNames();
739 break;
741 default:
742 /* An unsupported "poll" update type. */
743 Debug(net, 1, "[admin] Not supported poll {} ({}) from '{}' ({}).", type, d1, this->admin_name, this->admin_version);
744 return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
747 return NETWORK_RECV_STATUS_OKAY;
750 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet &p)
752 if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
754 NetworkAction action = (NetworkAction)p.Recv_uint8();
755 DestType desttype = (DestType)p.Recv_uint8();
756 int dest = p.Recv_uint32();
758 std::string msg = p.Recv_string(NETWORK_CHAT_LENGTH);
760 switch (action) {
761 case NETWORK_ACTION_CHAT:
762 case NETWORK_ACTION_CHAT_CLIENT:
763 case NETWORK_ACTION_CHAT_COMPANY:
764 case NETWORK_ACTION_SERVER_MESSAGE:
765 NetworkServerSendChat(action, desttype, dest, msg, _network_own_client_id, 0, true);
766 break;
768 default:
769 Debug(net, 1, "[admin] Invalid chat action {} from admin '{}' ({}).", action, this->admin_name, this->admin_version);
770 return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
773 return NETWORK_RECV_STATUS_OKAY;
776 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_EXTERNAL_CHAT(Packet &p)
778 if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
780 std::string source = p.Recv_string(NETWORK_CHAT_LENGTH);
781 TextColour colour = (TextColour)p.Recv_uint16();
782 std::string user = p.Recv_string(NETWORK_CHAT_LENGTH);
783 std::string msg = p.Recv_string(NETWORK_CHAT_LENGTH);
785 if (!IsValidConsoleColour(colour)) {
786 Debug(net, 1, "[admin] Not supported chat colour {} ({}, {}, {}) from '{}' ({}).", (uint16_t)colour, source, user, msg, this->admin_name, this->admin_version);
787 return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
790 NetworkServerSendExternalChat(source, colour, user, msg);
792 return NETWORK_RECV_STATUS_OKAY;
796 * Secure authentication send and receive methods.
799 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN_SECURE(Packet &p)
801 if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
803 this->admin_name = p.Recv_string(NETWORK_CLIENT_NAME_LENGTH);
804 this->admin_version = p.Recv_string(NETWORK_REVISION_LENGTH);
805 NetworkAuthenticationMethodMask method_mask{p.Recv_uint16()};
807 /* Always exclude key exchange only, as that provides no credential checking. */
808 method_mask.Reset(NetworkAuthenticationMethod::X25519_KeyExchangeOnly);
810 if (this->admin_name.empty() || this->admin_version.empty()) {
811 /* No name or version supplied. */
812 return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
815 auto handler = NetworkAuthenticationServerHandler::Create(&_admin_password_provider, &_admin_authorized_key_handler, method_mask);
816 if (!handler->CanBeUsed()) return this->SendError(NETWORK_ERROR_NO_AUTHENTICATION_METHOD_AVAILABLE);
818 this->authentication_handler = std::move(handler);
819 Debug(net, 3, "[admin] '{}' ({}) has connected", this->admin_name, this->admin_version);
821 return this->SendAuthRequest();
824 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendAuthRequest()
826 this->status = ADMIN_STATUS_AUTHENTICATE;
828 Debug(net, 6, "[admin] '{}' ({}) authenticating using {}", this->admin_name, this->admin_version, this->authentication_handler->GetName());
830 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_AUTH_REQUEST);
831 this->authentication_handler->SendRequest(*p);
833 this->SendPacket(std::move(p));
835 return NETWORK_RECV_STATUS_OKAY;
838 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendEnableEncryption()
840 if (this->status != ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
842 auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_ENABLE_ENCRYPTION);
843 this->authentication_handler->SendEnableEncryption(*p);
844 this->SendPacket(std::move(p));
846 return NETWORK_RECV_STATUS_OKAY;
849 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_AUTH_RESPONSE(Packet &p)
851 if (this->status != ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
853 switch (this->authentication_handler->ReceiveResponse(p)) {
854 case NetworkAuthenticationServerHandler::ResponseResult::Authenticated:
855 Debug(net, 3, "[admin] '{}' ({}) authenticated", this->admin_name, this->admin_version);
857 this->SendEnableEncryption();
859 this->receive_encryption_handler = this->authentication_handler->CreateClientToServerEncryptionHandler();
860 this->send_encryption_handler = this->authentication_handler->CreateServerToClientEncryptionHandler();
861 this->authentication_handler = nullptr;
862 return this->SendProtocol();
864 case NetworkAuthenticationServerHandler::ResponseResult::RetryNextMethod:
865 Debug(net, 6, "[admin] '{}' ({}) authentication failed, trying next method", this->admin_name, this->admin_version);
866 return this->SendAuthRequest();
868 case NetworkAuthenticationServerHandler::ResponseResult::NotAuthenticated:
869 default:
870 Debug(net, 3, "[admin] '{}' ({}) authentication failed", this->admin_name, this->admin_version);
871 return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
876 * Useful wrapper functions
880 * Notify the admin network of a new client (if they did opt in for the respective update).
881 * @param cs the client info.
882 * @param new_client if this is a new client, send the respective packet too.
884 void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client)
886 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
887 if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
888 as->SendClientInfo(cs, cs->GetInfo());
889 if (new_client) {
890 as->SendClientJoin(cs->client_id);
897 * Notify the admin network of a client update (if they did opt in for the respective update).
898 * @param ci the client info.
900 void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
902 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
903 if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
904 as->SendClientUpdate(ci);
910 * Notify the admin network that a client quit (if they have opt in for the respective update).
911 * @param client_id of the client that quit.
913 void NetworkAdminClientQuit(ClientID client_id)
915 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
916 if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
917 as->SendClientQuit(client_id);
923 * Notify the admin network of a client error (if they have opt in for the respective update).
924 * @param client_id the client that made the error.
925 * @param error_code the error that was caused.
927 void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code)
929 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
930 if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
931 as->SendClientError(client_id, error_code);
937 * Notify the admin network of a new company.
938 * @param company the company of which details will be sent into the admin network.
940 void NetworkAdminCompanyNew(const Company *company)
942 if (company == nullptr) {
943 Debug(net, 1, "[admin] Empty company given for update");
944 return;
947 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
948 if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
950 as->SendCompanyNew(company->index);
951 as->SendCompanyInfo(company);
956 * Notify the admin network of company updates.
957 * @param company company of which updates are going to be sent into the admin network.
959 void NetworkAdminCompanyUpdate(const Company *company)
961 if (company == nullptr) return;
963 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
964 if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
966 as->SendCompanyUpdate(company);
971 * Notify the admin network of a company to be removed (including the reason why).
972 * @param company_id ID of the company that got removed.
973 * @param bcrr the reason why the company got removed (e.g. bankruptcy).
975 void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bcrr)
977 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
978 as->SendCompanyRemove(company_id, bcrr);
984 * Send chat to the admin network (if they did opt in for the respective update).
986 void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const std::string &msg, int64_t data, bool from_admin)
988 if (from_admin) return;
990 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
991 if (as->update_frequency[ADMIN_UPDATE_CHAT] & ADMIN_FREQUENCY_AUTOMATIC) {
992 as->SendChat(action, desttype, client_id, msg, data);
998 * Pass the rcon reply to the admin.
999 * @param admin_index The admin to give the reply.
1000 * @param colour_code The colour of the string.
1001 * @param string The string to show.
1003 void NetworkServerSendAdminRcon(AdminID admin_index, TextColour colour_code, const std::string_view string)
1005 ServerNetworkAdminSocketHandler::Get(admin_index)->SendRcon(colour_code, string);
1009 * Send console to the admin network (if they did opt in for the respective update).
1010 * @param origin the origin of the message.
1011 * @param string the message as printed on the console.
1013 void NetworkAdminConsole(const std::string_view origin, const std::string_view string)
1015 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
1016 if (as->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) {
1017 as->SendConsole(origin, string);
1023 * Send GameScript JSON to the admin network (if they did opt in for the respective update).
1024 * @param json The JSON data as received from the GameScript.
1026 void NetworkAdminGameScript(const std::string_view json)
1028 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
1029 if (as->update_frequency[ADMIN_UPDATE_GAMESCRIPT] & ADMIN_FREQUENCY_AUTOMATIC) {
1030 as->SendGameScript(json);
1036 * Distribute CommandPacket details over the admin network for logging purposes.
1037 * @param owner The owner of the CommandPacket (who sent us the CommandPacket).
1038 * @param cp The CommandPacket to be distributed.
1040 void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket &cp)
1042 ClientID client_id = owner == nullptr ? _network_own_client_id : owner->client_id;
1044 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
1045 if (as->update_frequency[ADMIN_UPDATE_CMD_LOGGING] & ADMIN_FREQUENCY_AUTOMATIC) {
1046 as->SendCmdLogging(client_id, cp);
1052 * Send a Welcome packet to all connected admins
1054 void ServerNetworkAdminSocketHandler::WelcomeAll()
1056 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
1057 as->SendWelcome();
1062 * Send (push) updates to the admin network as they have registered for these updates.
1063 * @param freq the frequency to be processed.
1065 void NetworkAdminUpdate(AdminUpdateFrequency freq)
1067 for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
1068 for (int i = 0; i < ADMIN_UPDATE_END; i++) {
1069 if (as->update_frequency[i] & freq) {
1070 /* Update the admin for the required details */
1071 switch (i) {
1072 case ADMIN_UPDATE_DATE:
1073 as->SendDate();
1074 break;
1076 case ADMIN_UPDATE_COMPANY_ECONOMY:
1077 as->SendCompanyEconomy();
1078 break;
1080 case ADMIN_UPDATE_COMPANY_STATS:
1081 as->SendCompanyStats();
1082 break;
1084 default: NOT_REACHED();