Add sqlite3 for ip / online id ban table
This commit is contained in:
parent
7d19ccaad8
commit
bcc3aef4c8
@ -24,6 +24,7 @@ option(USE_SYSTEM_ANGELSCRIPT "Use system angelscript instead of built-in angels
|
||||
option(USE_SYSTEM_ENET "Use system ENet instead of the built-in version, when available." ON)
|
||||
option(USE_SYSTEM_GLEW "Use system GLEW instead of the built-in version, when available." ON)
|
||||
option(USE_SYSTEM_WIIUSE "Use system WiiUse instead of the built-in version, when available." OFF)
|
||||
option(USE_SQLITE3 "Use sqlite to manage server stats and ban list." ON)
|
||||
|
||||
option(USE_CRYPTO_OPENSSL "Use OpenSSL instead of Nettle for cryptography in STK." OFF)
|
||||
CMAKE_DEPENDENT_OPTION(BUILD_RECORDER "Build opengl recorder" ON
|
||||
@ -363,6 +364,23 @@ if(USE_LIBBFD)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# SQLITE
|
||||
if(USE_SQLITE3)
|
||||
find_library(SQLITE3_LIBRARY NAMES sqlite3 libsqlite3)
|
||||
find_path(SQLITE3_INCLUDEDIR NAMES sqlite3.h PATHS)
|
||||
if (NOT SQLITE3_LIBRARY OR NOT SQLITE3_INCLUDEDIR)
|
||||
# add_subdirectory("${PROJECT_SOURCE_DIR}/lib/sqlite3")
|
||||
# include_directories("${PROJECT_SOURCE_DIR}/lib/sqlite3")
|
||||
# SET(SQLITE3_LIBRARY sqlite3)
|
||||
set(USE_SQLITE3 OFF CACHE BOOL "Use sqlite to manage server stats and ban list." FORCE)
|
||||
message(WARNING "Sqlite3 not found, disable advanced server management.")
|
||||
else()
|
||||
add_definitions(-DENABLE_SQLITE3)
|
||||
include_directories("${SQLITE3_INCLUDEDIR}")
|
||||
MESSAGE(STATUS "Use system libsqlite3: ${SQLITE3_LIBRARY}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Set some compiler options
|
||||
if(UNIX OR MINGW)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
|
||||
@ -518,6 +536,10 @@ target_link_libraries(supertuxkart
|
||||
${CURL_LIBRARIES}
|
||||
)
|
||||
|
||||
if (USE_SQLITE3)
|
||||
target_link_libraries(supertuxkart ${SQLITE3_LIBRARY})
|
||||
endif()
|
||||
|
||||
if (USE_CRYPTO_OPENSSL)
|
||||
target_link_libraries(supertuxkart ${OPENSSL_CRYPTO_LIBRARY})
|
||||
else()
|
||||
|
@ -202,3 +202,55 @@ Tested on a Raspberry Pi 3 Model B+, if you have 8 players connected to a server
|
||||
For bad network simulation, we recommend `network traffic control` by linux kernel, see [here](https://wiki.linuxfoundation.org/networking/netem) for details.
|
||||
|
||||
You have the best gaming experience when choosing server having all players less than 100ms ping with no packet loss.
|
||||
|
||||
## Server management (Since 1.1)
|
||||
|
||||
Currently STK uses sqlite (if building with sqlite3 on) for server management with the following functions at the moment:
|
||||
1. Server statistics
|
||||
2. IP / online ID ban list
|
||||
|
||||
You need to create a database in sqlite first, run `sqlite3 stkservers.db` in the folder where (all) your server_config.xml(s) located.
|
||||
|
||||
STK will automatically create a table named `v(server database version)_(your_server_config_filename_without_.xml_extension)_stats` in your database if not exists:
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS (table name above)
|
||||
(
|
||||
host_id INTEGER UNSIGNED NOT NULL PRIMARY KEY, -- Unique host id in STKHost of each connection session for a STKPeer
|
||||
ip INTEGER UNSIGNED NOT NULL, -- IP decimal of host
|
||||
port INTEGER UNSIGNED NOT NULL, -- Port of host
|
||||
online_id INTEGER UNSIGNED NOT NULL, -- Online if of the host (0 for offline account)
|
||||
username TEXT NOT NULL, -- First player name in the host (if the host has splitscreen player)
|
||||
player_num INEGER UNSIGNED NOT NULL, -- Number of player(s) from the host, more than 1 if it has splitscreen player
|
||||
country_id TEXT NULL DEFAULT NULL, -- Country id of the host
|
||||
version TEXT NOT NULL, -- SuperTuxKart version of the host (with OS info)
|
||||
connected_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Time when connected
|
||||
disconnected_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Time when disconnected (saved when disconnected)
|
||||
ping INEGER UNSIGNED NOT NULL DEFAULT 0 -- Ping of the host
|
||||
) WITHOUT ROWID;
|
||||
```
|
||||
|
||||
For IP or online ID ban list, you need to create one yourself:
|
||||
```sql
|
||||
CREATE TABLE ipban
|
||||
(
|
||||
ip_start INTEGER UNSIGNED NOT NULL UNIQUE, -- Starting of ip decimal for banning (inclusive)
|
||||
ip_end INTEGER UNSIGNED NOT NULL UNIQUE, -- Ending of ip decimal for banning (inclusive)
|
||||
starting_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Starting time of this banning entry to be effective
|
||||
expired_days REAL NULL DEFAULT NULL, -- Days for this banning to be expired, use NULL for a permanent ban
|
||||
reason TEXT NOT NULL DEFAULT '', -- Banned reason shown in user stk menu, can be empty
|
||||
description TEXT NOT NULL DEFAULT '', -- Private description for server admin
|
||||
trigger_count INEGER UNSIGNED NOT NULL DEFAULT 0, -- Number of banning triggered by this ban entry
|
||||
last_trigger TIMESTAMP NULL DEFAULT NULL -- Latest time this banning entry was triggered
|
||||
);
|
||||
|
||||
CREATE TABLE onlineidban
|
||||
(
|
||||
online_id INTEGER UNSIGNED NOT NULL UNIQUE, -- Online id from STK addons database for banning
|
||||
starting_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Starting time of this banning entry to be effective
|
||||
expired_days REAL NULL DEFAULT NULL, -- Days for this banning to be expired, use NULL for a permanent ban
|
||||
reason TEXT NOT NULL DEFAULT '', -- Banned reason shown in user stk menu, can be empty
|
||||
description TEXT NOT NULL DEFAULT '', -- Private description for server admin
|
||||
trigger_count INEGER UNSIGNED NOT NULL DEFAULT 0, -- Number of banning triggered by this ban entry
|
||||
last_trigger TIMESTAMP NULL DEFAULT NULL -- Latest time this banning entry was triggered
|
||||
);
|
||||
```
|
||||
|
@ -91,6 +91,8 @@ void mainLoop(STKHost* host)
|
||||
peer->kick();
|
||||
// ATM use permanently ban
|
||||
auto sl = LobbyProtocol::get<ServerLobby>();
|
||||
if (sl)
|
||||
sl->saveIPBanTable(peer->getAddress());
|
||||
auto lock = sl->acquireConnectionMutex();
|
||||
ServerConfig::m_server_ip_ban_list
|
||||
[peer->getAddress().toString(false/*show_port*/) + "/32"]
|
||||
@ -114,6 +116,10 @@ void mainLoop(STKHost* host)
|
||||
}
|
||||
else if (str == "listban")
|
||||
{
|
||||
auto sl = LobbyProtocol::get<ServerLobby>();
|
||||
if (sl)
|
||||
sl->listBanTable();
|
||||
|
||||
for (auto& ban : ServerConfig::m_server_ip_ban_list)
|
||||
{
|
||||
if (ban.first == "0.0.0.0/0")
|
||||
|
@ -55,6 +55,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
|
||||
/** This is the central game setup protocol running in the server. It is
|
||||
@ -144,6 +145,7 @@ ServerLobby::ServerLobby() : LobbyProtocol(NULL)
|
||||
m_difficulty.store(ServerConfig::m_server_difficulty);
|
||||
m_game_mode.store(ServerConfig::m_server_mode);
|
||||
m_default_vote = new PeerVote();
|
||||
initDatabase();
|
||||
} // ServerLobby
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -161,8 +163,105 @@ ServerLobby::~ServerLobby()
|
||||
if (m_save_server_config)
|
||||
ServerConfig::writeServerConfigToDisk();
|
||||
delete m_default_vote;
|
||||
destroyDatabase();
|
||||
} // ~ServerLobby
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerLobby::initDatabase()
|
||||
{
|
||||
#ifdef ENABLE_SQLITE3
|
||||
m_db = NULL;
|
||||
sqlite3_stmt* stmt = NULL;;
|
||||
m_ip_ban_table_exists = false;
|
||||
m_online_id_ban_table_exists = false;
|
||||
if (!ServerConfig::m_sql_management)
|
||||
return;
|
||||
int ret = sqlite3_open(ServerConfig::m_database_file.c_str(), &m_db);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
Log::error("ServerLobby", "Cannot open database: %s.",
|
||||
sqlite3_errmsg(m_db));
|
||||
sqlite3_close(m_db);
|
||||
m_db = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string query = StringUtils::insertValues(
|
||||
"SELECT count(type) FROM sqlite_master "
|
||||
"WHERE type='table' AND name='%s';",
|
||||
ServerConfig::m_ip_ban_table.c_str());
|
||||
|
||||
ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0);
|
||||
if (ret == SQLITE_OK)
|
||||
{
|
||||
ret = sqlite3_step(stmt);
|
||||
if (ret == SQLITE_ROW)
|
||||
{
|
||||
int number = sqlite3_column_int(stmt, 0);
|
||||
if (number == 1)
|
||||
{
|
||||
Log::info("ServerLobby", "%s ip ban table will used.",
|
||||
ServerConfig::m_ip_ban_table.c_str());
|
||||
m_ip_ban_table_exists = true;
|
||||
}
|
||||
}
|
||||
ret = sqlite3_finalize(stmt);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
Log::error("ServerLobby", "Error finalize database: %s",
|
||||
sqlite3_errmsg(m_db));
|
||||
}
|
||||
}
|
||||
if (!m_ip_ban_table_exists)
|
||||
{
|
||||
Log::warn("ServerLobby", "%s ip ban table not found in database.",
|
||||
ServerConfig::m_ip_ban_table.c_str());
|
||||
}
|
||||
|
||||
query = StringUtils::insertValues(
|
||||
"SELECT count(type) FROM sqlite_master "
|
||||
"WHERE type='table' AND name='%s';",
|
||||
ServerConfig::m_online_id_ban_table.c_str());
|
||||
|
||||
ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0);
|
||||
if (ret == SQLITE_OK)
|
||||
{
|
||||
ret = sqlite3_step(stmt);
|
||||
if (ret == SQLITE_ROW)
|
||||
{
|
||||
int number = sqlite3_column_int(stmt, 0);
|
||||
if (number == 1)
|
||||
{
|
||||
Log::info("ServerLobby", "%s online id ban table will used.",
|
||||
ServerConfig::m_online_id_ban_table.c_str());
|
||||
m_online_id_ban_table_exists = true;
|
||||
}
|
||||
}
|
||||
ret = sqlite3_finalize(stmt);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
Log::error("ServerLobby", "Error finalize database: %s",
|
||||
sqlite3_errmsg(m_db));
|
||||
}
|
||||
}
|
||||
if (!m_online_id_ban_table_exists)
|
||||
{
|
||||
Log::warn("ServerLobby",
|
||||
"%s online id ban table not found in database.",
|
||||
ServerConfig::m_online_id_ban_table.c_str());
|
||||
}
|
||||
#endif
|
||||
} // initDatabase
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerLobby::destroyDatabase()
|
||||
{
|
||||
#ifdef ENABLE_SQLITE3
|
||||
if (m_db != NULL)
|
||||
sqlite3_close(m_db);
|
||||
#endif
|
||||
} // destroyDatabase
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called whenever server is reset or game mode is changed.
|
||||
*/
|
||||
@ -2075,6 +2174,51 @@ void ServerLobby::clearDisconnectedRankedPlayer()
|
||||
}
|
||||
} // clearDisconnectedRankedPlayer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerLobby::kickPlayerWithReason(STKPeer* peer, const char* reason) const
|
||||
{
|
||||
NetworkString *message = getNetworkString(2);
|
||||
message->setSynchronous(true);
|
||||
message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_BANNED);
|
||||
message->encodeString(std::string(reason));
|
||||
peer->cleanPlayerProfiles();
|
||||
peer->sendPacket(message, true/*reliable*/, false/*encrypted*/);
|
||||
peer->reset();
|
||||
delete message;
|
||||
} // kickPlayerWithReason
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerLobby::saveIPBanTable(const TransportAddress& addr)
|
||||
{
|
||||
#ifdef ENABLE_SQLITE3
|
||||
if (!m_db || !m_ip_ban_table_exists)
|
||||
return;
|
||||
|
||||
std::string query = StringUtils::insertValues(
|
||||
"INSERT INTO %s (ip_start, ip_end) "
|
||||
"VALUES (%u, %u);",
|
||||
ServerConfig::m_ip_ban_table.c_str(), addr.getIP(), addr.getIP());
|
||||
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0);
|
||||
if (ret == SQLITE_OK)
|
||||
{
|
||||
ret = sqlite3_step(stmt);
|
||||
ret = sqlite3_finalize(stmt);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
Log::error("ServerLobby", "Error finalize database: %s",
|
||||
sqlite3_errmsg(m_db));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ServerLobby", "Error preparing database: %s",
|
||||
sqlite3_errmsg(m_db));
|
||||
}
|
||||
#endif
|
||||
} // saveIPBanTable
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerLobby::connectionRequested(Event* event)
|
||||
{
|
||||
@ -2207,33 +2351,16 @@ void ServerLobby::connectionRequested(Event* event)
|
||||
online_id = data.getUInt32();
|
||||
encrypted_size = data.getUInt32();
|
||||
|
||||
bool is_banned = isBannedForIP(peer->getAddress());
|
||||
if (online_id != 0 && !is_banned)
|
||||
{
|
||||
if (m_online_id_ban_list.find(online_id) !=
|
||||
m_online_id_ban_list.end() &&
|
||||
(uint32_t)StkTime::getTimeSinceEpoch() <
|
||||
m_online_id_ban_list.at(online_id))
|
||||
{
|
||||
is_banned = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_banned)
|
||||
{
|
||||
NetworkString *message = getNetworkString(2);
|
||||
message->setSynchronous(true);
|
||||
message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_BANNED);
|
||||
// For future we can say the reason here
|
||||
// and use encodeString instead
|
||||
message->addUInt8(0);
|
||||
peer->cleanPlayerProfiles();
|
||||
peer->sendPacket(message, true/*reliable*/, false/*encrypted*/);
|
||||
peer->reset();
|
||||
delete message;
|
||||
Log::verbose("ServerLobby", "Player refused: banned");
|
||||
// Will be disconnected if banned by IP
|
||||
testBannedForIP(peer.get());
|
||||
if (peer->isDisconnected())
|
||||
return;
|
||||
|
||||
if (online_id != 0)
|
||||
testBannedForOnlineId(peer.get(), online_id);
|
||||
// Will be disconnected if banned by online id
|
||||
if (peer->isDisconnected())
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned total_players = 0;
|
||||
STKHost::get()->updatePlayers(NULL, NULL, &total_players);
|
||||
@ -3253,6 +3380,192 @@ void ServerLobby::resetServer()
|
||||
WAITING_FOR_START_GAME : REGISTER_SELF_ADDRESS;
|
||||
} // resetServer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerLobby::testBannedForIP(STKPeer* peer) const
|
||||
{
|
||||
#ifdef ENABLE_SQLITE3
|
||||
if (!m_db || !m_ip_ban_table_exists)
|
||||
return;
|
||||
|
||||
int row_id = -1;
|
||||
unsigned ip_start = 0;
|
||||
unsigned ip_end = 0;
|
||||
std::string query = StringUtils::insertValues(
|
||||
"SELECT rowid, ip_start, ip_end, reason, description FROM %s "
|
||||
"WHERE ip_start <= %u AND ip_end >= %u "
|
||||
"AND datetime('now') > datetime(starting_time) AND "
|
||||
"(expired_days is NULL OR datetime"
|
||||
"(starting_time, '+'||expired_days||' days') > datetime('now')) "
|
||||
"LIMIT 1;",
|
||||
ServerConfig::m_ip_ban_table.c_str(),
|
||||
peer->getAddress().getIP(), peer->getAddress().getIP());
|
||||
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0);
|
||||
if (ret == SQLITE_OK)
|
||||
{
|
||||
ret = sqlite3_step(stmt);
|
||||
if (ret == SQLITE_ROW)
|
||||
{
|
||||
row_id = sqlite3_column_int(stmt, 0);
|
||||
ip_start = (unsigned)sqlite3_column_int64(stmt, 1);
|
||||
ip_end = (unsigned)sqlite3_column_int64(stmt, 2);
|
||||
const char* reason = (char*)sqlite3_column_text(stmt, 3);
|
||||
const char* desc = (char*)sqlite3_column_text(stmt, 4);
|
||||
Log::info("ServerLobby", "%s banned by IP: %s "
|
||||
"(rowid: %d, description: %s).",
|
||||
peer->getAddress().toString().c_str(), reason, row_id, desc);
|
||||
kickPlayerWithReason(peer, reason);
|
||||
}
|
||||
ret = sqlite3_finalize(stmt);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
Log::error("ServerLobby", "Error finalize database: %s",
|
||||
sqlite3_errmsg(m_db));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ServerLobby", "Error preparing database: %s",
|
||||
sqlite3_errmsg(m_db));
|
||||
return;
|
||||
}
|
||||
if (row_id != -1)
|
||||
{
|
||||
query = StringUtils::insertValues(
|
||||
"UPDATE %s SET trigger_count = trigger_count + 1, "
|
||||
"last_trigger = datetime('now') "
|
||||
"WHERE ip_start = %u AND ip_end = %u;",
|
||||
ServerConfig::m_ip_ban_table.c_str(), ip_start, ip_end);
|
||||
int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0);
|
||||
if (ret == SQLITE_OK)
|
||||
{
|
||||
ret = sqlite3_step(stmt);
|
||||
ret = sqlite3_finalize(stmt);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
Log::error("ServerLobby", "Error finalize database: %s",
|
||||
sqlite3_errmsg(m_db));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ServerLobby", "Error preparing database: %s",
|
||||
sqlite3_errmsg(m_db));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // testBannedForIP
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerLobby::testBannedForOnlineId(STKPeer* peer,
|
||||
uint32_t online_id) const
|
||||
{
|
||||
#ifdef ENABLE_SQLITE3
|
||||
if (!m_db || !m_online_id_ban_table_exists)
|
||||
return;
|
||||
|
||||
int row_id = -1;
|
||||
std::string query = StringUtils::insertValues(
|
||||
"SELECT rowid, reason, description FROM %s "
|
||||
"WHERE online_id = %u "
|
||||
"AND datetime('now') > datetime(starting_time) AND "
|
||||
"(expired_days is NULL OR datetime"
|
||||
"(starting_time, '+'||expired_days||' days') > datetime('now')) "
|
||||
"LIMIT 1;",
|
||||
ServerConfig::m_online_id_ban_table.c_str(), online_id);
|
||||
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0);
|
||||
if (ret == SQLITE_OK)
|
||||
{
|
||||
ret = sqlite3_step(stmt);
|
||||
if (ret == SQLITE_ROW)
|
||||
{
|
||||
row_id = sqlite3_column_int(stmt, 0);
|
||||
const char* reason = (char*)sqlite3_column_text(stmt, 1);
|
||||
const char* desc = (char*)sqlite3_column_text(stmt, 2);
|
||||
Log::info("ServerLobby", "%s banned by online id: %s "
|
||||
"(online id: %u rowid: %d, description: %s).",
|
||||
peer->getAddress().toString().c_str(), reason, online_id,
|
||||
row_id, desc);
|
||||
kickPlayerWithReason(peer, reason);
|
||||
}
|
||||
ret = sqlite3_finalize(stmt);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
Log::error("ServerLobby", "Error finalize database: %s",
|
||||
sqlite3_errmsg(m_db));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ServerLobby", "Error preparing database: %s",
|
||||
sqlite3_errmsg(m_db));
|
||||
return;
|
||||
}
|
||||
if (row_id != -1)
|
||||
{
|
||||
query = StringUtils::insertValues(
|
||||
"UPDATE %s SET trigger_count = trigger_count + 1, "
|
||||
"last_trigger = datetime('now') "
|
||||
"WHERE online_id = %u;",
|
||||
ServerConfig::m_online_id_ban_table.c_str(), online_id);
|
||||
int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0);
|
||||
if (ret == SQLITE_OK)
|
||||
{
|
||||
ret = sqlite3_step(stmt);
|
||||
ret = sqlite3_finalize(stmt);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
Log::error("ServerLobby", "Error finalize database: %s",
|
||||
sqlite3_errmsg(m_db));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ServerLobby", "Error preparing database: %s",
|
||||
sqlite3_errmsg(m_db));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // testBannedForOnlineId
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerLobby::listBanTable()
|
||||
{
|
||||
#ifdef ENABLE_SQLITE3
|
||||
if (!m_db)
|
||||
return;
|
||||
auto printer = [](void* data, int argc, char** argv, char** name)
|
||||
{
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
std::cout << name[i] << " = " << (argv[i] ? argv[i] : "NULL")
|
||||
<< "\n";
|
||||
}
|
||||
std::cout << "\n";
|
||||
return 0;
|
||||
};
|
||||
if (m_ip_ban_table_exists)
|
||||
{
|
||||
std::string query = "SELECT * FROM ";
|
||||
query += ServerConfig::m_ip_ban_table;
|
||||
query += ";";
|
||||
std::cout << "IP ban list:\n";
|
||||
sqlite3_exec(m_db, query.c_str(), printer, NULL, NULL);
|
||||
}
|
||||
if (m_online_id_ban_table_exists)
|
||||
{
|
||||
std::string query = "SELECT * FROM ";
|
||||
query += ServerConfig::m_online_id_ban_table;
|
||||
query += ";";
|
||||
std::cout << "Online Id ban list:\n";
|
||||
sqlite3_exec(m_db, query.c_str(), printer, NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
} // listBanTable
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ServerLobby::isBannedForIP(const TransportAddress& addr) const
|
||||
{
|
||||
|
@ -34,6 +34,10 @@
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
|
||||
#ifdef ENABLE_SQLITE3
|
||||
#include <sqlite3.h>
|
||||
#endif
|
||||
|
||||
class BareNetworkString;
|
||||
class NetworkString;
|
||||
class NetworkPlayerProfile;
|
||||
@ -66,6 +70,17 @@ private:
|
||||
irr::core::stringw m_name;
|
||||
bool m_tried = false;
|
||||
};
|
||||
#ifdef ENABLE_SQLITE3
|
||||
sqlite3* m_db;
|
||||
|
||||
bool m_ip_ban_table_exists;
|
||||
|
||||
bool m_online_id_ban_table_exists;
|
||||
|
||||
#endif
|
||||
void initDatabase();
|
||||
|
||||
void destroyDatabase();
|
||||
|
||||
std::atomic<ServerState> m_state;
|
||||
|
||||
@ -305,6 +320,9 @@ private:
|
||||
void handleKartInfo(Event* event);
|
||||
void clientInGameWantsToBackLobby(Event* event);
|
||||
void clientSelectingAssetsWantsToBackLobby(Event* event);
|
||||
void kickPlayerWithReason(STKPeer* peer, const char* reason) const;
|
||||
void testBannedForIP(STKPeer* peer) const;
|
||||
void testBannedForOnlineId(STKPeer* peer, uint32_t online_id) const;
|
||||
public:
|
||||
ServerLobby();
|
||||
virtual ~ServerLobby();
|
||||
@ -333,6 +351,8 @@ public:
|
||||
int getDifficulty() const { return m_difficulty.load(); }
|
||||
int getGameMode() const { return m_game_mode.load(); }
|
||||
void saveInitialItems();
|
||||
void saveIPBanTable(const TransportAddress& addr);
|
||||
void listBanTable();
|
||||
}; // class ServerLobby
|
||||
|
||||
#endif // SERVER_LOBBY_HPP
|
||||
|
@ -319,6 +319,32 @@ namespace ServerConfig
|
||||
"more rewind, which clients with slow device may have problem playing "
|
||||
"this server, use the default value is recommended."));
|
||||
|
||||
SERVER_CFG_PREFIX BoolServerConfigParam m_sql_management
|
||||
SERVER_CFG_DEFAULT(BoolServerConfigParam(false,
|
||||
"sql-management",
|
||||
"Use sql to manage server stats and banlist, STK needs to be compiled "
|
||||
"with sqlite3 supported."));
|
||||
|
||||
SERVER_CFG_PREFIX StringServerConfigParam m_database_file
|
||||
SERVER_CFG_DEFAULT(StringServerConfigParam("stkservers.db",
|
||||
"database-file",
|
||||
"Database filename for sqlite to use, it can be shared for servers "
|
||||
"creating in this machine, and stk will create specific table for each "
|
||||
"server. You need to create the database yourself first, see "
|
||||
"NETWORKING.md for details"));
|
||||
|
||||
SERVER_CFG_PREFIX StringServerConfigParam m_ip_ban_table
|
||||
SERVER_CFG_DEFAULT(StringServerConfigParam("ipban",
|
||||
"ip-ban-table",
|
||||
"Ip ban list table name, you need to create the table first, see "
|
||||
"NETWORKING.md for details."));
|
||||
|
||||
SERVER_CFG_PREFIX StringServerConfigParam m_online_id_ban_table
|
||||
SERVER_CFG_DEFAULT(StringServerConfigParam("onlineidban",
|
||||
"online-id-ban-table",
|
||||
"Online ID ban list table name, you need to create the table first, "
|
||||
"see NETWORKING.md for details."));
|
||||
|
||||
SERVER_CFG_PREFIX StringToUIntServerConfigParam m_server_ip_ban_list
|
||||
SERVER_CFG_DEFAULT(StringToUIntServerConfigParam("server-ip-ban-list",
|
||||
"ip: IP in X.X.X.X/Y (CIDR) format for banning, use Y of 32 for a "
|
||||
|
@ -356,7 +356,7 @@ namespace StringUtils
|
||||
else
|
||||
{
|
||||
if(sv[i][1]=='s' || sv[i][1]=='d' || sv[i][1]=='i' ||
|
||||
sv[i][1]=='f')
|
||||
sv[i][1]=='f' || sv[i][1]=='u')
|
||||
{
|
||||
if (insertValID >= all_vals.size())
|
||||
{
|
||||
@ -429,7 +429,7 @@ namespace StringUtils
|
||||
else
|
||||
{
|
||||
if (sv[i][1]=='s' || sv[i][1]=='d' || sv[i][1]=='i' ||
|
||||
sv[i][1]=='f')
|
||||
sv[i][1]=='f' || sv[i][1]=='u')
|
||||
{
|
||||
if (insertValID >= all_vals.size())
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user