~aleteoryx/muditaos

bba04acbe0ac6234cb207704fcfb58259196a9af — Lefucjusz 1 year, 2 months ago ea1d750
[BH-2075] Add GET method to time sync endpoint

Added GET method returning current Harmony
time as a timestamp. This is needed by MC
to implement time synchronization
functionality.
23 files changed, 124 insertions(+), 116 deletions(-)

M module-services/service-desktop/endpoints/BaseHelper.cpp
M module-services/service-desktop/endpoints/backup/BackupEndpoint.cpp
M module-services/service-desktop/endpoints/backup/BackupHelper.cpp
M module-services/service-desktop/endpoints/developerMode/DeveloperModeEndpoint.cpp
M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp
M module-services/service-desktop/endpoints/developerMode/Mode/UI_Helper.cpp
M module-services/service-desktop/endpoints/filesystem/FS_Helper.cpp
M module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.cpp
M module-services/service-desktop/endpoints/include/endpoints/BaseHelper.hpp
M module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp
M module-services/service-desktop/endpoints/include/endpoints/developerMode/DeveloperModeHelper.hpp
M module-services/service-desktop/endpoints/include/endpoints/timeSync/TimeSyncHelper.hpp
M module-services/service-desktop/endpoints/include/endpoints/update/UpdateHelper.hpp
M module-services/service-desktop/endpoints/reboot/RebootEndpoint.cpp
M module-services/service-desktop/endpoints/reboot/RebootHelper.cpp
M module-services/service-desktop/endpoints/restore/RestoreEndpoint.cpp
M module-services/service-desktop/endpoints/restore/RestoreHelper.cpp
M module-services/service-desktop/endpoints/security/SecurityEndpoint.cpp
M module-services/service-desktop/endpoints/security/SecurityEndpointHelper.cpp
M module-services/service-desktop/endpoints/timeSync/TimeSyncEndpoint.cpp
M module-services/service-desktop/endpoints/timeSync/TimeSyncHelper.cpp
M module-services/service-desktop/endpoints/update/UpdateEndpoint.cpp
M module-services/service-desktop/endpoints/update/UpdateHelper.cpp
M module-services/service-desktop/endpoints/BaseHelper.cpp => module-services/service-desktop/endpoints/BaseHelper.cpp +2 -2
@@ 7,7 7,7 @@ namespace sdesktop::endpoints
{
    auto ret() -> BaseHelper::ProcessResult
    {
        return {sent::no, std::nullopt};
        return {Sent::No, std::nullopt};
    }

    auto BaseHelper::processPut(Context &) -> ProcessResult


@@ 44,6 44,6 @@ namespace sdesktop::endpoints
            return processPut(context);
        }
        postProcess(method, context);
        return {sent::no, std::nullopt};
        return {Sent::No, std::nullopt};
    }
} // namespace sdesktop::endpoints

M module-services/service-desktop/endpoints/backup/BackupEndpoint.cpp => module-services/service-desktop/endpoints/backup/BackupEndpoint.cpp +3 -4
@@ 11,10 11,10 @@ namespace sdesktop::endpoints
    {
        auto [sent, response] = helper->process(context.getMethod(), context);

        if (sent == sent::delayed) {
        if (sent == Sent::Delayed) {
            LOG_DEBUG("There is no proper delayed serving mechanism - depend on invisible context caching");
        }
        if (sent == sent::no) {
        if (sent == Sent::No) {
            if (not response) {
                LOG_ERROR("Response not sent & response not created : respond with error");
                context.setResponseStatus(http::Code::NotAcceptable);


@@ 25,9 25,8 @@ namespace sdesktop::endpoints

            sender::putToSendQueue(context.createSimpleResponse());
        }
        if (sent == sent::yes and response) {
        if (sent == Sent::Yes and response) {
            LOG_ERROR("Response set when we already handled response in handler");
        }
    }

} // namespace sdesktop::endpoints

M module-services/service-desktop/endpoints/backup/BackupHelper.cpp => module-services/service-desktop/endpoints/backup/BackupHelper.cpp +7 -8
@@ 20,7 20,7 @@ namespace sdesktop::endpoints
            return checkSyncState(context);
        }

        return {sent::no, ResponseContext{.status = http::Code::BadRequest}};
        return {Sent::No, ResponseContext{.status = http::Code::BadRequest}};
    }

    auto BackupHelper::processPost(Context &context) -> ProcessResult


@@ 33,16 33,16 @@ namespace sdesktop::endpoints
            return executeBackupRequest(context);
        }

        return {sent::no, ResponseContext{.status = http::Code::BadRequest}};
        return {Sent::No, ResponseContext{.status = http::Code::BadRequest}};
    }

    auto BackupHelper::executeBackupRequest([[maybe_unused]] Context &context) -> ProcessResult
    {
        if (sys::SystemManagerCommon::RebootToRecovery(owner, sys::RecoveryReason::Backup)) {
            return {sent::no, ResponseContext{.status = http::Code::NoContent}};
            return {Sent::No, ResponseContext{.status = http::Code::NoContent}};
        }

        return {sent::no, ResponseContext{.status = http::Code::InternalServerError}};
        return {Sent::No, ResponseContext{.status = http::Code::InternalServerError}};
    }

    auto BackupHelper::executeSyncRequest([[maybe_unused]] Context &context) -> ProcessResult


