Fix race condition in /map (untested)

This commit is contained in:
def 2019-06-25 21:03:15 +02:00
parent 6e24bf9ae2
commit f7e642bbbe
9 changed files with 58 additions and 21 deletions

View file

@ -511,7 +511,7 @@ void CGameContext::ConMap(IConsole::IResult *pResult, void *pUserData)
return;
#endif
pSelf->Score()->MapVote(pResult->m_ClientID, pResult->GetString(0));
pSelf->Score()->MapVote(&pSelf->m_pMapVoteResult, pResult->m_ClientID, pResult->GetString(0));
#if defined(CONF_SQL)
if(g_Config.m_SvUseSQL)

View file

@ -56,6 +56,9 @@ void CGameContext::Construct(int Resetting)
m_ChatResponseTargetID = -1;
m_aDeleteTempfile[0] = 0;
m_TeeHistorianActive = false;
m_pRandomMapResult = nullptr;
m_pMapVoteResult = nullptr;
}
CGameContext::CGameContext(int Resetting)
@ -876,6 +879,23 @@ void CGameContext::OnTick()
m_pRandomMapResult = NULL;
}
if(m_pMapVoteResult && m_pMapVoteResult->m_Done)
{
m_VoteKick = false;
m_VoteSpec = false;
m_LastMapVote = time_get();
char aCmd[256];
str_format(aCmd, sizeof(aCmd), "sv_reset_file types/%s/flexreset.cfg; change_map \"%s\"", m_pMapVoteResult->m_aServer, m_pMapVoteResult->m_aMap);
char aChatmsg[512];
str_format(aChatmsg, sizeof(aChatmsg), "'%s' called vote to change server option '%s' (%s)", Server()->ClientName(m_pMapVoteResult->m_ClientID), m_pMapVoteResult->m_aMap, "/map");
CallVote(m_pMapVoteResult->m_ClientID, m_pMapVoteResult->m_aMap, aCmd, "/map", aChatmsg);
m_pMapVoteResult = NULL;
}
#ifdef CONF_DEBUG
if(g_Config.m_DbgDummies)
{

View file

@ -57,6 +57,7 @@ class IConsole;
class IEngine;
class IStorage;
class CRandomMapResult;
class CMapVoteResult;
class CGameContext : public IGameServer
{
@ -77,6 +78,7 @@ class CGameContext : public IGameServer
CMapBugs m_MapBugs;
std::shared_ptr<CRandomMapResult> m_pRandomMapResult;
std::shared_ptr<CMapVoteResult> m_pMapVoteResult;
static void CommandCallback(int ClientID, int FlagMask, const char *pCmd, IConsole::IResult *pResult, void *pUser);
static void TeeHistorianWrite(const void *pData, int DataSize, void *pUser);

View file

@ -51,6 +51,17 @@ public:
CRandomMapResult() : m_Done(false) {}
};
class CMapVoteResult
{
public:
bool m_Done;
char m_aMap[64];
char m_aServer[32];
int m_ClientID;
CMapVoteResult() : m_Done(false) {}
};
class IScore
{
CPlayerData m_aPlayerData[MAX_CLIENTS];
@ -61,7 +72,7 @@ public:
CPlayerData *PlayerData(int ID) { return &m_aPlayerData[ID]; }
virtual void MapInfo(int ClientID, const char *pMapName) = 0;
virtual void MapVote(int ClientID, const char *pMapName) = 0;
virtual void MapVote(std::shared_ptr<CMapVoteResult> *ppResult, int ClientID, const char *pMapName) = 0;
virtual void CheckBirthday(int ClientID) = 0;
virtual void LoadScore(int ClientID) = 0;
virtual void SaveScore(int ClientID, float Time, const char *pTimestamp, float aCpTime[NUM_CHECKPOINTS], bool NotEligible) = 0;

View file

@ -59,7 +59,7 @@ void CFileScore::MapInfo(int ClientID, const char* MapName)
// TODO: implement
}
void CFileScore::MapVote(int ClientID, const char* MapName)
void CFileScore::MapVote(std::shared_ptr<CMapVoteResult> *ppResult, int ClientID, const char* MapName)
{
// TODO: implement
}

View file

@ -65,7 +65,7 @@ public:
virtual void CheckBirthday(int ClientID);
virtual void LoadScore(int ClientID);
virtual void MapInfo(int ClientID, const char* MapName);
virtual void MapVote(int ClientID, const char* MapName);
virtual void MapVote(std::shared_ptr<CMapVoteResult> *ppResult, int ClientID, const char* MapName);
virtual void SaveScore(int ClientID, float Time, const char *pTimestamp,
float CpTime[NUM_CHECKPOINTS], bool NotEligible);
virtual void SaveTeamScore(int* ClientIDs, unsigned int Size, float Time, const char *pTimestamp);

View file

@ -272,11 +272,14 @@ bool CSqlScore::LoadScoreThread(CSqlServer* pSqlServer, const CSqlData *pGameDat
return false;
}
void CSqlScore::MapVote(int ClientID, const char* MapName)
void CSqlScore::MapVote(std::shared_ptr<CMapVoteResult> *ppResult, int ClientID, const char* MapName)
{
CSqlMapData *Tmp = new CSqlMapData();
*ppResult = std::make_shared<CMapVoteResult>();
CSqlMapVoteData *Tmp = new CSqlMapVoteData();
Tmp->m_ClientID = ClientID;
Tmp->m_RequestedMap = MapName;
Tmp->m_pResult = *ppResult;
str_copy(Tmp->m_aFuzzyMap, MapName, sizeof(Tmp->m_aFuzzyMap));
sqlstr::ClearString(Tmp->m_aFuzzyMap, sizeof(Tmp->m_aFuzzyMap));
sqlstr::FuzzyString(Tmp->m_aFuzzyMap, sizeof(Tmp->m_aFuzzyMap));
@ -286,7 +289,7 @@ void CSqlScore::MapVote(int ClientID, const char* MapName)
bool CSqlScore::MapVoteThread(CSqlServer* pSqlServer, const CSqlData *pGameData, bool HandleFailure)
{
const CSqlMapData *pData = dynamic_cast<const CSqlMapData *>(pGameData);
const CSqlMapVoteData *pData = dynamic_cast<const CSqlMapVoteData *>(pGameData);
if (HandleFailure)
return true;
@ -334,22 +337,16 @@ bool CSqlScore::MapVoteThread(CSqlServer* pSqlServer, const CSqlData *pGameData,
{
pSqlServer->GetResults()->next();
char aMap[128];
strcpy(aMap, pSqlServer->GetResults()->getString("Map").c_str());
str_copy(pData->m_pResult->m_aMap, pSqlServer->GetResults()->getString("Map").c_str(), sizeof(pData->m_pResult->m_aMap));
char aServer[32];
strcpy(aServer, pSqlServer->GetResults()->getString("Server").c_str());
str_copy(pData->m_pResult->m_aServer, pSqlServer->GetResults()->getString("Server").c_str(), sizeof(pData->m_pResult->m_aServer));
for(char *p = aServer; *p; p++)
for(char *p = pData->m_pResult->m_aServer; *p; p++)
*p = tolower(*p);
char aCmd[256];
str_format(aCmd, sizeof(aCmd), "sv_reset_file types/%s/flexreset.cfg; change_map \"%s\"", aServer, aMap);
char aChatmsg[512];
str_format(aChatmsg, sizeof(aChatmsg), "'%s' called vote to change server option '%s' (%s)", pData->GameServer()->Server()->ClientName(pData->m_ClientID), aMap, "/map");
pData->m_pResult->m_ClientID = pData->m_ClientID;
pData->GameServer()->m_VoteKick = false;
pData->GameServer()->m_VoteSpec = false;
pData->GameServer()->m_LastMapVote = time_get();
pData->GameServer()->CallVote(pData->m_ClientID, aMap, aCmd, "/map", aChatmsg);
pData->m_pResult->m_Done = true;
}
end:
return true;

View file

@ -85,7 +85,7 @@ struct CSqlPlayerData : CSqlData
sqlstr::CSqlString<MAX_NAME_LENGTH> m_Name;
};
// used for mapvote and mapinfo
// used for mapinfo
struct CSqlMapData : CSqlData
{
int m_ClientID;
@ -95,6 +95,12 @@ struct CSqlMapData : CSqlData
sqlstr::CSqlString<MAX_NAME_LENGTH> m_Name;
};
// used for mapvote
struct CSqlMapVoteData : CSqlMapData
{
std::shared_ptr<CMapVoteResult> m_pResult;
};
struct CSqlScoreData : CSqlData
{
int m_ClientID;
@ -138,7 +144,7 @@ struct CSqlTeamLoad : CSqlData
struct CSqlRandomMap : CSqlScoreData
{
std::shared_ptr<CRandomMapResult> m_pResult;
std::shared_ptr<CRandomMapResult> m_pResult;
};
class CSqlScore: public IScore
@ -184,7 +190,7 @@ public:
virtual void CheckBirthday(int ClientID);
virtual void LoadScore(int ClientID);
virtual void MapInfo(int ClientID, const char* MapName);
virtual void MapVote(int ClientID, const char* MapName);
virtual void MapVote(std::shared_ptr<CMapVoteResult> *ppResult, int ClientID, const char* MapName);
virtual void SaveScore(int ClientID, float Time, const char *pTimestamp,
float CpTime[NUM_CHECKPOINTS], bool NotEligible);
virtual void SaveTeamScore(int* aClientIDs, unsigned int Size, float Time, const char *pTimestamp);

View file

@ -1,5 +1,6 @@
/* (c) Shereef Marzouk. See "licence DDRace.txt" and the readme.txt in the root of the distribution for more information. */
#include "teams.h"
#include "score.h"
#include <engine/shared/config.h>
CGameTeams::CGameTeams(CGameContext *pGameContext) :