feat(esp_https_ota): Support partial downloading of OTA over single connection

This commit added support to download OTA with partial download feature
over single HTTP connection if server supports persistent connection.
This commit is contained in:
nilesh.kale
2025-09-15 17:21:56 +05:30
parent 20098cb71c
commit 709b869a34
3 changed files with 79 additions and 5 deletions
+23 -3
View File
@@ -185,7 +185,7 @@ static const char *HTTP_METHOD_MAPPING[] = {
"REPORT"
};
static esp_err_t esp_http_client_request_send(esp_http_client_handle_t client, int write_len);
esp_err_t esp_http_client_request_send(esp_http_client_handle_t client, int write_len);
static esp_err_t esp_http_client_connect(esp_http_client_handle_t client);
static esp_err_t esp_http_client_send_post_data(esp_http_client_handle_t client);
@@ -701,8 +701,12 @@ error:
}
#endif
static esp_err_t esp_http_client_prepare(esp_http_client_handle_t client)
esp_err_t esp_http_client_prepare(esp_http_client_handle_t client)
{
if (client == NULL) {
return ESP_FAIL;
}
esp_err_t ret = ESP_OK;
client->process_again = 0;
client->response->data_process = 0;
@@ -1711,8 +1715,12 @@ static int http_client_prepare_first_line(esp_http_client_handle_t client, int w
return first_line_len;
}
static esp_err_t esp_http_client_request_send(esp_http_client_handle_t client, int write_len)
esp_err_t esp_http_client_request_send(esp_http_client_handle_t client, int write_len)
{
if (client == NULL) {
return ESP_FAIL;
}
int first_line_len = 0;
if (!client->first_line_prepared) {
if ((first_line_len = http_client_prepare_first_line(client, write_len)) < 0) {
@@ -2065,3 +2073,15 @@ esp_http_state_t esp_http_client_get_state(esp_http_client_handle_t client)
}
return client->state;
}
bool esp_http_client_is_persistent_connection(esp_http_client_handle_t client)
{
if (client == NULL) {
return false;
}
if (http_should_keep_alive(client->parser)) {
return true;
}
return false;
}
@@ -343,6 +343,33 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co
*/
esp_err_t esp_http_client_perform(esp_http_client_handle_t client);
/**
* @brief Prepare HTTP client for a new request
* This function initializes the client state and prepares authentication if needed.
* It should be called before sending a request.
*
* @param[in] client The esp_http_client handle
*
* @return
* - ESP_OK on successful
* - ESP_FAIL on error
*/
esp_err_t esp_http_client_prepare(esp_http_client_handle_t client);
/**
* @brief Send HTTP request headers and data
* This function sends the HTTP request line, headers, and any post data to the server.
*
* @param[in] client The esp_http_client handle
* @param[in] write_len Length of data to write (for POST/PUT requests)
*
* @return
* - ESP_OK on successful
* - ESP_FAIL on error
* - ESP_ERR_HTTP_WRITE_DATA if write operation fails
*/
esp_err_t esp_http_client_request_send(esp_http_client_handle_t client, int write_len);
/**
* @brief Cancel an ongoing HTTP request. This API closes the current socket and opens a new socket with the same esp_http_client context.
*
@@ -866,6 +893,15 @@ esp_err_t esp_http_client_get_chunk_length(esp_http_client_handle_t client, int
*/
esp_http_state_t esp_http_client_get_state(esp_http_client_handle_t client);
/**
* @brief Check if persistent connection is supported by the server
*
* @param[in] client The HTTP client handle
*
* @return true if persistent connection is supported, false otherwise
*/
bool esp_http_client_is_persistent_connection(esp_http_client_handle_t client);
#ifdef __cplusplus
}
#endif
+20 -2
View File
@@ -165,7 +165,22 @@ static esp_err_t _http_connect(esp_https_ota_t *https_ota_handle)
* is enabled
*/
int post_len = esp_http_client_get_post_field(https_ota_handle->http_client, &post_data);
err = esp_http_client_open(https_ota_handle->http_client, post_len);
#if CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD
// If support_persistent_connection is enabled and this is a subsequent request, skip connection
if (esp_http_client_is_persistent_connection(https_ota_handle->http_client) && https_ota_handle->state == ESP_HTTPS_OTA_IN_PROGRESS) {
ESP_LOGD(TAG, "Using existing connection for partial download");
err = esp_http_client_prepare(https_ota_handle->http_client);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to reset HTTP client response state: %s", esp_err_to_name(err));
return err;
}
err = esp_http_client_request_send(https_ota_handle->http_client, post_len);
} else
#endif
{
err = esp_http_client_open(https_ota_handle->http_client, post_len);
}
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
return err;
@@ -827,7 +842,10 @@ esp_err_t esp_https_ota_perform(esp_https_ota_handle_t https_ota_handle)
#if CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD
if (handle->partial_http_download) {
if (handle->state == ESP_HTTPS_OTA_IN_PROGRESS && handle->image_length > handle->binary_file_len) {
esp_http_client_close(handle->http_client);
// Only close connection if support_persistent_connection is not enabled
if (!esp_http_client_is_persistent_connection(handle->http_client)) {
esp_http_client_close(handle->http_client);
}
char *header_val = NULL;
int header_size = 0;
#if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB