Add sqlite3 for ip / online id ban table

This commit is contained in:
Benau 2019-05-06 00:19:58 +08:00
parent 7d19ccaad8
commit bcc3aef4c8
7 changed files with 467 additions and 28 deletions

View File

@ -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_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_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_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) option(USE_CRYPTO_OPENSSL "Use OpenSSL instead of Nettle for cryptography in STK." OFF)
CMAKE_DEPENDENT_OPTION(BUILD_RECORDER "Build opengl recorder" ON CMAKE_DEPENDENT_OPTION(BUILD_RECORDER "Build opengl recorder" ON
@ -363,6 +364,23 @@ if(USE_LIBBFD)
endif() endif()
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 # Set some compiler options
if(UNIX OR MINGW) if(UNIX OR MINGW)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
@ -518,6 +536,10 @@ target_link_libraries(supertuxkart
${CURL_LIBRARIES} ${CURL_LIBRARIES}
) )
if (USE_SQLITE3)
target_link_libraries(supertuxkart ${SQLITE3_LIBRARY})
endif()
if (USE_CRYPTO_OPENSSL) if (USE_CRYPTO_OPENSSL)
target_link_libraries(supertuxkart ${OPENSSL_CRYPTO_LIBRARY}) target_link_libraries(supertuxkart ${OPENSSL_CRYPTO_LIBRARY})
else() else()

View File

@ -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. 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. 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
);
```

View File

@ -91,6 +91,8 @@ void mainLoop(STKHost* host)
peer->kick(); peer->kick();
// ATM use permanently ban // ATM use permanently ban
auto sl = LobbyProtocol::get<ServerLobby>(); auto sl = LobbyProtocol::get<ServerLobby>();
if (sl)
sl->saveIPBanTable(peer->getAddress());
auto lock = sl->acquireConnectionMutex(); auto lock = sl->acquireConnectionMutex();
ServerConfig::m_server_ip_ban_list ServerConfig::m_server_ip_ban_list
[peer->getAddress().toString(false/*show_port*/) + "/32"] [peer->getAddress().toString(false/*show_port*/) + "/32"]
@ -114,6 +116,10 @@ void mainLoop(STKHost* host)
} }
else if (str == "listban") else if (str == "listban")
{ {
auto sl = LobbyProtocol::get<ServerLobby>();
if (sl)
sl->listBanTable();
for (auto& ban : ServerConfig::m_server_ip_ban_list) for (auto& ban : ServerConfig::m_server_ip_ban_list)
{ {
if (ban.first == "0.0.0.0/0") if (ban.first == "0.0.0.0/0")

View File

@ -55,6 +55,7 @@
#include <algorithm> #include <algorithm>
#include <fstream> #include <fstream>
#include <iostream>
#include <iterator> #include <iterator>
/** This is the central game setup protocol running in the server. It is /** 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_difficulty.store(ServerConfig::m_server_difficulty);
m_game_mode.store(ServerConfig::m_server_mode); m_game_mode.store(ServerConfig::m_server_mode);
m_default_vote = new PeerVote(); m_default_vote = new PeerVote();
initDatabase();
} // ServerLobby } // ServerLobby
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -161,8 +163,105 @@ ServerLobby::~ServerLobby()
if (m_save_server_config) if (m_save_server_config)
ServerConfig::writeServerConfigToDisk(); ServerConfig::writeServerConfigToDisk();
delete m_default_vote; delete m_default_vote;
destroyDatabase();
} // ~ServerLobby } // ~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. /** Called whenever server is reset or game mode is changed.
*/ */
@ -2075,6 +2174,51 @@ void ServerLobby::clearDisconnectedRankedPlayer()
} }
} // 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) void ServerLobby::connectionRequested(Event* event)
{ {
@ -2207,33 +2351,16 @@ void ServerLobby::connectionRequested(Event* event)
online_id = data.getUInt32(); online_id = data.getUInt32();
encrypted_size = data.getUInt32(); encrypted_size = data.getUInt32();
bool is_banned = isBannedForIP(peer->getAddress()); // Will be disconnected if banned by IP
if (online_id != 0 && !is_banned) testBannedForIP(peer.get());
{ if (peer->isDisconnected())
if (m_online_id_ban_list.find(online_id) != return;
m_online_id_ban_list.end() &&
(uint32_t)StkTime::getTimeSinceEpoch() < if (online_id != 0)
m_online_id_ban_list.at(online_id)) testBannedForOnlineId(peer.get(), online_id);
{ // Will be disconnected if banned by online id
is_banned = true; if (peer->isDisconnected())
}
}
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");
return; return;
}
unsigned total_players = 0; unsigned total_players = 0;
STKHost::get()->updatePlayers(NULL, NULL, &total_players); STKHost::get()->updatePlayers(NULL, NULL, &total_players);
@ -3253,6 +3380,192 @@ void ServerLobby::resetServer()
WAITING_FOR_START_GAME : REGISTER_SELF_ADDRESS; WAITING_FOR_START_GAME : REGISTER_SELF_ADDRESS;
} // resetServer } // 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 bool ServerLobby::isBannedForIP(const TransportAddress& addr) const
{ {

View File

@ -34,6 +34,10 @@
#include <set> #include <set>
#include <tuple> #include <tuple>
#ifdef ENABLE_SQLITE3
#include <sqlite3.h>
#endif
class BareNetworkString; class BareNetworkString;
class NetworkString; class NetworkString;
class NetworkPlayerProfile; class NetworkPlayerProfile;
@ -66,6 +70,17 @@ private:
irr::core::stringw m_name; irr::core::stringw m_name;
bool m_tried = false; 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; std::atomic<ServerState> m_state;
@ -305,6 +320,9 @@ private:
void handleKartInfo(Event* event); void handleKartInfo(Event* event);
void clientInGameWantsToBackLobby(Event* event); void clientInGameWantsToBackLobby(Event* event);
void clientSelectingAssetsWantsToBackLobby(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: public:
ServerLobby(); ServerLobby();
virtual ~ServerLobby(); virtual ~ServerLobby();
@ -333,6 +351,8 @@ public:
int getDifficulty() const { return m_difficulty.load(); } int getDifficulty() const { return m_difficulty.load(); }
int getGameMode() const { return m_game_mode.load(); } int getGameMode() const { return m_game_mode.load(); }
void saveInitialItems(); void saveInitialItems();
void saveIPBanTable(const TransportAddress& addr);
void listBanTable();
}; // class ServerLobby }; // class ServerLobby
#endif // SERVER_LOBBY_HPP #endif // SERVER_LOBBY_HPP

View File

@ -319,6 +319,32 @@ namespace ServerConfig
"more rewind, which clients with slow device may have problem playing " "more rewind, which clients with slow device may have problem playing "
"this server, use the default value is recommended.")); "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_PREFIX StringToUIntServerConfigParam m_server_ip_ban_list
SERVER_CFG_DEFAULT(StringToUIntServerConfigParam("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 " "ip: IP in X.X.X.X/Y (CIDR) format for banning, use Y of 32 for a "

View File

@ -356,7 +356,7 @@ namespace StringUtils
else else
{ {
if(sv[i][1]=='s' || sv[i][1]=='d' || sv[i][1]=='i' || 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()) if (insertValID >= all_vals.size())
{ {
@ -429,7 +429,7 @@ namespace StringUtils
else else
{ {
if (sv[i][1]=='s' || sv[i][1]=='d' || sv[i][1]=='i' || 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()) if (insertValID >= all_vals.size())
{ {