From 92ec86e818035897b0be322ff77547161af72178 Mon Sep 17 00:00:00 2001 From: Marek Niepieklo Date: Tue, 12 Oct 2021 10:39:20 +0200 Subject: [PATCH] [CP-610] Add removeFile operation to Filesystem EP Moved Rename/Remove/ListDir from DeveloperMode to Filesystem EP API --- .../service-desktop/endpoints/CMakeLists.txt | 4 +- .../developerMode/DeveloperModeEndpoint.cpp | 3 - .../endpoints/developerMode/fs/FS_Helper.cpp | 95 ----- .../endpoints/filesystem/FS_Helper.cpp | 333 ++++++++++++++++++ .../filesystem/FilesystemEndpoint.cpp | 314 +---------------- .../include/endpoints/JsonKeyNames.hpp | 27 +- .../developerMode/DeveloperModeEndpoint.hpp | 5 +- .../endpoints/developerMode/fs/FS_Helper.hpp | 36 -- .../endpoints/filesystem/FS_Helper.hpp | 55 +++ .../filesystem/FilesystemEndpoint.hpp | 21 +- test/harness | 2 +- 11 files changed, 412 insertions(+), 483 deletions(-) delete mode 100644 module-services/service-desktop/endpoints/developerMode/fs/FS_Helper.cpp create mode 100644 module-services/service-desktop/endpoints/filesystem/FS_Helper.cpp delete mode 100644 module-services/service-desktop/endpoints/include/endpoints/developerMode/fs/FS_Helper.hpp create mode 100644 module-services/service-desktop/endpoints/include/endpoints/filesystem/FS_Helper.hpp diff --git a/module-services/service-desktop/endpoints/CMakeLists.txt b/module-services/service-desktop/endpoints/CMakeLists.txt index 0137a68154a30ceafd1bae8e0b26aed1d4cd2393..18283fb06481b7b6f70dcfb0bfe32ca554277739 100644 --- a/module-services/service-desktop/endpoints/CMakeLists.txt +++ b/module-services/service-desktop/endpoints/CMakeLists.txt @@ -50,11 +50,11 @@ target_sources( developerMode/Mode/UI_Helper.cpp developerMode/event/ATRequest.cpp developerMode/event/DomRequest.cpp - developerMode/fs/FS_Helper.cpp factoryReset/FactoryResetEndpoint.cpp filesystem/FileContext.cpp filesystem/FileOperations.cpp filesystem/FilesystemEndpoint.cpp + filesystem/FS_Helper.cpp nullEndpoint/NullEndpoint.cpp restore/RestoreEndpoint.cpp restore/RestoreHelper.cpp @@ -74,11 +74,11 @@ target_sources( include/endpoints/developerMode/Mode/UI_Helper.hpp include/endpoints/developerMode/event/ATRequest.hpp include/endpoints/developerMode/event/DomRequest.hpp - include/endpoints/developerMode/fs/FS_Helper.hpp include/endpoints/factoryReset/FactoryResetEndpoint.hpp include/endpoints/filesystem/FileContext.hpp include/endpoints/filesystem/FileOperations.hpp include/endpoints/filesystem/FilesystemEndpoint.hpp + include/endpoints/filesystem/FS_Helper.hpp include/endpoints/nullEndpoint/NullEndpoint.hpp include/endpoints/restore/RestoreEndpoint.hpp include/endpoints/restore/RestoreHelper.hpp diff --git a/module-services/service-desktop/endpoints/developerMode/DeveloperModeEndpoint.cpp b/module-services/service-desktop/endpoints/developerMode/DeveloperModeEndpoint.cpp index 95e12525295dbc367098ecb858e6bc8e643b17ef..a049dad141c793cb405798fbb833d4b267d4f161 100644 --- a/module-services/service-desktop/endpoints/developerMode/DeveloperModeEndpoint.cpp +++ b/module-services/service-desktop/endpoints/developerMode/DeveloperModeEndpoint.cpp @@ -37,9 +37,6 @@ namespace sdesktop::endpoints if (ctx.getBody()["ui"] == true) { return *uiHelper; } - if (ctx.getBody()["fs"] == true) { - return *fsHelper; - } return *helper; } diff --git a/module-services/service-desktop/endpoints/developerMode/fs/FS_Helper.cpp b/module-services/service-desktop/endpoints/developerMode/fs/FS_Helper.cpp deleted file mode 100644 index 7e801fa6d4674ac1f62931eb06ea6ee98d6977fb..0000000000000000000000000000000000000000 --- a/module-services/service-desktop/endpoints/developerMode/fs/FS_Helper.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#include - -#include -#include -#include -#include - -#include -#include - -namespace sdesktop::endpoints -{ - using sender::putToSendQueue; - - void FS_Helper::preProcess(http::Method method, Context &context) - { - LOG_INFO("In FS helper - requesting %d", static_cast(method)); - } - - auto FS_Helper::processGet(Context &context) -> ProcessResult - { - const auto &body = context.getBody(); - if (body[json::fs::listDir].is_string()) { - const auto &dir = body[json::fs::listDir].string_value(); - auto response = requestListDir(dir); - return {sent::no, std::move(response)}; - } - else { - return {sent::no, ResponseContext{.status = http::Code::BadRequest}}; - } - } - - auto FS_Helper::processPut(Context &context) -> ProcessResult - { - auto body = context.getBody(); - auto code = http::Code::BadRequest; - if (body[json::fs::removeFile].is_string()) { - const auto &fileName = body[json::fs::removeFile].string_value(); - try { - code = requestFileRemoval(fileName) ? http::Code::NoContent : http::Code::NotFound; - } - catch (const std::filesystem::filesystem_error &) { - LOG_WARN("Can't remove requested file"); - code = http::Code::InternalServerError; - } - } - else if (body[json::fs::renameFile].is_string()) { - const auto &fileName = body[json::fs::renameFile].string_value(); - if (body[json::fs::destFileName].is_string()) { - const auto &destFileName = body[json::fs::destFileName].string_value(); - code = requestFileRename(fileName, destFileName) ? http::Code::NoContent : http::Code::NotFound; - } - else { - code = http::Code::NotFound; - } - } - else { - context.setResponseStatus(http::Code::BadRequest); - putToSendQueue(context.createSimpleResponse()); - } - - return {sent::no, ResponseContext{.status = code}}; - } - - bool FS_Helper::requestFileRemoval(const std::string &fileName) - { - return std::filesystem::remove(fileName); - } - - bool FS_Helper::requestFileRename(const std::string &fileName, const std::string &destFileName) noexcept - { - std::error_code ec; - std::filesystem::rename(fileName, destFileName, ec); - return (!ec) ? true : false; - } - - ResponseContext FS_Helper::requestListDir(const std::string &directory) - { - std::vector filesInDir; - for (const auto &entry : std::filesystem::directory_iterator{directory}) { - filesInDir.push_back(entry.path()); - } - json11::Json::array jsonArr; - jsonArr.reserve(filesInDir.size()); - for (const auto &path : filesInDir) { - jsonArr.push_back(json11::Json::object{{json::fs::path, path}}); - } - json11::Json::object response({{directory, jsonArr}}); - return ResponseContext{.status = http::Code::OK, .body = response}; - } - -} // namespace sdesktop::endpoints diff --git a/module-services/service-desktop/endpoints/filesystem/FS_Helper.cpp b/module-services/service-desktop/endpoints/filesystem/FS_Helper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5eb4b69a54c4c78018d33a2bf1ef5b6727a156dc --- /dev/null +++ b/module-services/service-desktop/endpoints/filesystem/FS_Helper.cpp @@ -0,0 +1,333 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace sdesktop::endpoints +{ + using sender::putToSendQueue; + namespace fs = std::filesystem; + + auto FS_Helper::processGet(Context &context) -> ProcessResult + { + LOG_DEBUG("Handling GET"); + const auto &body = context.getBody(); + ResponseContext response{}; + + if (body[json::fs::fileName].is_string()) { + response = startGetFile(context); + } + else if (body[json::fs::rxID].is_number()) { + response = getFileChunk(context); + } + else if (body[json::fs::listDir].is_string()) { + const auto &dir = body[json::fs::listDir].string_value(); + response = requestListDir(dir); + } + else { + LOG_ERROR("unknown request"); + response = {.status = http::Code::BadRequest}; + } + + return {sent::no, std::move(response)}; + } + + auto FS_Helper::processPut(Context &context) -> ProcessResult + { + LOG_DEBUG("Handling PUT"); + const auto &body = context.getBody(); + auto code = http::Code::BadRequest; + ResponseContext response{}; + + if (body[json::fs::fileName].is_string() && body[json::fs::fileSize].is_number() && + body[json::fs::fileCrc32].is_string()) { + response = startSendFile(context); + } + else if (body[json::fs::txID].is_number() && body[json::fs::chunkNo].is_number() && + body[json::fs::data].is_string()) { + response = sendFileChunk(context); + } + else if (body[json::fs::renameFile].is_string() && body[json::fs::destFilename].is_string()) { + const auto &fileName = body[json::fs::renameFile].string_value(); + const auto &destFilename = body[json::fs::destFilename].string_value(); + code = requestFileRename(fileName, destFilename) ? http::Code::NoContent : http::Code::NotFound; + + response = ResponseContext{.status = code}; + } + else { + LOG_ERROR("Bad request, missing or invalid argument"); + response = ResponseContext{.status = http::Code::BadRequest}; + } + + return {sent::no, std::move(response)}; + } + + auto FS_Helper::processDelete(Context &context) -> ProcessResult + { + LOG_DEBUG("Handling DEL"); + const auto &body = context.getBody(); + auto code = http::Code::BadRequest; + + if (body[json::fs::removeFile].is_string()) { + const auto &fileName = body[json::fs::removeFile].string_value(); + try { + code = requestFileRemoval(fileName) ? http::Code::NoContent : http::Code::NotFound; + } + catch (const std::filesystem::filesystem_error &ex) { + LOG_ERROR("Can't remove requested file, error: %d", ex.code().value()); + code = http::Code::InternalServerError; + } + } + else { + LOG_ERROR("Bad request, missing or invalid argument"); + } + + return {sent::no, ResponseContext{.status = code}}; + } + + auto FS_Helper::requestLogsFlush() const -> void + { + auto ownerService = dynamic_cast(owner); + if (ownerService) { + ownerService->requestLogsFlush(); + } + } + + auto FS_Helper::startGetFile(Context &context) const -> ResponseContext + { + const std::filesystem::path filePath = context.getBody()[json::fs::fileName].string_value(); + + try { + requestLogsFlush(); + } + catch (const std::runtime_error &e) { + LOG_ERROR("Logs flush exception: %s", e.what()); + + json11::Json::object response({{json::reason, e.what()}}); + return ResponseContext{.status = http::Code::InternalServerError, .body = response}; + } + + if (!std::filesystem::exists(filePath)) { + LOG_ERROR("file not found"); + + json11::Json::object response({{json::reason, json::fs::fileDoesNotExist}}); + return ResponseContext{.status = http::Code::NotFound, .body = response}; + } + + json11::Json::object response{}; + auto code = http::Code::BadRequest; + + LOG_DEBUG("Checking file"); + + try { + auto [rxID, fileSize] = fileOps.createReceiveIDForFile(filePath); + + code = http::Code::OK; + response = json11::Json::object({{json::fs::rxID, static_cast(rxID)}, + {json::fs::fileSize, static_cast(fileSize)}, + {json::fs::chunkSize, static_cast(FileOperations::ChunkSize)}}); + } + catch (std::runtime_error &e) { + LOG_ERROR("FileOperations exception: %s", e.what()); + + code = http::Code::InternalServerError; + response = json11::Json::object({{json::reason, std::string(e.what())}}); + } + catch (std::exception &e) { + LOG_ERROR("FileOperations exception: %s", e.what()); + + code = http::Code::BadRequest; + response = json11::Json::object({{json::reason, std::string(e.what())}}); + } + + return ResponseContext{.status = code, .body = response}; + } + + auto FS_Helper::getFileChunk(Context &context) const -> ResponseContext + { + const auto rxID = context.getBody()[json::fs::rxID].int_value(); + const auto chunkNo = context.getBody()[json::fs::chunkNo].int_value(); + FileOperations::DataWithCrc32 dataWithCrc32; + + try { + dataWithCrc32 = fileOps.getDataForReceiveID(rxID, chunkNo); + } + catch (std::exception &e) { + LOG_ERROR("%s", e.what()); + + json11::Json::object response({{json::reason, e.what()}}); + return ResponseContext{.status = http::Code::BadRequest, .body = response}; + } + + json11::Json::object response{}; + auto code = http::Code::BadRequest; + + if (dataWithCrc32.data.length()) { + code = http::Code::OK; + response = json11::Json::object({{json::fs::rxID, static_cast(rxID)}, + {json::fs::chunkNo, static_cast(chunkNo)}, + {json::fs::data, dataWithCrc32.data}}); + + if (dataWithCrc32.crc32.length()) { + response[json::fs::fileCrc32] = dataWithCrc32.crc32; + } + } + else { + std::ostringstream errorReason; + errorReason << "Invalid request rxID: " << std::to_string(rxID) << ", chunkNo: " << std::to_string(chunkNo); + LOG_ERROR("%s", errorReason.str().c_str()); + + code = http::Code::BadRequest; + response = json11::Json::object({{json::reason, errorReason.str()}}); + } + + return ResponseContext{.status = code, .body = response}; + } + + auto FS_Helper::startSendFile(Context &context) const -> ResponseContext + { + const auto &body = context.getBody(); + std::filesystem::path filePath = body[json::fs::fileName].string_value(); + const uint32_t fileSize = body[json::fs::fileSize].int_value(); + const auto fileCrc32 = body[json::fs::fileCrc32].string_value(); + auto code = http::Code::BadRequest; + + LOG_DEBUG("Start sending of file: %s", filePath.c_str()); + + if (fileSize == 0 || fileCrc32.empty()) { + LOG_ERROR("File %s corrupted", filePath.c_str()); + + return ResponseContext{.status = code}; + } + + if (!std::filesystem::exists(filePath)) { + LOG_DEBUG("Creating file %s", filePath.c_str()); + + code = http::Code::Created; + } + else { + LOG_DEBUG("Overwriting file %s", filePath.c_str()); + } + + json11::Json::object response{}; + + try { + auto txID = fileOps.createTransmitIDForFile(filePath, fileSize, fileCrc32); + + code = http::Code::OK; + response = json11::Json::object({{json::fs::txID, static_cast(txID)}, + {json::fs::chunkSize, static_cast(FileOperations::ChunkSize)}}); + } + catch (std::runtime_error &e) { + LOG_ERROR("FileOperations exception: %s", e.what()); + + code = http::Code::InternalServerError; + response = json11::Json::object({{json::reason, std::string(e.what())}}); + } + catch (std::exception &e) { + LOG_ERROR("FileOperations exception: %s", e.what()); + + code = http::Code::BadRequest; + response = json11::Json::object({{json::reason, std::string(e.what())}}); + } + + return ResponseContext{.status = code, .body = response}; + } + + auto FS_Helper::sendFileChunk(Context &context) const -> ResponseContext + { + const auto &body = context.getBody(); + const auto txID = body[json::fs::txID].int_value(); + const auto chunkNo = body[json::fs::chunkNo].int_value(); + const auto data = body[json::fs::data].string_value(); + + if (data.empty()) { + std::ostringstream errorReason; + errorReason << "Invalid request txID: " << std::to_string(txID) << ", chunkNo: " << std::to_string(chunkNo); + LOG_ERROR("%s", errorReason.str().c_str()); + + auto code = http::Code::BadRequest; + auto response = json11::Json::object({{json::reason, errorReason.str()}}); + + return ResponseContext{.status = code, .body = response}; + } + + auto returnCode = sys::ReturnCodes::Success; + + try { + returnCode = fileOps.sendDataForTransmitID(txID, chunkNo, data); + } + catch (std::exception &e) { + LOG_ERROR("%s", e.what()); + + auto code = http::Code::NotAcceptable; + auto response = json11::Json::object({{json::reason, e.what()}}); + + return ResponseContext{.status = code, .body = response}; + } + + json11::Json::object response{}; + auto code = http::Code::OK; + + if (returnCode == sys::ReturnCodes::Success) { + LOG_DEBUG("FileOperations::sendDataForTransmitID success"); + + response = json11::Json::object( + {{json::fs::txID, static_cast(txID)}, {json::fs::chunkNo, static_cast(chunkNo)}}); + } + else { + LOG_ERROR("FileOperations::sendDataForTransmitID failed"); + + code = http::Code::BadRequest; + response = json11::Json::object( + {{json::fs::txID, static_cast(txID)}, {json::fs::chunkNo, static_cast(chunkNo)}}); + } + + return ResponseContext{.status = code, .body = response}; + } + + auto FS_Helper::requestFileRemoval(const std::string &fileName) -> bool + { + return std::filesystem::remove(fileName); + } + + auto FS_Helper::requestFileRename(const std::string &fileName, const std::string &destFilename) noexcept -> bool + { + std::error_code ec; + std::filesystem::rename(fileName, destFilename, ec); + if (!ec) { + LOG_ERROR("Failed to rename %s, error: %d", fileName.c_str(), ec.value()); + } + return !ec; + } + + auto FS_Helper::requestListDir(const std::string &directory) -> ResponseContext + { + if (!std::filesystem::exists(directory)) { + return ResponseContext{.status = http::Code::NotFound}; + } + + std::vector filesInDir; + for (const auto &entry : std::filesystem::directory_iterator{directory}) { + filesInDir.push_back(entry.path()); + } + + json11::Json::array jsonArr; + jsonArr.reserve(filesInDir.size()); + + for (const auto &path : filesInDir) { + jsonArr.push_back(json11::Json::object{{json::fs::path, path}}); + } + + json11::Json::object response({{directory, jsonArr}}); + return ResponseContext{.status = http::Code::OK, .body = response}; + } +} // namespace sdesktop::endpoints diff --git a/module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.cpp b/module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.cpp index f0ae7caeab732e840cefa4175aceff881ab63ba1..0666202dcea4d1faf4a5626dd9b06e088f564696 100644 --- a/module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.cpp +++ b/module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.cpp @@ -2,320 +2,34 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include - -#include -#include -#include +#include #include -#include - -#include namespace sdesktop::endpoints { - - namespace fs = std::filesystem; using sender::putToSendQueue; auto FilesystemEndpoint::handle(Context &context) -> void { - auto returnCode = sys::ReturnCodes::Success; - switch (context.getMethod()) { - case http::Method::get: - returnCode = runGet(context); - break; - case http::Method::post: - returnCode = runPost(context); - break; - case http::Method::put: - returnCode = runPut(context); - break; - default: - LOG_ERROR("Unhandled method request: %u", static_cast(context.getMethod())); - returnCode = sys::ReturnCodes::Failure; - break; - } - LOG_DEBUG("returnCode: %u", static_cast(returnCode)); - } - - auto FilesystemEndpoint::requestLogsFlush() const -> void - { - auto owner = dynamic_cast(ownerServicePtr); - if (owner) { - owner->requestLogsFlush(); - } - } - - auto FilesystemEndpoint::startGetFile(Context &context) const -> sys::ReturnCodes - { - std::filesystem::path filePath = context.getBody()[json::fileName].string_value(); - - try { - requestLogsFlush(); - } - catch (const std::runtime_error &e) { - LOG_ERROR("Logs flush exception: %s", e.what()); + const auto &[sent, response] = helper->process(context.getMethod(), context); - context.setResponseStatus(http::Code::InternalServerError); - context.setResponseBody(json11::Json::object({{json::reason, std::string(e.what())}})); - return sys::ReturnCodes::Failure; + if (sent == sent::delayed) { + LOG_DEBUG("There is no proper delayed serving mechanism - depend on invisible context caching"); } - - if (!std::filesystem::exists(filePath)) { - LOG_ERROR("file not found"); - - context.setResponseStatus(http::Code::NotFound); - context.setResponseBody( - json11::Json::object({{json::reason, json::filesystem::reasons::fileDoesNotExist}})); - return sys::ReturnCodes::Failure; - } - - LOG_DEBUG("Checking file"); - - try { - auto [rxID, fileSize] = fileOps.createReceiveIDForFile(filePath); - - context.setResponseStatus(http::Code::OK); - context.setResponseBody( - json11::Json::object({{json::filesystem::rxID, static_cast(rxID)}, - {json::fileSize, static_cast(fileSize)}, - {json::filesystem::chunkSize, static_cast(FileOperations::ChunkSize)}})); - } - catch (std::runtime_error &e) { - LOG_ERROR("FileOperations exception: %s", e.what()); - - context.setResponseStatus(http::Code::InternalServerError); - context.setResponseBody(json11::Json::object({{json::reason, std::string(e.what())}})); - return sys::ReturnCodes::Failure; - } - catch (std::exception &e) { - LOG_ERROR("FileOperations exception: %s", e.what()); - - context.setResponseStatus(http::Code::BadRequest); - context.setResponseBody(json11::Json::object({{json::reason, std::string(e.what())}})); - return sys::ReturnCodes::Failure; - } - - return sys::ReturnCodes::Success; - } - - auto FilesystemEndpoint::getFileChunk(Context &context) const -> sys::ReturnCodes - { - auto returnCode = sys::ReturnCodes::Failure; - const auto rxID = context.getBody()[json::filesystem::rxID].int_value(); - const auto chunkNo = context.getBody()[json::filesystem::chunkNo].int_value(); - FileOperations::DataWithCrc32 dataWithCrc32; - - try { - dataWithCrc32 = fileOps.getDataForReceiveID(rxID, chunkNo); - } - catch (std::exception &e) { - LOG_ERROR("%s", e.what()); - context.setResponseStatus(http::Code::BadRequest); - context.setResponseBody(json11::Json::object({{json::reason, e.what()}})); - - return sys::ReturnCodes::Failure; - } - - if (dataWithCrc32.data.length()) { - context.setResponseStatus(http::Code::OK); - json11::Json::object contextJsonObject = - json11::Json::object({{json::filesystem::rxID, static_cast(rxID)}, - {json::filesystem::chunkNo, static_cast(chunkNo)}, - {json::filesystem::data, dataWithCrc32.data}}); - - if (dataWithCrc32.crc32.length()) { - contextJsonObject[json::fileCrc32] = dataWithCrc32.crc32; + if (sent == sent::no) { + if (not response) { + LOG_ERROR("Response not sent & response not created : respond with error"); + context.setResponseStatus(http::Code::NotAcceptable); + } + else { + context.setResponse(response.value()); } - context.setResponseBody(contextJsonObject); - - returnCode = sys::ReturnCodes::Success; - } - else { - std::ostringstream errorReason; - errorReason << "Invalid request rxID: " << std::to_string(rxID) << ", chunkNo: " << std::to_string(chunkNo); - LOG_ERROR("%s", errorReason.str().c_str()); - - context.setResponseStatus(http::Code::BadRequest); - context.setResponseBody(json11::Json::object({{json::reason, errorReason.str()}})); - } - - return returnCode; - } - - auto FilesystemEndpoint::runGet(Context &context) -> sys::ReturnCodes - { - LOG_DEBUG("Handling GET"); - auto returnCode = sys::ReturnCodes::Failure; - - if (context.getBody()[json::fileName].is_string()) { - returnCode = startGetFile(context); - } - else if (context.getBody()[json::filesystem::rxID].is_number()) { - returnCode = getFileChunk(context); - } - else { - LOG_ERROR("unknown request"); - context.setResponseStatus(http::Code::BadRequest); - returnCode = sys::ReturnCodes::Failure; - } - - putToSendQueue(context.createSimpleResponse()); - - return returnCode; - } - - auto FilesystemEndpoint::runPost(Context &context) -> sys::ReturnCodes - { - LOG_DEBUG("Handling POST"); - sys::ReturnCodes returnCode = sys::ReturnCodes::Failure; - std::string cmd = context.getBody()[json::filesystem::command].string_value(); - - context.setResponseBody( - json11::Json::object({{json::status, std::to_string(static_cast(sys::ReturnCodes::Failure))}})); - - if (cmd == json::filesystem::commands::checkFile) { - fs::path filePath = context.getBody()[json::fileName].string_value(); - LOG_DEBUG("Checking file"); - - context.setResponseBody(json11::Json::object{{json::fileExists, std::filesystem::exists(filePath)}}); - returnCode = sys::ReturnCodes::Success; - } - else { - LOG_ERROR("unknown command"); - context.setResponseStatus(http::Code::BadRequest); - returnCode = sys::ReturnCodes::Failure; - } - - putToSendQueue(context.createSimpleResponse()); - return returnCode; - } - - auto FilesystemEndpoint::runPut(Context &context) -> sys::ReturnCodes - { - LOG_DEBUG("Handling PUT"); - auto returnCode = sys::ReturnCodes::Failure; - const auto &requestBody = context.getBody(); - - if (requestBody[json::fileName].is_string() && requestBody[json::fileSize].is_number() && - requestBody[json::fileCrc32].is_string()) { - returnCode = startSendFile(context); - } - else if (requestBody[json::filesystem::txID].is_number() && - requestBody[json::filesystem::chunkNo].is_number() && - requestBody[json::filesystem::data].is_string()) { - returnCode = sendFileChunk(context); - } - else { - LOG_ERROR("unknown request"); - context.setResponseStatus(http::Code::BadRequest); - returnCode = sys::ReturnCodes::Failure; - } - - putToSendQueue(context.createSimpleResponse()); - return returnCode; - } - - auto FilesystemEndpoint::startSendFile(Context &context) const -> sys::ReturnCodes - { - auto returnCode = sys::ReturnCodes::Failure; - const auto &requestBody = context.getBody(); - - std::filesystem::path filePath = requestBody[json::fileName].string_value(); - const uint32_t fileSize = requestBody[json::fileSize].int_value(); - const auto fileCrc32 = requestBody[json::fileCrc32].string_value(); - - LOG_DEBUG("Start sending of file: %s", filePath.c_str()); - - if (fileSize == 0 || fileCrc32.empty()) { - LOG_ERROR("File %s corrupted", filePath.c_str()); - - context.setResponseStatus(http::Code::BadRequest); - return returnCode; - } - - if (!std::filesystem::exists(filePath)) { - LOG_DEBUG("Creating file %s", filePath.c_str()); - - context.setResponseStatus(http::Code::Created); - } - else { - LOG_DEBUG("Overwriting file %s", filePath.c_str()); - } - - try { - auto txID = fileOps.createTransmitIDForFile(filePath, fileSize, fileCrc32); - - context.setResponseStatus(http::Code::OK); - context.setResponseBody( - json11::Json::object({{json::filesystem::txID, static_cast(txID)}, - {json::filesystem::chunkSize, static_cast(FileOperations::ChunkSize)}})); - } - catch (std::runtime_error &e) { - LOG_ERROR("FileOperations exception: %s", e.what()); - - context.setResponseStatus(http::Code::InternalServerError); - context.setResponseBody(json11::Json::object({{json::reason, std::string(e.what())}})); - return sys::ReturnCodes::Failure; - } - catch (std::exception &e) { - LOG_ERROR("FileOperations exception: %s", e.what()); - - context.setResponseStatus(http::Code::BadRequest); - context.setResponseBody(json11::Json::object({{json::reason, std::string(e.what())}})); - return sys::ReturnCodes::Failure; - } - - return sys::ReturnCodes::Success; - } - - auto FilesystemEndpoint::sendFileChunk(Context &context) const -> sys::ReturnCodes - { - auto returnCode = sys::ReturnCodes::Failure; - const auto &requestBody = context.getBody(); - const auto txID = requestBody[json::filesystem::txID].int_value(); - const auto chunkNo = requestBody[json::filesystem::chunkNo].int_value(); - const auto data = requestBody[json::filesystem::data].string_value(); - - if (data.empty()) { - std::ostringstream errorReason; - errorReason << "Invalid request txID: " << std::to_string(txID) << ", chunkNo: " << std::to_string(chunkNo); - LOG_ERROR("%s", errorReason.str().c_str()); - - context.setResponseStatus(http::Code::BadRequest); - context.setResponseBody(json11::Json::object({{json::reason, errorReason.str()}})); - return returnCode; - } - - try { - returnCode = fileOps.sendDataForTransmitID(txID, chunkNo, data); - } - catch (std::exception &e) { - LOG_ERROR("%s", e.what()); - context.setResponseStatus(http::Code::NotAcceptable); - context.setResponseBody(json11::Json::object({{json::reason, e.what()}})); - - return sys::ReturnCodes::Failure; - } - if (returnCode == sys::ReturnCodes::Success) { - LOG_DEBUG("FileOperations::sendDataForTransmitID success"); - context.setResponseStatus(http::Code::OK); - context.setResponseBody(json11::Json::object({ - {json::filesystem::txID, static_cast(txID)}, - {json::filesystem::chunkNo, static_cast(chunkNo)}, - })); + sender::putToSendQueue(context.createSimpleResponse()); } - else { - LOG_ERROR("FileOperations::sendDataForTransmitID failed"); - context.setResponseStatus(http::Code::BadRequest); - context.setResponseBody(json11::Json::object({ - {json::filesystem::txID, static_cast(txID)}, - {json::filesystem::chunkNo, static_cast(chunkNo)}, - })); + if (sent == sent::yes and response) { + LOG_ERROR("Response set when we already handled response in handler"); } - - return returnCode; } } // namespace sdesktop::endpoints diff --git a/module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp b/module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp index fa3ebb45be0caf0d80dac7a0aa40b3492d0ca459..3b4f2cc946a67b8094ea93cb65b95b1934334a07 100644 --- a/module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp +++ b/module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp @@ -24,9 +24,7 @@ namespace sdesktop::endpoints::json inline constexpr auto networkStatus = "networkStatus"; inline constexpr auto networkOperatorName = "networkOperatorName"; inline constexpr auto accessTechnology = "accessTechnology"; - inline constexpr auto fileName = "fileName"; - inline constexpr auto fileSize = "fileSize"; - inline constexpr auto fileCrc32 = "fileCrc32"; + inline constexpr auto update = "update"; inline constexpr auto updateInfo = "updateInfo"; inline constexpr auto updateError = "updateError"; @@ -52,29 +50,6 @@ namespace sdesktop::endpoints::json inline constexpr auto files = "files"; inline constexpr auto backupLocation = "backupLocation"; - namespace filesystem - { - inline constexpr auto command = "command"; - inline constexpr auto chunkSize = "chunkSize"; - inline constexpr auto chunkNo = "chunkNo"; - inline constexpr auto data = "data"; - inline constexpr auto rxID = "rxID"; - inline constexpr auto txID = "txID"; - - namespace commands - { - inline constexpr auto upload = "upload"; - inline constexpr auto rm = "rm"; - inline constexpr auto download = "download"; - inline constexpr auto checkFile = "checkFile"; - } // namespace commands - - namespace reasons - { - inline constexpr auto fileDoesNotExist = "file does not exist"; - } - } // namespace filesystem - namespace updateprocess { inline constexpr auto command = "command"; diff --git a/module-services/service-desktop/endpoints/include/endpoints/developerMode/DeveloperModeEndpoint.hpp b/module-services/service-desktop/endpoints/include/endpoints/developerMode/DeveloperModeEndpoint.hpp index 4c26cac9d07b1c805a3045b5e70f2d90328d4abb..ecdbb5259b5bd6d71e4c87d012758d32639fc995 100644 --- a/module-services/service-desktop/endpoints/include/endpoints/developerMode/DeveloperModeEndpoint.hpp +++ b/module-services/service-desktop/endpoints/include/endpoints/developerMode/DeveloperModeEndpoint.hpp @@ -6,7 +6,6 @@ #include #include "DeveloperModeHelper.hpp" #include "Mode/UI_Helper.hpp" -#include "fs/FS_Helper.hpp" #include @@ -18,13 +17,11 @@ namespace sdesktop::endpoints private: const std::unique_ptr helper; const std::unique_ptr uiHelper; - const std::unique_ptr fsHelper; public: explicit DeveloperModeEndpoint(sys::Service *_ownerServicePtr) : Endpoint(_ownerServicePtr), helper(std::make_unique(ownerServicePtr)), - uiHelper(std::make_unique(ownerServicePtr)), - fsHelper(std::make_unique(ownerServicePtr)) + uiHelper(std::make_unique(ownerServicePtr)) { debugName = "DeveloperModeEndpoint"; } diff --git a/module-services/service-desktop/endpoints/include/endpoints/developerMode/fs/FS_Helper.hpp b/module-services/service-desktop/endpoints/include/endpoints/developerMode/fs/FS_Helper.hpp deleted file mode 100644 index 1b38c8787a0afc902259b48c6356d538af7608cd..0000000000000000000000000000000000000000 --- a/module-services/service-desktop/endpoints/include/endpoints/developerMode/fs/FS_Helper.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#pragma once - -#include - -namespace sdesktop::endpoints -{ - - class FS_Helper : public BaseHelper - { - public: - explicit FS_Helper(sys::Service *p) : BaseHelper(p) - {} - - private: - auto processGet(Context &context) -> ProcessResult final; - auto processPut(Context &context) -> ProcessResult final; - void preProcess(http::Method method, Context &context) final; - - bool requestFileRemoval(const std::string &fileName); - bool requestFileRename(const std::string &fileName, const std::string &destFileName) noexcept; - ResponseContext requestListDir(const std::string &directory); - }; - - namespace json::fs - { - inline constexpr auto removeFile = "removeFile"; - inline constexpr auto renameFile = "renameFile"; - inline constexpr auto destFileName = "destfilename"; - inline constexpr auto listDir = "listDir"; - inline constexpr auto path = "path"; - } // namespace json::fs - -} // namespace sdesktop::endpoints diff --git a/module-services/service-desktop/endpoints/include/endpoints/filesystem/FS_Helper.hpp b/module-services/service-desktop/endpoints/include/endpoints/filesystem/FS_Helper.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7b7cc45873a5f840efceebb3806ce0aeade0568f --- /dev/null +++ b/module-services/service-desktop/endpoints/include/endpoints/filesystem/FS_Helper.hpp @@ -0,0 +1,55 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include +#include "FileOperations.hpp" + +namespace sdesktop::endpoints +{ + namespace json::fs + { + inline constexpr auto removeFile = "removeFile"; + inline constexpr auto renameFile = "renameFile"; + inline constexpr auto destFilename = "destFilename"; + inline constexpr auto listDir = "listDir"; + inline constexpr auto path = "path"; + inline constexpr auto fileName = "fileName"; + inline constexpr auto fileSize = "fileSize"; + inline constexpr auto fileCrc32 = "fileCrc32"; + inline constexpr auto chunkSize = "chunkSize"; + inline constexpr auto chunkNo = "chunkNo"; + inline constexpr auto data = "data"; + inline constexpr auto rxID = "rxID"; + inline constexpr auto txID = "txID"; + + inline constexpr auto fileDoesNotExist = "file does not exist"; + } // namespace json::fs + + class FS_Helper : public BaseHelper + { + public: + explicit FS_Helper(sys::Service *p, FileOperations &fileOps) : BaseHelper(p), fileOps(fileOps) + {} + + auto processGet(Context &context) -> ProcessResult final; + auto processPut(Context &context) -> ProcessResult final; + auto processDelete(Context &context) -> ProcessResult final; + + private: + auto startGetFile(Context &context) const -> ResponseContext; + auto getFileChunk(Context &context) const -> ResponseContext; + + auto startSendFile(Context &context) const -> ResponseContext; + auto sendFileChunk(Context &context) const -> ResponseContext; + + auto requestFileRemoval(const std::string &fileName) -> bool; + auto requestFileRename(const std::string &fileName, const std::string &destFileName) noexcept -> bool; + auto requestListDir(const std::string &directory) -> ResponseContext; + + auto requestLogsFlush() const -> void; + + FileOperations &fileOps; + }; +} // namespace sdesktop::endpoints diff --git a/module-services/service-desktop/endpoints/include/endpoints/filesystem/FilesystemEndpoint.hpp b/module-services/service-desktop/endpoints/include/endpoints/filesystem/FilesystemEndpoint.hpp index 0b9145f09b1658a030b9029fb29ea209ccfedd80..ba26723339ece7c8f00ab4563301d20414d1ba65 100644 --- a/module-services/service-desktop/endpoints/include/endpoints/filesystem/FilesystemEndpoint.hpp +++ b/module-services/service-desktop/endpoints/include/endpoints/filesystem/FilesystemEndpoint.hpp @@ -4,6 +4,7 @@ #pragma once #include +#include "FS_Helper.hpp" #include #include "FileOperations.hpp" @@ -12,6 +13,8 @@ namespace sdesktop::endpoints class FilesystemEndpoint : public Endpoint { + const std::unique_ptr helper; + public: static auto createInstance(sys::Service *ownerServicePtr) -> std::unique_ptr { @@ -19,24 +22,10 @@ namespace sdesktop::endpoints } explicit FilesystemEndpoint(sys::Service *ownerServicePtr, FileOperations &fileOps) - : Endpoint(ownerServicePtr), fileOps(fileOps) + : Endpoint(ownerServicePtr), helper(std::make_unique(ownerServicePtr, fileOps)) {} - auto handle(Context &context) -> void override; - auto runGet(Context &context) -> sys::ReturnCodes; - auto runPost(Context &context) -> sys::ReturnCodes; - auto runPut(Context &context) -> sys::ReturnCodes; - auto getUpdates(Context &context) -> sys::ReturnCodes; - - private: - auto startGetFile(Context &context) const -> sys::ReturnCodes; - auto getFileChunk(Context &context) const -> sys::ReturnCodes; - auto startSendFile(Context &context) const -> sys::ReturnCodes; - auto sendFileChunk(Context &context) const -> sys::ReturnCodes; - - auto requestLogsFlush() const -> void; - - FileOperations &fileOps; + auto handle(Context &context) -> void override; }; } // namespace sdesktop::endpoints diff --git a/test/harness b/test/harness index 1e3d1ced82e8d94ce89d93f6d03378893c094731..a7aee485bcb04307202a5439748d6cd56b496a2a 160000 --- a/test/harness +++ b/test/harness @@ -1 +1 @@ -Subproject commit 1e3d1ced82e8d94ce89d93f6d03378893c094731 +Subproject commit a7aee485bcb04307202a5439748d6cd56b496a2a