From 356b981d8622eb4ec10f2729baef84af530df35e Mon Sep 17 00:00:00 2001 From: Li Jin Date: Thu, 1 Feb 2024 10:56:40 +0800 Subject: [PATCH] fix unzip issue, forcing HttpServer to stop before closing. --- Source/Basic/Content.cpp | 5 ++ Source/Basic/Director.cpp | 7 +++ Source/Http/HttpServer.cpp | 69 +++++++++++++++++++-------- Source/Http/HttpServer.h | 16 ++++++- Source/Lua/Builtin/Initialization.lua | 1 + Source/Lua/LuaManual.h | 3 ++ Tools/dora-dora/src/LogView.tsx | 6 ++- Tools/dora-dora/src/i18n.ts | 4 +- Tools/tolua++/Dora.h | 3 +- 9 files changed, 89 insertions(+), 25 deletions(-) diff --git a/Source/Basic/Content.cpp b/Source/Basic/Content.cpp index d482a9f6e..8a5ab538d 100644 --- a/Source/Basic/Content.cpp +++ b/Source/Basic/Content.cpp @@ -588,6 +588,11 @@ void Content::unzipAsync(String zipFile, String folderPath, const std::function< return; } auto zip = std::make_shared(fullZipPath); + if (!zip->isOK()) { + Error("failed to unzip file \"{}\"", zipFile.toString()); + callback(false); + return; + } std::string rootDir; BLOCK_START auto entries = zip->getDirEntries(""s, false); diff --git a/Source/Basic/Director.cpp b/Source/Basic/Director.cpp index d53be7c12..2575c17dc 100644 --- a/Source/Basic/Director.cpp +++ b/Source/Basic/Director.cpp @@ -22,6 +22,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include "Effect/Effect.h" #include "Entity/Entity.h" #include "GUI/ImGuiDora.h" +#include "Http/HttpServer.h" #include "Input/Controller.h" #include "Input/Keyboard.h" #include "Input/TouchDispather.h" @@ -520,6 +521,12 @@ void Director::handleSDLEvent(const SDL_Event& event) { _stoped = true; Event::send("AppQuit"_slice); cleanup(); + if (Singleton::isInitialized()) { + SharedHttpServer.stop(); + } + if (Singleton::isInitialized()) { + SharedHttpClient.stop(); + } break; // The application is being terminated by the OS. case SDL_APP_TERMINATING: diff --git a/Source/Http/HttpServer.cpp b/Source/Http/HttpServer.cpp index 75fa57e3b..bd514dfb3 100644 --- a/Source/Http/HttpServer.cpp +++ b/Source/Http/HttpServer.cpp @@ -506,11 +506,32 @@ const char* HttpServer::getVersion() { return CPPHTTPLIB_VERSION; } -void HttpClient::downloadAsync(String url, String filePath, const std::function& progress) { +/* HttpClient */ + +HttpClient::HttpClient() + : _thread(nullptr), + _stopped(false) { +} + +HttpClient::~HttpClient() { + stop(); +} + +bool HttpClient::isStopped() const { + return _stopped; +} + +void HttpClient::downloadAsync(String url, String filePath, const std::function& progress) { + if (_stopped) { + progress(true, 0, 0); + return; + } + if (!_thread) { + _thread = SharedAsyncThread.newThread(); + } static std::regex urlRegex( R"(^(([^:\/?#]+):)?(//([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)", - std::regex::extended - ); + std::regex::extended); std::smatch matchResult; auto urlStr = url.toString(); std::string schemeHostPort, pathToGet; @@ -543,7 +564,7 @@ void HttpClient::downloadAsync(String url, String filePath, const std::function< progress(true, 0, 0); return; } - SharedAsyncThread.run([schemeHostPort, fileStr = filePath.toString(), urlStr, progress, pathToGet]() { + _thread->run([schemeHostPort, fileStr = filePath.toString(), urlStr, progress, pathToGet]() { try { httplib::Client client(schemeHostPort); client.enable_server_certificate_verification(false); @@ -553,24 +574,28 @@ void HttpClient::downloadAsync(String url, String filePath, const std::function< Error("invalid local file path \"{}\" to download to", fileStr); return; } - auto result = client.Get(pathToGet, [&](const char* data, size_t data_length) -> bool { - if (!out.write(data, data_length)) { - Error("failed to write downloaded file for \"{}\"", urlStr); - SharedApplication.invokeInLogic([progress]() { - progress(true, 0, 0); + auto result = client.Get( + pathToGet, [&](const char* data, size_t data_length) -> bool { + if (SharedHttpClient.isStopped()) { + return false; + } else if (!out.write(data, data_length)) { + Error("failed to write downloaded file for \"{}\"", urlStr); + SharedApplication.invokeInLogic([progress]() { + progress(true, 0, 0); + }); + std::error_code err; + fs::remove_all(fileStr, err); + WarnIf(err, "failed to remove download file \"{}\" due to \"{}\".", fileStr, err.message()); + return false; + } + return true; + }, + [&](uint64_t current, uint64_t total) -> bool { + SharedApplication.invokeInLogic([progress, current, total]() { + progress(false, current, total); }); - std::error_code err; - fs::remove_all(fileStr, err); - WarnIf(err, "failed to remove download file \"{}\" due to \"{}\".", fileStr, err.message()); - return false; - } - return true; - }, [&](uint64_t current, uint64_t total) -> bool { - SharedApplication.invokeInLogic([progress, current, total]() { - progress(false, current, total); + return true; }); - return true; - }); if (!result || result.error() != httplib::Error::Success) { Error("failed to download \"{}\" due to {}", urlStr, httplib::to_string(result.error())); SharedApplication.invokeInLogic([progress]() { @@ -591,4 +616,8 @@ void HttpClient::downloadAsync(String url, String filePath, const std::function< }); } +void HttpClient::stop() { + _stopped = true; +} + NS_DORA_END diff --git a/Source/Http/HttpServer.h b/Source/Http/HttpServer.h index 906e8be9d..30e663a7d 100644 --- a/Source/Http/HttpServer.h +++ b/Source/Http/HttpServer.h @@ -84,7 +84,21 @@ class HttpServer { class HttpClient { public: - static void downloadAsync(String url, String filePath, const std::function& progress); + PROPERTY_BOOL(Stopped); + virtual ~HttpClient(); + void stop(); + void downloadAsync(String url, String filePath, const std::function& progress); + +protected: + HttpClient(); + +private: + Async* _thread; + bool _stopped; + SINGLETON_REF(HttpClient, AsyncThread, Director); }; +#define SharedHttpClient \ + Dora::Singleton::shared() + NS_DORA_END diff --git a/Source/Lua/Builtin/Initialization.lua b/Source/Lua/Builtin/Initialization.lua index 345ae1fe7..4dfa28c86 100644 --- a/Source/Lua/Builtin/Initialization.lua +++ b/Source/Lua/Builtin/Initialization.lua @@ -51,6 +51,7 @@ do dora.Keyboard = dora.Keyboard() dora.DB = dora.DB() dora.HttpServer = dora.HttpServer() + dora.HttpClient = dora.HttpClient() dora.Platformer.Decision.AI = dora.Platformer.Decision.AI() dora.Platformer.Data = dora.Platformer.Data() end diff --git a/Source/Lua/LuaManual.h b/Source/Lua/LuaManual.h index 01b24de1b..4db50d6d6 100644 --- a/Source/Lua/LuaManual.h +++ b/Source/Lua/LuaManual.h @@ -245,6 +245,9 @@ int HttpServer_postSchedule(lua_State* L); int HttpServer_upload(lua_State* L); inline HttpServer* HttpServer_shared() { return &SharedHttpServer; } +/* HttpClient */ +inline HttpClient* HttpClient_shared() { return &SharedHttpClient; } + /* Effect */ inline Pass* Effect_get(Effect* self, size_t index) { return self->get(index - 1); } diff --git a/Tools/dora-dora/src/LogView.tsx b/Tools/dora-dora/src/LogView.tsx index c3f43d888..bc9bf65e2 100644 --- a/Tools/dora-dora/src/LogView.tsx +++ b/Tools/dora-dora/src/LogView.tsx @@ -100,7 +100,11 @@ const LogView = memo((props: LogViewProps) => { color: Color.TextSecondary }} rowHeight={22} - enableSearch stream follow/> + selectableLines + enableSearch + stream + follow + />
diff --git a/Tools/dora-dora/src/i18n.ts b/Tools/dora-dora/src/i18n.ts index 720ca0b4d..486895334 100644 --- a/Tools/dora-dora/src/i18n.ts +++ b/Tools/dora-dora/src/i18n.ts @@ -55,7 +55,7 @@ i18n runFailed: "failed to run {{title}}", startUnzip: "start to unzip file {{title}}", doneUnzip: "finished unziping file {{title}}", - failedUnzip: "failed to unzip file {{title}}, make sure no same named folder exist", + failedUnzip: "failed to unzip file {{title}}, make sure it's a ZIP and no same named folder exist", failedTS: "TypeScript compile error, check log for details", }, popup: { @@ -172,7 +172,7 @@ i18n runFailed: "运行 {{title}} 失败", startUnzip: "开始解压缩 {{title}}", doneUnzip: "完成解压缩 {{title}}", - failedUnzip: "解压缩 {{title}} 未成功,请确保目录下无同名文件夹", + failedUnzip: "解压缩 {{title}} 失败,请确认为 ZIP 文件且目录下无同名文件夹", failedTS: "TypeScript 编译报错,请查看日志", }, popup: { diff --git a/Tools/tolua++/Dora.h b/Tools/tolua++/Dora.h index 160313ad9..528eec115 100644 --- a/Tools/tolua++/Dora.h +++ b/Tools/tolua++/Dora.h @@ -1112,7 +1112,8 @@ class HttpServer class HttpClient { - static void downloadAsync(String url, String filePath, tolua_function_void progress); + void downloadAsync(String url, String filePath, tolua_function_void progress); + static tolua_outside HttpClient* HttpClient_shared @ create(); }; namespace ML {