mirror of
https://github.com/esphome/esphome.git
synced 2025-08-01 07:57:47 +00:00
Merge branch 'integration' into memory_api
This commit is contained in:
commit
b70007852d
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user