tcp_close_tcpip() only closed active TCP PCBs, leaking other types of TCP PCBs
(notably bound only, not yet connected/used). With time, this led to DoS
situations.
Fix by giving up on the hacky way of searching the LWIP innards for the TCP PCB
needing closing. The searching was non-comprehensive, hence the problem in
principle, and inherently racy: could close a meanwhile freed & reused PCB.
Pass the pointer to the struct mg_lwip_conn_state of the struct mg_connection
being destroyed to tcp_close_tcpip() instead of the bare PCB pointer, so the PCB
pointer stored within can be used. Delay unassigning that pointer from the
struct mg_connection until tcp_close_tcpip() finishes, so that
a mg_lwip_tcp_error_cb() meanwhile can clear the PCB pointer stored within.
That ensures no double-closing of the TCP PCB when a concurrent TCP error makes
LWIP close the TCP PCB from the LWIP side.
NB! At the moment, PCBs can still leak if tcp_close() fails, which is unlikely
but possible as per the API. Retrying tcp_close() should somehow be
implemented. For now, at least add logging of tcp_close() failures.
Also: remove the extraneous though benign double-calling of tcp_arg(…, NULL).
h/t @QRPp
A TCP connection can get closed while there are TCPIP thread callbacks
queued. Add checks to close and write functions to avoid acting on
tcp_pcbs that have already been disposed of.
Store adddress in the memory immediately preceding the packet data.
It is guaranteed to have enough space (IP header is 20 bytes).
Introduce a limit on the length of the RX chain,
MG_LWIP_MAX_UDP_RX_CHAIN_LEN. Default is 20.
This is required to distinguish input interface for multicast traffic
and select correct output interface for outgoing traffic (advertisements).
http://savannah.nongnu.org/bugs/?49662 removed ability to receive
multicast traffic on on interface-bound sockets (making the previous
change useless, hence the revert), so for LWIP 2.0.1 and newer
multicast packets can only be received on INADDR_ANY listeners.
User is then required to distinguish input interface in the receive path.
This information is only available in the udp_recv callback, so we must
pass this down to dns-sd library somehow, and priv_2 is the how.
It is normally used for DNS resolver state, and is never used on
listening sockets. We thus avoid growing the mg_connection structure.
* Do not set MG_F_SSL ona connection until it's been fully accepted (MG_SIG_ACCEPT is handled).
This fixes a crash when SSL connection is polled before it's fully initialized.
* Fix mg_lwip_tcp_error_cb to NULL out tcp_pcb pointer even if mg_connection is already shutting down.
After mg_lwip_tcp_error_cb, tcp_pcb pointer can no longer be used and doesn't need to be freed.
This fixes https://github.com/cesanta/mongoose-os/issues/545
ESP8266 non-OS has very limited stack - only 4K. Undetected stack
overflows cause nasty bugs and it turns out serving files over http
routinely causes stack overflow.
This was exposed by a5f59123ed
As a short-term workaround, push http_message into bss, this is enough
as an immediate workaround. Longer term, we need to think how to bring
8266 to parity with other platforms where we have at least 8K stack.
At the same time, get rid of the compiler bug workaround - modern
toolchain doesn't need this.
Now src contains exactly what's embedded in mongoose.c and .h, nothing more.
Added `tools/amalgam.sh` to aamlgamate both files at once.
There are no functional changes to mongoose.c, .h in this PR, only slight filename changes.