Cancel Http client data download

Leander
Posts: 18
Joined: Thu Sep 26, 2019 8:50 pm

Cancel Http client data download

Postby Leander » Thu Jan 07, 2021 9:55 am

I'm using the http client to download a large file to the ESP. The file version is in the first part of the binary file. So I download the first 512 bytes and then check the version.
  1. If its an older version, I want to cancel the download.
  2. If the download is interrupted or fails, I want to retry.
  3. If the download is successful, I want to continue to the next step
The download data is chuncked so the handler starts multiple HTTP_EVENT_ON_DATA events until all data is downloaded.
I'm checking the received data and would like to stop the download at any time. In the HTTP_ON_DATA event I'm returning an esp_err_t state:
  1. Return ESP_ERR_INVALID_VERSION
  2. Return ESP_FAIL.
  3. Return ESP_OK
When I'm returning an error, the client continues to download the file and HTTP_ON_DATA events are triggered.

In the esp_http_client.c file the http_dispatch_event function is returning the esp_err_t from the handler.

Code: Select all

static esp_err_t http_dispatch_event(esp_http_client_t *client, esp_http_client_event_id_t event_id, void *data, int len)
{
    esp_http_client_event_t *event = &client->event;

    if (client->event_handler) {
        event->event_id = event_id;
        event->user_data = client->user_data;
        event->data = data;
        event->data_len = len;
        return client->event_handler(event);
    }
    return ESP_OK;
}
But the http_on_body function is ignoring the return value and always returns ESP_OK (0)

Code: Select all

static int http_on_body(http_parser *parser, const char *at, size_t length)
{
    esp_http_client_t *client = parser->data;
    ESP_LOGD(TAG, "http_on_body %d", length);
    client->response->buffer->raw_data = (char *)at;
    if (client->response->buffer->output_ptr) {
        memcpy(client->response->buffer->output_ptr, (char *)at, length);
        client->response->buffer->output_ptr += length;
    }

    client->response->data_process += length;
    client->response->buffer->raw_len += length;
    http_dispatch_event(client, HTTP_EVENT_ON_DATA, (void *)at, length);
    return 0;
}
If I'm changing the last line in esp_http_client.c and returning the http_dispatch_event, the download is stopped and the HTTP_EVENT_ON_FINISH is triggered. But only after the TCP receive timeout that for other reasons is set to 30s in my code.

I'm not fond of altering the original esp-idf libraries as its blocking future migration to new releases.

I tried to alter the esp_http_client_event_t->event_id in the HTTP_EVENT_ON_DATA and set it to HTTP_EVENT_ON_FINISH but that didn't work (download continues).

If I'm calling the "esp_http_client_close(evt->client);" function, the download stops without the HTTP_EVENT_ON_FINISH (no problem) but also after timeout of 15s.

For the moment this last method seems to be the best for the http server and client. In my opinion i could use global variable to indicate if the download was aborted, complete or not needed.

Are there any other methods or suggestions to cancel a download in a proper way?

Who is online

Users browsing this forum: Baidu [Spider], Bing [Bot] and 52 guests