HTTP: Set final m_State after running completion function

Ensures that we don't delete a file that is being used by ingame map
downloader already.

As reported by Jupeyy in #2901
This commit is contained in:
def 2020-09-24 09:52:11 +02:00
parent 1c3244a8f5
commit 2be54a30ad
3 changed files with 39 additions and 31 deletions

View file

@ -88,18 +88,19 @@ CRequest::CRequest(const char *pUrl, CTimeout Timeout, bool LogProgress)
void CRequest::Run() void CRequest::Run()
{ {
int FinalState;
if(!BeforeInit()) if(!BeforeInit())
{ {
m_State = HTTP_ERROR; FinalState = HTTP_ERROR;
OnCompletion(); }
return; else
{
CURL *pHandle = curl_easy_init();
FinalState = RunImpl(pHandle);
curl_easy_cleanup(pHandle);
} }
CURL *pHandle = curl_easy_init(); m_State = OnCompletion(FinalState);
m_State = RunImpl(pHandle);
curl_easy_cleanup(pHandle);
OnCompletion();
} }
int CRequest::RunImpl(CURL *pHandle) int CRequest::RunImpl(CURL *pHandle)
@ -144,10 +145,6 @@ int CRequest::RunImpl(CURL *pHandle)
dbg_msg("http", "http %s", m_aUrl); dbg_msg("http", "http %s", m_aUrl);
m_State = HTTP_RUNNING; m_State = HTTP_RUNNING;
int Ret = curl_easy_perform(pHandle); int Ret = curl_easy_perform(pHandle);
if(!BeforeCompletion())
{
return HTTP_ERROR;
}
if(Ret != CURLE_OK) if(Ret != CURLE_OK)
{ {
if(g_Config.m_DbgCurl || m_LogProgress) if(g_Config.m_DbgCurl || m_LogProgress)
@ -253,7 +250,8 @@ size_t CGet::OnData(char *pData, size_t DataSize)
CGetFile::CGetFile(IStorage *pStorage, const char *pUrl, const char *pDest, int StorageType, CTimeout Timeout, bool LogProgress) CGetFile::CGetFile(IStorage *pStorage, const char *pUrl, const char *pDest, int StorageType, CTimeout Timeout, bool LogProgress)
: CRequest(pUrl, Timeout, LogProgress), : CRequest(pUrl, Timeout, LogProgress),
m_pStorage(pStorage), m_pStorage(pStorage),
m_StorageType(StorageType) m_StorageType(StorageType),
m_File(0)
{ {
str_copy(m_aDest, pDest, sizeof(m_aDest)); str_copy(m_aDest, pDest, sizeof(m_aDest));
@ -285,17 +283,19 @@ size_t CGetFile::OnData(char *pData, size_t DataSize)
return io_write(m_File, pData, DataSize); return io_write(m_File, pData, DataSize);
} }
bool CGetFile::BeforeCompletion() int CGetFile::OnCompletion(int State)
{ {
return io_close(m_File) == 0; if(m_File && io_close(m_File) != 0)
} {
State = HTTP_ERROR;
}
void CGetFile::OnCompletion() if(State == HTTP_ERROR || State == HTTP_ABORTED)
{
if(State() == HTTP_ERROR || State() == HTTP_ABORTED)
{ {
m_pStorage->RemoveFile(m_aDestFull, IStorage::TYPE_ABSOLUTE); m_pStorage->RemoveFile(m_aDestFull, IStorage::TYPE_ABSOLUTE);
} }
return State;
} }
CPostJson::CPostJson(const char *pUrl, CTimeout Timeout, const char *pJson) CPostJson::CPostJson(const char *pUrl, CTimeout Timeout, const char *pJson)

View file

@ -33,9 +33,7 @@ class CRequest : public IJob
virtual bool AfterInit(void *pCurl) { return true; } virtual bool AfterInit(void *pCurl) { return true; }
virtual size_t OnData(char *pData, size_t DataSize) = 0; virtual size_t OnData(char *pData, size_t DataSize) = 0;
virtual void OnProgress() { } virtual void OnProgress() {}
virtual bool BeforeCompletion() { return true; }
virtual void OnCompletion() { }
char m_aUrl[256]; char m_aUrl[256];
@ -55,6 +53,9 @@ class CRequest : public IJob
void Run(); void Run();
int RunImpl(CURL *pHandle); int RunImpl(CURL *pHandle);
protected:
virtual int OnCompletion(int State) { return State; }
public: public:
CRequest(const char *pUrl, CTimeout Timeout, bool LogProgress = true); CRequest(const char *pUrl, CTimeout Timeout, bool LogProgress = true);
@ -87,8 +88,6 @@ class CGetFile : public CRequest
{ {
virtual size_t OnData(char *pData, size_t DataSize); virtual size_t OnData(char *pData, size_t DataSize);
virtual bool BeforeInit(); virtual bool BeforeInit();
virtual bool BeforeCompletion();
virtual void OnCompletion();
IStorage *m_pStorage; IStorage *m_pStorage;
@ -97,6 +96,9 @@ class CGetFile : public CRequest
int m_StorageType; int m_StorageType;
IOHANDLE m_File; IOHANDLE m_File;
protected:
virtual int OnCompletion(int State);
public: public:
CGetFile(IStorage *pStorage, const char *pUrl, const char *pDest, int StorageType = -2, CTimeout Timeout = CTimeout{4000, 500, 5}, bool LogProgress = true); CGetFile(IStorage *pStorage, const char *pUrl, const char *pDest, int StorageType = -2, CTimeout Timeout = CTimeout{4000, 500, 5}, bool LogProgress = true);

View file

@ -18,8 +18,10 @@ class CUpdaterFetchTask : public CGetFile
char m_aBuf2[256]; char m_aBuf2[256];
CUpdater *m_pUpdater; CUpdater *m_pUpdater;
void OnCompletion(); virtual void OnProgress();
void OnProgress();
protected:
virtual int OnCompletion(int State);
public: public:
CUpdaterFetchTask(CUpdater *pUpdater, const char *pFile, const char *pDestPath); CUpdaterFetchTask(CUpdater *pUpdater, const char *pFile, const char *pDestPath);
@ -55,8 +57,10 @@ void CUpdaterFetchTask::OnProgress()
lock_unlock(m_pUpdater->m_Lock); lock_unlock(m_pUpdater->m_Lock);
} }
void CUpdaterFetchTask::OnCompletion() int CUpdaterFetchTask::OnCompletion(int State)
{ {
State = CGetFile::OnCompletion(State);
const char *b = 0; const char *b = 0;
for(const char *a = Dest(); *a; a++) for(const char *a = Dest(); *a; a++)
if(*a == '/') if(*a == '/')
@ -64,18 +68,20 @@ void CUpdaterFetchTask::OnCompletion()
b = b ? b : Dest(); b = b ? b : Dest();
if(!str_comp(b, "update.json")) if(!str_comp(b, "update.json"))
{ {
if(State() == HTTP_DONE) if(State == HTTP_DONE)
m_pUpdater->SetCurrentState(IUpdater::GOT_MANIFEST); m_pUpdater->SetCurrentState(IUpdater::GOT_MANIFEST);
else if(State() == HTTP_ERROR) else if(State == HTTP_ERROR)
m_pUpdater->SetCurrentState(IUpdater::FAIL); m_pUpdater->SetCurrentState(IUpdater::FAIL);
} }
else if(!str_comp(b, m_pUpdater->m_aLastFile)) else if(!str_comp(b, m_pUpdater->m_aLastFile))
{ {
if(State() == HTTP_DONE) if(State == HTTP_DONE)
m_pUpdater->SetCurrentState(IUpdater::MOVE_FILES); m_pUpdater->SetCurrentState(IUpdater::MOVE_FILES);
else if(State() == HTTP_ERROR) else if(State == HTTP_ERROR)
m_pUpdater->SetCurrentState(IUpdater::FAIL); m_pUpdater->SetCurrentState(IUpdater::FAIL);
} }
return State;
} }
CUpdater::CUpdater() CUpdater::CUpdater()