espressif / esp-aws-iot

AWS IoT SDK for ESP32 based chipsets
Apache License 2.0
266 stars 157 forks source link

Timeout error occured when waiting large size packet (CA-110) #43

Open tenpa1105 opened 3 years ago

tenpa1105 commented 3 years ago

I think that timeout_ms of aws_iot_mqtt_yield should be specified short time because task called this function is blocked long time. But, if timeout_ms is short, timeout error occur when waiting large size packet. (ex. OTA)

I think iot_tls_read function should be improved as the below.

IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *read_len) {
    TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams);
    mbedtls_ssl_context *ssl = &(tlsDataParams->ssl);
    mbedtls_ssl_config *ssl_conf = &(tlsDataParams->conf);
    uint32_t read_timeout;
    size_t rxLen = 0;
    int ret;
    Timer readTimer = *timer;

    read_timeout = ssl_conf->read_timeout;

    while (len > 0) {

        /* Make sure we never block on read for longer than timer has left,
         but also that we don't block indefinitely (ie read_timeout > 0) */
        mbedtls_ssl_conf_read_timeout(ssl_conf, MAX(1, MIN(read_timeout, left_ms(timer))));

        ret = mbedtls_ssl_read(ssl, pMsg, len);

        /* Restore the old timeout */
        mbedtls_ssl_conf_read_timeout(ssl_conf, read_timeout);

        if (ret > 0) {

        /* Successfully received data, so reset the timeout */
        init_timer(&readTimer);
            countdown_ms(&readTimer, IOT_SSL_READ_RETRY_TIMEOUT_MS);

            rxLen += ret;
            pMsg += ret;
            len -= ret;
        } else if (ret == 0 || (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != MBEDTLS_ERR_SSL_TIMEOUT)) {
            return NETWORK_SSL_READ_ERROR;
        }

        // Evaluate timeout after the read to make sure read is done at least once
        if (has_timer_expired(&readTimer)) {
            break;
        }
    }

    if (len == 0) {
        *read_len = rxLen;
        return SUCCESS;
    }

    if (rxLen == 0) {
        return NETWORK_SSL_NOTHING_TO_READ;
    } else {
        return NETWORK_SSL_READ_TIMEOUT_ERROR;
    }
}

IOT_SSL_READ_RETRY_TIMEOUT_MS is user configuration parameter.

#define IOT_SSL_READ_RETRY_TIMEOUT_MS   3000