int main(int argc, char ** argv) { // Initialize logging subsystem: auto consoleLogListener = MakeConsoleListener(false); auto consoleAttachment = cLogger::GetInstance().AttachListener(std::move(consoleLogListener)); auto fileLogListenerRet = MakeFileListener(); if (!fileLogListenerRet.first) { LOGERROR("Failed to open log file, aborting"); return EXIT_FAILURE; } auto fileAttachment = cLogger::GetInstance().AttachListener(std::move(fileLogListenerRet.second)); cLogger::InitiateMultithreading(); int ListenPort = (argc > 1) ? atoi(argv[1]) : 25564; int ConnectPort = (argc > 2) ? atoi(argv[2]) : 25565; printf("Initializing ProtoProxy. Listen port %d, connect port %d.\n", ListenPort, ConnectPort); cServer Server; int res = Server.Init(ListenPort, ConnectPort); if (res != 0) { printf("Server initialization failed: %d", res); return res; } Server.Run(); return 0; }
int main(int argc, char ** argv) { // Initialize logging subsystem: auto consoleLogListener = MakeConsoleListener(false); auto consoleAttachment = cLogger::GetInstance().AttachListener(std::move(consoleLogListener)); auto fileLogListenerRet = MakeFileListener(); if (!fileLogListenerRet.first) { LOGERROR("Failed to open log file, aborting"); return EXIT_FAILURE; } auto fileAttachment = cLogger::GetInstance().AttachListener(std::move(fileLogListenerRet.second)); cLogger::InitiateMultithreading(); UInt16 ListenPort = 25564; UInt16 ConnectPort = 25565; if (argc > 1) { if (!StringToInteger(argv[1], ListenPort)) { LOGERROR("Invalid argument 1, expected port number, got \"%s\". Aborting.", argv[1]); return 1; } if (argc > 2) { if (!StringToInteger(argv[2], ConnectPort)) { LOGERROR("Invalid argument 2, expected port number, got \"%s\". Aborting.", argv[2]); return 2; } } } cServer Server; int res = Server.Init(ListenPort, ConnectPort); if (res != 0) { LOGERROR("Server initialization failed: %d", res); return res; } Server.Run(); return 0; }
int main(int argc, char ** argv) { // Initialize logging subsystem: cLogger::InitiateMultithreading(); auto consoleLogListener = MakeConsoleListener(false); auto fileLogListener = new cFileListener(); cLogger::GetInstance().AttachListener(consoleLogListener); cLogger::GetInstance().AttachListener(fileLogListener); int ListenPort = (argc > 1) ? atoi(argv[1]) : 25564; int ConnectPort = (argc > 2) ? atoi(argv[2]) : 25565; printf("Initializing ProtoProxy. Listen port %d, connect port %d.\n", ListenPort, ConnectPort); cServer Server; int res = Server.Init(ListenPort, ConnectPort); if (res != 0) { printf("Server initialization failed: %d", res); return res; } Server.Run(); return 0; }
void cRoot::Start(std::unique_ptr<cSettingsRepositoryInterface> overridesRepo) { #ifdef _WIN32 HWND hwnd = GetConsoleWindow(); HMENU hmenu = GetSystemMenu(hwnd, FALSE); EnableMenuItem(hmenu, SC_CLOSE, MF_GRAYED); // Disable close button when starting up; it causes problems with our CTRL-CLOSE handling #endif cLogger::cListener * consoleLogListener = MakeConsoleListener(); cLogger::cListener * fileLogListener = new cFileListener(); cLogger::GetInstance().AttachListener(consoleLogListener); cLogger::GetInstance().AttachListener(fileLogListener); LOG("--- Started Log ---\n"); #ifdef BUILD_ID LOG("MCServer " BUILD_SERIES_NAME " build id: " BUILD_ID); LOG("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME); #endif cDeadlockDetect dd; m_ShouldStop = false; while (!m_ShouldStop) { auto BeginTime = std::chrono::steady_clock::now(); m_bRestart = false; LoadGlobalSettings(); LOG("Creating new server instance..."); m_Server = new cServer(); LOG("Reading server config..."); auto IniFile = cpp14::make_unique<cIniFile>(); if (!IniFile->ReadFile("settings.ini")) { LOGWARN("Regenerating settings.ini, all settings will be reset"); IniFile->AddHeaderComment(" This is the main server configuration"); IniFile->AddHeaderComment(" Most of the settings here can be configured using the webadmin interface, if enabled in webadmin.ini"); IniFile->AddHeaderComment(" See: http://wiki.mc-server.org/doku.php?id=configure:settings.ini for further configuration help"); } auto settingsRepo = cpp14::make_unique<cOverridesSettingsRepository>(std::move(IniFile), std::move(overridesRepo)); LOG("Starting server..."); m_MojangAPI = new cMojangAPI; bool ShouldAuthenticate = settingsRepo->GetValueSetB("Authentication", "Authenticate", true); m_MojangAPI->Start(*settingsRepo, ShouldAuthenticate); // Mojang API needs to be started before plugins, so that plugins may use it for DB upgrades on server init if (!m_Server->InitServer(*settingsRepo, ShouldAuthenticate)) { settingsRepo->Flush(); LOGERROR("Failure starting server, aborting..."); return; } m_WebAdmin = new cWebAdmin(); m_WebAdmin->Init(); LOGD("Loading settings..."); m_RankManager.reset(new cRankManager()); m_RankManager->Initialize(*m_MojangAPI); m_CraftingRecipes = new cCraftingRecipes; m_FurnaceRecipe = new cFurnaceRecipe(); LOGD("Loading worlds..."); LoadWorlds(*settingsRepo); LOGD("Loading plugin manager..."); m_PluginManager = new cPluginManager(); m_PluginManager->ReloadPluginsNow(*settingsRepo); LOGD("Loading MonsterConfig..."); m_MonsterConfig = new cMonsterConfig; // This sets stuff in motion LOGD("Starting Authenticator..."); m_Authenticator.Start(*settingsRepo); LOGD("Starting worlds..."); StartWorlds(); if (settingsRepo->GetValueSetB("DeadlockDetect", "Enabled", true)) { LOGD("Starting deadlock detector..."); dd.Start(settingsRepo->GetValueSetI("DeadlockDetect", "IntervalSec", 20)); } settingsRepo->Flush(); LOGD("Finalising startup..."); if (m_Server->Start()) { m_WebAdmin->Start(); #if !defined(ANDROID_NDK) LOGD("Starting InputThread..."); try { m_InputThread = std::thread(InputThread, std::ref(*this)); m_InputThread.detach(); } catch (std::system_error & a_Exception) { LOGERROR("cRoot::Start (std::thread) error %i: could not construct input thread; %s", a_Exception.code().value(), a_Exception.what()); } #endif LOG("Startup complete, took %ldms!", static_cast<long int>(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - BeginTime).count())); // Save the current time m_StartTime = std::chrono::steady_clock::now(); #ifdef _WIN32 EnableMenuItem(hmenu, SC_CLOSE, MF_ENABLED); // Re-enable close button #endif while (!m_ShouldStop && !m_bRestart && !m_TerminateEventRaised) // These are modified by external threads { std::this_thread::sleep_for(std::chrono::seconds(1)); } if (m_TerminateEventRaised) { m_ShouldStop = true; } // Stop the server: m_WebAdmin->Stop(); LOG("Shutting down server..."); m_Server->Shutdown(); } // if (m_Server->Start()) else { m_ShouldStop = true; } delete m_MojangAPI; m_MojangAPI = nullptr; LOGD("Shutting down deadlock detector..."); dd.Stop(); LOGD("Stopping world threads..."); StopWorlds(); LOGD("Stopping authenticator..."); m_Authenticator.Stop(); LOGD("Freeing MonsterConfig..."); delete m_MonsterConfig; m_MonsterConfig = nullptr; delete m_WebAdmin; m_WebAdmin = nullptr; LOGD("Unloading recipes..."); delete m_FurnaceRecipe; m_FurnaceRecipe = nullptr; delete m_CraftingRecipes; m_CraftingRecipes = nullptr; LOGD("Unloading worlds..."); UnloadWorlds(); LOGD("Stopping plugin manager..."); delete m_PluginManager; m_PluginManager = nullptr; cItemHandler::Deinit(); LOG("Cleaning up..."); delete m_Server; m_Server = nullptr; LOG("Shutdown successful!"); } LOG("--- Stopped Log ---"); cLogger::GetInstance().DetachListener(consoleLogListener); delete consoleLogListener; cLogger::GetInstance().DetachListener(fileLogListener); delete fileLogListener; }
void cRoot::Start(std::unique_ptr<cSettingsRepositoryInterface> a_OverridesRepo) { #ifdef _WIN32 HMENU ConsoleMenu = GetSystemMenu(GetConsoleWindow(), FALSE); EnableMenuItem(ConsoleMenu, SC_CLOSE, MF_GRAYED); // Disable close button when starting up; it causes problems with our CTRL-CLOSE handling #endif auto consoleLogListener = MakeConsoleListener(m_RunAsService); auto consoleAttachment = cLogger::GetInstance().AttachListener(std::move(consoleLogListener)); auto fileLogListenerRet = MakeFileListener(); if (!fileLogListenerRet.first) { LOGERROR("Failed to open log file, aborting"); return; } auto fileAttachment = cLogger::GetInstance().AttachListener(std::move(fileLogListenerRet.second)); LOG("--- Started Log ---"); #ifdef BUILD_ID LOG("Cuberite " BUILD_SERIES_NAME " build id: " BUILD_ID); LOG("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME); #endif // Run the self-tests registered previously via cSelfTests::Register(): #ifdef SELF_TEST cSelfTests::ExecuteAll(); #endif cDeadlockDetect dd; auto BeginTime = std::chrono::steady_clock::now(); LoadGlobalSettings(); LOG("Creating new server instance..."); m_Server = new cServer(); LOG("Reading server config..."); auto IniFile = cpp14::make_unique<cIniFile>(); bool IsNewIniFile = !IniFile->ReadFile("settings.ini"); if (IsNewIniFile) { LOGWARN("Regenerating settings.ini, all settings will be reset"); IniFile->AddHeaderComment(" This is the main server configuration"); IniFile->AddHeaderComment(" Most of the settings here can be configured using the webadmin interface, if enabled in webadmin.ini"); } auto settingsRepo = cpp14::make_unique<cOverridesSettingsRepository>(std::move(IniFile), std::move(a_OverridesRepo)); LOG("Starting server..."); m_MojangAPI = new cMojangAPI; bool ShouldAuthenticate = settingsRepo->GetValueSetB("Authentication", "Authenticate", true); m_MojangAPI->Start(*settingsRepo, ShouldAuthenticate); // Mojang API needs to be started before plugins, so that plugins may use it for DB upgrades on server init if (!m_Server->InitServer(*settingsRepo, ShouldAuthenticate)) { settingsRepo->Flush(); LOGERROR("Failure starting server, aborting..."); return; } m_WebAdmin = new cWebAdmin(); m_WebAdmin->Init(); LOGD("Loading settings..."); m_RankManager.reset(new cRankManager()); m_RankManager->Initialize(*m_MojangAPI); m_CraftingRecipes = new cCraftingRecipes(); m_FurnaceRecipe = new cFurnaceRecipe(); m_BrewingRecipes.reset(new cBrewingRecipes()); LOGD("Loading worlds..."); LoadWorlds(*settingsRepo, IsNewIniFile); LOGD("Loading plugin manager..."); m_PluginManager = new cPluginManager(); m_PluginManager->ReloadPluginsNow(*settingsRepo); LOGD("Loading MonsterConfig..."); m_MonsterConfig = new cMonsterConfig; // This sets stuff in motion LOGD("Starting Authenticator..."); m_Authenticator.Start(*settingsRepo); LOGD("Starting worlds..."); StartWorlds(); if (settingsRepo->GetValueSetB("DeadlockDetect", "Enabled", true)) { LOGD("Starting deadlock detector..."); dd.Start(settingsRepo->GetValueSetI("DeadlockDetect", "IntervalSec", 20)); } settingsRepo->Flush(); LOGD("Finalising startup..."); if (m_Server->Start()) { m_WebAdmin->Start(); #if !defined(ANDROID_NDK) LOGD("Starting InputThread..."); try { m_InputThreadRunFlag.test_and_set(); m_InputThread = std::thread(InputThread, std::ref(*this)); } catch (std::system_error & a_Exception) { LOGERROR("cRoot::Start (std::thread) error %i: could not construct input thread; %s", a_Exception.code().value(), a_Exception.what()); } #endif LOG("Startup complete, took %ldms!", static_cast<long int>(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - BeginTime).count())); // Save the current time m_StartTime = std::chrono::steady_clock::now(); #ifdef _WIN32 EnableMenuItem(ConsoleMenu, SC_CLOSE, MF_ENABLED); // Re-enable close button #endif for (;;) { m_StopEvent.Wait(); break; } // Stop the server: m_WebAdmin->Stop(); LOG("Shutting down server..."); m_Server->Shutdown(); } // if (m_Server->Start() delete m_MojangAPI; m_MojangAPI = nullptr; LOGD("Shutting down deadlock detector..."); dd.Stop(); LOGD("Stopping world threads..."); StopWorlds(); LOGD("Stopping authenticator..."); m_Authenticator.Stop(); LOGD("Freeing MonsterConfig..."); delete m_MonsterConfig; m_MonsterConfig = nullptr; delete m_WebAdmin; m_WebAdmin = nullptr; LOGD("Unloading recipes..."); delete m_FurnaceRecipe; m_FurnaceRecipe = nullptr; delete m_CraftingRecipes; m_CraftingRecipes = nullptr; LOG("Unloading worlds..."); UnloadWorlds(); LOGD("Stopping plugin manager..."); delete m_PluginManager; m_PluginManager = nullptr; cItemHandler::Deinit(); LOG("Cleaning up..."); delete m_Server; m_Server = nullptr; m_InputThreadRunFlag.clear(); #ifdef _WIN32 DWORD Length; INPUT_RECORD Record { KEY_EVENT, { { TRUE, 1, VK_RETURN, static_cast<WORD>(MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC)), { { VK_RETURN } }, 0 } } }; // Can't kill the input thread since it breaks cin (getline doesn't block / receive input on restart) // Apparently no way to unblock getline // Only thing I can think of for now if (WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &Record, 1, &Length) == 0) { LOGWARN("Couldn't notify the input thread; the server will hang before shutdown!"); m_TerminateEventRaised = true; m_InputThread.detach(); } else { m_InputThread.join(); } #else if (pthread_kill(m_InputThread.native_handle(), SIGKILL) != 0) { LOGWARN("Couldn't notify the input thread; the server will hang before shutdown!"); m_TerminateEventRaised = true; m_InputThread.detach(); } #endif if (m_TerminateEventRaised) { LOG("Shutdown successful!"); } else { LOG("Shutdown successful - restarting..."); } LOG("--- Stopped Log ---"); }
void cRoot::Start(void) { #ifdef _WIN32 HWND hwnd = GetConsoleWindow(); HMENU hmenu = GetSystemMenu(hwnd, FALSE); EnableMenuItem(hmenu, SC_CLOSE, MF_GRAYED); // Disable close button when starting up; it causes problems with our CTRL-CLOSE handling #endif cLogger::cListener * consoleLogListener = MakeConsoleListener(); cLogger::cListener * fileLogListener = new cFileListener(); cLogger::GetInstance().AttachListener(consoleLogListener); cLogger::GetInstance().AttachListener(fileLogListener); LOG("--- Started Log ---\n"); #ifdef BUILD_ID LOG("MCServer " BUILD_SERIES_NAME " build id: " BUILD_ID ); LOG("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME ); #endif cDeadlockDetect dd; m_bStop = false; while (!m_bStop) { cTimer Time; long long mseconds = Time.GetNowTime(); m_bRestart = false; LoadGlobalSettings(); LOG("Creating new server instance..."); m_Server = new cServer(); LOG("Reading server config..."); cIniFile IniFile; if (!IniFile.ReadFile("settings.ini")) { LOGWARN("Regenerating settings.ini, all settings will be reset"); IniFile.AddHeaderComment(" This is the main server configuration"); IniFile.AddHeaderComment(" Most of the settings here can be configured using the webadmin interface, if enabled in webadmin.ini"); IniFile.AddHeaderComment(" See: http://wiki.mc-server.org/doku.php?id=configure:settings.ini for further configuration help"); } m_PrimaryServerVersion = IniFile.GetValueI("Server", "PrimaryServerVersion", 0); if (m_PrimaryServerVersion == 0) { m_PrimaryServerVersion = cProtocolRecognizer::PROTO_VERSION_LATEST; } else { // Make a note in the log that the primary server version is explicitly set in the ini file LOGINFO("Primary server version set explicitly to %d.", m_PrimaryServerVersion); } LOG("Starting server..."); m_MojangAPI.Start(IniFile); // Mojang API needs to be started before plugins, so that plugins may use it for DB upgrades on server init if (!m_Server->InitServer(IniFile)) { IniFile.WriteFile("settings.ini"); LOGERROR("Failure starting server, aborting..."); return; } m_WebAdmin = new cWebAdmin(); m_WebAdmin->Init(); LOGD("Loading settings..."); m_RankManager.Initialize(m_MojangAPI); m_CraftingRecipes = new cCraftingRecipes; m_FurnaceRecipe = new cFurnaceRecipe(); LOGD("Loading worlds..."); LoadWorlds(IniFile); LOGD("Loading plugin manager..."); m_PluginManager = new cPluginManager(); m_PluginManager->ReloadPluginsNow(IniFile); LOGD("Loading MonsterConfig..."); m_MonsterConfig = new cMonsterConfig; // This sets stuff in motion LOGD("Starting Authenticator..."); m_Authenticator.Start(IniFile); LOGD("Starting worlds..."); StartWorlds(); if (IniFile.GetValueSetB("DeadlockDetect", "Enabled", true)) { LOGD("Starting deadlock detector..."); dd.Start(IniFile.GetValueSetI("DeadlockDetect", "IntervalSec", 20)); } IniFile.WriteFile("settings.ini"); LOGD("Finalising startup..."); m_Server->Start(); m_WebAdmin->Start(); #if !defined(ANDROID_NDK) LOGD("Starting InputThread..."); m_InputThread = new cThread( InputThread, this, "cRoot::InputThread"); m_InputThread->Start( false); // We should NOT wait? Otherwise we can't stop the server from other threads than the input thread #endif long long finishmseconds = Time.GetNowTime(); finishmseconds -= mseconds; LOG("Startup complete, took %lld ms!", finishmseconds); #ifdef _WIN32 EnableMenuItem(hmenu, SC_CLOSE, MF_ENABLED); // Re-enable close button #endif while (!m_bStop && !m_bRestart && !m_TerminateEventRaised) // These are modified by external threads { cSleep::MilliSleep(1000); } if (m_TerminateEventRaised) { m_bStop = true; } #if !defined(ANDROID_NDK) delete m_InputThread; m_InputThread = NULL; #endif // Stop the server: m_WebAdmin->Stop(); LOG("Shutting down server..."); m_Server->Shutdown(); LOGD("Shutting down deadlock detector..."); dd.Stop(); LOGD("Stopping world threads..."); StopWorlds(); LOGD("Stopping authenticator..."); m_Authenticator.Stop(); LOGD("Freeing MonsterConfig..."); delete m_MonsterConfig; m_MonsterConfig = NULL; delete m_WebAdmin; m_WebAdmin = NULL; LOGD("Unloading recipes..."); delete m_FurnaceRecipe; m_FurnaceRecipe = NULL; delete m_CraftingRecipes; m_CraftingRecipes = NULL; LOGD("Unloading worlds..."); UnloadWorlds(); LOGD("Stopping plugin manager..."); delete m_PluginManager; m_PluginManager = NULL; cItemHandler::Deinit(); LOG("Cleaning up..."); delete m_Server; m_Server = NULL; LOG("Shutdown successful!"); } LOG("--- Stopped Log ---"); cLogger::GetInstance().DetachListener(consoleLogListener); delete consoleLogListener; cLogger::GetInstance().DetachListener(fileLogListener); delete fileLogListener; }