(svn r1527) -Add: RCon (Remote Connection). A server can set:
authortruelight
Sat, 15 Jan 2005 20:09:16 +0000
changeset 1026 5b2681cad645
parent 1025 882be6e4ad19
child 1027 8219023e674d
(svn r1527) -Add: RCon (Remote Connection). A server can set:
'set rcon_pw <password>'
Which enables rcon. A client can now do:
'rcon <password> "<command>"'
The command will be executed on the server. (guru3)
-Fix: 'kick 1' did crash dedicated servers
-Fix: server password is now correctly saved

!!Warning!!: do not give your rcon password to people you do not thrust!
console.c
console_cmds.c
network.c
network.h
network_client.c
network_client.h
network_data.h
network_server.c
network_server.h
settings.c
--- a/console.c	Sat Jan 15 19:17:45 2005 +0000
+++ b/console.c	Sat Jan 15 20:09:16 2005 +0000
@@ -11,6 +11,8 @@
 #include <string.h>
 #include "console.h"
 #include "network.h"
+#include "network_data.h"
+#include "network_server.h"
 
 #ifdef WIN32
 #include <windows.h>
@@ -372,6 +374,12 @@
 	char* i;
 	int j;
 
+	if (_redirect_console_to_client != 0) {
+		/* Redirect the string to the client */
+		SEND_COMMAND(PACKET_SERVER_RCON)(NetworkFindClientStateFromIndex(_redirect_console_to_client), color_code, string);
+		return;
+	}
+
 	if (_network_dedicated) {
 		printf("%s\n", string);
 		return;
--- a/console_cmds.c	Sat Jan 15 19:17:45 2005 +0000
+++ b/console_cmds.c	Sat Jan 15 20:09:16 2005 +0000
@@ -379,6 +379,18 @@
 	return NULL;
 }
 
