Cleanup of Sqlconnection

-moved all connectionstuff to a new class
-moved sqlstring functions to an own file
-do not give threads access to CSqlScore
This commit is contained in:
H-M-H 2015-11-22 00:52:12 +01:00
parent c1df605c5a
commit 9ed66f7adc
6 changed files with 732 additions and 692 deletions

View file

@ -4,6 +4,7 @@
#define ENGINE_SHARED_CONSOLE_H
#include <engine/console.h>
#include <base/math.h>
#include "memheap.h"
class CConsole : public IConsole

File diff suppressed because it is too large Load diff

View file

@ -4,41 +4,24 @@
#ifndef GAME_SERVER_SQLSCORE_H
#define GAME_SERVER_SQLSCORE_H
#include <mysql_connection.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/statement.h>
#include "sqlserver.h"
#include "../score.h"
class CSqlScore: public IScore
{
CGameContext *GameServer() { return m_pGameServer; }
IServer *Server() { return m_pServer; }
CSqlServer *SqlServer() { return &m_SqlServer; }
void Init();
CGameContext *m_pGameServer;
IServer *m_pServer;
sql::Driver *m_pDriver;
sql::Connection *m_pConnection;
sql::Statement *m_pStatement;
sql::ResultSet *m_pResults;
CSqlServer m_SqlServer;
// copy of config vars
const char* m_pDatabase;
const char* m_pPrefix;
const char* m_pUser;
const char* m_pPass;
const char* m_pIp;
char m_aMap[64];
int m_Port;
CGameContext *GameServer()
{
return m_pGameServer;
}
IServer *Server()
{
return m_pServer;
}
static void MapInfoThread(void *pUser);
static void MapVoteThread(void *pUser);
@ -57,17 +40,6 @@ class CSqlScore: public IScore
static void SaveTeamThread(void *pUser);
static void LoadTeamThread(void *pUser);
void Init();
bool Connect();
void Disconnect();
void FuzzyString(char *pString);
// anti SQL injection
void ClearString(char *pString, int size = 32);
void NormalizeMapname(char *pString);
public:
CSqlScore(CGameContext *pGameServer);
@ -94,19 +66,38 @@ public:
virtual void RandomUnfinishedMap(int ClientID, int stars);
virtual void SaveTeam(int Team, const char* Code, int ClientID, const char* Server);
virtual void LoadTeam(const char* Code, int ClientID);
static void agoTimeToString(int agoTime, char agoString[]);
};
struct CSqlMapData
// generic implementation to provide sqlserver, gameserver and server
struct CSqlData
{
CSqlScore *m_pSqlData;
CSqlData(CSqlServer* pSqlServer) : m_pSqlServer(pSqlServer) {}
CGameContext* GameServer() { return ms_pGameServer; }
IServer* Server() { return ms_pServer; }
CPlayerData* PlayerData(int ID) { return &ms_pPlayerData[ID]; }
const char* MapName() { return ms_pMap; }
CSqlServer* SqlServer() { return m_pSqlServer; }
static CGameContext *ms_pGameServer;
static IServer *ms_pServer;
static CPlayerData *ms_pPlayerData;
static const char *ms_pMap;
CSqlServer *m_pSqlServer;
};
struct CSqlMapData : CSqlData
{
CSqlMapData(CSqlServer* pSqlServer) : CSqlData(pSqlServer) {}
int m_ClientID;
char m_aMap[128];
};
struct CSqlScoreData
struct CSqlScoreData : CSqlData
{
CSqlScore *m_pSqlData;
CSqlScoreData(CSqlServer* pSqlServer) : CSqlData(pSqlServer) {}
int m_ClientID;
#if defined(CONF_FAMILY_WINDOWS)
char m_aName[16]; // Don't edit this, or all your teeth will fall http://bugs.mysql.com/bug.php?id=50046
@ -121,9 +112,10 @@ struct CSqlScoreData
char m_aRequestingPlayer[MAX_NAME_LENGTH];
};
struct CSqlTeamScoreData
struct CSqlTeamScoreData : CSqlData
{
CSqlScore *m_pSqlData;
CSqlTeamScoreData(CSqlServer* pSqlServer) : CSqlData(pSqlServer) {}
unsigned int m_Size;
int m_aClientIDs[MAX_CLIENTS];
#if defined(CONF_FAMILY_WINDOWS)
@ -139,20 +131,22 @@ struct CSqlTeamScoreData
char m_aRequestingPlayer[MAX_NAME_LENGTH];
};
struct CSqlTeamSave
struct CSqlTeamSave : CSqlData
{
CSqlTeamSave(CSqlServer* pSqlServer) : CSqlData(pSqlServer) {}
int m_Team;
int m_ClientID;
char m_Code[128];
char m_Server[5];
CSqlScore *m_pSqlData;
};
struct CSqlTeamLoad
struct CSqlTeamLoad : CSqlData
{
CSqlTeamLoad(CSqlServer* pSqlServer) : CSqlData(pSqlServer) {}
char m_Code[128];
int m_ClientID;
CSqlScore *m_pSqlData;
};
#endif