@@ 52,7 52,7 @@ namespace sdesktop::endpoints
        if (ownerServicePtr->getSyncStatus().state == Sync::OperationState::Running) {
            LOG_DEBUG("Sync already running");
            // a sync package preparation is already running, don't start a second task
            return {sent::no, ResponseContext{.status = http::Code::NotAcceptable}};
            return {Sent::No, ResponseContext{.status = http::Code::NotAcceptable}};
        }
        else {
            LOG_DEBUG("Starting a sync package preparation");


@@ 64,7 64,7 @@ namespace sdesktop::endpoints

            // return new generated sync package info

            return {sent::no, ResponseContext{.status = http::Code::Accepted, .body = json11::Json::object{}}};
            return {Sent::No, ResponseContext{.status = http::Code::Accepted, .body = json11::Json::object{}}};
        }
    }



@@ 75,7 75,6 @@ namespace sdesktop::endpoints

        const auto status =
            (syncStatus.state == Sync::OperationState::Finished) ? http::Code::SeeOther : http::Code::NoContent;
        return {sent::no, ResponseContext{.status = status, .body = syncStatus}};
        return {Sent::No, ResponseContext{.status = status, .body = syncStatus}};
    }

} // namespace sdesktop::endpoints

M module-services/service-desktop/endpoints/developerMode/DeveloperModeEndpoint.cpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeEndpoint.cpp +3 -3
@@ 13,10 13,10 @@ namespace sdesktop::endpoints
    {
        auto &p               = helperSwitcher(context);
        auto [sent, response] = p.process(context.getMethod(), context);
        if (sent == sent::delayed) {
        if (sent == Sent::Delayed) {
            LOG_DEBUG("There is no proper delayed serving mechanism - depend on invisible context caching");
        }
        if (sent == sent::no) {
        if (sent == Sent::No) {
            if (not response) {
                LOG_ERROR("Response not sent & response not created : respond with error");
                context.setResponseStatus(http::Code::NotAcceptable);


@@ 27,7 27,7 @@ namespace sdesktop::endpoints

            sender::putToSendQueue(context.createSimpleResponse());
        }
        if (sent == sent::yes and response) {
        if (sent == Sent::Yes and response) {
            LOG_ERROR("Response set when we already handled response in handler");
        }
    }

M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp +26 -28
@@ 30,21 30,19 @@
#include <locks/data/PhoneLockMessages.hpp>

#include <fstream>

namespace
{

    auto toTetheringState(const std::string &state) -> sys::phone_modes::Tethering
    {
        using namespace sdesktop::endpoints::json::developerMode;

        return state == tetheringOn ? sys::phone_modes::Tethering::On : sys::phone_modes::Tethering::Off;
    }

} // namespace

namespace sdesktop::endpoints
{

    using sender::putToSendQueue;

    auto DeveloperModeHelper::processPut(Context &context) -> ProcessResult


@@ 56,7 54,7 @@ namespace sdesktop::endpoints
            auto state    = body[json::developerMode::state].int_value();
            sendKeypress(getKeyCode(keyValue), static_cast<gui::InputEvent::State>(state));
            app::manager::Controller::preventBlockingDevice(owner);
            return {sent::no, std::nullopt};
            return {Sent::No, std::nullopt};
        }
        else if (body[json::developerMode::AT].is_string()) {
            using namespace sdesktop::developerMode;


@@ 66,7 64,7 @@ namespace sdesktop::endpoints
            auto event = std::make_unique<ATResponseEvent>(cmd, timeout);
            auto msg   = std::make_shared<DeveloperModeRequest>(std::move(event));
            code       = toCode(owner->bus.sendUnicast(msg, service::name::cellular));
            return {sent::delayed, std::nullopt};
            return {Sent::Delayed, std::nullopt};
        }
        else if (body[json::developerMode::EQ].is_string()) {
            using namespace sdesktop::developerMode;


@@ 94,19 92,19 @@ namespace sdesktop::endpoints
                LOG_INFO("File verify OK");
                code = toCode(true);
            }
            return {sent::no, ResponseContext{.status = code}};
            return {Sent::No, ResponseContext{.status = code}};
        }
        else if (body[json::developerMode::focus].bool_value()) {
            auto event = std::make_unique<sdesktop::developerMode::AppFocusChangeEvent>();
            auto msg   = std::make_shared<sdesktop::developerMode::DeveloperModeRequest>(std::move(event));
            code       = toCode(owner->bus.sendUnicast(std::move(msg), service::name::evt_manager));
            return {sent::delayed, std::nullopt};
            return {Sent::Delayed, std::nullopt};
        }
        else if (body[json::developerMode::phoneLocked].bool_value()) {
            auto event = std::make_unique<sdesktop::developerMode::ScreenlockCheckEvent>();
            auto msg   = std::make_shared<sdesktop::developerMode::DeveloperModeRequest>(std::move(event));
            code       = toCode(owner->bus.sendUnicast(std::move(msg), "ApplicationManager"));
            return {sent::delayed, std::nullopt};
            return {Sent::Delayed, std::nullopt};
        }
        else if (body[json::developerMode::changeAutoLockTimeout].is_string()) {
            auto value = body[json::developerMode::changeAutoLockTimeout].string_value();


@@ 118,20 116,20 @@ namespace sdesktop::endpoints
            code          = owner->bus.sendUnicast(std::move(msg), service::name::db) ? http::Code::NoContent
                                                                                      : http::Code::InternalServerError;

            return {sent::no, ResponseContext{.status = code}};
            return {Sent::No, ResponseContext{.status = code}};
        }
        else if (body[json::developerMode::changeSim].is_number()) {
            int simSelected = body[json::developerMode::changeSim].int_value();
            requestSimChange(simSelected);
            code = http::Code::NoContent;
            return {sent::no, ResponseContext{.status = code}};
            return {Sent::No, ResponseContext{.status = code}};
        }
        else if (body[json::developerMode::changeCellularStateCmd].is_number()) {
            int cellularState = body[json::developerMode::changeCellularStateCmd].int_value();
            code              = requestCellularPowerStateChange(cellularState) ? http::Code::NoContent
                                                                               : http::Code::InternalServerError;

            return {sent::no, ResponseContext{.status = code}};
            return {Sent::No, ResponseContext{.status = code}};
        }
        else if (body[json::developerMode::smsCommand].is_string()) {
            if (body[json::developerMode::smsCommand].string_value() == json::developerMode::smsAdd) {


@@ 140,7 138,7 @@ namespace sdesktop::endpoints
                    return prepareSMS(context);
                }
                else {
                    return {sent::no, ResponseContext{.status = http::Code::NotAcceptable}};
                    return {Sent::No, ResponseContext{.status = http::Code::NotAcceptable}};
                }
            }
        }


@@ 148,7 146,7 @@ namespace sdesktop::endpoints
            const auto &tetheringState = body[json::developerMode::tethering].string_value();
            owner->bus.sendUnicast(std::make_shared<sys::TetheringStateRequest>(toTetheringState(tetheringState)),
                                   service::name::system_manager);
            return {sent::delayed, std::nullopt};
            return {Sent::Delayed, std::nullopt};
        }
        else if (body[json::developerMode::phoneLockCodeEnabled].is_bool()) {
            auto phoneLockState = body[json::developerMode::phoneLockCodeEnabled].bool_value();


@@ 177,7 175,7 @@ namespace sdesktop::endpoints
            context.setResponseStatus(http::Code::BadRequest);
            putToSendQueue(context.createSimpleResponse());
        }
        return {sent::no, ResponseContext{.status = code}};
        return {Sent::No, ResponseContext{.status = code}};
    }

    auto DeveloperModeHelper::processGet(Context &context) -> ProcessResult