+DEF_CONSOLE_CMD(ConRcon)
+{
+	if (argc < 3) {
+		IConsolePrint(_iconsole_color_default, "Usage: rcon <password> <command>");
+		return NULL;
+	}
+
+	SEND_COMMAND(PACKET_CLIENT_RCON)(argv[1], argv[2]);
+
+	return NULL;
+}
+
 DEF_CONSOLE_CMD(ConStatus)
 {
 	const char *status;
@@ -425,7 +437,7 @@
 
 	if (argc == 2) {
 		uint32 index = atoi(argv[1]);
-		if (index == NETWORK_SERVER_INDEX && !_network_dedicated) {
+		if (index == NETWORK_SERVER_INDEX) {
 			IConsolePrint(_iconsole_color_default, "Silly boy, you can not kick yourself!");
 			return NULL;
 		}
@@ -900,13 +912,14 @@
 		if (argc == 3) {
 			// Change server password
 			if (strncmp(argv[2], "*", NETWORK_PASSWORD_LENGTH) == 0) {
-				_network_game_info.server_password[0] = '\0';
+				_network_server_password[0] = '\0';
 				_network_game_info.use_password = 0;
 			} else {
-				ttd_strlcpy(_network_game_info.server_password, argv[2], sizeof(_network_game_info.server_password));
+				ttd_strlcpy(_network_server_password, argv[2], sizeof(_network_server_password));
 				_network_game_info.use_password = 1;
 			}
-			IConsolePrintF(_iconsole_color_warning, "Game-password changed to '%s'", _network_game_info.server_password);
+			IConsolePrintF(_iconsole_color_warning, "Game-password changed to '%s'", _network_server_password);
+			ttd_strlcpy(_network_game_info.server_password, _network_server_password, sizeof(_network_game_info.server_password));
 		} else {
 			IConsolePrintF(_iconsole_color_default, "Current game-password is set to '%s'", _network_game_info.server_password);
 			IConsolePrint(_iconsole_color_warning, "Usage: set server_pw \"<password>\".   Use * as <password> to set no password.");
@@ -914,6 +927,28 @@
 		return NULL;
 	}
 
+	// setting the rcon password
+	if ((strcmp(argv[1], "rcon_pw") == 0) || (strcmp(argv[1], "rcon_password") == 0)) {
+		if (!_network_server) {
+			IConsolePrintF(_iconsole_color_error, "You are not the server");
+			return NULL;
+		}
+		if (argc == 3) {
+			// Change server password
+			if (strncmp(argv[2], "*", NETWORK_PASSWORD_LENGTH) == 0) {
+				_network_rcon_password[0] = '\0';
+			} else {
+				ttd_strlcpy(_network_rcon_password, argv[2], sizeof(_network_rcon_password));
+			}
+			IConsolePrintF(_iconsole_color_warning, "Rcon-password changed to '%s'", _network_rcon_password);
+			ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_game_info.rcon_password));
+		} else {
+			IConsolePrintF(_iconsole_color_default, "Current rcon-password is set to '%s'", _network_game_info.rcon_password);
+			IConsolePrint(_iconsole_color_warning, "Usage: set rcon_pw \"<password>\".   Use * as <password> to disable rcon.");
+		}
+		return NULL;
+	}
+
 	// setting the company password
 	if ((strcmp(argv[1],"company_pw") == 0) || (strcmp(argv[1],"company_password") == 0)) {
 		if (!_networking) {
@@ -1123,6 +1158,7 @@
 	IConsolePrint(_iconsole_color_error, " - autoclean_unprotected <months>");
 	IConsolePrint(_iconsole_color_error, " - company_pw \"<password>\"");
 	IConsolePrint(_iconsole_color_error, " - name \"<playername>\"");
+	IConsolePrint(_iconsole_color_error, " - rcon_pw \"<password>\"");
 	IConsolePrint(_iconsole_color_error, " - server_name \"<name>\"");
 	IConsolePrint(_iconsole_color_error, " - server_advertise on/off");
 	IConsolePrint(_iconsole_color_error, " - server_bind_ip <ip>");
@@ -1229,6 +1265,9 @@
 	IConsoleCmdHook("status", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetClient);
 	IConsoleCmdHook("resetengines", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetwork);
 
+	IConsoleCmdRegister("rcon",        ConRcon);
+	IConsoleCmdHook("rcon", ICONSOLE_HOOK_ACCESS, ConCmdHookNeedNetwork);
+
 	IConsoleCmdRegister("ban",   ConBan);
 	IConsoleCmdHook("ban", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetClient);
 	IConsoleCmdRegister("unban",   ConUnBan);
--- a/network.c	Sat Jan 15 19:17:45 2005 +0000
+++ b/network.c	Sat Jan 15 20:09:16 2005 +0000
@@ -927,6 +927,8 @@
 	NetworkClientInfo *ci;
 
 	ttd_strlcpy(_network_game_info.server_name, _network_server_name, sizeof(_network_game_info.server_name));
+	ttd_strlcpy(_network_game_info.server_password, _network_server_password, sizeof(_network_server_password));
+	ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_rcon_password));
 	if (_network_game_info.server_name[0] == '\0')
 		snprintf(_network_game_info.server_name, sizeof(_network_game_info.server_name), "Unnamed Server");
 
--- a/network.h	Sat Jan 15 19:17:45 2005 +0000
+++ b/network.h	Sat Jan 15 20:09:16 2005 +0000
@@ -42,12 +42,15 @@
 #define NETWORK_VEHICLE_TYPES 5
 #define NETWORK_STATION_TYPES 5
 
-#define NETWORK_NAME_LENGTH 80
-#define NETWORK_HOSTNAME_LENGTH 80
-#define NETWORK_REVISION_LENGTH 10
-#define NETWORK_PASSWORD_LENGTH 20
-#define NETWORK_PLAYERS_LENGTH 200
-#define NETWORK_CLIENT_NAME_LENGTH 25
+enum {
+	NETWORK_NAME_LENGTH        = 80,
+	NETWORK_HOSTNAME_LENGTH    = 80,
+	NETWORK_REVISION_LENGTH    = 10,
+	NETWORK_PASSWORD_LENGTH    = 20,
+	NETWORK_PLAYERS_LENGTH     = 200,
+	NETWORK_CLIENT_NAME_LENGTH = 25,
+	NETWORK_RCONCOMMAND_LENGTH = 500,
+};
 
 // This is the struct used by both client and server
 //  some fields will be empty on the client (like game_password) by default
@@ -71,6 +74,7 @@
 	uint16 map_height;															// Map height
 	byte map_set;																		// Graphical set
 	bool dedicated;																	// Is this a dedicated server?
+	char rcon_password[NETWORK_PASSWORD_LENGTH];		// RCon password for the server. "" if rcon is disabled
 } NetworkGameInfo;
 
 typedef struct NetworkPlayerInfo {
@@ -155,6 +159,10 @@
 VARDEF char _network_server_bind_ip_host[NETWORK_HOSTNAME_LENGTH];
 VARDEF bool _is_network_server; // Does this client wants to be a network-server?
 VARDEF char _network_server_name[NETWORK_NAME_LENGTH];
+VARDEF char _network_server_password[NETWORK_PASSWORD_LENGTH];
+VARDEF char _network_rcon_password[NETWORK_PASSWORD_LENGTH];
+
+VARDEF uint16 _redirect_console_to_client;
 
 VARDEF uint16 _network_sync_freq;
 VARDEF uint8 _network_frame_freq;
--- a/network_client.c	Sat Jan 15 19:17:45 2005 +0000
+++ b/network_client.c	Sat Jan 15 20:09:16 2005 +0000
@@ -10,6 +10,7 @@
 #include "gfx.h"
 #include "window.h"
 #include "settings.h"
+#include "console.h"
 
 
 // This file handles all the client-commands
@@ -246,6 +247,14 @@
 	NetworkSend_Packet(p, MY_CLIENT);
 }
 
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command)
+{
+	Packet *p = NetworkSend_Init(PACKET_CLIENT_RCON);
+	NetworkSend_string(p, pass);
+	NetworkSend_string(p, command);
+	NetworkSend_Packet(p, MY_CLIENT);
+}
+
 
 // **********
 // Receiving functions