View file

@ -0,0 +1,137 @@
#ifndef GAME_SERVER_SQL_STRING_HELPERS_H
#define GAME_SERVER_SQL_STRING_HELPERS_H
#include <base/system.h>
void FuzzyString(char *pString)
{
char newString[32*4-1];
int pos = 0;
for(int i=0;i<64;i++)
{
if(!pString[i])
break;
newString[pos++] = pString[i];
if (pString[i] != '\\' && str_utf8_isstart(pString[i+1]))
newString[pos++] = '%';
}
newString[pos] = '\0';
strcpy(pString, newString);
}
// anti SQL injection
void ClearString(char *pString, int size = 32)
{
char *newString = (char *)malloc(size * 2 - 1);
int pos = 0;
for(int i=0;i<size;i++)
{
if(pString[i] == '\\')
{
newString[pos++] = '\\';
newString[pos++] = '\\';
}
else if(pString[i] == '\'')
{
newString[pos++] = '\\';
newString[pos++] = '\'';
}
else if(pString[i] == '"')
{
newString[pos++] = '\\';
newString[pos++] = '"';
}
else
{
newString[pos++] = pString[i];
}
}
newString[pos] = '\0';
strcpy(pString,newString);
free(newString);
}
void agoTimeToString(int agoTime, char agoString[])
{
char aBuf[20];
int times[7] =
{
60 * 60 * 24 * 365 ,
60 * 60 * 24 * 30 ,
60 * 60 * 24 * 7,
60 * 60 * 24 ,
60 * 60 ,
60 ,
1
};
char names[7][6] =
{
"year",
"month",
"week",
"day",
"hour",
"min",
"sec"
};
int seconds = 0;
char name[6];
int count = 0;
int i = 0;
// finding biggest match
for(i = 0; i<7; i++)
{
seconds = times[i];
strcpy(name,names[i]);
count = floor((float)agoTime/(float)seconds);
if(count != 0)
{
break;
}
}
if(count == 1)
{
str_format(aBuf, sizeof(aBuf), "%d %s", 1 , name);
}
else
{
str_format(aBuf, sizeof(aBuf), "%d %ss", count , name);
}
strcat(agoString,aBuf);
if (i + 1 < 7)
{
// getting second piece now
int seconds2 = times[i+1];
char name2[6];
strcpy(name2,names[i+1]);
// add second piece if it's greater than 0
int count2 = floor((float)(agoTime - (seconds * count)) / (float)seconds2);
if (count2 != 0)
{
if(count2 == 1)
{
str_format(aBuf, sizeof(aBuf), " and %d %s", 1 , name2);
}
else
{
str_format(aBuf, sizeof(aBuf), " and %d %ss", count2 , name2);
}
strcat(agoString,aBuf);
}
}
}
#endif

View file

