recv returns errno 104 / ECONNRESET after 4320 bytes
Posted: Mon Aug 02, 2021 2:51 pm
Hi All,
I have an issue where my code connects a TCP socket to a web server then fetches some data with recv, but it eventually fails returning errno 104 (ECONNRESET) once it has read 4320 bytes.
The application is for connecting to a UPnP IGD and attempting to add a port mapping and mostly works up until it needs to read a file from the IGD that happens to be bigger than 4320 bytes. The code is fairly portable and I can compile the application on Linux and it runs fine, including fetching files bigger than 4320 bytes.
4320 happens to be 3 times the default maximum segment size (MSS) of 1440, so I'm hoping this is just a configuration issue that can be fixed by changing some settings. I tried enabling some LWiP debug output but it made matters worse and caused ECONNRESET errors on files smaller than 4320 bytes.
Before the app receives the ECONNRESET, the debug output shows
I dug through the code and found that
The function that fetches files from the IGD (which works on Linux) is as follows:
I've attached the debug output for runs with and without the LWiP socket and TCP debug enabled. The latter only fails when trying to fetch the service description from the IGD. The former seems to fail for any fetch from the IGD. Any ideas what I need to change so this works on ESP32?
Cheers
Paul
I have an issue where my code connects a TCP socket to a web server then fetches some data with recv, but it eventually fails returning errno 104 (ECONNRESET) once it has read 4320 bytes.
The application is for connecting to a UPnP IGD and attempting to add a port mapping and mostly works up until it needs to read a file from the IGD that happens to be bigger than 4320 bytes. The code is fairly portable and I can compile the application on Linux and it runs fine, including fetching files bigger than 4320 bytes.
4320 happens to be 3 times the default maximum segment size (MSS) of 1440, so I'm hoping this is just a configuration issue that can be fixed by changing some settings. I tried enabling some LWiP debug output but it made matters worse and caused ECONNRESET errors on files smaller than 4320 bytes.
Before the app receives the ECONNRESET, the debug output shows
then a short while latertcp_slowtmr: no active pcbs
thenlwip_recv_tcp: netconn_recv err=-7, pbuf=0x0
and finallylwip_recv_tcp: netconn_recv err=-14, pbuf=0x1
.lwip_recv_tcp: p == NULL, error is "Connection reset."!
I dug through the code and found that
is related to LWIP_MAX_LISTENING_TCP which I increased from 16 to 32 but it had no effect.no active pcbs
The function that fetches files from the IGD (which works on Linux) is as follows:
- struct http_req {
- int port, path_offset, len;
- char host[16], buf[1];
- };
- void http_req_run(struct http_req *q, char *body, int blen, http_req_f *heard, void *ctx)
- {
- if (!q)
- return;
- struct sockaddr_in sa = {0};
- sa.sin_family = AF_INET;
- sa.sin_port = htons(q->port);
- inet_aton(q->host, &sa.sin_addr);
- ESP_LOGD("UPNP", "TX %s%s", q->buf, body ? body : "");
- int s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP), got = 0, total = 0;
- if (s < 0)
- ESP_LOGE("UPNP", "socket error %i", errno);
- else if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
- ESP_LOGE("UPNP", "connect error %i", errno);
- else if (send(s, q->buf, q->len, 0) < 0)
- ESP_LOGE("UPNP", "send header error %i", errno);
- else if (send(s, "\r\n", 2, 0) < 0)
- ESP_LOGE("UPNP", "send CRLF error %i", errno);
- else if (body && send(s, body, blen, 0) < 0)
- ESP_LOGE("UPNP", "send body error %i", errno);
- else while ((got = recv(s, q->buf, q->len, 0)) > 0) {
- q->buf[got] = 0; ESP_LOGD("UPNP", "RX %i %s", got, q->buf);
- heard(ctx, q->buf, got);
- total += got;
- }
- if (got < 0)
- ESP_LOGE("UPNP", "http_req_run recv %i, read %i bytes", errno, total);
- close(s);
- }
Cheers
Paul