@@ -741,6 +750,18 @@
 	return NETWORK_RECV_STATUS_SERVER_ERROR;
 }
 
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_RCON)
+{
+	char rcon_out[NETWORK_RCONCOMMAND_LENGTH];
+	uint16 color_code;
+
+	color_code = NetworkRecv_uint16(MY_CLIENT, p);
+	NetworkRecv_string(MY_CLIENT, p, rcon_out, sizeof(rcon_out));
+
+	IConsolePrint(color_code, rcon_out);
+
+	return NETWORK_RECV_STATUS_OKAY;
+}
 
 
 
@@ -782,6 +803,8 @@
 	RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT),
 	RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN),
 	RECEIVE_COMMAND(PACKET_SERVER_NEWGAME),
+	RECEIVE_COMMAND(PACKET_SERVER_RCON),
+	NULL, /*PACKET_CLIENT_RCON,*/
 };
 
 // If this fails, check the array above with network_data.h
--- a/network_client.h	Sat Jan 15 19:17:45 2005 +0000
+++ b/network_client.h	Sat Jan 15 20:09:16 2005 +0000
@@ -13,6 +13,7 @@
 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_PASSWORD)(const char *password);
 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name);
 DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_ACK);
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command);
 
 NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientState *cs);
 void NetworkClient_Connected(void);
--- a/network_data.h	Sat Jan 15 19:17:45 2005 +0000
+++ b/network_data.h	Sat Jan 15 20:09:16 2005 +0000
@@ -160,6 +160,8 @@
 	PACKET_SERVER_ERROR_QUIT,
 	PACKET_SERVER_SHUTDOWN,
 	PACKET_SERVER_NEWGAME,
+	PACKET_SERVER_RCON,
+	PACKET_CLIENT_RCON,
 	PACKET_END // Should ALWAYS be on the end of this list!! (period)
 } PacketType;
 
