Description
Basic Infos
Hardware
Hardware: ESP-12 (NodeMCU)
Core Version: Tested 2.3.0 and Git
Description
I'm trying to implement a simple HTTP Proxy server on my NodeMCU. And it already works fine for very small transfers of only a few kb. However, when transferring larger files over the Proxy, the connection will only transmit the first few kb and will then stall forever in a WiFiclient.write operation.
I also tried several combinations of setNoDelay, delay() calls, yield() calls, etc. All to no avail.
I feel like if I put in a few delay() calls, the connection works a bit longer, but I've not measured it.
Terminology:
Let "server" be the server that hosts a website,
let "client" be a browser that tries to contact the "server" via the NodeMCU proxy.
The code during a file download basically comes down to
void loop() {
size_t len = serverConn.read(buff, 1460*2);
if (len > 0)
clientConn.write(buff, len);
}
The rest of the code is just connection handling, etc.
At some point, serverConn.read() will return that it has read some data, but clientConn.write() will hang forever.
If the data does not come from the server, but is generated on the device (e.g. sending megabytes of '\0' arrays), transmission rate is around 1Mb/s and stable. If the data is not forwarded to the client, but simply discarded, it's also around 1Mb/s and stable.
My uneducated guess would be, that, since the server keeps sending data as fast as possible, the internal rx buffer of the ESP will become full.
clientConn.write() will wait for an ACK, but will never be able to receive it, since the buffer is already full with data from the server. No idea if that makes sense or not, it just sounded plausible.
I also checked wireshark on the client side, and it seems that the ESP tries to retransmit multiple times and ignores the ACKs from the client, which also supports my guess.
Settings in IDE
Module: NodeMCU 1.0
Flash Size: 4MB
CPU Frequency: 80Mhz
Flash Mode: ?
Flash Frequency: ?
Upload Using: SERIAL
Reset Method: nodemcu
Sketch
The complete sketch for local testing can be found here:
https://paste.ubuntu.com/24095234/
There are also the two functions dlPage() and servePage() I used to test the general throughput of the device.
Debug Messages
Connected to: xxx, IP address: 192.168.1.17
New connection from proxy client
Read host header: GET http://example.com/large/file.zip HTTP/1.1
Connecting to host: example.com, Port: 80
Reading from browser
Read 59 bytes
Wrote bytes to http client
Done something! - Bytes written: 59
Reading from server
Read 2920 bytes from http server
Sent 2920 to proxy client
Done something! - Bytes written: 5840
Reading from server
Read 2920 bytes from http server
Sent 2920 to proxy client
Done something! - Bytes written: 5840
Reading from server
Read 2920 bytes from http server
Sent 2920 to proxy client
Done something! - Bytes written: 5840
...
Reading from server
Read 2920 bytes from http server
Sent 2920 to proxy client
Done something! - Bytes written: 5840
Reading from server
Read 2920 bytes from http server
Note that it does not always hang after the same amount of bytes. Sometimes it transmits only 5kb, sometimes 260kb or anything in between (only rarely more than that).
Tested with curl:
http_proxy=http://192.168.1.17:8080 curl http://example.com/large/file.zip > /dev/null