From f05e28c99f11db2dab3e57e8b9ef0e29da86956d Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Tue, 9 Sep 2025 14:52:59 +0300 Subject: [PATCH 1/4] feat: implement abortDownload function for downloadFile --- .../logic/CSingularFileDownload.cpp | 29 ++++++--- .../deathmatch/logic/CSingularFileDownload.h | 23 ++++--- .../logic/CSingularFileDownloadManager.cpp | 61 +++++++++++++++---- .../logic/CSingularFileDownloadManager.h | 8 +++ .../logic/CStaticFunctionDefinitions.cpp | 7 +-- .../logic/CStaticFunctionDefinitions.h | 5 +- .../logic/lua/CLuaFunctionDefs.Util.cpp | 33 +++++++++- .../deathmatch/logic/lua/CLuaFunctionDefs.h | 1 + .../mods/deathmatch/logic/lua/CLuaManager.cpp | 1 + 9 files changed, 132 insertions(+), 36 deletions(-) diff --git a/Client/mods/deathmatch/logic/CSingularFileDownload.cpp b/Client/mods/deathmatch/logic/CSingularFileDownload.cpp index bb606d0be52..b4857e6c94c 100644 --- a/Client/mods/deathmatch/logic/CSingularFileDownload.cpp +++ b/Client/mods/deathmatch/logic/CSingularFileDownload.cpp @@ -12,7 +12,7 @@ #include CSingularFileDownload::CSingularFileDownload(CResource* pResource, const char* szName, const char* szNameShort, SString strHTTPURL, CResource* pRequestResource, - CChecksum serverChecksum) + CChecksum serverChecksum, std::uint32_t handlerId) { // Store the name m_strName = szName; @@ -28,6 +28,10 @@ CSingularFileDownload::CSingularFileDownload(CResource* pResource, const char* s m_ServerChecksum = serverChecksum; m_bBeingDeleted = false; + m_bCancelled = false; + m_handlerId = handlerId; + m_pHTTPManager = nullptr; + m_downloadMode = EDownloadModeType::NONE; GenerateClientChecksum(); @@ -35,8 +39,9 @@ CSingularFileDownload::CSingularFileDownload(CResource* pResource, const char* s { SHttpRequestOptions options; options.bCheckContents = true; - CNetHTTPDownloadManagerInterface* pHTTP = g_pCore->GetNetwork()->GetHTTPDownloadManager(EDownloadMode::RESOURCE_SINGULAR_FILES); - pHTTP->QueueFile(strHTTPURL.c_str(), szName, this, DownloadFinishedCallBack, options); + m_pHTTPManager = g_pCore->GetNetwork()->GetHTTPDownloadManager(EDownloadMode::RESOURCE_SINGULAR_FILES); + m_downloadMode = EDownloadMode::RESOURCE_SINGULAR_FILES; + m_pHTTPManager->QueueFile(strHTTPURL.c_str(), szName, this, DownloadFinishedCallBack, options); m_bComplete = false; g_pClientGame->SetTransferringSingularFiles(true); } @@ -63,7 +68,7 @@ void CSingularFileDownload::CallFinished(bool bSuccess) if (!m_bBeingDeleted && m_pResource) { - // Call the onClientbFileDownloadComplete event + // Call the onClientFileDownloadComplete event CLuaArguments Arguments; Arguments.PushString(GetShortName()); // file name Arguments.PushBoolean(bSuccess); // Completed successfully? @@ -81,13 +86,21 @@ void CSingularFileDownload::CallFinished(bool bSuccess) SetComplete(); } -void CSingularFileDownload::Cancel() +bool CSingularFileDownload::Cancel() { + if (m_bCancelled || m_bComplete) + return false; + + m_bCancelled = true; m_bBeingDeleted = true; - m_pResource = NULL; - m_pRequestResource = NULL; + m_pResource = nullptr; + m_pRequestResource = nullptr; + + // Cancel the actual HTTP download + if (!m_pHTTPManager || m_downloadMode == EDownloadModeType::NONE) + return true; - // TODO: Cancel also in Net + return m_pHTTPManager->CancelDownload(this, DownloadFinishedCallBack); } bool CSingularFileDownload::DoesClientAndServerChecksumMatch() diff --git a/Client/mods/deathmatch/logic/CSingularFileDownload.h b/Client/mods/deathmatch/logic/CSingularFileDownload.h index b3686c14d85..0ba32909b8b 100644 --- a/Client/mods/deathmatch/logic/CSingularFileDownload.h +++ b/Client/mods/deathmatch/logic/CSingularFileDownload.h @@ -20,28 +20,32 @@ #include #include "CChecksum.h" +#include "net/CNetHTTPDownloadManagerInterface.h" +#include class CSingularFileDownload { public: CSingularFileDownload(CResource* pResource, const char* szName, const char* szNameShort, SString strHTTPURL, CResource* pRequestResource, - CChecksum serverChecksum); + CChecksum serverChecksum, std::uint32_t handlerId); ~CSingularFileDownload(); static void DownloadFinishedCallBack(const SHttpDownloadResult& result); bool DoesClientAndServerChecksumMatch(); - const char* GetName() { return m_strName; }; - const char* GetShortName() { return m_strNameShort; }; + const char* GetName() const noexcept { return m_strName; } + const char* GetShortName() const noexcept { return m_strNameShort; } - CResource* GetResource() { return m_pResource; }; + CResource* GetResource() const noexcept { return m_pResource; } + std::uint32_t GetHandlerId() const noexcept { return m_handlerId; } - void SetComplete() { m_bComplete = true; }; - bool GetComplete() { return m_bComplete; }; + void SetComplete() noexcept { m_bComplete = true; } + bool GetComplete() const noexcept { return m_bComplete; } + bool IsCancelled() const noexcept { return m_bCancelled; } void CallFinished(bool bSuccess); - void Cancel(); + bool Cancel(); CChecksum GenerateClientChecksum(); @@ -54,6 +58,11 @@ class CSingularFileDownload bool m_bComplete; bool m_bBeingDeleted; + bool m_bCancelled; + + std::uint32_t m_handlerId; + CNetHTTPDownloadManagerInterface* m_pHTTPManager; + EDownloadModeType m_downloadMode; CChecksum m_LastClientChecksum; CChecksum m_ServerChecksum; diff --git a/Client/mods/deathmatch/logic/CSingularFileDownloadManager.cpp b/Client/mods/deathmatch/logic/CSingularFileDownloadManager.cpp index 97be6ba0dd2..738d4a38c9b 100644 --- a/Client/mods/deathmatch/logic/CSingularFileDownloadManager.cpp +++ b/Client/mods/deathmatch/logic/CSingularFileDownloadManager.cpp @@ -12,7 +12,7 @@ #include using std::list; -CSingularFileDownloadManager::CSingularFileDownloadManager() +CSingularFileDownloadManager::CSingularFileDownloadManager() : m_nextHandlerId(1) { } @@ -25,38 +25,73 @@ CSingularFileDownloadManager::~CSingularFileDownloadManager() CSingularFileDownload* CSingularFileDownloadManager::AddFile(CResource* pResource, const char* szName, const char* szNameShort, SString strHTTPURL, CResource* pRequestResource, CChecksum checksum) { - CSingularFileDownload* pFile = new CSingularFileDownload(pResource, szName, szNameShort, strHTTPURL, pRequestResource, checksum); + const std::uint32_t handlerId = m_nextHandlerId++; + auto* pFile = new CSingularFileDownload(pResource, szName, szNameShort, strHTTPURL, pRequestResource, checksum, handlerId); m_Downloads.push_back(pFile); - return NULL; + m_HandlerMap[handlerId] = pFile; + return pFile; } void CSingularFileDownloadManager::CancelResourceDownloads(CResource* pResource) { - list::const_iterator iter = m_Downloads.begin(); - for (; iter != m_Downloads.end(); ++iter) + for (const auto& pDownload : m_Downloads) { - if ((*iter)->GetResource() == pResource) - (*iter)->Cancel(); + if (pDownload->GetResource() == pResource) + pDownload->Cancel(); } } void CSingularFileDownloadManager::ClearList() { - list::const_iterator iter = m_Downloads.begin(); - for (; iter != m_Downloads.end(); ++iter) + for (const auto& pDownload : m_Downloads) { - delete *iter; + delete pDownload; } m_Downloads.clear(); + m_HandlerMap.clear(); } bool CSingularFileDownloadManager::AllComplete() { - list::const_iterator iter = m_Downloads.begin(); - for (; iter != m_Downloads.end(); ++iter) + for (const auto& pDownload : m_Downloads) { - if (!(*iter)->GetComplete()) + if (!pDownload->GetComplete()) return false; } return true; +} + +CSingularFileDownload* CSingularFileDownloadManager::FindDownloadByHandler(std::uint32_t handlerId) const +{ + const auto it = m_HandlerMap.find(handlerId); + return (it != m_HandlerMap.end()) ? it->second : nullptr; +} + +bool CSingularFileDownloadManager::AbortDownload(std::uint32_t handlerId) +{ + auto* pDownload = FindDownloadByHandler(handlerId); + if (!pDownload) + return false; + + const bool success = pDownload->Cancel(); + if (success) + { + RemoveDownload(pDownload); + } + return success; +} + +void CSingularFileDownloadManager::RemoveDownload(CSingularFileDownload* pDownload) +{ + if (!pDownload) + return; + + // Remove from handler map + m_HandlerMap.erase(pDownload->GetHandlerId()); + + // Remove from downloads list + m_Downloads.remove(pDownload); + + // Delete the download object + delete pDownload; } \ No newline at end of file diff --git a/Client/mods/deathmatch/logic/CSingularFileDownloadManager.h b/Client/mods/deathmatch/logic/CSingularFileDownloadManager.h index 9b861b5dce8..c75bdf78c2a 100644 --- a/Client/mods/deathmatch/logic/CSingularFileDownloadManager.h +++ b/Client/mods/deathmatch/logic/CSingularFileDownloadManager.h @@ -21,6 +21,8 @@ #include #include "CChecksum.h" #include "CSingularFileDownload.h" +#include +#include class CSingularFileDownloadManager { @@ -36,6 +38,12 @@ class CSingularFileDownloadManager bool AllComplete(); + CSingularFileDownload* FindDownloadByHandler(std::uint32_t handlerId) const; + bool AbortDownload(std::uint32_t handlerId); + void RemoveDownload(CSingularFileDownload* pDownload); + protected: std::list m_Downloads; + std::map m_HandlerMap; + std::uint32_t m_nextHandlerId; }; diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 18430ed7f92..e3007a856f4 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -233,7 +233,7 @@ bool CStaticFunctionDefinitions::WasEventCancelled() return m_pEvents->WasEventCancelled(); } -bool CStaticFunctionDefinitions::DownloadFile(CResource* pResource, const char* szFile, CResource* pRequestResource, CChecksum checksum) +CSingularFileDownload* CStaticFunctionDefinitions::DownloadFile(CResource* pResource, const char* szFile, CResource* pRequestResource, CChecksum checksum) { SString strHTTPDownloadURLFull("%s/%s/%s", g_pClientGame->GetHTTPURL().c_str(), pResource->GetName(), szFile); SString strPath("%s\\resources\\%s\\%s", g_pClientGame->GetFileCacheRoot(), pResource->GetName(), szFile); @@ -241,10 +241,9 @@ bool CStaticFunctionDefinitions::DownloadFile(CResource* pResource, const char* // Call SingularFileDownloadManager if (g_pClientGame->GetSingularFileDownloadManager()) { - g_pClientGame->GetSingularFileDownloadManager()->AddFile(pResource, strPath.c_str(), szFile, strHTTPDownloadURLFull, pRequestResource, checksum); - return true; + return g_pClientGame->GetSingularFileDownloadManager()->AddFile(pResource, strPath.c_str(), szFile, strHTTPDownloadURLFull, pRequestResource, checksum); } - return false; + return nullptr; } bool CStaticFunctionDefinitions::OutputConsole(const char* szText) diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h index 75999cf0882..f3f0b7ea816 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -20,6 +20,9 @@ class CStaticFunctionDefinitions; #include "enums/WeaponProperty.h" #include "enums/ObjectProperty.h" +// Forward declarations +class CSingularFileDownload; + class CStaticFunctionDefinitions { public: @@ -39,7 +42,7 @@ class CStaticFunctionDefinitions static bool WasEventCancelled(); // Misc funcs - static bool DownloadFile(CResource* pResource, const char* szFile, CResource* pRequestResource, CChecksum checksum = CChecksum()); + static CSingularFileDownload* DownloadFile(CResource* pResource, const char* szFile, CResource* pRequestResource, CChecksum checksum = CChecksum()); // Output funcs static bool OutputConsole(const char* szText); diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Util.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Util.cpp index 2df7db7cea2..843ab2c8bd1 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Util.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Util.cpp @@ -390,10 +390,12 @@ int CLuaFunctionDefs::DownloadFile(lua_State* luaVM) { if (strcmp(strMetaPath, (*iter)->GetShortName()) == 0) { - if (CStaticFunctionDefinitions::DownloadFile(pOtherResource, strMetaPath, pThisResource, (*iter)->GetServerChecksum())) + CSingularFileDownload* pDownload = CStaticFunctionDefinitions::DownloadFile(pOtherResource, strMetaPath, pThisResource, (*iter)->GetServerChecksum()); + if (pDownload) { - lua_pushboolean(luaVM, true); - return 1; + lua_pushuserdata(luaVM, pDownload); + lua_pushnumber(luaVM, pDownload->GetHandlerId()); + return 2; } } } @@ -409,6 +411,31 @@ int CLuaFunctionDefs::DownloadFile(lua_State* luaVM) return 1; } +int CLuaFunctionDefs::AbortDownload(lua_State* luaVM) +{ + // bool abortDownload(number handlerId) + std::uint32_t handlerId = 0; + CScriptArgReader argStream(luaVM); + argStream.ReadNumber(handlerId); + + if (!argStream.HasErrors()) + { + if (g_pClientGame->GetSingularFileDownloadManager()) + { + const bool success = g_pClientGame->GetSingularFileDownloadManager()->AbortDownload(handlerId); + lua_pushboolean(luaVM, success); + return 1; + } + } + else + { + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + } + + lua_pushboolean(luaVM, false); + return 1; +} + int CLuaFunctionDefs::AddDebugHook(lua_State* luaVM) { // bool AddDebugHook ( string hookType, function callback[, table allowedNames ] ) diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.h b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.h index a6592f9df04..364ab06e335 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.h +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.h @@ -43,6 +43,7 @@ class CLuaFunctionDefs // Misc functions LUA_DECLARE(DownloadFile); + LUA_DECLARE(AbortDownload); // Output functions LUA_DECLARE(OutputConsole); diff --git a/Client/mods/deathmatch/logic/lua/CLuaManager.cpp b/Client/mods/deathmatch/logic/lua/CLuaManager.cpp index 89dadab3325..38adfc5a2b9 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaManager.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaManager.cpp @@ -199,6 +199,7 @@ void CLuaManager::LoadCFunctions() // Util functions {"getValidPedModels", CLuaFunctionDefs::GetValidPedModels}, {"downloadFile", CLuaFunctionDefs::DownloadFile}, + {"abortDownload", CLuaFunctionDefs::AbortDownload}, // Input functions {"bindKey", CLuaFunctionDefs::BindKey}, From c354c09f75cea1f26eaa41a71df27a94d4ec206f Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Tue, 9 Sep 2025 16:02:18 +0300 Subject: [PATCH 2/4] add input validation for DownloadFile and AbortDownload functions --- .../logic/lua/CLuaFunctionDefs.Util.cpp | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Util.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Util.cpp index 843ab2c8bd1..daea5696762 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Util.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Util.cpp @@ -372,6 +372,14 @@ int CLuaFunctionDefs::DownloadFile(lua_State* luaVM) if (!argStream.HasErrors()) { + // Validate that the file input is not empty + if (strFileInput.empty()) + { + m_pScriptDebugging->LogCustom(luaVM, "Expected non-empty string, got empty string"); + lua_pushboolean(luaVM, false); + return 1; + } + // Grab our VM CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); if (pLuaMain) @@ -416,10 +424,27 @@ int CLuaFunctionDefs::AbortDownload(lua_State* luaVM) // bool abortDownload(number handlerId) std::uint32_t handlerId = 0; CScriptArgReader argStream(luaVM); + + // Check if argument is a number first + if (!argStream.NextIsNumber()) + { + m_pScriptDebugging->LogCustom(luaVM, SString("Expected number, got %s", lua_typename(luaVM, lua_type(luaVM, 1)))); + lua_pushboolean(luaVM, false); + return 1; + } + argStream.ReadNumber(handlerId); if (!argStream.HasErrors()) { + // Validate that handlerId is positive + if (handlerId <= 0) + { + m_pScriptDebugging->LogCustom(luaVM, SString("Expected positive value, got %d", handlerId)); + lua_pushboolean(luaVM, false); + return 1; + } + if (g_pClientGame->GetSingularFileDownloadManager()) { const bool success = g_pClientGame->GetSingularFileDownloadManager()->AbortDownload(handlerId); From c5aa55b6e6a10e3a2feba6e9d691170938587c41 Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Tue, 9 Sep 2025 16:18:20 +0300 Subject: [PATCH 3/4] Refactor --- .../logic/CSingularFileDownload.cpp | 46 +++++++++---------- .../deathmatch/logic/CSingularFileDownload.h | 26 +++++------ .../logic/CSingularFileDownloadManager.cpp | 6 +-- 3 files changed, 38 insertions(+), 40 deletions(-) diff --git a/Client/mods/deathmatch/logic/CSingularFileDownload.cpp b/Client/mods/deathmatch/logic/CSingularFileDownload.cpp index b4857e6c94c..30aaaa66745 100644 --- a/Client/mods/deathmatch/logic/CSingularFileDownload.cpp +++ b/Client/mods/deathmatch/logic/CSingularFileDownload.cpp @@ -21,17 +21,17 @@ CSingularFileDownload::CSingularFileDownload(CResource* pResource, const char* s m_strNameShort = szNameShort; // store resources - m_pResource = pResource; - m_pRequestResource = pRequestResource; + resource = pResource; + requestResource = pRequestResource; // Store the server checksum m_ServerChecksum = serverChecksum; - m_bBeingDeleted = false; - m_bCancelled = false; - m_handlerId = handlerId; - m_pHTTPManager = nullptr; - m_downloadMode = EDownloadModeType::NONE; + beingDeleted = false; + cancelled = false; + handlerId = handlerId; + httpManager = nullptr; + downloadMode = EDownloadMode::NONE; GenerateClientChecksum(); @@ -39,10 +39,10 @@ CSingularFileDownload::CSingularFileDownload(CResource* pResource, const char* s { SHttpRequestOptions options; options.bCheckContents = true; - m_pHTTPManager = g_pCore->GetNetwork()->GetHTTPDownloadManager(EDownloadMode::RESOURCE_SINGULAR_FILES); - m_downloadMode = EDownloadMode::RESOURCE_SINGULAR_FILES; - m_pHTTPManager->QueueFile(strHTTPURL.c_str(), szName, this, DownloadFinishedCallBack, options); - m_bComplete = false; + httpManager = g_pCore->GetNetwork()->GetHTTPDownloadManager(EDownloadMode::RESOURCE_SINGULAR_FILES); + downloadMode = EDownloadMode::RESOURCE_SINGULAR_FILES; + httpManager->QueueFile(strHTTPURL.c_str(), szName, this, DownloadFinishedCallBack, options); + complete = false; g_pClientGame->SetTransferringSingularFiles(true); } else @@ -66,41 +66,41 @@ void CSingularFileDownload::CallFinished(bool bSuccess) // Flag file as loadable g_pClientGame->GetResourceManager()->OnDownloadedResourceFile(GetName()); - if (!m_bBeingDeleted && m_pResource) + if (!beingDeleted && resource) { // Call the onClientFileDownloadComplete event CLuaArguments Arguments; Arguments.PushString(GetShortName()); // file name Arguments.PushBoolean(bSuccess); // Completed successfully? - if (m_pRequestResource) + if (requestResource) { - Arguments.PushResource(m_pRequestResource); // Resource that called downloadFile + Arguments.PushResource(requestResource); // Resource that called downloadFile } else { Arguments.PushBoolean(false); // or false } - m_pResource->GetResourceEntity()->CallEvent("onClientFileDownloadComplete", Arguments, false); + resource->GetResourceEntity()->CallEvent("onClientFileDownloadComplete", Arguments, false); } SetComplete(); } bool CSingularFileDownload::Cancel() { - if (m_bCancelled || m_bComplete) + if (cancelled || complete) return false; - m_bCancelled = true; - m_bBeingDeleted = true; - m_pResource = nullptr; - m_pRequestResource = nullptr; + cancelled = true; + beingDeleted = true; + resource = nullptr; + requestResource = nullptr; // Cancel the actual HTTP download - if (!m_pHTTPManager || m_downloadMode == EDownloadModeType::NONE) - return true; + if (!httpManager || downloadMode == EDownloadMode::NONE) + return false; - return m_pHTTPManager->CancelDownload(this, DownloadFinishedCallBack); + return httpManager->CancelDownload(this, DownloadFinishedCallBack); } bool CSingularFileDownload::DoesClientAndServerChecksumMatch() diff --git a/Client/mods/deathmatch/logic/CSingularFileDownload.h b/Client/mods/deathmatch/logic/CSingularFileDownload.h index 0ba32909b8b..62f7169cfbc 100644 --- a/Client/mods/deathmatch/logic/CSingularFileDownload.h +++ b/Client/mods/deathmatch/logic/CSingularFileDownload.h @@ -37,12 +37,12 @@ class CSingularFileDownload const char* GetName() const noexcept { return m_strName; } const char* GetShortName() const noexcept { return m_strNameShort; } - CResource* GetResource() const noexcept { return m_pResource; } - std::uint32_t GetHandlerId() const noexcept { return m_handlerId; } + CResource* GetResource() const noexcept { return resource; } + std::uint32_t GetHandlerId() const noexcept { return handlerId; } - void SetComplete() noexcept { m_bComplete = true; } - bool GetComplete() const noexcept { return m_bComplete; } - bool IsCancelled() const noexcept { return m_bCancelled; } + void SetComplete() noexcept { complete = true; } + bool GetComplete() const noexcept { return complete; } + bool IsCancelled() const noexcept { return cancelled; } void CallFinished(bool bSuccess); bool Cancel(); @@ -53,16 +53,16 @@ class CSingularFileDownload SString m_strName; SString m_strNameShort; - CResource* m_pResource; - CResource* m_pRequestResource; + CResource* resource; + CResource* requestResource; - bool m_bComplete; - bool m_bBeingDeleted; - bool m_bCancelled; + bool complete; + bool beingDeleted; + bool cancelled; - std::uint32_t m_handlerId; - CNetHTTPDownloadManagerInterface* m_pHTTPManager; - EDownloadModeType m_downloadMode; + std::uint32_t handlerId; + CNetHTTPDownloadManagerInterface* httpManager; + EDownloadMode::EDownloadModeType downloadMode; CChecksum m_LastClientChecksum; CChecksum m_ServerChecksum; diff --git a/Client/mods/deathmatch/logic/CSingularFileDownloadManager.cpp b/Client/mods/deathmatch/logic/CSingularFileDownloadManager.cpp index 738d4a38c9b..eebfd4cc1b0 100644 --- a/Client/mods/deathmatch/logic/CSingularFileDownloadManager.cpp +++ b/Client/mods/deathmatch/logic/CSingularFileDownloadManager.cpp @@ -74,10 +74,8 @@ bool CSingularFileDownloadManager::AbortDownload(std::uint32_t handlerId) return false; const bool success = pDownload->Cancel(); - if (success) - { - RemoveDownload(pDownload); - } + // Always remove from tracking, regardless of cancel success + RemoveDownload(pDownload); return success; } From e4ad22a9e3b95bfbe40a19fa6046756485b1a29a Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Tue, 9 Sep 2025 16:21:56 +0300 Subject: [PATCH 4/4] Refactor CSingularFileDownload and add MarkForDeletion method for better resource management --- .../mods/deathmatch/logic/CSingularFileDownload.cpp | 11 ++++++++--- Client/mods/deathmatch/logic/CSingularFileDownload.h | 1 + .../deathmatch/logic/CSingularFileDownloadManager.cpp | 11 ++++------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Client/mods/deathmatch/logic/CSingularFileDownload.cpp b/Client/mods/deathmatch/logic/CSingularFileDownload.cpp index 30aaaa66745..927de266aba 100644 --- a/Client/mods/deathmatch/logic/CSingularFileDownload.cpp +++ b/Client/mods/deathmatch/logic/CSingularFileDownload.cpp @@ -96,11 +96,16 @@ bool CSingularFileDownload::Cancel() resource = nullptr; requestResource = nullptr; - // Cancel the actual HTTP download if (!httpManager || downloadMode == EDownloadMode::NONE) - return false; + return true; + + const bool httpCancelSuccess = httpManager->CancelDownload(this, DownloadFinishedCallBack); + return httpCancelSuccess; +} - return httpManager->CancelDownload(this, DownloadFinishedCallBack); +void CSingularFileDownload::MarkForDeletion() +{ + beingDeleted = true; } bool CSingularFileDownload::DoesClientAndServerChecksumMatch() diff --git a/Client/mods/deathmatch/logic/CSingularFileDownload.h b/Client/mods/deathmatch/logic/CSingularFileDownload.h index 62f7169cfbc..0bb8b0dce93 100644 --- a/Client/mods/deathmatch/logic/CSingularFileDownload.h +++ b/Client/mods/deathmatch/logic/CSingularFileDownload.h @@ -46,6 +46,7 @@ class CSingularFileDownload void CallFinished(bool bSuccess); bool Cancel(); + void MarkForDeletion(); CChecksum GenerateClientChecksum(); diff --git a/Client/mods/deathmatch/logic/CSingularFileDownloadManager.cpp b/Client/mods/deathmatch/logic/CSingularFileDownloadManager.cpp index eebfd4cc1b0..7cbfbdfa96b 100644 --- a/Client/mods/deathmatch/logic/CSingularFileDownloadManager.cpp +++ b/Client/mods/deathmatch/logic/CSingularFileDownloadManager.cpp @@ -73,8 +73,10 @@ bool CSingularFileDownloadManager::AbortDownload(std::uint32_t handlerId) if (!pDownload) return false; + if (pDownload->GetComplete() || pDownload->IsCancelled()) + return false; + const bool success = pDownload->Cancel(); - // Always remove from tracking, regardless of cancel success RemoveDownload(pDownload); return success; } @@ -84,12 +86,7 @@ void CSingularFileDownloadManager::RemoveDownload(CSingularFileDownload* pDownlo if (!pDownload) return; - // Remove from handler map m_HandlerMap.erase(pDownload->GetHandlerId()); - - // Remove from downloads list m_Downloads.remove(pDownload); - - // Delete the download object - delete pDownload; + pDownload->MarkForDeletion(); } \ No newline at end of file