Merge branch 'implement_buffer_queue' into frame_helper_optimize_cleanup_api
This commit is contained in:
@@ -91,12 +91,14 @@ APIError APIFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) {
|
||||
// Try to send the remaining data in this buffer
|
||||
ssize_t sent = this->socket_->write(front_buffer.current_data(), front_buffer.remaining());
|
||||
|
||||
if (this->is_would_block(sent)) {
|
||||
// Socket would block, we'll try again later
|
||||
} else if (sent == -1) {
|
||||
ESP_LOGVV(TAG, "%s: Socket write failed with errno %d", this->info_.c_str(), errno);
|
||||
this->state_ = State::FAILED;
|
||||
return APIError::SOCKET_WRITE_FAILED; // Socket write failed
|
||||
if (sent == -1) {
|
||||
if (errno != EWOULDBLOCK && errno != EAGAIN) {
|
||||
// Real socket error (not just would block)
|
||||
ESP_LOGVV(TAG, "%s: Socket write failed with errno %d", this->info_.c_str(), errno);
|
||||
this->state_ = State::FAILED;
|
||||
return APIError::SOCKET_WRITE_FAILED; // Socket write failed
|
||||
}
|
||||
// Socket would block, we'll try again later and continue execution to append new data to the buffer
|
||||
} else if (sent > 0 && static_cast<size_t>(sent) < front_buffer.remaining()) {
|
||||
// Partially sent, update offset
|
||||
front_buffer.offset += sent;
|
||||
@@ -129,19 +131,20 @@ APIError APIFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) {
|
||||
// Try to send directly if no buffered data
|
||||
ssize_t sent = this->socket_->writev(iov, iovcnt);
|
||||
|
||||
if (this->is_would_block(sent)) {
|
||||
// Socket would block, buffer the data
|
||||
SendBuffer buffer;
|
||||
buffer.data.reserve(total_write_len);
|
||||
if (sent == -1) {
|
||||
if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
||||
// Socket would block, buffer the data
|
||||
SendBuffer buffer;
|
||||
buffer.data.reserve(total_write_len);
|
||||
|
||||
for (int i = 0; i < iovcnt; i++) {
|
||||
const uint8_t *data = reinterpret_cast<uint8_t *>(iov[i].iov_base);
|
||||
buffer.data.insert(buffer.data.end(), data, data + iov[i].iov_len);
|
||||
for (int i = 0; i < iovcnt; i++) {
|
||||
const uint8_t *data = reinterpret_cast<uint8_t *>(iov[i].iov_base);
|
||||
buffer.data.insert(buffer.data.end(), data, data + iov[i].iov_len);
|
||||
}
|
||||
|
||||
this->tx_buf_.push_back(std::move(buffer));
|
||||
return APIError::OK; // Success, data buffered
|
||||
}
|
||||
|
||||
this->tx_buf_.push_back(std::move(buffer));
|
||||
return APIError::OK; // Success, data buffered
|
||||
} else if (sent == -1) {
|
||||
// Socket error
|
||||
ESP_LOGVV(TAG, "%s: Socket write failed with errno %d", this->info_.c_str(), errno);
|
||||
this->state_ = State::FAILED;
|
||||
@@ -184,10 +187,11 @@ APIError APIFrameHelper::try_send_tx_buf_() {
|
||||
// Try to send the remaining data in this buffer
|
||||
ssize_t sent = this->socket_->write(front_buffer.current_data(), front_buffer.remaining());
|
||||
|
||||
if (this->is_would_block(sent)) {
|
||||
// Socket would block, try again later
|
||||
break;
|
||||
} else if (sent == -1) {
|
||||
if (sent == -1) {
|
||||
if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
||||
// Socket would block, try again later
|
||||
break;
|
||||
}
|
||||
// Socket error
|
||||
state_ = State::FAILED;
|
||||
ESP_LOGVV(TAG, "%s: Socket write failed with errno %d", this->info_.c_str(), errno);
|
||||
|
||||
@@ -164,14 +164,6 @@ class APIFrameHelper {
|
||||
|
||||
// Try to send data from the tx buffer
|
||||
APIError try_send_tx_buf_();
|
||||
|
||||
// Check if the socket would block based on return value
|
||||
inline bool is_would_block(ssize_t ret) const {
|
||||
if (ret == -1) {
|
||||
return errno == EWOULDBLOCK || errno == EAGAIN;
|
||||
}
|
||||
return ret == 0;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef USE_API_NOISE
|
||||
|
||||
@@ -20,16 +20,26 @@ class ProtoVarInt {
|
||||
explicit ProtoVarInt(uint64_t value) : value_(value) {}
|
||||
|
||||
static optional<ProtoVarInt> parse(const uint8_t *buffer, uint32_t len, uint32_t *consumed) {
|
||||
if (consumed != nullptr)
|
||||
*consumed = 0;
|
||||
|
||||
if (len == 0)
|
||||
if (len == 0) {
|
||||
if (consumed != nullptr)
|
||||
*consumed = 0;
|
||||
return {};
|
||||
}
|
||||
|
||||
uint64_t result = 0;
|
||||
uint8_t bitpos = 0;
|
||||
// Most common case: single-byte varint (values 0-127)
|
||||
if ((buffer[0] & 0x80) == 0) {
|
||||
if (consumed != nullptr)
|
||||
*consumed = 1;
|
||||
return ProtoVarInt(buffer[0]);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
// General case for multi-byte varints
|
||||
// Since we know buffer[0]'s high bit is set, initialize with its value
|
||||
uint64_t result = buffer[0] & 0x7F;
|
||||
uint8_t bitpos = 7;
|
||||
|
||||
// Start from the second byte since we've already processed the first
|
||||
for (uint32_t i = 1; i < len; i++) {
|
||||
uint8_t val = buffer[i];
|
||||
result |= uint64_t(val & 0x7F) << uint64_t(bitpos);
|
||||
bitpos += 7;
|
||||
@@ -40,7 +50,9 @@ class ProtoVarInt {
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
if (consumed != nullptr)
|
||||
*consumed = 0;
|
||||
return {}; // Incomplete or invalid varint
|
||||
}
|
||||
|
||||
uint32_t as_uint32() const { return this->value_; }
|
||||
|
||||
@@ -19,7 +19,7 @@ puremagic==1.29
|
||||
ruamel.yaml==0.18.10 # dashboard_import
|
||||
esphome-glyphsets==0.2.0
|
||||
pillow==10.4.0
|
||||
cairosvg==2.8.0
|
||||
cairosvg==2.8.1
|
||||
freetype-py==2.5.1
|
||||
|
||||
# esp-idf requires this, but doesn't bundle it by default
|
||||
|
||||
Reference in New Issue
Block a user