From b9a688a946d118e8bd97346fef3da6ceffae18ed Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 16 Mar 2026 12:35:08 -1000 Subject: [PATCH] Clean up write_raw_: collapse error checks, remove redundant comments --- esphome/components/api/api_frame_helper.cpp | 32 +++++++++------------ 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/esphome/components/api/api_frame_helper.cpp b/esphome/components/api/api_frame_helper.cpp index b19556f034e..35c0fc8a08b 100644 --- a/esphome/components/api/api_frame_helper.cpp +++ b/esphome/components/api/api_frame_helper.cpp @@ -100,11 +100,10 @@ const LogString *api_error_to_logstr(APIError err) { return LOG_STR("UNKNOWN"); } -// This method writes data to socket or buffers it +// Write data to socket, overflow to backlog buffer if LWIP TCP send buffer is full. +// Returns OK if all data was sent or successfully queued. +// Returns SOCKET_WRITE_FAILED on hard error (sets state to FAILED). APIError APIFrameHelper::write_raw_(const struct iovec *iov, int iovcnt, uint16_t total_write_len) { - // Returns APIError::OK if all data was sent or successfully queued. - // Returns APIError::SOCKET_WRITE_FAILED if socket write failed, and sets state to FAILED. - #ifdef HELPER_LOG_PACKETS for (int i = 0; i < iovcnt; i++) { LOG_PACKET_SENDING(reinterpret_cast(iov[i].iov_base), iov[i].iov_len); @@ -113,34 +112,29 @@ APIError APIFrameHelper::write_raw_(const struct iovec *iov, int iovcnt, uint16_ uint16_t skip = 0; - // If there is already backlogged data, try to drain it first + // Drain any existing backlog first if (!this->overflow_buf_.empty()) [[unlikely]] { - if (this->overflow_buf_.try_drain(this->socket_.get()) == -1) { - HELPER_LOG("Socket write failed with errno %d", errno); - if (this->check_socket_write_err_(errno) != APIError::WOULD_BLOCK) - return APIError::SOCKET_WRITE_FAILED; - } - // If drain didn't fully clear, skip direct send and queue behind backlog + if (this->overflow_buf_.try_drain(this->socket_.get()) == -1 && + this->check_socket_write_err_(errno) != APIError::WOULD_BLOCK) + return APIError::SOCKET_WRITE_FAILED; } + // If backlog is clear, try direct send if (this->overflow_buf_.empty()) { - // No backlog — try to send directly - // Optimize for single iovec case (common for plaintext API) ssize_t sent = (iovcnt == 1) ? this->socket_->write(iov[0].iov_base, iov[0].iov_len) : this->socket_->writev(iov, iovcnt); - if (sent == -1) [[unlikely]] { // Socket write failed - HELPER_LOG("Socket write failed with errno %d", errno); + if (sent == -1) [[unlikely]] { if (this->check_socket_write_err_(errno) != APIError::WOULD_BLOCK) return APIError::SOCKET_WRITE_FAILED; - } else if (static_cast(sent) >= total_write_len) [[likely]] { // All data sent successfully - return APIError::OK; // All data sent successfully + } else if (static_cast(sent) >= total_write_len) [[likely]] { + return APIError::OK; } else { - skip = static_cast(sent); // Partially sent — queue the remainder + skip = static_cast(sent); } } - // Queue data into overflow buffer, or fail the connection if full + // Queue unsent data into overflow buffer if (!this->overflow_buf_.enqueue_iov(iov, iovcnt, total_write_len, skip)) { this->state_ = State::FAILED; return APIError::SOCKET_WRITE_FAILED;