MbedTLS fails to receive bytes - errno11 & esp_trasport_read()

MelBWG
Posts: 2
Joined: Thu Jun 01, 2023 8:00 pm

MbedTLS fails to receive bytes - errno11 & esp_trasport_read()

Postby MelBWG » Fri Jun 02, 2023 6:35 pm

<r>So I've been dealing with a very persistent error when receiving bytes (MQTT- MbedTLS) even though the connection is successfull and some bytes are received without problems before the error occurs. I'm using Azure FreeRTOS Middleware to connect to IoTHub, and it breaks either during provisioning or subscription. Tried asking on the SDK Forum but this seems more related to socket access.<br/>
MbedTLS debug on info level gives out:<br/>

<CODE><s>

Code: Select all

</s><i>
</i>...

ESP-TLS Read status: 1

ESP-TLS Bytes Available: 2
I (13341) mbedtls: ssl_msg.c:5399 => read

I (13351) mbedtls: ssl_msg.c:5693 <= read


ESP-TLS Read status: 2
I (13361) MQTT: Packet received. ReceivedBytes=2.
I (13361) MQTT: CONNACK session present bit not set.
I (13371) MQTT: Connection accepted.
I (13371) MQTT: Received MQTT CONNACK successfully from broker.
I (13381) MQTT: MQTT connection established with the broker.

ESP-TLS Bytes Available: 0
I (13401) mbedtls: ssl_msg.c:5399 => read

I (13401) mbedtls: ssl_msg.c:3941 => read record

I (13411) mbedtls: ssl_msg.c:1886 => fetch input

I (13411) mbedtls: ssl_msg.c:2043 in_left: 0, nb_want: 5

I (14421) mbedtls: ssl_msg.c:2068 in_left: 0, nb_want: 5


ESP-TLS Read status: -26880
E (14421) tls_freertos: Reading failed, errno= 11, ERROR
E (14421) MQTT: A single byte was not read from the transport: transportStatus=-1.
E (14431) MQTT: Receiving incoming packet length failed. Status=MQTTRecvFailed
E (14441) MQTT: Exiting process loop due to failure: ErrorStatus=MQTTRecvFailed
<e>
</e></CODE>

ESP-IDF version: 4.4.3<br/>
<br/>
This implementation uses the esp-tls API. I also tried the tcp-transport API (included in sample code) and the error eventually breaks everything. The port used is default set to 8883.<br/>

<CODE><s>

Code: Select all

</s><i>
</i>...

I (30181) mbedtls: ssl_msg.c:2069 ssl->f_recv(_timeout)() returned 5 (-0xfffffffb)

I (30191) mbedtls: ssl_msg.c:2089 <= fetch input

I (30201) mbedtls: ssl_msg.c:1886 => fetch input

I (30201) mbedtls: ssl_msg.c:2043 in_left: 5, nb_want: 69

I (30211) mbedtls: ssl_msg.c:2068 in_left: 5, nb_want: 69

I (30221) mbedtls: ssl_msg.c:2069 ssl->f_recv(_timeout)() returned 64 (-0xffffffc0)

I (30221) mbedtls: ssl_msg.c:2089 <= fetch input

I (30231) mbedtls: ssl_msg.c:1144 => decrypt buf

I (30241) mbedtls: ssl_msg.c:1741 <= decrypt buf

I (30241) mbedtls: ssl_msg.c:4015 <= read record

I (30251) mbedtls: ssl_msg.c:5693 <= read

MQTT Buffer bytes:
MQTT Buffer bytes:
MQTT Buffer size: 1
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x400dee2a  PS      : 0x00060a30  A0      : 0x800eaefc  A1      : 0x3ffd0960
0x400dee2a: TLS_Socket_Recv at C:/.../sample-azure-iot/transport_tls_esp32.c:430

A2      : 0x00000b58  A3      : 0x3ffd0990  A4      : 0x00000001  A5      : 0x3f40aa00
A6      : 0x00000001  A7      : 0x3ffe1878  A8      : 0x800dee26  A9      : 0x3ffd0910  
A10     : 0x00000014  A11     : 0x3ffd0990  A12     : 0x00000001  A13     : 0x000003e8
A14     : 0x3f813f40  A15     : 0x00001000  SAR     : 0x00000004  EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000b60  LBEG    : 0x4008b9a1  LEND    : 0x4008b9b1  LCOUNT  : 0xffffffff
0x4008b9a1: strlen at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/newlib/newlib/libc/machine/xtensa/strlen.S:84

0x4008b9b1: strlen at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/newlib/newlib/libc/machine/xtensa/strlen.S:96



Backtrace: 0x400dee27:0x3ffd0960 0x400eaef9:0x3ffd0990 0x400e99c2:0x3ffd09c0 0x400e9df2:0x3ffd0a30 0x400debe1:0x3ffd0a50 0x400ddf63:0x3ffd0a70 0x400de838:0x3ffd0a90 0x400dc4c2:0x3ffd0ae0 0x400d8ea7:0x3ffd0b40
0x400dee27: TLS_Socket_Recv at C:/.../sample-azure-iot/transport_tls_esp32.c:430  // This indicates error in esp_transport_read()

