ServerSettings.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** Confidential - Westwood Studios ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Commando *
  23. * *
  24. * $Archive:: /Commando/Code/Commando/ServerSettings.cpp $*
  25. * *
  26. * $Author:: Steve_t $*
  27. * *
  28. * $Modtime:: 8/09/02 2:12p $*
  29. * *
  30. * $Revision:: 17 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "ServerSettings.h"
  36. #include "slavemaster.h"
  37. #include "wwdebug.h"
  38. #include "gamedata.h"
  39. #include "gdcnc.h"
  40. #include "ini.h"
  41. #include "registry.h"
  42. #include "rawfile.h"
  43. #include "consolemode.h"
  44. #include "specialbuilds.h"
  45. #include "_globals.h"
  46. #include "bandwidth.h"
  47. #include "mpsettingsmgr.h"
  48. #include "wwonline\wolserver.h"
  49. #include "useroptions.h"
  50. #include "gamespyadmin.h"
  51. #include "servercontrol.h"
  52. #include "gamesideservercontrol.h"
  53. #include "autostart.h"
  54. #include "GameSpy_QnR.h"
  55. #include "bandwidthcheck.h"
  56. const char *ConfigSettingsName = "Config";
  57. const char *MasterServerSection = "Server";
  58. const char *SlaveServerSection = "Slave";
  59. #define ENCRYPTION_STRING_LENGTH 128
  60. #define KEY_SLAVE_SERIAL "Serial"
  61. char ServerSettingsClass::SettingsFile[MAX_PATH];
  62. bool ServerSettingsClass::IsActive = false;
  63. char ServerSettingsClass::MasterPassword[128];
  64. ServerSettingsClass::GameModeTypeEnum ServerSettingsClass::GameMode = MODE_NONE;
  65. unsigned long ServerSettingsClass::MasterBandwidth = 0;
  66. char ServerSettingsClass::PreferredLoginServer[256];
  67. int ServerSettingsClass::DiskLogSize = -1;
  68. const char *ServerListTag = "Available Westwood Servers:";
  69. const char *ServerListEnd = "; End generated section.";
  70. /***********************************************************************************************
  71. * ServerSettingsClass::Set_Settings_File_Name -- Set the name of the settings file *
  72. * *
  73. * *
  74. * *
  75. * INPUT: File name *
  76. * *
  77. * OUTPUT: Nothing *
  78. * *
  79. * WARNINGS: None *
  80. * *
  81. * HISTORY: *
  82. * 2/1/2002 12:07PM ST : Created *
  83. *=============================================================================================*/
  84. void ServerSettingsClass::Set_Settings_File_Name(char *filename)
  85. {
  86. if (strlen(filename) < sizeof(SettingsFile)) {
  87. strcpy(SettingsFile, filename);
  88. IsActive = true;
  89. }
  90. }
  91. /***********************************************************************************************
  92. * ServerSettingsClass::Parse -- Pull the server info out of the settings file *
  93. * *
  94. * *
  95. * *
  96. * INPUT: True if we should apply the settings. False to parse for errors only. *
  97. * *
  98. * OUTPUT: Nothing *
  99. * *
  100. * WARNINGS: None *
  101. * *
  102. * HISTORY: *
  103. * 2/1/2002 12:07PM ST : Created *
  104. *=============================================================================================*/
  105. bool ServerSettingsClass::Parse(bool apply)
  106. {
  107. char master_settings[MAX_PATH];
  108. char slave_settings[MAX_PATH];
  109. char slave_section[256];
  110. char slave_nick[128];
  111. char slave_serial[128];
  112. char slave_pass[128];
  113. int slave_port;
  114. int slave_bw;
  115. char master_nick[128];
  116. char master_serial[128];
  117. int master_port;
  118. int master_bw;
  119. char master_pass[128];
  120. char remote_admin_pass[128];
  121. char game_type[32];
  122. char heartbeat_list[512];
  123. bool wol = true;
  124. char remote_admin_ip[128];
  125. MasterPassword[0] = 0;
  126. /*
  127. ** IsActive is set when the settigns file name is set.
  128. */
  129. if (IsActive) {
  130. WWASSERT(The_Game() || !apply);
  131. if (apply) {
  132. WWDEBUG_SAY(("Applying server settings\n"));
  133. ConsoleBox.Print("Applying server settings\n");
  134. }
  135. /*
  136. ** Make sure the server config file is there. It should be since it's verified at command line parsing time.
  137. */
  138. RawFileClass file(SettingsFile);
  139. if (!file.Is_Available()) {
  140. WWDEBUG_SAY(("Server startup file '%s' not found\n", SettingsFile));
  141. ConsoleBox.Print("Error - server startup file '%s' not found - aborting\n", SettingsFile);
  142. ConsoleBox.Wait_For_Keypress();
  143. return(false);
  144. }
  145. /*
  146. ** Get the name of the master server settings file.
  147. */
  148. INIClass ini(file);
  149. ini.Get_String(MasterServerSection, ConfigSettingsName, "", master_settings, sizeof(master_settings));
  150. if (strlen(master_settings) == 0) {
  151. if (apply) {
  152. WWDEBUG_SAY(("No master server settings specified - using defaults\n"));
  153. ConsoleBox.Print("No master server settings specified - using defaults\n");
  154. }
  155. }
  156. /*
  157. ** Load the master server settings from the ini file.
  158. */
  159. /*
  160. ** Game Type.
  161. */
  162. ini.Get_String(MasterServerSection, "GameType", "WOL", game_type, sizeof(game_type));
  163. if (cGameSpyAdmin::Get_Is_Server_Gamespy_Listed()) {
  164. strcpy(game_type, "GameSpy");
  165. }
  166. if (stricmp(game_type, "WOL") == 0) {
  167. GameMode = MODE_WOL;
  168. } else if (stricmp(game_type, "LAN") == 0) {
  169. wol = false;
  170. GameMode = MODE_LAN;
  171. } else if (stricmp(game_type, "GameSpy") == 0) {
  172. wol = false;
  173. cGameSpyAdmin::Set_Is_Server_Gamespy_Listed(true);
  174. GameSpyQnR.Enable_Reporting(true);
  175. GameMode = MODE_GAMESPY;
  176. } else {
  177. WWDEBUG_SAY(("Bad game type specified in server.ini\n"));
  178. ConsoleBox.Print("Error - Unknown game type in server settings. Use 'LAN', 'WOL', or 'GameSpy' - aborting\n");
  179. ConsoleBox.Wait_For_Keypress();;
  180. return(false);
  181. }
  182. /*
  183. ** Parse the list of GameSpy Style Master servers from the HeartBeat List
  184. */
  185. heartbeat_list[sizeof(heartbeat_list)-1] = 0;
  186. ini.Get_String(MasterServerSection, "HeartBeatServers", GameSpyQnR.Get_Default_HeartBeat_List(), heartbeat_list, sizeof(heartbeat_list)-1);
  187. if (!GameSpyQnR.Parse_HeartBeat_List(heartbeat_list)) {
  188. GameSpyQnR.Parse_HeartBeat_List(GameSpyQnR.Get_Default_HeartBeat_List());
  189. }
  190. /*
  191. ** Make sure the master server settings file is there.
  192. */
  193. char filename[MAX_PATH];
  194. sprintf(filename, "data\\%s", master_settings);
  195. file.Set_Name(filename);
  196. if (!file.Is_Available()) {
  197. WWDEBUG_SAY(("Server settings file '%s' not found\n", filename));
  198. ConsoleBox.Print("Error - server settings file '%s' not found - aborting\n", filename);
  199. ConsoleBox.Wait_For_Keypress();;
  200. return(false);
  201. } else {
  202. if (!Check_Game_Settings_File(master_settings)) {
  203. WWDEBUG_SAY(("Server settings file '%s' not usable\n", master_settings));
  204. ConsoleBox.Print("Error - server settings file '%s' contains errors - aborting\n", master_settings);
  205. ConsoleBox.Wait_For_Keypress();;
  206. return(false);
  207. }
  208. if (apply && The_Game()) {
  209. The_Game()->Set_Ini_Filename(master_settings);
  210. }
  211. }
  212. /*
  213. ** Restart Flag
  214. */
  215. RegistryClass restart_reg(APPLICATION_SUB_KEY_NAME_WOLSETTINGS);
  216. if (restart_reg.Is_Valid ()) {
  217. restart_reg.Set_Int(AutoRestartClass::REG_VALUE_AUTO_RESTART_FLAG, 1);
  218. switch (GameMode) {
  219. case MODE_WOL:
  220. restart_reg.Set_Int(AutoRestartClass::REG_VALUE_AUTO_RESTART_TYPE, 1);
  221. break;
  222. case MODE_LAN:
  223. case MODE_GAMESPY:
  224. restart_reg.Set_Int(AutoRestartClass::REG_VALUE_AUTO_RESTART_TYPE, 0);
  225. break;
  226. }
  227. }
  228. /*
  229. ** Nickname.
  230. */
  231. ini.Get_String(MasterServerSection, "Nickname", "", master_nick, sizeof(master_nick));
  232. #ifdef FREEDEDICATEDSERVER
  233. /*
  234. ** We only need to validate this for the FDS. The regular game can allow the login name to be specified in the registry.
  235. */
  236. if (wol && strlen(master_nick) == 0) {
  237. WWDEBUG_SAY(("Error - No login nickname specified for master server - aborting\n"));
  238. ConsoleBox.Print("Error - No login nickname specified for master server - aborting\n");
  239. ConsoleBox.Wait_For_Keypress();;
  240. return(false);
  241. }
  242. #endif //FREEDEDICATEDSERVER
  243. /*
  244. ** Password.
  245. */
  246. ini.Get_String(MasterServerSection, "Password", "", master_pass, sizeof(master_pass));
  247. #ifdef FREEDEDICATEDSERVER
  248. /*
  249. ** We only need to validate this for the FDS. The regular game can allow the login name to be specified in the registry.
  250. */
  251. if (wol && strlen(master_pass) == 0) {
  252. WWDEBUG_SAY(("Error - No login password specified for master server - aborting\n"));
  253. ConsoleBox.Print("Error - No login password specified for master server - aborting\n");
  254. ConsoleBox.Wait_For_Keypress();;
  255. return(false);
  256. }
  257. #endif //FREEDEDICATEDSERVER
  258. /*
  259. ** Serial number.
  260. */
  261. ini.Get_String(MasterServerSection, "Serial", "", master_serial, sizeof(master_serial));
  262. #ifdef FREEDEDICATEDSERVER
  263. /*
  264. ** We only need to validate the serial number if we are the FDS. For the regular game, the master serial will be stored
  265. ** in the registry.
  266. */
  267. if (wol && strlen(master_serial) == 0) {
  268. WWDEBUG_SAY(("Error - No serial number specified for master server - aborting\n"));
  269. ConsoleBox.Print("Error - No serial number specified for master server - aborting\n");
  270. ConsoleBox.Wait_For_Keypress();;
  271. return(false);
  272. }
  273. #endif //FREEDEDICATEDSERVER
  274. /*
  275. ** Get the port number.
  276. */
  277. master_port = ini.Get_Int(MasterServerSection, "Port", 0xffffffff);
  278. if (wol && master_port != 0xffffffff && (master_port < 0 || master_port > 0xffff)) {
  279. WWDEBUG_SAY(("Error - Invalid port number %d specified for master server - aborting\n", master_port));
  280. ConsoleBox.Print("Error - Invalid port number %d specified for master server - aborting\n", master_port);
  281. ConsoleBox.Wait_For_Keypress();
  282. return(false);
  283. }
  284. /*
  285. ** Get the GameSpy Query port number.
  286. */
  287. int gsqport = cUserOptions::GameSpyQueryPort.Get();
  288. gsqport = ini.Get_Int(MasterServerSection, "GameSpyQueryPort", gsqport);
  289. if (!gsqport) gsqport = cUserOptions::GameSpyQueryPort.Get();
  290. if (gsqport < 0 || gsqport > 0xffff) {
  291. WWDEBUG_SAY(("Error - Invalid port number %d specified for GameSpy Query Port - aborting\n", gsqport));
  292. ConsoleBox.Print("Error - Invalid port number %d specified for GameSpy Query Port - aborting\n", gsqport);
  293. ConsoleBox.Wait_For_Keypress();;
  294. return(false);
  295. }
  296. cUserOptions::GameSpyQueryPort.Set(gsqport);
  297. /*
  298. ** Get the GameSpy Game port number.
  299. */
  300. int gsgport = cUserOptions::GameSpyGamePort.Get();
  301. gsgport = ini.Get_Int(MasterServerSection, "GameSpyGamePort", gsgport);
  302. if (!gsgport) gsgport = cUserOptions::GameSpyGamePort.Get();
  303. if (gsgport < 0 || gsgport > 0xffff || gsgport == gsqport) {
  304. WWDEBUG_SAY(("Error - Invalid port number %d specified for GameSpy Game Port - aborting\n", gsgport));
  305. ConsoleBox.Print("Error - Invalid port number %d specified for GameSpy Game Port - aborting\n", gsgport);
  306. ConsoleBox.Wait_For_Keypress();;
  307. return(false);
  308. }
  309. cUserOptions::GameSpyGamePort.Set(gsgport);
  310. /*
  311. ** Get the bandwidth allowance.
  312. */
  313. master_bw = ini.Get_Int(MasterServerSection, "BandwidthUp", 0xffffffff);
  314. if (master_bw != 0 && master_bw != 0xffffffff && master_bw < 33600) {
  315. WWDEBUG_SAY(("Error - Insufficient bandwidth specified for master server - aborting\n"));
  316. ConsoleBox.Print("Error - Insufficient bandwidth specified for master server - aborting\n");
  317. ConsoleBox.Wait_For_Keypress();;
  318. return(false);
  319. }
  320. MasterBandwidth = master_bw;
  321. /*
  322. ** Get the max size of the disk log in days.
  323. */
  324. DiskLogSize = ini.Get_Int(MasterServerSection, "DiskLogSize", 7);
  325. if (DiskLogSize > 365) {
  326. WWDEBUG_SAY(("Error - Disk log size too large - aborting\n"));
  327. ConsoleBox.Print("Error - Disk log size too large - aborting\n");
  328. ConsoleBox.Wait_For_Keypress();;
  329. return(false);
  330. }
  331. /*
  332. ** Get the preferred login server. No preference means use default from ping profile.
  333. */
  334. ini.Get_String(MasterServerSection, "LoginServer", "", PreferredLoginServer, sizeof(PreferredLoginServer));
  335. /*
  336. ** Get the Network Update Rate override.
  337. */
  338. int nur = ini.Get_Int(MasterServerSection, "NetUpdateRate", 8);
  339. if (nur < 5 || nur > 30) {
  340. WWDEBUG_SAY(("Error - Bad NetUpdateRate specified - aborting\n"));
  341. ConsoleBox.Print("Error - NetUpdateRate must be between 5 and 30 - aborting\n");
  342. ConsoleBox.Wait_For_Keypress();;
  343. return(false);
  344. }
  345. cUserOptions::NetUpdateRate.Set(nur);
  346. /*
  347. ** Get the remote admin settings.
  348. */
  349. bool allow_remote = ini.Get_Bool(MasterServerSection, "AllowRemoteAdmin", false);
  350. RegistryClass reg_remote(APPLICATION_SUB_KEY_NAME_NET_SERVER_CONTROL);
  351. if (allow_remote) {
  352. ini.Get_String(MasterServerSection, "RemoteAdminPassword", "", remote_admin_pass, sizeof(remote_admin_pass));
  353. int len = strlen(remote_admin_pass);
  354. if (len == 0) {
  355. ConsoleBox.Print("Error - Remote admin password must be specified - aborting\n");
  356. ConsoleBox.Wait_For_Keypress();;
  357. return(false);
  358. } else {
  359. if (len > 31) {
  360. ConsoleBox.Print("Error - Remote admin password too long - aborting\n");
  361. ConsoleBox.Wait_For_Keypress();;
  362. return(false);
  363. }
  364. }
  365. int admin_port = ini.Get_Int(MasterServerSection, "RemoteAdminPort", 0);
  366. if (admin_port != 0 && (admin_port < 1024 || admin_port > 65535-8)) {
  367. ConsoleBox.Print("Error - Remote admin port number out of range - aborting\n");
  368. ConsoleBox.Wait_For_Keypress();;
  369. return(false);
  370. }
  371. ServerControl.Allow_Remote_Admin(true);
  372. /*
  373. ** Set the port number into the registry.
  374. */
  375. if (admin_port == 0) {
  376. admin_port = DEFAULT_SERVER_CONTROL_PORT;
  377. }
  378. reg_remote.Set_Int(SERVER_CONTROL_PORT_KEY, admin_port);
  379. /*
  380. ** Set the password into the registry.
  381. */
  382. reg_remote.Set_String(SERVER_CONTROL_PASSWORD_KEY, remote_admin_pass);
  383. /*
  384. ** We need to bind to more than just the loopback address when listening for control messages.
  385. */
  386. reg_remote.Set_Int(SERVER_CONTROL_LOOPBACK_KEY, 0);
  387. /*
  388. ** There may be an IP override specified.
  389. */
  390. ini.Get_String(MasterServerSection, "RemoteAdminIP", "0.0.0.0", remote_admin_ip, sizeof(remote_admin_ip));
  391. unsigned long admin_ip_long = ntohl(inet_addr(remote_admin_ip));
  392. reg_remote.Set_Int(SERVER_CONTROL_IP_KEY, admin_ip_long);
  393. } else {
  394. /*
  395. ** Only listen to control messages on the loopback address.
  396. */
  397. reg_remote.Set_Int(SERVER_CONTROL_LOOPBACK_KEY, 1);
  398. ServerControl.Allow_Remote_Admin(false);
  399. }
  400. /*
  401. ** Set the master settings into the registry.
  402. */
  403. //if (apply) {
  404. /*
  405. ** Serial number.
  406. */
  407. if (wol) {
  408. if (strlen(master_serial)) {
  409. StringClass serial(master_serial, true);
  410. StringClass encrypted_serial;
  411. Encrypt_Serial(serial, encrypted_serial);
  412. RegistryClass reg_base(APPLICATION_SUB_KEY_NAME);
  413. if (reg_base.Is_Valid()) {
  414. reg_base.Set_String(KEY_SLAVE_SERIAL, encrypted_serial.Peek_Buffer());
  415. }
  416. }
  417. /*
  418. ** Nickname.
  419. */
  420. if (strlen(master_nick)) {
  421. RegistryClass reg_wol(APPLICATION_SUB_KEY_NAME_WOLSETTINGS);
  422. if (reg_wol.Is_Valid()) {
  423. reg_wol.Set_String("AutoLogin", master_nick);
  424. reg_wol.Set_String("LastLogin", master_nick);
  425. reg_wol.Set_Int("AutoLoginPrompt", 0);
  426. MPSettingsMgrClass::Set_Auto_Login(master_nick);
  427. }
  428. }
  429. /*
  430. ** Password.
  431. */
  432. MPSettingsMgrClass::Set_Auto_Password(master_pass);
  433. /*
  434. ** Port number.
  435. */
  436. if (master_port != 0xffffffff) {
  437. RegistryClass reg_fw(APPLICATION_SUB_KEY_NAME_NET_FIREWALL);
  438. reg_fw.Set_Int("ForcePort", master_port);
  439. }
  440. }
  441. /*
  442. ** Bandwidth.
  443. */
  444. if (master_bw != 0xffffffff) {
  445. RegistryClass reg_netopt(APPLICATION_SUB_KEY_NAME_NETOPTIONS);
  446. if (reg_netopt.Is_Valid()) {
  447. if (cGameSpyAdmin::Is_Gamespy_Game()) {
  448. if (master_bw == 0) master_bw = 1000000;
  449. cUserOptions::Set_Bandwidth_Bps(master_bw);
  450. } else {
  451. if (wol) {
  452. reg_netopt.Set_Int("BandwidthType", BANDWIDTH_AUTO);
  453. /*
  454. ** We want this to be set always on the first time through, but not neccessarily on the second, apply, pass.
  455. */
  456. if (master_bw != 0 || !apply) {
  457. RegistryClass reg_bw(APPLICATION_SUB_KEY_NAME_BANDTEST);
  458. if (reg_bw.Is_Valid()) {
  459. reg_bw.Set_Int("Up", master_bw);
  460. reg_bw.Set_Int("Down", master_bw);
  461. }
  462. }
  463. } else {
  464. cUserOptions::Set_Bandwidth_Type(BANDWIDTH_LANT1);
  465. }
  466. }
  467. }
  468. }
  469. //}
  470. if (apply) {
  471. SlaveMaster.Reset();
  472. }
  473. /*
  474. ** Read the slave server info.
  475. */
  476. for (int i=0 ; i<MAX_SLAVES ; i++) {
  477. slave_settings[0] = 0;
  478. slave_nick[0] = 0;
  479. slave_serial[0] = 0;
  480. slave_port = 0;
  481. slave_bw = 0xffffffff;
  482. /*
  483. ** See if this slave is enabled in the .ini
  484. */
  485. sprintf(slave_section, "%s%d", SlaveServerSection, i+1);
  486. bool enabled = ini.Get_Bool(slave_section, "Enable", false);
  487. if (enabled) {
  488. /*
  489. ** Make sure the slaves config file is present.
  490. */
  491. ini.Get_String(slave_section, ConfigSettingsName, "", slave_settings, sizeof(slave_settings));
  492. if (strlen(slave_settings) != 0) {
  493. sprintf(filename, "data\\%s", slave_settings);
  494. file.Set_Name(filename);
  495. if (!file.Is_Available()) {
  496. WWDEBUG_SAY(("Slave server settings file '%s' not found\n", filename));
  497. ConsoleBox.Print("Error - Slave server settings file '%s' not found - aborting\n", filename);
  498. ConsoleBox.Wait_For_Keypress();;
  499. return(false);
  500. } else {
  501. if (!Check_Game_Settings_File(slave_settings)) {
  502. WWDEBUG_SAY(("Server settings file '%s' not usable\n", slave_settings));
  503. ConsoleBox.Print("Error - server settings file '%s' contains errors - aborting\n", slave_settings);
  504. ConsoleBox.Wait_For_Keypress();;
  505. return(false);
  506. }
  507. }
  508. }
  509. /*
  510. ** Make sure there's a nickname and a serial.
  511. */
  512. ini.Get_String(slave_section, "Nickname", "", slave_nick, sizeof(slave_nick));
  513. if (wol && strlen(slave_nick) == 0) {
  514. WWDEBUG_SAY(("Error - No login nickname specified for slave %d - aborting\n", i+1));
  515. ConsoleBox.Print("Error - No login nickname specified for slave %d - aborting\n", i+1);
  516. ConsoleBox.Wait_For_Keypress();;
  517. return(false);
  518. }
  519. ini.Get_String(slave_section, "Serial", "", slave_serial, sizeof(slave_serial));
  520. if (wol && strlen(slave_serial) == 0) {
  521. WWDEBUG_SAY(("Error - No serial number specified for slave %d - aborting\n", i+1));
  522. ConsoleBox.Print("Error - No serial number specified for slave %d - aborting\n", i+1);
  523. ConsoleBox.Wait_For_Keypress();;
  524. return(false);
  525. }
  526. /*
  527. ** Get the password.
  528. */
  529. ini.Get_String(slave_section, "Password", "", slave_pass, sizeof(slave_pass));
  530. #ifdef FREEDEDICATEDSERVER
  531. if (wol && strlen(slave_pass) == 0) {
  532. WWDEBUG_SAY(("Error - No login password specified for slave %d - aborting\n", i+1));
  533. ConsoleBox.Print("Error - No login password specified for slave %d - aborting\n", i+1);
  534. ConsoleBox.Wait_For_Keypress();;
  535. return(false);
  536. }
  537. #endif //FREEDEDICATEDSERVER
  538. /*
  539. ** Get the port number.
  540. */
  541. slave_port = ini.Get_Int(slave_section, "Port", 0);
  542. if (slave_port < 0 || slave_port > 0xffff) {
  543. WWDEBUG_SAY(("Error - Invalid port number %d specified for slave %d - aborting\n", slave_port, i+1));
  544. ConsoleBox.Print("Error - Invalid port number %d specified for slave %d - aborting\n", slave_port, i+1);
  545. ConsoleBox.Wait_For_Keypress();;
  546. return(false);
  547. }
  548. /*
  549. ** Get the bandwidth allowance.
  550. */
  551. slave_bw = ini.Get_Int(slave_section, "BandwidthUp", 0xffffffff);
  552. if (slave_bw != 0 && slave_bw != 0xffffffff && slave_bw < 33600) {
  553. WWDEBUG_SAY(("Error - Insufficient bandwidth specified for slave %d - aborting\n", i+1));
  554. ConsoleBox.Print("Error - Insufficient bandwidth specified for slave %d - aborting\n", i+1);
  555. ConsoleBox.Wait_For_Keypress();;
  556. return(false);
  557. }
  558. }
  559. /*
  560. ** Apply the settings.
  561. */
  562. if (apply) {
  563. SlaveMaster.Add_Slave(enabled, slave_nick, slave_serial, (unsigned short)slave_port, slave_settings, slave_bw, slave_pass);
  564. }
  565. }
  566. if (apply) {
  567. SlaveMaster.Save();
  568. }
  569. }
  570. return(true);
  571. }
  572. /***********************************************************************************************
  573. * ServerSettingsClass::Encrypt_Serial -- Serial number encryption/decryption *
  574. * *
  575. * *
  576. * *
  577. * INPUT: Input serial number *
  578. * Reference to output serial number *
  579. * Encrypt flag - true to encrypt, false to decrypt *
  580. * *
  581. * OUTPUT: Nothing *
  582. * *
  583. * WARNINGS: None *
  584. * *
  585. * HISTORY: *
  586. * 2/1/2002 12:08PM ST : Created *
  587. *=============================================================================================*/
  588. void ServerSettingsClass::Encrypt_Serial(StringClass serial_in, StringClass &serial_out, bool encrypt)
  589. {
  590. char *s;
  591. int numberlength = serial_in.Get_Length();
  592. unsigned long bytesread;
  593. char stringbuffer[ENCRYPTION_STRING_LENGTH];
  594. int p;
  595. WWASSERT(numberlength);
  596. s = new char [numberlength + 1];
  597. memcpy(s, serial_in.Peek_Buffer(), numberlength + 1);
  598. /*
  599. ** See if the key file is available. If not, don't bother encrypting.
  600. */
  601. HANDLE handle = CreateFile ("woldata.key", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  602. if (handle == INVALID_HANDLE_VALUE) {
  603. delete [] s;
  604. serial_out = serial_in;
  605. return;
  606. }
  607. /*
  608. ** Read the key.
  609. */
  610. if (!ReadFile(handle, stringbuffer, sizeof (stringbuffer), &bytesread, NULL)) {
  611. WWDEBUG_SAY(("Unable to read serial encryption key file\n"));
  612. delete [] s;
  613. serial_out = serial_in;
  614. return;
  615. }
  616. int sign = encrypt ? 1 : -1;
  617. p = 0;
  618. for (unsigned i = 0; i < ENCRYPTION_STRING_LENGTH; i++) {
  619. int t;
  620. char c;
  621. t = s[p] - '0';
  622. t %= 10;
  623. t += (sign * stringbuffer[i]);
  624. t += 1000;
  625. t %= 10;
  626. c = t + '0';
  627. s[p] = c;
  628. p++;
  629. if (p == numberlength) {
  630. p = 0;
  631. }
  632. }
  633. serial_out = StringClass(s, true);
  634. delete [] s;
  635. }
  636. /***********************************************************************************************
  637. * ServerSettingsClass::Decrypt_Serial -- Serial number decryption *
  638. * *
  639. * *
  640. * *
  641. * INPUT: Input serial number *
  642. * Reference to output serial number *
  643. * *
  644. * OUTPUT: Nothing *
  645. * *
  646. * WARNINGS: None *
  647. * *
  648. * HISTORY: *
  649. * 2/1/2002 12:08PM ST : Created *
  650. *=============================================================================================*/
  651. void ServerSettingsClass::Decrypt_Serial(StringClass serial_in, StringClass &serial_out)
  652. {
  653. Encrypt_Serial(serial_in, serial_out, false);
  654. }
  655. /***********************************************************************************************
  656. * ServerSettingsClass::Get_Preferred_Server -- Get the users specified server *
  657. * *
  658. * *
  659. * *
  660. * INPUT: Server list from servserv *
  661. * *
  662. * OUTPUT: Name of preferred server *
  663. * *
  664. * WARNINGS: None *
  665. * *
  666. * HISTORY: *
  667. * 2/1/2002 1:18PM ST : Created *
  668. *=============================================================================================*/
  669. char *ServerSettingsClass::Get_Preferred_Server(const WWOnline::IRCServerList &server_list)
  670. {
  671. if (IsActive && server_list.size()) {
  672. Write_Server_List(server_list);
  673. }
  674. return(PreferredLoginServer);
  675. }
  676. /***********************************************************************************************
  677. * ServerSettingsClass::Write_Server_List -- Write the server list into the settings ini file *
  678. * *
  679. * *
  680. * *
  681. * INPUT: Server list *
  682. * *
  683. * OUTPUT: Nothing *
  684. * *
  685. * WARNINGS: None *
  686. * *
  687. * HISTORY: *
  688. * 2/1/2002 1:19PM ST : Created *
  689. *=============================================================================================*/
  690. void ServerSettingsClass::Write_Server_List(const WWOnline::IRCServerList &server_list)
  691. {
  692. WWASSERT(server_list.size());
  693. WWASSERT(strlen(SettingsFile) != 0);
  694. char temp[256];
  695. if (server_list.size()) {
  696. RawFileClass file(SettingsFile);
  697. /*
  698. ** This is a bit hacky. Basically we just want the .ini file commented with the latest server list.
  699. **
  700. ** We will do this by reading in the file, looking for a tag that tells us where to write the server list, then writing
  701. ** the file back out with the server list in place.
  702. */
  703. if (file.Is_Available()) {
  704. unsigned long size = file.Size();
  705. if (size) {
  706. /*
  707. ** Read the file.
  708. */
  709. char *file_buffer = new char[size + 8192];
  710. #ifdef WWDEBUG
  711. unsigned long read_size =
  712. #endif //WWDEBUG
  713. file.Read(file_buffer, size);
  714. WWASSERT(read_size == size);
  715. file.Close();
  716. /*
  717. ** Find the placeholder tag.
  718. */
  719. char *tag = strstr(file_buffer, ServerListTag);
  720. char *end_tag = strstr(file_buffer, ServerListEnd);
  721. if (tag && end_tag) {
  722. /*
  723. ** Write out the first portion of the file unchanged.
  724. */
  725. file.Open(FileClass::WRITE);
  726. file.Write(file_buffer, (tag - file_buffer) + strlen(ServerListTag));
  727. /*
  728. ** Insert the server list.
  729. */
  730. char *server_list_text = new char [8192];
  731. strcpy(server_list_text, "\r\n;\r\n");
  732. for (unsigned int i = 0; i < server_list.size(); i++) {
  733. const RefPtr<WWOnline::IRCServerData> &server = server_list[i];
  734. if (server->HasLanguageCode()) {
  735. const char *server_name = server->GetName();
  736. sprintf(temp, "; %s\r\n", server_name);
  737. strcat(server_list_text, temp);
  738. }
  739. }
  740. strcat(server_list_text, ";\r\n");
  741. file.Write(server_list_text, strlen(server_list_text));
  742. /*
  743. ** Write out the post server list sections of the original file.
  744. */
  745. file.Write(end_tag, (file_buffer + size) - end_tag);
  746. file.Close();
  747. }
  748. }
  749. }
  750. }
  751. }
  752. /***********************************************************************************************
  753. * ServerSettingsClass::Check_Game_Settings_File -- Check game settings for validity *
  754. * *
  755. * *
  756. * *
  757. * INPUT: Game settings .ini file name *
  758. * *
  759. * OUTPUT: True if valid. *
  760. * *
  761. * WARNINGS: None *
  762. * *
  763. * HISTORY: *
  764. * 2/3/2002 9:37PM ST : Created *
  765. *=============================================================================================*/
  766. bool ServerSettingsClass::Check_Game_Settings_File(char *config_file)
  767. {
  768. cGameDataCnc *game_settings = (cGameDataCnc*) cGameData::Create_Game_Of_Type(cGameData::GAME_TYPE_CNC);
  769. WWASSERT(game_settings != NULL);
  770. if (game_settings) {
  771. game_settings->Set_Ini_Filename(config_file);
  772. game_settings->Load_From_Server_Config();
  773. WideStringClass outMsg;
  774. bool ok = game_settings->Is_Valid_Settings(outMsg, true);
  775. delete game_settings;
  776. return(ok);
  777. }
  778. return(false);
  779. }