mirror of
https://github.com/esphome/esphome.git
synced 2026-09-16 17:48:40 +00:00
[api] Skip state_action_() call in noise data path
The noise frame helper was calling state_action_() (447 bytes) on every read_packet() and write_protobuf_messages() call. In the DATA state (steady-state after handshake), this function falls through all handshake checks and returns OK — pure overhead on every encrypted packet. Add check_data_state_() inline helper that replaces the call with a single byte-load + branch instruction in the hot path. The handshake state machine continues to be driven by loop() as before. Also applies consistent state checking to the plaintext frame helper.
This commit is contained in:
@@ -232,6 +232,17 @@ class APIFrameHelper {
|
||||
EXPLICIT_REJECT = 8, // Noise only
|
||||
};
|
||||
|
||||
// Fast inline check for read_packet/write_protobuf_messages hot path.
|
||||
// In DATA state, state_action_() is a no-op (falls through all checks to return OK).
|
||||
// This avoids a 447-byte function call on every packet during normal operation.
|
||||
inline APIError ESPHOME_ALWAYS_INLINE check_data_state_() const {
|
||||
if (state_ == State::DATA)
|
||||
return APIError::OK;
|
||||
if (state_ == State::CLOSED || state_ == State::FAILED)
|
||||
return APIError::BAD_STATE;
|
||||
return APIError::WOULD_BLOCK;
|
||||
}
|
||||
|
||||
// Containers (size varies, but typically 12+ bytes on 32-bit)
|
||||
std::array<std::unique_ptr<SendBuffer>, API_MAX_SEND_QUEUE> tx_buf_;
|
||||
std::vector<uint8_t> rx_buf_;
|
||||
|
||||
@@ -397,14 +397,9 @@ void APINoiseFrameHelper::send_explicit_handshake_reject_(const LogString *reaso
|
||||
state_ = orig_state;
|
||||
}
|
||||
APIError APINoiseFrameHelper::read_packet(ReadPacketBuffer *buffer) {
|
||||
APIError aerr = this->state_action_();
|
||||
if (aerr != APIError::OK) {
|
||||
APIError aerr = this->check_data_state_();
|
||||
if (aerr != APIError::OK)
|
||||
return aerr;
|
||||
}
|
||||
|
||||
if (this->state_ != State::DATA) {
|
||||
return APIError::WOULD_BLOCK;
|
||||
}
|
||||
|
||||
aerr = this->try_read_frame_();
|
||||
if (aerr != APIError::OK)
|
||||
@@ -461,14 +456,9 @@ APIError APINoiseFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuff
|
||||
}
|
||||
|
||||
APIError APINoiseFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffer, std::span<const MessageInfo> messages) {
|
||||
APIError aerr = state_action_();
|
||||
if (aerr != APIError::OK) {
|
||||
APIError aerr = this->check_data_state_();
|
||||
if (aerr != APIError::OK)
|
||||
return aerr;
|
||||
}
|
||||
|
||||
if (state_ != State::DATA) {
|
||||
return APIError::WOULD_BLOCK;
|
||||
}
|
||||
|
||||
if (messages.empty()) {
|
||||
return APIError::OK;
|
||||
|
||||
@@ -195,11 +195,11 @@ APIError APIPlaintextFrameHelper::try_read_frame_() {
|
||||
}
|
||||
|
||||
APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
|
||||
if (this->state_ != State::DATA) {
|
||||
return APIError::WOULD_BLOCK;
|
||||
}
|
||||
APIError aerr = this->check_data_state_();
|
||||
if (aerr != APIError::OK)
|
||||
return aerr;
|
||||
|
||||
APIError aerr = this->try_read_frame_();
|
||||
aerr = this->try_read_frame_();
|
||||
if (aerr != APIError::OK) {
|
||||
if (aerr == APIError::BAD_INDICATOR) {
|
||||
// Make sure to tell the remote that we don't
|
||||
@@ -244,9 +244,9 @@ APIError APIPlaintextFrameHelper::write_protobuf_packet(uint8_t type, ProtoWrite
|
||||
|
||||
APIError APIPlaintextFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffer,
|
||||
std::span<const MessageInfo> messages) {
|
||||
if (state_ != State::DATA) {
|
||||
return APIError::BAD_STATE;
|
||||
}
|
||||
APIError aerr = this->check_data_state_();
|
||||
if (aerr != APIError::OK)
|
||||
return aerr;
|
||||
|
||||
if (messages.empty()) {
|
||||
return APIError::OK;
|
||||
|
||||
Reference in New Issue
Block a user