0x400eaef9: getRemainingLength at C:/.../esp-azure/azure-iot-middleware-freertos/azure-iot-middleware-freertos/libraries/coreMQTT/source/core_mqtt_serializer.c:724        
 (inlined by) MQTT_GetIncomingPacketTypeAndLength at C:/.../esp-azure/azure-iot-middleware-freertos/azure-iot-middleware-freertos/libraries/coreMQTT/source/core_mqtt_serializer.c:2369
 
 0x400e99c2: receiveSingleIteration at C:/.../esp-azure/azure-iot-middleware-freertos/azure-iot-middleware-freertos/libraries/coreMQTT/source/core_mqtt.c:1297

0x400e9df2: MQTT_ProcessLoop at C:/.../esp-azure/azure-iot-middleware-freertos/azure-iot-middleware-freertos/libraries/coreMQTT/source/core_mqtt.c:2185
<e>
</e></CODE>
<br/>
Please help! Any insight is greatly appreciated.</r>

MelBWG
Posts: 2
Joined: Thu Jun 01, 2023 8:00 pm

Re: MbedTLS fails to receive bytes - errno11 & esp_trasport_read()

Postby MelBWG » Mon Jun 05, 2023 8:01 pm

So I found the issue and solved it for my implementation. In Azure Middleware for FreeRTOS it is required that the user implements four transport layer functions: TLS Connect, TLS Disconnect, TLS Recv and TLS Send. These were the functions I used:

Code: Select all

int32_t TLS_Socket_Recv( NetworkContext_t * pNetworkContext,
                           void * pBuffer,
                           size_t xBytesToRecv )
{
    int32_t tlsStatus = 0;

    if (( pNetworkContext == NULL ) ||
        ( pBuffer == NULL) ||
        ( xBytesToRecv == 0) )
    {
        ESP_LOGE( TAG, "Invalid input parameter(s): Arguments cannot be NULL.");
        if(pNetworkContext == NULL) {
            ESP_LOGE( TAG, "Invalid input parameter: pNetworkContext is NULL.");
        }
        if(pBuffer == NULL) {
            ESP_LOGE( TAG, "Invalid input parameter: pBuffer is NULL.");
        }
        if(xBytesToRecv == 0) {
            ESP_LOGE( TAG, "Invalid input parameter: xBytesToRecv is 0.");
        }
        return eTLSTransportInvalidParameter;
    }

    esp_tls_t * xHandleTLS = (esp_tls_t *)pNetworkContext->pParams;

    if (( xHandleTLS == NULL ))
    {
        ESP_LOGE( TAG, "Invalid input parameter(s): TLS Handle NULL." );
        return eTLSTransportInvalidParameter;
    }

    tlsStatus = esp_tls_conn_read(xHandleTLS, pBuffer, xBytesToRecv);

    if ( tlsStatus <= 0 )
    {
        ESP_LOGE( TAG, "Reading failed, errno= %d, %s", errno, esp_err_to_name(errno) );
        return ESP_FAIL;
    }

    return tlsStatus;
}


int32_t TLS_Socket_Send( NetworkContext_t * pNetworkContext,
                           const void * pBuffer,
                           size_t xBytesToSend )
{
    int32_t tlsStatus = 0;

    if (( pNetworkContext == NULL ) ||
        ( pBuffer == NULL) ||
        ( xBytesToSend == 0) )
    {
        ESP_LOGE( TAG, "Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p, "
                "pBuffer=%p, xBytesToSend=%d.", pNetworkContext, pBuffer, xBytesToSend );
        return eTLSTransportInvalidParameter;
    }

    esp_tls_t * xHandleTLS = (esp_tls_t*)pNetworkContext->pParams;

    if (( xHandleTLS == NULL ))
    {
        ESP_LOGE( TAG, "Invalid input parameter(s): TLS Handle NULL." );
        return eTLSTransportInvalidParameter;
    }

    tlsStatus = esp_tls_conn_write(xHandleTLS, pBuffer, xBytesToSend);

    if ( tlsStatus < 0 )
    {
        ESP_LOGE( TAG, "Writing failed, errno= %d", errno );
        return ESP_FAIL;
    }

    return tlsStatus;
}
It appears that the MQTT function that receives the bytes only considers NoDataAvailable if the return value for the TLS Recv function is 0. This also happens with the return value for the Send function. If it's negative it only returns RecvFail/SendFail and the assert that comes next stops the execution. So the easy way to solve this is just to:

Code: Select all

//Change from:
if ( tlsStatus <= 0 )
    {
        ESP_LOGE( TAG, "Reading failed, errno= %d, %s", errno, esp_err_to_name(errno) );
        return ESP_FAIL;
    }

//To:
if ( tlsStatus <= 0 )
    {
        //ESP_LOGE( TAG, "Reading failed, errno= %d, %s", errno, esp_err_to_name(errno) );
        return 0;
    }
Of course, this makes it so that every error returns 0, which isn't ideal. If you need to treat other errors it's best to use the esp-tls error get function and establish conditions based off that. Either way, the code works now :)
Also: I didn't try to solve the issue with the sample implementation from the SDK since the fix worked and these functions are less complicated than the ones on the sample

Who is online

Users browsing this forum: No registered users and 116 guests