~aleteoryx/muditaos

042e5b69849b28df367b0540156512adc2f4ed32 — Marek Niepieklo 5 years ago 465159e
[EGD-4625] Fix update timeout timer

Moved timer handling to Service Desktop
Use message comm. to update timer state
M module-services/service-desktop/ServiceDesktop.cpp => module-services/service-desktop/ServiceDesktop.cpp +29 -1
@@ 29,7 29,6 @@ ServiceDesktop::ServiceDesktop() : sys::Service(service::name::service_desktop, 

    updateOS = std::make_unique<UpdateMuditaOS>(this);
    settings = std::make_unique<settings::Settings>(this);

}

ServiceDesktop::~ServiceDesktop()


@@ 51,6 50,10 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
    else {
        desktopWorker->run();
    }

    transferTimer = std::make_unique<sys::Timer>("WorkerDesktop file upload", this, sdesktop::file_transfer_timeout);
    transferTimer->connect([&](sys::Timer &) { desktopWorker->cancelTransferOnTimeout(); });

    connect(sdesktop::developerMode::DeveloperModeRequest(), [&](sys::Message *msg) {
        auto request = static_cast<sdesktop::developerMode::DeveloperModeRequest *>(msg);
        if (request->event != nullptr) {


@@ 114,6 117,31 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
        return std::make_shared<sys::ResponseMessage>();
    });

    connect(sdesktop::transfer::TransferTimerState(), [&](sys::Message *msg) {
        sdesktop::transfer::TransferTimerState *timerStateMsg =
            dynamic_cast<sdesktop::transfer::TransferTimerState *>(msg);

        if (timerStateMsg != nullptr && timerStateMsg->messageType == MessageType::TransferTimer) {
            switch (timerStateMsg->req) {
            case sdesktop::transfer::TransferTimerState::Start:
                transferTimer->start();
                break;
            case sdesktop::transfer::TransferTimerState::Reload:
                transferTimer->reload();
                break;
            case sdesktop::transfer::TransferTimerState::Stop:
                transferTimer->stop();
                break;
            case sdesktop::transfer::TransferTimerState::None:
                [[fallthrough]];
            default:
                LOG_DEBUG("ServiceDesktop::SetTransferTimerState unhandled req:%u", timerStateMsg->req);
                break;
            }
        }
        return std::make_shared<sys::ResponseMessage>();
    });

    settings->registerValueChange(updateos::settings::history,
                                  [this](const std::string &value) { updateOS->setInitialHistory(value); });


M module-services/service-desktop/WorkerDesktop.cpp => module-services/service-desktop/WorkerDesktop.cpp +45 -7
@@ 3,6 3,7 @@

#include "service-desktop/ServiceDesktop.hpp"
#include "service-desktop/WorkerDesktop.hpp"
#include "service-desktop/DesktopMessages.hpp"
#include "parser/MessageHandler.hpp"
#include "parser/ParserFSM.hpp"
#include "endpoints/Context.hpp"


@@ 20,9 21,6 @@ inline constexpr auto uploadFailedMessage = "file upload terminated before all d
WorkerDesktop::WorkerDesktop(sys::Service *ownerServicePtr)
    : sys::Worker(ownerServicePtr), ownerService(ownerServicePtr), parser(ownerServicePtr), fileDes(nullptr)
{
    transferTimer =
        std::make_unique<sys::Timer>("WorkerDesktop file upload", ownerServicePtr, sdesktop::file_transfer_timeout);
    transferTimer->connect([=](sys::Timer &) { timerHandler(); });
}

bool WorkerDesktop::init(std::list<sys::WorkerQueueInfo> queues)


@@ 77,6 75,22 @@ bool WorkerDesktop::handleMessage(uint32_t queueID)
        bsp::usbCDCSend(sendMsg);
        delete sendMsg;
    }
    else if (qname == SERVICE_QUEUE_NAME) {
        auto &serviceQueue = getServiceQueue();
        sys::WorkerCommand cmd;

        if (serviceQueue.Dequeue(&cmd, 0)) {
            switch (static_cast<Command>(cmd.command)) {
            case Command::CancelTransfer:
                transferTimeoutHandler();
                break;
            }
        }
        else {
            LOG_ERROR("handleMessage xQueueReceive failed for %s.", SERVICE_QUEUE_NAME.c_str());
            return false;
        }
    }
    else {
        LOG_INFO("handeMessage got message on an unhandled queue");
    }


