Page 1 of 1

slight change to esp_http_client_config_t url parameter breaks esp_http_client_perform

Posted: Wed Sep 25, 2024 5:39 pm
by jdbaptista
Note that the API key used here is both no longer active and was on a free account.

When esp_http_client_config_t is setup as

Code: Select all

const esp_http_client_config_t s_defaultTomtomConfig = {
    .url = url,
    .auth_type = API_AUTH_TYPE,
    .method = API_METHOD,
    .event_handler = tomtomHandler,
    .crt_bundle_attach = esp_crt_bundle_attach,
    .user_data = &reqResult,
};
with url = "https:// api.tomtom.com/traffic/services/4/flowSegmentData/relative0/10/json?key=(apikey)&point=34.420842,-119.702440&unit=mph&openLr=true", everything works fine and esp_http_client_perform executes successfully, calls the callback, and returns the speed from the API.

However, when url = "https:// api.tomtom.com/traffic/services/4/flowSegmentData/relative0/10/json?key=(apikey)&point=34.45661100,-119.976601&unit=mph&openLr=true", the following error message appears
I (4900) esp-x509-crt-bundle: Certificate validated

assert failed: xQueueTakeMutexRecursive queue.c:821 (pxMutex)


Backtrace: 0x40081a2e:0x3ffbb5c0 0x4008936d:0x3ffbb5e0 0x40091069:0x3ffbb600 0x40089d63:0x3ffbb720 0x4016ac0e:0x3ffbb740 0x4016a237:0x3ffbb780 0x400e12da:0x3ffbb7a0 0x400e150b:0x3ffbb7d0 0x4014c3a6:0x3ffbb800 0x400e18a1:0x3ffbb860 0x400e2a1c:0x3ffbb880 0x400d7cc5:0x3ffbb8b0 0x400d7a83:0x3ffbb970 0x4016be74:0x3ffbba80 0x40089e79:0x3ffbbaa0
0x40081a2e: panic_abort at C:/Users/bapti/esp/v5.3/esp-idf/components/esp_system/panic.c:463
0x4008936d: esp_system_abort at C:/Users/bapti/esp/v5.3/esp-idf/components/esp_system/port/esp_system_chip.c:92
0x40091069: __assert_func at C:/Users/bapti/esp/v5.3/esp-idf/components/newlib/assert.c:80
0x40089d63: xQueueTakeMutexRecursive at C:/Users/bapti/esp/v5.3/esp-idf/components/freertos/FreeRTOS-Kernel/queue.c:821 (discriminator 1)
0x4016ac0e: esp_event_post_to at C:/Users/bapti/esp/v5.3/esp-idf/components/esp_event/esp_event.c:858
0x4016a237: esp_event_post at C:/Users/bapti/esp/v5.3/esp-idf/components/esp_event/default_event_loop.c:75
0x400e12da: http_dispatch_event_to_event_loop at C:/Users/bapti/esp/v5.3/esp-idf/components/esp_http_client/esp_http_client.c:205
0x400e150b: http_on_body at C:/Users/bapti/esp/v5.3/esp-idf/components/esp_http_client/esp_http_client.c:325
0x4014c3a6: http_parser_execute at C:/Users/bapti/esp/v5.3/esp-idf/components/http_parser/http_parser.c:2104 (discriminator 5)
0x400e18a1: esp_http_client_get_data at C:/Users/bapti/esp/v5.3/esp-idf/components/esp_http_client/esp_http_client.c:1160
0x400e2a1c: esp_http_client_perform at C:/Users/bapti/esp/v5.3/esp-idf/components/esp_http_client/esp_http_client.c:1352
0x400d7cc5: tomtomRequestPerform at C:/Users/bapti/Documents/traffic-pcb-sb/software/esp-firmware/components/TomTom/tomtom.c:204
0x400d7a83: app_main at C:/Users/bapti/Documents/traffic-pcb-sb/software/esp-firmware/main/main.c:64
0x4016be74: main_task at C:/Users/bapti/esp/v5.3/esp-idf/components/freertos/app_startup.c:208
0x40089e79: vPortTaskWrapper at C:/Users/bapti/esp/v5.3/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:134

