1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-26 12:43:48 +00:00

Merge branch 'esp32_ble_server_unique_ptr_mfr_data' into integration

This commit is contained in:
J. Nick Koston
2025-10-05 17:10:24 -05:00
13 changed files with 89 additions and 36 deletions

View File

@@ -68,6 +68,10 @@ void ESP32BLE::advertising_set_service_data(const std::vector<uint8_t> &data) {
}
void ESP32BLE::advertising_set_manufacturer_data(const std::vector<uint8_t> &data) {
this->advertising_set_manufacturer_data(std::span<const uint8_t>(data));
}
void ESP32BLE::advertising_set_manufacturer_data(std::span<const uint8_t> data) {
this->advertising_init_();
this->advertising_->set_manufacturer_data(data);
this->advertising_start();

View File

@@ -118,6 +118,7 @@ class ESP32BLE : public Component {
void advertising_start();
void advertising_set_service_data(const std::vector<uint8_t> &data);
void advertising_set_manufacturer_data(const std::vector<uint8_t> &data);
void advertising_set_manufacturer_data(std::span<const uint8_t> data);
void advertising_set_appearance(uint16_t appearance) { this->appearance_ = appearance; }
void advertising_set_service_data_and_name(std::span<const uint8_t> data, bool include_name);
void advertising_add_service_uuid(ESPBTUUID uuid);

View File

@@ -59,6 +59,10 @@ void BLEAdvertising::set_service_data(const std::vector<uint8_t> &data) {
}
void BLEAdvertising::set_manufacturer_data(const std::vector<uint8_t> &data) {
this->set_manufacturer_data(std::span<const uint8_t>(data));
}
void BLEAdvertising::set_manufacturer_data(std::span<const uint8_t> data) {
delete[] this->advertising_data_.p_manufacturer_data;
this->advertising_data_.p_manufacturer_data = nullptr;
this->advertising_data_.manufacturer_len = data.size();

View File

@@ -35,6 +35,7 @@ class BLEAdvertising {
void set_scan_response(bool scan_response) { this->scan_response_ = scan_response; }
void set_min_preferred_interval(uint16_t interval) { this->advertising_data_.min_interval = interval; }
void set_manufacturer_data(const std::vector<uint8_t> &data);
void set_manufacturer_data(std::span<const uint8_t> data);
void set_appearance(uint16_t appearance) { this->advertising_data_.appearance = appearance; }
void set_service_data(const std::vector<uint8_t> &data);
void set_service_data(std::span<const uint8_t> data);

View File

@@ -99,7 +99,8 @@ bool BLEServer::can_proceed() { return this->is_running() || !this->parent_->is_
void BLEServer::restart_advertising_() {
if (this->is_running()) {
this->parent_->advertising_set_manufacturer_data(this->manufacturer_data_);
this->parent_->advertising_set_manufacturer_data(
std::span<const uint8_t>(this->manufacturer_data_.get(), this->manufacturer_data_length_));
}
}

View File

@@ -35,7 +35,11 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv
bool is_running();
void set_manufacturer_data(const std::vector<uint8_t> &data) {
this->manufacturer_data_ = data;
this->manufacturer_data_length_ = data.size();
this->manufacturer_data_.reset(data.empty() ? nullptr : new uint8_t[data.size()]);
if (!data.empty()) {
memcpy(this->manufacturer_data_.get(), data.data(), data.size());
}
this->restart_advertising_();
}
@@ -87,24 +91,27 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv
void remove_client_(uint16_t conn_id);
void dispatch_callbacks_(CallbackType type, uint16_t conn_id);
// 4-byte aligned (pointers and vectors on 32-bit)
std::vector<CallbackEntry> callbacks_;
std::vector<uint8_t> manufacturer_data_{};
esp_gatt_if_t gatts_if_{0};
bool registered_{false};
uint16_t clients_[USE_ESP32_BLE_MAX_CONNECTIONS]{};
uint8_t client_count_{0};
std::vector<ServiceEntry> services_{};
std::vector<BLEService *> services_to_start_{};
std::unique_ptr<uint8_t[]> manufacturer_data_{};
BLEService *device_information_service_{};
// 2-byte aligned
uint16_t clients_[USE_ESP32_BLE_MAX_CONNECTIONS]{};
// 1-byte aligned
uint8_t manufacturer_data_length_{0};
uint8_t client_count_{0};
esp_gatt_if_t gatts_if_{0};
enum State : uint8_t {
INIT = 0x00,
REGISTERING,
STARTING_SERVICE,
RUNNING,
} state_{INIT};
bool registered_{false};
};
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)

View File

@@ -79,7 +79,7 @@ void MDNSComponent::compile_records_() {
#ifdef USE_API
if (api::global_api_server != nullptr) {
auto &service = this->services_[this->services_.count()++];
auto &service = this->services_.emplace_next();
service.service_type = MDNS_STR(SERVICE_ESPHOMELIB);
service.proto = MDNS_STR(SERVICE_TCP);
service.port = api::global_api_server->get_port();
@@ -158,14 +158,14 @@ void MDNSComponent::compile_records_() {
#endif // USE_API
#ifdef USE_PROMETHEUS
auto &prom_service = this->services_[this->services_.count()++];
auto &prom_service = this->services_.emplace_next();
prom_service.service_type = MDNS_STR(SERVICE_PROMETHEUS);
prom_service.proto = MDNS_STR(SERVICE_TCP);
prom_service.port = USE_WEBSERVER_PORT;
#endif
#ifdef USE_WEBSERVER
auto &web_service = this->services_[this->services_.count()++];
auto &web_service = this->services_.emplace_next();
web_service.service_type = MDNS_STR(SERVICE_HTTP);
web_service.proto = MDNS_STR(SERVICE_TCP);
web_service.port = USE_WEBSERVER_PORT;
@@ -174,7 +174,7 @@ void MDNSComponent::compile_records_() {
#if !defined(USE_API) && !defined(USE_PROMETHEUS) && !defined(USE_WEBSERVER) && !defined(USE_MDNS_EXTRA_SERVICES)
// Publish "http" service if not using native API or any other services
// This is just to have *some* mDNS service so that .local resolution works
auto &fallback_service = this->services_[this->services_.count()++];
auto &fallback_service = this->services_.emplace_next();
fallback_service.service_type = "_http";
fallback_service.proto = "_tcp";
fallback_service.port = USE_WEBSERVER_PORT;

View File

@@ -39,7 +39,7 @@ class MDNSComponent : public Component {
float get_setup_priority() const override { return setup_priority::AFTER_CONNECTION; }
#ifdef USE_MDNS_EXTRA_SERVICES
void add_extra_service(MDNSService service) { this->services_[this->services_.count()++] = std::move(service); }
void add_extra_service(MDNSService service) { this->services_.emplace_next() = std::move(service); }
#endif
const StaticVector<MDNSService, MDNS_SERVICE_COUNT> &get_services() const { return this->services_; }

View File

@@ -52,6 +52,20 @@ DefaultHeaders &DefaultHeaders::Instance() { return default_headers_instance; }
namespace {
// Non-blocking send function to prevent watchdog timeouts when TCP buffers are full
/**
* Sends data on a socket in non-blocking mode.
*
* @param hd HTTP server handle (unused).
* @param sockfd Socket file descriptor.
* @param buf Buffer to send.
* @param buf_len Length of buffer.
* @param flags Flags for send().
* @return
* - Number of bytes sent on success.
* - HTTPD_SOCK_ERR_INVALID if buf is nullptr.
* - HTTPD_SOCK_ERR_TIMEOUT if the send buffer is full (EAGAIN/EWOULDBLOCK).
* - HTTPD_SOCK_ERR_FAIL for other errors.
*/
int nonblocking_send(httpd_handle_t hd, int sockfd, const char *buf, size_t buf_len, int flags) {
if (buf == nullptr) {
return HTTPD_SOCK_ERR_INVALID;
@@ -319,8 +333,8 @@ AsyncWebParameter *AsyncWebServerRequest::getParam(const std::string &name) {
}
}
// Don't cache misses to prevent memory exhaustion from malicious requests
// with thousands of non-existent parameter lookups
// Don't cache misses to avoid wasting memory when handlers check for
// optional parameters that don't exist in the request
if (!val.has_value()) {
return nullptr;
}

View File

@@ -172,7 +172,8 @@ class AsyncWebServerRequest {
AsyncWebServerResponse *rsp_{};
// Use vector instead of map/unordered_map: most requests have 0-3 params, so linear search
// is faster than tree/hash overhead. AsyncWebParameter stores both name and value to avoid
// duplicate storage. Only successful lookups are cached to prevent memory exhaustion attacks.
// duplicate storage. Only successful lookups are cached to prevent cache pollution when
// handlers check for optional parameters that don't exist.
std::vector<AsyncWebParameter *> params_;
std::string post_query_;
AsyncWebServerRequest(httpd_req_t *req) : req_(req) {}

View File

@@ -365,7 +365,7 @@ void WiFiComponent::start_connecting(const WiFiAP &ap, bool two) {
ESP_LOGV(TAG, " Identity: " LOG_SECRET("'%s'"), eap_config.identity.c_str());
ESP_LOGV(TAG, " Username: " LOG_SECRET("'%s'"), eap_config.username.c_str());
ESP_LOGV(TAG, " Password: " LOG_SECRET("'%s'"), eap_config.password.c_str());
#if defined(USE_ESP32) && ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
#if defined(USE_ESP32) && defined(USE_WIFI_WPA2_EAP) && ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
ESP_LOGV(TAG, " TTLS Phase 2: " LOG_SECRET("'%s'"), eap_phase2_to_str(eap_config.ttls_phase_2));
#endif
bool ca_cert_present = eap_config.ca_cert != nullptr && strlen(eap_config.ca_cert);