Fix storage recovery and deferred runtime state

Recover usable ESP32 preferences and channels before permitting replacement; keep identity and ACL persistence transactional and complete.

Preserve MQTT commit boundaries, restore OTA identity and policy after deferred allocation, retain radio gain retries, and reject invalid flood limits. Add production-path fault regressions and CI coverage.
This commit is contained in:
mikecarper committed 2026-09-15 16:46:17 -07:00
1 parent 86defc840c
commit e2a1828987
32 files changed
+1546 -189

No files matched your search

+32 -45
View File
@@ -1,10 +1,30 @@
#include "IdentityStore.h"
#if defined(NRF52_PLATFORM)
#include "FilePresence.h"
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
#include "AtomicFileWriter.h"
#else
#include "ContactFileTransaction.h"
#endif
bool IdentityStore::recover(const char* name) {
#if defined(ESP32_PLATFORM) || defined(RP2040_PLATFORM)
char filename[40], backup[48];
if (snprintf(filename, sizeof(filename), "%s/%s.id", _dir, name)
>= (int)sizeof(filename)) return false;
snprintf(backup, sizeof(backup), "%s.bak", filename);
bool primary_exists = false, backup_exists = false;
if (!mesh::filePresence(_fs, filename, primary_exists)
|| !mesh::filePresence(_fs, backup, backup_exists)) return false;
if (!primary_exists && backup_exists) return _fs->rename(backup, filename);
#else
(void)name;
#endif
return true;
}
bool IdentityStore::load(const char *name, mesh::LocalIdentity& id) {
if (!recover(name)) return false;
bool loaded = false;
char filename[40];
sprintf(filename, "%s/%s.id", _dir, name);
@@ -23,6 +43,7 @@ bool IdentityStore::load(const char *name, mesh::LocalIdentity& id) {
}
bool IdentityStore::load(const char *name, mesh::LocalIdentity& id, char display_name[], int max_name_sz) {
if (!recover(name)) return false;
bool loaded = false;
char filename[40];
sprintf(filename, "%s/%s.id", _dir, name);
@@ -50,44 +71,30 @@ bool IdentityStore::save(const char *name, const mesh::LocalIdentity& id) {
char filename[40];
sprintf(filename, "%s/%s.id", _dir, name);
#if defined(NRF52_PLATFORM)
if (!recover(name)) return false;
uint8_t key_data[PRV_KEY_SIZE + PUB_KEY_SIZE];
if (id.writeTo(key_data, sizeof(key_data)) != sizeof(key_data)) return false;
// LocalIdentity's byte-buffer export is private-key then public-key, while
// the historical file format is public-key then private-key.
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
mesh::AtomicFileWriter writer(_fs, filename);
#else
mesh::ContactFileTransaction writer(_fs, filename, mesh::filePresence<FILESYSTEM>);
#endif
const bool wrote = writer
&& writer.write(&key_data[PRV_KEY_SIZE], PUB_KEY_SIZE) == PUB_KEY_SIZE
&& writer.write(key_data, PRV_KEY_SIZE) == PRV_KEY_SIZE;
const bool success = writer.commit(wrote);
MESH_DEBUG_PRINTLN("IdentityStore::save() atomic write - %s", success ? "OK" : "Err");
return success;
#elif defined(STM32_PLATFORM)
_fs->remove(filename);
File file = _fs->open(filename, FILE_O_WRITE);
#elif defined(RP2040_PLATFORM)
File file = _fs->open(filename, "w");
#else
File file = _fs->open(filename, "w", true);
#endif
#if !defined(NRF52_PLATFORM)
if (file) {
bool success = id.writeTo(file);
file.close();
MESH_DEBUG_PRINTLN("IdentityStore::save() write - %s", success ? "OK" : "Err");
return success;
}
#endif
MESH_DEBUG_PRINTLN("IdentityStore::save() failed");
return false;
}
bool IdentityStore::save(const char *name, const mesh::LocalIdentity& id, const char display_name[]) {
char filename[40];
sprintf(filename, "%s/%s.id", _dir, name);
#if defined(NRF52_PLATFORM)
if (!recover(name)) return false;
uint8_t key_data[PRV_KEY_SIZE + PUB_KEY_SIZE];
if (id.writeTo(key_data, sizeof(key_data)) != sizeof(key_data)) return false;
uint8_t display_data[32];
@@ -96,34 +103,14 @@ bool IdentityStore::save(const char *name, const mesh::LocalIdentity& id, const
if (display_len > sizeof(display_data) - 1) display_len = sizeof(display_data) - 1;
memcpy(display_data, display_name, display_len);
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
mesh::AtomicFileWriter writer(_fs, filename);
#else
mesh::ContactFileTransaction writer(_fs, filename, mesh::filePresence<FILESYSTEM>);
#endif
const bool wrote = writer
&& writer.write(&key_data[PRV_KEY_SIZE], PUB_KEY_SIZE) == PUB_KEY_SIZE
&& writer.write(key_data, PRV_KEY_SIZE) == PRV_KEY_SIZE
&& writer.write(display_data, sizeof(display_data)) == sizeof(display_data);
return writer.commit(wrote);
#elif defined(STM32_PLATFORM)
_fs->remove(filename);
File file = _fs->open(filename, FILE_O_WRITE);
#elif defined(RP2040_PLATFORM)
File file = _fs->open(filename, "w");
#else
File file = _fs->open(filename, "w", true);
#endif
#if !defined(NRF52_PLATFORM)
if (file) {
bool success = id.writeTo(file);
uint8_t tmp[32];
memset(tmp, 0, sizeof(tmp));
int n = strlen(display_name);
if (n > sizeof(tmp)-1) n = sizeof(tmp)-1;
memcpy(tmp, display_name, n);
success = success && file.write(tmp, sizeof(tmp)) == sizeof(tmp);
file.close();
return success;
}
#endif
return false;
}