From d78756363915ab8360ccc19e94d9c04be126401b Mon Sep 17 00:00:00 2001 From: lblach Date: Fri, 22 Jan 2021 10:52:48 +0100 Subject: [PATCH] [EGD-5309] Add a new message Abort in Update endpoint API In order to be able to interrupt the OS update after its launch in the phone, it was necessary to implement the new "Abort" message for the Update Endpoint API. --- .../endpoints/update/UpdateEndpoint.cpp | 19 +++++++++ .../endpoints/update/UpdateMuditaOS.cpp | 40 +++++++++++++++++-- .../endpoints/update/UpdateMuditaOS.hpp | 12 +++++- .../service-desktop/parser/ParserUtils.hpp | 11 +++++ 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/module-services/service-desktop/endpoints/update/UpdateEndpoint.cpp b/module-services/service-desktop/endpoints/update/UpdateEndpoint.cpp index 0b5ba5f396e142df89143579bc1456b7e5815b67..f66e64f662d9ee4ab54befe8c074e4e92e2dd8c9 100644 --- a/module-services/service-desktop/endpoints/update/UpdateEndpoint.cpp +++ b/module-services/service-desktop/endpoints/update/UpdateEndpoint.cpp @@ -35,6 +35,25 @@ auto UpdateEndpoint::handle(Context &context) -> void auto UpdateEndpoint::run(Context &context) -> sys::ReturnCodes { + std::string cmd = context.getBody()[parserFSM::json::updateprocess::command].string_value(); + if (cmd == parserFSM::json::updateprocess::commands::abort) { + auto owner = static_cast(ownerServicePtr); + auto currentState = owner->updateOS->status; + if (currentState <= updateos::UpdateState::ExtractingFiles) { + owner->updateOS->setUpdateAbortFlag(true); + context.setResponseBody(json11::Json::object({{parserFSM::json::updateprocess::updateAborted, true}})); + context.setResponseStatus(http::Code::OK); + MessageHandler::putToSendQueue(context.createSimpleResponse()); + return sys::ReturnCodes::Success; + } + else { + context.setResponseBody(json11::Json::object({{parserFSM::json::updateprocess::updateAborted, false}})); + context.setResponseStatus(http::Code::NotAcceptable); + MessageHandler::putToSendQueue(context.createSimpleResponse()); + return sys::ReturnCodes::Failure; + } + } + std::string fileName = context.getBody()["fileName"].string_value(); auto path = purefs::dir::getUpdatesOSPath() / fileName; auto fileExists = std::filesystem::exists(path.c_str()); diff --git a/module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp b/module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp index ca618f135aabb78bd97f98b70862cf960d4c5088..8f1f8bc33217439a1c79d0139b54d9fa72a3d72f 100644 --- a/module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp +++ b/module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp @@ -54,6 +54,11 @@ UpdateMuditaOS::UpdateMuditaOS(ServiceDesktop *ownerService) : owner(ownerServic updateos::UpdateError UpdateMuditaOS::setUpdateFile(fs::path updateFileToUse) { + if (isUpdateToBeAborted()) { + setUpdateAbortFlag(false); + return informError(updateos::UpdateError::UpdateAborted, "update aborted"); + } + updateFile = purefs::dir::getUpdatesOSPath() / updateFileToUse; if (std::filesystem::exists(updateFile.c_str())) { versionInformation = UpdateMuditaOS::getVersionInfoFromFile(updateFile); @@ -78,7 +83,7 @@ updateos::UpdateError UpdateMuditaOS::setUpdateFile(fs::path updateFileToUse) updateos::UpdateError UpdateMuditaOS::runUpdate() { - informDebug("Prepraring temp dir"); + informDebug("Preparing temp dir"); updateRunStatus.startTime = utils::time::getCurrentTimestamp().getTime(); updateRunStatus.fromVersion = bootConfig.to_json(); @@ -86,20 +91,33 @@ updateos::UpdateError UpdateMuditaOS::runUpdate() updateos::UpdateError err = prepareTempDirForUpdate(); if (err != updateos::UpdateError::NoError) { - return informError(err, "runUpdate can't prepare temp directory for update"); + if (err == updateos::UpdateError::UpdateAborted) { + return informError(updateos::UpdateError::UpdateAborted, "update aborted"); + } + else { + return informError(err, "runUpdate can't prepare temp directory for update"); + } } informDebug("Unpacking update"); - if ((err = unpackUpdate()) == updateos::UpdateError::NoError) { + err = unpackUpdate(); + if (err == updateos::UpdateError::NoError) { informUpdate(status, "Unpacked"); } + else if (err == updateos::UpdateError::UpdateAborted) { + return informError(updateos::UpdateError::UpdateAborted, "update aborted"); + } else { return informError(err, "%s can't be unpacked", updateFile.c_str()); } - if ((err = verifyChecksums()) == updateos::UpdateError::NoError) { + err = verifyChecksums(); + if (err == updateos::UpdateError::NoError) { informUpdate(status, "Verify checksums"); } + else if (err == updateos::UpdateError::UpdateAborted) { + return informError(updateos::UpdateError::UpdateAborted, "update aborted"); + } else { return informError(err, "Checksum verification failed"); } @@ -149,6 +167,10 @@ updateos::UpdateError UpdateMuditaOS::unpackUpdate() status = updateos::UpdateState::ExtractingFiles; std::rewind(updateTar.stream); while ((mtar_read_header(&updateTar, &tarHeader)) != MTAR_ENULLRECORD) { + if (isUpdateToBeAborted()) { + setUpdateAbortFlag(false); + return updateos::UpdateError::UpdateAborted; + } if (std::string(tarHeader.name) == "./") { mtar_next(&updateTar); continue; @@ -200,6 +222,11 @@ std::string UpdateMuditaOS::readContent(const char *filename) noexcept updateos::UpdateError UpdateMuditaOS::verifyChecksums() { + if (isUpdateToBeAborted()) { + setUpdateAbortFlag(false); + return informError(updateos::UpdateError::UpdateAborted, "update aborted"); + } + status = updateos::UpdateState::ChecksumVerification; auto lineBuff = std::make_unique( @@ -491,6 +518,11 @@ const fs::path UpdateMuditaOS::getUpdateTmpChild(const fs::path &childPath) updateos::UpdateError UpdateMuditaOS::prepareTempDirForUpdate() { + if (isUpdateToBeAborted()) { + setUpdateAbortFlag(false); + return updateos::UpdateError::UpdateAborted; + } + status = updateos::UpdateState::CreatingDirectories; updateTempDirectory = purefs::dir::getTemporaryPath() / utils::filesystem::generateRandomId(updateos::prefix_len); diff --git a/module-services/service-desktop/endpoints/update/UpdateMuditaOS.hpp b/module-services/service-desktop/endpoints/update/UpdateMuditaOS.hpp index 77b00b845162a142a6b47c28ba626be6fab4d6a5..2193794441e3a0063b855fa458e005a9ddded4b1 100644 --- a/module-services/service-desktop/endpoints/update/UpdateMuditaOS.hpp +++ b/module-services/service-desktop/endpoints/update/UpdateMuditaOS.hpp @@ -66,7 +66,8 @@ namespace updateos NoBootloaderFile, CantOpenBootloaderFile, CantAllocateBuffer, - CantLoadBootloaderFile + CantLoadBootloaderFile, + UpdateAborted }; enum class UpdateState @@ -171,10 +172,19 @@ class UpdateMuditaOS : public updateos::UpdateStats { return updateHistory; } + void setUpdateAbortFlag(bool flag) + { + updateAbort = flag; + } + bool isUpdateToBeAborted() const noexcept + { + return updateAbort; + } private: std::vector filesInUpdatePackage; mtar_t updateTar = {}; + std::atomic_bool updateAbort = false; ServiceDesktop *owner = nullptr; void storeRunStatusInDB(); diff --git a/module-services/service-desktop/parser/ParserUtils.hpp b/module-services/service-desktop/parser/ParserUtils.hpp index a7e027b5ef0809c72caf50c5aa27aa1301692d12..bb12a589c1f942fb9f723ff58f136412cf6327e6 100644 --- a/module-services/service-desktop/parser/ParserUtils.hpp +++ b/module-services/service-desktop/parser/ParserUtils.hpp @@ -130,6 +130,7 @@ namespace parserFSM inline constexpr auto errorCode = "errorCode"; inline constexpr auto statusCode = "statusCode"; inline constexpr auto updateHistory = "updateHistory"; + namespace filesystem { inline constexpr auto command = "command"; @@ -141,6 +142,16 @@ namespace parserFSM } // namespace commands } // namespace filesystem + namespace updateprocess + { + inline constexpr auto command = "command"; + inline constexpr auto updateAborted = "updateAborted"; + namespace commands + { + inline constexpr auto abort = "abort"; + } // namespace commands + } // namespace updateprocess + namespace messages { inline constexpr auto id = "id";