Skip to content

2.3.0 infinite loop in WifiClientSecure.write when no internet (found reason) #3537

Closed
@odelot

Description

@odelot

Hi guys,

I had this bug, then tried to migrate to 2.4.0rc but there the behavior is more unpredictible (details here). So, I came back to 2.3.0 and tried to debug.

the infinite loop happens when you are connected with a secured TCP socket in a long duration connection, is connected to a wifi router but the wifi router lost internet access.

ClientContext write tries to send the package and after a few tries logs the error :wr !ERR_OK and returns 0

err_t err = tcp_write(_pcb, data, will_send, 0);
            if(err != ERR_OK) {
                DEBUGV(":wr !ERR_OK\r\n");
                return 0;
            }

but the tls1.c send_raw_packet function (from igrr/axtls-8266 library - used this tree version to build and debug) has this while code that just gives error with a ret < 0

while (sent < pkt_size)
    {
        ret = SOCKET_WRITE(ssl->client_fd, 
                        &ssl->bm_all_data[sent], pkt_size-sent);

        if (ret >= 0)
            sent += ret;
        else
        {

#ifdef WIN32
            if (GetLastError() != WSAEWOULDBLOCK)
#else
            if (errno != EAGAIN && errno != EWOULDBLOCK)
#endif
                return SSL_ERROR_CONN_LOST;
        }
#ifndef ESP8266
        /* keep going until the write buffer has some space */
        if (sent != pkt_size)
        {
            fd_set wfds;
            FD_ZERO(&wfds);
            FD_SET(ssl->client_fd, &wfds);

            /* block and wait for it */
            if (select(ssl->client_fd + 1, NULL, &wfds, NULL, NULL) < 0)
                return SSL_ERROR_CONN_LOST;
        }
#endif
    }

so it never detects the error and stay in loop.

Is this analysis right?

I was thinking to change the ClientContext write to return err on error. But I cannot predict all the impacts of this change.

Solution (so far so good)

ClientContext write

err_t err = tcp_write(_pcb, data, will_send, 0);
            if(err != ERR_OK) {
                DEBUGV(":wr !ERR_OK\r\n");
                return err;                                           //<- CHANGED HERE
            }

tsl1.c send_raw_packet

while (sent < pkt_size)
    {
        ret = SOCKET_WRITE(ssl->client_fd, 
                        &ssl->bm_all_data[sent], pkt_size-sent);

        if (ret >= 0)
            sent += ret;
        else
        {
            errno = ret; //? can I do this?                     //<- CHANGED HERE

#ifdef WIN32
            if (GetLastError() != WSAEWOULDBLOCK)
#else
            if (errno != EAGAIN && errno != EWOULDBLOCK)
#endif
                return SSL_ERROR_CONN_LOST;
        }
#ifndef ESP8266
        /* keep going until the write buffer has some space */
        if (sent != pkt_size)
        {
            fd_set wfds;
            FD_ZERO(&wfds);
            FD_SET(ssl->client_fd, &wfds);

            /* block and wait for it */
            if (select(ssl->client_fd + 1, NULL, &wfds, NULL, NULL) < 0)
                return SSL_ERROR_CONN_LOST;
        }
#endif
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions