From 9bb9739b27b3171926481ef6483aac265df61d36 Mon Sep 17 00:00:00 2001 From: jpirnay Date: Sun, 24 May 2026 16:40:05 +0200 Subject: [PATCH] Review comments taken on board --- src/JsonSettingsIO.cpp | 6 +++++- src/WifiCredentialStore.cpp | 10 +++++++++- src/activities/network/WifiSelectionActivity.cpp | 7 +++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/JsonSettingsIO.cpp b/src/JsonSettingsIO.cpp index 5cf2efa7..5d61fa8a 100644 --- a/src/JsonSettingsIO.cpp +++ b/src/JsonSettingsIO.cpp @@ -507,7 +507,11 @@ bool JsonSettingsIO::loadWifi(WifiCredentialStore& store, const char* json, bool } const auto parseQuad = [](const std::string& s, uint8_t out[4]) -> bool { unsigned int a = 0, b = 0, c = 0, d = 0; - if (sscanf(s.c_str(), "%u.%u.%u.%u", &a, &b, &c, &d) != 4) return false; + int consumed = 0; + // %n stores characters consumed; require it to equal full string length so we + // reject inputs with trailing garbage like "192.168.1.10xyz". + if (sscanf(s.c_str(), "%u.%u.%u.%u%n", &a, &b, &c, &d, &consumed) != 4) return false; + if (consumed < 0 || static_cast(consumed) != s.size()) return false; if (a > 255 || b > 255 || c > 255 || d > 255) return false; out[0] = a; out[1] = b; diff --git a/src/WifiCredentialStore.cpp b/src/WifiCredentialStore.cpp index d2e01239..55b2f9e3 100644 --- a/src/WifiCredentialStore.cpp +++ b/src/WifiCredentialStore.cpp @@ -95,8 +95,16 @@ bool WifiCredentialStore::updateConnectionCache(const std::string& ssid, const u const bool sameHint = (channel == cred->channel) && std::memcmp(bssid, cred->bssid, 6) == 0; const bool sameIp = std::memcmp(ip, cred->ip, 4) == 0 && std::memcmp(gateway, cred->gateway, 4) == 0 && std::memcmp(mask, cred->mask, 4) == 0 && std::memcmp(dns, cred->dns, 4) == 0; - // Timestamp updates are not worth a write on their own; only persist when topology changed. if (sameHint && sameIp) { + // Refresh the TTL only if the cache is older than half the TTL window — otherwise + // a long-running device that reconnects daily would let its 7-day TTL expire even + // though the topology hasn't changed. Half-TTL avoids an SD write on every connect. + constexpr uint32_t REFRESH_THRESHOLD_SECONDS = (7 * 24 * 60 * 60) / 2; + const int64_t elapsed = static_cast(cacheTimestamp) - static_cast(cred->cacheTimestamp); + if (cacheTimestamp != 0 && cred->cacheTimestamp != 0 && elapsed > REFRESH_THRESHOLD_SECONDS) { + cred->cacheTimestamp = cacheTimestamp; + return saveToFile(); + } return true; } std::memcpy(cred->bssid, bssid, 6); diff --git a/src/activities/network/WifiSelectionActivity.cpp b/src/activities/network/WifiSelectionActivity.cpp index 75b9d354..55b3d87c 100644 --- a/src/activities/network/WifiSelectionActivity.cpp +++ b/src/activities/network/WifiSelectionActivity.cpp @@ -549,6 +549,13 @@ void WifiSelectionActivity::checkConnectionStatus() { LOG_DBG("WIFI", "Hint attempt did not connect (%s after %lu ms), retrying with full scan", hintHardFail ? "hard fail" : "timeout", millis() - connectionStartTime); hintFallbackDone = true; + // Wipe the stale cache before retrying. If the fallback succeeds, the success + // path writes a fresh cache (one extra SD write). If it fails or is interrupted, + // we won't carry a known-bad hint into the next session. + { + RenderLock lock(*this); + WIFI_STORE.clearConnectionCache(selectedSSID); + } WiFi.disconnect(true, false); connectionStartTime = millis(); issueWifiBegin(/*useHint=*/false);