mirror of
https://github.com/esphome/esphome.git
synced 2026-07-10 17:05:36 +00:00
Track request pointer to avoid re-init on web_server_idf's double index==0 call
web_server_idf invokes handleUpload twice with index==0 at the start of every upload (once as a 'Start' signal with nullptr data, then with the first data chunk). The previous fix treated the second call as a stale-session retry, wastefully aborting and re-initializing the backend on every single upload. Store the AsyncWebServerRequest pointer that owns the current session and only tear down the backend when a different request arrives at index==0. Clear the tracked pointer on every backend reset path so a stack-reused request pointer from a later upload cannot collide.
This commit is contained in:
@@ -72,6 +72,11 @@ class OTARequestHandler : public AsyncWebHandler {
|
||||
|
||||
private:
|
||||
ota::OTABackendPtr ota_backend_{nullptr};
|
||||
// Tracks the request that owns the current ota_backend_ session so we can
|
||||
// detect when a new (retry) request arrives while a previous session is
|
||||
// still open -- without re-triggering on the multiple index==0 callbacks
|
||||
// web_server_idf makes for a single upload (Start + first data chunk).
|
||||
AsyncWebServerRequest *ota_request_{nullptr};
|
||||
};
|
||||
|
||||
void OTARequestHandler::report_ota_progress_(AsyncWebServerRequest *request) {
|
||||
@@ -114,8 +119,8 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Platf
|
||||
uint8_t *data, size_t len, bool final) {
|
||||
ota::OTAResponseTypes error_code = ota::OTA_RESPONSE_OK;
|
||||
|
||||
if (index == 0) {
|
||||
// A new multipart upload is starting. If a previous upload was interrupted
|
||||
if (index == 0 && this->ota_request_ != request) {
|
||||
// A new request is starting an upload. If a previous upload was interrupted
|
||||
// (e.g. TCP reset) the backend from that session may still be open; tear it
|
||||
// down so flash state doesn't get concatenated with the new image (which
|
||||
// can produce a technically-valid-sized but corrupted firmware that
|
||||
@@ -125,6 +130,7 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Platf
|
||||
this->ota_backend_->abort();
|
||||
this->ota_backend_.reset();
|
||||
}
|
||||
this->ota_request_ = request;
|
||||
|
||||
// Initialize OTA on first call
|
||||
this->ota_init_(filename.c_str());
|
||||
@@ -160,6 +166,7 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Platf
|
||||
if (error_code != ota::OTA_RESPONSE_OK) {
|
||||
ESP_LOGE(TAG, "OTA begin failed: %d", error_code);
|
||||
this->ota_backend_.reset();
|
||||
this->ota_request_ = nullptr;
|
||||
#ifdef USE_OTA_STATE_LISTENER
|
||||
this->parent_->notify_state_deferred_(ota::OTA_ERROR, 0.0f, static_cast<uint8_t>(error_code));
|
||||
#endif
|
||||
@@ -178,6 +185,7 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Platf
|
||||
ESP_LOGE(TAG, "OTA write failed: %d", error_code);
|
||||
this->ota_backend_->abort();
|
||||
this->ota_backend_.reset();
|
||||
this->ota_request_ = nullptr;
|
||||
#ifdef USE_OTA_STATE_LISTENER
|
||||
this->parent_->notify_state_deferred_(ota::OTA_ERROR, 0.0f, static_cast<uint8_t>(error_code));
|
||||
#endif
|
||||
@@ -210,6 +218,7 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Platf
|
||||
#endif
|
||||
}
|
||||
this->ota_backend_.reset();
|
||||
this->ota_request_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user