mirror of
https://github.com/esphome/esphome.git
synced 2026-09-22 20:48:43 +00:00
[ota,socket] Add SO_SNDTIMEO and use delay(0) in readall_
- Add SO_SNDTIMEO to OTA socket to prevent blocking writes from stalling the WDT when the TCP send buffer is full - Add SO_SNDTIMEO as no-op in raw TCP (writes never block) - Use delay(0) instead of delay(1) in readall_() since SO_RCVTIMEO already handles the wait - Keep delay(1) in writeall_() since raw TCP writes are non-blocking and would spin on EWOULDBLOCK without it
This commit is contained in:
@@ -258,6 +258,9 @@ void ESPHomeOTAComponent::handle_data_() {
|
||||
tv.tv_sec = 2;
|
||||
tv.tv_usec = 0;
|
||||
this->client_->setsockopt(SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
|
||||
// Also set send timeout to prevent blocking writes from stalling the WDT
|
||||
// when the TCP send buffer is full (e.g., network congestion).
|
||||
this->client_->setsockopt(SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
|
||||
this->client_->setblocking(true);
|
||||
|
||||
// Acknowledge auth OK - 1 byte
|
||||
@@ -413,7 +416,9 @@ bool ESPHomeOTAComponent::readall_(uint8_t *buf, size_t len) {
|
||||
} else {
|
||||
at += read;
|
||||
}
|
||||
this->yield_and_feed_watchdog_();
|
||||
// read() already waited via SO_RCVTIMEO, just yield without 1ms stall
|
||||
App.feed_wdt();
|
||||
delay(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
|
||||
#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
|
||||
#define SO_RCVTIMEO 0x1006 /* receive timeout */
|
||||
#define SO_SNDTIMEO 0x1005 /* send timeout */
|
||||
|
||||
#define SOL_SOCKET 0xfff /* options for socket level */
|
||||
|
||||
|
||||
@@ -355,6 +355,10 @@ int LWIPRawCommon::setsockopt(int level, int optname, const void *optval, sockle
|
||||
this->recv_timeout_cs_ = cs > 255 ? 255 : static_cast<uint8_t>(cs);
|
||||
return 0;
|
||||
}
|
||||
if (level == SOL_SOCKET && optname == SO_SNDTIMEO) {
|
||||
// Raw TCP writes are non-blocking (tcp_write), so send timeout is a no-op.
|
||||
return 0;
|
||||
}
|
||||
if (level == IPPROTO_TCP && optname == TCP_NODELAY) {
|
||||
if (optlen != 4) {
|
||||
errno = EINVAL;
|
||||
|
||||
Reference in New Issue
Block a user