mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Fix slow noise handshake by reading multiple messages per loop
This commit is contained in:
		| @@ -28,6 +28,12 @@ | |||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace api { | namespace api { | ||||||
|  |  | ||||||
|  | // Read a maximum of 5 messages per loop iteration to prevent starving other components. | ||||||
|  | // This is a balance between API responsiveness and allowing other components to run. | ||||||
|  | // Since each message could contain multiple protobuf messages when using packet batching, | ||||||
|  | // this limits the number of messages processed, not the number of TCP packets. | ||||||
|  | static constexpr uint8_t MAX_MESSAGES_PER_LOOP = 5; | ||||||
|  |  | ||||||
| static const char *const TAG = "api.connection"; | static const char *const TAG = "api.connection"; | ||||||
| static const int ESP32_CAMERA_STOP_STREAM = 5000; | static const int ESP32_CAMERA_STOP_STREAM = 5000; | ||||||
|  |  | ||||||
| @@ -109,33 +115,38 @@ void APIConnection::loop() { | |||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   const uint32_t now = App.get_loop_component_start_time(); | ||||||
|   // Check if socket has data ready before attempting to read |   // Check if socket has data ready before attempting to read | ||||||
|   if (this->helper_->is_socket_ready()) { |   if (this->helper_->is_socket_ready()) { | ||||||
|     ReadPacketBuffer buffer; |     // Read up to MAX_MESSAGES_PER_LOOP messages per loop to improve throughput | ||||||
|     err = this->helper_->read_packet(&buffer); |     for (uint8_t message_count = 0; message_count < MAX_MESSAGES_PER_LOOP; message_count++) { | ||||||
|     if (err == APIError::WOULD_BLOCK) { |       ReadPacketBuffer buffer; | ||||||
|       // pass |       err = this->helper_->read_packet(&buffer); | ||||||
|     } else if (err != APIError::OK) { |       if (err == APIError::WOULD_BLOCK) { | ||||||
|       on_fatal_error(); |         // No more data available | ||||||
|       if (err == APIError::SOCKET_READ_FAILED && errno == ECONNRESET) { |         break; | ||||||
|         ESP_LOGW(TAG, "%s: Connection reset", this->client_combined_info_.c_str()); |       } else if (err != APIError::OK) { | ||||||
|       } else if (err == APIError::CONNECTION_CLOSED) { |         on_fatal_error(); | ||||||
|         ESP_LOGW(TAG, "%s: Connection closed", this->client_combined_info_.c_str()); |         if (err == APIError::SOCKET_READ_FAILED && errno == ECONNRESET) { | ||||||
|       } else { |           ESP_LOGW(TAG, "%s: Connection reset", this->client_combined_info_.c_str()); | ||||||
|         ESP_LOGW(TAG, "%s: Reading failed: %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err), |         } else if (err == APIError::CONNECTION_CLOSED) { | ||||||
|                  errno); |           ESP_LOGW(TAG, "%s: Connection closed", this->client_combined_info_.c_str()); | ||||||
|       } |         } else { | ||||||
|       return; |           ESP_LOGW(TAG, "%s: Reading failed: %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err), | ||||||
|     } else { |                    errno); | ||||||
|       this->last_traffic_ = App.get_loop_component_start_time(); |         } | ||||||
|       // read a packet |  | ||||||
|       if (buffer.data_len > 0) { |  | ||||||
|         this->read_message(buffer.data_len, buffer.type, &buffer.container[buffer.data_offset]); |  | ||||||
|       } else { |  | ||||||
|         this->read_message(0, buffer.type, nullptr); |  | ||||||
|       } |  | ||||||
|       if (this->remove_) |  | ||||||
|         return; |         return; | ||||||
|  |       } else { | ||||||
|  |         this->last_traffic_ = now; | ||||||
|  |         // read a packet | ||||||
|  |         if (buffer.data_len > 0) { | ||||||
|  |           this->read_message(buffer.data_len, buffer.type, &buffer.container[buffer.data_offset]); | ||||||
|  |         } else { | ||||||
|  |           this->read_message(0, buffer.type, nullptr); | ||||||
|  |         } | ||||||
|  |         if (this->remove_) | ||||||
|  |           return; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -152,7 +163,6 @@ void APIConnection::loop() { | |||||||
|  |  | ||||||
|   static uint8_t max_ping_retries = 60; |   static uint8_t max_ping_retries = 60; | ||||||
|   static uint16_t ping_retry_interval = 1000; |   static uint16_t ping_retry_interval = 1000; | ||||||
|   const uint32_t now = App.get_loop_component_start_time(); |  | ||||||
|   if (this->sent_ping_) { |   if (this->sent_ping_) { | ||||||
|     // Disconnect if not responded within 2.5*keepalive |     // Disconnect if not responded within 2.5*keepalive | ||||||
|     if (now - this->last_traffic_ > (KEEPALIVE_TIMEOUT_MS * 5) / 2) { |     if (now - this->last_traffic_ > (KEEPALIVE_TIMEOUT_MS * 5) / 2) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user