Read the noise handshake frame in one loop

This commit is contained in:
J. Nick Koston
2026-09-05 11:52:45 +02:00
parent d6176bcb7d
commit 4f7ba7fa29
@@ -41,7 +41,9 @@ ESPHomeOTAComponent::NoiseSession::~NoiseSession() {
*/
bool ESPHomeOTAComponent::noise_start_session_(uint8_t server_feature_flags) {
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
this->noise_ = std::unique_ptr<NoiseSession>(new (std::nothrow) NoiseSession());
// Default-init: the frame buffer is always written before it is read, so
// skip zeroing its 132 bytes
this->noise_ = std::unique_ptr<NoiseSession>(new (std::nothrow) NoiseSession);
static constexpr size_t PROLOGUE_ACK_LEN = 2; // OTA_RESPONSE_OK + version
static constexpr size_t PROLOGUE_CLIENT_FEATURES_LEN = 1;
static constexpr size_t PROLOGUE_FEATURE_ACK_LEN = 2; // OTA_RESPONSE_FEATURE_FLAGS + server flags
@@ -165,14 +167,20 @@ size_t ESPHomeOTAComponent::noise_frame_payload_len_(const uint8_t *header, size
/// Non-blocking read of one handshake frame into the session buffer.
bool ESPHomeOTAComponent::noise_try_read_frame_() {
NoiseSession &s = *this->noise_;
while (s.frame_pos < noise::FRAME_HEADER_SIZE) {
ssize_t read = this->client_->read(s.frame_buf + s.frame_pos, noise::FRAME_HEADER_SIZE - s.frame_pos);
if (!this->handle_read_error_(read, LOG_STR("read noise"))) {
return false;
while (true) {
// The header first, then the body once the header says how long it is
const uint16_t want = s.frame_len == 0 ? noise::FRAME_HEADER_SIZE : s.frame_len;
if (s.frame_pos < want) {
ssize_t read = this->client_->read(s.frame_buf + s.frame_pos, want - s.frame_pos);
if (!this->handle_read_error_(read, LOG_STR("read noise"))) {
return false;
}
s.frame_pos += read;
continue;
}
if (s.frame_len != 0) {
return true;
}
s.frame_pos += read;
}
if (s.frame_len == 0) {
const size_t payload_len = this->noise_frame_payload_len_(s.frame_buf, 1, 1 + noise::MAX_HANDSHAKE_SIZE);
if (payload_len == 0) {
this->cleanup_connection_();
@@ -180,14 +188,6 @@ bool ESPHomeOTAComponent::noise_try_read_frame_() {
}
s.frame_len = noise::FRAME_HEADER_SIZE + payload_len;
}
while (s.frame_pos < s.frame_len) {
ssize_t read = this->client_->read(s.frame_buf + s.frame_pos, s.frame_len - s.frame_pos);
if (!this->handle_read_error_(read, LOG_STR("read noise"))) {
return false;
}
s.frame_pos += read;
}
return true;
}
/// Non-blocking write of the pending session-buffer frame.