@@ 192,30 190,30 @@ namespace sdesktop::endpoints
                         {json::deviceInfo::sim, std::to_string(static_cast<int>(Store::GSM::get()->sim))},
                         {json::deviceInfo::trayState, std::to_string(static_cast<int>(Store::GSM::get()->tray))}})};
                response.status = http::Code::OK;
                return {sent::no, std::move(response)};
                return {Sent::No, std::move(response)};
            }
            else if (keyValue == json::developerMode::cellularStateInfo) {
                if (!requestServiceStateInfo(owner)) {
                    return {sent::no, ResponseContext{.status = http::Code::NotAcceptable}};
                    return {Sent::No, ResponseContext{.status = http::Code::NotAcceptable}};
                }
                else {
                    return {sent::delayed, std::nullopt};
                    return {Sent::Delayed, std::nullopt};
                }
            }
            else if (keyValue == json::developerMode::cellularSleepModeInfo) {
                if (!requestCellularSleepModeInfo(owner)) {
                    return {sent::no, ResponseContext{.status = http::Code::NotAcceptable}};
                    return {Sent::No, ResponseContext{.status = http::Code::NotAcceptable}};
                }
                else {
                    return {sent::delayed, std::nullopt};
                    return {Sent::Delayed, std::nullopt};
                }
            }
            else {
                return {sent::no, ResponseContext{.status = http::Code::BadRequest}};
                return {Sent::No, ResponseContext{.status = http::Code::BadRequest}};
            }
        }
        else {
            return {sent::no, ResponseContext{.status = http::Code::BadRequest}};
            return {Sent::No, ResponseContext{.status = http::Code::BadRequest}};
        }
    }



