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; }
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 ---"); }