From 27482fef01d1d9923cd9c14d1457d30a4c0cdc64 Mon Sep 17 00:00:00 2001 From: Rasmus Date: Sat, 12 Sep 2026 18:10:32 +0200 Subject: [PATCH] fix(stability): disable dangerous mbedtls free configs, place panic handler in IRAM, and make prefetch safe and on-demand --- main/Kconfig.projbuild | 2 +- main/scryfall_client.c | 35 ++++++++++++++++++++++++++++++----- sdkconfig | 8 +++----- sdkconfig.defaults | 12 ++++++++---- 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index cc57527..27cc08f 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -10,7 +10,7 @@ menu "MTG RFID Companion" config MTG_SCAN_PREFETCH bool "Prefetch card data for all mapped UIDs at boot" - default y + default n config MTG_GITEA_URL string "Gitea instance base URL (e.g. https://gitea.com)" diff --git a/main/scryfall_client.c b/main/scryfall_client.c index d3f90ad..447802e 100644 --- a/main/scryfall_client.c +++ b/main/scryfall_client.c @@ -87,6 +87,7 @@ typedef struct { size_t cap; esp_err_t err; FILE *file; /* when downloading to a file */ + const char *file_path; int status; } http_sink_t; @@ -153,11 +154,22 @@ static esp_err_t http_request(const char *url, http_sink_t *sink) return ESP_ERR_TIMEOUT; } + /* Disable power save during HTTPS requests for maximum reliability */ + wifi_manager_set_power_save(false); + esp_err_t overall_ret = ESP_FAIL; for (int attempt = 0; attempt < MAX_ATTEMPTS; attempt++) { if (sink->file != NULL) { - rewind(sink->file); - ftruncate(fileno(sink->file), 0); + if (attempt > 0 && sink->file_path != NULL) { + fclose(sink->file); + sink->file = fopen(sink->file_path, "wb"); + if (sink->file == NULL) { + overall_ret = ESP_FAIL; + break; + } + } else { + rewind(sink->file); + } } else { sink->len = 0; } @@ -171,6 +183,7 @@ static esp_err_t http_request(const char *url, http_sink_t *sink) .user_data = sink, .buffer_size = 2048, .crt_bundle_attach = esp_crt_bundle_attach, + .keep_alive_enable = false, }; esp_http_client_handle_t client = esp_http_client_init(&cfg); if (client == NULL) { @@ -201,6 +214,7 @@ static esp_err_t http_request(const char *url, http_sink_t *sink) vTaskDelay(pdMS_TO_TICKS(500)); } + wifi_manager_set_power_save(true); wifi_manager_release_net_lock(); return overall_ret; } @@ -230,7 +244,7 @@ static esp_err_t http_download_file(const char *url, const char *path) if (f == NULL) { return ESP_FAIL; } - http_sink_t sink = { .file = f }; + http_sink_t sink = { .file = f, .file_path = tmp }; esp_err_t ret = http_request(url, &sink); fclose(f); if (ret != ESP_OK) { @@ -441,8 +455,17 @@ static esp_err_t scryfall_ensure_cached(const char *card_name, const char *uid) /* net_task */ /* ------------------------------------------------------------------ */ +#ifdef CONFIG_MTG_SCAN_PREFETCH static void prefetch_mappings(void) { + /* Settle delay: give system and Wi-Fi time to settle before background fetch */ + vTaskDelay(pdMS_TO_TICKS(5000)); + + if (esp_get_free_heap_size() < 40000) { + ESP_LOGW(TAG, "Heap too low (%u bytes) for startup prefetch, skipping", (unsigned int)esp_get_free_heap_size()); + return; + } + char *buf = NULL; size_t len = 0; if (storage_read_text(STORAGE_MAPPINGS, &buf, &len) != ESP_OK || buf == NULL) { @@ -463,12 +486,14 @@ static void prefetch_mappings(void) cJSON_ArrayForEach(item, root) { uid = item->string; if (uid == NULL || item->valuestring == NULL) continue; - scryfall_ensure_cached(item->valuestring, uid); + /* Call scryfall_do_fetch directly so we do not clobber UI fetch signaling */ + scryfall_do_fetch(item->valuestring, uid); /* Rate-limit delay: Scryfall requests 50-100ms between queries */ - vTaskDelay(pdMS_TO_TICKS(100)); + vTaskDelay(pdMS_TO_TICKS(150)); } cJSON_Delete(root); } +#endif static void net_task(void *arg) { diff --git a/sdkconfig b/sdkconfig index 7ee2012..89c6611 100644 --- a/sdkconfig +++ b/sdkconfig @@ -436,7 +436,7 @@ CONFIG_PARTITION_TABLE_MD5=y # CONFIG_MTG_WIFI_SSID="WiFimodem-FD58" CONFIG_MTG_WIFI_PASS="gzhrt5yzm3" -CONFIG_MTG_SCAN_PREFETCH=y +# CONFIG_MTG_SCAN_PREFETCH is not set CONFIG_MTG_GITEA_URL="https://gitea.com" CONFIG_MTG_GITEA_REPO_OWNER="user" CONFIG_MTG_GITEA_REPO_NAME="espMTG" @@ -1156,7 +1156,7 @@ CONFIG_ESP_TASK_WDT_INIT=y CONFIG_ESP_TASK_WDT_TIMEOUT_S=15 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y -# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +CONFIG_ESP_PANIC_HANDLER_IRAM=y # CONFIG_ESP_DEBUG_STUBS_ENABLE is not set CONFIG_ESP_DEBUG_OCDAWARE=y # CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 is not set @@ -1384,7 +1384,6 @@ CONFIG_FREERTOS_NO_AFFINITY=0xFFFFFFFF CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y CONFIG_FREERTOS_DEBUG_OCDAWARE=y CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y -CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y CONFIG_FREERTOS_NUMBER_OF_CORES=2 CONFIG_FREERTOS_IN_IRAM=y # end of FreeRTOS @@ -1666,8 +1665,7 @@ CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 CONFIG_MBEDTLS_DYNAMIC_BUFFER=y -CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y -CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT=y +# CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA is not set # CONFIG_MBEDTLS_DEBUG is not set # diff --git a/sdkconfig.defaults b/sdkconfig.defaults index a9fd514..6414928 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -34,11 +34,15 @@ CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=2 -# Watchdog Timeouts for Flash Erase & OTA Operations +# Watchdog & Panic Handlers CONFIG_ESP_INT_WDT_TIMEOUT_MS=2000 CONFIG_ESP_TASK_WDT_TIMEOUT_S=15 +CONFIG_ESP_PANIC_HANDLER_IRAM=y -# mbedTLS Dynamic Buffers & Memory Optimization (Vital for ESP32 without PSRAM) +# Prefetch disabled by default for boot stability +CONFIG_MTG_SCAN_PREFETCH=n + +# mbedTLS Dynamic Buffers (Keep only dynamic buffer; free ca cert causes crashes with crt bundle) CONFIG_MBEDTLS_DYNAMIC_BUFFER=y -CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y -CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT=y \ No newline at end of file +# CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA is not set +# CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT is not set \ No newline at end of file