[api] Use static constexpr HEADER_PADDING instead of loading member field

The header padding is a compile-time constant per protocol (6 for
plaintext, 7 for noise). Using constexpr eliminates memory loads
on the hot path. The value is defined once per class with the
component breakdown in the comment.
This commit is contained in:
J. Nick Koston
2026-03-29 14:32:47 -10:00
parent a19a6f2a0e
commit ccafd442a7
4 changed files with 22 additions and 21 deletions
@@ -497,8 +497,7 @@ APIError APINoiseFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuff
if (frame_footer_size_)
buffer.get_buffer()->resize(buffer.get_buffer()->size() + frame_footer_size_);
MessageInfo msg{type, 0,
static_cast<uint16_t>(buffer.get_buffer()->size() - frame_header_padding_ - frame_footer_size_)};
MessageInfo msg{type, 0, static_cast<uint16_t>(buffer.get_buffer()->size() - HEADER_PADDING - frame_footer_size_)};
uint8_t *buf_start = buffer.get_buffer()->data();
struct iovec iov;
APIError aerr = this->encrypt_noise_message_(buf_start, msg, iov);
@@ -9,14 +9,16 @@ namespace esphome::api {
class APINoiseFrameHelper final : public APIFrameHelper {
public:
// Noise header structure:
// Pos 0: indicator (0x01)
// Pos 1-2: encrypted payload size (16-bit big-endian)
// Pos 3-6: encrypted type (16-bit) + data_len (16-bit)
// Pos 7+: actual payload data
static constexpr uint8_t HEADER_PADDING = 1 + 2 + 2 + 2; // indicator + size + type + data_len
APINoiseFrameHelper(std::unique_ptr<socket::Socket> socket, APINoiseContext &ctx)
: APIFrameHelper(std::move(socket)), ctx_(ctx) {
// Noise header structure:
// Pos 0: indicator (0x01)
// Pos 1-2: encrypted payload size (16-bit big-endian)
// Pos 3-6: encrypted type (16-bit) + data_len (16-bit)
// Pos 7+: actual payload data
frame_header_padding_ = 7;
frame_header_padding_ = HEADER_PADDING;
}
~APINoiseFrameHelper() override;
APIError init() override;
@@ -287,10 +287,10 @@ APIError APIPlaintextFrameHelper::write_protobuf_packet(uint8_t type, ProtoWrite
assert(this->state_ == State::DATA);
#endif
MessageInfo msg{type, 0, static_cast<uint16_t>(buffer.get_buffer()->size() - frame_header_padding_)};
MessageInfo msg{type, 0, static_cast<uint16_t>(buffer.get_buffer()->size() - HEADER_PADDING)};
uint8_t *buffer_data = buffer.get_buffer()->data();
uint8_t header_len = write_plaintext_header(buffer_data, msg, frame_header_padding_);
uint8_t *msg_start = buffer_data + frame_header_padding_ - header_len;
uint8_t header_len = write_plaintext_header(buffer_data, msg, HEADER_PADDING);
uint8_t *msg_start = buffer_data + HEADER_PADDING - header_len;
uint16_t msg_len = static_cast<uint16_t>(header_len + msg.payload_size);
LOG_PACKET_SENDING(msg_start, msg_len);
return this->write_raw_fast_buf_(msg_start, msg_len);
@@ -302,15 +302,13 @@ APIError APIPlaintextFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffe
assert(this->state_ == State::DATA);
assert(!messages.empty());
#endif
uint8_t *buffer_data = buffer.get_buffer()->data();
StaticVector<struct iovec, MAX_MESSAGES_PER_BATCH> iovs;
uint16_t total_write_len = 0;
const uint8_t padding = frame_header_padding_;
for (const auto &msg : messages) {
uint8_t header_len = write_plaintext_header(buffer_data + msg.offset, msg, padding);
uint8_t *msg_start = buffer_data + msg.offset + padding - header_len;
uint8_t header_len = write_plaintext_header(buffer_data + msg.offset, msg, HEADER_PADDING);
uint8_t *msg_start = buffer_data + msg.offset + HEADER_PADDING - header_len;
size_t msg_len = static_cast<size_t>(header_len + msg.payload_size);
iovs.push_back({msg_start, msg_len});
total_write_len += msg_len;
@@ -7,13 +7,15 @@ namespace esphome::api {
class APIPlaintextFrameHelper final : public APIFrameHelper {
public:
// Plaintext header structure (worst case):
// Pos 0: indicator (0x00)
// Pos 1-3: payload size varint (up to 3 bytes)
// Pos 4-5: message type varint (up to 2 bytes)
// Pos 6+: actual payload data
static constexpr uint8_t HEADER_PADDING = 1 + 3 + 2; // indicator + size varint + type varint
explicit APIPlaintextFrameHelper(std::unique_ptr<socket::Socket> socket) : APIFrameHelper(std::move(socket)) {
// Plaintext header structure (worst case):
// Pos 0: indicator (0x00)
// Pos 1-3: payload size varint (up to 3 bytes)
// Pos 4-5: message type varint (up to 2 bytes)
// Pos 6+: actual payload data
frame_header_padding_ = 6;
frame_header_padding_ = HEADER_PADDING;
}
~APIPlaintextFrameHelper() override = default;
APIError init() override;