Beispiel #1
0
Database* _Database::getInstance()
{
	if(!_instance)
	{
#if defined MULTI_SQL_DRIVERS
#ifdef __USE_MYSQL__
		if(g_config.getString(ConfigManager::SQL_TYPE) == "mysql")
			_instance = new DatabaseMySQL;
#endif
#ifdef __USE_ODBC__
		if(g_config.getString(ConfigManager::SQL_TYPE) == "odbc")
			_instance = new DatabaseODBC;
#endif
#ifdef __USE_SQLITE__
		if(g_config.getString(ConfigManager::SQL_TYPE) == "sqlite")
			_instance = new DatabaseSQLite;
#endif
#ifdef __USE_PGSQL__
		if(g_config.getString(ConfigManager::SQL_TYPE) == "pgsql")
			_instance = new DatabasePgSQL;
#endif
#else
		_instance = new Database;
#endif

		OTSYS_THREAD_LOCKVARINIT(DBQuery::databaseLock);
	}

	_instance->use();
	return _instance;
}
Beispiel #2
0
void ProtocolLogin::getCharacterList(const std::string& accountName, const std::string& password, uint16_t version)
{
	Account account;
	if (!IOLoginData::loginserverAuthentication(accountName, password, account)) {
		disconnectClient("Account name or password is not correct.", version);
		return;
	}

	auto output = OutputMessagePool::getOutputMessage();
	//Update premium days
	Game::updatePremium(account);

	const std::string& motd = g_config.getString(ConfigManager::MOTD);
	if (!motd.empty()) {
		//Add MOTD
		output->addByte(0x14);

		std::ostringstream ss;
		ss << g_game.getMotdNum() << "\n" << motd;
		output->addString(ss.str());
	}

	//Add session key
	output->addByte(0x28);
	output->addString(accountName + "\n" + password);

	//Add char list
	output->addByte(0x64);

	output->addByte(1); // number of worlds

	output->addByte(0); // world id
	output->addString(g_config.getString(ConfigManager::SERVER_NAME));
	output->addString(g_config.getString(ConfigManager::IP));
	output->add<uint16_t>(g_config.getNumber(ConfigManager::GAME_PORT));
	output->addByte(0);

	uint8_t size = std::min<size_t>(std::numeric_limits<uint8_t>::max(), account.characters.size());
	output->addByte(size);
	for (uint8_t i = 0; i < size; i++) {
		output->addByte(0);
		output->addString(account.characters[i]);
	}

	// Add premium days
	if (version >= 1080) {
		output->addByte((g_config.getBoolean(ConfigManager::FREE_PREMIUM)) ? 0x01 : 0x00);
		auto time = std::chrono::system_clock::now() + std::chrono::hours(account.premiumDays * 24);
		std::chrono::seconds timestamp = std::chrono::duration_cast<std::chrono::seconds>(time.time_since_epoch());
		output->add<uint32_t>(g_config.getBoolean(ConfigManager::FREE_PREMIUM) ? 0 : timestamp.count());
	} else {
		output->add<uint16_t>(g_config.getBoolean(ConfigManager::FREE_PREMIUM) ? 0xFFFF : account.premiumDays);
	}

	send(output);

	disconnect();
}
Beispiel #3
0
int main(int argc, char* argv[])
{
	StringVec args = StringVec(argv, argv + argc);
	if(argc > 1 && !argumentsHandler(args))
		return 0;

	std::set_new_handler(allocationHandler);
	ServiceManager servicer;
	g_config.startup();

#ifdef __OTSERV_ALLOCATOR_STATS__
	boost::thread(boost::bind(&allocatorStatsThread, (void*)NULL));
	// TODO: shutdown this thread?
#endif
#ifdef __EXCEPTION_TRACER__
	ExceptionHandler mainExceptionHandler;
	mainExceptionHandler.InstallHandler();
#endif
#ifndef WINDOWS

	// ignore sigpipe...
	struct sigaction sigh;
	sigh.sa_handler = SIG_IGN;
	sigh.sa_flags = 0;

	sigemptyset(&sigh.sa_mask);
	sigaction(SIGPIPE, &sigh, NULL);

	// register signals
	signal(SIGHUP, signalHandler); //save
	signal(SIGTRAP, signalHandler); //clean
	signal(SIGCHLD, signalHandler); //refresh
	signal(SIGUSR1, signalHandler); //close server
	signal(SIGUSR2, signalHandler); //open server
	signal(SIGCONT, signalHandler); //reload all
	signal(SIGQUIT, signalHandler); //save & shutdown
	signal(SIGTERM, signalHandler); //shutdown
#endif

	OutputHandler::getInstance();
	Dispatcher::getInstance().addTask(createTask(boost::bind(otserv, args, &servicer)));

	g_loaderSignal.wait(g_loaderUniqueLock);
	if(servicer.isRunning())
	{
		std::clog << ">> " << g_config.getString(ConfigManager::SERVER_NAME) << " server Online!" << std::endl << std::endl;
		servicer.run();
	}
	else
		std::clog << ">> " << g_config.getString(ConfigManager::SERVER_NAME) << " server Offline! No services available..." << std::endl << std::endl;

#ifdef __EXCEPTION_TRACER__
	mainExceptionHandler.RemoveHandler();
#endif
	return 0;
}
Beispiel #4
0
DatabaseODBC::DatabaseODBC()
{
	m_connected = false;

	char* dns = new char[SQL_MAX_DSN_LENGTH];
	char* user = new char[32];
	char* pass = new char[32];

	strcpy((char*)dns, g_config.getString(ConfigManager::SQL_DB).c_str());
	strcpy((char*)user, g_config.getString(ConfigManager::SQL_USER).c_str());
	strcpy((char*)pass, g_config.getString(ConfigManager::SQL_PASS).c_str());

	SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_env);
	if(!RETURN_SUCCESS(ret)){
		std::cout << "Failed to allocate ODBC SQLHENV enviroment handle." << std::endl;
		m_env = NULL;
		return;
	}

	ret = SQLSetEnvAttr(m_env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
	if(!RETURN_SUCCESS(ret)){
		std::cout << "SQLSetEnvAttr(SQL_ATTR_ODBC_VERSION): Failed to switch to ODBC 3 version." << std::endl;
		SQLFreeHandle(SQL_HANDLE_ENV, m_env);
		m_env = NULL;
	}

	if(m_env == NULL){
		std::cout << "ODBC SQLHENV enviroment not initialized." << std::endl;
		return;
	}

	ret = SQLAllocHandle(SQL_HANDLE_DBC, m_env, &m_handle);
	if(!RETURN_SUCCESS(ret)){
		std::cout << "Failed to allocate ODBC SQLHDBC connection handle." << std::endl;
		m_handle = NULL;
		return;
	}

	ret = SQLSetConnectAttr(m_handle, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER*)5, 0);
	if(!RETURN_SUCCESS(ret)){
		std::cout << "SQLSetConnectAttr(SQL_ATTR_CONNECTION_TIMEOUT): Failed to set connection timeout." << std::endl;
		SQLFreeHandle(SQL_HANDLE_DBC, m_handle);
		m_handle = NULL;
		return;
	}

	ret = SQLConnect(m_handle, (SQLCHAR*)dns, SQL_NTS, (SQLCHAR*)user, SQL_NTS, (SQLCHAR*)pass, SQL_NTS);
	if(!RETURN_SUCCESS(ret)){
		std::cout << "Failed to connect to ODBC via DSN: " << dns << " (user " << user << ")" << std::endl;
		SQLFreeHandle(SQL_HANDLE_DBC, m_handle);
		m_handle = NULL;
		return;
	}

	m_connected = true;
}
DatabasePgSQL::DatabasePgSQL()
{
	std::stringstream dns;
	dns << "host='" << g_config.getString(ConfigManager::SQL_HOST) << "' dbname='" << g_config.getString(ConfigManager::SQL_DB) << "' user='******' password='******' port='" << g_config.getNumber(ConfigManager::SQL_PORT) << "'";

	m_handle = PQconnectdb(dns.str().c_str());
	m_connected = PQstatus(m_handle) == CONNECTION_OK;
	if(!m_connected)
		std::cout << "Failed to estabilish PostgreSQL database connection: " << PQerrorMessage(m_handle) << std::endl;
}
Beispiel #6
0
void ProtocolLogin::getCharacterList(const std::string& accountName, const std::string& password, uint16_t version)
{
	Account account;
	if (!IOLoginData::loginserverAuthentication(accountName, password, account)) {
		disconnectClient("Account name or password is not correct.", version);
		return;
	}

	OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
	if (output) {
		//Update premium days
		Game::updatePremium(account);

		//Add MOTD
		output->addByte(0x14);

		std::ostringstream ss;
		ss << g_game.getMotdNum() << "\n" << g_config.getString(ConfigManager::MOTD);
		output->addString(ss.str());

		//Add session key
		output->addByte(0x28);
		output->addString(accountName + "\n" + password);

		//Add char list
		output->addByte(0x64);

		output->addByte(1); // number of worlds

		output->addByte(0); // world id
		output->addString(g_config.getString(ConfigManager::SERVER_NAME));
		output->addString(g_config.getString(ConfigManager::IP));
		output->add<uint16_t>(g_config.getNumber(ConfigManager::GAME_PORT));
		output->addByte(0);

		uint8_t size = std::min<size_t>(std::numeric_limits<uint8_t>::max(), account.characters.size());
		output->addByte(size);
		for (uint8_t i = 0; i < size; i++) {
			output->addByte(0);
			output->addString(account.characters[i]);
		}

		//Add premium days
		if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) {
			output->add<uint16_t>(0xFFFF);    //client displays free premium
		} else {
			output->add<uint16_t>(account.premiumDays);
		}

		OutputMessagePool::getInstance()->send(output);
	}

	getConnection()->close();
}
Beispiel #7
0
DatabaseMySQL::DatabaseMySQL() :
	m_timeoutTask(0)
{
	m_connected = false;
	if(!mysql_init(&m_handle))
	{
		std::clog << std::endl << "Failed to initialize MySQL connection handler." << std::endl;
		return;
	}

	uint32_t timeout = g_config.getNumber(ConfigManager::MYSQL_READ_TIMEOUT);
	if(timeout)
		mysql_options(&m_handle, MYSQL_OPT_READ_TIMEOUT, (const char*)&timeout);

	timeout = g_config.getNumber(ConfigManager::MYSQL_WRITE_TIMEOUT);
	if(timeout)
		mysql_options(&m_handle, MYSQL_OPT_WRITE_TIMEOUT, (const char*)&timeout);

	my_bool reconnect = true;
	mysql_options(&m_handle, MYSQL_OPT_RECONNECT, &reconnect);
	if(!mysql_real_connect(&m_handle, g_config.getString(ConfigManager::SQL_HOST).c_str(), g_config.getString(
		ConfigManager::SQL_USER).c_str(), g_config.getString(ConfigManager::SQL_PASS).c_str(), g_config.getString(
		ConfigManager::SQL_DB).c_str(), g_config.getNumber(ConfigManager::SQL_PORT), NULL, 0))
	{
		std::clog << "Failed connecting to database - MYSQL ERROR: " << mysql_error(&m_handle) << " (" << mysql_errno(&m_handle) << ")" << std::endl;
		return;
	}

	m_connected = true;
	if(mysql_get_client_version() <= 50019)
		//MySQL servers <= 5.0.19 have a bug where MYSQL_OPT_RECONNECT option is reset by mysql_real_connect calls.
		//Read this http://dev.mysql.com/doc/refman/5.0/en/mysql-options.html for more information.
		std::clog << std::endl << "> WARNING: Outdated MySQL server detected, consider upgrading to a newer version." << std::endl;

	timeout = g_config.getNumber(ConfigManager::SQL_KEEPALIVE) * 1000;
	if(timeout)
		m_timeoutTask = Scheduler::getInstance().addEvent(createSchedulerTask(timeout,
			boost::bind(&DatabaseMySQL::keepAlive, this)));

	if(!g_config.getBool(ConfigManager::HOUSE_STORAGE))
		return;

	//we cannot lock mutex here :)
	DBResult* result = storeQuery("SHOW variables LIKE 'max_allowed_packet';");
	if(!result)
		return;

	if(result->getDataLong("Value") < 16776192)
		std::clog << std::endl << "> WARNING: max_allowed_packet might be set too low for binary map storage." << std::endl
			<< "Use the following query to raise max_allow_packet: SET GLOBAL max_allowed_packet = 16776192;" << std::endl;

	result->free();
}
Beispiel #8
0
void ProtocolLogin::getCharacterList(uint32_t accountName, const std::string& password)
{
	uint32_t serverIp = serverIPs[0].first;
	for (uint32_t i = 0; i < serverIPs.size(); i++) {
		if ((serverIPs[i].first & serverIPs[i].second) == (getConnection()->getIP() & serverIPs[i].second)) {
			serverIp = serverIPs[i].first;
			break;
		}
	}

	Account account;
	if (!IOLoginData::loginserverAuthentication(accountName, password, account)) {
		disconnectClient("Account name or password is not correct.");
		return;
	}

	auto output = OutputMessagePool::getOutputMessage();
	//Update premium days
	Game::updatePremium(account);

	const std::string& motd = g_config.getString(ConfigManager::MOTD);
	if (!motd.empty()) {
		//Add MOTD
		output->addByte(0x14);

		std::ostringstream ss;
		ss << g_game.getMotdNum() << "\n" << motd;
		output->addString(ss.str());
	}

	//Add char list
	output->addByte(0x64);

	uint8_t size = std::min<size_t>(std::numeric_limits<uint8_t>::max(), account.characters.size());
	output->addByte(size);
	for (uint8_t i = 0; i < size; i++) {
		output->addString(account.characters[i]);
		output->addString(g_config.getString(ConfigManager::SERVER_NAME));
		output->add<uint32_t>(serverIp);
		output->add<uint16_t>(g_config.getNumber(ConfigManager::GAME_PORT));
	}

	//Add premium days
	if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) {
		output->add<uint16_t>(0xFFFF); //client displays free premium
	} else {
		output->add<uint16_t>(account.premiumDays);
	}

	send(output);

	disconnect();
}
DatabaseMySQL::DatabaseMySQL()
{
	m_connected = false;

	// connection handle initialization
	if(!mysql_init(&m_handle))
	{
		std::cout << std::endl << "Failed to initialize MySQL connection handle." << std::endl;
		return;
	}

	// automatic reconnect
	my_bool reconnect = true;
	mysql_options(&m_handle, MYSQL_OPT_RECONNECT, &reconnect);

	// connects to database
	if(!mysql_real_connect(&m_handle, g_config.getString(ConfigManager::MYSQL_HOST).c_str(), g_config.getString(ConfigManager::MYSQL_USER).c_str(), g_config.getString(ConfigManager::MYSQL_PASS).c_str(), g_config.getString(ConfigManager::MYSQL_DB).c_str(), g_config.getNumber(ConfigManager::SQL_PORT), NULL, 0))
	{
		std::cout << "Failed to connect to database. MYSQL ERROR: " << mysql_error(&m_handle) << std::endl;
		return;
	}

	if(MYSQL_VERSION_ID < 50019)
	{
		//mySQL servers < 5.0.19 has a bug where MYSQL_OPT_RECONNECT is (incorrectly) reset by mysql_real_connect calls
		//See http://dev.mysql.com/doc/refman/5.0/en/mysql-options.html for more information.
		mysql_options(&m_handle, MYSQL_OPT_RECONNECT, &reconnect);
		std::cout << std::endl << "[Warning] Outdated mySQL server detected. Consider upgrading to a newer version." << std::endl;
	}

	m_connected = true;

	if(g_config.getString(ConfigManager::MAP_STORAGE_TYPE) == "binary")
	{
		DBQuery query;
		query << "SHOW variables LIKE 'max_allowed_packet';";

		DBResult* result;
		if((result = storeQuery(query.str())))
		{
			int32_t max_query = result->getDataInt("Value");
			freeResult(result);

			if(max_query < 16777216)
			{
				std::cout << std::endl << "[Warning] max_allowed_packet might be set too low for binary map storage." << std::endl;
				std::cout << "Use the following query to raise max_allow_packet: ";
				std::cout << "SET GLOBAL max_allowed_packet = 16777216;";
			}
		}
	}
}
Beispiel #10
0
bool DatabaseMySQL::sqlConnect(bool _reconnect)
{
	if(_reconnect)
		std::clog << "MYSQL Lost connection, attempting to reconnect..." << std::endl;
	if(!mysql_real_connect(&m_handle, g_config.getString(ConfigManager::SQL_HOST).c_str(), g_config.getString(
		ConfigManager::SQL_USER).c_str(), g_config.getString(ConfigManager::SQL_PASS).c_str(), g_config.getString(
		ConfigManager::SQL_DB).c_str(), g_config.getNumber(ConfigManager::SQL_PORT), NULL, 0))
	{
		std::clog << "Failed connecting to database - MYSQL ERROR: " << mysql_error(&m_handle) << " (" << mysql_errno(&m_handle) << ")" << std::endl;
		return false;
	}
	return true;
}
Beispiel #11
0
std::string getFilePath(FileType_t type, std::string name/* = ""*/)
{
	#ifdef __FILESYSTEM_HIERARCHY_STANDARD__
	std::string path = "/var/lib/tfs/";
	#else
	std::string path = g_config.getString(ConfigManager::DATA_DIRECTORY);
	#endif
	switch(type)
	{
		case FILE_TYPE_OTHER:
			path += name;
			break;
		case FILE_TYPE_XML:
			path += "XML/" + name;
			break;
		case FILE_TYPE_LOG:
			#ifndef __FILESYSTEM_HIERARCHY_STANDARD__
			path = g_config.getString(ConfigManager::LOGS_DIRECTORY) + name;
			#else
			path = "/var/log/tfs/" + name;
			#endif
			break;
		case FILE_TYPE_MOD:
		{
			#ifndef __FILESYSTEM_HIERARCHY_STANDARD__
			path = "mods/" + name;
			#else
			path = "/usr/share/tfs/" + name;
			#endif
			break;
		}
		case FILE_TYPE_CONFIG:
		{
			#if defined(__HOMEDIR_CONF__)
			if(fileExists("~/.tfs/" + name))
				path = "~/.tfs/" + name;
			else
			#endif
			#if defined(__FILESYSTEM_HIERARCHY_STANDARD__)
				path = "/etc/tfs/" + name;
			#else
				path = name;
			#endif
			break;
		}
		default:
			std::clog << "> ERROR: Wrong file type!" << std::endl;
			break;
	}
	return path;
}
Beispiel #12
0
void ServicePort::open(uint16_t port)
{
	close();

	m_serverPort = port;
	m_pendingStart = false;

	try {
		if (g_config.getBoolean(ConfigManager::BIND_ONLY_GLOBAL_ADDRESS)) {
			m_acceptor = new boost::asio::ip::tcp::acceptor(m_io_service, boost::asio::ip::tcp::endpoint(
			            boost::asio::ip::address(boost::asio::ip::address_v4::from_string(g_config.getString(ConfigManager::IP))), m_serverPort));
		} else {
			m_acceptor = new boost::asio::ip::tcp::acceptor(m_io_service, boost::asio::ip::tcp::endpoint(
			            boost::asio::ip::address(boost::asio::ip::address_v4(INADDR_ANY)), m_serverPort));
		}

		m_acceptor->set_option(boost::asio::ip::tcp::no_delay(true));

		accept();
	} catch (boost::system::system_error& e) {
		std::cout << "[ServicePort::open] Error: " << e.what() << std::endl;

		m_pendingStart = true;
		g_scheduler.addEvent(createSchedulerTask(15000,
		                     boost::bind(&ServicePort::openAcceptor, boost::weak_ptr<ServicePort>(shared_from_this()), port)));
	}
}
bool IOMapSerialize::loadMap(Map* map)
{
	std::string config = asLowerCaseString(g_config.getString(ConfigManager::HOUSE_STORAGE));
	bool result = false;
	if(config == "binary-tilebased")
		result = loadMapBinaryTileBased(map);
	else if(config == "binary")
		result = loadMapBinary(map);
	else
		result = loadMapRelational(map);

	if(!result)
		return false;

	for(HouseMap::iterator it = Houses::getInstance()->getHouseBegin();
		it != Houses::getInstance()->getHouseEnd(); ++it)
	{
		if(!it->second->hasSyncFlag(House::HOUSE_SYNC_UPDATE))
			continue;

		it->second->resetSyncFlag(House::HOUSE_SYNC_UPDATE);
		it->second->updateDoorDescription();
	}
	return true;
}
void ServicePort::open(uint16_t port)
{
	m_serverPort = port;
	m_pendingStart = false;

	try{
		if(g_config.getNumber(ConfigManager::BIND_ONLY_GLOBAL_ADDRESS))
		{
			m_acceptor = new boost::asio::ip::tcp::acceptor(m_io_service, boost::asio::ip::tcp::endpoint(
				boost::asio::ip::address(boost::asio::ip::address_v4::from_string(g_config.getString(ConfigManager::IP))), m_serverPort));
		}
		else
		{
			m_acceptor = new boost::asio::ip::tcp::acceptor(m_io_service, boost::asio::ip::tcp::endpoint(
				boost::asio::ip::address(boost::asio::ip::address_v4(INADDR_ANY)), m_serverPort));
		}
		m_acceptor->set_option(boost::asio::ip::tcp::no_delay(true));
		accept();
	}
	catch(boost::system::system_error& e){
		if(m_logError){
			LOG_MESSAGE("NETWORK", LOGTYPE_ERROR, 1, e.what());
			m_logError = false;
		}

		m_pendingStart = true;
		g_scheduler.addEvent(createSchedulerTask(5000,
			boost::bind(&ServicePort::openAcceptor, boost::weak_ptr<ServicePort>(shared_from_this()), port)));
	}
}
void ServicePort::open(uint16_t port)
{
	m_serverPort = port;
	m_pendingStart = false;
	try
	{
		if(g_config.getBool(ConfigManager::BIND_IP_ONLY))
			m_acceptor = new boost::asio::ip::tcp::acceptor(m_io_service, boost::asio::ip::tcp::endpoint(
				boost::asio::ip::address(boost::asio::ip::address_v4::from_string(
				g_config.getString(ConfigManager::IP))), m_serverPort));
		else
			m_acceptor = new boost::asio::ip::tcp::acceptor(m_io_service, boost::asio::ip::tcp::endpoint(
				boost::asio::ip::address(boost::asio::ip::address_v4(INADDR_ANY)), m_serverPort));

		accept();
	}
	catch(boost::system::system_error& e)
	{
		if(m_logError)
		{
			LOG_MESSAGE(LOGTYPE_ERROR, e.what(), "NETWORK")
			m_logError = false;
		}

		m_pendingStart = true;
		Scheduler::getInstance().addEvent(createSchedulerTask(5000, boost::bind(
			&ServicePort::onOpen, boost::weak_ptr<ServicePort>(shared_from_this()), m_serverPort)));
	}
}
Beispiel #16
0
bool Database::connect()
{
	// connection handle initialization
	m_handle = mysql_init(nullptr);
	if (!m_handle) {
		std::cout << std::endl << "Failed to initialize MySQL connection handle." << std::endl;
		return false;
	}

	// automatic reconnect
	my_bool reconnect = true;
	mysql_options(m_handle, MYSQL_OPT_RECONNECT, &reconnect);

	// connects to database
	if (!mysql_real_connect(m_handle, g_config.getString(ConfigManager::MYSQL_HOST).c_str(), g_config.getString(ConfigManager::MYSQL_USER).c_str(), g_config.getString(ConfigManager::MYSQL_PASS).c_str(), g_config.getString(ConfigManager::MYSQL_DB).c_str(), g_config.getNumber(ConfigManager::SQL_PORT), nullptr, 0)) {
		std::cout << std::endl << "MySQL Error Message: " << mysql_error(m_handle) << std::endl;
		return false;
	}

	m_connected = true;

	DBResult* result = storeQuery("SHOW variables LIKE 'max_allowed_packet'");
	if (result) {
		int32_t max_query = result->getDataInt("Value");
		freeResult(result);

		if (max_query < 16777216) {
			std::cout << std::endl << "[Warning] max_allowed_packet might too low for house item storage" << std::endl;
			std::cout << "Use the following query to raise max_allow_packet: ";
			std::cout << "SET GLOBAL max_allowed_packet = 16777216";
		}
	}
	return true;
}
Beispiel #17
0
int main(int argc, char* argv[])
{
	// Setup bad allocation handler
	std::set_new_handler(badAllocationHandler);

#ifndef _WIN32
	// ignore sigpipe...
	struct sigaction sigh;
	sigh.sa_handler = SIG_IGN;
	sigh.sa_flags = 0;
	sigemptyset(&sigh.sa_mask);
	sigaction(SIGPIPE, &sigh, nullptr);
#endif

	ServiceManager servicer;

	g_dispatcher.start();
	g_scheduler.start();

	g_dispatcher.addTask(createTask(std::bind(mainLoader, argc, argv, &servicer)));

	g_loaderSignal.wait(g_loaderUniqueLock);

	if (servicer.is_running()) {
		std::cout << ">> " << g_config.getString(ConfigManager::SERVER_NAME) << " Server Online!" << std::endl << std::endl;
#ifdef _WIN32
		SetConsoleCtrlHandler([](DWORD) -> BOOL {
			g_dispatcher.addTask(createTask([]() {
				g_dispatcher.addTask(createTask(
					std::bind(&Game::shutdown, &g_game)
				));
				g_scheduler.stop();
				g_databaseTasks.stop();
				g_dispatcher.stop();
			}));
			ExitThread(0);
		}, 1);
#endif
		servicer.run();
		g_scheduler.join();
		g_databaseTasks.join();
		g_dispatcher.join();
	} else {
		std::cout << ">> No services running. The server is NOT online." << std::endl;
		g_dispatcher.addTask(createTask([]() {
			g_dispatcher.addTask(createTask([]() {
				g_scheduler.shutdown();
				g_databaseTasks.shutdown();
				g_dispatcher.shutdown();
			}));
			g_scheduler.stop();
			g_databaseTasks.stop();
			g_dispatcher.stop();
		}));
		g_scheduler.join();
		g_databaseTasks.join();
		g_dispatcher.join();
	}
	return 0;
}
DatabaseSQLite::DatabaseSQLite()
{
	m_connected = false;
	// test for existence of database file;
	// sqlite3_open will create a new one if it isn't there (what we don't want)
	if(!fileExists(g_config.getString(ConfigManager::SQL_FILE).c_str()))
		return;

	// Initialize sqlite
	if(sqlite3_open(g_config.getString(ConfigManager::SQL_FILE).c_str(), &m_handle) != SQLITE_OK)
	{
		std::cout << "Failed to initialize SQLite connection." << std::endl;
		sqlite3_close(m_handle);
	}
	else
		m_connected = true;
}
Beispiel #19
0
bool passwordTest(std::string plain, std::string &hash)
{
  // Salt it beforehand
  plain += g_config.getString(ConfigManager::PASSWORD_SALT);

  switch(g_config.getNumber(ConfigManager::PASSWORD_TYPE)){
  case PASSWORD_TYPE_PLAIN:
  {
    if(plain == hash){
      return true;
    }
    break;
  }
  case PASSWORD_TYPE_MD5:
  {
    MD5_CTX m_md5;
    std::stringstream hexStream;

    MD5Init(&m_md5, 0);
    MD5Update(&m_md5, (const unsigned char*)plain.c_str(), plain.length());
    MD5Final(&m_md5);

    hexStream.flags(std::ios::hex | std::ios::uppercase);
    for(uint32_t i = 0; i < 16; ++i){
      hexStream << std::setw(2) << std::setfill('0') << (uint32_t)m_md5.digest[i];
    }

    std::transform(hash.begin(), hash.end(), hash.begin(), upchar);
    if(hexStream.str() == hash){
      return true;
    }
    break;
  }
  case PASSWORD_TYPE_SHA1:
  {
    SHA1 sha1;
    unsigned sha1Hash[5];
    std::stringstream hexStream;

    sha1.Input((const unsigned char*)plain.c_str(), plain.length());
    sha1.Result(sha1Hash);

    hexStream.flags(std::ios::hex | std::ios::uppercase);
    for(uint32_t i = 0; i < 5; ++i){
      hexStream << std::setw(8) << std::setfill('0') << (uint32_t)sha1Hash[i];
    }

    std::transform(hash.begin(), hash.end(), hash.begin(), upchar);
    if(hexStream.str() == hash){
      return true;
    }

    break;
  }
  }
  return false;
}
bool IOMapSerialize::saveMap(Map* map)
{
	std::string config = asLowerCaseString(g_config.getString(ConfigManager::HOUSE_STORAGE));
	if(config == "binary-tilebased")
		return saveMapBinaryTileBased(map);
	else if(config == "binary")
		return saveMapBinary(map);

	return saveMapRelational(map);
}
Beispiel #21
0
DatabaseDriver* DatabaseDriver::instance(){
	if(!_instance){
#ifdef __USE_MYSQL__
		if(g_config.getString(ConfigManager::SQL_TYPE) == "mysql")
			_instance = new DatabaseMySQL;
#endif
#ifdef __USE_ODBC__
		if(g_config.getString(ConfigManager::SQL_TYPE) == "odbc")
			_instance = new DatabaseODBC;
#endif
#ifdef __USE_SQLITE__
		if(g_config.getString(ConfigManager::SQL_TYPE) == "sqlite")
			_instance = new DatabaseSQLite;
#endif
#ifdef __USE_PGSQL__
		if(g_config.getString(ConfigManager::SQL_TYPE) == "pgsql")
			_instance = new DatabasePgSQL;
#endif
	}
	return _instance;
}
bool IOMapSerialize::saveHouseItems(Database* db, House* house)
{
	std::string config = asLowerCaseString(g_config.getString(ConfigManager::HOUSE_STORAGE));
	if(config == "binary-tilebased")
	{
		DBQuery query;
		query << "DELETE FROM `tile_store` WHERE `house_id` = " << house->getId()
			<< " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID);
		if(!db->query(query.str()))
			return false;

		DBInsert stmt(db);
		stmt.setQuery("INSERT INTO `tile_store` (`house_id`, `world_id`, `data`) VALUES ");
		return saveHouseBinaryTileBased(db, stmt, house) && stmt.execute();
	}
	else if(config == "binary")
	{
		DBQuery query;
		query << "DELETE FROM `house_data` WHERE `house_id` = "<< house->getId()
			<< " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID);
		if(!db->query(query.str()))
			return false;

		DBInsert stmt(db);
		stmt.setQuery("INSERT INTO `house_data` (`house_id`, `world_id`, `data`) VALUES ");
		return saveHouseBinary(db, stmt, house) && stmt.execute();
	}

	DBQuery query;
	query << "DELETE FROM `tile_items` WHERE `tile_id` IN (SELECT `id` FROM `tiles` WHERE `house_id` = "
		<< house->getId() << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID)
		<< ") AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID);
	if(!db->query(query.str()))
		return false;

	query.str("");
	query << "DELETE FROM `tiles` WHERE `house_id` = " << house->getId()
		<< " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID);
	if(!db->query(query.str()))
		return false;

	query.str("");
	query << "SELECT `id` FROM `tiles` WHERE `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID) << " ORDER BY `id` DESC LIMIT 1;";

	DBResult* result;
	if(!(result = db->storeQuery(query.str())))
		return false;

	uint32_t tileId = result->getDataInt("id") + 1;
	result->free();
	return saveHouseRelational(db, house, tileId);
}
Beispiel #23
0
Admin::Admin(): m_currentConnections(0), m_encrypted(false),
	m_key_RSA1024XTEA(NULL)
{
	std::string strValue = g_config.getString(ConfigManager::ADMIN_ENCRYPTION);
	if(!strValue.empty())
	{
		toLowerCaseString(strValue);
		if(strValue == "rsa1024xtea")
		{
			m_key_RSA1024XTEA = new RSA();
			if(!m_key_RSA1024XTEA->initialize(getFilePath(FILE_TYPE_CONFIG,
				g_config.getString(ConfigManager::ADMIN_ENCRYPTION_DATA))))
			{
				std::clog << "[Warning - Admin::Admin] Unable to set RSA1024XTEA key!" << std::endl;
				delete m_key_RSA1024XTEA;
				m_key_RSA1024XTEA = NULL;
			}
			else
				m_encrypted = true;
		}
	}
}
Beispiel #24
0
Houses::Houses()
{
	rentPeriod = RENTPERIOD_NEVER;
	std::string strValue = asLowerCaseString(g_config.getString(ConfigManager::HOUSE_RENT_PERIOD));
	if(strValue == "yearly")
		rentPeriod = RENTPERIOD_YEARLY;
	else if(strValue == "monthly")
		rentPeriod = RENTPERIOD_MONTHLY;
	else if(strValue == "weekly")
		rentPeriod = RENTPERIOD_WEEKLY;
	else if(strValue == "daily")
		rentPeriod = RENTPERIOD_DAILY;
}
Beispiel #25
0
DatabaseSQLite::DatabaseSQLite()
{
	m_connected = false;

	// test for existence of database file;
	// sqlite3_open will create a new one if it isn't there (which we don't want)
	std::fstream fin(g_config.getString(ConfigManager::SQL_DB).c_str(), std::ios::in | std::ios::binary);
	if(fin.fail()){
		std::cout << "Failed to initialize SQLite connection. File " << g_config.getString(ConfigManager::SQL_DB) 
			<< " does not exist." << std::endl;
		return;
	}
	fin.close();

	// Initialize sqlite
	if( sqlite3_open(g_config.getString(ConfigManager::SQL_DB).c_str(), &m_handle) != SQLITE_OK){
		std::cout << "Failed to initialize SQLite connection." << std::endl;
		sqlite3_close(m_handle);
	}
	else{
		m_connected = true;
	}
}
Beispiel #26
0
void ProtocolAdmin::adminCommandRelationalSaveServer()
{
	std::string old_type = g_config.getString(ConfigManager::MAP_STORAGE_TYPE);
	g_config.setString(ConfigManager::MAP_STORAGE_TYPE, "relational");
	g_game.saveServer(false);
	g_config.setString(ConfigManager::MAP_STORAGE_TYPE, old_type);
	addLogLine(this, LOGTYPE_EVENT, 1, "relational save server ok");

	OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
	if(output){
		TRACK_MESSAGE(output);
		output->AddByte(AP_MSG_COMMAND_OK);
		OutputMessagePool::getInstance()->send(output);
	}
}
Beispiel #27
0
Npc::Npc(const std::string& _name) :
	Creature()
{
	m_datadir = g_config.getString(ConfigManager::DATA_DIRECTORY);
	m_scriptdir = m_datadir + "npc/scripts/";
	m_filename = m_datadir + "npc/" + _name + ".xml";
	loaded = false;

	m_npcEventHandler = NULL;
	reset();

#ifdef __ENABLE_SERVER_DIAGNOSTIC__
	npcCount++;
#endif
}
Beispiel #28
0
ChatChannel::ChatChannel(uint16_t id, const std::string& name, uint16_t flags, uint32_t access/* = 0*/,
	uint32_t level/* = 1*/, Condition* condition/* = NULL*/, int32_t conditionId/* = -1*/,
	const std::string& conditionMessage/* = ""*/, VocationMap* vocationMap/* = NULL*/):
	m_id(id), m_flags(flags), m_conditionId(conditionId), m_access(access), m_level(level),
		m_name(name), m_conditionMessage(conditionMessage), m_condition(condition),
		m_vocationMap(vocationMap)
{
	if(hasFlag(CHANNELFLAG_LOGGED))
	{
		m_file.reset(new std::ofstream(getFilePath(FILE_TYPE_LOG, (std::string)"chat/" + g_config.getString(
			ConfigManager::PREFIX_CHANNEL_LOGS) + m_name + (std::string)".log").c_str(), std::ios::app | std::ios::out));
		if(!m_file->is_open())
			m_flags &= ~CHANNELFLAG_LOGGED;
	}
}
Beispiel #29
0
Database* _Database::getInstance()
{
	if(!_instance)
	{
#if defined MULTI_SQL_DRIVERS
		std::string sqlType = asLowerCaseString(g_config.getString(ConfigManager::SQL_TYPE));
		if(sqlType == "mysql")
			_instance = new DatabaseMySQL;
		else if(sqlType == "sqlite")
			_instance = new DatabaseSQLite;
		else
			_instance = new Database;
#else
		_instance = new Database;
#endif
	}
	return _instance;
}
void ProtocolStatus::onRecvFirstMessage(NetworkMessage& msg)
{
	uint32_t ip = getIP();
	if (ip != 0x0100007F) {
		std::string ipStr = convertIPToString(ip);
		if (ipStr != g_config.getString(ConfigManager::IP)) {
			std::map<uint32_t, int64_t>::const_iterator it = ipConnectMap.find(ip);
			if (it != ipConnectMap.end()) {
				if (OTSYS_TIME() < (it->second + g_config.getNumber(ConfigManager::STATUSQUERY_TIMEOUT))) {
					getConnection()->close();
					return;
				}
			}
		}
	}

	ipConnectMap[ip] = OTSYS_TIME();

	switch (msg.getByte()) {
		//XML info protocol
		case 0xFF: {
			if (msg.getString(4) == "info") {
				g_dispatcher.addTask(createTask(std::bind(&ProtocolStatus::sendStatusString, this)));
				return;
			}
			break;
		}

		//Another ServerInfo protocol
		case 0x01: {
			uint16_t requestedInfo = msg.get<uint16_t>(); // only a Byte is necessary, though we could add new info here
			std::string characterName;
			if (requestedInfo & REQUEST_PLAYER_STATUS_INFO) {
				characterName = msg.getString();
			}
			g_dispatcher.addTask(createTask(std::bind(&ProtocolStatus::sendInfo, this, requestedInfo, characterName)));
			return;
		}

		default:
			break;
	}
	getConnection()->close();
}