Example #1
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();

	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;
}
Example #2
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;
}
Example #3
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 ---");
}