Add server stats table and writing handling
This commit is contained in:
parent
f397064850
commit
f6e8ff2936
@ -252,15 +252,148 @@ void ServerLobby::initDatabase()
|
|||||||
#endif
|
#endif
|
||||||
} // initDatabase
|
} // initDatabase
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void ServerLobby::initServerStatsTable()
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_SQLITE3
|
||||||
|
if (!ServerConfig::m_sql_management || !m_db)
|
||||||
|
return;
|
||||||
|
std::string table_name = std::string("v") +
|
||||||
|
StringUtils::toString(ServerConfig::m_server_db_version) + "_" +
|
||||||
|
ServerConfig::m_server_uid + "_stats";
|
||||||
|
|
||||||
|
std::string query = StringUtils::insertValues(
|
||||||
|
"CREATE TABLE IF NOT EXISTS %s (\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"
|
||||||
|
" 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"
|
||||||
|
" username TEXT NOT NULL, -- First player name in the host (if the host has splitscreen player)\n"
|
||||||
|
" player_num INEGER UNSIGNED NOT NULL, -- Number of player(s) from the host, more than 1 if it has splitscreen player\n"
|
||||||
|
" country_id TEXT NULL DEFAULT NULL, -- Country id of the host\n"
|
||||||
|
" version TEXT NOT NULL, -- SuperTuxKart version of the host (with OS info)\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"
|
||||||
|
" ping INEGER UNSIGNED NOT NULL DEFAULT 0 -- Ping of the host\n"
|
||||||
|
") WITHOUT ROWID;", table_name.c_str());
|
||||||
|
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)
|
||||||
|
m_server_stats_table = table_name;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::error("ServerLobby", "Error finalize database: %s",
|
||||||
|
sqlite3_errmsg(m_db));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::error("ServerLobby", "Error preparing database: %s",
|
||||||
|
sqlite3_errmsg(m_db));
|
||||||
|
}
|
||||||
|
if (m_server_stats_table.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t last_host_id = 0;
|
||||||
|
query = StringUtils::insertValues("SELECT MAX(host_id) FROM %s;",
|
||||||
|
m_server_stats_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 && sqlite3_column_type(stmt, 0) != SQLITE_NULL)
|
||||||
|
{
|
||||||
|
last_host_id = (unsigned)sqlite3_column_int64(stmt, 0);
|
||||||
|
Log::info("ServerLobby", "%u was last server session max host id.",
|
||||||
|
last_host_id);
|
||||||
|
}
|
||||||
|
ret = sqlite3_finalize(stmt);
|
||||||
|
if (ret != SQLITE_OK)
|
||||||
|
{
|
||||||
|
Log::error("ServerLobby", "Error finalize database: %s",
|
||||||
|
sqlite3_errmsg(m_db));
|
||||||
|
m_server_stats_table = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::error("ServerLobby", "Error preparing database: %s",
|
||||||
|
sqlite3_errmsg(m_db));
|
||||||
|
m_server_stats_table = "";
|
||||||
|
}
|
||||||
|
STKHost::get()->setNextHostId(last_host_id);
|
||||||
|
|
||||||
|
// Update disconnected time (if stk crashed it will not be written)
|
||||||
|
query = StringUtils::insertValues(
|
||||||
|
"UPDATE %s SET disconnected_time = datetime('now')"
|
||||||
|
"WHERE connected_time = disconnected_time;",
|
||||||
|
m_server_stats_table.c_str());
|
||||||
|
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
|
||||||
|
} // initServerStatsTable
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void ServerLobby::destroyDatabase()
|
void ServerLobby::destroyDatabase()
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_SQLITE3
|
#ifdef ENABLE_SQLITE3
|
||||||
|
auto peers = STKHost::get()->getPeers();
|
||||||
|
for (auto& peer : peers)
|
||||||
|
writeDisconnectInfoTable(peer.get());
|
||||||
if (m_db != NULL)
|
if (m_db != NULL)
|
||||||
sqlite3_close(m_db);
|
sqlite3_close(m_db);
|
||||||
#endif
|
#endif
|
||||||
} // destroyDatabase
|
} // destroyDatabase
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void ServerLobby::writeDisconnectInfoTable(STKPeer* peer)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_SQLITE3
|
||||||
|
if (m_server_stats_table.empty())
|
||||||
|
return;
|
||||||
|
std::string query = StringUtils::insertValues(
|
||||||
|
"UPDATE %s SET disconnected_time = datetime('now'), ping = %d "
|
||||||
|
"WHERE host_id = %u;", m_server_stats_table.c_str(),
|
||||||
|
peer->getAveragePing(), peer->getHostId());
|
||||||
|
|
||||||
|
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
|
||||||
|
} // writeDisconnectInfoTable
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Called whenever server is reset or game mode is changed.
|
/** Called whenever server is reset or game mode is changed.
|
||||||
*/
|
*/
|
||||||
@ -2151,6 +2284,8 @@ void ServerLobby::clientDisconnected(Event* event)
|
|||||||
}, msg);
|
}, msg);
|
||||||
updatePlayerList();
|
updatePlayerList();
|
||||||
delete msg;
|
delete msg;
|
||||||
|
|
||||||
|
writeDisconnectInfoTable(event->getPeer());
|
||||||
} // clientDisconnected
|
} // clientDisconnected
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -2235,7 +2370,7 @@ void ServerLobby::connectionRequested(Event* event)
|
|||||||
NetworkString *message = getNetworkString(2);
|
NetworkString *message = getNetworkString(2);
|
||||||
message->setSynchronous(true);
|
message->setSynchronous(true);
|
||||||
message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_BUSY);
|
message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_BUSY);
|
||||||
// send only to the peer that made the request and disconect it now
|
// send only to the peer that made the request and disconnect it now
|
||||||
peer->sendPacket(message, true/*reliable*/, false/*encrypted*/);
|
peer->sendPacket(message, true/*reliable*/, false/*encrypted*/);
|
||||||
peer->reset();
|
peer->reset();
|
||||||
delete message;
|
delete message;
|
||||||
@ -2553,6 +2688,37 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr<STKPeer> peer,
|
|||||||
getRankingForPlayer(peer->getPlayerProfiles()[0]);
|
getRankingForPlayer(peer->getPlayerProfiles()[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef ENABLE_SQLITE3
|
||||||
|
if (m_server_stats_table.empty())
|
||||||
|
return;
|
||||||
|
std::string query = StringUtils::insertValues(
|
||||||
|
"INSERT INTO %s "
|
||||||
|
"(host_id, ip, port, online_id, username, player_num, version, ping) "
|
||||||
|
"VALUES (%u, %u, %u, %u, \"%s\", %u, \"%s\", %u);",
|
||||||
|
m_server_stats_table.c_str(), peer->getHostId(),
|
||||||
|
peer->getAddress().getIP(), peer->getAddress().getPort(), online_id,
|
||||||
|
StringUtils::wideToUtf8(
|
||||||
|
peer->getPlayerProfiles()[0]->getName()).c_str(), player_count,
|
||||||
|
peer->getUserVersion().c_str(), peer->getAveragePing());
|
||||||
|
|
||||||
|
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
|
||||||
} // handleUnencryptedConnection
|
} // handleUnencryptedConnection
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -73,6 +73,8 @@ private:
|
|||||||
#ifdef ENABLE_SQLITE3
|
#ifdef ENABLE_SQLITE3
|
||||||
sqlite3* m_db;
|
sqlite3* m_db;
|
||||||
|
|
||||||
|
std::string m_server_stats_table;
|
||||||
|
|
||||||
bool m_ip_ban_table_exists;
|
bool m_ip_ban_table_exists;
|
||||||
|
|
||||||
bool m_online_id_ban_table_exists;
|
bool m_online_id_ban_table_exists;
|
||||||
@ -315,6 +317,7 @@ private:
|
|||||||
void kickPlayerWithReason(STKPeer* peer, const char* reason) const;
|
void kickPlayerWithReason(STKPeer* peer, const char* reason) const;
|
||||||
void testBannedForIP(STKPeer* peer) const;
|
void testBannedForIP(STKPeer* peer) const;
|
||||||
void testBannedForOnlineId(STKPeer* peer, uint32_t online_id) const;
|
void testBannedForOnlineId(STKPeer* peer, uint32_t online_id) const;
|
||||||
|
void writeDisconnectInfoTable(STKPeer* peer);
|
||||||
public:
|
public:
|
||||||
ServerLobby();
|
ServerLobby();
|
||||||
virtual ~ServerLobby();
|
virtual ~ServerLobby();
|
||||||
@ -344,6 +347,7 @@ public:
|
|||||||
void saveInitialItems();
|
void saveInitialItems();
|
||||||
void saveIPBanTable(const TransportAddress& addr);
|
void saveIPBanTable(const TransportAddress& addr);
|
||||||
void listBanTable();
|
void listBanTable();
|
||||||
|
void initServerStatsTable();
|
||||||
}; // class ServerLobby
|
}; // class ServerLobby
|
||||||
|
|
||||||
#endif // SERVER_LOBBY_HPP
|
#endif // SERVER_LOBBY_HPP
|
||||||
|
@ -46,6 +46,7 @@ namespace ServerConfig
|
|||||||
{
|
{
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
std::string g_server_config_path;
|
std::string g_server_config_path;
|
||||||
|
std::string m_server_uid;
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
FloatServerConfigParam::FloatServerConfigParam(float default_value,
|
FloatServerConfigParam::FloatServerConfigParam(float default_value,
|
||||||
const char* param_name,
|
const char* param_name,
|
||||||
@ -121,6 +122,8 @@ void loadServerConfig(const std::string& path)
|
|||||||
g_server_config_path = file_manager->getFileSystem()
|
g_server_config_path = file_manager->getFileSystem()
|
||||||
->getAbsolutePath(path.c_str()).c_str();
|
->getAbsolutePath(path.c_str()).c_str();
|
||||||
}
|
}
|
||||||
|
m_server_uid = StringUtils::removeExtension(
|
||||||
|
StringUtils::getBasename(g_server_config_path));
|
||||||
const XMLNode* root = file_manager->createXMLTree(g_server_config_path);
|
const XMLNode* root = file_manager->createXMLTree(g_server_config_path);
|
||||||
loadServerConfigXML(root, default_config);
|
loadServerConfigXML(root, default_config);
|
||||||
} // loadServerConfig
|
} // loadServerConfig
|
||||||
|
@ -349,6 +349,13 @@ namespace ServerConfig
|
|||||||
/** Server version, will be advanced if there are protocol changes. */
|
/** Server version, will be advanced if there are protocol changes. */
|
||||||
static const uint32_t m_server_version = 6;
|
static const uint32_t m_server_version = 6;
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
/** Server database version, will be advanced if there are protocol
|
||||||
|
* changes. */
|
||||||
|
static const uint32_t m_server_db_version = 1;
|
||||||
|
// ========================================================================
|
||||||
|
/** Server uid, extracted from server_config.xml file with .xml removed. */
|
||||||
|
extern std::string m_server_uid;
|
||||||
|
// ========================================================================
|
||||||
void loadServerConfig(const std::string& path = "");
|
void loadServerConfig(const std::string& path = "");
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void loadServerConfigXML(const XMLNode* root, bool default_config = false);
|
void loadServerConfigXML(const XMLNode* root, bool default_config = false);
|
||||||
|
@ -79,8 +79,11 @@ std::shared_ptr<LobbyProtocol> STKHost::create(SeparateProcess* p)
|
|||||||
std::shared_ptr<LobbyProtocol> lp;
|
std::shared_ptr<LobbyProtocol> lp;
|
||||||
if (NetworkConfig::get()->isServer())
|
if (NetworkConfig::get()->isServer())
|
||||||
{
|
{
|
||||||
lp = LobbyProtocol::create<ServerLobby>();
|
std::shared_ptr<ServerLobby> sl =
|
||||||
|
LobbyProtocol::create<ServerLobby>();
|
||||||
m_stk_host = new STKHost(true/*server*/);
|
m_stk_host = new STKHost(true/*server*/);
|
||||||
|
sl->initServerStatsTable();
|
||||||
|
lp = sl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -929,8 +932,9 @@ void STKHost::mainLoop()
|
|||||||
Event* stk_event = NULL;
|
Event* stk_event = NULL;
|
||||||
if (event.type == ENET_EVENT_TYPE_CONNECT)
|
if (event.type == ENET_EVENT_TYPE_CONNECT)
|
||||||
{
|
{
|
||||||
|
// ++m_next_unique_host_id for unique host id for database
|
||||||
auto stk_peer = std::make_shared<STKPeer>
|
auto stk_peer = std::make_shared<STKPeer>
|
||||||
(event.peer, this, m_next_unique_host_id++);
|
(event.peer, this, ++m_next_unique_host_id);
|
||||||
std::unique_lock<std::mutex> lock(m_peers_mutex);
|
std::unique_lock<std::mutex> lock(m_peers_mutex);
|
||||||
m_peers[event.peer] = stk_peer;
|
m_peers[event.peer] = stk_peer;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
@ -315,6 +315,8 @@ public:
|
|||||||
return m_next_unique_host_id;
|
return m_next_unique_host_id;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
void setNextHostId(uint32_t id) { m_next_unique_host_id = id; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the number of currently connected peers. */
|
/** Returns the number of currently connected peers. */
|
||||||
unsigned int getPeerCount() const
|
unsigned int getPeerCount() const
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user