@@ 278,7 276,7 @@ namespace sdesktop::endpoints
        };
    }

    bool DeveloperModeHelper::sendKeypress(bsp::KeyCodes keyCode, gui::InputEvent::State state)
    auto DeveloperModeHelper::sendKeypress(bsp::KeyCodes keyCode, gui::InputEvent::State state) -> bool
    {
        RawKey key{.state = RawKey::State::Released, .keyCode = keyCode};



@@ 288,14 286,14 @@ namespace sdesktop::endpoints
        return owner->bus.sendUnicast(std::move(message), service::name::evt_manager);
    }

    void DeveloperModeHelper::requestSimChange(const int simSelected)
    auto DeveloperModeHelper::requestSimChange(const int simSelected) -> void
    {
        auto arg = (simSelected == static_cast<int>(cellular::api::SimSlot::SIM2)) ? cellular::api::SimSlot::SIM2
                                                                                   : cellular::api::SimSlot::SIM1;
        owner->bus.sendUnicast<cellular::msg::request::sim::SetActiveSim>(arg);
    }

    bool DeveloperModeHelper::requestCellularPowerStateChange(const int cellularState)
    auto DeveloperModeHelper::requestCellularPowerStateChange(const int cellularState) -> bool
    {
        bool res = false;
        if (cellularState == 1) {


@@ 311,6 309,7 @@ namespace sdesktop::endpoints
        }
        return res;
    }

    auto DeveloperModeHelper::smsRecordFromJson(const json11::Json &msgJson) -> SMSRecord
    {
        auto record = SMSRecord();


@@ 349,21 348,20 @@ namespace sdesktop::endpoints

        DBServiceAPI::AddSMS(owner, record, std::move(listener));
        // actual success / fail happens in listener
        return {sent::delayed, std::nullopt};
        return {Sent::Delayed, std::nullopt};
    }

    bool DeveloperModeHelper::requestServiceStateInfo(sys::Service *serv)
    auto DeveloperModeHelper::requestServiceStateInfo(sys::Service *serv) -> bool
    {
        auto event = std::make_unique<sdesktop::developerMode::CellularStateInfoRequestEvent>();
        auto msg   = std::make_shared<sdesktop::developerMode::DeveloperModeRequest>(std::move(event));
        return serv->bus.sendUnicast(std::move(msg), service::name::cellular);
    }

    bool DeveloperModeHelper::requestCellularSleepModeInfo(sys::Service *serv)
    auto DeveloperModeHelper::requestCellularSleepModeInfo(sys::Service *serv) -> bool
    {
        auto event = std::make_unique<sdesktop::developerMode::CellularSleepModeInfoRequestEvent>();
        auto msg   = std::make_shared<sdesktop::developerMode::DeveloperModeRequest>(std::move(event));
        return serv->bus.sendUnicast(std::move(msg), service::name::cellular);
    }

} // namespace sdesktop::endpoints

M module-services/service-desktop/endpoints/developerMode/Mode/UI_Helper.cpp => module-services/service-desktop/endpoints/developerMode/Mode/UI_Helper.cpp +2 -2
@@ 33,8 33,8 @@ namespace sdesktop::endpoints
                std::make_shared<app::manager::DOMRequest>(service::name::service_desktop,
                                                           std::make_unique<sdesktop::Event>(std::move(event))),
                service::name::appmgr);
            return {sent::delayed, std::nullopt};
            return {Sent::Delayed, std::nullopt};
        }
        return {sent::no, std::nullopt};
        return {Sent::No, std::nullopt};
    }
}; // namespace sdesktop::endpoints

M module-services/service-desktop/endpoints/filesystem/FS_Helper.cpp => module-services/service-desktop/endpoints/filesystem/FS_Helper.cpp +3 -3
@@ 68,7 68,7 @@ namespace sdesktop::endpoints
            response = {.status = http::Code::BadRequest};
        }

        return {sent::no, std::move(response)};
        return {Sent::No, std::move(response)};
    }

    auto FS_Helper::processPut(Context &context) -> ProcessResult


@@ 96,7 96,7 @@ namespace sdesktop::endpoints
            response = ResponseContext{.status = http::Code::BadRequest};
        }

        return {sent::no, std::move(response)};
        return {Sent::No, std::move(response)};
    }

    auto FS_Helper::processDelete(Context &context) -> ProcessResult


