mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-20 09:34:19 +00:00
Overhauled job system
The engine now takes `std::shared_ptr<IJob>`, this will ensure the appropriate lifetime of the given parameters, it also allows for proper destruction. Remove the now obsolete `IFetcher` interface and `CFetcher` class. Also adds some locks to `CUpdater`, previously it didn't have any locks at all.
This commit is contained in:
parent
add0b88976
commit
94acac91a0
|
@ -1506,7 +1506,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
||||||
char aEscaped[128];
|
char aEscaped[128];
|
||||||
str_format(aFilename, sizeof(aFilename), "%s_%08x.map", pMap, MapCrc);
|
str_format(aFilename, sizeof(aFilename), "%s_%08x.map", pMap, MapCrc);
|
||||||
|
|
||||||
Fetcher()->Escape(aEscaped, sizeof(aEscaped), aFilename);
|
EscapeUrl(aEscaped, sizeof(aEscaped), aFilename);
|
||||||
str_format(aUrl, sizeof(aUrl), "%s/", g_Config.m_ClDDNetMapDownloadUrl);
|
str_format(aUrl, sizeof(aUrl), "%s/", g_Config.m_ClDDNetMapDownloadUrl);
|
||||||
|
|
||||||
// We only trust our own custom-selected CAs for our own servers.
|
// We only trust our own custom-selected CAs for our own servers.
|
||||||
|
@ -1518,7 +1518,8 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
||||||
|
|
||||||
str_append(aUrl, aEscaped, sizeof(aUrl));
|
str_append(aUrl, aEscaped, sizeof(aUrl));
|
||||||
|
|
||||||
m_pMapdownloadTask = Fetcher()->FetchFile(aUrl, m_aMapdownloadFilename, IStorage::TYPE_SAVE, UseDDNetCA, true);
|
m_pMapdownloadTask = std::make_shared<CFetchTask>(Storage(), aUrl, m_aMapdownloadFilename, IStorage::TYPE_SAVE, UseDDNetCA, true);
|
||||||
|
Engine()->AddJob(m_pMapdownloadTask);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SendMapRequest();
|
SendMapRequest();
|
||||||
|
@ -2089,7 +2090,6 @@ void CClient::ResetMapDownload()
|
||||||
if(m_pMapdownloadTask)
|
if(m_pMapdownloadTask)
|
||||||
{
|
{
|
||||||
m_pMapdownloadTask->Abort();
|
m_pMapdownloadTask->Abort();
|
||||||
m_pMapdownloadTask->Destroy();
|
|
||||||
m_pMapdownloadTask = NULL;
|
m_pMapdownloadTask = NULL;
|
||||||
}
|
}
|
||||||
m_MapdownloadFile = 0;
|
m_MapdownloadFile = 0;
|
||||||
|
@ -2135,7 +2135,6 @@ void CClient::ResetDDNetInfo()
|
||||||
if(m_pDDNetInfoTask)
|
if(m_pDDNetInfoTask)
|
||||||
{
|
{
|
||||||
m_pDDNetInfoTask->Abort();
|
m_pDDNetInfoTask->Abort();
|
||||||
m_pDDNetInfoTask->Destroy();
|
|
||||||
m_pDDNetInfoTask = NULL;
|
m_pDDNetInfoTask = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2476,33 +2475,31 @@ void CClient::Update()
|
||||||
|
|
||||||
if(m_pMapdownloadTask)
|
if(m_pMapdownloadTask)
|
||||||
{
|
{
|
||||||
if(m_pMapdownloadTask->State() == IFetchTask::STATE_DONE)
|
if(m_pMapdownloadTask->State() == CFetchTask::STATE_DONE)
|
||||||
FinishMapDownload();
|
FinishMapDownload();
|
||||||
else if(m_pMapdownloadTask->State() == IFetchTask::STATE_ERROR)
|
else if(m_pMapdownloadTask->State() == CFetchTask::STATE_ERROR)
|
||||||
{
|
{
|
||||||
dbg_msg("webdl", "http failed, falling back to gameserver");
|
dbg_msg("webdl", "http failed, falling back to gameserver");
|
||||||
ResetMapDownload();
|
ResetMapDownload();
|
||||||
SendMapRequest();
|
SendMapRequest();
|
||||||
}
|
}
|
||||||
else if(m_pMapdownloadTask->State() == IFetchTask::STATE_ABORTED)
|
else if(m_pMapdownloadTask->State() == CFetchTask::STATE_ABORTED)
|
||||||
{
|
{
|
||||||
m_pMapdownloadTask->Destroy();
|
|
||||||
m_pMapdownloadTask = NULL;
|
m_pMapdownloadTask = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pDDNetInfoTask)
|
if(m_pDDNetInfoTask)
|
||||||
{
|
{
|
||||||
if(m_pDDNetInfoTask->State() == IFetchTask::STATE_DONE)
|
if(m_pDDNetInfoTask->State() == CFetchTask::STATE_DONE)
|
||||||
FinishDDNetInfo();
|
FinishDDNetInfo();
|
||||||
else if(m_pDDNetInfoTask->State() == IFetchTask::STATE_ERROR)
|
else if(m_pDDNetInfoTask->State() == CFetchTask::STATE_ERROR)
|
||||||
{
|
{
|
||||||
dbg_msg("ddnet-info", "download failed");
|
dbg_msg("ddnet-info", "download failed");
|
||||||
ResetDDNetInfo();
|
ResetDDNetInfo();
|
||||||
}
|
}
|
||||||
else if(m_pDDNetInfoTask->State() == IFetchTask::STATE_ABORTED)
|
else if(m_pDDNetInfoTask->State() == CFetchTask::STATE_ABORTED)
|
||||||
{
|
{
|
||||||
m_pDDNetInfoTask->Destroy();
|
|
||||||
m_pDDNetInfoTask = NULL;
|
m_pDDNetInfoTask = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2532,7 +2529,6 @@ void CClient::RegisterInterfaces()
|
||||||
Kernel()->RegisterInterface(static_cast<IGhostRecorder*>(&m_GhostRecorder), false);
|
Kernel()->RegisterInterface(static_cast<IGhostRecorder*>(&m_GhostRecorder), false);
|
||||||
Kernel()->RegisterInterface(static_cast<IGhostLoader*>(&m_GhostLoader), false);
|
Kernel()->RegisterInterface(static_cast<IGhostLoader*>(&m_GhostLoader), false);
|
||||||
Kernel()->RegisterInterface(static_cast<IServerBrowser*>(&m_ServerBrowser), false);
|
Kernel()->RegisterInterface(static_cast<IServerBrowser*>(&m_ServerBrowser), false);
|
||||||
Kernel()->RegisterInterface(static_cast<IFetcher*>(&m_Fetcher), false);
|
|
||||||
#if !defined(CONF_PLATFORM_MACOSX) && !defined(__ANDROID__)
|
#if !defined(CONF_PLATFORM_MACOSX) && !defined(__ANDROID__)
|
||||||
Kernel()->RegisterInterface(static_cast<IUpdater*>(&m_Updater), false);
|
Kernel()->RegisterInterface(static_cast<IUpdater*>(&m_Updater), false);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2551,7 +2547,6 @@ void CClient::InitInterfaces()
|
||||||
m_pInput = Kernel()->RequestInterface<IEngineInput>();
|
m_pInput = Kernel()->RequestInterface<IEngineInput>();
|
||||||
m_pMap = Kernel()->RequestInterface<IEngineMap>();
|
m_pMap = Kernel()->RequestInterface<IEngineMap>();
|
||||||
m_pMasterServer = Kernel()->RequestInterface<IEngineMasterServer>();
|
m_pMasterServer = Kernel()->RequestInterface<IEngineMasterServer>();
|
||||||
m_pFetcher = Kernel()->RequestInterface<IFetcher>();
|
|
||||||
#if !defined(CONF_PLATFORM_MACOSX) && !defined(__ANDROID__)
|
#if !defined(CONF_PLATFORM_MACOSX) && !defined(__ANDROID__)
|
||||||
m_pUpdater = Kernel()->RequestInterface<IUpdater>();
|
m_pUpdater = Kernel()->RequestInterface<IUpdater>();
|
||||||
#endif
|
#endif
|
||||||
|
@ -2561,7 +2556,7 @@ void CClient::InitInterfaces()
|
||||||
|
|
||||||
m_ServerBrowser.SetBaseInfo(&m_NetClient[2], m_pGameClient->NetVersion());
|
m_ServerBrowser.SetBaseInfo(&m_NetClient[2], m_pGameClient->NetVersion());
|
||||||
|
|
||||||
m_Fetcher.Init();
|
FetcherInit();
|
||||||
|
|
||||||
#if !defined(CONF_PLATFORM_MACOSX) && !defined(__ANDROID__)
|
#if !defined(CONF_PLATFORM_MACOSX) && !defined(__ANDROID__)
|
||||||
m_Updater.Init();
|
m_Updater.Init();
|
||||||
|
@ -3632,15 +3627,13 @@ void CClient::RequestDDNetInfo()
|
||||||
if(g_Config.m_BrIndicateFinished)
|
if(g_Config.m_BrIndicateFinished)
|
||||||
{
|
{
|
||||||
char aEscaped[128];
|
char aEscaped[128];
|
||||||
Fetcher()->Escape(aEscaped, sizeof(aEscaped), g_Config.m_PlayerName);
|
EscapeUrl(aEscaped, sizeof(aEscaped), g_Config.m_PlayerName);
|
||||||
str_append(aUrl, "?name=", sizeof(aUrl));
|
str_append(aUrl, "?name=", sizeof(aUrl));
|
||||||
str_append(aUrl, aEscaped, sizeof(aUrl));
|
str_append(aUrl, aEscaped, sizeof(aUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pDDNetInfoTask)
|
m_pDDNetInfoTask = std::make_shared<CFetchTask>(Storage(), aUrl, "ddnet-info.json.tmp", IStorage::TYPE_SAVE, true, true);
|
||||||
m_pDDNetInfoTask->Destroy();
|
Engine()->AddJob(m_pDDNetInfoTask);
|
||||||
|
|
||||||
m_pDDNetInfoTask = Fetcher()->FetchFile(aUrl, "ddnet-info.json.tmp", IStorage::TYPE_SAVE, true, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CClient::GetPredictionTime()
|
int CClient::GetPredictionTime()
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
#ifndef ENGINE_CLIENT_CLIENT_H
|
#ifndef ENGINE_CLIENT_CLIENT_H
|
||||||
#define ENGINE_CLIENT_CLIENT_H
|
#define ENGINE_CLIENT_CLIENT_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "fetcher.h"
|
||||||
|
|
||||||
class CGraph
|
class CGraph
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -61,7 +65,6 @@ class CClient : public IClient, public CDemoPlayer::IListener
|
||||||
IEngineMap *m_pMap;
|
IEngineMap *m_pMap;
|
||||||
IConsole *m_pConsole;
|
IConsole *m_pConsole;
|
||||||
IStorage *m_pStorage;
|
IStorage *m_pStorage;
|
||||||
IFetcher *m_pFetcher;
|
|
||||||
IUpdater *m_pUpdater;
|
IUpdater *m_pUpdater;
|
||||||
IEngineMasterServer *m_pMasterServer;
|
IEngineMasterServer *m_pMasterServer;
|
||||||
|
|
||||||
|
@ -78,7 +81,6 @@ class CClient : public IClient, public CDemoPlayer::IListener
|
||||||
class CGhostRecorder m_GhostRecorder;
|
class CGhostRecorder m_GhostRecorder;
|
||||||
class CGhostLoader m_GhostLoader;
|
class CGhostLoader m_GhostLoader;
|
||||||
class CServerBrowser m_ServerBrowser;
|
class CServerBrowser m_ServerBrowser;
|
||||||
class CFetcher m_Fetcher;
|
|
||||||
class CUpdater m_Updater;
|
class CUpdater m_Updater;
|
||||||
class CFriends m_Friends;
|
class CFriends m_Friends;
|
||||||
class CFriends m_Foes;
|
class CFriends m_Foes;
|
||||||
|
@ -128,7 +130,7 @@ class CClient : public IClient, public CDemoPlayer::IListener
|
||||||
char m_aCmdConnect[256];
|
char m_aCmdConnect[256];
|
||||||
|
|
||||||
// map download
|
// map download
|
||||||
IFetchTask *m_pMapdownloadTask;
|
std::shared_ptr<CFetchTask> m_pMapdownloadTask;
|
||||||
char m_aMapdownloadFilename[256];
|
char m_aMapdownloadFilename[256];
|
||||||
char m_aMapdownloadName[256];
|
char m_aMapdownloadName[256];
|
||||||
IOHANDLE m_MapdownloadFile;
|
IOHANDLE m_MapdownloadFile;
|
||||||
|
@ -137,7 +139,7 @@ class CClient : public IClient, public CDemoPlayer::IListener
|
||||||
int m_MapdownloadAmount;
|
int m_MapdownloadAmount;
|
||||||
int m_MapdownloadTotalsize;
|
int m_MapdownloadTotalsize;
|
||||||
|
|
||||||
IFetchTask *m_pDDNetInfoTask;
|
std::shared_ptr<CFetchTask> m_pDDNetInfoTask;
|
||||||
|
|
||||||
// time
|
// time
|
||||||
CSmoothTime m_GameTime[2];
|
CSmoothTime m_GameTime[2];
|
||||||
|
@ -209,7 +211,6 @@ public:
|
||||||
IGameClient *GameClient() { return m_pGameClient; }
|
IGameClient *GameClient() { return m_pGameClient; }
|
||||||
IEngineMasterServer *MasterServer() { return m_pMasterServer; }
|
IEngineMasterServer *MasterServer() { return m_pMasterServer; }
|
||||||
IStorage *Storage() { return m_pStorage; }
|
IStorage *Storage() { return m_pStorage; }
|
||||||
IFetcher *Fetcher() { return m_pFetcher; }
|
|
||||||
IUpdater *Updater() { return m_pUpdater; }
|
IUpdater *Updater() { return m_pUpdater; }
|
||||||
|
|
||||||
CClient();
|
CClient();
|
||||||
|
@ -302,7 +303,6 @@ public:
|
||||||
void FinishDDNetInfo();
|
void FinishDDNetInfo();
|
||||||
void LoadDDNetInfo();
|
void LoadDDNetInfo();
|
||||||
|
|
||||||
virtual IFetchTask *MapDownloadTask() { return m_pMapdownloadTask; }
|
|
||||||
virtual const char *MapDownloadName() { return m_aMapdownloadName; }
|
virtual const char *MapDownloadName() { return m_aMapdownloadName; }
|
||||||
virtual int MapDownloadAmount() { return !m_pMapdownloadTask ? m_MapdownloadAmount : (int)m_pMapdownloadTask->Current(); }
|
virtual int MapDownloadAmount() { return !m_pMapdownloadTask ? m_MapdownloadAmount : (int)m_pMapdownloadTask->Current(); }
|
||||||
virtual int MapDownloadTotalsize() { return !m_pMapdownloadTask ? m_MapdownloadTotalsize : (int)m_pMapdownloadTask->Size(); }
|
virtual int MapDownloadTotalsize() { return !m_pMapdownloadTask ? m_MapdownloadTotalsize : (int)m_pMapdownloadTask->Size(); }
|
||||||
|
|
|
@ -10,136 +10,55 @@
|
||||||
|
|
||||||
#include "fetcher.h"
|
#include "fetcher.h"
|
||||||
|
|
||||||
class CFetchTask : public IFetchTask
|
double CFetchTask::Current() const { return m_Current; }
|
||||||
|
double CFetchTask::Size() const { return m_Size; }
|
||||||
|
int CFetchTask::Progress() const { return m_Progress; }
|
||||||
|
int CFetchTask::State() const { return m_State; }
|
||||||
|
const char *CFetchTask::Dest() const { return m_aDest; }
|
||||||
|
|
||||||
|
void CFetchTask::Abort() { m_Abort = true; };
|
||||||
|
|
||||||
|
CFetchTask::CFetchTask(IStorage *pStorage, const char *pUrl, const char *pDest, int StorageType, bool UseDDNetCA, bool CanTimeout) :
|
||||||
|
m_pStorage(pStorage),
|
||||||
|
m_StorageType(StorageType),
|
||||||
|
m_UseDDNetCA(UseDDNetCA),
|
||||||
|
m_CanTimeout(CanTimeout),
|
||||||
|
m_Size(0),
|
||||||
|
m_Progress(0),
|
||||||
|
m_State(CFetchTask::STATE_QUEUED),
|
||||||
|
m_Abort(false)
|
||||||
{
|
{
|
||||||
friend class CFetcher;
|
str_copy(m_aUrl, pUrl, sizeof(m_aUrl));
|
||||||
class CFetcher *m_pFetcher;
|
str_copy(m_aDest, pDest, sizeof(m_aDest));
|
||||||
|
|
||||||
CURL *m_pHandle;
|
|
||||||
void *m_pUser;
|
|
||||||
|
|
||||||
char m_aUrl[256];
|
|
||||||
char m_aDest[128];
|
|
||||||
int m_StorageType;
|
|
||||||
bool m_UseDDNetCA;
|
|
||||||
bool m_CanTimeout;
|
|
||||||
|
|
||||||
PROGFUNC m_pfnProgressCallback;
|
|
||||||
COMPFUNC m_pfnCompCallback;
|
|
||||||
|
|
||||||
double m_Size;
|
|
||||||
double m_Current;
|
|
||||||
int m_Progress;
|
|
||||||
int m_State;
|
|
||||||
|
|
||||||
LOCK m_Lock;
|
|
||||||
bool m_Abort;
|
|
||||||
bool m_Destroy;
|
|
||||||
bool m_PastCB;
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual double Current() { return m_Current; }
|
|
||||||
virtual double Size() { return m_Size; }
|
|
||||||
virtual int Progress() { return m_Progress; }
|
|
||||||
virtual int State() { return m_State; }
|
|
||||||
virtual const char *Dest() { return m_aDest; }
|
|
||||||
|
|
||||||
virtual void Abort() { m_Abort = true; };
|
|
||||||
virtual void Destroy();
|
|
||||||
};
|
|
||||||
|
|
||||||
void CFetchTask::Destroy()
|
|
||||||
{
|
|
||||||
lock_wait(m_Lock);
|
|
||||||
if(m_PastCB)
|
|
||||||
{
|
|
||||||
lock_destroy(m_Lock);
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_Abort = true;
|
|
||||||
m_Destroy = true;
|
|
||||||
lock_unlock(m_Lock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFetcher::Init()
|
|
||||||
|
bool FetcherInit()
|
||||||
{
|
{
|
||||||
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
return !curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
m_pEngine = Kernel()->RequestInterface<IEngine>();
|
|
||||||
if(curl_global_init(CURL_GLOBAL_DEFAULT))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFetcher::Escape(char *pBuf, size_t size, const char *pStr)
|
void EscapeUrl(char *pBuf, int Size, const char *pStr)
|
||||||
{
|
{
|
||||||
char *pEsc = curl_easy_escape(0, pStr, 0);
|
char *pEsc = curl_easy_escape(0, pStr, 0);
|
||||||
str_copy(pBuf, pEsc, size);
|
str_copy(pBuf, pEsc, Size);
|
||||||
curl_free(pEsc);
|
curl_free(pEsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFetcher::DestroyCallback(CJob *pJob, void *pUser)
|
void CFetchTask::Run()
|
||||||
{
|
{
|
||||||
CFetchTask *pTask = (CFetchTask *)pUser;
|
CURL *pHandle = curl_easy_init();
|
||||||
|
if(!pHandle)
|
||||||
delete pJob;
|
|
||||||
|
|
||||||
lock_wait(pTask->m_Lock);
|
|
||||||
if(pTask->m_Destroy)
|
|
||||||
{
|
{
|
||||||
lock_destroy(pTask->m_Lock);
|
m_State = STATE_ERROR;
|
||||||
delete pTask;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
pTask->m_PastCB = true;
|
|
||||||
}
|
|
||||||
lock_unlock(pTask->m_Lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
IFetchTask *CFetcher::FetchFile(const char *pUrl, const char *pDest, int StorageType, bool UseDDNetCA, bool CanTimeout, void *pUser, COMPFUNC pfnCompCb, PROGFUNC pfnProgCb)
|
|
||||||
{
|
|
||||||
CFetchTask *pTask = new CFetchTask;
|
|
||||||
pTask->m_pFetcher = this;
|
|
||||||
|
|
||||||
str_copy(pTask->m_aUrl, pUrl, sizeof(pTask->m_aUrl));
|
|
||||||
str_copy(pTask->m_aDest, pDest, sizeof(pTask->m_aDest));
|
|
||||||
pTask->m_StorageType = StorageType;
|
|
||||||
pTask->m_pUser = pUser;
|
|
||||||
pTask->m_pfnCompCallback = pfnCompCb;
|
|
||||||
pTask->m_pfnProgressCallback = pfnProgCb;
|
|
||||||
pTask->m_UseDDNetCA = UseDDNetCA;
|
|
||||||
pTask->m_CanTimeout = CanTimeout;
|
|
||||||
|
|
||||||
pTask->m_Lock = lock_create();
|
|
||||||
pTask->m_Abort = false;
|
|
||||||
pTask->m_Destroy = false;
|
|
||||||
pTask->m_PastCB = false;
|
|
||||||
pTask->m_Size = pTask->m_Progress = 0;
|
|
||||||
|
|
||||||
pTask->m_State = IFetchTask::STATE_QUEUED;
|
|
||||||
|
|
||||||
CJob *pJob = new CJob;
|
|
||||||
m_pEngine->AddJob(pJob, FetcherThread, pTask, DestroyCallback);
|
|
||||||
|
|
||||||
return pTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CFetcher::FetcherThread(void *pUser)
|
|
||||||
{
|
|
||||||
CFetchTask *pTask = (CFetchTask *)pUser;
|
|
||||||
|
|
||||||
pTask->m_pHandle = curl_easy_init();
|
|
||||||
if(!pTask->m_pHandle)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
char aPath[512];
|
char aPath[512];
|
||||||
if(pTask->m_StorageType == -2)
|
if(m_StorageType == -2)
|
||||||
pTask->m_pFetcher->m_pStorage->GetBinaryPath(pTask->m_aDest, aPath, sizeof(aPath));
|
m_pStorage->GetBinaryPath(m_aDest, aPath, sizeof(aPath));
|
||||||
else
|
else
|
||||||
pTask->m_pFetcher->m_pStorage->GetCompletePath(pTask->m_StorageType, pTask->m_aDest, aPath, sizeof(aPath));
|
m_pStorage->GetCompletePath(m_StorageType, m_aDest, aPath, sizeof(aPath));
|
||||||
|
|
||||||
if(fs_makedir_rec_for(aPath) < 0)
|
if(fs_makedir_rec_for(aPath) < 0)
|
||||||
dbg_msg("fetcher", "i/o error, cannot create folder for: %s", aPath);
|
dbg_msg("fetcher", "i/o error, cannot create folder for: %s", aPath);
|
||||||
|
@ -148,80 +67,76 @@ int CFetcher::FetcherThread(void *pUser)
|
||||||
|
|
||||||
if(!File)
|
if(!File)
|
||||||
{
|
{
|
||||||
dbg_msg("fetcher", "i/o error, cannot open file: %s", pTask->m_aDest);
|
dbg_msg("fetcher", "i/o error, cannot open file: %s", m_aDest);
|
||||||
pTask->m_State = IFetchTask::STATE_ERROR;
|
m_State = CFetchTask::STATE_ERROR;
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char aErr[CURL_ERROR_SIZE];
|
char aErr[CURL_ERROR_SIZE];
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_ERRORBUFFER, aErr);
|
curl_easy_setopt(pHandle, CURLOPT_ERRORBUFFER, aErr);
|
||||||
|
|
||||||
//curl_easy_setopt(pTask->m_pHandle, CURLOPT_VERBOSE, 1L);
|
//curl_easy_setopt(pHandle, CURLOPT_VERBOSE, 1L);
|
||||||
if(pTask->m_CanTimeout)
|
if(m_CanTimeout)
|
||||||
{
|
{
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_CONNECTTIMEOUT_MS, (long)g_Config.m_ClHTTPConnectTimeoutMs);
|
curl_easy_setopt(pHandle, CURLOPT_CONNECTTIMEOUT_MS, (long)g_Config.m_ClHTTPConnectTimeoutMs);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_LOW_SPEED_LIMIT, (long)g_Config.m_ClHTTPLowSpeedLimit);
|
curl_easy_setopt(pHandle, CURLOPT_LOW_SPEED_LIMIT, (long)g_Config.m_ClHTTPLowSpeedLimit);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_LOW_SPEED_TIME, (long)g_Config.m_ClHTTPLowSpeedTime);
|
curl_easy_setopt(pHandle, CURLOPT_LOW_SPEED_TIME, (long)g_Config.m_ClHTTPLowSpeedTime);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_CONNECTTIMEOUT_MS, 0);
|
curl_easy_setopt(pHandle, CURLOPT_CONNECTTIMEOUT_MS, 0);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_LOW_SPEED_LIMIT, 0);
|
curl_easy_setopt(pHandle, CURLOPT_LOW_SPEED_LIMIT, 0);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_LOW_SPEED_TIME, 0);
|
curl_easy_setopt(pHandle, CURLOPT_LOW_SPEED_TIME, 0);
|
||||||
}
|
}
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_FOLLOWLOCATION, 1L);
|
curl_easy_setopt(pHandle, CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_MAXREDIRS, 4L);
|
curl_easy_setopt(pHandle, CURLOPT_MAXREDIRS, 4L);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_FAILONERROR, 1L);
|
curl_easy_setopt(pHandle, CURLOPT_FAILONERROR, 1L);
|
||||||
if(pTask->m_UseDDNetCA)
|
if(m_UseDDNetCA)
|
||||||
{
|
{
|
||||||
char aCAFile[512];
|
char aCAFile[512];
|
||||||
pTask->m_pFetcher->m_pStorage->GetBinaryPath("data/ca-ddnet.pem", aCAFile, sizeof aCAFile);
|
m_pStorage->GetBinaryPath("data/ca-ddnet.pem", aCAFile, sizeof aCAFile);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_CAINFO, aCAFile);
|
curl_easy_setopt(pHandle, CURLOPT_CAINFO, aCAFile);
|
||||||
}
|
}
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_URL, pTask->m_aUrl);
|
curl_easy_setopt(pHandle, CURLOPT_URL, m_aUrl);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_WRITEDATA, File);
|
curl_easy_setopt(pHandle, CURLOPT_WRITEDATA, File);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_WRITEFUNCTION, &CFetcher::WriteToFile);
|
curl_easy_setopt(pHandle, CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_NOPROGRESS, 0);
|
curl_easy_setopt(pHandle, CURLOPT_NOPROGRESS, 0);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_PROGRESSDATA, pTask);
|
curl_easy_setopt(pHandle, CURLOPT_PROGRESSDATA, this);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_PROGRESSFUNCTION, &CFetcher::ProgressCallback);
|
curl_easy_setopt(pHandle, CURLOPT_PROGRESSFUNCTION, ProgressCallback);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_NOSIGNAL, 1L);
|
curl_easy_setopt(pHandle, CURLOPT_NOSIGNAL, 1L);
|
||||||
curl_easy_setopt(pTask->m_pHandle, CURLOPT_USERAGENT, "DDNet " GAME_RELEASE_VERSION " (" CONF_PLATFORM_STRING "; " CONF_ARCH_STRING ")");
|
curl_easy_setopt(pHandle, CURLOPT_USERAGENT, "DDNet " GAME_RELEASE_VERSION " (" CONF_PLATFORM_STRING "; " CONF_ARCH_STRING ")");
|
||||||
|
|
||||||
dbg_msg("fetcher", "downloading %s", pTask->m_aDest);
|
dbg_msg("fetcher", "downloading %s", m_aDest);
|
||||||
pTask->m_State = IFetchTask::STATE_RUNNING;
|
m_State = CFetchTask::STATE_RUNNING;
|
||||||
int ret = curl_easy_perform(pTask->m_pHandle);
|
int Ret = curl_easy_perform(pHandle);
|
||||||
io_close(File);
|
io_close(File);
|
||||||
if(ret != CURLE_OK)
|
if(Ret != CURLE_OK)
|
||||||
{
|
{
|
||||||
dbg_msg("fetcher", "task failed. libcurl error: %s", aErr);
|
dbg_msg("fetcher", "task failed. libcurl error: %s", aErr);
|
||||||
pTask->m_State = (ret == CURLE_ABORTED_BY_CALLBACK) ? IFetchTask::STATE_ABORTED : IFetchTask::STATE_ERROR;
|
m_State = (Ret == CURLE_ABORTED_BY_CALLBACK) ? CFetchTask::STATE_ABORTED : CFetchTask::STATE_ERROR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dbg_msg("fetcher", "task done %s", pTask->m_aDest);
|
dbg_msg("fetcher", "task done %s", m_aDest);
|
||||||
pTask->m_State = IFetchTask::STATE_DONE;
|
m_State = CFetchTask::STATE_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_easy_cleanup(pTask->m_pHandle);
|
curl_easy_cleanup(pHandle);
|
||||||
|
|
||||||
if(pTask->m_pfnCompCallback)
|
OnCompletion();
|
||||||
pTask->m_pfnCompCallback(pTask, pTask->m_pUser);
|
|
||||||
|
|
||||||
return(ret != CURLE_OK) ? 1 : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CFetcher::WriteToFile(char *pData, size_t size, size_t nmemb, void *pFile)
|
size_t CFetchTask::WriteCallback(char *pData, size_t Size, size_t Number, void *pFile)
|
||||||
{
|
{
|
||||||
return io_write((IOHANDLE)pFile, pData, size*nmemb);
|
return io_write((IOHANDLE)pFile, pData, Size * Number);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CFetcher::ProgressCallback(void *pUser, double DlTotal, double DlCurr, double UlTotal, double UlCurr)
|
int CFetchTask::ProgressCallback(void *pUser, double DlTotal, double DlCurr, double UlTotal, double UlCurr)
|
||||||
{
|
{
|
||||||
CFetchTask *pTask = (CFetchTask *)pUser;
|
CFetchTask *pTask = (CFetchTask *)pUser;
|
||||||
pTask->m_Current = DlCurr;
|
pTask->m_Current = DlCurr;
|
||||||
pTask->m_Size = DlTotal;
|
pTask->m_Size = DlTotal;
|
||||||
pTask->m_Progress = (100 * DlCurr) / (DlTotal ? DlTotal : 1);
|
pTask->m_Progress = (100 * DlCurr) / (DlTotal ? DlTotal : 1);
|
||||||
if(pTask->m_pfnProgressCallback)
|
pTask->OnProgress();
|
||||||
pTask->m_pfnProgressCallback(pTask, pTask->m_pUser);
|
|
||||||
return pTask->m_Abort ? -1 : 0;
|
return pTask->m_Abort ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,56 @@
|
||||||
#ifndef ENGINE_CLIENT_FETCHER_H
|
#ifndef ENGINE_CLIENT_FETCHER_H
|
||||||
#define ENGINE_CLIENT_FETCHER_H
|
#define ENGINE_CLIENT_FETCHER_H
|
||||||
|
|
||||||
#include <engine/fetcher.h>
|
#include <engine/shared/jobs.h>
|
||||||
|
#include <engine/storage.h>
|
||||||
|
#include <engine/kernel.h>
|
||||||
|
|
||||||
class CFetcher : public IFetcher
|
class CFetchTask : public IJob
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
class IEngine *m_pEngine;
|
IStorage *m_pStorage;
|
||||||
class IStorage *m_pStorage;
|
|
||||||
|
char m_aUrl[256];
|
||||||
|
char m_aDest[128];
|
||||||
|
int m_StorageType;
|
||||||
|
bool m_UseDDNetCA;
|
||||||
|
bool m_CanTimeout;
|
||||||
|
|
||||||
|
double m_Size;
|
||||||
|
double m_Current;
|
||||||
|
int m_Progress;
|
||||||
|
int m_State;
|
||||||
|
|
||||||
|
std::atomic<bool> m_Abort;
|
||||||
|
|
||||||
|
virtual void OnProgress() { }
|
||||||
|
virtual void OnCompletion() { }
|
||||||
|
|
||||||
|
static int ProgressCallback(void *pUser, double DlTotal, double DlCurr, double UlTotal, double UlCurr);
|
||||||
|
static size_t WriteCallback(char *pData, size_t Size, size_t Number, void *pFile);
|
||||||
|
|
||||||
|
void Run();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool Init();
|
enum
|
||||||
|
{
|
||||||
|
STATE_ERROR = -1,
|
||||||
|
STATE_QUEUED,
|
||||||
|
STATE_RUNNING,
|
||||||
|
STATE_DONE,
|
||||||
|
STATE_ABORTED,
|
||||||
|
};
|
||||||
|
|
||||||
virtual IFetchTask *FetchFile(const char *pUrl, const char *pDest, int StorageType = -2, bool UseDDNetCA = false, bool CanTimeout = true, void *pUser = 0, COMPFUNC pfnCompCb = 0, PROGFUNC pfnProgCb = 0);
|
CFetchTask(IStorage *pStorage, const char *pUrl, const char *pDest, int StorageType = -2, bool UseDDNetCA = false, bool CanTimeout = true);
|
||||||
virtual void Escape(char *pBud, size_t size, const char *pStr);
|
|
||||||
|
|
||||||
static void DestroyCallback(CJob *pJob, void *pUser);
|
double Current() const;
|
||||||
static int FetcherThread(void *pUser);
|
double Size() const;
|
||||||
static size_t WriteToFile(char *pData, size_t size, size_t nmemb, void *pFile);
|
int Progress() const;
|
||||||
static int ProgressCallback(void *pUser, double DlTotal, double DlCurr, double UlTotal, double UlCurr);
|
int State() const;
|
||||||
|
const char *Dest() const;
|
||||||
|
void Abort();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool FetcherInit();
|
||||||
|
void EscapeUrl(char *pBud, int Size, const char *pStr);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "updater.h"
|
#include "updater.h"
|
||||||
#include <base/system.h>
|
#include <base/system.h>
|
||||||
#include <engine/fetcher.h>
|
#include <engine/engine.h>
|
||||||
#include <engine/storage.h>
|
#include <engine/storage.h>
|
||||||
#include <engine/client.h>
|
#include <engine/client.h>
|
||||||
#include <engine/external/json-parser/json.h>
|
#include <engine/external/json-parser/json.h>
|
||||||
|
@ -11,63 +11,128 @@
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::map;
|
using std::map;
|
||||||
|
|
||||||
|
class CUpdaterFetchTask : public CFetchTask
|
||||||
|
{
|
||||||
|
char m_aBuf[256];
|
||||||
|
char m_aBuf2[256];
|
||||||
|
CUpdater *m_pUpdater;
|
||||||
|
|
||||||
|
void OnCompletion();
|
||||||
|
void OnProgress();
|
||||||
|
|
||||||
|
public:
|
||||||
|
CUpdaterFetchTask(CUpdater *pUpdater, const char *pFile, const char *pDestPath);
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *GetUpdaterUrl(char *pBuf, int BufSize, const char *pFile)
|
||||||
|
{
|
||||||
|
str_format(pBuf, BufSize, "https://update4.ddnet.tw/%s", pFile);
|
||||||
|
return pBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *GetUpdaterDestPath(char *pBuf, int BufSize, const char *pFile, const char *pDestPath)
|
||||||
|
{
|
||||||
|
if(!pDestPath)
|
||||||
|
{
|
||||||
|
pDestPath = pFile;
|
||||||
|
}
|
||||||
|
str_format(pBuf, BufSize, "update/%s", pDestPath);
|
||||||
|
return pBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUpdaterFetchTask::CUpdaterFetchTask(CUpdater *pUpdater, const char *pFile, const char *pDestPath) :
|
||||||
|
CFetchTask(pUpdater->m_pStorage, GetUpdaterUrl(m_aBuf, sizeof(m_aBuf), pFile), GetUpdaterDestPath(m_aBuf2, sizeof(m_aBuf), pFile, pDestPath), -2, true, false),
|
||||||
|
m_pUpdater(pUpdater)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUpdaterFetchTask::OnProgress()
|
||||||
|
{
|
||||||
|
lock_wait(m_pUpdater->m_Lock);
|
||||||
|
str_copy(m_pUpdater->m_aStatus, Dest(), sizeof(m_pUpdater->m_aStatus));
|
||||||
|
m_pUpdater->m_Percent = Progress();
|
||||||
|
lock_unlock(m_pUpdater->m_Lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUpdaterFetchTask::OnCompletion()
|
||||||
|
{
|
||||||
|
const char *b = 0;
|
||||||
|
for(const char *a = Dest(); *a; a++)
|
||||||
|
if(*a == '/')
|
||||||
|
b = a + 1;
|
||||||
|
b = b ? b : Dest();
|
||||||
|
if(!str_comp(b, "update.json"))
|
||||||
|
{
|
||||||
|
if(State() == CFetchTask::STATE_DONE)
|
||||||
|
m_pUpdater->SetCurrentState(IUpdater::GOT_MANIFEST);
|
||||||
|
else if(State() == CFetchTask::STATE_ERROR)
|
||||||
|
m_pUpdater->SetCurrentState(IUpdater::FAIL);
|
||||||
|
}
|
||||||
|
else if(!str_comp(b, m_pUpdater->m_aLastFile))
|
||||||
|
{
|
||||||
|
if(State() == CFetchTask::STATE_DONE)
|
||||||
|
m_pUpdater->SetCurrentState(IUpdater::MOVE_FILES);
|
||||||
|
else if(State() == CFetchTask::STATE_ERROR)
|
||||||
|
m_pUpdater->SetCurrentState(IUpdater::FAIL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CUpdater::CUpdater()
|
CUpdater::CUpdater()
|
||||||
{
|
{
|
||||||
m_pClient = NULL;
|
m_pClient = NULL;
|
||||||
m_pStorage = NULL;
|
m_pStorage = NULL;
|
||||||
m_pFetcher = NULL;
|
m_pEngine = NULL;
|
||||||
m_State = CLEAN;
|
m_State = CLEAN;
|
||||||
m_Percent = 0;
|
m_Percent = 0;
|
||||||
|
m_Lock = lock_create();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUpdater::Init()
|
void CUpdater::Init()
|
||||||
{
|
{
|
||||||
m_pClient = Kernel()->RequestInterface<IClient>();
|
m_pClient = Kernel()->RequestInterface<IClient>();
|
||||||
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
||||||
m_pFetcher = Kernel()->RequestInterface<IFetcher>();
|
m_pEngine = Kernel()->RequestInterface<IEngine>();
|
||||||
m_IsWinXP = os_is_winxp_or_lower();
|
m_IsWinXP = os_is_winxp_or_lower();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUpdater::ProgressCallback(IFetchTask *pTask, void *pUser)
|
CUpdater::~CUpdater()
|
||||||
{
|
{
|
||||||
CUpdater *pUpdate = (CUpdater *)pUser;
|
lock_destroy(m_Lock);
|
||||||
str_copy(pUpdate->m_Status, pTask->Dest(), sizeof(pUpdate->m_Status));
|
|
||||||
pUpdate->m_Percent = pTask->Progress();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUpdater::CompletionCallback(IFetchTask *pTask, void *pUser)
|
void CUpdater::SetCurrentState(int NewState)
|
||||||
{
|
{
|
||||||
CUpdater *pUpdate = (CUpdater *)pUser;
|
lock_wait(m_Lock);
|
||||||
const char *b = 0;
|
m_State = NewState;
|
||||||
for(const char *a = pTask->Dest(); *a; a++)
|
lock_unlock(m_Lock);
|
||||||
if(*a == '/')
|
}
|
||||||
b = a + 1;
|
|
||||||
b = b ? b : pTask->Dest();
|
int CUpdater::GetCurrentState()
|
||||||
if(!str_comp(b, "update.json"))
|
{
|
||||||
{
|
lock_wait(m_Lock);
|
||||||
if(pTask->State() == IFetchTask::STATE_DONE)
|
int Result = m_State;
|
||||||
pUpdate->m_State = GOT_MANIFEST;
|
lock_unlock(m_Lock);
|
||||||
else if(pTask->State() == IFetchTask::STATE_ERROR)
|
return Result;
|
||||||
pUpdate->m_State = FAIL;
|
}
|
||||||
}
|
|
||||||
else if(!str_comp(b, pUpdate->m_aLastFile))
|
void CUpdater::GetCurrentFile(char *pBuf, int BufSize)
|
||||||
{
|
{
|
||||||
if(pTask->State() == IFetchTask::STATE_DONE)
|
lock_wait(m_Lock);
|
||||||
pUpdate->m_State = MOVE_FILES;
|
str_copy(pBuf, m_aStatus, BufSize);
|
||||||
else if(pTask->State() == IFetchTask::STATE_ERROR)
|
lock_unlock(m_Lock);
|
||||||
pUpdate->m_State = FAIL;
|
}
|
||||||
}
|
|
||||||
pTask->Destroy();
|
int CUpdater::GetCurrentPercent()
|
||||||
|
{
|
||||||
|
lock_wait(m_Lock);
|
||||||
|
int Result = m_Percent;
|
||||||
|
lock_unlock(m_Lock);
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUpdater::FetchFile(const char *pFile, const char *pDestPath)
|
void CUpdater::FetchFile(const char *pFile, const char *pDestPath)
|
||||||
{
|
{
|
||||||
char aBuf[256], aPath[256];
|
m_pEngine->AddJob(std::make_shared<CUpdaterFetchTask>(this, pFile, pDestPath));
|
||||||
str_format(aBuf, sizeof(aBuf), "https://update4.ddnet.tw/%s", pFile);
|
|
||||||
if(!pDestPath)
|
|
||||||
pDestPath = pFile;
|
|
||||||
str_format(aPath, sizeof(aPath), "update/%s", pDestPath);
|
|
||||||
m_pFetcher->FetchFile(aBuf, aPath, -2, true, false, this, &CUpdater::CompletionCallback, &CUpdater::ProgressCallback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUpdater::MoveFile(const char *pFile)
|
void CUpdater::MoveFile(const char *pFile)
|
||||||
|
@ -93,10 +158,10 @@ void CUpdater::Update()
|
||||||
{
|
{
|
||||||
switch(m_State)
|
switch(m_State)
|
||||||
{
|
{
|
||||||
case GOT_MANIFEST:
|
case IUpdater::GOT_MANIFEST:
|
||||||
PerformUpdate();
|
PerformUpdate();
|
||||||
break;
|
break;
|
||||||
case MOVE_FILES:
|
case IUpdater::MOVE_FILES:
|
||||||
CommitUpdate();
|
CommitUpdate();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -104,9 +169,9 @@ void CUpdater::Update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUpdater::AddFileJob(const char *pFile, bool job)
|
void CUpdater::AddFileJob(const char *pFile, bool Job)
|
||||||
{
|
{
|
||||||
m_FileJobs[string(pFile)] = job;
|
m_FileJobs[string(pFile)] = Job;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUpdater::ReplaceClient()
|
void CUpdater::ReplaceClient()
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define ENGINE_CLIENT_UPDATER_H
|
#define ENGINE_CLIENT_UPDATER_H
|
||||||
|
|
||||||
#include <engine/updater.h>
|
#include <engine/updater.h>
|
||||||
#include <engine/fetcher.h>
|
#include "fetcher.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -34,14 +34,18 @@
|
||||||
|
|
||||||
class CUpdater : public IUpdater
|
class CUpdater : public IUpdater
|
||||||
{
|
{
|
||||||
|
friend class CUpdaterFetchTask;
|
||||||
|
|
||||||
class IClient *m_pClient;
|
class IClient *m_pClient;
|
||||||
class IStorage *m_pStorage;
|
class IStorage *m_pStorage;
|
||||||
class IFetcher *m_pFetcher;
|
class IEngine *m_pEngine;
|
||||||
|
|
||||||
bool m_IsWinXP;
|
bool m_IsWinXP;
|
||||||
|
|
||||||
|
LOCK m_Lock;
|
||||||
|
|
||||||
int m_State;
|
int m_State;
|
||||||
char m_Status[256];
|
char m_aStatus[256];
|
||||||
int m_Percent;
|
int m_Percent;
|
||||||
char m_aLastFile[256];
|
char m_aLastFile[256];
|
||||||
|
|
||||||
|
@ -50,7 +54,7 @@ class CUpdater : public IUpdater
|
||||||
|
|
||||||
std::map<std::string, bool> m_FileJobs;
|
std::map<std::string, bool> m_FileJobs;
|
||||||
|
|
||||||
void AddFileJob(const char *pFile, bool job);
|
void AddFileJob(const char *pFile, bool Job);
|
||||||
void FetchFile(const char *pFile, const char *pDestPath = 0);
|
void FetchFile(const char *pFile, const char *pDestPath = 0);
|
||||||
void MoveFile(const char *pFile);
|
void MoveFile(const char *pFile);
|
||||||
|
|
||||||
|
@ -61,14 +65,15 @@ class CUpdater : public IUpdater
|
||||||
void ReplaceClient();
|
void ReplaceClient();
|
||||||
void ReplaceServer();
|
void ReplaceServer();
|
||||||
|
|
||||||
|
void SetCurrentState(int NewState);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CUpdater();
|
CUpdater();
|
||||||
static void ProgressCallback(IFetchTask *pTask, void *pUser);
|
~CUpdater();
|
||||||
static void CompletionCallback(IFetchTask *pTask, void *pUser);
|
|
||||||
|
|
||||||
int GetCurrentState() { return m_State; };
|
int GetCurrentState();
|
||||||
char *GetCurrentFile() { return m_Status; };
|
void GetCurrentFile(char *pBuf, int BufSize);
|
||||||
int GetCurrentPercent() { return m_Percent; };
|
int GetCurrentPercent();
|
||||||
|
|
||||||
virtual void InitiateUpdate();
|
virtual void InitiateUpdate();
|
||||||
void Init();
|
void Init();
|
||||||
|
|
|
@ -6,10 +6,16 @@
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include <engine/shared/jobs.h>
|
#include <engine/shared/jobs.h>
|
||||||
|
|
||||||
class CHostLookup
|
class CHostLookup : public IJob
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
virtual void Run();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CJob m_Job;
|
CHostLookup();
|
||||||
|
CHostLookup(const char *pHostname, int Nettype);
|
||||||
|
|
||||||
|
int m_Result;
|
||||||
char m_aHostname[128];
|
char m_aHostname[128];
|
||||||
int m_Nettype;
|
int m_Nettype;
|
||||||
NETADDR m_Addr;
|
NETADDR m_Addr;
|
||||||
|
@ -25,8 +31,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
virtual void Init() = 0;
|
virtual void Init() = 0;
|
||||||
virtual void InitLogfile() = 0;
|
virtual void InitLogfile() = 0;
|
||||||
virtual void HostLookup(CHostLookup *pLookup, const char *pHostname, int Nettype) = 0;
|
virtual void AddJob(std::shared_ptr<IJob> pJob) = 0;
|
||||||
virtual void AddJob(CJob *pJob, JOBFUNC pfnFunc, void *pData, CBFUNC pfnDestroy = 0) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern IEngine *CreateEngine(const char *pAppname, bool Silent);
|
extern IEngine *CreateEngine(const char *pAppname, bool Silent);
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
#ifndef ENGINE_FETCHER_H
|
|
||||||
#define ENGINE_FETCHER_H
|
|
||||||
|
|
||||||
#include <engine/shared/jobs.h>
|
|
||||||
#include "kernel.h"
|
|
||||||
#include "stddef.h"
|
|
||||||
|
|
||||||
class IFetchTask
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
STATE_ERROR = -1,
|
|
||||||
STATE_QUEUED,
|
|
||||||
STATE_RUNNING,
|
|
||||||
STATE_DONE,
|
|
||||||
STATE_ABORTED,
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual ~IFetchTask() {};
|
|
||||||
|
|
||||||
virtual double Current() = 0;
|
|
||||||
virtual double Size() = 0;
|
|
||||||
virtual int Progress() = 0;
|
|
||||||
virtual int State() = 0;
|
|
||||||
virtual const char *Dest() = 0;
|
|
||||||
virtual void Abort() = 0;
|
|
||||||
|
|
||||||
virtual void Destroy() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef void (*PROGFUNC)(IFetchTask *pTask, void *pUser);
|
|
||||||
typedef void (*COMPFUNC)(IFetchTask *pDest, void *pUser);
|
|
||||||
|
|
||||||
class IFetcher : public IInterface
|
|
||||||
{
|
|
||||||
MACRO_INTERFACE("fetcher", 0)
|
|
||||||
public:
|
|
||||||
virtual bool Init() = 0;
|
|
||||||
virtual IFetchTask *FetchFile(const char *pUrl, const char *pDest, int StorageType = -2, bool UseDDNetCA = false, bool CanTimeout = true, void *pUser = 0, COMPFUNC pfnCompCb = 0, PROGFUNC pfnProgCb = 0) = 0;
|
|
||||||
virtual void Escape(char *pBud, size_t size, const char *pStr) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -820,20 +820,24 @@ void CServer::InitDnsbl(int ClientID)
|
||||||
NETADDR Addr = *m_NetServer.ClientAddr(ClientID);
|
NETADDR Addr = *m_NetServer.ClientAddr(ClientID);
|
||||||
|
|
||||||
//TODO: support ipv6
|
//TODO: support ipv6
|
||||||
if (Addr.type != NETTYPE_IPV4)
|
if(Addr.type != NETTYPE_IPV4)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// build dnsbl host lookup
|
// build dnsbl host lookup
|
||||||
char aBuf[256];
|
char aBuf[256];
|
||||||
if (g_Config.m_SvDnsblKey[0] == '\0')
|
if(g_Config.m_SvDnsblKey[0] == '\0')
|
||||||
|
{
|
||||||
// without key
|
// without key
|
||||||
str_format(aBuf, sizeof(aBuf), "%d.%d.%d.%d.%s", Addr.ip[3], Addr.ip[2], Addr.ip[1], Addr.ip[0], g_Config.m_SvDnsblHost);
|
str_format(aBuf, sizeof(aBuf), "%d.%d.%d.%d.%s", Addr.ip[3], Addr.ip[2], Addr.ip[1], Addr.ip[0], g_Config.m_SvDnsblHost);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
// with key
|
// with key
|
||||||
str_format(aBuf, sizeof(aBuf), "%s.%d.%d.%d.%d.%s", g_Config.m_SvDnsblKey, Addr.ip[3], Addr.ip[2], Addr.ip[1], Addr.ip[0], g_Config.m_SvDnsblHost);
|
str_format(aBuf, sizeof(aBuf), "%s.%d.%d.%d.%d.%s", g_Config.m_SvDnsblKey, Addr.ip[3], Addr.ip[2], Addr.ip[1], Addr.ip[0], g_Config.m_SvDnsblHost);
|
||||||
|
}
|
||||||
|
|
||||||
IEngine *pEngine = Kernel()->RequestInterface<IEngine>();
|
IEngine *pEngine = Kernel()->RequestInterface<IEngine>();
|
||||||
pEngine->HostLookup(&m_aClients[ClientID].m_DnsblLookup, aBuf, NETTYPE_IPV4);
|
pEngine->AddJob(m_aClients[ClientID].m_pDnsblLookup = std::make_shared<CHostLookup>(aBuf, NETTYPE_IPV4));
|
||||||
}
|
}
|
||||||
|
|
||||||
int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser)
|
int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser)
|
||||||
|
@ -1843,10 +1847,10 @@ int CServer::Run()
|
||||||
InitDnsbl(ClientID);
|
InitDnsbl(ClientID);
|
||||||
}
|
}
|
||||||
else if (m_aClients[ClientID].m_DnsblState == CClient::DNSBL_STATE_PENDING &&
|
else if (m_aClients[ClientID].m_DnsblState == CClient::DNSBL_STATE_PENDING &&
|
||||||
m_aClients[ClientID].m_DnsblLookup.m_Job.Status() == CJob::STATE_DONE)
|
m_aClients[ClientID].m_pDnsblLookup->Status() == IJob::STATE_DONE)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (m_aClients[ClientID].m_DnsblLookup.m_Job.Result() != 0)
|
if (m_aClients[ClientID].m_pDnsblLookup->m_Result != 0)
|
||||||
{
|
{
|
||||||
// entry not found -> whitelisted
|
// entry not found -> whitelisted
|
||||||
m_aClients[ClientID].m_DnsblState = CClient::DNSBL_STATE_WHITELISTED;
|
m_aClients[ClientID].m_DnsblState = CClient::DNSBL_STATE_WHITELISTED;
|
||||||
|
|
|
@ -164,7 +164,7 @@ public:
|
||||||
|
|
||||||
// DNSBL
|
// DNSBL
|
||||||
int m_DnsblState;
|
int m_DnsblState;
|
||||||
CHostLookup m_DnsblLookup;
|
std::shared_ptr<CHostLookup> m_pDnsblLookup;
|
||||||
};
|
};
|
||||||
|
|
||||||
CClient m_aClients[MAX_CLIENTS];
|
CClient m_aClients[MAX_CLIENTS];
|
||||||
|
|
|
@ -9,11 +9,20 @@
|
||||||
#include <engine/shared/config.h>
|
#include <engine/shared/config.h>
|
||||||
#include <engine/shared/network.h>
|
#include <engine/shared/network.h>
|
||||||
|
|
||||||
|
CHostLookup::CHostLookup()
|
||||||
static int HostLookupThread(void *pUser)
|
|
||||||
{
|
{
|
||||||
CHostLookup *pLookup = (CHostLookup *)pUser;
|
}
|
||||||
return net_host_lookup(pLookup->m_aHostname, &pLookup->m_Addr, pLookup->m_Nettype);
|
|
||||||
|
CHostLookup::CHostLookup(const char *pHostname, int Nettype)
|
||||||
|
{
|
||||||
|
str_copy(m_aHostname, pHostname, sizeof(m_aHostname));
|
||||||
|
m_Nettype = Nettype;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CHostLookup::Run()
|
||||||
|
{
|
||||||
|
m_Result = net_host_lookup(m_aHostname, &m_Addr, m_Nettype);
|
||||||
}
|
}
|
||||||
|
|
||||||
class CEngine : public IEngine
|
class CEngine : public IEngine
|
||||||
|
@ -99,18 +108,11 @@ public:
|
||||||
dbg_logger_file(g_Config.m_Logfile);
|
dbg_logger_file(g_Config.m_Logfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostLookup(CHostLookup *pLookup, const char *pHostname, int Nettype)
|
void AddJob(std::shared_ptr<IJob> pJob)
|
||||||
{
|
|
||||||
str_copy(pLookup->m_aHostname, pHostname, sizeof(pLookup->m_aHostname));
|
|
||||||
pLookup->m_Nettype = Nettype;
|
|
||||||
AddJob(&pLookup->m_Job, HostLookupThread, pLookup);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddJob(CJob *pJob, JOBFUNC pfnFunc, void *pData, CBFUNC pfnDestroy = 0)
|
|
||||||
{
|
{
|
||||||
if(g_Config.m_Debug)
|
if(g_Config.m_Debug)
|
||||||
dbg_msg("engine", "job added");
|
dbg_msg("engine", "job added");
|
||||||
m_JobPool.Add(pJob, pfnFunc, pData, pfnDestroy);
|
m_JobPool.Add(pJob);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,31 @@
|
||||||
#include <base/system.h>
|
#include <base/system.h>
|
||||||
#include "jobs.h"
|
#include "jobs.h"
|
||||||
|
|
||||||
|
IJob::IJob() :
|
||||||
|
m_Status(STATE_PENDING)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IJob::IJob(const IJob &Other) :
|
||||||
|
m_Status(STATE_PENDING)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IJob &IJob::operator=(const IJob &Other)
|
||||||
|
{
|
||||||
|
m_Status = STATE_PENDING;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
IJob::~IJob()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int IJob::Status()
|
||||||
|
{
|
||||||
|
return m_Status.load();
|
||||||
|
}
|
||||||
|
|
||||||
CJobPool::CJobPool()
|
CJobPool::CJobPool()
|
||||||
{
|
{
|
||||||
// empty the pool
|
// empty the pool
|
||||||
|
@ -31,7 +56,7 @@ void CJobPool::WorkerThread(void *pUser)
|
||||||
|
|
||||||
while(!pPool->m_Shutdown)
|
while(!pPool->m_Shutdown)
|
||||||
{
|
{
|
||||||
CJob *pJob = 0;
|
std::shared_ptr<IJob> pJob = 0;
|
||||||
|
|
||||||
// fetch job from queue
|
// fetch job from queue
|
||||||
sphore_wait(&pPool->m_Semaphore);
|
sphore_wait(&pPool->m_Semaphore);
|
||||||
|
@ -40,9 +65,7 @@ void CJobPool::WorkerThread(void *pUser)
|
||||||
{
|
{
|
||||||
pJob = pPool->m_pFirstJob;
|
pJob = pPool->m_pFirstJob;
|
||||||
pPool->m_pFirstJob = pPool->m_pFirstJob->m_pNext;
|
pPool->m_pFirstJob = pPool->m_pFirstJob->m_pNext;
|
||||||
if(pPool->m_pFirstJob)
|
if(!pPool->m_pFirstJob)
|
||||||
pPool->m_pFirstJob->m_pPrev = 0;
|
|
||||||
else
|
|
||||||
pPool->m_pLastJob = 0;
|
pPool->m_pLastJob = 0;
|
||||||
}
|
}
|
||||||
lock_unlock(pPool->m_Lock);
|
lock_unlock(pPool->m_Lock);
|
||||||
|
@ -50,11 +73,9 @@ void CJobPool::WorkerThread(void *pUser)
|
||||||
// do the job if we have one
|
// do the job if we have one
|
||||||
if(pJob)
|
if(pJob)
|
||||||
{
|
{
|
||||||
pJob->m_Status = CJob::STATE_RUNNING;
|
pJob->m_Status = IJob::STATE_RUNNING;
|
||||||
pJob->m_Result = pJob->m_pfnFunc(pJob->m_pFuncData);
|
pJob->Run();
|
||||||
pJob->m_Status = CJob::STATE_DONE;
|
pJob->m_Status = IJob::STATE_DONE;
|
||||||
if(pJob->m_pfnDestroy)
|
|
||||||
pJob->m_pfnDestroy(pJob, pJob->m_pFuncData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,17 +90,11 @@ int CJobPool::Init(int NumThreads)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CJobPool::Add(CJob *pJob, JOBFUNC pfnFunc, void *pData, CBFUNC pfnDestroy)
|
int CJobPool::Add(std::shared_ptr<IJob> pJob)
|
||||||
{
|
{
|
||||||
mem_zero(pJob, sizeof(CJob));
|
|
||||||
pJob->m_pfnFunc = pfnFunc;
|
|
||||||
pJob->m_pFuncData = pData;
|
|
||||||
pJob->m_pfnDestroy = pfnDestroy;
|
|
||||||
|
|
||||||
lock_wait(m_Lock);
|
lock_wait(m_Lock);
|
||||||
|
|
||||||
// add job to queue
|
// add job to queue
|
||||||
pJob->m_pPrev = m_pLastJob;
|
|
||||||
if(m_pLastJob)
|
if(m_pLastJob)
|
||||||
m_pLastJob->m_pNext = pJob;
|
m_pLastJob->m_pNext = pJob;
|
||||||
m_pLastJob = pJob;
|
m_pLastJob = pJob;
|
||||||
|
|
|
@ -2,31 +2,29 @@
|
||||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||||
#ifndef ENGINE_SHARED_JOBS_H
|
#ifndef ENGINE_SHARED_JOBS_H
|
||||||
#define ENGINE_SHARED_JOBS_H
|
#define ENGINE_SHARED_JOBS_H
|
||||||
class CJob;
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class IJob;
|
||||||
class CJobPool;
|
class CJobPool;
|
||||||
|
|
||||||
typedef int (*JOBFUNC)(void *pData);
|
class IJob
|
||||||
typedef void (*CBFUNC)(CJob *pJob, void *pData);
|
|
||||||
|
|
||||||
class CJob
|
|
||||||
{
|
{
|
||||||
friend class CJobPool;
|
friend CJobPool;
|
||||||
|
|
||||||
CJob *m_pPrev;
|
private:
|
||||||
CJob *m_pNext;
|
std::shared_ptr<IJob> m_pNext;
|
||||||
|
|
||||||
volatile int m_Status;
|
std::atomic<int> m_Status;
|
||||||
volatile int m_Result;
|
virtual void Run() = 0;
|
||||||
|
|
||||||
JOBFUNC m_pfnFunc;
|
|
||||||
CBFUNC m_pfnDestroy;
|
|
||||||
void *m_pFuncData;
|
|
||||||
public:
|
public:
|
||||||
CJob()
|
IJob();
|
||||||
{
|
IJob(const IJob &Other);
|
||||||
m_Status = STATE_DONE;
|
IJob &operator=(const IJob &Other);
|
||||||
m_pFuncData = 0;
|
virtual ~IJob();
|
||||||
}
|
int Status();
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -34,9 +32,6 @@ public:
|
||||||
STATE_RUNNING,
|
STATE_RUNNING,
|
||||||
STATE_DONE
|
STATE_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
int Status() const { return m_Status; }
|
|
||||||
int Result() const { return m_Result; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CJobPool
|
class CJobPool
|
||||||
|
@ -51,8 +46,8 @@ class CJobPool
|
||||||
|
|
||||||
LOCK m_Lock;
|
LOCK m_Lock;
|
||||||
SEMAPHORE m_Semaphore;
|
SEMAPHORE m_Semaphore;
|
||||||
CJob *m_pFirstJob;
|
std::shared_ptr<IJob> m_pFirstJob;
|
||||||
CJob *m_pLastJob;
|
std::shared_ptr<IJob> m_pLastJob;
|
||||||
|
|
||||||
static void WorkerThread(void *pUser);
|
static void WorkerThread(void *pUser);
|
||||||
|
|
||||||
|
@ -61,6 +56,6 @@ public:
|
||||||
~CJobPool();
|
~CJobPool();
|
||||||
|
|
||||||
int Init(int NumThreads);
|
int Init(int NumThreads);
|
||||||
int Add(CJob *pJob, JOBFUNC pfnFunc, void *pData, CBFUNC pfnDestroy = 0);
|
int Add(std::shared_ptr<IJob> pJob);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -20,7 +20,7 @@ public:
|
||||||
NETADDR m_Addr;
|
NETADDR m_Addr;
|
||||||
bool m_Valid;
|
bool m_Valid;
|
||||||
int m_Count;
|
int m_Count;
|
||||||
CHostLookup m_Lookup;
|
std::shared_ptr<CHostLookup> m_pLookup;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -53,11 +53,10 @@ public:
|
||||||
// add lookup jobs
|
// add lookup jobs
|
||||||
for(int i = 0; i < MAX_MASTERSERVERS; i++)
|
for(int i = 0; i < MAX_MASTERSERVERS; i++)
|
||||||
{
|
{
|
||||||
m_pEngine->HostLookup(&m_aMasterServers[i].m_Lookup, m_aMasterServers[i].m_aHostname, Nettype);
|
*m_aMasterServers[i].m_pLookup = CHostLookup(m_aMasterServers[i].m_aHostname, Nettype);
|
||||||
|
m_pEngine->AddJob(m_aMasterServers[i].m_pLookup);
|
||||||
m_aMasterServers[i].m_Valid = false;
|
m_aMasterServers[i].m_Valid = false;
|
||||||
m_aMasterServers[i].m_Count = 0;
|
m_aMasterServers[i].m_Count = 0;
|
||||||
|
|
||||||
//dbg_msg("MasterServer", "Lookup id: %d, name: %s, nettype: %d", i, m_aMasterServers[i].m_aHostname, Nettype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_State = STATE_UPDATE;
|
m_State = STATE_UPDATE;
|
||||||
|
@ -73,23 +72,19 @@ public:
|
||||||
|
|
||||||
for(int i = 0; i < MAX_MASTERSERVERS; i++)
|
for(int i = 0; i < MAX_MASTERSERVERS; i++)
|
||||||
{
|
{
|
||||||
if(m_aMasterServers[i].m_Lookup.m_Job.Status() != CJob::STATE_DONE)
|
if(m_aMasterServers[i].m_pLookup->Status() != IJob::STATE_DONE)
|
||||||
m_State = STATE_UPDATE;
|
m_State = STATE_UPDATE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(m_aMasterServers[i].m_Lookup.m_Job.Result() == 0)
|
if(m_aMasterServers[i].m_pLookup->m_Result == 0)
|
||||||
{
|
{
|
||||||
m_aMasterServers[i].m_Addr = m_aMasterServers[i].m_Lookup.m_Addr;
|
m_aMasterServers[i].m_Addr = m_aMasterServers[i].m_pLookup->m_Addr;
|
||||||
m_aMasterServers[i].m_Addr.port = 8300;
|
m_aMasterServers[i].m_Addr.port = 8300;
|
||||||
m_aMasterServers[i].m_Valid = true;
|
m_aMasterServers[i].m_Valid = true;
|
||||||
|
|
||||||
//dbg_msg("MasterServer", "Set server %d, name: %s with addr-port: %d addr-ip %s addr-type %d", i, m_aMasterServers[i].m_aHostname, m_aMasterServers[i].m_Addr.port, m_aMasterServers[i].m_Addr.ip, m_aMasterServers[i].m_Addr.type);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_aMasterServers[i].m_Valid = false;
|
m_aMasterServers[i].m_Valid = false;
|
||||||
|
|
||||||
// dbg_msg("MasterServer", "Dropped %d, name: %s with addr-port: %d addr-ip %s addr-type %d", i, m_aMasterServers[i].m_aHostname);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ public:
|
||||||
virtual void InitiateUpdate() = 0;
|
virtual void InitiateUpdate() = 0;
|
||||||
|
|
||||||
virtual int GetCurrentState() = 0;
|
virtual int GetCurrentState() = 0;
|
||||||
virtual char *GetCurrentFile() = 0;
|
virtual void GetCurrentFile(char *pBuf, int BufSize) = 0;
|
||||||
virtual int GetCurrentPercent() = 0;
|
virtual int GetCurrentPercent() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1321,9 +1321,15 @@ void CMenus::RenderServerbrowser(CUIRect MainView)
|
||||||
TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f);
|
TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f);
|
||||||
}
|
}
|
||||||
else if(State == IUpdater::CLEAN)
|
else if(State == IUpdater::CLEAN)
|
||||||
|
{
|
||||||
str_format(aBuf, sizeof(aBuf), Localize("Current version: %s"), GAME_VERSION);
|
str_format(aBuf, sizeof(aBuf), Localize("Current version: %s"), GAME_VERSION);
|
||||||
|
}
|
||||||
else if(State >= IUpdater::GETTING_MANIFEST && State < IUpdater::NEED_RESTART)
|
else if(State >= IUpdater::GETTING_MANIFEST && State < IUpdater::NEED_RESTART)
|
||||||
str_format(aBuf, sizeof(aBuf), "Downloading %s:", Updater()->GetCurrentFile());
|
{
|
||||||
|
char aCurrentFile[64];
|
||||||
|
Updater()->GetCurrentFile(aCurrentFile, sizeof(aCurrentFile));
|
||||||
|
str_format(aBuf, sizeof(aBuf), "Downloading %s:", aCurrentFile);
|
||||||
|
}
|
||||||
else if(State == IUpdater::FAIL)
|
else if(State == IUpdater::FAIL)
|
||||||
{
|
{
|
||||||
str_format(aBuf, sizeof(aBuf), "Failed to download a file! Restart client to retry...");
|
str_format(aBuf, sizeof(aBuf), "Failed to download a file! Restart client to retry...");
|
||||||
|
|
|
@ -13,29 +13,25 @@
|
||||||
#include "sounds.h"
|
#include "sounds.h"
|
||||||
|
|
||||||
|
|
||||||
struct CUserData
|
CSoundLoading::CSoundLoading(CGameClient *pGameClient, bool Render) :
|
||||||
|
m_pGameClient(pGameClient),
|
||||||
|
m_Render(Render)
|
||||||
{
|
{
|
||||||
CGameClient *m_pGameClient;
|
}
|
||||||
bool m_Render;
|
|
||||||
} g_UserData;
|
|
||||||
|
|
||||||
static int LoadSoundsThread(void *pUser)
|
void CSoundLoading::Run()
|
||||||
{
|
{
|
||||||
CUserData *pData = static_cast<CUserData *>(pUser);
|
|
||||||
|
|
||||||
for(int s = 0; s < g_pData->m_NumSounds; s++)
|
for(int s = 0; s < g_pData->m_NumSounds; s++)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < g_pData->m_aSounds[s].m_NumSounds; i++)
|
for(int i = 0; i < g_pData->m_aSounds[s].m_NumSounds; i++)
|
||||||
{
|
{
|
||||||
int Id = pData->m_pGameClient->Sound()->LoadWV(g_pData->m_aSounds[s].m_aSounds[i].m_pFilename);
|
int Id = m_pGameClient->Sound()->LoadWV(g_pData->m_aSounds[s].m_aSounds[i].m_pFilename);
|
||||||
g_pData->m_aSounds[s].m_aSounds[i].m_Id = Id;
|
g_pData->m_aSounds[s].m_aSounds[i].m_Id = Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pData->m_Render)
|
if(m_Render)
|
||||||
pData->m_pGameClient->m_pMenus->RenderLoading();
|
m_pGameClient->m_pMenus->RenderLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CSounds::GetSampleId(int SetId)
|
int CSounds::GetSampleId(int SetId)
|
||||||
|
@ -79,16 +75,13 @@ void CSounds::OnInit()
|
||||||
// load sounds
|
// load sounds
|
||||||
if(g_Config.m_ClThreadsoundloading)
|
if(g_Config.m_ClThreadsoundloading)
|
||||||
{
|
{
|
||||||
g_UserData.m_pGameClient = m_pClient;
|
m_pSoundJob = std::make_shared<CSoundLoading>(m_pClient, false);
|
||||||
g_UserData.m_Render = false;
|
m_pClient->Engine()->AddJob(m_pSoundJob);
|
||||||
m_pClient->Engine()->AddJob(&m_SoundJob, LoadSoundsThread, &g_UserData);
|
|
||||||
m_WaitForSoundJob = true;
|
m_WaitForSoundJob = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_UserData.m_pGameClient = m_pClient;
|
CSoundLoading(m_pClient, true).Run();
|
||||||
g_UserData.m_Render = true;
|
|
||||||
LoadSoundsThread(&g_UserData);
|
|
||||||
m_WaitForSoundJob = false;
|
m_WaitForSoundJob = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,7 +106,7 @@ void CSounds::OnRender()
|
||||||
// check for sound initialisation
|
// check for sound initialisation
|
||||||
if(m_WaitForSoundJob)
|
if(m_WaitForSoundJob)
|
||||||
{
|
{
|
||||||
if(m_SoundJob.Status() == CJob::STATE_DONE)
|
if(m_pSoundJob->Status() == IJob::STATE_DONE)
|
||||||
m_WaitForSoundJob = false;
|
m_WaitForSoundJob = false;
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -2,9 +2,20 @@
|
||||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||||
#ifndef GAME_CLIENT_COMPONENTS_SOUNDS_H
|
#ifndef GAME_CLIENT_COMPONENTS_SOUNDS_H
|
||||||
#define GAME_CLIENT_COMPONENTS_SOUNDS_H
|
#define GAME_CLIENT_COMPONENTS_SOUNDS_H
|
||||||
|
#include <engine/engine.h>
|
||||||
#include <engine/sound.h>
|
#include <engine/sound.h>
|
||||||
#include <game/client/component.h>
|
#include <game/client/component.h>
|
||||||
|
|
||||||
|
class CSoundLoading : public IJob
|
||||||
|
{
|
||||||
|
CGameClient *m_pGameClient;
|
||||||
|
bool m_Render;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CSoundLoading(CGameClient *pGameClient, bool Render);
|
||||||
|
void Run();
|
||||||
|
};
|
||||||
|
|
||||||
class CSounds : public CComponent
|
class CSounds : public CComponent
|
||||||
{
|
{
|
||||||
enum
|
enum
|
||||||
|
@ -18,7 +29,7 @@ class CSounds : public CComponent
|
||||||
} m_aQueue[QUEUE_SIZE];
|
} m_aQueue[QUEUE_SIZE];
|
||||||
int m_QueuePos;
|
int m_QueuePos;
|
||||||
int64 m_QueueWaitTime;
|
int64 m_QueueWaitTime;
|
||||||
class CJob m_SoundJob;
|
std::shared_ptr<CSoundLoading> m_pSoundJob;
|
||||||
bool m_WaitForSoundJob;
|
bool m_WaitForSoundJob;
|
||||||
|
|
||||||
int GetSampleId(int SetId);
|
int GetSampleId(int SetId);
|
||||||
|
|
|
@ -43,13 +43,13 @@ public:
|
||||||
|
|
||||||
CPlayerData *PlayerData(int ID) { return &m_aPlayerData[ID]; }
|
CPlayerData *PlayerData(int ID) { return &m_aPlayerData[ID]; }
|
||||||
|
|
||||||
virtual void MapInfo(int ClientID, const char* MapName) = 0;
|
virtual void MapInfo(int ClientID, const char *pMapName) = 0;
|
||||||
virtual void MapVote(int ClientID, const char* MapName) = 0;
|
virtual void MapVote(int ClientID, const char *pMapName) = 0;
|
||||||
virtual void CheckBirthday(int ClientID) = 0;
|
virtual void CheckBirthday(int ClientID) = 0;
|
||||||
virtual void LoadScore(int ClientID) = 0;
|
virtual void LoadScore(int ClientID) = 0;
|
||||||
virtual void SaveScore(int ClientID, float Time, float CpTime[NUM_CHECKPOINTS]) = 0;
|
virtual void SaveScore(int ClientID, float Time, float aCpTime[NUM_CHECKPOINTS]) = 0;
|
||||||
|
|
||||||
virtual void SaveTeamScore(int* ClientIDs, unsigned int Size, float Time) = 0;
|
virtual void SaveTeamScore(int *pClientIDs, unsigned int Size, float Time) = 0;
|
||||||
|
|
||||||
virtual void ShowTop5(IConsole::IResult *pResult, int ClientID, void *pUserData, int Debut=1) = 0;
|
virtual void ShowTop5(IConsole::IResult *pResult, int ClientID, void *pUserData, int Debut=1) = 0;
|
||||||
virtual void ShowRank(int ClientID, const char *pName, bool Search=false) = 0;
|
virtual void ShowRank(int ClientID, const char *pName, bool Search=false) = 0;
|
||||||
|
@ -60,8 +60,8 @@ public:
|
||||||
virtual void ShowTopPoints(IConsole::IResult *pResult, int ClientID, void *pUserData, int Debut=1) = 0;
|
virtual void ShowTopPoints(IConsole::IResult *pResult, int ClientID, void *pUserData, int Debut=1) = 0;
|
||||||
virtual void ShowPoints(int ClientID, const char *pName, bool Search=false) = 0;
|
virtual void ShowPoints(int ClientID, const char *pName, bool Search=false) = 0;
|
||||||
|
|
||||||
virtual void RandomMap(int ClientID, int stars) = 0;
|
virtual void RandomMap(int ClientID, int Stars) = 0;
|
||||||
virtual void RandomUnfinishedMap(int ClientID, int stars) = 0;
|
virtual void RandomUnfinishedMap(int ClientID, int Stars) = 0;
|
||||||
|
|
||||||
virtual void SaveTeam(int Team, const char *pCode, int ClientID, const char *pServer) = 0;
|
virtual void SaveTeam(int Team, const char *pCode, int ClientID, const char *pServer) = 0;
|
||||||
virtual void LoadTeam(const char *pCode, int ClientID) = 0;
|
virtual void LoadTeam(const char *pCode, int ClientID) = 0;
|
||||||
|
|
Loading…
Reference in a new issue