1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-20 02:33:50 +01:00

[api] Optimize frame helpers to eliminate double-move overhead

This commit is contained in:
J. Nick Koston
2025-10-06 17:27:05 -05:00
parent 1cf5290f28
commit 517f59afe4
2 changed files with 16 additions and 4 deletions

View File

@@ -133,6 +133,9 @@ APIError APINoiseFrameHelper::loop() {
} }
/** Read a packet into the rx_buf_. /** Read a packet into the rx_buf_.
*
* On success, rx_buf_ contains the frame data and state variables are cleared for the next read.
* Caller is responsible for consuming rx_buf_ (e.g., via std::move).
* *
* @return APIError::OK if a full packet is in rx_buf_ * @return APIError::OK if a full packet is in rx_buf_
* *
@@ -142,6 +145,11 @@ APIError APINoiseFrameHelper::loop() {
* errno API_ERROR_HANDSHAKE_PACKET_LEN: Packet too big for this phase. * errno API_ERROR_HANDSHAKE_PACKET_LEN: Packet too big for this phase.
*/ */
APIError APINoiseFrameHelper::try_read_frame_() { APIError APINoiseFrameHelper::try_read_frame_() {
// Clear buffer when starting a new frame (rx_buf_len_ == 0 means not resuming after WOULD_BLOCK)
if (this->rx_buf_len_ == 0) {
this->rx_buf_.clear();
}
// read header // read header
if (rx_header_buf_len_ < 3) { if (rx_header_buf_len_ < 3) {
// no header information yet // no header information yet
@@ -240,7 +248,6 @@ APIError APINoiseFrameHelper::state_action_() {
this->prologue_[old_size] = (uint8_t) (this->rx_buf_.size() >> 8); this->prologue_[old_size] = (uint8_t) (this->rx_buf_.size() >> 8);
this->prologue_[old_size + 1] = (uint8_t) this->rx_buf_.size(); this->prologue_[old_size + 1] = (uint8_t) this->rx_buf_.size();
std::memcpy(this->prologue_.data() + old_size + 2, this->rx_buf_.data(), this->rx_buf_.size()); std::memcpy(this->prologue_.data() + old_size + 2, this->rx_buf_.data(), this->rx_buf_.size());
this->rx_buf_.clear();
state_ = State::SERVER_HELLO; state_ = State::SERVER_HELLO;
} }
@@ -307,7 +314,6 @@ APIError APINoiseFrameHelper::state_action_() {
return handle_noise_error_(err, LOG_STR("noise_handshakestate_read_message"), return handle_noise_error_(err, LOG_STR("noise_handshakestate_read_message"),
APIError::HANDSHAKESTATE_READ_FAILED); APIError::HANDSHAKESTATE_READ_FAILED);
} }
this->rx_buf_.clear();
aerr = check_handshake_finished_(); aerr = check_handshake_finished_();
if (aerr != APIError::OK) if (aerr != APIError::OK)
@@ -419,7 +425,6 @@ APIError APINoiseFrameHelper::read_packet(ReadPacketBuffer *buffer) {
buffer->data_offset = 4; buffer->data_offset = 4;
buffer->data_len = data_len; buffer->data_len = data_len;
buffer->type = type; buffer->type = type;
this->rx_buf_.clear();
return APIError::OK; return APIError::OK;
} }
APIError APINoiseFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) { APIError APINoiseFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) {

View File

@@ -48,12 +48,20 @@ APIError APIPlaintextFrameHelper::loop() {
} }
/** Read a packet into the rx_buf_. /** Read a packet into the rx_buf_.
*
* On success, rx_buf_ contains the frame data and state variables are cleared for the next read.
* Caller is responsible for consuming rx_buf_ (e.g., via std::move).
* *
* @return See APIError * @return See APIError
* *
* error API_ERROR_BAD_INDICATOR: Bad indicator byte at start of frame. * error API_ERROR_BAD_INDICATOR: Bad indicator byte at start of frame.
*/ */
APIError APIPlaintextFrameHelper::try_read_frame_() { APIError APIPlaintextFrameHelper::try_read_frame_() {
// Clear buffer when starting a new frame (rx_buf_len_ == 0 means not resuming after WOULD_BLOCK)
if (this->rx_buf_len_ == 0) {
this->rx_buf_.clear();
}
// read header // read header
while (!rx_header_parsed_) { while (!rx_header_parsed_) {
// Now that we know when the socket is ready, we can read up to 3 bytes // Now that we know when the socket is ready, we can read up to 3 bytes
@@ -214,7 +222,6 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
buffer->data_offset = 0; buffer->data_offset = 0;
buffer->data_len = this->rx_header_parsed_len_; buffer->data_len = this->rx_header_parsed_len_;
buffer->type = this->rx_header_parsed_type_; buffer->type = this->rx_header_parsed_type_;
this->rx_buf_.clear();
return APIError::OK; return APIError::OK;
} }
APIError APIPlaintextFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) { APIError APIPlaintextFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) {