892 lines
No EOL
34 KiB
C++
892 lines
No EOL
34 KiB
C++
/*
|
|
** Command & Conquer Renegade(tm)
|
|
** Copyright 2025 Electronic Arts Inc.
|
|
**
|
|
** This program 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, either version 3 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program 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. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/***********************************************************************************************
|
|
*** Confidential - Westwood Studios ***
|
|
***********************************************************************************************
|
|
* *
|
|
* Project Name : Commando *
|
|
* *
|
|
* $Archive:: /Commando/Code/Commando/ServerSettings.cpp $*
|
|
* *
|
|
* $Author:: Steve_t $*
|
|
* *
|
|
* $Modtime:: 8/09/02 2:12p $*
|
|
* *
|
|
* $Revision:: 17 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
|
|
#include "ServerSettings.h"
|
|
#include "slavemaster.h"
|
|
#include "wwdebug.h"
|
|
#include "gamedata.h"
|
|
#include "gdcnc.h"
|
|
#include "ini.h"
|
|
#include "registry.h"
|
|
#include "rawfile.h"
|
|
#include "consolemode.h"
|
|
#include "specialbuilds.h"
|
|
#include "_globals.h"
|
|
#include "bandwidth.h"
|
|
#include "mpsettingsmgr.h"
|
|
#include "wwonline\wolserver.h"
|
|
#include "useroptions.h"
|
|
#include "gamespyadmin.h"
|
|
#include "servercontrol.h"
|
|
#include "gamesideservercontrol.h"
|
|
#include "autostart.h"
|
|
#include "GameSpy_QnR.h"
|
|
#include "bandwidthcheck.h"
|
|
|
|
|
|
|
|
const char *ConfigSettingsName = "Config";
|
|
const char *MasterServerSection = "Server";
|
|
const char *SlaveServerSection = "Slave";
|
|
|
|
#define ENCRYPTION_STRING_LENGTH 128
|
|
#define KEY_SLAVE_SERIAL "Serial"
|
|
|
|
char ServerSettingsClass::SettingsFile[MAX_PATH];
|
|
bool ServerSettingsClass::IsActive = false;
|
|
char ServerSettingsClass::MasterPassword[128];
|
|
ServerSettingsClass::GameModeTypeEnum ServerSettingsClass::GameMode = MODE_NONE;
|
|
unsigned long ServerSettingsClass::MasterBandwidth = 0;
|
|
char ServerSettingsClass::PreferredLoginServer[256];
|
|
int ServerSettingsClass::DiskLogSize = -1;
|
|
|
|
const char *ServerListTag = "Available Westwood Servers:";
|
|
const char *ServerListEnd = "; End generated section.";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* ServerSettingsClass::Set_Settings_File_Name -- Set the name of the settings file *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: File name *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 2/1/2002 12:07PM ST : Created *
|
|
*=============================================================================================*/
|
|
void ServerSettingsClass::Set_Settings_File_Name(char *filename)
|
|
{
|
|
if (strlen(filename) < sizeof(SettingsFile)) {
|
|
strcpy(SettingsFile, filename);
|
|
IsActive = true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* ServerSettingsClass::Parse -- Pull the server info out of the settings file *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: True if we should apply the settings. False to parse for errors only. *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 2/1/2002 12:07PM ST : Created *
|
|
*=============================================================================================*/
|
|
bool ServerSettingsClass::Parse(bool apply)
|
|
{
|
|
char master_settings[MAX_PATH];
|
|
char slave_settings[MAX_PATH];
|
|
char slave_section[256];
|
|
char slave_nick[128];
|
|
char slave_serial[128];
|
|
char slave_pass[128];
|
|
int slave_port;
|
|
int slave_bw;
|
|
char master_nick[128];
|
|
char master_serial[128];
|
|
int master_port;
|
|
int master_bw;
|
|
char master_pass[128];
|
|
char remote_admin_pass[128];
|
|
char game_type[32];
|
|
char heartbeat_list[512];
|
|
bool wol = true;
|
|
char remote_admin_ip[128];
|
|
|
|
MasterPassword[0] = 0;
|
|
|
|
/*
|
|
** IsActive is set when the settigns file name is set.
|
|
*/
|
|
if (IsActive) {
|
|
|
|
WWASSERT(The_Game() || !apply);
|
|
if (apply) {
|
|
WWDEBUG_SAY(("Applying server settings\n"));
|
|
ConsoleBox.Print("Applying server settings\n");
|
|
}
|
|
|
|
/*
|
|
** Make sure the server config file is there. It should be since it's verified at command line parsing time.
|
|
*/
|
|
RawFileClass file(SettingsFile);
|
|
if (!file.Is_Available()) {
|
|
WWDEBUG_SAY(("Server startup file '%s' not found\n", SettingsFile));
|
|
ConsoleBox.Print("Error - server startup file '%s' not found - aborting\n", SettingsFile);
|
|
ConsoleBox.Wait_For_Keypress();
|
|
return(false);
|
|
}
|
|
|
|
/*
|
|
** Get the name of the master server settings file.
|
|
*/
|
|
INIClass ini(file);
|
|
ini.Get_String(MasterServerSection, ConfigSettingsName, "", master_settings, sizeof(master_settings));
|
|
if (strlen(master_settings) == 0) {
|
|
if (apply) {
|
|
WWDEBUG_SAY(("No master server settings specified - using defaults\n"));
|
|
ConsoleBox.Print("No master server settings specified - using defaults\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Load the master server settings from the ini file.
|
|
*/
|
|
|
|
|
|
/*
|
|
** Game Type.
|
|
*/
|
|
ini.Get_String(MasterServerSection, "GameType", "WOL", game_type, sizeof(game_type));
|
|
if (cGameSpyAdmin::Get_Is_Server_Gamespy_Listed()) {
|
|
strcpy(game_type, "GameSpy");
|
|
}
|
|
if (stricmp(game_type, "WOL") == 0) {
|
|
GameMode = MODE_WOL;
|
|
} else if (stricmp(game_type, "LAN") == 0) {
|
|
wol = false;
|
|
GameMode = MODE_LAN;
|
|
} else if (stricmp(game_type, "GameSpy") == 0) {
|
|
wol = false;
|
|
cGameSpyAdmin::Set_Is_Server_Gamespy_Listed(true);
|
|
GameSpyQnR.Enable_Reporting(true);
|
|
GameMode = MODE_GAMESPY;
|
|
} else {
|
|
WWDEBUG_SAY(("Bad game type specified in server.ini\n"));
|
|
ConsoleBox.Print("Error - Unknown game type in server settings. Use 'LAN', 'WOL', or 'GameSpy' - aborting\n");
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
|
|
/*
|
|
** Parse the list of GameSpy Style Master servers from the HeartBeat List
|
|
*/
|
|
heartbeat_list[sizeof(heartbeat_list)-1] = 0;
|
|
ini.Get_String(MasterServerSection, "HeartBeatServers", GameSpyQnR.Get_Default_HeartBeat_List(), heartbeat_list, sizeof(heartbeat_list)-1);
|
|
if (!GameSpyQnR.Parse_HeartBeat_List(heartbeat_list)) {
|
|
GameSpyQnR.Parse_HeartBeat_List(GameSpyQnR.Get_Default_HeartBeat_List());
|
|
}
|
|
|
|
/*
|
|
** Make sure the master server settings file is there.
|
|
*/
|
|
char filename[MAX_PATH];
|
|
sprintf(filename, "data\\%s", master_settings);
|
|
file.Set_Name(filename);
|
|
if (!file.Is_Available()) {
|
|
WWDEBUG_SAY(("Server settings file '%s' not found\n", filename));
|
|
ConsoleBox.Print("Error - server settings file '%s' not found - aborting\n", filename);
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
} else {
|
|
if (!Check_Game_Settings_File(master_settings)) {
|
|
WWDEBUG_SAY(("Server settings file '%s' not usable\n", master_settings));
|
|
ConsoleBox.Print("Error - server settings file '%s' contains errors - aborting\n", master_settings);
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
if (apply && The_Game()) {
|
|
The_Game()->Set_Ini_Filename(master_settings);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Restart Flag
|
|
*/
|
|
|
|
RegistryClass restart_reg(APPLICATION_SUB_KEY_NAME_WOLSETTINGS);
|
|
if (restart_reg.Is_Valid ()) {
|
|
restart_reg.Set_Int(AutoRestartClass::REG_VALUE_AUTO_RESTART_FLAG, 1);
|
|
switch (GameMode) {
|
|
case MODE_WOL:
|
|
restart_reg.Set_Int(AutoRestartClass::REG_VALUE_AUTO_RESTART_TYPE, 1);
|
|
break;
|
|
case MODE_LAN:
|
|
case MODE_GAMESPY:
|
|
restart_reg.Set_Int(AutoRestartClass::REG_VALUE_AUTO_RESTART_TYPE, 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Nickname.
|
|
*/
|
|
ini.Get_String(MasterServerSection, "Nickname", "", master_nick, sizeof(master_nick));
|
|
#ifdef FREEDEDICATEDSERVER
|
|
/*
|
|
** We only need to validate this for the FDS. The regular game can allow the login name to be specified in the registry.
|
|
*/
|
|
if (wol && strlen(master_nick) == 0) {
|
|
WWDEBUG_SAY(("Error - No login nickname specified for master server - aborting\n"));
|
|
ConsoleBox.Print("Error - No login nickname specified for master server - aborting\n");
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
#endif //FREEDEDICATEDSERVER
|
|
|
|
/*
|
|
** Password.
|
|
*/
|
|
ini.Get_String(MasterServerSection, "Password", "", master_pass, sizeof(master_pass));
|
|
#ifdef FREEDEDICATEDSERVER
|
|
/*
|
|
** We only need to validate this for the FDS. The regular game can allow the login name to be specified in the registry.
|
|
*/
|
|
if (wol && strlen(master_pass) == 0) {
|
|
WWDEBUG_SAY(("Error - No login password specified for master server - aborting\n"));
|
|
ConsoleBox.Print("Error - No login password specified for master server - aborting\n");
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
#endif //FREEDEDICATEDSERVER
|
|
|
|
/*
|
|
** Serial number.
|
|
*/
|
|
ini.Get_String(MasterServerSection, "Serial", "", master_serial, sizeof(master_serial));
|
|
#ifdef FREEDEDICATEDSERVER
|
|
/*
|
|
** We only need to validate the serial number if we are the FDS. For the regular game, the master serial will be stored
|
|
** in the registry.
|
|
*/
|
|
if (wol && strlen(master_serial) == 0) {
|
|
WWDEBUG_SAY(("Error - No serial number specified for master server - aborting\n"));
|
|
ConsoleBox.Print("Error - No serial number specified for master server - aborting\n");
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
#endif //FREEDEDICATEDSERVER
|
|
|
|
/*
|
|
** Get the port number.
|
|
*/
|
|
master_port = ini.Get_Int(MasterServerSection, "Port", 0xffffffff);
|
|
if (wol && master_port != 0xffffffff && (master_port < 0 || master_port > 0xffff)) {
|
|
WWDEBUG_SAY(("Error - Invalid port number %d specified for master server - aborting\n", master_port));
|
|
ConsoleBox.Print("Error - Invalid port number %d specified for master server - aborting\n", master_port);
|
|
ConsoleBox.Wait_For_Keypress();
|
|
return(false);
|
|
}
|
|
|
|
/*
|
|
** Get the GameSpy Query port number.
|
|
*/
|
|
int gsqport = cUserOptions::GameSpyQueryPort.Get();
|
|
gsqport = ini.Get_Int(MasterServerSection, "GameSpyQueryPort", gsqport);
|
|
if (!gsqport) gsqport = cUserOptions::GameSpyQueryPort.Get();
|
|
if (gsqport < 0 || gsqport > 0xffff) {
|
|
WWDEBUG_SAY(("Error - Invalid port number %d specified for GameSpy Query Port - aborting\n", gsqport));
|
|
ConsoleBox.Print("Error - Invalid port number %d specified for GameSpy Query Port - aborting\n", gsqport);
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
cUserOptions::GameSpyQueryPort.Set(gsqport);
|
|
|
|
/*
|
|
** Get the GameSpy Game port number.
|
|
*/
|
|
int gsgport = cUserOptions::GameSpyGamePort.Get();
|
|
gsgport = ini.Get_Int(MasterServerSection, "GameSpyGamePort", gsgport);
|
|
if (!gsgport) gsgport = cUserOptions::GameSpyGamePort.Get();
|
|
if (gsgport < 0 || gsgport > 0xffff || gsgport == gsqport) {
|
|
WWDEBUG_SAY(("Error - Invalid port number %d specified for GameSpy Game Port - aborting\n", gsgport));
|
|
ConsoleBox.Print("Error - Invalid port number %d specified for GameSpy Game Port - aborting\n", gsgport);
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
cUserOptions::GameSpyGamePort.Set(gsgport);
|
|
|
|
/*
|
|
** Get the bandwidth allowance.
|
|
*/
|
|
master_bw = ini.Get_Int(MasterServerSection, "BandwidthUp", 0xffffffff);
|
|
if (master_bw != 0 && master_bw != 0xffffffff && master_bw < 33600) {
|
|
WWDEBUG_SAY(("Error - Insufficient bandwidth specified for master server - aborting\n"));
|
|
ConsoleBox.Print("Error - Insufficient bandwidth specified for master server - aborting\n");
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
MasterBandwidth = master_bw;
|
|
|
|
/*
|
|
** Get the max size of the disk log in days.
|
|
*/
|
|
DiskLogSize = ini.Get_Int(MasterServerSection, "DiskLogSize", 7);
|
|
if (DiskLogSize > 365) {
|
|
WWDEBUG_SAY(("Error - Disk log size too large - aborting\n"));
|
|
ConsoleBox.Print("Error - Disk log size too large - aborting\n");
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
|
|
/*
|
|
** Get the preferred login server. No preference means use default from ping profile.
|
|
*/
|
|
ini.Get_String(MasterServerSection, "LoginServer", "", PreferredLoginServer, sizeof(PreferredLoginServer));
|
|
|
|
/*
|
|
** Get the Network Update Rate override.
|
|
*/
|
|
int nur = ini.Get_Int(MasterServerSection, "NetUpdateRate", 8);
|
|
if (nur < 5 || nur > 30) {
|
|
WWDEBUG_SAY(("Error - Bad NetUpdateRate specified - aborting\n"));
|
|
ConsoleBox.Print("Error - NetUpdateRate must be between 5 and 30 - aborting\n");
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
cUserOptions::NetUpdateRate.Set(nur);
|
|
|
|
/*
|
|
** Get the remote admin settings.
|
|
*/
|
|
bool allow_remote = ini.Get_Bool(MasterServerSection, "AllowRemoteAdmin", false);
|
|
RegistryClass reg_remote(APPLICATION_SUB_KEY_NAME_NET_SERVER_CONTROL);
|
|
if (allow_remote) {
|
|
ini.Get_String(MasterServerSection, "RemoteAdminPassword", "", remote_admin_pass, sizeof(remote_admin_pass));
|
|
int len = strlen(remote_admin_pass);
|
|
if (len == 0) {
|
|
ConsoleBox.Print("Error - Remote admin password must be specified - aborting\n");
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
} else {
|
|
if (len > 31) {
|
|
ConsoleBox.Print("Error - Remote admin password too long - aborting\n");
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
}
|
|
int admin_port = ini.Get_Int(MasterServerSection, "RemoteAdminPort", 0);
|
|
if (admin_port != 0 && (admin_port < 1024 || admin_port > 65535-8)) {
|
|
ConsoleBox.Print("Error - Remote admin port number out of range - aborting\n");
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
|
|
ServerControl.Allow_Remote_Admin(true);
|
|
|
|
/*
|
|
** Set the port number into the registry.
|
|
*/
|
|
if (admin_port == 0) {
|
|
admin_port = DEFAULT_SERVER_CONTROL_PORT;
|
|
}
|
|
reg_remote.Set_Int(SERVER_CONTROL_PORT_KEY, admin_port);
|
|
|
|
/*
|
|
** Set the password into the registry.
|
|
*/
|
|
reg_remote.Set_String(SERVER_CONTROL_PASSWORD_KEY, remote_admin_pass);
|
|
|
|
/*
|
|
** We need to bind to more than just the loopback address when listening for control messages.
|
|
*/
|
|
reg_remote.Set_Int(SERVER_CONTROL_LOOPBACK_KEY, 0);
|
|
|
|
/*
|
|
** There may be an IP override specified.
|
|
*/
|
|
ini.Get_String(MasterServerSection, "RemoteAdminIP", "0.0.0.0", remote_admin_ip, sizeof(remote_admin_ip));
|
|
unsigned long admin_ip_long = ntohl(inet_addr(remote_admin_ip));
|
|
reg_remote.Set_Int(SERVER_CONTROL_IP_KEY, admin_ip_long);
|
|
|
|
} else {
|
|
|
|
/*
|
|
** Only listen to control messages on the loopback address.
|
|
*/
|
|
reg_remote.Set_Int(SERVER_CONTROL_LOOPBACK_KEY, 1);
|
|
ServerControl.Allow_Remote_Admin(false);
|
|
}
|
|
|
|
|
|
/*
|
|
** Set the master settings into the registry.
|
|
*/
|
|
//if (apply) {
|
|
|
|
/*
|
|
** Serial number.
|
|
*/
|
|
if (wol) {
|
|
if (strlen(master_serial)) {
|
|
StringClass serial(master_serial, true);
|
|
StringClass encrypted_serial;
|
|
Encrypt_Serial(serial, encrypted_serial);
|
|
RegistryClass reg_base(APPLICATION_SUB_KEY_NAME);
|
|
if (reg_base.Is_Valid()) {
|
|
reg_base.Set_String(KEY_SLAVE_SERIAL, encrypted_serial.Peek_Buffer());
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Nickname.
|
|
*/
|
|
if (strlen(master_nick)) {
|
|
RegistryClass reg_wol(APPLICATION_SUB_KEY_NAME_WOLSETTINGS);
|
|
if (reg_wol.Is_Valid()) {
|
|
reg_wol.Set_String("AutoLogin", master_nick);
|
|
reg_wol.Set_String("LastLogin", master_nick);
|
|
reg_wol.Set_Int("AutoLoginPrompt", 0);
|
|
MPSettingsMgrClass::Set_Auto_Login(master_nick);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Password.
|
|
*/
|
|
MPSettingsMgrClass::Set_Auto_Password(master_pass);
|
|
|
|
/*
|
|
** Port number.
|
|
*/
|
|
if (master_port != 0xffffffff) {
|
|
RegistryClass reg_fw(APPLICATION_SUB_KEY_NAME_NET_FIREWALL);
|
|
reg_fw.Set_Int("ForcePort", master_port);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Bandwidth.
|
|
*/
|
|
if (master_bw != 0xffffffff) {
|
|
RegistryClass reg_netopt(APPLICATION_SUB_KEY_NAME_NETOPTIONS);
|
|
if (reg_netopt.Is_Valid()) {
|
|
if (cGameSpyAdmin::Is_Gamespy_Game()) {
|
|
if (master_bw == 0) master_bw = 1000000;
|
|
cUserOptions::Set_Bandwidth_Bps(master_bw);
|
|
} else {
|
|
if (wol) {
|
|
reg_netopt.Set_Int("BandwidthType", BANDWIDTH_AUTO);
|
|
|
|
/*
|
|
** We want this to be set always on the first time through, but not neccessarily on the second, apply, pass.
|
|
*/
|
|
if (master_bw != 0 || !apply) {
|
|
RegistryClass reg_bw(APPLICATION_SUB_KEY_NAME_BANDTEST);
|
|
if (reg_bw.Is_Valid()) {
|
|
reg_bw.Set_Int("Up", master_bw);
|
|
reg_bw.Set_Int("Down", master_bw);
|
|
}
|
|
}
|
|
} else {
|
|
cUserOptions::Set_Bandwidth_Type(BANDWIDTH_LANT1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//}
|
|
|
|
|
|
|
|
if (apply) {
|
|
SlaveMaster.Reset();
|
|
}
|
|
|
|
/*
|
|
** Read the slave server info.
|
|
*/
|
|
for (int i=0 ; i<MAX_SLAVES ; i++) {
|
|
|
|
slave_settings[0] = 0;
|
|
slave_nick[0] = 0;
|
|
slave_serial[0] = 0;
|
|
slave_port = 0;
|
|
slave_bw = 0xffffffff;
|
|
|
|
/*
|
|
** See if this slave is enabled in the .ini
|
|
*/
|
|
sprintf(slave_section, "%s%d", SlaveServerSection, i+1);
|
|
bool enabled = ini.Get_Bool(slave_section, "Enable", false);
|
|
|
|
if (enabled) {
|
|
|
|
/*
|
|
** Make sure the slaves config file is present.
|
|
*/
|
|
ini.Get_String(slave_section, ConfigSettingsName, "", slave_settings, sizeof(slave_settings));
|
|
if (strlen(slave_settings) != 0) {
|
|
sprintf(filename, "data\\%s", slave_settings);
|
|
file.Set_Name(filename);
|
|
if (!file.Is_Available()) {
|
|
WWDEBUG_SAY(("Slave server settings file '%s' not found\n", filename));
|
|
ConsoleBox.Print("Error - Slave server settings file '%s' not found - aborting\n", filename);
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
} else {
|
|
if (!Check_Game_Settings_File(slave_settings)) {
|
|
WWDEBUG_SAY(("Server settings file '%s' not usable\n", slave_settings));
|
|
ConsoleBox.Print("Error - server settings file '%s' contains errors - aborting\n", slave_settings);
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Make sure there's a nickname and a serial.
|
|
*/
|
|
ini.Get_String(slave_section, "Nickname", "", slave_nick, sizeof(slave_nick));
|
|
if (wol && strlen(slave_nick) == 0) {
|
|
WWDEBUG_SAY(("Error - No login nickname specified for slave %d - aborting\n", i+1));
|
|
ConsoleBox.Print("Error - No login nickname specified for slave %d - aborting\n", i+1);
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
|
|
ini.Get_String(slave_section, "Serial", "", slave_serial, sizeof(slave_serial));
|
|
if (wol && strlen(slave_serial) == 0) {
|
|
WWDEBUG_SAY(("Error - No serial number specified for slave %d - aborting\n", i+1));
|
|
ConsoleBox.Print("Error - No serial number specified for slave %d - aborting\n", i+1);
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
|
|
/*
|
|
** Get the password.
|
|
*/
|
|
ini.Get_String(slave_section, "Password", "", slave_pass, sizeof(slave_pass));
|
|
#ifdef FREEDEDICATEDSERVER
|
|
if (wol && strlen(slave_pass) == 0) {
|
|
WWDEBUG_SAY(("Error - No login password specified for slave %d - aborting\n", i+1));
|
|
ConsoleBox.Print("Error - No login password specified for slave %d - aborting\n", i+1);
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
#endif //FREEDEDICATEDSERVER
|
|
|
|
/*
|
|
** Get the port number.
|
|
*/
|
|
slave_port = ini.Get_Int(slave_section, "Port", 0);
|
|
|
|
if (slave_port < 0 || slave_port > 0xffff) {
|
|
WWDEBUG_SAY(("Error - Invalid port number %d specified for slave %d - aborting\n", slave_port, i+1));
|
|
ConsoleBox.Print("Error - Invalid port number %d specified for slave %d - aborting\n", slave_port, i+1);
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
|
|
/*
|
|
** Get the bandwidth allowance.
|
|
*/
|
|
slave_bw = ini.Get_Int(slave_section, "BandwidthUp", 0xffffffff);
|
|
if (slave_bw != 0 && slave_bw != 0xffffffff && slave_bw < 33600) {
|
|
WWDEBUG_SAY(("Error - Insufficient bandwidth specified for slave %d - aborting\n", i+1));
|
|
ConsoleBox.Print("Error - Insufficient bandwidth specified for slave %d - aborting\n", i+1);
|
|
ConsoleBox.Wait_For_Keypress();;
|
|
return(false);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Apply the settings.
|
|
*/
|
|
if (apply) {
|
|
SlaveMaster.Add_Slave(enabled, slave_nick, slave_serial, (unsigned short)slave_port, slave_settings, slave_bw, slave_pass);
|
|
}
|
|
}
|
|
if (apply) {
|
|
SlaveMaster.Save();
|
|
}
|
|
}
|
|
return(true);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* ServerSettingsClass::Encrypt_Serial -- Serial number encryption/decryption *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Input serial number *
|
|
* Reference to output serial number *
|
|
* Encrypt flag - true to encrypt, false to decrypt *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 2/1/2002 12:08PM ST : Created *
|
|
*=============================================================================================*/
|
|
void ServerSettingsClass::Encrypt_Serial(StringClass serial_in, StringClass &serial_out, bool encrypt)
|
|
{
|
|
char *s;
|
|
int numberlength = serial_in.Get_Length();
|
|
unsigned long bytesread;
|
|
char stringbuffer[ENCRYPTION_STRING_LENGTH];
|
|
int p;
|
|
|
|
WWASSERT(numberlength);
|
|
|
|
s = new char [numberlength + 1];
|
|
memcpy(s, serial_in.Peek_Buffer(), numberlength + 1);
|
|
|
|
/*
|
|
** See if the key file is available. If not, don't bother encrypting.
|
|
*/
|
|
HANDLE handle = CreateFile ("woldata.key", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
|
if (handle == INVALID_HANDLE_VALUE) {
|
|
delete [] s;
|
|
serial_out = serial_in;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
** Read the key.
|
|
*/
|
|
if (!ReadFile(handle, stringbuffer, sizeof (stringbuffer), &bytesread, NULL)) {
|
|
WWDEBUG_SAY(("Unable to read serial encryption key file\n"));
|
|
delete [] s;
|
|
serial_out = serial_in;
|
|
return;
|
|
}
|
|
|
|
int sign = encrypt ? 1 : -1;
|
|
|
|
p = 0;
|
|
for (unsigned i = 0; i < ENCRYPTION_STRING_LENGTH; i++) {
|
|
|
|
int t;
|
|
char c;
|
|
|
|
t = s[p] - '0';
|
|
t %= 10;
|
|
t += (sign * stringbuffer[i]);
|
|
t += 1000;
|
|
t %= 10;
|
|
c = t + '0';
|
|
s[p] = c;
|
|
p++;
|
|
if (p == numberlength) {
|
|
p = 0;
|
|
}
|
|
}
|
|
|
|
serial_out = StringClass(s, true);
|
|
|
|
delete [] s;
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* ServerSettingsClass::Decrypt_Serial -- Serial number decryption *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Input serial number *
|
|
* Reference to output serial number *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 2/1/2002 12:08PM ST : Created *
|
|
*=============================================================================================*/
|
|
void ServerSettingsClass::Decrypt_Serial(StringClass serial_in, StringClass &serial_out)
|
|
{
|
|
Encrypt_Serial(serial_in, serial_out, false);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* ServerSettingsClass::Get_Preferred_Server -- Get the users specified server *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Server list from servserv *
|
|
* *
|
|
* OUTPUT: Name of preferred server *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 2/1/2002 1:18PM ST : Created *
|
|
*=============================================================================================*/
|
|
char *ServerSettingsClass::Get_Preferred_Server(const WWOnline::IRCServerList &server_list)
|
|
{
|
|
if (IsActive && server_list.size()) {
|
|
Write_Server_List(server_list);
|
|
}
|
|
return(PreferredLoginServer);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* ServerSettingsClass::Write_Server_List -- Write the server list into the settings ini file *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Server list *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 2/1/2002 1:19PM ST : Created *
|
|
*=============================================================================================*/
|
|
void ServerSettingsClass::Write_Server_List(const WWOnline::IRCServerList &server_list)
|
|
{
|
|
WWASSERT(server_list.size());
|
|
WWASSERT(strlen(SettingsFile) != 0);
|
|
|
|
char temp[256];
|
|
|
|
if (server_list.size()) {
|
|
RawFileClass file(SettingsFile);
|
|
|
|
/*
|
|
** This is a bit hacky. Basically we just want the .ini file commented with the latest server list.
|
|
**
|
|
** We will do this by reading in the file, looking for a tag that tells us where to write the server list, then writing
|
|
** the file back out with the server list in place.
|
|
*/
|
|
if (file.Is_Available()) {
|
|
unsigned long size = file.Size();
|
|
if (size) {
|
|
|
|
/*
|
|
** Read the file.
|
|
*/
|
|
char *file_buffer = new char[size + 8192];
|
|
#ifdef WWDEBUG
|
|
unsigned long read_size =
|
|
#endif //WWDEBUG
|
|
file.Read(file_buffer, size);
|
|
WWASSERT(read_size == size);
|
|
file.Close();
|
|
|
|
/*
|
|
** Find the placeholder tag.
|
|
*/
|
|
char *tag = strstr(file_buffer, ServerListTag);
|
|
char *end_tag = strstr(file_buffer, ServerListEnd);
|
|
if (tag && end_tag) {
|
|
|
|
/*
|
|
** Write out the first portion of the file unchanged.
|
|
*/
|
|
file.Open(FileClass::WRITE);
|
|
file.Write(file_buffer, (tag - file_buffer) + strlen(ServerListTag));
|
|
|
|
/*
|
|
** Insert the server list.
|
|
*/
|
|
char *server_list_text = new char [8192];
|
|
strcpy(server_list_text, "\r\n;\r\n");
|
|
|
|
for (unsigned int i = 0; i < server_list.size(); i++) {
|
|
const RefPtr<WWOnline::IRCServerData> &server = server_list[i];
|
|
if (server->HasLanguageCode()) {
|
|
const char *server_name = server->GetName();
|
|
sprintf(temp, "; %s\r\n", server_name);
|
|
strcat(server_list_text, temp);
|
|
}
|
|
}
|
|
strcat(server_list_text, ";\r\n");
|
|
file.Write(server_list_text, strlen(server_list_text));
|
|
|
|
/*
|
|
** Write out the post server list sections of the original file.
|
|
*/
|
|
file.Write(end_tag, (file_buffer + size) - end_tag);
|
|
file.Close();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* ServerSettingsClass::Check_Game_Settings_File -- Check game settings for validity *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Game settings .ini file name *
|
|
* *
|
|
* OUTPUT: True if valid. *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 2/3/2002 9:37PM ST : Created *
|
|
*=============================================================================================*/
|
|
bool ServerSettingsClass::Check_Game_Settings_File(char *config_file)
|
|
{
|
|
cGameDataCnc *game_settings = (cGameDataCnc*) cGameData::Create_Game_Of_Type(cGameData::GAME_TYPE_CNC);
|
|
WWASSERT(game_settings != NULL);
|
|
|
|
if (game_settings) {
|
|
game_settings->Set_Ini_Filename(config_file);
|
|
game_settings->Load_From_Server_Config();
|
|
|
|
WideStringClass outMsg;
|
|
bool ok = game_settings->Is_Valid_Settings(outMsg, true);
|
|
|
|
delete game_settings;
|
|
return(ok);
|
|
}
|
|
return(false);
|
|
} |