From 9bf72ff05f28533f42020fcb6e71ae1c5239a19c 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 15014b7937..172e1040ad 100644 --- a/esphome/components/api/api_frame_helper.cpp +++ b/esphome/components/api/api_frame_helper.cpp @@ -126,6 +126,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)); @@ -721,6 +729,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 3c225aeb82..0fe608b62e 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -256,7 +256,7 @@ class LWIPRawImpl : public Socket { errno = EINVAL; return -1; } - *reinterpret_cast(optval) = tcp_nagle_disabled(pcb_); + *reinterpret_cast(optval) = nodelay_; *optlen = 4; return 0; } @@ -285,11 +285,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; } @@ -443,9 +439,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 { @@ -465,9 +463,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 { @@ -549,6 +549,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) {