[ota] Fix OTA handshake failure by switching to blocking before feature ACK write

Switch to blocking mode before writing the feature ACK byte in the
no-password path. lwIP may not transmit data written in non-blocking
mode when the socket immediately switches to blocking and blocks in
recv(). Writing the feature ACK in blocking mode ensures it is flushed
to the wire before entering the blocking data transfer phase.
This commit is contained in:
J. Nick Koston
2026-04-05 09:51:37 -10:00
parent bf39dfef6a
commit 2243e34981
+10 -5
View File
@@ -185,6 +185,16 @@ void ESPHomeOTAComponent::handle_handshake_() {
}
case OTAState::FEATURE_ACK: {
// No password: switch to blocking before writing so the feature ACK
// byte is flushed to the wire before entering the blocking data phase.
// lwIP may not transmit data written in non-blocking mode when the
// socket immediately switches to blocking and blocks in recv().
#ifdef USE_OTA_PASSWORD
if (this->password_.empty())
#endif
{
this->client_->setblocking(true);
}
// Acknowledge header - 1 byte
if (!this->try_write_(1, LOG_STR("ack feature"))) {
return;
@@ -283,11 +293,6 @@ void ESPHomeOTAComponent::handle_data_() {
this->client_->setsockopt(SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
this->client_->setblocking(true);
// Yield to flush any pending non-blocking writes (e.g. the feature ACK byte)
// before entering the blocking data transfer. lwIP may not transmit data
// written in non-blocking mode until the task yields.
delay(0);
// Acknowledge auth OK - 1 byte
this->write_byte_(ota::OTA_RESPONSE_AUTH_OK);