diff --git a/OVMS.V3/components/console_ssh/src/console_ssh.cpp b/OVMS.V3/components/console_ssh/src/console_ssh.cpp index 7efa7c1..a6137f7 100644 --- a/OVMS.V3/components/console_ssh/src/console_ssh.cpp +++ b/OVMS.V3/components/console_ssh/src/console_ssh.cpp @@ -158,6 +158,7 @@ OvmsSSH::OvmsSSH() using std::placeholders::_2; MyEvents.RegisterEvent(tag,"network.mgr.init", std::bind(&OvmsSSH::NetManInit, this, _1, _2)); MyEvents.RegisterEvent(tag,"network.mgr.stop", std::bind(&OvmsSSH::NetManStop, this, _1, _2)); + MyEvents.RegisterEvent(tag,"config.restore", std::bind(&OvmsSSH::ConfigRestore, this, _1, _2)); MyConfig.RegisterParam("ssh.server", "SSH server private key store", true, false); MyConfig.RegisterParam("ssh.info", "SSH server information", false, true); MyConfig.RegisterParam("ssh.keys", "SSH public key store", true, true); @@ -232,6 +233,14 @@ void OvmsSSH::NetManStop(std::string event, void* data) } } +void OvmsSSH::ConfigRestore(std::string event, void* data) + { + if (RSAKeyGenerator::KillInstance()) + { + ESP_LOGW(tag, "RSAKeyGenerator killed by request"); + } + } + int OvmsSSH::Authenticate(uint8_t type, WS_UserAuthData* data, void* ctx) { ConsoleSSH* cons = (ConsoleSSH*)ctx; @@ -1058,11 +1067,26 @@ int SendCallback(WOLFSSH* ssh, void* data, uint32_t size, void* ctx) // Class RSAKeyGenerator //----------------------------------------------------------------------------- +RSAKeyGenerator* RSAKeyGenerator::s_instance = NULL; + RSAKeyGenerator::RSAKeyGenerator() : TaskBase("RSAKeyGen", 7*1024, 0) { + s_instance = this; Instantiate(); } +RSAKeyGenerator::~RSAKeyGenerator() + { + s_instance = NULL; + } + +bool RSAKeyGenerator::KillInstance() + { + if (!s_instance) return false; + s_instance->Kill(); + return true; + } + void RSAKeyGenerator::Service() { // Generate a random 2048-bit SSH host key for the SSH server in DER format. diff --git a/OVMS.V3/components/console_ssh/src/console_ssh.h b/OVMS.V3/components/console_ssh/src/console_ssh.h index f852e15..1d22d24 100644 --- a/OVMS.V3/components/console_ssh/src/console_ssh.h +++ b/OVMS.V3/components/console_ssh/src/console_ssh.h @@ -49,6 +49,7 @@ class OvmsSSH void EventHandler(struct mg_connection *nc, int ev, void *p); void NetManInit(std::string event, void* data); void NetManStop(std::string event, void* data); + void ConfigRestore(std::string event, void* data); static int Authenticate(uint8_t type, WS_UserAuthData* data, void* ctx); WOLFSSH_CTX* ctx() { return m_ctx; } @@ -118,14 +119,18 @@ class ConsoleSSH : public OvmsConsole class RSAKeyGenerator : public TaskBase { + private: + static RSAKeyGenerator* s_instance; + public: RSAKeyGenerator(); - virtual ~RSAKeyGenerator() {} + virtual ~RSAKeyGenerator(); + static bool KillInstance(); private: void Service(); private: - byte m_der[1200]; // Big enough for 2048-bit private key + byte m_der[1200]; // Big enough for 2048-bit private key }; #endif //#ifndef __CONSOLE_SSH_H__ diff --git a/OVMS.V3/main/ovms_config.cpp b/OVMS.V3/main/ovms_config.cpp index e1a7a66..7f2e805 100644 --- a/OVMS.V3/main/ovms_config.cpp +++ b/OVMS.V3/main/ovms_config.cpp @@ -44,6 +44,7 @@ static const char *TAG = "config"; #include "ovms_events.h" #include "ovms_utils.h" #include "ovms_boot.h" +#include "ovms_semaphore.h" #ifdef CONFIG_OVMS_SC_ZIP #include "zip_archive.h" @@ -852,7 +853,24 @@ bool OvmsConfig::Restore(std::string path, std::string password, OvmsWriter* wri else ESP_LOGD(TAG, "Restore: reading '%s'...", path.c_str()); - m_store_lock.Lock(); + // Lock config store: + if (!m_store_lock.Lock(pdMS_TO_TICKS(5000))) + { + if (writer) + writer->puts("Error: config store currently in use by another process"); + else + ESP_LOGE(TAG, "Restore: timeout waiting for config lock"); + return false; + } + + // Signal & wait for components to shutdown: + { + OvmsSemaphore eventdone; + auto callback = [](const char* event, void* data) { ((OvmsSemaphore*)data)->Give(); }; + MyEvents.SignalEvent("config.restore", &eventdone, callback); + eventdone.Take(); + } + bool ok = true; // unzip into restore directory: diff --git a/OVMS.V3/main/task_base.cpp b/OVMS.V3/main/task_base.cpp index 47f77aa..30750b1 100644 --- a/OVMS.V3/main/task_base.cpp +++ b/OVMS.V3/main/task_base.cpp @@ -165,10 +165,11 @@ void TaskBase::Task(void *object) } // This function should be overridden in the derived class to perform any -// cleanup operations that must be done before the task is deleted. +// cleanup operations that must be done after Service() has finished/stopped +// and before the TaskBase instance is deleted. // This function should NOT be called from the destructor because it is // called explicitly here before the object is deleted. That separation -// is needed so DeleteTask can clean up before deleting the task and still +// is needed so DeleteFromParent can clean up before deleting the task and still // wait to delete the object until after the task is deleted. void TaskBase::Cleanup() { @@ -192,8 +193,21 @@ void TaskBase::DeleteFromParent() // parent object's task. void TaskBase::DeleteTask() { - Cleanup(); if (m_taskid) + { + ESP_LOGD(TAG, "Task %s deletion at %u stack free", m_name, uxTaskGetStackHighWaterMark(m_taskid)); vTaskDelete(m_taskid); + } + Cleanup(); delete this; } + +// Kill: immediate task removal and instance deletion. +// ATT: This will terminate the running task (Service()) unconditionally! +// This function must NOT be called from the TaskBase object's own task. +void TaskBase::Kill() + { + if (m_parent) + m_parent->RemoveChild(this); + DeleteTask(); + } diff --git a/OVMS.V3/main/task_base.h b/OVMS.V3/main/task_base.h index 41f1da1..f4571c5 100644 --- a/OVMS.V3/main/task_base.h +++ b/OVMS.V3/main/task_base.h @@ -66,6 +66,7 @@ class TaskBase public: TaskBase(const char* name, int stack = DEFAULT_STACK, UBaseType_t priority = DEFAULT_PRIORITY, Parent* parent = NULL); Parent* parent() { return m_parent; } + virtual void Kill(); protected: virtual ~TaskBase();