@ -0,0 +1,194 @@
#include <base/system.h>
#include <engine/shared/protocol.h>
#include <engine/shared/config.h>
#include "sqlserver.h"
CSqlServer::CSqlServer(const char* pDatabase, const char* pPrefix, const char* pUser, const char* pPass, const char* pIp, int Port) :
m_pDatabase(pDatabase),
m_pPrefix(pPrefix),
m_pUser(pUser),
m_pPass(pPass),
m_pIp(pIp),
m_Port(Port)
{
m_pDriver = 0;
m_pConnection = 0;
m_pResults = 0;
m_pStatement = 0;
}
CSqlServer::~CSqlServer()
{
try
{
if (m_pResults)
delete m_pResults;
if (m_pConnection)
delete m_pConnection;
dbg_msg("SQL", "SQL connection disconnected");
}
catch (sql::SQLException &e)
{
dbg_msg("SQL", "ERROR: No SQL connection");
}
}
bool CSqlServer::Connect()
{
if (m_pDriver != NULL && m_pConnection != NULL)
{
try
{
// Connect to specific database
m_pConnection->setSchema(m_pDatabase);
}
catch (sql::SQLException &e)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what());
dbg_msg("SQL", aBuf);
dbg_msg("SQL", "ERROR: SQL connection failed");
return false;
}
return true;
}
try
{
m_pDriver = 0;
m_pConnection = 0;
m_pStatement = 0;
sql::ConnectOptionsMap connection_properties;
connection_properties["hostName"] = sql::SQLString(m_pIp);
connection_properties["port"] = m_Port;
connection_properties["userName"] = sql::SQLString(m_pUser);
connection_properties["password"] = sql::SQLString(m_pPass);
connection_properties["OPT_RECONNECT"] = true;
// Create connection
m_pDriver = get_driver_instance();
m_pConnection = m_pDriver->connect(connection_properties);
// Create Statement
m_pStatement = m_pConnection->createStatement();
// Connect to specific database
m_pConnection->setSchema(m_pDatabase);
dbg_msg("SQL", "SQL connection established");
return true;
}
catch (sql::SQLException &e)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what());
dbg_msg("SQL", aBuf);
dbg_msg("SQL", "ERROR: SQL connection failed");
return false;
}
catch (const std::exception& ex)
{
// ...
dbg_msg("SQL", "1 %s",ex.what());
}
catch (const std::string& ex)
{
// ...
dbg_msg("SQL", "2 %s",ex.c_str());
}
catch( int )
{
dbg_msg("SQL", "3 %s");
}
catch( float )
{
dbg_msg("SQL", "4 %s");
}
catch( char[] )
{
dbg_msg("SQL", "5 %s");
}
catch( char )
{
dbg_msg("SQL", "6 %s");
}
catch (...)
{
dbg_msg("SQL", "Unknown Error cause by the MySQL/C++ Connector, my advice compile server_debug and use it");
dbg_msg("SQL", "ERROR: SQL connection failed");
return false;
}
return false;
}
void CSqlServer::Disconnect()
{
}
void CSqlServer::CreateTables()
{
try
{
char aBuf[1024];
// create database
str_format(aBuf, sizeof(aBuf), "CREATE DATABASE IF NOT EXISTS %s", m_pDatabase);
m_pStatement->execute(aBuf);
// create tables
str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS %s_race (Map VARCHAR(128) BINARY NOT NULL, Name VARCHAR(%d) BINARY NOT NULL, Timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , Time FLOAT DEFAULT 0, Server CHAR(4), cp1 FLOAT DEFAULT 0, cp2 FLOAT DEFAULT 0, cp3 FLOAT DEFAULT 0, cp4 FLOAT DEFAULT 0, cp5 FLOAT DEFAULT 0, cp6 FLOAT DEFAULT 0, cp7 FLOAT DEFAULT 0, cp8 FLOAT DEFAULT 0, cp9 FLOAT DEFAULT 0, cp10 FLOAT DEFAULT 0, cp11 FLOAT DEFAULT 0, cp12 FLOAT DEFAULT 0, cp13 FLOAT DEFAULT 0, cp14 FLOAT DEFAULT 0, cp15 FLOAT DEFAULT 0, cp16 FLOAT DEFAULT 0, cp17 FLOAT DEFAULT 0, cp18 FLOAT DEFAULT 0, cp19 FLOAT DEFAULT 0, cp20 FLOAT DEFAULT 0, cp21 FLOAT DEFAULT 0, cp22 FLOAT DEFAULT 0, cp23 FLOAT DEFAULT 0, cp24 FLOAT DEFAULT 0, cp25 FLOAT DEFAULT 0, KEY (Map, Name)) CHARACTER SET utf8 ;", m_pPrefix, MAX_NAME_LENGTH);
executeSql(aBuf);
str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS %s_teamrace (Map VARCHAR(128) BINARY NOT NULL, Name VARCHAR(%d) BINARY NOT NULL, Timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, Time FLOAT DEFAULT 0, ID VARBINARY(16) NOT NULL, KEY Map (Map)) CHARACTER SET utf8 ;", m_pPrefix, MAX_NAME_LENGTH);
executeSql(aBuf);
str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS %s_maps (Map VARCHAR(128) BINARY NOT NULL, Server VARCHAR(32) BINARY NOT NULL, Mapper VARCHAR(128) BINARY NOT NULL, Points INT DEFAULT 0, Stars INT DEFAULT 0, Timestamp TIMESTAMP, UNIQUE KEY Map (Map)) CHARACTER SET utf8 ;", m_pPrefix);
executeSql(aBuf);
str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS %s_saves (Savegame TEXT CHARACTER SET utf8 BINARY NOT NULL, Map VARCHAR(128) BINARY NOT NULL, Code VARCHAR(128) BINARY NOT NULL, Timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, Server CHAR(4), UNIQUE KEY (Map, Code)) CHARACTER SET utf8 ;", m_pPrefix);
executeSql(aBuf);
str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS %s_points (Name VARCHAR(%d) BINARY NOT NULL, Points INT DEFAULT 0, UNIQUE KEY Name (Name)) CHARACTER SET utf8 ;", m_pPrefix, MAX_NAME_LENGTH);
executeSql(aBuf);
dbg_msg("SQL", "Tables were created successfully");
}
catch (sql::SQLException &e)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what());
dbg_msg("SQL", aBuf);
dbg_msg("SQL", "ERROR: Tables were NOT created");
}
}
void CSqlServer::executeSql(const char *pCommand)
{
m_pStatement->execute(pCommand);
}
void CSqlServer::executeSqlQuery(const char *pQuery)
{
if (m_pResults)
delete m_pResults;
m_pResults = m_pStatement->executeQuery(pQuery);
}
sql::ResultSet* CSqlServer::GetResults()
{
return m_pResults;
}
const char* CSqlServer::GetPrefix()
{
return m_pPrefix;
}

View file

@ -0,0 +1,40 @@
#ifndef GAME_SERVER_SQLSERVER_H
#define GAME_SERVER_SQLSERVER_H
#include <mysql_connection.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/statement.h>
class CSqlServer
{
public:
CSqlServer(const char* pDatabase, const char* pPrefix, const char* pUser, const char* pPass, const char* pIp, int Port);
~CSqlServer();
bool Connect();
void Disconnect();
void CreateTables();
void executeSql(const char* pCommand);
void executeSqlQuery(const char* pQuery);
sql::ResultSet* GetResults();
const char* GetPrefix();
private:
sql::Driver *m_pDriver;
sql::Connection *m_pConnection;
sql::Statement *m_pStatement;
sql::ResultSet *m_pResults;
// copy of config vars
const char* m_pDatabase;
const char* m_pPrefix;
const char* m_pUser;
const char* m_pPass;
const char* m_pIp;
int m_Port;
};
#endif