diff --git a/components/esp_http_client/Kconfig b/components/esp_http_client/Kconfig index 2dc015fa73..947a5ab8db 100644 --- a/components/esp_http_client/Kconfig +++ b/components/esp_http_client/Kconfig @@ -29,6 +29,12 @@ menu "ESP HTTP client" This option will enable injection of a custom tcp_transport handle, so the http operation will be performed on top of the user defined transport abstraction (if configured) + config ESP_HTTP_CLIENT_ENABLE_GET_CONTENT_RANGE + bool "Enable content range functionality" + default n + help + This enables use of content range header in esp_http_client component. + config ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT int "Time in millisecond to wait for posting event" default 2000 diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index 6a2ee300b1..a5e0c7f6d1 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -67,7 +67,9 @@ typedef struct { int64_t data_process; /*!< data processed */ int method; /*!< http method */ bool is_chunked; +#if CONFIG_ESP_HTTP_CLIENT_ENABLE_GET_CONTENT_RANGE int64_t content_range; /*!< content range */ +#endif } esp_http_data_t; typedef struct { @@ -279,6 +281,7 @@ static int http_on_header_value(http_parser *parser, const char *at, size_t leng if (client->current_header_key == NULL) { return 0; } +#if CONFIG_ESP_HTTP_CLIENT_ENABLE_GET_CONTENT_RANGE if (strcasecmp(client->current_header_key, "Content-Range") == 0) { HTTP_RET_ON_FALSE_DBG(http_utils_append_string(&client->current_header_value, at, length), -1, TAG, "Failed to append string"); @@ -301,7 +304,9 @@ static int http_on_header_value(http_parser *parser, const char *at, size_t leng } else { ESP_LOGE(TAG, "Invalid Content-Range format (missing '/')"); } - } else if (strcasecmp(client->current_header_key, "Location") == 0) { + } else +#endif + if (strcasecmp(client->current_header_key, "Location") == 0) { HTTP_RET_ON_FALSE_DBG(http_utils_append_string(&client->location, at, length), -1, TAG, "Failed to append string"); } else if (strcasecmp(client->current_header_key, "Transfer-Encoding") == 0 && memcmp(at, "chunked", length) == 0) { @@ -1859,10 +1864,12 @@ int64_t esp_http_client_get_content_length(esp_http_client_handle_t client) return client->response->content_length; } +#if CONFIG_ESP_HTTP_CLIENT_ENABLE_GET_CONTENT_RANGE int64_t esp_http_client_get_content_range(esp_http_client_handle_t client) { return client->response->content_range; } +#endif bool esp_http_client_is_chunked_response(esp_http_client_handle_t client) { diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h index abdd28ff79..b707a22c03 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -644,6 +644,7 @@ int esp_http_client_get_status_code(esp_http_client_handle_t client); */ int64_t esp_http_client_get_content_length(esp_http_client_handle_t client); +#if CONFIG_ESP_HTTP_CLIENT_ENABLE_GET_CONTENT_RANGE || __DOXYGEN__ /** * @brief Get http response content range (from header Content-Range) * The returned value is valid only if this function is invoked after @@ -656,6 +657,7 @@ int64_t esp_http_client_get_content_length(esp_http_client_handle_t client); * - Content-Range value as bytes */ int64_t esp_http_client_get_content_range(esp_http_client_handle_t client); +#endif /** * @brief Close http connection, still kept all http request resources diff --git a/components/esp_https_ota/Kconfig b/components/esp_https_ota/Kconfig index a5512b0c5c..9873b3a0fb 100644 --- a/components/esp_https_ota/Kconfig +++ b/components/esp_https_ota/Kconfig @@ -25,4 +25,12 @@ menu "ESP HTTPS OTA" This config option helps in setting the time in millisecond to wait for event to be posted to the system default event loop. Set it to -1 if you need to set timeout to portMAX_DELAY. + config ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD + bool "Enable partial HTTP download for OTA" + default n + select ESP_HTTP_CLIENT_ENABLE_GET_CONTENT_RANGE + help + This enables use of range header in esp_https_ota component. + The firmware image will be downloaded over multiple HTTP requests. + endmenu diff --git a/components/esp_https_ota/include/esp_https_ota.h b/components/esp_https_ota/include/esp_https_ota.h index 42bf1d1954..7fc150cada 100644 --- a/components/esp_https_ota/include/esp_https_ota.h +++ b/components/esp_https_ota/include/esp_https_ota.h @@ -62,8 +62,10 @@ typedef struct { const esp_http_client_config_t *http_config; /*!< ESP HTTP client configuration */ http_client_init_cb_t http_client_init_cb; /*!< Callback after ESP HTTP client is initialised */ bool bulk_flash_erase; /*!< Erase entire flash partition during initialization. By default flash partition is erased during write operation and in chunk of 4K sector size */ +#if CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD || __DOXYGEN__ bool partial_http_download; /*!< Enable Firmware image to be downloaded over multiple HTTP requests */ int max_http_request_size; /*!< Maximum request size for partial HTTP download */ +#endif uint32_t buffer_caps; /*!< The memory capability to use when allocating the buffer for OTA update. Default capability is MALLOC_CAP_DEFAULT */ bool ota_resumption; /*!< Enable resumption in downloading of OTA image between reboots */ size_t ota_image_bytes_written; /*!< Number of OTA image bytes written to flash so far, updated by the application when OTA data is written successfully in the target OTA partition. */ diff --git a/components/esp_https_ota/src/esp_https_ota.c b/components/esp_https_ota/src/esp_https_ota.c index 89390591a9..c958a89d58 100644 --- a/components/esp_https_ota/src/esp_https_ota.c +++ b/components/esp_https_ota/src/esp_https_ota.c @@ -52,10 +52,12 @@ struct esp_https_ota_handle { size_t ota_upgrade_buf_size; int binary_file_len; int image_length; +#if CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD int max_http_request_size; + bool partial_http_download; +#endif esp_https_ota_state state; bool bulk_flash_erase; - bool partial_http_download; int max_authorization_retries; #if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB decrypt_cb_t decrypt_cb; @@ -316,8 +318,10 @@ esp_err_t esp_https_ota_begin(const esp_https_ota_config_t *ota_config, esp_http return ESP_ERR_NO_MEM; } +#if CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD https_ota_handle->partial_http_download = ota_config->partial_http_download; https_ota_handle->max_http_request_size = (ota_config->max_http_request_size == 0) ? DEFAULT_REQUEST_SIZE : ota_config->max_http_request_size; +#endif https_ota_handle->max_authorization_retries = ota_config->http_config->max_authorization_retries; if (https_ota_handle->max_authorization_retries == 0) { @@ -356,13 +360,18 @@ esp_err_t esp_https_ota_begin(const esp_https_ota_config_t *ota_config, esp_http * Partial cases ('from-to') are handled separately below based on the remaining data to * be downloaded and the max_http_request_size. */ - if (https_ota_handle->binary_file_len > 0 && !https_ota_handle->partial_http_download) { + if (https_ota_handle->binary_file_len > 0 +#if CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD + && !https_ota_handle->partial_http_download +#endif + ) { char *header_val = NULL; asprintf(&header_val, "bytes=%d-", https_ota_handle->binary_file_len); esp_http_client_set_header(https_ota_handle->http_client, "Range", header_val); free(header_val); } +#if CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD if (https_ota_handle->partial_http_download) { esp_http_client_set_method(https_ota_handle->http_client, HTTP_METHOD_HEAD); @@ -435,6 +444,7 @@ esp_err_t esp_https_ota_begin(const esp_https_ota_config_t *ota_config, esp_http } esp_http_client_set_method(https_ota_handle->http_client, HTTP_METHOD_GET); } +#endif err = _http_connect(https_ota_handle); if (err == ESP_ERR_HTTP_RANGE_NOT_SATISFIABLE && https_ota_handle->binary_file_len > 0) { @@ -445,6 +455,7 @@ esp_err_t esp_https_ota_begin(const esp_https_ota_config_t *ota_config, esp_http // If range in request header is not satisfiable, restart download from beginning esp_http_client_delete_header(https_ota_handle->http_client, "Range"); +#if CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD if (https_ota_handle->partial_http_download && https_ota_handle->image_length > https_ota_handle->max_http_request_size) { char *header_val = NULL; asprintf(&header_val, "bytes=0-%d", https_ota_handle->max_http_request_size - 1); @@ -456,6 +467,7 @@ esp_err_t esp_https_ota_begin(const esp_https_ota_config_t *ota_config, esp_http esp_http_client_set_header(https_ota_handle->http_client, "Range", header_val); free(header_val); } +#endif err = _http_connect(https_ota_handle); } @@ -468,7 +480,10 @@ esp_err_t esp_https_ota_begin(const esp_https_ota_config_t *ota_config, esp_http esp_https_ota_dispatch_event(ESP_HTTPS_OTA_CONNECTED, NULL, 0); } - if (!https_ota_handle->partial_http_download) { +#if CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD + if (!https_ota_handle->partial_http_download) +#endif + { https_ota_handle->image_length = esp_http_client_get_content_length(https_ota_handle->http_client); #if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB /* In case of pre ecnrypted OTA, actual image size of OTA binary includes header size @@ -783,7 +798,10 @@ esp_err_t esp_https_ota_perform(esp_https_ota_handle_t https_ota_handle) ESP_LOGE(TAG, "data read %d, errno %d", data_read, errno); return ESP_FAIL; } - if (!handle->partial_http_download || (handle->partial_http_download && handle->image_length == handle->binary_file_len)) { +#if CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD + if (!handle->partial_http_download || (handle->partial_http_download && handle->image_length == handle->binary_file_len)) +#endif + { handle->state = ESP_HTTPS_OTA_SUCCESS; } break; @@ -792,6 +810,7 @@ esp_err_t esp_https_ota_perform(esp_https_ota_handle_t https_ota_handle) return ESP_FAIL; break; } +#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); @@ -820,6 +839,7 @@ esp_err_t esp_https_ota_perform(esp_https_ota_handle_t https_ota_handle) return ESP_ERR_HTTPS_OTA_IN_PROGRESS; } } +#endif return ESP_OK; } @@ -827,9 +847,12 @@ bool esp_https_ota_is_complete_data_received(esp_https_ota_handle_t https_ota_ha { bool ret = false; esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle; +#if CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD if (handle->partial_http_download) { ret = (handle->image_length == handle->binary_file_len); - } else { + } else +#endif + { ret = esp_http_client_is_complete_data_received(handle->http_client); } return ret; diff --git a/docs/en/api-reference/system/esp_https_ota.rst b/docs/en/api-reference/system/esp_https_ota.rst index 37c1239095..bd6da73297 100644 --- a/docs/en/api-reference/system/esp_https_ota.rst +++ b/docs/en/api-reference/system/esp_https_ota.rst @@ -41,7 +41,13 @@ Please refer to :ref:`ESP-TLS: TLS Server Verification