1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-15 09:42:19 +01:00

Fix footer space not being reserved for batched messages

This only affects noise protocol, and its not a correctness issue, its only
fixing an inefficent reserve
This commit is contained in:
J. Nick Koston
2025-06-13 15:54:31 -05:00
parent 02469c2d4c
commit fdfbb3e944
2 changed files with 24 additions and 26 deletions

View File

@@ -252,8 +252,12 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint16_t mes
msg.calculate_size(size);
// Calculate total size with padding for buffer allocation
uint16_t total_size =
static_cast<uint16_t>(size) + conn->helper_->frame_header_padding() + conn->helper_->frame_footer_size();
uint32_t total_size = size + conn->helper_->frame_header_padding() + conn->helper_->frame_footer_size();
// Check if total size fits in uint16_t (API messages are limited to 64KB)
if (total_size > std::numeric_limits<uint16_t>::max()) {
return 0; // Message too large
}
// Check if it fits
if (total_size > remaining_size) {
@@ -266,7 +270,7 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint16_t mes
// Encode directly into buffer
msg.encode(buffer);
return total_size;
return static_cast<uint16_t>(total_size); // Safe cast - we checked the size above
}
#ifdef USE_BINARY_SENSOR

View File

@@ -240,8 +240,8 @@ class APIConnection : public APIServerConnection {
// - Header padding: space for protocol headers (7 bytes for Noise, 6 for Plaintext)
// - Footer: space for MAC (16 bytes for Noise, 0 for Plaintext)
shared_buf.reserve(reserve_size + header_padding + this->helper_->frame_footer_size());
// Insert header padding bytes so message encoding starts at the correct position
shared_buf.insert(shared_buf.begin(), header_padding, 0);
// Resize to add header padding so message encoding starts at the correct position
shared_buf.resize(header_padding);
return {&shared_buf};
}
@@ -249,32 +249,26 @@ class APIConnection : public APIServerConnection {
ProtoWriteBuffer prepare_message_buffer(uint16_t message_size, bool is_first_message) {
// Get reference to shared buffer (it maintains state between batch messages)
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
size_t current_size = shared_buf.size();
if (is_first_message) {
// For first message, initialize buffer with header padding
uint8_t header_padding = this->helper_->frame_header_padding();
shared_buf.clear();
shared_buf.reserve(message_size + header_padding);
shared_buf.resize(header_padding);
// Fill header padding with zeros
std::fill(shared_buf.begin(), shared_buf.end(), 0);
} else {
// For subsequent messages, add footer space for previous message and header for this message
uint8_t footer_size = this->helper_->frame_footer_size();
uint8_t header_padding = this->helper_->frame_header_padding();
// Reserve additional space for everything
shared_buf.reserve(current_size + footer_size + header_padding + message_size);
// Single resize to add both footer and header padding
size_t new_size = current_size + footer_size + header_padding;
shared_buf.resize(new_size);
// Fill the newly added bytes with zeros (footer + header padding)
std::fill(shared_buf.begin() + current_size, shared_buf.end(), 0);
}
size_t current_size = shared_buf.size();
// Calculate padding to add:
// - First message: just header padding
// - Subsequent messages: footer for previous message + header padding for this message
size_t padding_to_add = is_first_message
? this->helper_->frame_header_padding()
: this->helper_->frame_header_padding() + this->helper_->frame_footer_size();
// Reserve space for padding + message
shared_buf.reserve(current_size + padding_to_add + message_size);
// Resize to add the padding bytes
shared_buf.resize(current_size + padding_to_add);
return {&shared_buf};
}