[api] Optimize noise handshake with memcpy for faster connection setup (#9779)

This commit is contained in:
J. Nick Koston 2025-07-21 12:56:32 -10:00 committed by GitHub
parent 5343a6d16a
commit 118b74b7cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -15,6 +15,7 @@ namespace api {
static const char *const TAG = "api.noise"; static const char *const TAG = "api.noise";
static const char *const PROLOGUE_INIT = "NoiseAPIInit"; static const char *const PROLOGUE_INIT = "NoiseAPIInit";
static constexpr size_t PROLOGUE_INIT_LEN = 12; // strlen("NoiseAPIInit")
#define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s: " msg, this->client_info_->get_combined_info().c_str(), ##__VA_ARGS__) #define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s: " msg, this->client_info_->get_combined_info().c_str(), ##__VA_ARGS__)
@ -73,7 +74,9 @@ APIError APINoiseFrameHelper::init() {
} }
// init prologue // init prologue
prologue_.insert(prologue_.end(), PROLOGUE_INIT, PROLOGUE_INIT + strlen(PROLOGUE_INIT)); size_t old_size = prologue_.size();
prologue_.resize(old_size + PROLOGUE_INIT_LEN);
std::memcpy(prologue_.data() + old_size, PROLOGUE_INIT, PROLOGUE_INIT_LEN);
state_ = State::CLIENT_HELLO; state_ = State::CLIENT_HELLO;
return APIError::OK; return APIError::OK;
@ -223,11 +226,12 @@ APIError APINoiseFrameHelper::state_action_() {
return handle_handshake_frame_error_(aerr); return handle_handshake_frame_error_(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 // Resize for: existing prologue + 2 size bytes + frame data
prologue_.reserve(prologue_.size() + 2 + frame.size()); size_t old_size = prologue_.size();
prologue_.push_back((uint8_t) (frame.size() >> 8)); prologue_.resize(old_size + 2 + frame.size());
prologue_.push_back((uint8_t) frame.size()); prologue_[old_size] = (uint8_t) (frame.size() >> 8);
prologue_.insert(prologue_.end(), frame.begin(), frame.end()); prologue_[old_size + 1] = (uint8_t) frame.size();
std::memcpy(prologue_.data() + old_size + 2, frame.data(), frame.size());
state_ = State::SERVER_HELLO; state_ = State::SERVER_HELLO;
} }
@ -237,18 +241,22 @@ APIError APINoiseFrameHelper::state_action_() {
const std::string &mac = get_mac_address(); const std::string &mac = get_mac_address();
std::vector<uint8_t> msg; std::vector<uint8_t> msg;
// Reserve space for: 1 byte proto + name + null + mac + null // Calculate positions and sizes
msg.reserve(1 + name.size() + 1 + mac.size() + 1); size_t name_len = name.size() + 1; // including null terminator
size_t mac_len = mac.size() + 1; // including null terminator
size_t name_offset = 1;
size_t mac_offset = name_offset + name_len;
size_t total_size = 1 + name_len + mac_len;
msg.resize(total_size);
// chosen proto // chosen proto
msg.push_back(0x01); msg[0] = 0x01;
// node name, terminated by null byte // node name, terminated by null byte
const uint8_t *name_ptr = reinterpret_cast<const uint8_t *>(name.c_str()); std::memcpy(msg.data() + name_offset, name.c_str(), name_len);
msg.insert(msg.end(), name_ptr, name_ptr + name.size() + 1);
// node mac, terminated by null byte // node mac, terminated by null byte
const uint8_t *mac_ptr = reinterpret_cast<const uint8_t *>(mac.c_str()); std::memcpy(msg.data() + mac_offset, mac.c_str(), mac_len);
msg.insert(msg.end(), mac_ptr, mac_ptr + mac.size() + 1);
aerr = write_frame_(msg.data(), msg.size()); aerr = write_frame_(msg.data(), msg.size());
if (aerr != APIError::OK) if (aerr != APIError::OK)