From f00a598153b01b3cd5ba7b7d1c3162a377e60421 Mon Sep 17 00:00:00 2001 From: donglianghao Date: Tue, 21 Jul 2020 20:14:26 +0800 Subject: [PATCH] 1. correct http client read return value 2. fix redirection bug 3. add new ota api --- components/esp_http_client/esp_http_client.c | 20 ++++- .../esp_https_ota/include/esp_https_ota.h | 28 +++++++ components/esp_https_ota/src/esp_https_ota.c | 81 +++++++++++++++++++ 3 files changed, 128 insertions(+), 1 deletion(-) diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index ade9fb1c24..e6917065ed 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -657,6 +657,24 @@ esp_err_t esp_http_client_set_redirection(esp_http_client_handle_t client) return ESP_ERR_INVALID_ARG; } ESP_LOGD(TAG, "Redirect to %s", client->location); + if (client->response->buffer->raw_len > 0) { + memset(client->response->buffer->raw_data, 0, client->response->buffer->raw_len); + client->response->buffer->raw_len = 0; + } + if (client->response->buffer->len > 0) { + memset(client->response->buffer->data, 0, client->response->buffer->len); + client->response->buffer->len = 0; + } + client->request->buffer->output_ptr = NULL; + if (client->request->buffer->raw_len > 0) { + memset(client->request->buffer->raw_data, 0, client->request->buffer->raw_len); + client->request->buffer->raw_len = 0; + } + if (client->request->buffer->len > 0) { + memset(client->request->buffer->data, 0, client->request->buffer->len); + client->request->buffer->len = 0; + } + client->request->buffer->output_ptr = NULL; return esp_http_client_set_url(client, client->location); } @@ -871,7 +889,7 @@ int esp_http_client_read(esp_http_client_handle_t client, char *buffer, int len) } ESP_LOG_LEVEL(sev, TAG, "esp_transport_read returned:%d and errno:%d ", rlen, errno); } - return ridx; + return rlen; } res_buffer->output_ptr = buffer + ridx; http_parser_execute(client->parser, client->parser_settings, res_buffer->data, rlen); diff --git a/components/esp_https_ota/include/esp_https_ota.h b/components/esp_https_ota/include/esp_https_ota.h index fd69f27f89..b1ce329fc0 100644 --- a/components/esp_https_ota/include/esp_https_ota.h +++ b/components/esp_https_ota/include/esp_https_ota.h @@ -88,6 +88,34 @@ esp_err_t esp_https_ota(const esp_http_client_config_t *config); */ esp_err_t esp_https_ota_begin(esp_https_ota_config_t *ota_config, esp_https_ota_handle_t *handle); +/** + * @brief Start HTTPS OTA Firmware upgrade + * + * This function initializes ESP HTTPS OTA context and establishes HTTPS connection. + * This function must be invoked first. If this function returns successfully, then `esp_https_ota_perform` should be + * called to continue with the OTA process and there should be a call to `esp_https_ota_finish` on + * completion of OTA operation or on failure in subsequent operations. + * This API supports URL redirection, but if CA cert of URLs differ then it + * should be appended to `cert_pem` member of `http_config`, which is a part of `ota_config`. + * In case of error, this API explicitly sets `handle` to NULL. + * + * @param[in] ota_config pointer to esp_https_ota_config_t structure + * @param[out] handle pointer to an allocated data of type `esp_https_ota_handle_t` + * which will be initialised in this function + * @param[in] offset Start OTA based on the given URL offset corresponding length + * + * @note This API is blocking, so setting `is_async` member of `http_config` structure will + * result in an error. + * + * @return + * - ESP_OK: HTTPS OTA Firmware upgrade context initialised and HTTPS connection established + * - ESP_FAIL: For generic failure. + * - ESP_ERR_INVALID_ARG: Invalid argument (missing/incorrect config, certificate, etc.) + * - For other return codes, refer documentation in app_update component and esp_http_client + * component in esp-idf. + */ +esp_err_t esp_https_ota_begin_with_pos(esp_https_ota_config_t *ota_config, esp_https_ota_handle_t *handle, size_t offset); + /** * @brief Read image data from HTTP stream and write it to 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 4bab1dcdbd..689e840c60 100644 --- a/components/esp_https_ota/src/esp_https_ota.c +++ b/components/esp_https_ota/src/esp_https_ota.c @@ -209,6 +209,87 @@ failure: return err; } +esp_err_t esp_https_ota_begin_with_pos(esp_https_ota_config_t *ota_config, esp_https_ota_handle_t *handle, size_t offset) +{ + esp_err_t err; + + if (handle == NULL || ota_config == NULL || ota_config->http_config == NULL) { + ESP_LOGE(TAG, "esp_https_ota_begin: Invalid argument"); + if (handle) { + *handle = NULL; + } + return ESP_ERR_INVALID_ARG; + } + +#if !CONFIG_OTA_ALLOW_HTTP + if (!ota_config->http_config->cert_pem) { + ESP_LOGE(TAG, "Server certificate not found in esp_http_client config"); + *handle = NULL; + return ESP_ERR_INVALID_ARG; + } +#endif + + esp_https_ota_t *https_ota_handle = calloc(1, sizeof(esp_https_ota_t)); + if (!https_ota_handle) { + ESP_LOGE(TAG, "Couldn't allocate memory to upgrade data buffer"); + *handle = NULL; + return ESP_ERR_NO_MEM; + } + + /* Initiate HTTP Connection */ + https_ota_handle->http_client = esp_http_client_init(ota_config->http_config); + if (https_ota_handle->http_client == NULL) { + ESP_LOGE(TAG, "Failed to initialise HTTP connection"); + err = ESP_FAIL; + goto failure; + } + + if (offset > 0) { + char range_header[32]; + snprintf(range_header, 32, "bytes=%d-", (int)offset); + esp_http_client_set_header(https_ota_handle->http_client, "Range", range_header); + } + + err = _http_connect(https_ota_handle->http_client); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to establish HTTP connection"); + goto http_cleanup; + } + + https_ota_handle->update_partition = NULL; + ESP_LOGI(TAG, "Starting OTA..."); + https_ota_handle->update_partition = esp_ota_get_next_update_partition(NULL); + if (https_ota_handle->update_partition == NULL) { + ESP_LOGE(TAG, "Passive OTA partition not found"); + err = ESP_FAIL; + goto http_cleanup; + } + ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", + https_ota_handle->update_partition->subtype, https_ota_handle->update_partition->address); + + const int alloc_size = (ota_config->http_config->buffer_size > DEFAULT_OTA_BUF_SIZE) ? + ota_config->http_config->buffer_size : DEFAULT_OTA_BUF_SIZE; + https_ota_handle->ota_upgrade_buf = (char *)malloc(alloc_size); + if (!https_ota_handle->ota_upgrade_buf) { + ESP_LOGE(TAG, "Couldn't allocate memory to upgrade data buffer"); + err = ESP_ERR_NO_MEM; + goto http_cleanup; + } + https_ota_handle->ota_upgrade_buf_size = alloc_size; + + https_ota_handle->binary_file_len = 0; + *handle = (esp_https_ota_handle_t)https_ota_handle; + https_ota_handle->state = ESP_HTTPS_OTA_BEGIN; + return ESP_OK; + +http_cleanup: + _http_cleanup(https_ota_handle->http_client); +failure: + free(https_ota_handle); + *handle = NULL; + return err; +} + esp_err_t esp_https_ota_get_img_desc(esp_https_ota_handle_t https_ota_handle, esp_app_desc_t *new_app_info) { esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;