mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-19 22:48:18 +00:00
Merge pull request #7923 from Robyt3/Http-DDNet-Info-Sha-Check
Write DDNet info file only when it changed, initialize HTTP later on client launch, show message box on error, refactoring
This commit is contained in:
commit
68ee8a758b
|
@ -84,7 +84,6 @@ CClient::CClient() :
|
|||
for(auto &DemoRecorder : m_aDemoRecorder)
|
||||
DemoRecorder = CDemoRecorder(&m_SnapshotDelta);
|
||||
m_LastRenderTime = time_get();
|
||||
IStorage::FormatTmpPath(m_aDDNetInfoTmp, sizeof(m_aDDNetInfoTmp), DDNET_INFO_FILE);
|
||||
mem_zero(m_aInputs, sizeof(m_aInputs));
|
||||
mem_zero(m_aapSnapshots, sizeof(m_aapSnapshots));
|
||||
for(auto &SnapshotStorage : m_aSnapshotStorage)
|
||||
|
@ -2054,7 +2053,7 @@ void CClient::FinishMapDownload()
|
|||
}
|
||||
}
|
||||
|
||||
void CClient::ResetDDNetInfo()
|
||||
void CClient::ResetDDNetInfoTask()
|
||||
{
|
||||
if(m_pDDNetInfoTask)
|
||||
{
|
||||
|
@ -2063,56 +2062,50 @@ void CClient::ResetDDNetInfo()
|
|||
}
|
||||
}
|
||||
|
||||
bool CClient::IsDDNetInfoChanged()
|
||||
{
|
||||
IOHANDLE OldFile = m_pStorage->OpenFile(DDNET_INFO_FILE, IOFLAG_READ | IOFLAG_SKIP_BOM, IStorage::TYPE_SAVE);
|
||||
|
||||
if(!OldFile)
|
||||
return true;
|
||||
|
||||
IOHANDLE NewFile = m_pStorage->OpenFile(m_aDDNetInfoTmp, IOFLAG_READ | IOFLAG_SKIP_BOM, IStorage::TYPE_SAVE);
|
||||
|
||||
if(NewFile)
|
||||
{
|
||||
char aOldData[4096];
|
||||
char aNewData[4096];
|
||||
unsigned OldBytes;
|
||||
unsigned NewBytes;
|
||||
|
||||
do
|
||||
{
|
||||
OldBytes = io_read(OldFile, aOldData, sizeof(aOldData));
|
||||
NewBytes = io_read(NewFile, aNewData, sizeof(aNewData));
|
||||
|
||||
if(OldBytes != NewBytes || mem_comp(aOldData, aNewData, OldBytes) != 0)
|
||||
{
|
||||
io_close(NewFile);
|
||||
io_close(OldFile);
|
||||
return true;
|
||||
}
|
||||
} while(OldBytes > 0);
|
||||
|
||||
io_close(NewFile);
|
||||
}
|
||||
|
||||
io_close(OldFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
void CClient::FinishDDNetInfo()
|
||||
{
|
||||
ResetDDNetInfo();
|
||||
if(IsDDNetInfoChanged())
|
||||
if(m_ServerBrowser.DDNetInfoSha256() == m_pDDNetInfoTask->Sha256())
|
||||
{
|
||||
m_pStorage->RenameFile(m_aDDNetInfoTmp, DDNET_INFO_FILE, IStorage::TYPE_SAVE);
|
||||
LoadDDNetInfo();
|
||||
if(m_ServerBrowser.GetCurrentType() == IServerBrowser::TYPE_INTERNET || m_ServerBrowser.GetCurrentType() == IServerBrowser::TYPE_FAVORITES)
|
||||
m_ServerBrowser.Refresh(m_ServerBrowser.GetCurrentType());
|
||||
log_debug("client/info", "DDNet info already up-to-date");
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
char aTempFilename[IO_MAX_PATH_LENGTH];
|
||||
IStorage::FormatTmpPath(aTempFilename, sizeof(aTempFilename), DDNET_INFO_FILE);
|
||||
IOHANDLE File = Storage()->OpenFile(aTempFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE);
|
||||
if(!File)
|
||||
{
|
||||
m_pStorage->RemoveFile(m_aDDNetInfoTmp, IStorage::TYPE_SAVE);
|
||||
log_error("client/info", "Failed to open temporary DDNet info '%s' for writing", aTempFilename);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char *pResult;
|
||||
size_t ResultLength;
|
||||
m_pDDNetInfoTask->Result(&pResult, &ResultLength);
|
||||
dbg_assert(pResult != nullptr, "Invalid info task state");
|
||||
bool Error = io_write(File, pResult, ResultLength) != ResultLength;
|
||||
Error |= io_close(File) != 0;
|
||||
if(Error)
|
||||
{
|
||||
log_error("client/info", "Error writing temporary DDNet info to file '%s'", aTempFilename);
|
||||
return;
|
||||
}
|
||||
|
||||
if(Storage()->FileExists(DDNET_INFO_FILE, IStorage::TYPE_SAVE) && !Storage()->RemoveFile(DDNET_INFO_FILE, IStorage::TYPE_SAVE))
|
||||
{
|
||||
log_error("client/info", "Failed to remove old DDNet info '%s'", DDNET_INFO_FILE);
|
||||
Storage()->RemoveFile(aTempFilename, IStorage::TYPE_SAVE);
|
||||
return;
|
||||
}
|
||||
if(!Storage()->RenameFile(aTempFilename, DDNET_INFO_FILE, IStorage::TYPE_SAVE))
|
||||
{
|
||||
log_error("client/info", "Failed to rename temporary DDNet info '%s' to '%s'", aTempFilename, DDNET_INFO_FILE);
|
||||
Storage()->RemoveFile(aTempFilename, IStorage::TYPE_SAVE);
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug("client/info", "Loading new DDNet info");
|
||||
LoadDDNetInfo();
|
||||
}
|
||||
|
||||
typedef std::tuple<int, int, int> TVersion;
|
||||
|
@ -2590,16 +2583,13 @@ void CClient::Update()
|
|||
if(m_pDDNetInfoTask)
|
||||
{
|
||||
if(m_pDDNetInfoTask->State() == EHttpState::DONE)
|
||||
{
|
||||
FinishDDNetInfo();
|
||||
else if(m_pDDNetInfoTask->State() == EHttpState::ERROR)
|
||||
{
|
||||
Storage()->RemoveFile(m_aDDNetInfoTmp, IStorage::TYPE_SAVE);
|
||||
ResetDDNetInfo();
|
||||
ResetDDNetInfoTask();
|
||||
}
|
||||
else if(m_pDDNetInfoTask->State() == EHttpState::ABORTED)
|
||||
else if(m_pDDNetInfoTask->State() == EHttpState::ERROR || m_pDDNetInfoTask->State() == EHttpState::ABORTED)
|
||||
{
|
||||
Storage()->RemoveFile(m_aDDNetInfoTmp, IStorage::TYPE_SAVE);
|
||||
m_pDDNetInfoTask = NULL;
|
||||
ResetDDNetInfoTask();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2685,8 +2675,6 @@ void CClient::InitInterfaces()
|
|||
|
||||
m_DemoEditor.Init(m_pGameClient->NetVersion(), &m_SnapshotDelta, m_pConsole, m_pStorage);
|
||||
|
||||
m_Http.Init(std::chrono::seconds{1});
|
||||
|
||||
m_ServerBrowser.SetBaseInfo(&m_aNetClient[CONN_CONTACT], m_pGameClient->NetVersion());
|
||||
|
||||
#if defined(CONF_AUTOUPDATE)
|
||||
|
@ -2757,6 +2745,14 @@ void CClient::Run()
|
|||
}
|
||||
#endif
|
||||
|
||||
if(!m_Http.Init(std::chrono::seconds{1}))
|
||||
{
|
||||
const char *pErrorMessage = "Failed to initialize the HTTP client.";
|
||||
log_error("client", "%s", pErrorMessage);
|
||||
ShowMessageBox("HTTP Error", pErrorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
// init text render
|
||||
m_pTextRender = Kernel()->RequestInterface<IEngineTextRender>();
|
||||
m_pTextRender->Init();
|
||||
|
@ -3002,11 +2998,6 @@ void CClient::Run()
|
|||
s_SavedConfig = true;
|
||||
}
|
||||
|
||||
if(m_pStorage->FileExists(m_aDDNetInfoTmp, IStorage::TYPE_SAVE))
|
||||
{
|
||||
m_pStorage->RemoveFile(m_aDDNetInfoTmp, IStorage::TYPE_SAVE);
|
||||
}
|
||||
|
||||
if(m_vWarnings.empty() && !GameClient()->IsDisplayingWarning())
|
||||
break;
|
||||
}
|
||||
|
@ -4572,7 +4563,7 @@ void CClient::RequestDDNetInfo()
|
|||
}
|
||||
|
||||
// Use ipv4 so we can know the ingame ip addresses of players before they join game servers
|
||||
m_pDDNetInfoTask = HttpGetFile(aUrl, Storage(), m_aDDNetInfoTmp, IStorage::TYPE_SAVE);
|
||||
m_pDDNetInfoTask = HttpGet(aUrl);
|
||||
m_pDDNetInfoTask->Timeout(CTimeout{10000, 0, 500, 10});
|
||||
m_pDDNetInfoTask->IpResolve(IPRESOLVE::V4);
|
||||
Http()->Run(m_pDDNetInfoTask);
|
||||
|
|
|
@ -157,7 +157,6 @@ class CClient : public IClient, public CDemoPlayer::IListener
|
|||
SHA256_DIGEST m_MapDetailsSha256 = SHA256_ZEROED;
|
||||
char m_aMapDetailsUrl[256] = "";
|
||||
|
||||
char m_aDDNetInfoTmp[64];
|
||||
std::shared_ptr<CHttpRequest> m_pDDNetInfoTask = nullptr;
|
||||
|
||||
// time
|
||||
|
@ -353,8 +352,7 @@ public:
|
|||
void FinishMapDownload();
|
||||
|
||||
void RequestDDNetInfo() override;
|
||||
void ResetDDNetInfo();
|
||||
bool IsDDNetInfoChanged();
|
||||
void ResetDDNetInfoTask();
|
||||
void FinishDDNetInfo();
|
||||
void LoadDDNetInfo();
|
||||
|
||||
|
|
|
@ -66,9 +66,6 @@ CServerBrowser::CServerBrowser() :
|
|||
m_BroadcastTime = 0;
|
||||
secure_random_fill(m_aTokenSeed, sizeof(m_aTokenSeed));
|
||||
|
||||
m_pDDNetInfo = nullptr;
|
||||
m_DDNetInfoUpdateTime = 0;
|
||||
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
|
@ -1272,7 +1269,6 @@ const json_value *CServerBrowser::LoadDDNetInfo()
|
|||
UpdateServerCommunity(&m_ppServerlist[i]->m_Info);
|
||||
UpdateServerRank(&m_ppServerlist[i]->m_Info);
|
||||
}
|
||||
m_DDNetInfoUpdateTime = time_get();
|
||||
return m_pDDNetInfo;
|
||||
}
|
||||
|
||||
|
@ -1281,7 +1277,12 @@ void CServerBrowser::LoadDDNetInfoJson()
|
|||
void *pBuf;
|
||||
unsigned Length;
|
||||
if(!m_pStorage->ReadFile(DDNET_INFO_FILE, IStorage::TYPE_SAVE, &pBuf, &Length))
|
||||
{
|
||||
m_DDNetInfoSha256 = SHA256_ZEROED;
|
||||
return;
|
||||
}
|
||||
|
||||
m_DDNetInfoSha256 = sha256(pBuf, Length);
|
||||
|
||||
json_value_free(m_pDDNetInfo);
|
||||
json_settings JsonSettings{};
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#ifndef ENGINE_CLIENT_SERVERBROWSER_H
|
||||
#define ENGINE_CLIENT_SERVERBROWSER_H
|
||||
|
||||
#include <base/hash.h>
|
||||
#include <base/system.h>
|
||||
|
||||
#include <engine/console.h>
|
||||
|
@ -252,7 +253,7 @@ public:
|
|||
unsigned CurrentCommunitiesHash() const override;
|
||||
|
||||
bool DDNetInfoAvailable() const override { return m_pDDNetInfo != nullptr; }
|
||||
int64_t DDNetInfoUpdateTime() const override { return m_DDNetInfoUpdateTime; }
|
||||
SHA256_DIGEST DDNetInfoSha256() const override { return m_DDNetInfoSha256; }
|
||||
|
||||
CFavoriteCommunityFilterList &FavoriteCommunitiesFilter() override { return m_FavoriteCommunitiesFilter; }
|
||||
CExcludedCommunityFilterList &CommunitiesFilter() override { return m_CommunitiesFilter; }
|
||||
|
@ -311,8 +312,8 @@ private:
|
|||
CExcludedCommunityCountryFilterList m_CountriesFilter;
|
||||
CExcludedCommunityTypeFilterList m_TypesFilter;
|
||||
|
||||
json_value *m_pDDNetInfo;
|
||||
int64_t m_DDNetInfoUpdateTime;
|
||||
json_value *m_pDDNetInfo = nullptr;
|
||||
SHA256_DIGEST m_DDNetInfoSha256 = SHA256_ZEROED;
|
||||
|
||||
CServerEntry *m_pFirstReqServer; // request list
|
||||
CServerEntry *m_pLastReqServer;
|
||||
|
|
|
@ -306,7 +306,7 @@ public:
|
|||
virtual unsigned CurrentCommunitiesHash() const = 0;
|
||||
|
||||
virtual bool DDNetInfoAvailable() const = 0;
|
||||
virtual int64_t DDNetInfoUpdateTime() const = 0;
|
||||
virtual SHA256_DIGEST DDNetInfoSha256() const = 0;
|
||||
|
||||
virtual IFilterList &FavoriteCommunitiesFilter() = 0;
|
||||
virtual IFilterList &CommunitiesFilter() = 0;
|
||||
|
|
|
@ -67,26 +67,15 @@ bool HttpHasIpresolveBug()
|
|||
CHttpRequest::CHttpRequest(const char *pUrl)
|
||||
{
|
||||
str_copy(m_aUrl, pUrl);
|
||||
sha256_init(&m_ActualSha256);
|
||||
sha256_init(&m_ActualSha256Ctx);
|
||||
}
|
||||
|
||||
CHttpRequest::~CHttpRequest()
|
||||
{
|
||||
m_ResponseLength = 0;
|
||||
if(!m_WriteToFile)
|
||||
{
|
||||
m_BufferSize = 0;
|
||||
free(m_pBuffer);
|
||||
m_pBuffer = nullptr;
|
||||
}
|
||||
dbg_assert(m_File == nullptr, "HTTP request file was not closed");
|
||||
free(m_pBuffer);
|
||||
curl_slist_free_all((curl_slist *)m_pHeaders);
|
||||
m_pHeaders = nullptr;
|
||||
if(m_pBody)
|
||||
{
|
||||
m_BodyLength = 0;
|
||||
free(m_pBody);
|
||||
m_pBody = nullptr;
|
||||
}
|
||||
free(m_pBody);
|
||||
}
|
||||
|
||||
bool CHttpRequest::BeforeInit()
|
||||
|
@ -95,14 +84,14 @@ bool CHttpRequest::BeforeInit()
|
|||
{
|
||||
if(fs_makedir_rec_for(m_aDestAbsolute) < 0)
|
||||
{
|
||||
dbg_msg("http", "i/o error, cannot create folder for: %s", m_aDest);
|
||||
log_error("http", "i/o error, cannot create folder for: %s", m_aDest);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_File = io_open(m_aDestAbsolute, IOFLAG_WRITE);
|
||||
if(!m_File)
|
||||
{
|
||||
dbg_msg("http", "i/o error, cannot open file: %s", m_aDest);
|
||||
log_error("http", "i/o error, cannot open file: %s", m_aDest);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -224,7 +213,7 @@ size_t CHttpRequest::OnData(char *pData, size_t DataSize)
|
|||
return 0;
|
||||
}
|
||||
|
||||
sha256_update(&m_ActualSha256, pData, DataSize);
|
||||
sha256_update(&m_ActualSha256Ctx, pData, DataSize);
|
||||
|
||||
if(!m_WriteToFile)
|
||||
{
|
||||
|
@ -277,34 +266,38 @@ void CHttpRequest::OnCompletionInternal(std::optional<unsigned int> Result)
|
|||
if(Code != CURLE_OK)
|
||||
{
|
||||
if(g_Config.m_DbgCurl || m_LogProgress >= HTTPLOG::FAILURE)
|
||||
dbg_msg("http", "%s failed. libcurl error (%u): %s", m_aUrl, Code, m_aErr);
|
||||
{
|
||||
log_error("http", "%s failed. libcurl error (%u): %s", m_aUrl, Code, m_aErr);
|
||||
}
|
||||
State = (Code == CURLE_ABORTED_BY_CALLBACK) ? EHttpState::ABORTED : EHttpState::ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(g_Config.m_DbgCurl || m_LogProgress >= HTTPLOG::ALL)
|
||||
dbg_msg("http", "task done: %s", m_aUrl);
|
||||
{
|
||||
log_info("http", "task done: %s", m_aUrl);
|
||||
}
|
||||
State = EHttpState::DONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_msg("http", "%s failed. internal error: %s", m_aUrl, m_aErr);
|
||||
log_error("http", "%s failed. internal error: %s", m_aUrl, m_aErr);
|
||||
State = EHttpState::ERROR;
|
||||
}
|
||||
|
||||
if(State == EHttpState::DONE && m_ExpectedSha256 != SHA256_ZEROED)
|
||||
if(State == EHttpState::DONE)
|
||||
{
|
||||
const SHA256_DIGEST ActualSha256 = sha256_finish(&m_ActualSha256);
|
||||
if(ActualSha256 != m_ExpectedSha256)
|
||||
m_ActualSha256 = sha256_finish(&m_ActualSha256Ctx);
|
||||
if(m_ExpectedSha256 != SHA256_ZEROED && m_ActualSha256 != m_ExpectedSha256)
|
||||
{
|
||||
if(g_Config.m_DbgCurl || m_LogProgress >= HTTPLOG::FAILURE)
|
||||
{
|
||||
char aActualSha256[SHA256_MAXSTRSIZE];
|
||||
sha256_str(ActualSha256, aActualSha256, sizeof(aActualSha256));
|
||||
sha256_str(m_ActualSha256, aActualSha256, sizeof(aActualSha256));
|
||||
char aExpectedSha256[SHA256_MAXSTRSIZE];
|
||||
sha256_str(m_ExpectedSha256, aExpectedSha256, sizeof(aExpectedSha256));
|
||||
dbg_msg("http", "SHA256 mismatch: got=%s, expected=%s, url=%s", aActualSha256, aExpectedSha256, m_aUrl);
|
||||
log_error("http", "SHA256 mismatch: got=%s, expected=%s, url=%s", aActualSha256, aExpectedSha256, m_aUrl);
|
||||
}
|
||||
State = EHttpState::ERROR;
|
||||
}
|
||||
|
@ -314,9 +307,10 @@ void CHttpRequest::OnCompletionInternal(std::optional<unsigned int> Result)
|
|||
{
|
||||
if(m_File && io_close(m_File) != 0)
|
||||
{
|
||||
dbg_msg("http", "i/o error, cannot close file: %s", m_aDest);
|
||||
log_error("http", "i/o error, cannot close file: %s", m_aDest);
|
||||
State = EHttpState::ERROR;
|
||||
}
|
||||
m_File = nullptr;
|
||||
|
||||
if(State == EHttpState::ERROR || State == EHttpState::ABORTED)
|
||||
{
|
||||
|
@ -422,7 +416,7 @@ void CHttp::RunLoop()
|
|||
std::unique_lock Lock(m_Lock);
|
||||
if(curl_global_init(CURL_GLOBAL_DEFAULT))
|
||||
{
|
||||
dbg_msg("http", "curl_global_init failed");
|
||||
log_error("http", "curl_global_init failed");
|
||||
m_State = CHttp::ERROR;
|
||||
m_Cv.notify_all();
|
||||
return;
|
||||
|
@ -431,7 +425,7 @@ void CHttp::RunLoop()
|
|||
m_pMultiH = curl_multi_init();
|
||||
if(!m_pMultiH)
|
||||
{
|
||||
dbg_msg("http", "curl_multi_init failed");
|
||||
log_error("http", "curl_multi_init failed");
|
||||
m_State = CHttp::ERROR;
|
||||
m_Cv.notify_all();
|
||||
return;
|
||||
|
@ -440,19 +434,18 @@ void CHttp::RunLoop()
|
|||
// print curl version
|
||||
{
|
||||
curl_version_info_data *pVersion = curl_version_info(CURLVERSION_NOW);
|
||||
dbg_msg("http", "libcurl version %s (compiled = " LIBCURL_VERSION ")", pVersion->version);
|
||||
log_info("http", "libcurl version %s (compiled = " LIBCURL_VERSION ")", pVersion->version);
|
||||
}
|
||||
|
||||
m_State = CHttp::RUNNING;
|
||||
m_Cv.notify_all();
|
||||
dbg_msg("http", "running");
|
||||
Lock.unlock();
|
||||
|
||||
while(m_State == CHttp::RUNNING)
|
||||
{
|
||||
static int NextTimeout = std::numeric_limits<int>::max();
|
||||
static int s_NextTimeout = std::numeric_limits<int>::max();
|
||||
int Events = 0;
|
||||
CURLMcode mc = curl_multi_poll(m_pMultiH, NULL, 0, NextTimeout, &Events);
|
||||
const CURLMcode PollCode = curl_multi_poll(m_pMultiH, nullptr, 0, s_NextTimeout, &Events);
|
||||
|
||||
// We may have been woken up for a shutdown
|
||||
if(m_Shutdown)
|
||||
|
@ -461,7 +454,7 @@ void CHttp::RunLoop()
|
|||
if(!m_ShutdownTime.has_value())
|
||||
{
|
||||
m_ShutdownTime = Now + m_ShutdownDelay;
|
||||
NextTimeout = m_ShutdownDelay.count();
|
||||
s_NextTimeout = m_ShutdownDelay.count();
|
||||
}
|
||||
else if(m_ShutdownTime < Now || m_RunningRequests.empty())
|
||||
{
|
||||
|
@ -469,36 +462,36 @@ void CHttp::RunLoop()
|
|||
}
|
||||
}
|
||||
|
||||
if(mc != CURLM_OK)
|
||||
if(PollCode != CURLM_OK)
|
||||
{
|
||||
Lock.lock();
|
||||
dbg_msg("http", "Failed multi wait: %s", curl_multi_strerror(mc));
|
||||
log_error("http", "Failed multi wait: %s", curl_multi_strerror(PollCode));
|
||||
m_State = CHttp::ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
mc = curl_multi_perform(m_pMultiH, &Events);
|
||||
if(mc != CURLM_OK)
|
||||
const CURLMcode PerformCode = curl_multi_perform(m_pMultiH, &Events);
|
||||
if(PerformCode != CURLM_OK)
|
||||
{
|
||||
Lock.lock();
|
||||
dbg_msg("http", "Failed multi perform: %s", curl_multi_strerror(mc));
|
||||
log_error("http", "Failed multi perform: %s", curl_multi_strerror(PerformCode));
|
||||
m_State = CHttp::ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
struct CURLMsg *m;
|
||||
while((m = curl_multi_info_read(m_pMultiH, &Events)))
|
||||
struct CURLMsg *pMsg;
|
||||
while((pMsg = curl_multi_info_read(m_pMultiH, &Events)))
|
||||
{
|
||||
if(m->msg == CURLMSG_DONE)
|
||||
if(pMsg->msg == CURLMSG_DONE)
|
||||
{
|
||||
auto RequestIt = m_RunningRequests.find(m->easy_handle);
|
||||
auto RequestIt = m_RunningRequests.find(pMsg->easy_handle);
|
||||
dbg_assert(RequestIt != m_RunningRequests.end(), "Running handle not added to map");
|
||||
auto pRequest = std::move(RequestIt->second);
|
||||
m_RunningRequests.erase(RequestIt);
|
||||
|
||||
pRequest->OnCompletionInternal(m->data.result);
|
||||
curl_multi_remove_handle(m_pMultiH, m->easy_handle);
|
||||
curl_easy_cleanup(m->easy_handle);
|
||||
pRequest->OnCompletionInternal(pMsg->data.result);
|
||||
curl_multi_remove_handle(m_pMultiH, pMsg->easy_handle);
|
||||
curl_easy_cleanup(pMsg->easy_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -511,7 +504,7 @@ void CHttp::RunLoop()
|
|||
{
|
||||
auto &pRequest = NewRequests.front();
|
||||
if(g_Config.m_DbgCurl)
|
||||
dbg_msg("http", "task: %s %s", CHttpRequest::GetRequestType(pRequest->m_Type), pRequest->m_aUrl);
|
||||
log_debug("http", "task: %s %s", CHttpRequest::GetRequestType(pRequest->m_Type), pRequest->m_aUrl);
|
||||
|
||||
CURL *pEH = curl_easy_init();
|
||||
if(!pEH)
|
||||
|
@ -520,8 +513,7 @@ void CHttp::RunLoop()
|
|||
if(!pRequest->ConfigureHandle(pEH))
|
||||
goto error_configure;
|
||||
|
||||
mc = curl_multi_add_handle(m_pMultiH, pEH);
|
||||
if(mc != CURLM_OK)
|
||||
if(curl_multi_add_handle(m_pMultiH, pEH) != CURLM_OK)
|
||||
goto error_configure;
|
||||
|
||||
m_RunningRequests.emplace(pEH, std::move(pRequest));
|
||||
|
@ -532,7 +524,7 @@ void CHttp::RunLoop()
|
|||
error_configure:
|
||||
curl_easy_cleanup(pEH);
|
||||
error_init:
|
||||
dbg_msg("http", "failed to start new request");
|
||||
log_error("http", "failed to start new request");
|
||||
Lock.lock();
|
||||
m_State = CHttp::ERROR;
|
||||
break;
|
||||
|
|
|
@ -88,7 +88,8 @@ class CHttpRequest : public IHttpRequest
|
|||
int64_t m_MaxResponseSize = -1;
|
||||
REQUEST m_Type = REQUEST::GET;
|
||||
|
||||
SHA256_CTX m_ActualSha256;
|
||||
SHA256_DIGEST m_ActualSha256 = SHA256_ZEROED;
|
||||
SHA256_CTX m_ActualSha256Ctx;
|
||||
SHA256_DIGEST m_ExpectedSha256 = SHA256_ZEROED;
|
||||
|
||||
bool m_WriteToFile = false;
|
||||
|
@ -197,6 +198,8 @@ public:
|
|||
|
||||
void Result(unsigned char **ppResult, size_t *pResultLength) const;
|
||||
json_value *ResultJson() const;
|
||||
|
||||
const SHA256_DIGEST &Sha256() const { return m_ActualSha256; }
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHttpRequest> HttpHead(const char *pUrl)
|
||||
|
|
|
@ -506,7 +506,7 @@ protected:
|
|||
static void ConchainUiPageUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||
struct SCommunityCache
|
||||
{
|
||||
int64_t m_UpdateTime = 0;
|
||||
SHA256_DIGEST m_InfoSha256 = SHA256_ZEROED;
|
||||
int m_LastPage = 0;
|
||||
unsigned m_SelectedCommunitiesHash;
|
||||
std::vector<const CCommunity *> m_vpSelectedCommunities;
|
||||
|
@ -560,7 +560,7 @@ protected:
|
|||
std::vector<SCommunityIcon> m_vCommunityIcons;
|
||||
std::deque<std::shared_ptr<CCommunityIconLoadJob>> m_CommunityIconLoadJobs;
|
||||
std::deque<std::shared_ptr<CCommunityIconDownloadJob>> m_CommunityIconDownloadJobs;
|
||||
int64_t m_CommunityIconsUpdateTime = 0;
|
||||
SHA256_DIGEST m_CommunityIconsInfoSha256 = SHA256_ZEROED;
|
||||
static int CommunityIconScan(const char *pName, int IsDir, int DirType, void *pUser);
|
||||
const SCommunityIcon *FindCommunityIcon(const char *pCommunityId);
|
||||
bool LoadCommunityIconFile(const char *pPath, int DirType, CImageInfo &Info, SHA256_DIGEST &Sha256);
|
||||
|
|
|
@ -1840,8 +1840,8 @@ void CMenus::UpdateCommunityCache(bool Force)
|
|||
ServerBrowser()->Refresh(g_Config.m_UiPage - PAGE_FAVORITE_COMMUNITY_1 + IServerBrowser::TYPE_FAVORITE_COMMUNITY_1, true);
|
||||
}
|
||||
|
||||
if(!Force && m_CommunityCache.m_UpdateTime != 0 &&
|
||||
m_CommunityCache.m_UpdateTime == ServerBrowser()->DDNetInfoUpdateTime() &&
|
||||
if(!Force && m_CommunityCache.m_InfoSha256 != SHA256_ZEROED &&
|
||||
m_CommunityCache.m_InfoSha256 == ServerBrowser()->DDNetInfoSha256() &&
|
||||
!CurrentCommunitiesChanged && !PageChanged)
|
||||
{
|
||||
return;
|
||||
|
@ -1849,7 +1849,7 @@ void CMenus::UpdateCommunityCache(bool Force)
|
|||
|
||||
ServerBrowser()->CleanFilters();
|
||||
|
||||
m_CommunityCache.m_UpdateTime = ServerBrowser()->DDNetInfoUpdateTime();
|
||||
m_CommunityCache.m_InfoSha256 = ServerBrowser()->DDNetInfoSha256();
|
||||
m_CommunityCache.m_LastPage = g_Config.m_UiPage;
|
||||
m_CommunityCache.m_SelectedCommunitiesHash = CommunitiesHash;
|
||||
m_CommunityCache.m_vpSelectedCommunities = ServerBrowser()->CurrentCommunities();
|
||||
|
@ -2055,9 +2055,9 @@ void CMenus::UpdateCommunityIcons()
|
|||
}
|
||||
|
||||
// Rescan for changed communities only when necessary
|
||||
if(!ServerBrowser()->DDNetInfoAvailable() || (m_CommunityIconsUpdateTime != 0 && m_CommunityIconsUpdateTime == ServerBrowser()->DDNetInfoUpdateTime()))
|
||||
if(!ServerBrowser()->DDNetInfoAvailable() || (m_CommunityIconsInfoSha256 != SHA256_ZEROED && m_CommunityIconsInfoSha256 == ServerBrowser()->DDNetInfoSha256()))
|
||||
return;
|
||||
m_CommunityIconsUpdateTime = ServerBrowser()->DDNetInfoUpdateTime();
|
||||
m_CommunityIconsInfoSha256 = ServerBrowser()->DDNetInfoSha256();
|
||||
|
||||
// Remove icons for removed communities
|
||||
auto RemovalIterator = m_vCommunityIcons.begin();
|
||||
|
|
Loading…
Reference in a new issue