Even if I truncate the point value to "34.456,-119.976", the issue persists. Does anyone know why this might be happening?

Relevant code (wifi connection works):

Code: Select all

void app_main(void)
{
    // Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    // initialize tcp/ip stack
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();
    // establish wifi connection
    wifi_init_config_t default_wifi_cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&default_wifi_cfg));
    ESP_ERROR_CHECK(establishWifiConnection());

    esp_tls_t *tls = esp_tls_init();
    if (!tls) {
        printf("failed to allocate esp_tls handle!");
        fflush(stdout);
        for (int countdown = 10; countdown >= 0; countdown--) {
            vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
    }

    uint result = 0;
    char *var = "https://api.tomtom.com/traffic/services/4/flowSegmentData/relative0/10/json?key=(apikey)&point=34.456,-119.976&unit=mph&openLr=true";
    ESP_ERROR_CHECK(tomtomRequestPerform(&result, var));
    printf("speed: %d\n", result);
    fflush(stdout);

    for (;;) {
      vTaskDelay(INT_MAX);
    }
}

Code: Select all

/**
 * Requires:
 * - WIFI connection (establishWifiConnection called).
 * - TLS initialized (esp_tls_init called).
 */
esp_err_t tomtomRequestPerform(uint *result, const char *url) {
    if (result == NULL) {
        return ESP_FAIL;
    }

    struct requestResult reqResult = {
        .error = ESP_FAIL,
        .result = 0,
    };

    const esp_http_client_config_t s_defaultTomtomConfig = {
        .url = url,
        .auth_type = API_AUTH_TYPE,
        .method = API_METHOD,
        .event_handler = tomtomHandler,
        .crt_bundle_attach = esp_crt_bundle_attach,
        .user_data = &reqResult,
    };

    printf("%s\n", s_defaultTomtomConfig.url);
    esp_http_client_handle_t httpClientHandle = esp_http_client_init(&s_defaultTomtomConfig);
    if (esp_http_client_perform(httpClientHandle) == ESP_FAIL) { // blocks when requesting
        return ESP_FAIL;
    }
    esp_http_client_cleanup(httpClientHandle);
    *result = reqResult.result;
    return ESP_OK;
}

Code: Select all

/**
 * Handler for recieving responses from the TomTom API.
 */
esp_err_t tomtomHandler(esp_http_client_event_t *evt) {
    struct requestResult *reqResult = (struct requestResult *) evt->user_data;
    static char buffer[RCV_BUFFER_SIZE];
    static uint content_size;
    switch (evt->event_id) {
        case HTTP_EVENT_ON_CONNECTED:
            memset(buffer, 0, RCV_BUFFER_SIZE);
            content_size = 0;
            break;
        case HTTP_EVENT_ON_DATA:
            if (evt->data == NULL) {
            } else {
                memcpy(buffer + content_size, evt->data, evt->data_len);
                content_size += evt->data_len;
            }
            break;
        case HTTP_EVENT_ON_FINISH:
            cJSON *json = cJSON_Parse(buffer);
            json = json->child;
            for (cJSON *curr = json->child; !cJSON_IsNull(curr); curr = curr->next) {
                if (strcmp(curr->string, "currentSpeed") != 0) {
                    continue;
                }
                if (!cJSON_IsNumber(curr)) {
                    reqResult->error = ESP_FAIL;
                } else {
                    reqResult->error = ESP_OK;
                    reqResult->result = curr->valueint;
                }
                break;
            }
            break;
        default: 
            break;
    }
    fflush(stdout);
    return ESP_OK;
}

Re: slight change to esp_http_client_config_t url parameter breaks esp_http_client_perform

Posted: Thu Sep 26, 2024 7:11 pm
by jdbaptista
Turns out my buffer size was too small! Its unfortunate there is no easy error message for this though.

Re: slight change to esp_http_client_config_t url parameter breaks esp_http_client_perform

Posted: Thu Oct 31, 2024 6:21 pm
by jdbaptista
After some more use of esp-idf, I realize this was most likely a stack overflow, which can be detected by turning on stack canaries. This can be done in the Menuconfig using the FreeRTOS option configCHECK_FOR_STACK_OVERFLOW and also probably the COMPILER_STACK_CHECK_MODE option.