cesanta / mongoose

Embedded Web Server
https://mongoose.ws
Other
11.05k stars 2.72k forks source link

No TCP response on STM32 LWIP FreeRTOS #1134

Closed pjung-bosch closed 3 years ago

pjung-bosch commented 4 years ago

Hi,

I'm trying to run a simple hello world demo on an stm32 with freertos and lwip. I took the application code (task and ev_handler) from examples/ESP8266_RTOS. I ran into the "poll macro" issue and thus set LWIP_SOCKET_POLL to 0 in ma lwipopts.h. I also had to suppress the inclusion of here to get it to compile. Other than that everything worked pretty much out of the box.

I compile it with -DSTM32 -DMG_LWIP -DCS_ENABLE_STDIO=0

The problem is that, when I request something via HTTP (via my browser or netcat), my mongoose task sees the request but my client doesn't get a response. (Other lwip TCP tasks work. Actually the log from below is transmitted via Telnet). Also the task continues to run and the tcp connection is kept alive until I explicitely close it (i.e. by pressing ESC in my browser)

Here's the output of the LOG() and DBG() calls when I do a "GET /":

1703558 ms DEBUG : 0x20014898 fd=0 fd_flags=1 nc_flags=0x1 rmbl=0 smbl=0 1703558 ms DEBUG : 0x200146e8 0x20012010 1703558 ms INFO : 0x20014898 0x20012010 -1 0 1703558 ms DEBUG : 0x20012010 conn from 192.168.0.97:59396 1703558 ms DEBUG : 0x20012010 1 1703558 ms INFO : 0x20012010 tcp://192.168.0.97:59396 1703558 ms DEBUG : 0x20012010 proto ev=1 ev_data=0x20012028 flags=0x0 rmbl=0 smbl=0 1703558 ms DEBUG : 0x20012010 user ev=1 ev_data=0x20012028 flags=0x0 rmbl=0 smbl=0 1703559 ms DEBUG : 0x20012010 after user flags=0x0 rmbl=0 smbl=0 1703559 ms DEBUG : 0x20012010 after proto flags=0x0 rmbl=0 smbl=0 1703559 ms DEBUG : 0x20014898 after fd=0 nc_flags=0x1 rmbl=0 smbl=0 1703559 ms DEBUG : 0x20012010 fd=1 fd_flags=1 nc_flags=0x0 rmbl=0 smbl=0 1703559 ms DEBUG : 0x20012010 <- 332 bytes 1703559 ms DEBUG : 0x20012010 proto ev=3 ev_data=0x2001461c flags=0x0 rmbl=332 smbl=0 1703559 ms DEBUG : 0x20012010 user ev=3 ev_data=0x2001461c flags=0x0 rmbl=332 smbl=0 1703559 ms DEBUG : 0x20012010 after user flags=0x0 rmbl=332 smbl=0 1703560 ms DEBUG : 0x20012010 user ev=102 ev_data=0x20014440 flags=0x0 rmbl=332 smbl=0 1703560 ms DEBUG : 0x20012010 after user flags=0x0 rmbl=332 smbl=0 1703560 ms DEBUG : 0x20012010 192.168.0.97:59396 GET / 1703560 ms DEBUG : 0x20012010 user ev=100 ev_data=0x20014440 flags=0x0 rmbl=332 smbl=0 1703560 ms DEBUG : 0x20012010 after user flags=0x400 rmbl=332 smbl=89 1703560 ms DEBUG : 0x20012010 finished 1 ml 332 bl 0 1703560 ms DEBUG : 0x20012010 after proto flags=0x400 rmbl=0 smbl=89

Then, after I close the browser connection:

1712250 ms DEBUG : 0x20012010 <- 0 bytes 1712250 ms DEBUG : 0x20012010 after fd=1 nc_flags=0x400 rmbl=0 smbl=89 1712250 ms DEBUG : 0x20012010 fd=1 fd_flags=3 nc_flags=0x400 rmbl=0 smbl=89 1712250 ms DEBUG : 0x20012010 <- -1 bytes 1712250 ms DEBUG : 0x20012010 after fd=1 nc_flags=0xc00 rmbl=0 smbl=89 1712250 ms DEBUG : 0x20012010 fd=1 fd_flags=3 nc_flags=0xc00 rmbl=0 smbl=89 1712251 ms DEBUG : 0x20012010 proto ev=5 ev_data=0 flags=0xc00 rmbl=0 smbl=89 1712251 ms DEBUG : 0x20012010 user ev=5 ev_data=0 flags=0xc00 rmbl=0 smbl=89 1712251 ms DEBUG : 0x20012010 after user flags=0xc00 rmbl=0 smbl=89 1712251 ms DEBUG : 0x20012010 after proto flags=0xc00 rmbl=0 smbl=89

Any ideas?

pjung-bosch commented 4 years ago

I did some more digging, what seems to happen is this:

After successfully receiving the first packet, in mg_do_recv (and after calling the ev_handler), there is a loop which continues to read from tcp (mg_recv_tcp) while the recv return value is > 0. In my setup, however, mg_recv_tcp ultimately calls recv on an lwip socket, which is blocking. So the socket keeps waiting for more data (that isn't coming) while the data in the send buffer don't get sent.

So how is this meant to work? Are the sockets supposed to be non-blocking?

pjung-bosch commented 4 years ago

So, following up on my last message, I used the following workaround to fix the problem temporarily:

I changed

https://github.com/cesanta/mongoose/blob/0a09b46c94f05cde7c0e8e7e70e9ea1f10337660/mongoose.c#L3749

to use the MSG_DONTWAIT flag so it now looks like this:

int n = (int) MG_RECV_FUNC(nc->sock, buf, len, MSG_DONTWAIT);

This seems to fix the problem as mg_is_error() accepts the "ERR_WOULDBLOCK" as a "good" error and proceeds. However, I'd still like to know how this situation is supposed to be handled. Is this a bug or am I making some mistake in my integration code?

mill1000 commented 3 years ago

Also seeing this on an ESP8266. The fix you described works for me as well. This is however on Mongoose 6.18, maybe the new 7.0 release doesn't have the issue

cpq commented 3 years ago

In 7.0, there is a snippet

#ifndef MSG_NONBLOCKING
#define MSG_NONBLOCKING 0
#endif

So you might -DMSG_NONBLOCKING=MSG_DONTWAIT