@@ 118,7 118,7 @@ namespace sdesktop::endpoints
            LOG_ERROR("Bad request, missing or invalid argument");
        }

        return {sent::no, ResponseContext{.status = code}};
        return {Sent::No, ResponseContext{.status = code}};
    }
    auto FS_Helper::requestLogsFlush() const -> void
    {

M module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.cpp => module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.cpp +3 -4
@@ 14,10 14,10 @@ namespace sdesktop::endpoints
    {
        const auto &[sent, response] = helper->process(context.getMethod(), context);

        if (sent == sent::delayed) {
        if (sent == Sent::Delayed) {
            LOG_DEBUG("There is no proper delayed serving mechanism - depend on invisible context caching");
        }
        if (sent == sent::no) {
        if (sent == Sent::No) {
            if (not response) {
                LOG_ERROR("Response not sent & response not created : respond with error");
                context.setResponseStatus(http::Code::NotAcceptable);


@@ 28,9 28,8 @@ namespace sdesktop::endpoints

            sender::putToSendQueue(context.createSimpleResponse());
        }
        if (sent == sent::yes and response) {
        if (sent == Sent::Yes and response) {
            LOG_ERROR("Response set when we already handled response in handler");
        }
    }

} // namespace sdesktop::endpoints

M module-services/service-desktop/endpoints/include/endpoints/BaseHelper.hpp => module-services/service-desktop/endpoints/include/endpoints/BaseHelper.hpp +6 -7
@@ 15,28 15,28 @@ namespace sys

namespace sdesktop::endpoints
{

    class Context;
    enum class sent

    enum class Sent
    {
        /// response was sent from Helper class
        /// we should avoid that
        yes,
        Yes,
        /// response wasn't sent from Helper class
        /// we should send it from endpoint based on processing result
        no,
        No,
        /// works on global context
        /// mechanism:
        /// - Send message which is delayed
        /// - send the actual response form ServiceDesktop on `sdesktop::developerMode::DeveloperModeRequest`
        delayed,
        Delayed,
    };

    /// base helper class to avoid copies
    class BaseHelper
    {
      public:
        using ProcessResult = std::pair<sent, std::optional<ResponseContext>>;
        using ProcessResult = std::pair<Sent, std::optional<ResponseContext>>;

      protected:
        sys::Service *owner = nullptr;


@@ 68,5 68,4 @@ namespace sdesktop::endpoints
        /// pre and post processing is available on pre/post process method override
        [[nodiscard]] auto process(http::Method method, Context &context) -> ProcessResult;
    };

} // namespace sdesktop::endpoints

M module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp => module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp +1 -0
@@ 120,6 120,7 @@ namespace sdesktop::endpoints::json

    namespace timeSync
    {
        inline constexpr auto value     = "value";
        inline constexpr auto timestamp = "timestamp";
    }
} // namespace sdesktop::endpoints::json

M module-services/service-desktop/endpoints/include/endpoints/developerMode/DeveloperModeHelper.hpp => module-services/service-desktop/endpoints/include/endpoints/developerMode/DeveloperModeHelper.hpp +5 -7
@@ 10,17 10,16 @@

namespace sdesktop::endpoints
{

    class DeveloperModeHelper : public BaseHelper
    {
        static auto getKeyCode(int val) noexcept -> bsp::KeyCodes;
        bool sendKeypress(bsp::KeyCodes keyCode, gui::InputEvent::State state);
        auto sendKeypress(bsp::KeyCodes keyCode, gui::InputEvent::State state) -> bool;

        void requestSimChange(int simSelected);
        auto requestSimChange(int simSelected) -> void;
        auto smsRecordFromJson(const json11::Json &msgJson) -> SMSRecord;
        bool requestCellularPowerStateChange(int simSelected);
        bool requestServiceStateInfo(sys::Service *serv);
        bool requestCellularSleepModeInfo(sys::Service *serv);
        auto requestCellularPowerStateChange(int simSelected) -> bool;
        auto requestServiceStateInfo(sys::Service *serv) -> bool;
        auto requestCellularSleepModeInfo(sys::Service *serv) -> bool;
        auto prepareSMS(Context &context) -> ProcessResult;

      public:


@@ 73,5 72,4 @@ namespace sdesktop::endpoints
        inline constexpr auto tetheringOff = "off";

    } // namespace json::developerMode

} // namespace sdesktop::endpoints

M module-services/service-desktop/endpoints/include/endpoints/timeSync/TimeSyncHelper.hpp => module-services/service-desktop/endpoints/include/endpoints/timeSync/TimeSyncHelper.hpp +1 -0
@@ 14,6 14,7 @@ namespace sdesktop::endpoints
        explicit TimeSyncHelper(sys::Service *p) : BaseHelper(p)
        {}

        auto processGet(Context &context) -> ProcessResult final;
        auto processPost(Context &context) -> ProcessResult final;

      private:

M module-services/service-desktop/endpoints/include/endpoints/update/UpdateHelper.hpp => module-services/service-desktop/endpoints/include/endpoints/update/UpdateHelper.hpp +1 -1
@@ 15,7 15,7 @@ namespace sdesktop::endpoints
        explicit UpdateHelper(sys::Service *p);

        auto processPost(Context &context) -> ProcessResult final;
        void preProcess(http::Method method, Context &context) final;
        auto preProcess(http::Method method, Context &context) -> void final;

      private:
        std::filesystem::path updatePackagePath;

M module-services/service-desktop/endpoints/reboot/RebootEndpoint.cpp => module-services/service-desktop/endpoints/reboot/RebootEndpoint.cpp +3 -3
@@ 12,10 12,10 @@ namespace sdesktop::endpoints
    {
        const auto &[sent, response] = helper->process(context.getMethod(), context);

        if (sent == sent::delayed) {
        if (sent == Sent::Delayed) {
            LOG_DEBUG("There is no proper delayed serving mechanism - depend on invisible context caching");
        }
        if (sent == sent::no) {
        if (sent == Sent::No) {
            if (not response.has_value()) {
                LOG_ERROR("Response not sent & response not created : respond with error");
                context.setResponseStatus(http::Code::NotAcceptable);


@@ 26,7 26,7 @@ namespace sdesktop::endpoints

            sender::putToSendQueue(context.createSimpleResponse());
        }
        if (sent == sent::yes and response.has_value()) {
        if (sent == Sent::Yes and response.has_value()) {
            LOG_ERROR("Response set when we already handled response in handler");
        }
    }

M module-services/service-desktop/endpoints/reboot/RebootHelper.cpp => module-services/service-desktop/endpoints/reboot/RebootHelper.cpp +4 -4
@@ 16,17 16,17 @@ namespace sdesktop::endpoints

        if (rebootType == json::reboot::msc) {
            sys::SystemManagerCommon::RebootMSC(owner);
            return {sent::no, ResponseContext{.status = http::Code::Accepted}};
            return {Sent::No, ResponseContext{.status = http::Code::Accepted}};
        }
        else if (rebootType == json::reboot::reboot) {
            sys::SystemManagerCommon::Reboot(owner);
            return {sent::no, ResponseContext{.status = http::Code::Accepted}};
            return {Sent::No, ResponseContext{.status = http::Code::Accepted}};
        }
        else if (rebootType == json::reboot::shutdown) {
            sys::SystemManagerCommon::RegularPowerDown(owner);
            return {sent::no, ResponseContext{.status = http::Code::Accepted}};
            return {Sent::No, ResponseContext{.status = http::Code::Accepted}};
        }
        LOG_ERROR("Invalid request: %s", rebootType.c_str());
        return {sent::no, ResponseContext{.status = http::Code::BadRequest}};
        return {Sent::No, ResponseContext{.status = http::Code::BadRequest}};
    }
} // namespace sdesktop::endpoints

M module-services/service-desktop/endpoints/restore/RestoreEndpoint.cpp => module-services/service-desktop/endpoints/restore/RestoreEndpoint.cpp +3 -3
@@ 11,10 11,10 @@ namespace sdesktop::endpoints
    {
        auto [sent, response] = helper->process(context.getMethod(), context);

        if (sent == sent::delayed) {
        if (sent == Sent::Delayed) {
            LOG_DEBUG("There is no proper delayed serving mechanism - depend on invisible context caching");
        }
        if (sent == sent::no) {
        if (sent == Sent::No) {
            if (not response) {
                LOG_ERROR("Response not sent & response not created : respond with error");
                context.setResponseStatus(http::Code::NotAcceptable);


@@ 25,7 25,7 @@ namespace sdesktop::endpoints

            sender::putToSendQueue(context.createSimpleResponse());
        }
        if (sent == sent::yes and response) {
        if (sent == Sent::Yes and response) {
            LOG_ERROR("Response set when we already handled response in handler");
        }
    }

M module-services/service-desktop/endpoints/restore/RestoreHelper.cpp => module-services/service-desktop/endpoints/restore/RestoreHelper.cpp +2 -2
@@ 10,9 10,9 @@ namespace sdesktop::endpoints
    auto RestoreHelper::processPost([[maybe_unused]] Context &context) -> ProcessResult
    {
        if (sys::SystemManagerCommon::RebootToRecovery(owner, sys::RecoveryReason::Restore)) {
            return {sent::no, ResponseContext{.status = http::Code::NoContent}};
            return {Sent::No, ResponseContext{.status = http::Code::NoContent}};
        }

        return {sent::no, ResponseContext{.status = http::Code::InternalServerError}};
        return {Sent::No, ResponseContext{.status = http::Code::InternalServerError}};
    }
} // namespace sdesktop::endpoints

M module-services/service-desktop/endpoints/security/SecurityEndpoint.cpp => module-services/service-desktop/endpoints/security/SecurityEndpoint.cpp +3 -3
@@ 12,10 12,10 @@ namespace sdesktop::endpoints
    {
        auto [sent, response] = helper->process(context.getMethod(), context);

        if (sent == sent::delayed) {
        if (sent == Sent::Delayed) {
            LOG_DEBUG("There is no proper delayed serving mechanism - depend on invisible context caching");
        }
        if (sent == sent::no) {
        if (sent == Sent::No) {
            if (not response) {
                LOG_ERROR("Response not sent & response not created : respond with error");
                context.setResponseStatus(http::Code::NotAcceptable);


@@ 26,7 26,7 @@ namespace sdesktop::endpoints

            sender::putToSendQueue(context.createSimpleResponse());
        }
        if (sent == sent::yes and response) {
        if (sent == Sent::Yes and response) {
            LOG_ERROR("Response set when we already handled response in handler");
        }
    }

M module-services/service-desktop/endpoints/security/SecurityEndpointHelper.cpp => module-services/service-desktop/endpoints/security/SecurityEndpointHelper.cpp +4 -5
@@ 23,13 23,13 @@ namespace sdesktop::endpoints
    auto SecurityEndpointHelper::processPut(Context &context) -> ProcessResult
    {
        auto code = processConfiguration(context);
        return {sent::no, ResponseContext{.status = code}};
        return {Sent::No, ResponseContext{.status = code}};
    }

    auto SecurityEndpointHelper::processGet(Context &context) -> ProcessResult
    {
        if (context.getBody()[json::messages::category].string_value() == json::usb::phoneLockStatus) {
            return {sent::no, processStatus(context)};
            return {Sent::No, processStatus(context)};
        }
        if (context.getBody()[json::messages::category].string_value() == json::usb::phoneLockTime) {
            if (auto phoneLockTime = getPhoneLockTime(context); phoneLockTime > std::time(nullptr)) {


@@ 43,9 43,9 @@ namespace sdesktop::endpoints
                context.setResponseStatus(http::Code::UnprocessableEntity);
            }
            putToSendQueue(context.createSimpleResponse());
            return {sent::yes, std::nullopt};
            return {Sent::Yes, std::nullopt};
        }
        return {sent::no, ResponseContext{.status = http::Code::BadRequest}};
        return {Sent::No, ResponseContext{.status = http::Code::BadRequest}};
    }

    auto SecurityEndpointHelper::processStatus(Context & /*context*/) -> ResponseContext


@@ 119,5 119,4 @@ namespace sdesktop::endpoints

        return status;
    }

} // namespace sdesktop::endpoints

M module-services/service-desktop/endpoints/timeSync/TimeSyncEndpoint.cpp => module-services/service-desktop/endpoints/timeSync/TimeSyncEndpoint.cpp +3 -3
@@ 11,10 11,10 @@ namespace sdesktop::endpoints
    {
        const auto &[sent, response] = helper->process(context.getMethod(), context);

        if (sent == sent::delayed) {
        if (sent == Sent::Delayed) {
            LOG_DEBUG("There is no proper delayed serving mechanism - depend on invisible context caching");
        }
        if (sent == sent::no) {
        if (sent == Sent::No) {
            if (not response.has_value()) {
                LOG_ERROR("Response not sent & response not created : respond with error");
                context.setResponseStatus(http::Code::NotAcceptable);


@@ 25,7 25,7 @@ namespace sdesktop::endpoints

            sender::putToSendQueue(context.createSimpleResponse());
        }
        if (sent == sent::yes and response.has_value()) {
        if (sent == Sent::Yes and response.has_value()) {
            LOG_ERROR("Response set when we already handled response in handler");
        }
    }

M module-services/service-desktop/endpoints/timeSync/TimeSyncHelper.cpp => module-services/service-desktop/endpoints/timeSync/TimeSyncHelper.cpp +19 -3
@@ 11,6 11,22 @@

namespace sdesktop::endpoints
{
    auto TimeSyncHelper::processGet(Context &context) -> ProcessResult
    {
        const auto &body = context.getBody();

        /* Validate */
        if (body[json::timeSync::value] != json::timeSync::timestamp) {
            return {Sent::No, ResponseContext{.status = http::Code::BadRequest}};
        }

        std::time_t currentTimestamp;
        std::time(&currentTimestamp);

        json11::Json::object response({{json::timeSync::timestamp, currentTimestamp}});
        return {Sent::No, ResponseContext{.status = http::Code::OK, .body = std::move(response)}};
    }

    auto TimeSyncHelper::processPost(Context &context) -> ProcessResult
    {
        const auto &jsonTimestamp = context.getBody()[json::timeSync::timestamp];


@@ 18,17 34,17 @@ namespace sdesktop::endpoints
        /* Validate */
        if (!jsonTimestamp.is_number()) {
            LOG_ERROR("Timestamp data type not a number!");
            return {sent::no, ResponseContext{.status = http::Code::UnprocessableEntity}};
            return {Sent::No, ResponseContext{.status = http::Code::UnprocessableEntity}};
        }

        const auto timestamp = static_cast<std::time_t>(jsonTimestamp.number_value());
        logReceivedDateTime(timestamp);
        if (const auto success = sendTimeUpdateMessage(timestamp); !success) {
            LOG_ERROR("Failed to send time update message!");
            return {sent::no, ResponseContext{.status = http::Code::InternalServerError}};
            return {Sent::No, ResponseContext{.status = http::Code::InternalServerError}};
        }

        return {sent::no, ResponseContext{.status = http::Code::OK}};
        return {Sent::No, ResponseContext{.status = http::Code::OK}};
    }

    auto TimeSyncHelper::logReceivedDateTime(std::time_t timestamp) const noexcept -> void

M module-services/service-desktop/endpoints/update/UpdateEndpoint.cpp => module-services/service-desktop/endpoints/update/UpdateEndpoint.cpp +3 -5
@@ 8,15 8,14 @@

namespace sdesktop::endpoints
{

    auto UpdateEndpoint::handle(Context &context) -> void
    {
        auto &p               = helperSwitcher(context);
        auto [sent, response] = p.process(context.getMethod(), context);
        if (sent == sent::delayed) {
        if (sent == Sent::Delayed) {
            LOG_DEBUG("There is no proper delayed serving mechanism - depend on invisible context caching");
        }
        if (sent == sent::no) {
        if (sent == Sent::No) {
            if (not response) {
                LOG_ERROR("Response not sent & response not created : respond with error");
                context.setResponseStatus(http::Code::NotAcceptable);


@@ 27,7 26,7 @@ namespace sdesktop::endpoints

            sender::putToSendQueue(context.createSimpleResponse());
        }
        if (sent == sent::yes and response) {
        if (sent == Sent::Yes and response) {
            LOG_ERROR("Response set when we already handled response in handler");
        }
    }


@@ 36,5 35,4 @@ namespace sdesktop::endpoints
    {
        return *updateHelper;
    }

} // namespace sdesktop::endpoints

M module-services/service-desktop/endpoints/update/UpdateHelper.cpp => module-services/service-desktop/endpoints/update/UpdateHelper.cpp +17 -16
@@ 43,7 43,7 @@ namespace sdesktop::endpoints
        Entry recovery;
    };

    std::optional<json11::Json> fetchVersionJsonFromFile(const std::filesystem::path &path)
    auto fetchVersionJsonFromFile(const std::filesystem::path &path) -> std::optional<json11::Json>
    {
        std::ifstream versionJsonFile{path};
        if (not versionJsonFile.is_open()) {


@@ 60,7 60,7 @@ namespace sdesktop::endpoints
        return versionJson;
    }

    std::optional<UpdatePackageEntries> getUpdatePackageEntries(const std::filesystem::path &path)
    auto getUpdatePackageEntries(const std::filesystem::path &path) -> std::optional<UpdatePackageEntries>
    {
        if (const auto version = fetchVersionJsonFromFile(path)) {
            return UpdatePackageEntries{version.value()};


@@ 68,7 68,7 @@ namespace sdesktop::endpoints
        return std::nullopt;
    }

    bool validateImageEntry(const std::filesystem::path &path, const std::string &hash)
    auto validateImageEntry(const std::filesystem::path &path, const std::string &hash) -> bool
    {
        auto fd = std::fopen(path.c_str(), "rb");
        if (fd == nullptr) {


@@ 88,7 88,7 @@ namespace sdesktop::endpoints
        return (md5.getHash() == hash);
    }

    bool removeDirectory(const std::filesystem::path &path)
    auto removeDirectory(const std::filesystem::path &path) -> bool
    {
        if (std::filesystem::is_directory(path)) {
            LOG_INFO("Removing directory: %s", path.c_str());


@@ 100,7 100,7 @@ namespace sdesktop::endpoints
        return true;
    }

    bool unpackUpdatePackage(const std::filesystem::path &path, const std::filesystem::path &where)
    auto unpackUpdatePackage(const std::filesystem::path &path, const std::filesystem::path &where) -> bool
    {
        if (not removeDirectory(where)) {
            LOG_ERROR("Removing '%s' directory failed", path.c_str());


@@ 118,7 118,8 @@ namespace sdesktop::endpoints
        return true;
    }

    bool validateUpdatePackage(const std::filesystem::path &packagePath, const std::filesystem::path &binariesPath)
    auto validateUpdatePackage(const std::filesystem::path &packagePath, const std::filesystem::path &binariesPath)
        -> bool
    {
        LOG_INFO("Validating '%s' package", packagePath.c_str());
        const auto entries = getUpdatePackageEntries(packagePath / purefs::file::version_json);


@@ 132,7 133,7 @@ namespace sdesktop::endpoints
               validateImageEntry(prefix / entries->bootloader.first, entries->bootloader.second);
    }

    bool checkAvailableSpace(const std::filesystem::path &path, const std::filesystem::path &updatePackage)
    auto checkAvailableSpace(const std::filesystem::path &path, const std::filesystem::path &updatePackage) -> bool
    {
        struct statvfs stat
        {};


@@ 156,13 157,13 @@ namespace sdesktop::endpoints
        return freeSpace >= requiredSpace;
    }

    bool checkUpdatePackageFile(const std::filesystem::path &path)
    auto checkUpdatePackageFile(const std::filesystem::path &path) -> bool
    {
        LOG_INFO("Checking if update package exist, '%s'", path.c_str());
        return std::filesystem::exists(path);
    }

    void UpdateHelper::preProcess(http::Method method, [[maybe_unused]] Context &context)
    auto UpdateHelper::preProcess(http::Method method, [[maybe_unused]] Context &context) -> void
    {
        LOG_INFO("UpdateHelper requesting: %s", magic_enum::enum_name(method).data());
    }


@@ 172,32 173,32 @@ namespace sdesktop::endpoints
        const auto &body = context.getBody();

        if (body[json::update::update] != true || body[json::update::reboot] != true) {
            return {sent::no, ResponseContext{.status = http::Code::BadRequest}};
            return {Sent::No, ResponseContext{.status = http::Code::BadRequest}};
        }

        if (not checkUpdatePackageFile(purefs::dir::getTemporaryPath() / sdesktop::paths::updateFilename)) {
            return {sent::no, ResponseContext{.status = http::Code::NotFound}};
            return {Sent::No, ResponseContext{.status = http::Code::NotFound}};
        }

        if (not checkAvailableSpace(purefs::dir::getUserDiskPath(),
                                    purefs::dir::getTemporaryPath() / sdesktop::paths::updateFilename)) {
            return {sent::no, ResponseContext{.status = http::Code::NotAcceptable}};
            return {Sent::No, ResponseContext{.status = http::Code::NotAcceptable}};
        }

        if (not unpackUpdatePackage(purefs::dir::getTemporaryPath() / sdesktop::paths::updateFilename,
                                    updatePackagePath)) {
            return {sent::no, ResponseContext{.status = http::Code::UnprocessableEntity}};
            return {Sent::No, ResponseContext{.status = http::Code::UnprocessableEntity}};
        }

        if (not validateUpdatePackage(updatePackagePath, binariesPath)) {
            return {sent::no, ResponseContext{.status = http::Code::UnprocessableEntity}};
            return {Sent::No, ResponseContext{.status = http::Code::UnprocessableEntity}};
        }

        if (sys::SystemManagerCommon::RebootToRecovery(owner, sys::RecoveryReason::Update)) {
            return {sent::no, ResponseContext{.status = http::Code::NoContent}};
            return {Sent::No, ResponseContext{.status = http::Code::NoContent}};
        }

        return {sent::no, ResponseContext{.status = http::Code::InternalServerError}};
        return {Sent::No, ResponseContext{.status = http::Code::InternalServerError}};
    }

    UpdateHelper::UpdateHelper(sys::Service *p)