Description
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
}