mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Merge branch 'api_cleanups_2' into integration
This commit is contained in:
		| @@ -76,6 +76,16 @@ APIError APIFrameHelper::loop() { | |||||||
|   return APIError::OK;  // Convert WOULD_BLOCK to OK to avoid connection termination |   return APIError::OK;  // Convert WOULD_BLOCK to OK to avoid connection termination | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Common socket write error handling | ||||||
|  | APIError APIFrameHelper::handle_socket_write_error_() { | ||||||
|  |   if (errno == EWOULDBLOCK || errno == EAGAIN) { | ||||||
|  |     return APIError::WOULD_BLOCK; | ||||||
|  |   } | ||||||
|  |   ESP_LOGVV(TAG, "%s: Socket write failed with errno %d", this->info_.c_str(), errno); | ||||||
|  |   this->state_ = State::FAILED; | ||||||
|  |   return APIError::SOCKET_WRITE_FAILED; | ||||||
|  | } | ||||||
|  |  | ||||||
| // Helper method to buffer data from IOVs | // Helper method to buffer data from IOVs | ||||||
| void APIFrameHelper::buffer_data_from_iov_(const struct iovec *iov, int iovcnt, uint16_t total_write_len, | void APIFrameHelper::buffer_data_from_iov_(const struct iovec *iov, int iovcnt, uint16_t total_write_len, | ||||||
|                                            uint16_t offset) { |                                            uint16_t offset) { | ||||||
| @@ -137,15 +147,13 @@ APIError APIFrameHelper::write_raw_(const struct iovec *iov, int iovcnt, uint16_ | |||||||
|   ssize_t sent = this->socket_->writev(iov, iovcnt); |   ssize_t sent = this->socket_->writev(iov, iovcnt); | ||||||
|  |  | ||||||
|   if (sent == -1) { |   if (sent == -1) { | ||||||
|     if (errno == EWOULDBLOCK || errno == EAGAIN) { |     APIError err = this->handle_socket_write_error_(); | ||||||
|  |     if (err == APIError::WOULD_BLOCK) { | ||||||
|       // Socket would block, buffer the data |       // Socket would block, buffer the data | ||||||
|       this->buffer_data_from_iov_(iov, iovcnt, total_write_len, 0); |       this->buffer_data_from_iov_(iov, iovcnt, total_write_len, 0); | ||||||
|       return APIError::OK;  // Success, data buffered |       return APIError::OK;  // Success, data buffered | ||||||
|     } |     } | ||||||
|     // Socket error |     return err;  // Socket write failed | ||||||
|     ESP_LOGVV(TAG, "%s: Socket write failed with errno %d", this->info_.c_str(), errno); |  | ||||||
|     this->state_ = State::FAILED; |  | ||||||
|     return APIError::SOCKET_WRITE_FAILED;  // Socket write failed |  | ||||||
|   } else if (static_cast<uint16_t>(sent) < total_write_len) { |   } else if (static_cast<uint16_t>(sent) < total_write_len) { | ||||||
|     // Partially sent, buffer the remaining data |     // Partially sent, buffer the remaining data | ||||||
|     this->buffer_data_from_iov_(iov, iovcnt, total_write_len, static_cast<uint16_t>(sent)); |     this->buffer_data_from_iov_(iov, iovcnt, total_write_len, static_cast<uint16_t>(sent)); | ||||||
| @@ -167,14 +175,7 @@ APIError APIFrameHelper::try_send_tx_buf_() { | |||||||
|     ssize_t sent = this->socket_->write(front_buffer.current_data(), front_buffer.remaining()); |     ssize_t sent = this->socket_->write(front_buffer.current_data(), front_buffer.remaining()); | ||||||
|  |  | ||||||
|     if (sent == -1) { |     if (sent == -1) { | ||||||
|       if (errno != EWOULDBLOCK && errno != EAGAIN) { |       return this->handle_socket_write_error_(); | ||||||
|         // Real socket error (not just would block) |  | ||||||
|         ESP_LOGVV(TAG, "%s: Socket write failed with errno %d", this->info_.c_str(), errno); |  | ||||||
|         this->state_ = State::FAILED; |  | ||||||
|         return APIError::SOCKET_WRITE_FAILED;  // Socket write failed |  | ||||||
|       } |  | ||||||
|       // Socket would block, we'll try again later |  | ||||||
|       return APIError::WOULD_BLOCK; |  | ||||||
|     } else if (sent == 0) { |     } else if (sent == 0) { | ||||||
|       // Nothing sent but not an error |       // Nothing sent but not an error | ||||||
|       return APIError::WOULD_BLOCK; |       return APIError::WOULD_BLOCK; | ||||||
| @@ -292,6 +293,29 @@ APIError APINoiseFrameHelper::init() { | |||||||
|   state_ = State::CLIENT_HELLO; |   state_ = State::CLIENT_HELLO; | ||||||
|   return APIError::OK; |   return APIError::OK; | ||||||
| } | } | ||||||
|  | // Helper for handling handshake frame errors | ||||||
|  | APIError APINoiseFrameHelper::handle_handshake_frame_error_(APIError aerr) { | ||||||
|  |   if (aerr == APIError::BAD_INDICATOR) { | ||||||
|  |     send_explicit_handshake_reject_("Bad indicator byte"); | ||||||
|  |     return aerr; | ||||||
|  |   } | ||||||
|  |   if (aerr == APIError::BAD_HANDSHAKE_PACKET_LEN) { | ||||||
|  |     send_explicit_handshake_reject_("Bad handshake packet len"); | ||||||
|  |     return aerr; | ||||||
|  |   } | ||||||
|  |   return aerr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Helper for handling noise library errors | ||||||
|  | APIError APINoiseFrameHelper::handle_noise_error_(int err, const char *func_name, APIError api_err) { | ||||||
|  |   if (err != 0) { | ||||||
|  |     state_ = State::FAILED; | ||||||
|  |     HELPER_LOG("%s failed: %s", func_name, noise_err_to_str(err).c_str()); | ||||||
|  |     return api_err; | ||||||
|  |   } | ||||||
|  |   return APIError::OK; | ||||||
|  | } | ||||||
|  |  | ||||||
| /// Run through handshake messages (if in that phase) | /// Run through handshake messages (if in that phase) | ||||||
| APIError APINoiseFrameHelper::loop() { | APIError APINoiseFrameHelper::loop() { | ||||||
|   // During handshake phase, process as many actions as possible until we can't progress |   // During handshake phase, process as many actions as possible until we can't progress | ||||||
| @@ -299,12 +323,12 @@ APIError APINoiseFrameHelper::loop() { | |||||||
|   // WOULD_BLOCK when no more data is available to read |   // WOULD_BLOCK when no more data is available to read | ||||||
|   while (state_ != State::DATA && this->socket_->ready()) { |   while (state_ != State::DATA && this->socket_->ready()) { | ||||||
|     APIError err = state_action_(); |     APIError err = state_action_(); | ||||||
|     if (err != APIError::OK && err != APIError::WOULD_BLOCK) { |  | ||||||
|       return err; |  | ||||||
|     } |  | ||||||
|     if (err == APIError::WOULD_BLOCK) { |     if (err == APIError::WOULD_BLOCK) { | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|  |     if (err != APIError::OK) { | ||||||
|  |       return err; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Use base class implementation for buffer sending |   // Use base class implementation for buffer sending | ||||||
| @@ -325,7 +349,7 @@ APIError APINoiseFrameHelper::loop() { | |||||||
|  * errno API_ERROR_BAD_INDICATOR: Bad indicator byte at start of frame. |  * errno API_ERROR_BAD_INDICATOR: Bad indicator byte at start of frame. | ||||||
|  * 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_(ParsedFrame *frame) { | APIError APINoiseFrameHelper::try_read_frame_(std::vector<uint8_t> *frame) { | ||||||
|   if (frame == nullptr) { |   if (frame == nullptr) { | ||||||
|     HELPER_LOG("Bad argument for try_read_frame_"); |     HELPER_LOG("Bad argument for try_read_frame_"); | ||||||
|     return APIError::BAD_ARG; |     return APIError::BAD_ARG; | ||||||
| @@ -388,7 +412,7 @@ APIError APINoiseFrameHelper::try_read_frame_(ParsedFrame *frame) { | |||||||
| #ifdef HELPER_LOG_PACKETS | #ifdef HELPER_LOG_PACKETS | ||||||
|   ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(rx_buf_).c_str()); |   ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(rx_buf_).c_str()); | ||||||
| #endif | #endif | ||||||
|   frame->msg = std::move(rx_buf_); |   *frame = std::move(rx_buf_); | ||||||
|   // consume msg |   // consume msg | ||||||
|   rx_buf_ = {}; |   rx_buf_ = {}; | ||||||
|   rx_buf_len_ = 0; |   rx_buf_len_ = 0; | ||||||
| @@ -414,24 +438,17 @@ APIError APINoiseFrameHelper::state_action_() { | |||||||
|   } |   } | ||||||
|   if (state_ == State::CLIENT_HELLO) { |   if (state_ == State::CLIENT_HELLO) { | ||||||
|     // waiting for client hello |     // waiting for client hello | ||||||
|     ParsedFrame frame; |     std::vector<uint8_t> frame; | ||||||
|     aerr = try_read_frame_(&frame); |     aerr = try_read_frame_(&frame); | ||||||
|     if (aerr == APIError::BAD_INDICATOR) { |     if (aerr != APIError::OK) { | ||||||
|       send_explicit_handshake_reject_("Bad indicator byte"); |       return handle_handshake_frame_error_(aerr); | ||||||
|       return aerr; |  | ||||||
|     } |     } | ||||||
|     if (aerr == APIError::BAD_HANDSHAKE_PACKET_LEN) { |  | ||||||
|       send_explicit_handshake_reject_("Bad handshake packet len"); |  | ||||||
|       return aerr; |  | ||||||
|     } |  | ||||||
|     if (aerr != APIError::OK) |  | ||||||
|       return aerr; |  | ||||||
|     // ignore contents, may be used in future for flags |     // ignore contents, may be used in future for flags | ||||||
|     // Reserve space for: existing prologue + 2 size bytes + frame data |     // Reserve space for: existing prologue + 2 size bytes + frame data | ||||||
|     prologue_.reserve(prologue_.size() + 2 + frame.msg.size()); |     prologue_.reserve(prologue_.size() + 2 + frame.size()); | ||||||
|     prologue_.push_back((uint8_t) (frame.msg.size() >> 8)); |     prologue_.push_back((uint8_t) (frame.size() >> 8)); | ||||||
|     prologue_.push_back((uint8_t) frame.msg.size()); |     prologue_.push_back((uint8_t) frame.size()); | ||||||
|     prologue_.insert(prologue_.end(), frame.msg.begin(), frame.msg.end()); |     prologue_.insert(prologue_.end(), frame.begin(), frame.end()); | ||||||
|  |  | ||||||
|     state_ = State::SERVER_HELLO; |     state_ = State::SERVER_HELLO; | ||||||
|   } |   } | ||||||
| @@ -469,41 +486,33 @@ APIError APINoiseFrameHelper::state_action_() { | |||||||
|     int action = noise_handshakestate_get_action(handshake_); |     int action = noise_handshakestate_get_action(handshake_); | ||||||
|     if (action == NOISE_ACTION_READ_MESSAGE) { |     if (action == NOISE_ACTION_READ_MESSAGE) { | ||||||
|       // waiting for handshake msg |       // waiting for handshake msg | ||||||
|       ParsedFrame frame; |       std::vector<uint8_t> frame; | ||||||
|       aerr = try_read_frame_(&frame); |       aerr = try_read_frame_(&frame); | ||||||
|       if (aerr == APIError::BAD_INDICATOR) { |       if (aerr != APIError::OK) { | ||||||
|         send_explicit_handshake_reject_("Bad indicator byte"); |         return handle_handshake_frame_error_(aerr); | ||||||
|         return aerr; |  | ||||||
|       } |       } | ||||||
|       if (aerr == APIError::BAD_HANDSHAKE_PACKET_LEN) { |  | ||||||
|         send_explicit_handshake_reject_("Bad handshake packet len"); |  | ||||||
|         return aerr; |  | ||||||
|       } |  | ||||||
|       if (aerr != APIError::OK) |  | ||||||
|         return aerr; |  | ||||||
|  |  | ||||||
|       if (frame.msg.empty()) { |       if (frame.empty()) { | ||||||
|         send_explicit_handshake_reject_("Empty handshake message"); |         send_explicit_handshake_reject_("Empty handshake message"); | ||||||
|         return APIError::BAD_HANDSHAKE_ERROR_BYTE; |         return APIError::BAD_HANDSHAKE_ERROR_BYTE; | ||||||
|       } else if (frame.msg[0] != 0x00) { |       } else if (frame[0] != 0x00) { | ||||||
|         HELPER_LOG("Bad handshake error byte: %u", frame.msg[0]); |         HELPER_LOG("Bad handshake error byte: %u", frame[0]); | ||||||
|         send_explicit_handshake_reject_("Bad handshake error byte"); |         send_explicit_handshake_reject_("Bad handshake error byte"); | ||||||
|         return APIError::BAD_HANDSHAKE_ERROR_BYTE; |         return APIError::BAD_HANDSHAKE_ERROR_BYTE; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       NoiseBuffer mbuf; |       NoiseBuffer mbuf; | ||||||
|       noise_buffer_init(mbuf); |       noise_buffer_init(mbuf); | ||||||
|       noise_buffer_set_input(mbuf, frame.msg.data() + 1, frame.msg.size() - 1); |       noise_buffer_set_input(mbuf, frame.data() + 1, frame.size() - 1); | ||||||
|       err = noise_handshakestate_read_message(handshake_, &mbuf, nullptr); |       err = noise_handshakestate_read_message(handshake_, &mbuf, nullptr); | ||||||
|       if (err != 0) { |       if (err != 0) { | ||||||
|         state_ = State::FAILED; |         // Special handling for MAC failure | ||||||
|         HELPER_LOG("noise_handshakestate_read_message failed: %s", noise_err_to_str(err).c_str()); |  | ||||||
|         if (err == NOISE_ERROR_MAC_FAILURE) { |         if (err == NOISE_ERROR_MAC_FAILURE) { | ||||||
|           send_explicit_handshake_reject_("Handshake MAC failure"); |           send_explicit_handshake_reject_("Handshake MAC failure"); | ||||||
|         } else { |         } else { | ||||||
|           send_explicit_handshake_reject_("Handshake error"); |           send_explicit_handshake_reject_("Handshake error"); | ||||||
|         } |         } | ||||||
|         return APIError::HANDSHAKESTATE_READ_FAILED; |         return handle_noise_error_(err, "noise_handshakestate_read_message", APIError::HANDSHAKESTATE_READ_FAILED); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       aerr = check_handshake_finished_(); |       aerr = check_handshake_finished_(); | ||||||
| @@ -516,11 +525,10 @@ APIError APINoiseFrameHelper::state_action_() { | |||||||
|       noise_buffer_set_output(mbuf, buffer + 1, sizeof(buffer) - 1); |       noise_buffer_set_output(mbuf, buffer + 1, sizeof(buffer) - 1); | ||||||
|  |  | ||||||
|       err = noise_handshakestate_write_message(handshake_, &mbuf, nullptr); |       err = noise_handshakestate_write_message(handshake_, &mbuf, nullptr); | ||||||
|       if (err != 0) { |       APIError aerr_write = | ||||||
|         state_ = State::FAILED; |           handle_noise_error_(err, "noise_handshakestate_write_message", APIError::HANDSHAKESTATE_WRITE_FAILED); | ||||||
|         HELPER_LOG("noise_handshakestate_write_message failed: %s", noise_err_to_str(err).c_str()); |       if (aerr_write != APIError::OK) | ||||||
|         return APIError::HANDSHAKESTATE_WRITE_FAILED; |         return aerr_write; | ||||||
|       } |  | ||||||
|       buffer[0] = 0x00;  // success |       buffer[0] = 0x00;  // success | ||||||
|  |  | ||||||
|       aerr = write_frame_(buffer, mbuf.size + 1); |       aerr = write_frame_(buffer, mbuf.size + 1); | ||||||
| @@ -569,23 +577,21 @@ APIError APINoiseFrameHelper::read_packet(ReadPacketBuffer *buffer) { | |||||||
|     return APIError::WOULD_BLOCK; |     return APIError::WOULD_BLOCK; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   ParsedFrame frame; |   std::vector<uint8_t> frame; | ||||||
|   aerr = try_read_frame_(&frame); |   aerr = try_read_frame_(&frame); | ||||||
|   if (aerr != APIError::OK) |   if (aerr != APIError::OK) | ||||||
|     return aerr; |     return aerr; | ||||||
|  |  | ||||||
|   NoiseBuffer mbuf; |   NoiseBuffer mbuf; | ||||||
|   noise_buffer_init(mbuf); |   noise_buffer_init(mbuf); | ||||||
|   noise_buffer_set_inout(mbuf, frame.msg.data(), frame.msg.size(), frame.msg.size()); |   noise_buffer_set_inout(mbuf, frame.data(), frame.size(), frame.size()); | ||||||
|   err = noise_cipherstate_decrypt(recv_cipher_, &mbuf); |   err = noise_cipherstate_decrypt(recv_cipher_, &mbuf); | ||||||
|   if (err != 0) { |   APIError decrypt_err = handle_noise_error_(err, "noise_cipherstate_decrypt", APIError::CIPHERSTATE_DECRYPT_FAILED); | ||||||
|     state_ = State::FAILED; |   if (decrypt_err != APIError::OK) | ||||||
|     HELPER_LOG("noise_cipherstate_decrypt failed: %s", noise_err_to_str(err).c_str()); |     return decrypt_err; | ||||||
|     return APIError::CIPHERSTATE_DECRYPT_FAILED; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   uint16_t msg_size = mbuf.size; |   uint16_t msg_size = mbuf.size; | ||||||
|   uint8_t *msg_data = frame.msg.data(); |   uint8_t *msg_data = frame.data(); | ||||||
|   if (msg_size < 4) { |   if (msg_size < 4) { | ||||||
|     state_ = State::FAILED; |     state_ = State::FAILED; | ||||||
|     HELPER_LOG("Bad data packet: size %d too short", msg_size); |     HELPER_LOG("Bad data packet: size %d too short", msg_size); | ||||||
| @@ -600,7 +606,7 @@ APIError APINoiseFrameHelper::read_packet(ReadPacketBuffer *buffer) { | |||||||
|     return APIError::BAD_DATA_PACKET; |     return APIError::BAD_DATA_PACKET; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   buffer->container = std::move(frame.msg); |   buffer->container = std::move(frame); | ||||||
|   buffer->data_offset = 4; |   buffer->data_offset = 4; | ||||||
|   buffer->data_len = data_len; |   buffer->data_len = data_len; | ||||||
|   buffer->type = type; |   buffer->type = type; | ||||||
| @@ -662,11 +668,9 @@ APIError APINoiseFrameHelper::write_protobuf_packets(ProtoWriteBuffer buffer, st | |||||||
|                            4 + packet.payload_size + frame_footer_size_); |                            4 + packet.payload_size + frame_footer_size_); | ||||||
|  |  | ||||||
|     int err = noise_cipherstate_encrypt(send_cipher_, &mbuf); |     int err = noise_cipherstate_encrypt(send_cipher_, &mbuf); | ||||||
|     if (err != 0) { |     APIError aerr = handle_noise_error_(err, "noise_cipherstate_encrypt", APIError::CIPHERSTATE_ENCRYPT_FAILED); | ||||||
|       state_ = State::FAILED; |     if (aerr != APIError::OK) | ||||||
|       HELPER_LOG("noise_cipherstate_encrypt failed: %s", noise_err_to_str(err).c_str()); |       return aerr; | ||||||
|       return APIError::CIPHERSTATE_ENCRYPT_FAILED; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Fill in the encrypted size |     // Fill in the encrypted size | ||||||
|     buf_start[1] = static_cast<uint8_t>(mbuf.size >> 8); |     buf_start[1] = static_cast<uint8_t>(mbuf.size >> 8); | ||||||
| @@ -718,35 +722,27 @@ APIError APINoiseFrameHelper::init_handshake_() { | |||||||
|   nid_.modifier_ids[0] = NOISE_MODIFIER_PSK0; |   nid_.modifier_ids[0] = NOISE_MODIFIER_PSK0; | ||||||
|  |  | ||||||
|   err = noise_handshakestate_new_by_id(&handshake_, &nid_, NOISE_ROLE_RESPONDER); |   err = noise_handshakestate_new_by_id(&handshake_, &nid_, NOISE_ROLE_RESPONDER); | ||||||
|   if (err != 0) { |   APIError aerr = handle_noise_error_(err, "noise_handshakestate_new_by_id", APIError::HANDSHAKESTATE_SETUP_FAILED); | ||||||
|     state_ = State::FAILED; |   if (aerr != APIError::OK) | ||||||
|     HELPER_LOG("noise_handshakestate_new_by_id failed: %s", noise_err_to_str(err).c_str()); |     return aerr; | ||||||
|     return APIError::HANDSHAKESTATE_SETUP_FAILED; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   const auto &psk = ctx_->get_psk(); |   const auto &psk = ctx_->get_psk(); | ||||||
|   err = noise_handshakestate_set_pre_shared_key(handshake_, psk.data(), psk.size()); |   err = noise_handshakestate_set_pre_shared_key(handshake_, psk.data(), psk.size()); | ||||||
|   if (err != 0) { |   aerr = handle_noise_error_(err, "noise_handshakestate_set_pre_shared_key", APIError::HANDSHAKESTATE_SETUP_FAILED); | ||||||
|     state_ = State::FAILED; |   if (aerr != APIError::OK) | ||||||
|     HELPER_LOG("noise_handshakestate_set_pre_shared_key failed: %s", noise_err_to_str(err).c_str()); |     return aerr; | ||||||
|     return APIError::HANDSHAKESTATE_SETUP_FAILED; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   err = noise_handshakestate_set_prologue(handshake_, prologue_.data(), prologue_.size()); |   err = noise_handshakestate_set_prologue(handshake_, prologue_.data(), prologue_.size()); | ||||||
|   if (err != 0) { |   aerr = handle_noise_error_(err, "noise_handshakestate_set_prologue", APIError::HANDSHAKESTATE_SETUP_FAILED); | ||||||
|     state_ = State::FAILED; |   if (aerr != APIError::OK) | ||||||
|     HELPER_LOG("noise_handshakestate_set_prologue failed: %s", noise_err_to_str(err).c_str()); |     return aerr; | ||||||
|     return APIError::HANDSHAKESTATE_SETUP_FAILED; |  | ||||||
|   } |  | ||||||
|   // set_prologue copies it into handshakestate, so we can get rid of it now |   // set_prologue copies it into handshakestate, so we can get rid of it now | ||||||
|   prologue_ = {}; |   prologue_ = {}; | ||||||
|  |  | ||||||
|   err = noise_handshakestate_start(handshake_); |   err = noise_handshakestate_start(handshake_); | ||||||
|   if (err != 0) { |   aerr = handle_noise_error_(err, "noise_handshakestate_start", APIError::HANDSHAKESTATE_SETUP_FAILED); | ||||||
|     state_ = State::FAILED; |   if (aerr != APIError::OK) | ||||||
|     HELPER_LOG("noise_handshakestate_start failed: %s", noise_err_to_str(err).c_str()); |     return aerr; | ||||||
|     return APIError::HANDSHAKESTATE_SETUP_FAILED; |  | ||||||
|   } |  | ||||||
|   return APIError::OK; |   return APIError::OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -762,11 +758,9 @@ APIError APINoiseFrameHelper::check_handshake_finished_() { | |||||||
|     return APIError::HANDSHAKESTATE_BAD_STATE; |     return APIError::HANDSHAKESTATE_BAD_STATE; | ||||||
|   } |   } | ||||||
|   int err = noise_handshakestate_split(handshake_, &send_cipher_, &recv_cipher_); |   int err = noise_handshakestate_split(handshake_, &send_cipher_, &recv_cipher_); | ||||||
|   if (err != 0) { |   APIError aerr = handle_noise_error_(err, "noise_handshakestate_split", APIError::HANDSHAKESTATE_SPLIT_FAILED); | ||||||
|     state_ = State::FAILED; |   if (aerr != APIError::OK) | ||||||
|     HELPER_LOG("noise_handshakestate_split failed: %s", noise_err_to_str(err).c_str()); |     return aerr; | ||||||
|     return APIError::HANDSHAKESTATE_SPLIT_FAILED; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   frame_footer_size_ = noise_cipherstate_get_mac_length(send_cipher_); |   frame_footer_size_ = noise_cipherstate_get_mac_length(send_cipher_); | ||||||
|  |  | ||||||
| @@ -833,7 +827,7 @@ APIError APIPlaintextFrameHelper::loop() { | |||||||
|  * |  * | ||||||
|  * 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_(ParsedFrame *frame) { | APIError APIPlaintextFrameHelper::try_read_frame_(std::vector<uint8_t> *frame) { | ||||||
|   if (frame == nullptr) { |   if (frame == nullptr) { | ||||||
|     HELPER_LOG("Bad argument for try_read_frame_"); |     HELPER_LOG("Bad argument for try_read_frame_"); | ||||||
|     return APIError::BAD_ARG; |     return APIError::BAD_ARG; | ||||||
| @@ -951,7 +945,7 @@ APIError APIPlaintextFrameHelper::try_read_frame_(ParsedFrame *frame) { | |||||||
| #ifdef HELPER_LOG_PACKETS | #ifdef HELPER_LOG_PACKETS | ||||||
|   ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(rx_buf_).c_str()); |   ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(rx_buf_).c_str()); | ||||||
| #endif | #endif | ||||||
|   frame->msg = std::move(rx_buf_); |   *frame = std::move(rx_buf_); | ||||||
|   // consume msg |   // consume msg | ||||||
|   rx_buf_ = {}; |   rx_buf_ = {}; | ||||||
|   rx_buf_len_ = 0; |   rx_buf_len_ = 0; | ||||||
| @@ -966,7 +960,7 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) { | |||||||
|     return APIError::WOULD_BLOCK; |     return APIError::WOULD_BLOCK; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   ParsedFrame frame; |   std::vector<uint8_t> frame; | ||||||
|   aerr = try_read_frame_(&frame); |   aerr = try_read_frame_(&frame); | ||||||
|   if (aerr != APIError::OK) { |   if (aerr != APIError::OK) { | ||||||
|     if (aerr == APIError::BAD_INDICATOR) { |     if (aerr == APIError::BAD_INDICATOR) { | ||||||
| @@ -991,7 +985,7 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) { | |||||||
|     return aerr; |     return aerr; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   buffer->container = std::move(frame.msg); |   buffer->container = std::move(frame); | ||||||
|   buffer->data_offset = 0; |   buffer->data_offset = 0; | ||||||
|   buffer->data_len = rx_header_parsed_len_; |   buffer->data_len = rx_header_parsed_len_; | ||||||
|   buffer->type = rx_header_parsed_type_; |   buffer->type = rx_header_parsed_type_; | ||||||
|   | |||||||
| @@ -109,11 +109,6 @@ class APIFrameHelper { | |||||||
|   bool is_socket_ready() const { return socket_ != nullptr && socket_->ready(); } |   bool is_socket_ready() const { return socket_ != nullptr && socket_->ready(); } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   // Struct for holding parsed frame data |  | ||||||
|   struct ParsedFrame { |  | ||||||
|     std::vector<uint8_t> msg; |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   // Buffer containing data to be sent |   // Buffer containing data to be sent | ||||||
|   struct SendBuffer { |   struct SendBuffer { | ||||||
|     std::unique_ptr<uint8_t[]> data; |     std::unique_ptr<uint8_t[]> data; | ||||||
| @@ -133,6 +128,9 @@ class APIFrameHelper { | |||||||
|  |  | ||||||
|   // Helper method to buffer data from IOVs |   // Helper method to buffer data from IOVs | ||||||
|   void buffer_data_from_iov_(const struct iovec *iov, int iovcnt, uint16_t total_write_len, uint16_t offset); |   void buffer_data_from_iov_(const struct iovec *iov, int iovcnt, uint16_t total_write_len, uint16_t offset); | ||||||
|  |  | ||||||
|  |   // Common socket write error handling | ||||||
|  |   APIError handle_socket_write_error_(); | ||||||
|   template<typename StateEnum> |   template<typename StateEnum> | ||||||
|   APIError write_raw_(const struct iovec *iov, int iovcnt, socket::Socket *socket, std::vector<uint8_t> &tx_buf, |   APIError write_raw_(const struct iovec *iov, int iovcnt, socket::Socket *socket, std::vector<uint8_t> &tx_buf, | ||||||
|                       const std::string &info, StateEnum &state, StateEnum failed_state); |                       const std::string &info, StateEnum &state, StateEnum failed_state); | ||||||
| @@ -205,11 +203,13 @@ class APINoiseFrameHelper : public APIFrameHelper { | |||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   APIError state_action_(); |   APIError state_action_(); | ||||||
|   APIError try_read_frame_(ParsedFrame *frame); |   APIError try_read_frame_(std::vector<uint8_t> *frame); | ||||||
|   APIError write_frame_(const uint8_t *data, uint16_t len); |   APIError write_frame_(const uint8_t *data, uint16_t len); | ||||||
|   APIError init_handshake_(); |   APIError init_handshake_(); | ||||||
|   APIError check_handshake_finished_(); |   APIError check_handshake_finished_(); | ||||||
|   void send_explicit_handshake_reject_(const std::string &reason); |   void send_explicit_handshake_reject_(const std::string &reason); | ||||||
|  |   APIError handle_handshake_frame_error_(APIError aerr); | ||||||
|  |   APIError handle_noise_error_(int err, const char *func_name, APIError api_err); | ||||||
|  |  | ||||||
|   // Pointers first (4 bytes each) |   // Pointers first (4 bytes each) | ||||||
|   NoiseHandshakeState *handshake_{nullptr}; |   NoiseHandshakeState *handshake_{nullptr}; | ||||||
| @@ -257,7 +257,7 @@ class APIPlaintextFrameHelper : public APIFrameHelper { | |||||||
|   uint8_t frame_footer_size() override { return frame_footer_size_; } |   uint8_t frame_footer_size() override { return frame_footer_size_; } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   APIError try_read_frame_(ParsedFrame *frame); |   APIError try_read_frame_(std::vector<uint8_t> *frame); | ||||||
|  |  | ||||||
|   // Group 2-byte aligned types |   // Group 2-byte aligned types | ||||||
|   uint16_t rx_header_parsed_type_ = 0; |   uint16_t rx_header_parsed_type_ = 0; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user