--- a/network_server.c	Sat Jan 15 19:17:45 2005 +0000
+++ b/network_server.c	Sat Jan 15 20:09:16 2005 +0000
@@ -566,6 +566,15 @@
 	NetworkSend_Packet(p, cs);
 }
 
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkClientState *cs, uint16 color, const char *command)
+{
+	Packet *p = NetworkSend_Init(PACKET_SERVER_RCON);
+
+	NetworkSend_uint16(p, color);
+	NetworkSend_string(p, command);
+	NetworkSend_Packet(p, cs);
+}
+
 // **********
 // Receiving functions
 //   DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientState *cs, Packet *p
@@ -1082,6 +1091,30 @@
 	}
 }
 
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_RCON)
+{
+	char pass[NETWORK_PASSWORD_LENGTH];
+	char command[NETWORK_RCONCOMMAND_LENGTH];
+
+	if (_network_game_info.rcon_password[0] == '\0')
+		return;
+
+	NetworkRecv_string(cs, p, pass, sizeof(pass));
+	NetworkRecv_string(cs, p, command, sizeof(command));
+
+	if (strncmp(pass, _network_game_info.rcon_password, sizeof(pass)) != 0) {
+		DEBUG(net, 0)("[RCon] Wrong password from client-id %d", cs->index);
+		return;
+	}
+
+	DEBUG(net, 0)("[RCon] Client-id %d executed: %s", cs->index, command);
+
+	_redirect_console_to_client = cs->index;
+	IConsoleCmdExec(command);
+	_redirect_console_to_client = 0;
+	return;
+}
+
 // The layout for the receive-functions by the server
 typedef void NetworkServerPacket(NetworkClientState *cs, Packet *p);
 
@@ -1121,6 +1154,8 @@
 	NULL, /*PACKET_SERVER_ERROR_QUIT,*/
 	NULL, /*PACKET_SERVER_SHUTDOWN,*/
 	NULL, /*PACKET_SERVER_NEWGAME,*/
+	NULL, /*PACKET_SERVER_RCON,*/
+	RECEIVE_COMMAND(PACKET_CLIENT_RCON),
 };
 
 // If this fails, check the array above with network_data.h
--- a/network_server.h	Sat Jan 15 19:17:45 2005 +0000
+++ b/network_server.h	Sat Jan 15 20:09:16 2005 +0000
@@ -8,6 +8,7 @@
 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientState *cs, NetworkErrorCode error);
 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN);
 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME);
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkClientState *cs, uint16 color, const char *command);
 
 bool NetworkFindName(char new_name[NETWORK_NAME_LENGTH]);
 void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest, const char *msg, uint16 from_index);
--- a/settings.c	Sat Jan 15 19:17:45 2005 +0000
+++ b/settings.c	Sat Jan 15 20:09:16 2005 +0000
@@ -759,7 +759,8 @@
 	{"server_advertise",SDT_BOOL, (void*)false, &_network_advertise, NULL},
 	{"lan_internet",		SDT_UINT8, (void*)0, &_network_lan_internet, NULL},
 	{"player_name",			SDT_STRINGBUF | (lengthof(_network_player_name) << 16), NULL, &_network_player_name, NULL},
-	{"server_password",	SDT_STRINGBUF | (lengthof(_network_game_info.server_password) << 16), NULL, &_network_game_info.server_password, NULL},
+	{"server_password",	SDT_STRINGBUF | (lengthof(_network_server_password) << 16), NULL, &_network_server_password, NULL},
+	{"rcon_password",		SDT_STRINGBUF | (lengthof(_network_rcon_password) << 16), NULL, &_network_rcon_password, NULL},
 	{"server_name",			SDT_STRINGBUF | (lengthof(_network_server_name) << 16), NULL, &_network_server_name, NULL},
 	{"connect_to_ip",		SDT_STRINGBUF | (lengthof(_network_default_ip) << 16), NULL, &_network_default_ip, NULL},
 	{"network_id",			SDT_STRINGBUF | (lengthof(_network_unique_id) << 16), NULL, &_network_unique_id, NULL},