mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Optimize OTA loop to avoid unnecessary stack allocations (#9129)
This commit is contained in:
		| @@ -26,19 +26,19 @@ void ESPHomeOTAComponent::setup() { | |||||||
|   ota::register_ota_platform(this); |   ota::register_ota_platform(this); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   server_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0);  // monitored for incoming connections |   this->server_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0);  // monitored for incoming connections | ||||||
|   if (server_ == nullptr) { |   if (this->server_ == nullptr) { | ||||||
|     ESP_LOGW(TAG, "Could not create socket"); |     ESP_LOGW(TAG, "Could not create socket"); | ||||||
|     this->mark_failed(); |     this->mark_failed(); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   int enable = 1; |   int enable = 1; | ||||||
|   int err = server_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); |   int err = this->server_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); | ||||||
|   if (err != 0) { |   if (err != 0) { | ||||||
|     ESP_LOGW(TAG, "Socket unable to set reuseaddr: errno %d", err); |     ESP_LOGW(TAG, "Socket unable to set reuseaddr: errno %d", err); | ||||||
|     // we can still continue |     // we can still continue | ||||||
|   } |   } | ||||||
|   err = server_->setblocking(false); |   err = this->server_->setblocking(false); | ||||||
|   if (err != 0) { |   if (err != 0) { | ||||||
|     ESP_LOGW(TAG, "Socket unable to set nonblocking mode: errno %d", err); |     ESP_LOGW(TAG, "Socket unable to set nonblocking mode: errno %d", err); | ||||||
|     this->mark_failed(); |     this->mark_failed(); | ||||||
| @@ -54,14 +54,14 @@ void ESPHomeOTAComponent::setup() { | |||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   err = server_->bind((struct sockaddr *) &server, sizeof(server)); |   err = this->server_->bind((struct sockaddr *) &server, sizeof(server)); | ||||||
|   if (err != 0) { |   if (err != 0) { | ||||||
|     ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno); |     ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno); | ||||||
|     this->mark_failed(); |     this->mark_failed(); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   err = server_->listen(4); |   err = this->server_->listen(4); | ||||||
|   if (err != 0) { |   if (err != 0) { | ||||||
|     ESP_LOGW(TAG, "Socket unable to listen: errno %d", errno); |     ESP_LOGW(TAG, "Socket unable to listen: errno %d", errno); | ||||||
|     this->mark_failed(); |     this->mark_failed(); | ||||||
| @@ -82,7 +82,14 @@ void ESPHomeOTAComponent::dump_config() { | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| void ESPHomeOTAComponent::loop() { this->handle_(); } | void ESPHomeOTAComponent::loop() { | ||||||
|  |   // Skip handle_() call if no client connected and no incoming connections | ||||||
|  |   // This optimization reduces idle loop overhead when OTA is not active | ||||||
|  |   // Note: No need to check server_ for null as the component is marked failed in setup() if server_ creation fails | ||||||
|  |   if (this->client_ != nullptr || this->server_->ready()) { | ||||||
|  |     this->handle_(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| static const uint8_t FEATURE_SUPPORTS_COMPRESSION = 0x01; | static const uint8_t FEATURE_SUPPORTS_COMPRESSION = 0x01; | ||||||
|  |  | ||||||
| @@ -101,23 +108,21 @@ void ESPHomeOTAComponent::handle_() { | |||||||
|   size_t size_acknowledged = 0; |   size_t size_acknowledged = 0; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   if (client_ == nullptr) { |   if (this->client_ == nullptr) { | ||||||
|     // Check if the server socket is ready before accepting |     // We already checked server_->ready() in loop(), so we can accept directly | ||||||
|     if (this->server_->ready()) { |     struct sockaddr_storage source_addr; | ||||||
|       struct sockaddr_storage source_addr; |     socklen_t addr_len = sizeof(source_addr); | ||||||
|       socklen_t addr_len = sizeof(source_addr); |     this->client_ = this->server_->accept((struct sockaddr *) &source_addr, &addr_len); | ||||||
|       client_ = server_->accept((struct sockaddr *) &source_addr, &addr_len); |     if (this->client_ == nullptr) | ||||||
|     } |       return; | ||||||
|   } |   } | ||||||
|   if (client_ == nullptr) |  | ||||||
|     return; |  | ||||||
|  |  | ||||||
|   int enable = 1; |   int enable = 1; | ||||||
|   int err = client_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(int)); |   int err = this->client_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(int)); | ||||||
|   if (err != 0) { |   if (err != 0) { | ||||||
|     ESP_LOGW(TAG, "Socket could not enable TCP nodelay, errno %d", errno); |     ESP_LOGW(TAG, "Socket could not enable TCP nodelay, errno %d", errno); | ||||||
|     client_->close(); |     this->client_->close(); | ||||||
|     client_ = nullptr; |     this->client_ = nullptr; | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user