From 97e76d64d60d2d46a4bd4a4b50d11c496d596138 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Mon, 27 Sep 2021 11:40:28 +0200 Subject: [PATCH] Re-enable TCP nodelay for ESP32 (#2390) --- esphome/components/api/api_frame_helper.cpp | 15 +++++++++++ .../components/socket/lwip_raw_tcp_impl.cpp | 27 ++++++++++--------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/esphome/components/api/api_frame_helper.cpp b/esphome/components/api/api_frame_helper.cpp index 00f28457ae..4971272f41 100644 --- a/esphome/components/api/api_frame_helper.cpp +++ b/esphome/components/api/api_frame_helper.cpp @@ -127,6 +127,14 @@ APIError APINoiseFrameHelper::init() { return APIError::TCP_NONBLOCKING_FAILED; } + int enable = 1; + err = socket_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(int)); + if (err != 0) { + state_ = State::FAILED; + HELPER_LOG("Setting nodelay failed with errno %d", errno); + return APIError::TCP_NODELAY_FAILED; + } + // init prologue prologue_.insert(prologue_.end(), PROLOGUE_INIT, PROLOGUE_INIT + strlen(PROLOGUE_INIT)); @@ -722,6 +730,13 @@ APIError APIPlaintextFrameHelper::init() { HELPER_LOG("Setting nonblocking failed with errno %d", errno); return APIError::TCP_NONBLOCKING_FAILED; } + int enable = 1; + err = socket_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(int)); + if (err != 0) { + state_ = State::FAILED; + HELPER_LOG("Setting nodelay failed with errno %d", errno); + return APIError::TCP_NODELAY_FAILED; + } state_ = State::DATA; return APIError::OK; diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 7521d1339f..54dfddac3f 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -257,7 +257,7 @@ class LWIPRawImpl : public Socket { errno = EINVAL; return -1; } - *reinterpret_cast(optval) = tcp_nagle_disabled(pcb_); + *reinterpret_cast(optval) = nodelay_; *optlen = 4; return 0; } @@ -286,11 +286,7 @@ class LWIPRawImpl : public Socket { return -1; } int val = *reinterpret_cast(optval); - if (val != 0) { - tcp_nagle_disable(pcb_); - } else { - tcp_nagle_enable(pcb_); - } + nodelay_ = val; return 0; } @@ -444,9 +440,11 @@ class LWIPRawImpl : public Socket { if (written == 0) // no need to output if nothing written return 0; - int err = internal_output(); - if (err == -1) - return -1; + if (nodelay_) { + int err = internal_output(); + if (err == -1) + return -1; + } return written; } ssize_t writev(const struct iovec *iov, int iovcnt) override { @@ -466,9 +464,11 @@ class LWIPRawImpl : public Socket { if (written == 0) // no need to output if nothing written return 0; - int err = internal_output(); - if (err == -1) - return -1; + if (nodelay_) { + int err = internal_output(); + if (err == -1) + return -1; + } return written; } int setblocking(bool blocking) override { @@ -550,6 +550,9 @@ class LWIPRawImpl : public Socket { bool rx_closed_ = false; pbuf *rx_buf_ = nullptr; size_t rx_buf_offset_ = 0; + // don't use lwip nodelay flag, it sometimes causes reconnect + // instead use it for determining whether to call lwip_output + bool nodelay_ = false; }; std::unique_ptr socket(int domain, int type, int protocol) {