mirror of
https://github.com/esphome/esphome.git
synced 2026-09-17 18:18:43 +00:00
Inline empty() fast path, out-of-line drain+error handling
Keep the cheap overflow_buf_.empty() check inline at all call sites. Move try_drain + HELPER_LOG + error handling into a single out-of-line drain_overflow_and_handle_errors_() used by both write_raw_ and the subclass loop() methods. Eliminates the duplicated drain logic.
This commit is contained in:
@@ -100,6 +100,15 @@ const LogString *api_error_to_logstr(APIError err) {
|
||||
return LOG_STR("UNKNOWN");
|
||||
}
|
||||
|
||||
APIError APIFrameHelper::drain_overflow_and_handle_errors_() {
|
||||
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;
|
||||
}
|
||||
return APIError::OK;
|
||||
}
|
||||
|
||||
// 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).
|
||||
@@ -114,11 +123,9 @@ APIError APIFrameHelper::write_raw_(const struct iovec *iov, int iovcnt, uint16_
|
||||
|
||||
// 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;
|
||||
}
|
||||
APIError err = this->drain_overflow_and_handle_errors_();
|
||||
if (err != APIError::OK)
|
||||
return err;
|
||||
}
|
||||
|
||||
// If backlog is clear, try direct send
|
||||
|
||||
@@ -190,15 +190,11 @@ class APIFrameHelper {
|
||||
}
|
||||
|
||||
protected:
|
||||
// Drain any backlogged overflow data to the socket.
|
||||
// Returns OK even for WOULD_BLOCK to avoid connection termination.
|
||||
APIError try_drain_overflow_buffer_() {
|
||||
if (!this->overflow_buf_.empty() && this->overflow_buf_.try_drain(this->socket_.get()) == -1) {
|
||||
if (this->check_socket_write_err_(errno) != APIError::WOULD_BLOCK)
|
||||
return APIError::SOCKET_WRITE_FAILED;
|
||||
}
|
||||
return APIError::OK;
|
||||
}
|
||||
// Drain backlogged overflow data to the socket and handle errors.
|
||||
// Called when overflow_buf_.empty() is false. Out-of-line to keep the
|
||||
// fast path (empty check) inline at call sites.
|
||||
// Returns OK for transient errors (WOULD_BLOCK), SOCKET_WRITE_FAILED for hard errors.
|
||||
APIError drain_overflow_and_handle_errors_();
|
||||
|
||||
// Common implementation for writing raw data to socket
|
||||
APIError write_raw_(const struct iovec *iov, int iovcnt, uint16_t total_write_len);
|
||||
|
||||
@@ -153,11 +153,12 @@ APIError APINoiseFrameHelper::loop() {
|
||||
}
|
||||
}
|
||||
|
||||
APIError err = this->try_drain_overflow_buffer_();
|
||||
if (err != APIError::OK) {
|
||||
HELPER_LOG("Overflow drain failed with errno %d", errno);
|
||||
if (!this->overflow_buf_.empty()) [[unlikely]] {
|
||||
APIError err = this->drain_overflow_and_handle_errors_();
|
||||
if (err != APIError::OK)
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
return APIError::OK;
|
||||
}
|
||||
|
||||
/** Read a packet into the rx_buf_.
|
||||
|
||||
@@ -64,11 +64,12 @@ APIError APIPlaintextFrameHelper::loop() {
|
||||
if (state_ != State::DATA) {
|
||||
return APIError::BAD_STATE;
|
||||
}
|
||||
APIError err = this->try_drain_overflow_buffer_();
|
||||
if (err != APIError::OK) {
|
||||
HELPER_LOG("Overflow drain failed with errno %d", errno);
|
||||
if (!this->overflow_buf_.empty()) [[unlikely]] {
|
||||
APIError err = this->drain_overflow_and_handle_errors_();
|
||||
if (err != APIError::OK)
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
return APIError::OK;
|
||||
}
|
||||
|
||||
/** Read a packet into the rx_buf_.
|
||||
|
||||
Reference in New Issue
Block a user