Add IPV6 support to stats database
This commit is contained in:
parent
f7da3c94f9
commit
58ad947443
@ -224,9 +224,9 @@ You have the best gaming experience when choosing server having all players less
|
|||||||
|
|
||||||
Currently STK uses sqlite (if building with sqlite3 on) for server management with the following functions at the moment:
|
Currently STK uses sqlite (if building with sqlite3 on) for server management with the following functions at the moment:
|
||||||
1. Server statistics
|
1. Server statistics
|
||||||
2. IP / online ID ban list
|
2. IPV4 / online ID ban list
|
||||||
3. Player reports
|
3. Player reports
|
||||||
4. IP geolocation
|
4. IPV4 geolocation
|
||||||
|
|
||||||
You need to create a database in sqlite first, run `sqlite3 stkservers.db` in the folder where (all) your server_config.xml(s) located.
|
You need to create a database in sqlite first, run `sqlite3 stkservers.db` in the folder where (all) your server_config.xml(s) located.
|
||||||
|
|
||||||
@ -236,6 +236,7 @@ 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
|
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
|
ip INTEGER UNSIGNED NOT NULL, -- IP decimal of host
|
||||||
|
ipv6 TEXT NOT NULL DEFAULT '', -- IPV6 (if exists) in string of host (only created if ipv6 server)
|
||||||
port INTEGER UNSIGNED NOT NULL, -- Port 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)
|
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)
|
username TEXT NOT NULL, -- First player name in the host (if the host has splitscreen player)
|
||||||
@ -272,7 +273,7 @@ CREATE TABLE IF NOT EXISTS (table name above)
|
|||||||
|
|
||||||
If you want to see flags and readable names of countries in the above views, you need to initialize `v(server database version)_countries` table, check [this script](tools/generate-countries-table.py).
|
If you want to see flags and readable names of countries in the above views, you need to initialize `v(server database version)_countries` table, check [this script](tools/generate-countries-table.py).
|
||||||
|
|
||||||
For IP and online ID ban list, player reports or IP mapping, you need to create one yourself:
|
For IPV4 and online ID ban list, player reports or IP mapping, you need to create one yourself:
|
||||||
```sql
|
```sql
|
||||||
CREATE TABLE ip_ban
|
CREATE TABLE ip_ban
|
||||||
(
|
(
|
||||||
@ -301,11 +302,13 @@ CREATE TABLE player_reports
|
|||||||
(
|
(
|
||||||
server_uid TEXT NOT NULL, -- Report from which server unique id (config filename)
|
server_uid TEXT NOT NULL, -- Report from which server unique id (config filename)
|
||||||
reporter_ip INTEGER UNSIGNED NOT NULL, -- IP decimal of player who reports
|
reporter_ip INTEGER UNSIGNED NOT NULL, -- IP decimal of player who reports
|
||||||
|
reporter_ipv6 TEXT NOT NULL DEFAULT '', -- IPV6 (if exists) in string of player who reports (only needed for ipv6 server)
|
||||||
reporter_online_id INTEGER UNSIGNED NOT NULL, -- Online id of player who reports, 0 for offline player
|
reporter_online_id INTEGER UNSIGNED NOT NULL, -- Online id of player who reports, 0 for offline player
|
||||||
reporter_username TEXT NOT NULL, -- Player name who reports
|
reporter_username TEXT NOT NULL, -- Player name who reports
|
||||||
reported_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Time of reporting
|
reported_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Time of reporting
|
||||||
info TEXT NOT NULL, -- Report info by reporter
|
info TEXT NOT NULL, -- Report info by reporter
|
||||||
reporting_ip INTEGER UNSIGNED NOT NULL, -- IP decimal of player being reported
|
reporting_ip INTEGER UNSIGNED NOT NULL, -- IP decimal of player being reported
|
||||||
|
reporting_ipv6 TEXT NOT NULL DEFAULT '', -- IPV6 (if exists) in string of player who reports (only needed for ipv6 server)
|
||||||
reporting_online_id INTEGER UNSIGNED NOT NULL, -- Online id of player being reported, 0 for offline player
|
reporting_online_id INTEGER UNSIGNED NOT NULL, -- Online id of player being reported, 0 for offline player
|
||||||
reporting_username TEXT NOT NULL -- Player name being reported
|
reporting_username TEXT NOT NULL -- Player name being reported
|
||||||
);
|
);
|
||||||
|
@ -222,11 +222,13 @@ void ServerLobby::initServerStatsTable()
|
|||||||
StringUtils::toString(ServerConfig::m_server_db_version) + "_" +
|
StringUtils::toString(ServerConfig::m_server_db_version) + "_" +
|
||||||
ServerConfig::m_server_uid + "_stats";
|
ServerConfig::m_server_uid + "_stats";
|
||||||
|
|
||||||
std::string query = StringUtils::insertValues(
|
std::ostringstream oss;
|
||||||
"CREATE TABLE IF NOT EXISTS %s (\n"
|
oss << "CREATE TABLE IF NOT EXISTS " << table_name << " (\n"
|
||||||
" host_id INTEGER UNSIGNED NOT NULL PRIMARY KEY, -- Unique host id in STKHost of each connection session for a STKPeer\n"
|
" host_id INTEGER UNSIGNED NOT NULL PRIMARY KEY, -- Unique host id in STKHost of each connection session for a STKPeer\n"
|
||||||
" ip INTEGER UNSIGNED NOT NULL, -- IP decimal of host\n"
|
" ip INTEGER UNSIGNED NOT NULL, -- IP decimal of host\n";
|
||||||
" port INTEGER UNSIGNED NOT NULL, -- Port of host\n"
|
if (ServerConfig::m_ipv6_server)
|
||||||
|
oss << " ipv6 TEXT NOT NULL DEFAULT '', -- IPV6 (if exists) in string of host\n";
|
||||||
|
oss << " port INTEGER UNSIGNED NOT NULL, -- Port of host\n"
|
||||||
" online_id INTEGER UNSIGNED NOT NULL, -- Online if of the host (0 for offline account)\n"
|
" online_id INTEGER UNSIGNED NOT NULL, -- Online if of the host (0 for offline account)\n"
|
||||||
" username TEXT NOT NULL, -- First player name in the host (if the host has splitscreen player)\n"
|
" username TEXT NOT NULL, -- First player name in the host (if the host has splitscreen player)\n"
|
||||||
" player_num INTEGER UNSIGNED NOT NULL, -- Number of player(s) from the host, more than 1 if it has splitscreen player\n"
|
" player_num INTEGER UNSIGNED NOT NULL, -- Number of player(s) from the host, more than 1 if it has splitscreen player\n"
|
||||||
@ -235,7 +237,8 @@ void ServerLobby::initServerStatsTable()
|
|||||||
" connected_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Time when connected\n"
|
" connected_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Time when connected\n"
|
||||||
" disconnected_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Time when disconnected (saved when disconnected)\n"
|
" disconnected_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Time when disconnected (saved when disconnected)\n"
|
||||||
" ping INTEGER UNSIGNED NOT NULL DEFAULT 0 -- Ping of the host\n"
|
" ping INTEGER UNSIGNED NOT NULL DEFAULT 0 -- Ping of the host\n"
|
||||||
") WITHOUT ROWID;", table_name.c_str());
|
") WITHOUT ROWID;";
|
||||||
|
std::string query = oss.str();
|
||||||
sqlite3_stmt* stmt = NULL;
|
sqlite3_stmt* stmt = NULL;
|
||||||
int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0);
|
int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0);
|
||||||
if (ret == SQLITE_OK)
|
if (ret == SQLITE_OK)
|
||||||
@ -278,11 +281,13 @@ void ServerLobby::initServerStatsTable()
|
|||||||
std::string full_stats_view_name = std::string("v") +
|
std::string full_stats_view_name = std::string("v") +
|
||||||
StringUtils::toString(ServerConfig::m_server_db_version) + "_" +
|
StringUtils::toString(ServerConfig::m_server_db_version) + "_" +
|
||||||
ServerConfig::m_server_uid + "_full_stats";
|
ServerConfig::m_server_uid + "_full_stats";
|
||||||
std::ostringstream oss;
|
oss.str("");
|
||||||
oss << "CREATE VIEW IF NOT EXISTS " << full_stats_view_name << " AS\n"
|
oss << "CREATE VIEW IF NOT EXISTS " << full_stats_view_name << " AS\n"
|
||||||
<< " SELECT host_id, ip,\n"
|
<< " SELECT host_id, ip,\n"
|
||||||
<< " ((ip >> 24) & 255) ||'.'|| ((ip >> 16) & 255) ||'.'|| ((ip >> 8) & 255) ||'.'|| ((ip ) & 255) AS ip_readable,\n"
|
<< " ((ip >> 24) & 255) ||'.'|| ((ip >> 16) & 255) ||'.'|| ((ip >> 8) & 255) ||'.'|| ((ip ) & 255) AS ip_readable,\n";
|
||||||
<< " port, online_id, username, player_num,\n"
|
if (ServerConfig::m_ipv6_server)
|
||||||
|
oss << " ipv6,";
|
||||||
|
oss << " port, online_id, username, player_num,\n"
|
||||||
<< " " << m_server_stats_table << ".country_code AS country_code, country_flag, country_name, version,\n"
|
<< " " << m_server_stats_table << ".country_code AS country_code, country_flag, country_name, version,\n"
|
||||||
<< " ROUND((STRFTIME(\"%s\", disconnected_time) - STRFTIME(\"%s\", connected_time)) / 60.0, 2) AS time_played,\n"
|
<< " ROUND((STRFTIME(\"%s\", disconnected_time) - STRFTIME(\"%s\", connected_time)) / 60.0, 2) AS time_played,\n"
|
||||||
<< " connected_time, disconnected_time, ping FROM " << m_server_stats_table << "\n"
|
<< " connected_time, disconnected_time, ping FROM " << m_server_stats_table << "\n"
|
||||||
@ -302,8 +307,10 @@ void ServerLobby::initServerStatsTable()
|
|||||||
oss.clear();
|
oss.clear();
|
||||||
oss << "CREATE VIEW IF NOT EXISTS " << current_players_view_name << " AS\n"
|
oss << "CREATE VIEW IF NOT EXISTS " << current_players_view_name << " AS\n"
|
||||||
<< " SELECT host_id, ip,\n"
|
<< " SELECT host_id, ip,\n"
|
||||||
<< " ((ip >> 24) & 255) ||'.'|| ((ip >> 16) & 255) ||'.'|| ((ip >> 8) & 255) ||'.'|| ((ip ) & 255) AS ip_readable,\n"
|
<< " ((ip >> 24) & 255) ||'.'|| ((ip >> 16) & 255) ||'.'|| ((ip >> 8) & 255) ||'.'|| ((ip ) & 255) AS ip_readable,\n";
|
||||||
<< " port, online_id, username, player_num,\n"
|
if (ServerConfig::m_ipv6_server)
|
||||||
|
oss << " ipv6,";
|
||||||
|
oss << " port, online_id, username, player_num,\n"
|
||||||
<< " " << m_server_stats_table << ".country_code AS country_code, country_flag, country_name, version,\n"
|
<< " " << m_server_stats_table << ".country_code AS country_code, country_flag, country_name, version,\n"
|
||||||
<< " ROUND((STRFTIME(\"%s\", 'now') - STRFTIME(\"%s\", connected_time)) / 60.0, 2) AS time_played,\n"
|
<< " ROUND((STRFTIME(\"%s\", 'now') - STRFTIME(\"%s\", connected_time)) / 60.0, 2) AS time_played,\n"
|
||||||
<< " connected_time, ping FROM " << m_server_stats_table << "\n"
|
<< " connected_time, ping FROM " << m_server_stats_table << "\n"
|
||||||
@ -338,7 +345,10 @@ void ServerLobby::initServerStatsTable()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
oss << "CREATE VIEW IF NOT EXISTS " << player_stats_view_name << " AS\n"
|
oss << "CREATE VIEW IF NOT EXISTS " << player_stats_view_name << " AS\n"
|
||||||
<< " SELECT a.online_id, a.username, a.ip, a.ip_readable, a.port, a.player_num,\n"
|
<< " SELECT a.online_id, a.username, a.ip, a.ip_readable,\n";
|
||||||
|
if (ServerConfig::m_ipv6_server)
|
||||||
|
oss << " a.ipv6,";
|
||||||
|
oss << " a.port, a.player_num,\n"
|
||||||
<< " a.country_code, a.country_flag, a.country_name, a.version, a.ping,\n"
|
<< " a.country_code, a.country_flag, a.country_name, a.version, a.ping,\n"
|
||||||
<< " b.num_connections, b.first_connected_time, b.first_disconnected_time,\n"
|
<< " b.num_connections, b.first_connected_time, b.first_disconnected_time,\n"
|
||||||
<< " a.connected_time AS last_connected_time, a.disconnected_time AS last_disconnected_time,\n"
|
<< " a.connected_time AS last_connected_time, a.disconnected_time AS last_disconnected_time,\n"
|
||||||
@ -923,14 +933,32 @@ void ServerLobby::writePlayerReport(Event* event)
|
|||||||
return;
|
return;
|
||||||
auto reporting_npp = reporting_peer->getPlayerProfiles()[0];
|
auto reporting_npp = reporting_peer->getPlayerProfiles()[0];
|
||||||
|
|
||||||
std::string query = StringUtils::insertValues(
|
std::string query;
|
||||||
"INSERT INTO %s "
|
if (ServerConfig::m_ipv6_server)
|
||||||
"(server_uid, reporter_ip, reporter_online_id, reporter_username, "
|
{
|
||||||
"info, reporting_ip, reporting_online_id, reporting_username) "
|
// We don't save the internally mapped ipv4 (0.x.x.x)
|
||||||
"VALUES (?, %u, %u, ?, ?, %u, %u, ?);",
|
query = StringUtils::insertValues(
|
||||||
ServerConfig::m_player_reports_table.c_str(),
|
"INSERT INTO %s "
|
||||||
reporter->getAddress().getIP(), reporter_npp->getOnlineId(),
|
"(server_uid, reporter_ip, reporter_ipv6, reporter_online_id, reporter_username, "
|
||||||
reporting_peer->getAddress().getIP(), reporting_npp->getOnlineId());
|
"info, reporting_ip, reporting_ipv6, reporting_online_id, reporting_username) "
|
||||||
|
"VALUES (?, %u, \"%s\", %u, ?, ?, %u, \"%s\", %u, ?);",
|
||||||
|
ServerConfig::m_player_reports_table.c_str(),
|
||||||
|
reporter->getIPV6Address().empty() ? reporter->getAddress().getIP() : 0,
|
||||||
|
reporter->getIPV6Address(), reporter_npp->getOnlineId(),
|
||||||
|
reporting_peer->getIPV6Address().empty() ? reporting_peer->getAddress().getIP() : 0,
|
||||||
|
reporting_peer->getIPV6Address(), reporting_npp->getOnlineId());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
query = StringUtils::insertValues(
|
||||||
|
"INSERT INTO %s "
|
||||||
|
"(server_uid, reporter_ip, reporter_online_id, reporter_username, "
|
||||||
|
"info, reporting_ip, reporting_online_id, reporting_username) "
|
||||||
|
"VALUES (?, %u, %u, ?, ?, %u, %u, ?);",
|
||||||
|
ServerConfig::m_player_reports_table.c_str(),
|
||||||
|
reporter->getAddress().getIP(), reporter_npp->getOnlineId(),
|
||||||
|
reporting_peer->getAddress().getIP(), reporting_npp->getOnlineId());
|
||||||
|
}
|
||||||
bool written = easySQLQuery(query,
|
bool written = easySQLQuery(query,
|
||||||
[reporter_npp, reporting_npp, info](sqlite3_stmt* stmt)
|
[reporter_npp, reporting_npp, info](sqlite3_stmt* stmt)
|
||||||
{
|
{
|
||||||
@ -3026,14 +3054,30 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr<STKPeer> peer,
|
|||||||
#ifdef ENABLE_SQLITE3
|
#ifdef ENABLE_SQLITE3
|
||||||
if (m_server_stats_table.empty())
|
if (m_server_stats_table.empty())
|
||||||
return;
|
return;
|
||||||
std::string query = StringUtils::insertValues(
|
std::string query;
|
||||||
"INSERT INTO %s "
|
if (ServerConfig::m_ipv6_server && !peer->getIPV6Address().empty())
|
||||||
"(host_id, ip, port, online_id, username, player_num, "
|
{
|
||||||
"country_code, version, ping) "
|
// We don't save the internally mapped ipv4 (0.x.x.x)
|
||||||
"VALUES (%u, %u, %u, %u, ?, %u, ?, ?, %u);",
|
query = StringUtils::insertValues(
|
||||||
m_server_stats_table.c_str(), peer->getHostId(),
|
"INSERT INTO %s "
|
||||||
peer->getAddress().getIP(), peer->getAddress().getPort(), online_id,
|
"(host_id, ip, ipv6 ,port, online_id, username, player_num, "
|
||||||
player_count, peer->getAveragePing());
|
"country_code, version, ping) "
|
||||||
|
"VALUES (%u, 0, \"%s\" ,%u, %u, ?, %u, ?, ?, %u);",
|
||||||
|
m_server_stats_table.c_str(), peer->getHostId(),
|
||||||
|
peer->getIPV6Address(), peer->getAddress().getPort(), online_id,
|
||||||
|
player_count, peer->getAveragePing());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
query = StringUtils::insertValues(
|
||||||
|
"INSERT INTO %s "
|
||||||
|
"(host_id, ip, port, online_id, username, player_num, "
|
||||||
|
"country_code, version, ping) "
|
||||||
|
"VALUES (%u, %u, %u, %u, ?, %u, ?, ?, %u);",
|
||||||
|
m_server_stats_table.c_str(), peer->getHostId(),
|
||||||
|
peer->getAddress().getIP(), peer->getAddress().getPort(),
|
||||||
|
online_id, player_count, peer->getAveragePing());
|
||||||
|
}
|
||||||
easySQLQuery(query, [peer, country_code](sqlite3_stmt* stmt)
|
easySQLQuery(query, [peer, country_code](sqlite3_stmt* stmt)
|
||||||
{
|
{
|
||||||
if (sqlite3_bind_text(stmt, 1, StringUtils::wideToUtf8(
|
if (sqlite3_bind_text(stmt, 1, StringUtils::wideToUtf8(
|
||||||
@ -3841,6 +3885,10 @@ void ServerLobby::testBannedForIP(STKPeer* peer) const
|
|||||||
if (!m_db || !m_ip_ban_table_exists)
|
if (!m_db || !m_ip_ban_table_exists)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// We only test for ipv4 atm
|
||||||
|
if (!peer->getIPV6Address().empty())
|
||||||
|
return;
|
||||||
|
|
||||||
int row_id = -1;
|
int row_id = -1;
|
||||||
unsigned ip_start = 0;
|
unsigned ip_start = 0;
|
||||||
unsigned ip_end = 0;
|
unsigned ip_end = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user