@@ 95,7 109,7 @@ sys::ReturnCodes WorkerDesktop::startDownload(const std::filesystem::path &desti
    if (fileSize <= 0)
        return sys::ReturnCodes::Failure;

    transferTimer->start();
    startTransferTimer();

    writeFileSizeExpected = fileSize;
    rawModeEnabled        = true;


@@ 104,6 118,26 @@ sys::ReturnCodes WorkerDesktop::startDownload(const std::filesystem::path &desti
    return sys::ReturnCodes::Success;
}

void WorkerDesktop::startTransferTimer()
{
    auto msg = std::make_shared<sdesktop::transfer::TransferTimerState>(
        sdesktop::transfer::TransferTimerState::Request::Start);
    ownerService->bus.sendUnicast(std::move(msg), service::name::service_desktop);
}

void WorkerDesktop::stopTransferTimer()
{
    auto msg =
        std::make_shared<sdesktop::transfer::TransferTimerState>(sdesktop::transfer::TransferTimerState::Request::Stop);
    ownerService->bus.sendUnicast(std::move(msg), service::name::service_desktop);
}
void WorkerDesktop::reloadTransferTimer()
{
    auto msg = std::make_shared<sdesktop::transfer::TransferTimerState>(
        sdesktop::transfer::TransferTimerState::Request::Reload);
    ownerService->bus.sendUnicast(std::move(msg), service::name::service_desktop);
}

void WorkerDesktop::stopTransfer(const TransferFailAction action)
{
    LOG_DEBUG("stopTransfer %s",


@@ 124,7 158,7 @@ void WorkerDesktop::stopTransfer(const TransferFailAction action)
    fclose(fileDes);

    // stop the timeout timer
    transferTimer->stop();
    stopTransferTimer();

    // reset all counters
    writeFileSizeExpected = 0;


@@ 142,7 176,7 @@ void WorkerDesktop::stopTransfer(const TransferFailAction action)
void WorkerDesktop::rawDataReceived(void *dataPtr, uint32_t dataLen)
{
    if (getRawMode()) {
        transferTimer->reload();
        reloadTransferTimer();

        if (dataPtr == nullptr || dataLen == 0) {
            LOG_ERROR("transferDataReceived invalid data");


@@ 170,10 204,14 @@ void WorkerDesktop::rawDataReceived(void *dataPtr, uint32_t dataLen)
    }
}

void WorkerDesktop::timerHandler()
void WorkerDesktop::cancelTransferOnTimeout()
{
    LOG_DEBUG("timeout timer: run");
    sendCommand({.command = static_cast<uint32_t>(Command::CancelTransfer), .data = nullptr});
}

void WorkerDesktop::transferTimeoutHandler()
{
    if (getRawMode()) {
        LOG_DEBUG("timeout timer: stopping transfer");
        uploadFileFailedResponse();

M module-services/service-desktop/service-desktop/DesktopMessages.hpp => module-services/service-desktop/service-desktop/DesktopMessages.hpp +18 -0
@@ 143,4 143,22 @@ namespace sdesktop
        };

    } // namespace bluetooth

    namespace transfer
    {
        class TransferTimerState : public sys::DataMessage
        {
          public:
            enum Request
            {
                None,
                Start,
                Reload,
                Stop
            };
            enum Request req = Request::None;
            TransferTimerState(enum Request req = None) : sys::DataMessage(MessageType::TransferTimer), req(req){};
            ~TransferTimerState() override = default;
        };
    } // namespace transfer
} // namespace sdesktop

M module-services/service-desktop/service-desktop/ServiceDesktop.hpp => module-services/service-desktop/service-desktop/ServiceDesktop.hpp +1 -0
@@ 46,6 46,7 @@ class ServiceDesktop : public sys::Service

  private:
    std::unique_ptr<settings::Settings> settings;
    std::unique_ptr<sys::Timer> transferTimer;
};

namespace sys

M module-services/service-desktop/service-desktop/WorkerDesktop.hpp => module-services/service-desktop/service-desktop/WorkerDesktop.hpp +17 -3
@@ 6,6 6,7 @@
#include <string.h>
#include <stdio.h>
#include <filesystem>
#include <atomic>
#include "Service/Message.hpp"
#include "Service/Service.hpp"
#include "Service/Worker.hpp"


@@ 21,6 22,10 @@ class WorkerDesktop : public sys::Worker, public bsp::USBDeviceListener
        doNothing,
        removeDesitnationFile
    };
    enum class Command
    {
        CancelTransfer,
    };
    WorkerDesktop(sys::Service *ownerServicePtr);

    virtual bool init(std::list<sys::WorkerQueueInfo> queues) override;


@@ 34,21 39,30 @@ class WorkerDesktop : public sys::Worker, public bsp::USBDeviceListener
    {
        return receiveQueue;
    }

    sys::ReturnCodes startDownload(const std::filesystem::path &destinationPath, const uint32_t fileSize);
    void stopTransfer(const TransferFailAction action);

    void timerHandler(void);
    void cancelTransferOnTimeout();

    void rawDataReceived(void *dataPtr, uint32_t dataLen) override;
    bool getRawMode() const noexcept override;

  private:
    void uploadFileFailedResponse();

    void transferTimeoutHandler();

    void startTransferTimer();
    void stopTransferTimer();
    void reloadTransferTimer();

    bool stateChangeWait();

    xQueueHandle receiveQueue;
    FILE *fileDes                  = nullptr;
    uint32_t writeFileSizeExpected = 0;
    uint32_t writeFileDataWritten  = 0;
    std::filesystem::path filePath;
    volatile bool rawModeEnabled = false;
    std::unique_ptr<sys::Timer> transferTimer;
    std::atomic<bool> rawModeEnabled = false;
};

M source/MessageType.hpp => source/MessageType.hpp +1 -0
@@ 211,6 211,7 @@ enum class MessageType
    Restore,
    Factory,
    DeveloperModeRequest,
    TransferTimer,

    // FOTA messages
    HttpRequest,