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  */
7 
8 /** @file network_admin.cpp Server part of the admin network protocol. */
9 
10 #include "../stdafx.h"
11 #include "../strings_func.h"
12 #include "../date_func.h"
13 #include "core/game_info.h"
14 #include "network_admin.h"
15 #include "network_base.h"
16 #include "network_server.h"
17 #include "../command_func.h"
18 #include "../company_base.h"
19 #include "../console_func.h"
20 #include "../core/pool_func.hpp"
21 #include "../map_func.h"
22 #include "../rev.h"
23 #include "../game/game.hpp"
24 
25 #include "../safeguards.h"
26 
27 
28 /* This file handles all the admin network commands. */
29 
30 /** Redirection of the (remote) console to the admin. */
31 AdminIndex _redirect_console_to_admin = INVALID_ADMIN_ID;
32 
33 /** The amount of admins connected. */
34 byte _network_admins_connected = 0;
35 
36 /** The pool with sockets/clients. */
37 NetworkAdminSocketPool _networkadminsocket_pool("NetworkAdminSocket");
38 INSTANTIATE_POOL_METHODS(NetworkAdminSocket)
39 
40 /** The timeout for authorisation of the client. */
41 static const std::chrono::seconds ADMIN_AUTHORISATION_TIMEOUT(10);
42 
43 
44 /** Frequencies, which may be registered for a certain update type. */
45 static const AdminUpdateFrequency _admin_update_type_frequencies[] = {
46 	ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_DAILY | ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, ///< ADMIN_UPDATE_DATE
47 	ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      ///< ADMIN_UPDATE_CLIENT_INFO
48 	ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      ///< ADMIN_UPDATE_COMPANY_INFO
49 	ADMIN_FREQUENCY_POLL |                         ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, ///< ADMIN_UPDATE_COMPANY_ECONOMY
50 	ADMIN_FREQUENCY_POLL |                         ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, ///< ADMIN_UPDATE_COMPANY_STATS
51 	                       ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      ///< ADMIN_UPDATE_CHAT
52 	                       ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      ///< ADMIN_UPDATE_CONSOLE
53 	ADMIN_FREQUENCY_POLL,                                                                                                                                  ///< ADMIN_UPDATE_CMD_NAMES
54 	                       ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      ///< ADMIN_UPDATE_CMD_LOGGING
55 	                       ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      ///< ADMIN_UPDATE_GAMESCRIPT
56 };
57 /** Sanity check. */
58 static_assert(lengthof(_admin_update_type_frequencies) == ADMIN_UPDATE_END);
59 
60 /**
61  * Create a new socket for the server side of the admin network.
62  * @param s The socket to connect with.
63  */
ServerNetworkAdminSocketHandler(SOCKET s)64 ServerNetworkAdminSocketHandler::ServerNetworkAdminSocketHandler(SOCKET s) : NetworkAdminSocketHandler(s)
65 {
66 	_network_admins_connected++;
67 	this->status = ADMIN_STATUS_INACTIVE;
68 	this->connect_time = std::chrono::steady_clock::now();
69 }
70 
71 /**
72  * Clear everything related to this admin.
73  */
~ServerNetworkAdminSocketHandler()74 ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler()
75 {
76 	_network_admins_connected--;
77 	Debug(net, 3, "[admin] '{}' ({}) has disconnected", this->admin_name, this->admin_version);
78 	if (_redirect_console_to_admin == this->index) _redirect_console_to_admin = INVALID_ADMIN_ID;
79 
80 	if (this->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) {
81 		this->update_frequency[ADMIN_UPDATE_CONSOLE] = (AdminUpdateFrequency)0;
82 		DebugReconsiderSendRemoteMessages();
83 	}
84 }
85 
86 /**
87  * Whether a connection is allowed or not at this moment.
88  * @return Whether the connection is allowed.
89  */
AllowConnection()90 /* static */ bool ServerNetworkAdminSocketHandler::AllowConnection()
91 {
92 	bool accept = !_settings_client.network.admin_password.empty() && _network_admins_connected < MAX_ADMINS;
93 	/* We can't go over the MAX_ADMINS limit here. However, if we accept
94 	 * the connection, there has to be space in the pool. */
95 	static_assert(NetworkAdminSocketPool::MAX_SIZE == MAX_ADMINS);
96 	assert(!accept || ServerNetworkAdminSocketHandler::CanAllocateItem());
97 	return accept;
98 }
99 
100 /** Send the packets for the server sockets. */
Send()101 /* static */ void ServerNetworkAdminSocketHandler::Send()
102 {
103 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::Iterate()) {
104 		if (as->status == ADMIN_STATUS_INACTIVE && std::chrono::steady_clock::now() > as->connect_time + ADMIN_AUTHORISATION_TIMEOUT) {
105 			Debug(net, 2, "[admin] Admin did not send its authorisation within {} seconds", std::chrono::duration_cast<std::chrono::seconds>(ADMIN_AUTHORISATION_TIMEOUT).count());
106 			as->CloseConnection(true);
107 			continue;
108 		}
109 		if (as->writable) {
110 			as->SendPackets();
111 		}
112 	}
113 }
114 
115 /**
116  * Handle the acception of a connection.
117  * @param s The socket of the new connection.
118  * @param address The address of the peer.
119  */
AcceptConnection(SOCKET s,const NetworkAddress & address)120 /* static */ void ServerNetworkAdminSocketHandler::AcceptConnection(SOCKET s, const NetworkAddress &address)
121 {
122 	ServerNetworkAdminSocketHandler *as = new ServerNetworkAdminSocketHandler(s);
123 	as->address = address; // Save the IP of the client
124 }
125 
126 /***********
127  * Sending functions for admin network
128  ************/
129 
130 /**
131  * Send an error to the admin.
132  * @param error The error to send.
133  */
SendError(NetworkErrorCode error)134 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode error)
135 {
136 	Packet *p = new Packet(ADMIN_PACKET_SERVER_ERROR);
137 
138 	p->Send_uint8(error);
139 	this->SendPacket(p);
140 
141 	std::string error_message = GetString(GetNetworkErrorMsg(error));
142 
143 	Debug(net, 1, "[admin] The admin '{}' ({}) made an error and has been disconnected: '{}'", this->admin_name, this->admin_version, error_message);
144 
145 	return this->CloseConnection(true);
146 }
147 
148 /** Send the protocol version to the admin. */
SendProtocol()149 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendProtocol()
150 {
151 	Packet *p = new Packet(ADMIN_PACKET_SERVER_PROTOCOL);
152 
153 	/* announce the protocol version */
154 	p->Send_uint8(NETWORK_GAME_ADMIN_VERSION);
155 
156 	for (int i = 0; i < ADMIN_UPDATE_END; i++) {
157 		p->Send_bool  (true);
158 		p->Send_uint16(i);
159 		p->Send_uint16(_admin_update_type_frequencies[i]);
160 	}
161 
162 	p->Send_bool(false);
163 	this->SendPacket(p);
164 
165 	return this->SendWelcome();
166 }
167 
168 /** Send a welcome message to the admin. */
SendWelcome()169 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendWelcome()
170 {
171 	Packet *p = new Packet(ADMIN_PACKET_SERVER_WELCOME);
172 
173 	p->Send_string(_settings_client.network.server_name);
174 	p->Send_string(GetNetworkRevisionString());
175 	p->Send_bool  (_network_dedicated);
176 
177 	p->Send_string(""); // Used to be map-name.
178 	p->Send_uint32(_settings_game.game_creation.generation_seed);
179 	p->Send_uint8 (_settings_game.game_creation.landscape);
180 	p->Send_uint32(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
181 	p->Send_uint16(MapSizeX());
182 	p->Send_uint16(MapSizeY());
183 
184 	this->SendPacket(p);
185 
186 	return NETWORK_RECV_STATUS_OKAY;
187 }
188 
189 /** Tell the admin we started a new game. */
SendNewGame()190 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendNewGame()
191 {
192 	Packet *p = new Packet(ADMIN_PACKET_SERVER_NEWGAME);
193 	this->SendPacket(p);
194 	return NETWORK_RECV_STATUS_OKAY;
195 }
196 
197 /** Tell the admin we're shutting down. */
SendShutdown()198 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendShutdown()
199 {
200 	Packet *p = new Packet(ADMIN_PACKET_SERVER_SHUTDOWN);
201 	this->SendPacket(p);
202 	return NETWORK_RECV_STATUS_OKAY;
203 }
204 
205 /** Tell the admin the date. */
SendDate()206 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendDate()
207 {
208 	Packet *p = new Packet(ADMIN_PACKET_SERVER_DATE);
209 
210 	p->Send_uint32(_date);
211 	this->SendPacket(p);
212 
213 	return NETWORK_RECV_STATUS_OKAY;
214 }
215 
216 /**
217  * Tell the admin that a client joined.
218  * @param client_id The client that joined.
219  */
SendClientJoin(ClientID client_id)220 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientJoin(ClientID client_id)
221 {
222 	Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_JOIN);
223 
224 	p->Send_uint32(client_id);
225 	this->SendPacket(p);
226 
227 	return NETWORK_RECV_STATUS_OKAY;
228 }
229 
230 /**
231  * Send an initial set of data from some client's information.
232  * @param cs The socket of the client.
233  * @param ci The information about the client.
234  */
SendClientInfo(const NetworkClientSocket * cs,const NetworkClientInfo * ci)235 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientInfo(const NetworkClientSocket *cs, const NetworkClientInfo *ci)
236 {
237 	/* Only send data when we're a proper client, not just someone trying to query the server. */
238 	if (ci == nullptr) return NETWORK_RECV_STATUS_OKAY;
239 
240 	Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_INFO);
241 
242 	p->Send_uint32(ci->client_id);
243 	p->Send_string(cs == nullptr ? "" : const_cast<NetworkAddress &>(cs->client_address).GetHostname());
244 	p->Send_string(ci->client_name);
245 	p->Send_uint8 (0); // Used to be language
246 	p->Send_uint32(ci->join_date);
247 	p->Send_uint8 (ci->client_playas);
248 
249 	this->SendPacket(p);
250 
251 	return NETWORK_RECV_STATUS_OKAY;
252 }
253 
254 
255 /**
256  * Send an update for some client's information.
257  * @param ci The information about a client.
258  */
SendClientUpdate(const NetworkClientInfo * ci)259 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientUpdate(const NetworkClientInfo *ci)
260 {
261 	Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_UPDATE);
262 
263 	p->Send_uint32(ci->client_id);
264 	p->Send_string(ci->client_name);
265 	p->Send_uint8 (ci->client_playas);
266 
267 	this->SendPacket(p);
268 
269 	return NETWORK_RECV_STATUS_OKAY;
270 }
271 
272 /**
273  * Tell the admin that a client quit.
274  * @param client_id The client that quit.
275  */
SendClientQuit(ClientID client_id)276 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientQuit(ClientID client_id)
277 {
278 	Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_QUIT);
279 
280 	p->Send_uint32(client_id);
281 	this->SendPacket(p);
282 
283 	return NETWORK_RECV_STATUS_OKAY;
284 }
285 
286 /**
287  * Tell the admin that a client made an error.
288  * @param client_id The client that made the error.
289  * @param error The error that was made.
290  */
SendClientError(ClientID client_id,NetworkErrorCode error)291 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientError(ClientID client_id, NetworkErrorCode error)
292 {
293 	Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_ERROR);
294 
295 	p->Send_uint32(client_id);
296 	p->Send_uint8 (error);
297 	this->SendPacket(p);
298 
299 	return NETWORK_RECV_STATUS_OKAY;
300 }
301 
302 /**
303  * Tell the admin that a new company was founded.
304  * @param company_id The company that was founded.
305  */
SendCompanyNew(CompanyID company_id)306 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyNew(CompanyID company_id)
307 {
308 	Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_NEW);
309 	p->Send_uint8(company_id);
310 
311 	this->SendPacket(p);
312 
313 	return NETWORK_RECV_STATUS_OKAY;
314 }
315 
316 /**
317  * Send the admin some information about a company.
318  * @param c The company to send the information about.
319  */
SendCompanyInfo(const Company * c)320 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company *c)
321 {
322 	Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_INFO);
323 
324 	p->Send_uint8 (c->index);
325 	SetDParam(0, c->index);
326 	p->Send_string(GetString(STR_COMPANY_NAME));
327 	SetDParam(0, c->index);
328 	p->Send_string(GetString(STR_PRESIDENT_NAME));
329 	p->Send_uint8 (c->colour);
330 	p->Send_bool  (NetworkCompanyIsPassworded(c->index));
331 	p->Send_uint32(c->inaugurated_year);
332 	p->Send_bool  (c->is_ai);
333 	p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy
334 
335 	for (size_t i = 0; i < lengthof(c->share_owners); i++) {
336 		p->Send_uint8(c->share_owners[i]);
337 	}
338 
339 	this->SendPacket(p);
340 
341 	return NETWORK_RECV_STATUS_OKAY;
342 }
343 
344 
345 /**
346  * Send an update about a company.
347  * @param c The company to send the update of.
348  */
SendCompanyUpdate(const Company * c)349 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyUpdate(const Company *c)
350 {
351 	Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_UPDATE);
352 
353 	p->Send_uint8 (c->index);
354 	SetDParam(0, c->index);
355 	p->Send_string(GetString(STR_COMPANY_NAME));
356 	SetDParam(0, c->index);
357 	p->Send_string(GetString(STR_PRESIDENT_NAME));
358 	p->Send_uint8 (c->colour);
359 	p->Send_bool  (NetworkCompanyIsPassworded(c->index));
360 	p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy
361 
362 	for (size_t i = 0; i < lengthof(c->share_owners); i++) {
363 		p->Send_uint8(c->share_owners[i]);
364 	}
365 
366 	this->SendPacket(p);
367 
368 	return NETWORK_RECV_STATUS_OKAY;
369 }
370 
371 /**
372  * Tell the admin that a company got removed.
373  * @param company_id The company that got removed.
374  * @param acrr The reason for removal, e.g. bankruptcy or merger.
375  */
SendCompanyRemove(CompanyID company_id,AdminCompanyRemoveReason acrr)376 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason acrr)
377 {
378 	Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_REMOVE);
379 
380 	p->Send_uint8(company_id);
381 	p->Send_uint8(acrr);
382 
383 	this->SendPacket(p);
384 
385 	return NETWORK_RECV_STATUS_OKAY;
386 }
387 
388 /** Send economic information of all companies. */
SendCompanyEconomy()389 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyEconomy()
390 {
391 	for (const Company *company : Company::Iterate()) {
392 		/* Get the income. */
393 		Money income = 0;
394 		for (uint i = 0; i < lengthof(company->yearly_expenses[0]); i++) {
395 			income -= company->yearly_expenses[0][i];
396 		}
397 
398 		Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_ECONOMY);
399 
400 		p->Send_uint8(company->index);
401 
402 		/* Current information. */
403 		p->Send_uint64(company->money);
404 		p->Send_uint64(company->current_loan);
405 		p->Send_uint64(income);
406 		p->Send_uint16(static_cast<uint16>(std::min<uint64>(UINT16_MAX, company->cur_economy.delivered_cargo.GetSum<OverflowSafeInt64>())));
407 
408 		/* Send stats for the last 2 quarters. */
409 		for (uint i = 0; i < 2; i++) {
410 			p->Send_uint64(company->old_economy[i].company_value);
411 			p->Send_uint16(company->old_economy[i].performance_history);
412 			p->Send_uint16(static_cast<uint16>(std::min<uint64>(UINT16_MAX, company->old_economy[i].delivered_cargo.GetSum<OverflowSafeInt64>())));
413 		}
414 
415 		this->SendPacket(p);
416 	}
417 
418 
419 	return NETWORK_RECV_STATUS_OKAY;
420 }
421 
422 /** Send statistics about the companies. */
SendCompanyStats()423 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyStats()
424 {
425 	/* Fetch the latest version of the stats. */
426 	NetworkCompanyStats company_stats[MAX_COMPANIES];
427 	NetworkPopulateCompanyStats(company_stats);
428 
429 	/* Go through all the companies. */
430 	for (const Company *company : Company::Iterate()) {
431 		Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_STATS);
432 
433 		/* Send the information. */
434 		p->Send_uint8(company->index);
435 
436 		for (uint i = 0; i < NETWORK_VEH_END; i++) {
437 			p->Send_uint16(company_stats[company->index].num_vehicle[i]);
438 		}
439 
440 		for (uint i = 0; i < NETWORK_VEH_END; i++) {
441 			p->Send_uint16(company_stats[company->index].num_station[i]);
442 		}
443 
444 		this->SendPacket(p);
445 	}
446 
447 	return NETWORK_RECV_STATUS_OKAY;
448 }
449 
450 /**
451  * Send a chat message.
452  * @param action The action associated with the message.
453  * @param desttype The destination type.
454  * @param client_id The origin of the chat message.
455  * @param msg The actual message.
456  * @param data Arbitrary extra data.
457  */
SendChat(NetworkAction action,DestType desttype,ClientID client_id,const std::string & msg,int64 data)458 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendChat(NetworkAction action, DestType desttype, ClientID client_id, const std::string &msg, int64 data)
459 {
460 	Packet *p = new Packet(ADMIN_PACKET_SERVER_CHAT);
461 
462 	p->Send_uint8 (action);
463 	p->Send_uint8 (desttype);
464 	p->Send_uint32(client_id);
465 	p->Send_string(msg);
466 	p->Send_uint64(data);
467 
468 	this->SendPacket(p);
469 	return NETWORK_RECV_STATUS_OKAY;
470 }
471 
472 /**
473  * Send a notification indicating the rcon command has completed.
474  * @param command The original command sent.
475  */
SendRconEnd(const std::string_view command)476 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRconEnd(const std::string_view command)
477 {
478 	Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON_END);
479 
480 	p->Send_string(command);
481 	this->SendPacket(p);
482 
483 	return NETWORK_RECV_STATUS_OKAY;
484 }
485 
486 /**
487  * Send the reply of an rcon command.
488  * @param colour The colour of the text.
489  * @param result The result of the command.
490  */
SendRcon(uint16 colour,const std::string_view result)491 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRcon(uint16 colour, const std::string_view result)
492 {
493 	Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON);
494 
495 	p->Send_uint16(colour);
496 	p->Send_string(result);
497 	this->SendPacket(p);
498 
499 	return NETWORK_RECV_STATUS_OKAY;
500 }
501 
Receive_ADMIN_RCON(Packet * p)502 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet *p)
503 {
504 	if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
505 
506 	std::string command = p->Recv_string(NETWORK_RCONCOMMAND_LENGTH);
507 
508 	Debug(net, 3, "[admin] Rcon command from '{}' ({}): {}", this->admin_name, this->admin_version, command);
509 
510 	_redirect_console_to_admin = this->index;
511 	IConsoleCmdExec(command.c_str());
512 	_redirect_console_to_admin = INVALID_ADMIN_ID;
513 	return this->SendRconEnd(command);
514 }
515 
Receive_ADMIN_GAMESCRIPT(Packet * p)516 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet *p)
517 {
518 	if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
519 
520 	std::string json = p->Recv_string(NETWORK_GAMESCRIPT_JSON_LENGTH);
521 
522 	Debug(net, 6, "[admin] GameScript JSON from '{}' ({}): {}", this->admin_name, this->admin_version, json);
523 
524 	Game::NewEvent(new ScriptEventAdminPort(json));
525 	return NETWORK_RECV_STATUS_OKAY;
526 }
527 
Receive_ADMIN_PING(Packet * p)528 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_PING(Packet *p)
529 {
530 	if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
531 
532 	uint32 d1 = p->Recv_uint32();
533 
534 	Debug(net, 6, "[admin] Ping from '{}' ({}): {}", this->admin_name, this->admin_version, d1);
535 
536 	return this->SendPong(d1);
537 }
538 
539 /**
540  * Send console output of other clients.
541  * @param origin The origin of the string.
542  * @param string The string that's put on the console.
543  */
SendConsole(const std::string_view origin,const std::string_view string)544 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const std::string_view origin, const std::string_view string)
545 {
546 	/* If the length of both strings, plus the 2 '\0' terminations and 3 bytes of the packet
547 	 * are bigger than the MTU, just ignore the message. Better safe than sorry. It should
548 	 * never occur though as the longest strings are chat messages, which are still 30%
549 	 * smaller than COMPAT_MTU. */
550 	if (origin.size() + string.size() + 2 + 3 >= COMPAT_MTU) return NETWORK_RECV_STATUS_OKAY;
551 
552 	Packet *p = new Packet(ADMIN_PACKET_SERVER_CONSOLE);
553 
554 	p->Send_string(origin);
555 	p->Send_string(string);
556 	this->SendPacket(p);
557 
558 	return NETWORK_RECV_STATUS_OKAY;
559 }
560 
561 /**
562  * Send GameScript JSON output.
563  * @param json The JSON string.
564  */
SendGameScript(const std::string_view json)565 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendGameScript(const std::string_view json)
566 {
567 	/* At the moment we cannot transmit anything larger than MTU. So we limit
568 	 *  the maximum amount of json data that can be sent. Account also for
569 	 *  the trailing \0 of the string */
570 	if (json.size() + 1 >= NETWORK_GAMESCRIPT_JSON_LENGTH) return NETWORK_RECV_STATUS_OKAY;
571 
572 	Packet *p = new Packet(ADMIN_PACKET_SERVER_GAMESCRIPT);
573 
574 	p->Send_string(json);
575 	this->SendPacket(p);
576 
577 	return NETWORK_RECV_STATUS_OKAY;
578 }
579 
580 /** Send ping-reply (pong) to admin **/
SendPong(uint32 d1)581 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendPong(uint32 d1)
582 {
583 	Packet *p = new Packet(ADMIN_PACKET_SERVER_PONG);
584 
585 	p->Send_uint32(d1);
586 	this->SendPacket(p);
587 
588 	return NETWORK_RECV_STATUS_OKAY;
589 }
590 
591 /** Send the names of the commands. */
SendCmdNames()592 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdNames()
593 {
594 	Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
595 
596 	for (uint i = 0; i < CMD_END; i++) {
597 		const char *cmdname = GetCommandName(i);
598 
599 		/* Should COMPAT_MTU be exceeded, start a new packet
600 		 * (magic 5: 1 bool "more data" and one uint16 "command id", one
601 		 * byte for string '\0' termination and 1 bool "no more data" */
602 		if (!p->CanWriteToPacket(strlen(cmdname) + 5)) {
603 			p->Send_bool(false);
604 			this->SendPacket(p);
605 
606 			p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
607 		}
608 
609 		p->Send_bool(true);
610 		p->Send_uint16(i);
611 		p->Send_string(cmdname);
612 	}
613 
614 	/* Marker to notify the end of the packet has been reached. */
615 	p->Send_bool(false);
616 	this->SendPacket(p);
617 
618 	return NETWORK_RECV_STATUS_OKAY;
619 }
620 
621 /**
622  * Send a command for logging purposes.
623  * @param client_id The client executing the command.
624  * @param cp The command that would be executed.
625  */
SendCmdLogging(ClientID client_id,const CommandPacket * cp)626 NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdLogging(ClientID client_id, const CommandPacket *cp)
627 {
628 	Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_LOGGING);
629 
630 	p->Send_uint32(client_id);
631 	p->Send_uint8 (cp->company);
632 	p->Send_uint16(cp->cmd & CMD_ID_MASK);
633 	p->Send_uint32(cp->p1);
634 	p->Send_uint32(cp->p2);
635 	p->Send_uint32(cp->tile);
636 	p->Send_string(cp->text);
637 	p->Send_uint32(cp->frame);
638 
639 	this->SendPacket(p);
640 
641 	return NETWORK_RECV_STATUS_OKAY;
642 }
643 
644 /***********
645  * Receiving functions
646  ************/
647 
Receive_ADMIN_JOIN(Packet * p)648 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet *p)
649 {
650 	if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
651 
652 	std::string password = p->Recv_string(NETWORK_PASSWORD_LENGTH);
653 
654 	if (_settings_client.network.admin_password.empty() ||
655 			_settings_client.network.admin_password.compare(password) != 0) {
656 		/* Password is invalid */
657 		return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
658 	}
659 
660 	this->admin_name = p->Recv_string(NETWORK_CLIENT_NAME_LENGTH);
661 	this->admin_version = p->Recv_string(NETWORK_REVISION_LENGTH);
662 
663 	if (this->admin_name.empty() || this->admin_version.empty()) {
664 		/* no name or version supplied */
665 		return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
666 	}
667 
668 	this->status = ADMIN_STATUS_ACTIVE;
669 
670 	Debug(net, 3, "[admin] '{}' ({}) has connected", this->admin_name, this->admin_version);
671 
672 	return this->SendProtocol();
673 }
674 
Receive_ADMIN_QUIT(Packet * p)675 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_QUIT(Packet *p)
676 {
677 	/* The admin is leaving nothing else to do */
678 	return this->CloseConnection();
679 }
680 
Receive_ADMIN_UPDATE_FREQUENCY(Packet * p)681 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENCY(Packet *p)
682 {
683 	if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
684 
685 	AdminUpdateType type = (AdminUpdateType)p->Recv_uint16();
686 	AdminUpdateFrequency freq = (AdminUpdateFrequency)p->Recv_uint16();
687 
688 	if (type >= ADMIN_UPDATE_END || (_admin_update_type_frequencies[type] & freq) != freq) {
689 		/* The server does not know of this UpdateType. */
690 		Debug(net, 1, "[admin] Not supported update frequency {} ({}) from '{}' ({})", type, freq, this->admin_name, this->admin_version);
691 		return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
692 	}
693 
694 	this->update_frequency[type] = freq;
695 
696 	if (type == ADMIN_UPDATE_CONSOLE) DebugReconsiderSendRemoteMessages();
697 
698 	return NETWORK_RECV_STATUS_OKAY;
699 }
700 
Receive_ADMIN_POLL(Packet * p)701 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet *p)
702 {
703 	if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
704 
705 	AdminUpdateType type = (AdminUpdateType)p->Recv_uint8();
706 	uint32 d1 = p->Recv_uint32();
707 
708 	switch (type) {
709 		case ADMIN_UPDATE_DATE:
710 			/* The admin is requesting the current date. */
711 			this->SendDate();
712 			break;
713 
714 		case ADMIN_UPDATE_CLIENT_INFO:
715 			/* The admin is requesting client info. */
716 			if (d1 == UINT32_MAX) {
717 				this->SendClientInfo(nullptr, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
718 				for (const NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
719 					this->SendClientInfo(cs, cs->GetInfo());
720 				}
721 			} else {
722 				if (d1 == CLIENT_ID_SERVER) {
723 					this->SendClientInfo(nullptr, NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
724 				} else {
725 					const NetworkClientSocket *cs = NetworkClientSocket::GetByClientID((ClientID)d1);
726 					if (cs != nullptr) this->SendClientInfo(cs, cs->GetInfo());
727 				}
728 			}
729 			break;
730 
731 		case ADMIN_UPDATE_COMPANY_INFO:
732 			/* The admin is asking for company info. */
733 			if (d1 == UINT32_MAX) {
734 				for (const Company *company : Company::Iterate()) {
735 					this->SendCompanyInfo(company);
736 				}
737 			} else {
738 				const Company *company = Company::GetIfValid(d1);
739 				if (company != nullptr) this->SendCompanyInfo(company);
740 			}
741 			break;
742 
743 		case ADMIN_UPDATE_COMPANY_ECONOMY:
744 			/* The admin is requesting economy info. */
745 			this->SendCompanyEconomy();
746 			break;
747 
748 		case ADMIN_UPDATE_COMPANY_STATS:
749 			/* the admin is requesting company stats. */
750 			this->SendCompanyStats();
751 			break;
752 
753 		case ADMIN_UPDATE_CMD_NAMES:
754 			/* The admin is requesting the names of DoCommands. */
755 			this->SendCmdNames();
756 			break;
757 
758 		default:
759 			/* An unsupported "poll" update type. */
760 			Debug(net, 1, "[admin] Not supported poll {} ({}) from '{}' ({}).", type, d1, this->admin_name, this->admin_version);
761 			return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
762 	}
763 
764 	return NETWORK_RECV_STATUS_OKAY;
765 }
766 
Receive_ADMIN_CHAT(Packet * p)767 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet *p)
768 {
769 	if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
770 
771 	NetworkAction action = (NetworkAction)p->Recv_uint8();
772 	DestType desttype = (DestType)p->Recv_uint8();
773 	int dest = p->Recv_uint32();
774 
775 	std::string msg = p->Recv_string(NETWORK_CHAT_LENGTH);
776 
777 	switch (action) {
778 		case NETWORK_ACTION_CHAT:
779 		case NETWORK_ACTION_CHAT_CLIENT:
780 		case NETWORK_ACTION_CHAT_COMPANY:
781 		case NETWORK_ACTION_SERVER_MESSAGE:
782 			NetworkServerSendChat(action, desttype, dest, msg, _network_own_client_id, 0, true);
783 			break;
784 
785 		default:
786 			Debug(net, 1, "[admin] Invalid chat action {} from admin '{}' ({}).", action, this->admin_name, this->admin_version);
787 			return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
788 	}
789 
790 	return NETWORK_RECV_STATUS_OKAY;
791 }
792 
Receive_ADMIN_EXTERNAL_CHAT(Packet * p)793 NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_EXTERNAL_CHAT(Packet *p)
794 {
795 	if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
796 
797 	std::string source = p->Recv_string(NETWORK_CHAT_LENGTH);
798 	TextColour colour = (TextColour)p->Recv_uint16();
799 	std::string user = p->Recv_string(NETWORK_CHAT_LENGTH);
800 	std::string msg = p->Recv_string(NETWORK_CHAT_LENGTH);
801 
802 	if (!IsValidConsoleColour(colour)) {
803 		Debug(net, 1, "[admin] Not supported chat colour {} ({}, {}, {}) from '{}' ({}).", (uint16)colour, source, user, msg, this->admin_name, this->admin_version);
804 		return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
805 	}
806 
807 	NetworkServerSendExternalChat(source, colour, user, msg);
808 
809 	return NETWORK_RECV_STATUS_OKAY;
810 }
811 
812 /*
813  * Useful wrapper functions
814  */
815 
816 /**
817  * Notify the admin network of a new client (if they did opt in for the respective update).
818  * @param cs the client info.
819  * @param new_client if this is a new client, send the respective packet too.
820  */
NetworkAdminClientInfo(const NetworkClientSocket * cs,bool new_client)821 void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client)
822 {
823 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
824 		if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
825 			as->SendClientInfo(cs, cs->GetInfo());
826 			if (new_client) {
827 				as->SendClientJoin(cs->client_id);
828 			}
829 		}
830 	}
831 }
832 
833 /**
834  * Notify the admin network of a client update (if they did opt in for the respective update).
835  * @param ci the client info.
836  */
NetworkAdminClientUpdate(const NetworkClientInfo * ci)837 void NetworkAdminClientUpdate(const NetworkClientInfo *ci)
838 {
839 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
840 		if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
841 			as->SendClientUpdate(ci);
842 		}
843 	}
844 }
845 
846 /**
847  * Notify the admin network that a client quit (if they have opt in for the respective update).
848  * @param client_id of the client that quit.
849  */
NetworkAdminClientQuit(ClientID client_id)850 void NetworkAdminClientQuit(ClientID client_id)
851 {
852 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
853 		if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
854 			as->SendClientQuit(client_id);
855 		}
856 	}
857 }
858 
859 /**
860  * Notify the admin network of a client error (if they have opt in for the respective update).
861  * @param client_id the client that made the error.
862  * @param error_code the error that was caused.
863  */
NetworkAdminClientError(ClientID client_id,NetworkErrorCode error_code)864 void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code)
865 {
866 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
867 		if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
868 			as->SendClientError(client_id, error_code);
869 		}
870 	}
871 }
872 
873 /**
874  * Notify the admin network of company details.
875  * @param company the company of which details will be sent into the admin network.
876  * @param new_company whether this is a new company or not.
877  */
NetworkAdminCompanyInfo(const Company * company,bool new_company)878 void NetworkAdminCompanyInfo(const Company *company, bool new_company)
879 {
880 	if (company == nullptr) {
881 		Debug(net, 1, "[admin] Empty company given for update");
882 		return;
883 	}
884 
885 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
886 		if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
887 
888 		as->SendCompanyInfo(company);
889 		if (new_company) {
890 			as->SendCompanyNew(company->index);
891 		}
892 	}
893 }
894 
895 /**
896  * Notify the admin network of company updates.
897  * @param company company of which updates are going to be sent into the admin network.
898  */
NetworkAdminCompanyUpdate(const Company * company)899 void NetworkAdminCompanyUpdate(const Company *company)
900 {
901 	if (company == nullptr) return;
902 
903 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
904 		if (as->update_frequency[ADMIN_UPDATE_COMPANY_INFO] != ADMIN_FREQUENCY_AUTOMATIC) continue;
905 
906 		as->SendCompanyUpdate(company);
907 	}
908 }
909 
910 /**
911  * Notify the admin network of a company to be removed (including the reason why).
912  * @param company_id ID of the company that got removed.
913  * @param bcrr the reason why the company got removed (e.g. bankruptcy).
914  */
NetworkAdminCompanyRemove(CompanyID company_id,AdminCompanyRemoveReason bcrr)915 void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bcrr)
916 {
917 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
918 		as->SendCompanyRemove(company_id, bcrr);
919 	}
920 }
921 
922 
923 /**
924  * Send chat to the admin network (if they did opt in for the respective update).
925  */
NetworkAdminChat(NetworkAction action,DestType desttype,ClientID client_id,const std::string & msg,int64 data,bool from_admin)926 void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const std::string &msg, int64 data, bool from_admin)
927 {
928 	if (from_admin) return;
929 
930 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
931 		if (as->update_frequency[ADMIN_UPDATE_CHAT] & ADMIN_FREQUENCY_AUTOMATIC) {
932 			as->SendChat(action, desttype, client_id, msg, data);
933 		}
934 	}
935 }
936 
937 /**
938  * Pass the rcon reply to the admin.
939  * @param admin_index The admin to give the reply.
940  * @param colour_code The colour of the string.
941  * @param string      The string to show.
942  */
NetworkServerSendAdminRcon(AdminIndex admin_index,TextColour colour_code,const std::string_view string)943 void NetworkServerSendAdminRcon(AdminIndex admin_index, TextColour colour_code, const std::string_view string)
944 {
945 	ServerNetworkAdminSocketHandler::Get(admin_index)->SendRcon(colour_code, string);
946 }
947 
948 /**
949  * Send console to the admin network (if they did opt in for the respective update).
950  * @param origin the origin of the message.
951  * @param string the message as printed on the console.
952  */
NetworkAdminConsole(const std::string_view origin,const std::string_view string)953 void NetworkAdminConsole(const std::string_view origin, const std::string_view string)
954 {
955 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
956 		if (as->update_frequency[ADMIN_UPDATE_CONSOLE] & ADMIN_FREQUENCY_AUTOMATIC) {
957 			as->SendConsole(origin, string);
958 		}
959 	}
960 }
961 
962 /**
963  * Send GameScript JSON to the admin network (if they did opt in for the respective update).
964  * @param json The JSON data as received from the GameScript.
965  */
NetworkAdminGameScript(const std::string_view json)966 void NetworkAdminGameScript(const std::string_view json)
967 {
968 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
969 		if (as->update_frequency[ADMIN_UPDATE_GAMESCRIPT] & ADMIN_FREQUENCY_AUTOMATIC) {
970 			as->SendGameScript(json);
971 		}
972 	}
973 }
974 
975 /**
976  * Distribute CommandPacket details over the admin network for logging purposes.
977  * @param owner The owner of the CommandPacket (who sent us the CommandPacket).
978  * @param cp    The CommandPacket to be distributed.
979  */
NetworkAdminCmdLogging(const NetworkClientSocket * owner,const CommandPacket * cp)980 void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket *cp)
981 {
982 	ClientID client_id = owner == nullptr ? _network_own_client_id : owner->client_id;
983 
984 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
985 		if (as->update_frequency[ADMIN_UPDATE_CMD_LOGGING] & ADMIN_FREQUENCY_AUTOMATIC) {
986 			as->SendCmdLogging(client_id, cp);
987 		}
988 	}
989 }
990 
991 /**
992  * Send a Welcome packet to all connected admins
993  */
WelcomeAll()994 void ServerNetworkAdminSocketHandler::WelcomeAll()
995 {
996 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
997 		as->SendWelcome();
998 	}
999 }
1000 
1001 /**
1002  * Send (push) updates to the admin network as they have registered for these updates.
1003  * @param freq the frequency to be processed.
1004  */
NetworkAdminUpdate(AdminUpdateFrequency freq)1005 void NetworkAdminUpdate(AdminUpdateFrequency freq)
1006 {
1007 	for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::IterateActive()) {
1008 		for (int i = 0; i < ADMIN_UPDATE_END; i++) {
1009 			if (as->update_frequency[i] & freq) {
1010 				/* Update the admin for the required details */
1011 				switch (i) {
1012 					case ADMIN_UPDATE_DATE:
1013 						as->SendDate();
1014 						break;
1015 
1016 					case ADMIN_UPDATE_COMPANY_ECONOMY:
1017 						as->SendCompanyEconomy();
1018 						break;
1019 
1020 					case ADMIN_UPDATE_COMPANY_STATS:
1021 						as->SendCompanyStats();
1022 						break;
1023 
1024 					default: NOT_REACHED();
1025 				}
1026 			}
1027 		}
1028 	}
1029 }
1030